stream.go
changeset 17 d269d9c0fc8e
parent 16 b839e37b3f29
child 19 e923f28d65aa
--- a/stream.go	Wed Dec 28 11:57:29 2011 -0700
+++ b/stream.go	Wed Dec 28 12:39:24 2011 -0700
@@ -5,7 +5,8 @@
 // This file contains the three layers of processing for the
 // communication with the server: transport (where TLS happens), XML
 // (where strings are converted to go structures), and Stream (where
-// we respond to XMPP events on behalf of the library client).
+// we respond to XMPP events on behalf of the library client), or send
+// those events to the client.
 
 package xmpp
 
@@ -26,11 +27,16 @@
 	"xml"
 )
 
+// Callback to handle a stanza with a particular id.
 type stanzaHandler struct {
 	id string
+	// Return true means pass this to the application
 	f func(Stanza) bool
 }
 
+// TODO Review all these *Client receiver methods. They should
+// probably either all be receivers, or none.
+
 func (cl *Client) readTransport(w io.Writer) {
 	defer tryClose(cl.socket, w)
 	cl.socket.SetReadTimeout(1e8)
@@ -138,6 +144,10 @@
 			break
 		}
 
+		// TODO If it's a Stanza, use reflection to search for
+		// any Unrecognized elements and fill in their
+		// attributes.
+
 		// Put it on the channel.
 		ch <- obj
 	}
@@ -160,6 +170,8 @@
 	}
 }
 
+// TODO This should go away. We shouldn't allow writing of
+// unstructured data.
 func writeText(w io.Writer, ch <-chan *string) {
 	if debug {
 		pr, pw := io.Pipe()
@@ -214,6 +226,9 @@
 	}
 }
 
+// TODO Disable this loop until resource binding is
+// complete. Otherwise the app might inject something weird into our
+// negotiation stream.
 func writeStream(srvOut chan<- interface{}, cliIn <-chan interface{}) {
 	defer tryClose(srvOut, cliIn)
 
@@ -240,6 +255,7 @@
 
 	if fe.Bind != nil {
 		cl.bind(fe.Bind)
+		return
 	}
 }
 
@@ -291,6 +307,7 @@
 	cl.socketSync.Done()
 }
 
+// TODO Implement TLS/SASL EXTERNAL.
 func (cl *Client) chooseSasl(fe *Features) {
 	var digestMd5 bool
 	for _, m := range(fe.Mechanisms.Mechanism) {
@@ -436,6 +453,7 @@
 	return m
 }
 
+// Inverse of parseSasl().
 func packSasl(m map[string]string) string {
 	var terms []string
 	for key, value := range(m) {
@@ -447,6 +465,7 @@
 	return strings.Join(terms, ",")
 }
 
+// Computes the response string for digest authentication.
 func saslDigestResponse(username, realm, passwd, nonce, cnonceStr,
 	authenticate, digestUri, nonceCountStr string) string {
 	h := func(text string) []byte {
@@ -470,6 +489,7 @@
 	return response
 }
 
+// Send a request to bind a resource. RFC 3920, section 7.
 func (cl *Client) bind(bind *Unrecognized) {
 	res := cl.Jid.Resource
 	msg := &Iq{Type: "set", Id: cl.NextId(), Any:
@@ -512,6 +532,10 @@
 	cl.xmlOut <- msg
 }
 
+// Register a callback to handle the next XMPP stanza (iq, message, or
+// presence) with a given id. The provided function will not be called
+// more than once. If it returns false, the stanza will not be made
+// available on the normal Client.In channel.
 func (cl *Client) HandleStanza(id string, f func(Stanza) bool) {
 	h := &stanzaHandler{id: id, f: f}
 	cl.handlers <- h