1package xmpp
2
3import (
4	"encoding/xml"
5	"io"
6	"log"
7	"net"
8	"time"
9
10	"github.com/coyim/coyim/xmpp/data"
11)
12
13var (
14	keepaliveInterval = 10 * time.Second
15	keepaliveTimeout  = 30 * time.Second
16)
17
18const logKeepAlives = false
19
20// Manage whitespace keepalives as specified in RFC 6120, section 4.6.1
21func (c *conn) watchKeepAlive(conn net.Conn) {
22	tick := time.NewTicker(keepaliveInterval)
23	defer tick.Stop()
24	defer log.Println("xmpp: no more watching keepalives")
25
26	for _ = range tick.C {
27		if c.closed {
28			return
29		}
30
31		if c.sendKeepalive() {
32			if logKeepAlives {
33				log.Println("xmpp: keepalive sent")
34			}
35			continue
36		}
37
38		log.Println("xmpp: keepalive failed")
39
40		go c.sendStreamError(data.StreamError{
41			DefinedCondition: data.ConnectionTimeout,
42		})
43
44		return
45	}
46}
47
48func (c *conn) sendKeepalive() bool {
49	_, err := c.keepaliveOut.Write([]byte{0x20})
50	return c.closed || err == nil || err == io.EOF
51}
52
53func (c *conn) sendStreamError(streamError data.StreamError) error {
54	enc, err := xml.Marshal(streamError)
55	if err != nil {
56		return err
57	}
58
59	//This is expected to error since the connection may be unreliable at this moment
60	c.out.Write(enc)
61
62	return c.Close()
63}
64