Added a callback handler which will handle a stanza with a particular id.
authorChris Jones <chris@cjones.org>
Wed, 28 Dec 2011 11:30:10 -0700
changeset 13 c9527bbe99a6
parent 12 122ab6208c3c
child 14 fd6781a41e6f
Added a callback handler which will handle a stanza with a particular id.
stream.go
xmpp.go
--- 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()