package xmpp import ( "encoding/xml" "log" ) func runStreamPair(s *session) { openStream(s) defer closeStream(s) buf := newElementBuffer() for { select { case data := <-s.in: switch data.(type) { case SessionShouldDisconnect: return default: log.Printf("Unknown data '%d'!\n", data) } case t := <-s.rx: err := buf.add(t) if err != nil { log.Printf("Could not add XML token to buffer: %v\n", err) return } if buf.isComplete() { element := buf.reset() route(element, getRoutingTable()) } } } } func openStream(s *session) { start := xml.StartElement{ xml.Name{"jabber:client", "stream:stream"}, []xml.Attr{ xml.Attr{xml.Name{"", "from"}, s.jid}, xml.Attr{xml.Name{"", "to"}, domainpart(s.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"}, }, } s.streamEnd = start.End() err := s.ed.encodeToken(start) if err != nil { log.Println("Could not encode stream start!") } syncStreams(s) } // syncStreams drops XML tokens from the receiving stream until an // xml.StartElement with the local name `stream` is received. If this function // is called after opening a new stream in the sending direction it is ensured // that both streams directions work on the same stream level and are in sync. // Tokens received which are not a stream StartElement are not handled but // logged since this should not happen. func syncStreams(s *session) { for { select { case data := <-s.in: switch data.(type) { case SessionShouldDisconnect: return default: log.Printf("Unhandled data '%d' during stream sync!\n", data) } case t := <-s.rx: switch token := t.(type) { case xml.StartElement: if token.Name.Local == "stream" { return } } log.Printf("Unhandled XML token '%v' during stream sync!\n", t) } } } func closeStream(s *session) { err := s.ed.encodeToken(s.streamEnd) if err != nil { log.Println("Could not encode stream end!") } } func streamFeaturesHandler(e []xml.Token) { log.Println("Received stream features") }