Added a callback handler which will handle a stanza with a particular id.
--- a/stream.go Tue Dec 27 20:42:44 2011 -0700
+++ b/stream.go Wed Dec 28 11:30:10 2011 -0700
@@ -26,6 +26,11 @@
"xml"
)
+type stanzaHandler struct {
+ id string
+ f func(Stanza) bool
+}
+
func (cl *Client) readTransport(w io.Writer) {
defer tryClose(cl.socket, w)
cl.socket.SetReadTimeout(1e8)
@@ -171,18 +176,35 @@
func (cl *Client) readStream(srvIn <-chan interface{}, cliOut chan<- interface{}) {
defer tryClose(srvIn, cliOut)
- for x := range srvIn {
- switch obj := x.(type) {
- case *Stream:
- handleStream(obj)
- case *Features:
- cl.handleFeatures(obj)
- case *starttls:
- cl.handleTls(obj)
- case *auth:
- cl.handleSasl(obj)
- default:
- cliOut <- x
+ handlers := make(map[string] func(Stanza) bool)
+ // TODO This for loop will never terminate, even when the
+ // channels are closed.
+ for {
+ select {
+ case h := <- cl.handlers:
+ handlers[h.id] = h.f
+ case x := <- srvIn:
+ send := false
+ switch obj := x.(type) {
+ case *Stream:
+ handleStream(obj)
+ case *Features:
+ cl.handleFeatures(obj)
+ case *starttls:
+ cl.handleTls(obj)
+ case *auth:
+ cl.handleSasl(obj)
+ default:
+ send = true
+ }
+ if st, ok := x.(Stanza) ; ok &&
+ handlers[st.XId()] != nil {
+ f := handlers[st.XId()]
+ send = f(st)
+ }
+ if send {
+ cliOut <- x
+ }
}
}
}
@@ -455,3 +477,8 @@
cl.xmlOut <- msg
// TODO Grab the iq result from the server and update cl.Jid.
}
+
+func (cl *Client) HandleStanza(id string, f func(Stanza) bool) {
+ h := &stanzaHandler{id: id, f: f}
+ cl.handlers <- h
+}
--- a/xmpp.go Tue Dec 27 20:42:44 2011 -0700
+++ b/xmpp.go Wed Dec 28 11:30:10 2011 -0700
@@ -43,6 +43,7 @@
authDone bool
idMutex sync.Mutex
nextId int64
+ handlers chan *stanzaHandler
In <-chan interface{}
Out chan<- interface{}
xmlOut chan<- interface{}
@@ -84,6 +85,7 @@
cl.password = password
cl.Jid = *jid
cl.socket = tcp
+ cl.handlers = make(chan *stanzaHandler)
// Start the transport handler, initially unencrypted.
tlsr, tlsw := cl.startTransport()