stream.go
branchgo.weekly.2012-01-15
changeset 93 fbd51fa6b7ea
parent 84 25c4296a3524
--- a/stream.go	Mon Jan 23 21:58:53 2012 -0700
+++ b/stream.go	Sun Apr 15 11:20:55 2012 -0600
@@ -19,7 +19,6 @@
 	"encoding/xml"
 	"fmt"
 	"io"
-	"log/syslog"
 	"math/big"
 	"net"
 	"regexp"
@@ -52,11 +51,17 @@
 
 func (cl *Client) readTransport(w io.WriteCloser) {
 	defer w.Close()
-	cl.socket.SetReadTimeout(1e8)
+	readDelay, _ := time.ParseDuration("1s")
 	p := make([]byte, 1024)
 	for {
 		if cl.socket == nil {
 			cl.waitForSocket()
+			readDelay = 0
+		}
+		if readDelay != 0 {
+			readTimeout := time.Now()
+			readTimeout.Add(readDelay)
+			cl.socket.SetReadDeadline(readTimeout)
 		}
 		nr, err := cl.socket.Read(p)
 		if nr == 0 {
@@ -103,14 +108,14 @@
 
 func readXml(r io.Reader, ch chan<- interface{},
 	extStanza map[string]func(*xml.Name) interface{}) {
-	if Loglevel >= syslog.LOG_DEBUG {
+	if Loglevel >= LOG_DEBUG {
 		pr, pw := io.Pipe()
 		go tee(r, pw, "S: ")
 		r = pr
 	}
 	defer close(ch)
 
-	p := xml.NewParser(r)
+	p := xml.NewDecoder(r)
 Loop:
 	for {
 		// Sniff the next token on the stream.
@@ -162,14 +167,14 @@
 			obj = &Presence{}
 		default:
 			obj = &Generic{}
-			if Log != nil && Loglevel >= syslog.LOG_NOTICE {
+			if Log != nil && Loglevel >= LOG_NOTICE {
 				Log.Printf("Ignoring unrecognized: %s %s",
 					se.Name.Space, se.Name.Local)
 			}
 		}
 
 		// Read the complete XML stanza.
-		err = p.Unmarshal(obj, &se)
+		err = p.DecodeElement(obj, &se)
 		if err != nil {
 			if Log != nil {
 				Log.Println("unmarshal: " + err.Error())
@@ -200,7 +205,7 @@
 	// Now parse the stanza's innerxml to find the string that we
 	// can unmarshal this nested element from.
 	reader := strings.NewReader(st.innerxml())
-	p := xml.NewParser(reader)
+	p := xml.NewDecoder(reader)
 	for {
 		t, err := p.Token()
 		if err == io.EOF {
@@ -216,7 +221,7 @@
 
 				// Unmarshal the nested element and
 				// stuff it back into the stanza.
-				err := p.Unmarshal(nested, &se)
+				err := p.DecodeElement(nested, &se)
 				if err != nil {
 					return err
 				}
@@ -229,7 +234,7 @@
 }
 
 func writeXml(w io.Writer, ch <-chan interface{}) {
-	if Loglevel >= syslog.LOG_DEBUG {
+	if Loglevel >= LOG_DEBUG {
 		pr, pw := io.Pipe()
 		go tee(pr, w, "C: ")
 		w = pw
@@ -241,7 +246,7 @@
 	}(w)
 
 	for obj := range ch {
-		err := xml.Marshal(w, obj)
+		err := xml.NewEncoder(w).Encode(obj)
 		if err != nil {
 			if Log != nil {
 				Log.Println("write: " + err.Error())
@@ -284,7 +289,7 @@
 			}
 			st, ok := x.(Stanza)
 			if !ok {
-				if Log != nil && Loglevel >= syslog.LOG_WARNING {
+				if Log != nil && Loglevel >= LOG_WARNING {
 					Log.Printf(
 						"Unhandled non-stanza: %v", x)
 				}
@@ -328,7 +333,7 @@
 				break Loop
 			}
 			if x == nil {
-				if Log != nil && Loglevel >= syslog.LOG_NOTICE {
+				if Log != nil && Loglevel >= LOG_NOTICE {
 					Log.Println("Refusing to send" +
 						" nil stanza")
 				}
@@ -349,7 +354,7 @@
 		select {
 		case newFilterOut := <-filterOut:
 			if newFilterOut == nil {
-				if Log != nil && Loglevel >= syslog.LOG_WARNING {
+				if Log != nil && Loglevel >= LOG_WARNING {
 					Log.Println("Received nil filter")
 				}
 				filterIn <- nil
@@ -378,7 +383,7 @@
 }
 
 func (cl *Client) handleStreamError(se *streamError) {
-	if Log != nil && Loglevel >= syslog.LOG_NOTICE {
+	if Log != nil && Loglevel >= LOG_NOTICE {
 		Log.Printf("Received stream error: %v", se)
 	}
 	close(cl.Out)
@@ -428,11 +433,7 @@
 	cl.socket = tls
 	cl.socketSync.Wait()
 
-	// Reset the read timeout on the (underlying) socket so the
-	// reader doesn't get woken up unnecessarily.
-	tcp.SetReadTimeout(0)
-
-	if Log != nil && Loglevel >= syslog.LOG_INFO {
+	if Log != nil && Loglevel >= LOG_INFO {
 		Log.Println("TLS negotiation succeeded.")
 	}
 	cl.Features = nil
@@ -470,8 +471,7 @@
 	}
 
 	if external {
-		auth := &auth{XMLName: xml.Name{Space: NsSASL, Local:
-				"auth"}, Mechanism: "EXTERNAL"}
+		auth := &auth{XMLName: xml.Name{Space: NsSASL, Local: "auth"}, Mechanism: "EXTERNAL"}
 		cl.xmlOut <- auth
 	} else if digestMd5 {
 		auth := &auth{XMLName: xml.Name{Space: NsSASL, Local: "auth"}, Mechanism: "DIGEST-MD5"}
@@ -479,17 +479,15 @@
 	} else {
 		if Log != nil {
 			buf := bytes.NewBuffer(nil)
-			xml.Marshal(buf, fe)
+			xml.NewEncoder(buf).Encode(fe)
 			Log.Printf("No supported mechanisms: %s",
 				buf.String())
 		}
 		abort := Generic{XMLName: xml.Name{Local: "abort",
 			Space: NsSASL}}
 		cl.xmlOut <- abort
-		se := streamError{Any: Generic{XMLName:
-				xml.Name{Local: "undefined-condition",
-				Space: NsStreams}}, Text:
-			&errText{Lang: "en", Text: "No supported mechs"}}
+		se := streamError{Any: Generic{XMLName: xml.Name{Local: "undefined-condition",
+			Space: NsStreams}}, Text: &errText{Lang: "en", Text: "No supported mechs"}}
 		cl.xmlOut <- se
 		close(cl.xmlOut)
 	}
@@ -515,11 +513,11 @@
 			cl.saslDigest2(srvMap)
 		}
 	case "failure":
-		if Log != nil && Loglevel >= syslog.LOG_NOTICE {
+		if Log != nil && Loglevel >= LOG_NOTICE {
 			Log.Println("SASL authentication failed")
 		}
 	case "success":
-		if Log != nil && Loglevel >= syslog.LOG_INFO {
+		if Log != nil && Loglevel >= LOG_INFO {
 			Log.Println("Sasl authentication succeeded")
 		}
 		cl.Features = nil
@@ -708,7 +706,7 @@
 			return false
 		}
 		cl.Jid = *jid
-		if Log != nil && Loglevel >= syslog.LOG_INFO {
+		if Log != nil && Loglevel >= LOG_INFO {
 			Log.Println("Bound resource: " + cl.Jid.String())
 		}
 		cl.bindDone()