package xmpp import ( "encoding/xml" "errors" "log" ) type tokenRouter struct { start xml.StartElement end xml.EndElement buffer []xml.Token level uint16 // XML nesting level enc *encoder } func newTokenRouter(e *encoder) tokenRouter { return tokenRouter{ buffer: make([]xml.Token, 0), level: 0, enc: e, } } func (r *tokenRouter) route(t xml.Token) error { r.buffer = append(r.buffer, t) switch unwrapped := t.(type) { case xml.StartElement: r.level += 1 if r.level == 1 { r.start = unwrapped r.buffer = r.buffer[:0] // call start handler } case xml.EndElement: if r.level == 0 { log.Println("Ignoring XML end element on nesting level zero") return nil } r.level -= 1 switch r.level { case 0: return errors.New("Stream was closed by server") case 1: // call elementRouter err := routeElement(r.buffer) if err != nil { return err } r.buffer = r.buffer[:0] } case xml.ProcInst: log.Println("Ignoring xml.ProcInst element") r.buffer = r.buffer[:len(r.buffer)-1] case xml.Directive: log.Println("Ignoring xml.Directive element") r.buffer = r.buffer[:len(r.buffer)-1] case xml.Comment: log.Println("Ignoring xml.Comment element") r.buffer = r.buffer[:len(r.buffer)-1] } return nil } func routeElement(b []xml.Token) error { tab := elementRoutingTable{ {xml.Name{"http://etherx.jabber.org/streams", "features"}, streamFeatures}, } switch unwrapped := b[0].(type) { case xml.StartElement: for _, v := range(tab) { if unwrapped.Name == v.name { err := v.handler(b) if err != nil { return err } return nil } } log.Printf("Ignoring XML element '%s' from namespace '%s'", unwrapped.Name.Local, unwrapped.Name.Space) default: log.Println("Ignoring XML element which has no StartElement as first token") } return nil } type elementRoutingTable []struct { name xml.Name handler func(b []xml.Token) error } func streamFeatures(b []xml.Token) error { log.Println("Received stream features") return nil }