package xmpp import ( "crypto/tls" "crypto/x509" "encoding/xml" "log" ) type Event uint8 const ( DisconnectEvent Event = iota ConnectEvent ShouldDisconnectEvent ) type Conn struct { ch chan Event jid, pwd string tcp *tls.Conn } func NewConn(ch chan Event, jid string, pwd string) *Conn { c := Conn{ ch: ch, jid: jid, pwd: pwd} return &c } func (c *Conn) Connect() error { var err error domain := domainpart(c.jid) roots, err := x509.SystemCertPool() if err != nil { log.Println(err) return err } c.tcp, err = tls.Dial("tcp", domain+":"+"5223", &tls.Config{RootCAs: roots}) if err != nil { log.Println(err) return err } return nil } func (c *Conn) Disconnect() { c.tcp.Close() } func (c *Conn) Run() { err := c.Connect() if err != nil { return } defer c.Disconnect() decoder := newDecoder(c.tcp) go decoder.run() defer decoder.stop() enc := newEncoder(c.tcp) defer enc.Close() tr := newTokenRouter(&enc) end := sendStreamStart(&enc, c.jid) defer sendStreamEnd(&enc, end) c.ch <- ConnectEvent defer func() { c.ch <- DisconnectEvent }() for { select { case ev := <-c.ch: switch ev { case ShouldDisconnectEvent: return default: log.Printf("Unknown Event '%d'!\n", ev) } case token := <-decoder.data: err = tr.route(token) if err != nil { log.Println(err) return } } } } func sendStreamStart(enc *encoder, jid string) xml.EndElement { start := xml.StartElement{ xml.Name{"jabber:client", "stream:stream"}, []xml.Attr{ xml.Attr{xml.Name{"", "from"}, jid}, xml.Attr{xml.Name{"", "to"}, domainpart(jid)}, xml.Attr{xml.Name{"", "version"}, "1.0"}, xml.Attr{xml.Name{"", "xml:lang"}, "en"}, xml.Attr{xml.Name{"", "xmlns:stream"}, "http://etherx.jabber.org/streams"}, }, } err := enc.encodeNow(start) if err != nil { log.Println("Could not encode stream start!") } return start.End() } func sendStreamEnd(enc *encoder, end xml.EndElement) { err := enc.encodeNow(end) if err != nil { log.Println("Could not encode stream end!") } }