package xmpp import ( "crypto/tls" "crypto/x509" "encoding/xml" "log" "os" ) type Event uint8 const ( DisconnectEvent Event = iota ConnectEvent ShouldDisconnectEvent ) func Run(rxChan chan Event, txChan chan any, 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 := xml.NewEncoder(conn) defer enc.Close() dbg := xml.NewEncoder(os.Stdout) defer dbg.Close() end := sendStreamStart(enc, dbg, jid) defer sendStreamEnd(enc, dbg, end) txChan <- ConnectEvent defer func() { txChan <- DisconnectEvent }() for { select { case ev := <-rxChan: switch ev { case ShouldDisconnectEvent: return default: log.Printf("Unknown Event '%d'!\n", ev) } case rx := <-decoder.data: dbg.Indent("S: ", " ") dbg.EncodeToken(rx) dbg.Flush() } } } 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 *xml.Encoder, dbg *xml.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.EncodeToken(start) if err != nil { log.Println("Could not encode stream start to TCP channel!") } err = enc.Flush() if err != nil { log.Println("Could not flush TCP channel XML encoder!") } dbg.Indent("C: ", " ") err = dbg.EncodeToken(start) if err != nil { log.Println("Could not encode stream start to debug output!") } err = dbg.Flush() if err != nil { log.Println("Could not flush debug XML encoder!") } return start.End() } func sendStreamEnd(enc *xml.Encoder, dbg *xml.Encoder, end xml.EndElement) { err := enc.EncodeToken(end) if err != nil { log.Println("Could not encode stream end to TCP channel!") } err = enc.Flush() if err != nil { log.Println("Could not flush TCP channel XML encoder!") } dbg.Indent("C: ", " ") err = dbg.EncodeToken(end) if err != nil { log.Println("Could not encode stream end to debug output!") } err = dbg.Flush() if err != nil { log.Println("Could not flush debug XML encoder!") } }