diff options
author | xengineering <me@xengineering.eu> | 2023-05-20 22:33:56 +0200 |
---|---|---|
committer | xengineering <me@xengineering.eu> | 2023-05-21 10:47:58 +0200 |
commit | e386931283f3752d581530665a9c6616851aa536 (patch) | |
tree | 845d67f68bfff039827e008041858ebcac2805c7 | |
parent | 7b29491f10ee31d0c275fa69d96c3ac6af8fa7a7 (diff) | |
download | limox-e386931283f3752d581530665a9c6616851aa536.tar limox-e386931283f3752d581530665a9c6616851aa536.tar.zst limox-e386931283f3752d581530665a9c6616851aa536.zip |
Implement xengineering.eu/xmpp.tokenRouter
This will collect XML tokens until a full XML element is received and
can be routed by a to-implement elementRouter.
-rw-r--r-- | xmpp/routing.go | 51 | ||||
-rw-r--r-- | xmpp/xmpp.go | 11 |
2 files changed, 56 insertions, 6 deletions
diff --git a/xmpp/routing.go b/xmpp/routing.go new file mode 100644 index 0000000..8af3190 --- /dev/null +++ b/xmpp/routing.go @@ -0,0 +1,51 @@ +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 + // 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 + r.buffer = r.buffer[:1] + } + } + + return nil +} diff --git a/xmpp/xmpp.go b/xmpp/xmpp.go index 5c6e3e9..c0a52a0 100644 --- a/xmpp/xmpp.go +++ b/xmpp/xmpp.go @@ -30,6 +30,8 @@ func Run(ch chan Event, jid string, pwd string) { enc := newEncoder(conn) defer enc.Close() + tr := newTokenRouter(&enc) + end := sendStreamStart(&enc, jid) defer sendStreamEnd(&enc, end) @@ -46,12 +48,9 @@ func Run(ch chan Event, jid string, pwd string) { 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 - } + err = tr.route(token) + if err != nil { + return } } } |