package xmpp import ( "crypto/tls" "crypto/x509" "encoding/xml" "log" ) type Event uint8 const ( DisconnectEvent Event = iota ConnectEvent ShouldDisconnectEvent ) func Run(ch chan Event, jid string, pwd string) { conn, err := setupConn(jid) if err != nil { log.Print(err) return } defer conn.Close() decoder := newDecoder(conn) go decoder.run() defer decoder.stop() enc := newEncoder(conn) defer enc.Close() end := sendStreamStart(&enc, jid) defer sendStreamEnd(&enc, end) ch <- ConnectEvent defer func() { ch <- DisconnectEvent }() for { select { case ev := <-ch: switch ev { case ShouldDisconnectEvent: return default: log.Printf("Unknown Event '%d'!\n", ev) } case token := <-decoder.data: switch element := token.(type) { case xml.EndElement: if element.Name.Local == "error" { log.Println("Received stream error!") return } } } } } func setupConn(jid string) (*tls.Conn, error) { domain := domainpart(jid) roots, err := x509.SystemCertPool() if err != nil { return nil, err } return tls.Dial("tcp", domain+":"+"5223", &tls.Config{RootCAs: roots}) } 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!") } }