Added global variables for logging.
authorChris Jones <chris@cjones.org>
Sun, 08 Jan 2012 09:11:14 -0700
changeset 62 6e2eea62ccca
parent 61 16513974d273
child 63 c7f2edd25f4a
child 69 a38173c1c8b2
Added global variables for logging.
stream.go
xmpp.go
--- a/stream.go	Sat Jan 07 22:22:18 2012 -0700
+++ b/stream.go	Sun Jan 08 09:11:14 2012 -0700
@@ -18,11 +18,11 @@
 	"encoding/base64"
 	"fmt"
 	"io"
-	"log"
 	"net"
 	"os"
 	"regexp"
 	"strings"
+	"syslog"
 	"time"
 	"xml"
 )
@@ -52,12 +52,16 @@
 					continue
 				}
 			}
-			log.Printf("read: %s", err.String())
+			if Log != nil {
+				Log.Err("read: " + err.String())
+			}
 			break
 		}
 		nw, err := w.Write(p[:nr])
 		if nw < nr {
-			log.Println("read: %s", err.String())
+			if Log != nil {
+				Log.Err("read: " + err.String())
+			}
 			break
 		}
 	}
@@ -69,12 +73,16 @@
 	for {
 		nr, err := r.Read(p)
 		if nr == 0 {
-			log.Printf("write: %s", err.String())
+			if Log != nil {
+				Log.Err("write: " + err.String())
+			}
 			break
 		}
 		nw, err := cl.socket.Write(p[:nr])
 		if nw < nr {
-			log.Println("write: %s", err.String())
+			if Log != nil {
+				Log.Err("write: " + err.String())
+			}
 			break
 		}
 	}
@@ -82,7 +90,7 @@
 
 func readXml(r io.Reader, ch chan<- interface{},
 	extStanza map[string] func(*xml.Name) interface{}) {
-	if debug {
+	if Loglevel >= syslog.LOG_DEBUG {
 		pr, pw := io.Pipe()
 		go tee(r, pw, "S: ")
 		r = pr
@@ -95,7 +103,9 @@
 		t, err := p.Token()
 		if t == nil {
 			if err != os.EOF {
-				log.Printf("read: %v", err)
+				if Log != nil {
+					Log.Err("read: " + err.String())
+				}
 			}
 			break
 		}
@@ -111,8 +121,10 @@
 		case NsStream + " stream":
 			st, err := parseStream(se)
 			if err != nil {
-				log.Printf("unmarshal stream: %v",
-					err)
+				if Log != nil {
+					Log.Err("unmarshal stream: " +
+						err.String())
+				}
 				break
 			}
 			ch <- st
@@ -134,14 +146,18 @@
 			obj = &Presence{}
 		default:
 			obj = &Generic{}
-			log.Printf("Ignoring unrecognized: %s %s\n",
-				se.Name.Space, se.Name.Local)
+			if Log != nil {
+				Log.Notice("Ignoring unrecognized: " +
+					se.Name.Space + " " + se.Name.Local)
+			}
 		}
 
 		// Read the complete XML stanza.
 		err = p.Unmarshal(obj, &se)
 		if err != nil {
-			log.Printf("unmarshal: %v", err)
+			if Log != nil {
+				Log.Err("unmarshal: " + err.String())
+			}
 			break
 		}
 
@@ -151,8 +167,10 @@
 		if st, ok := obj.(Stanza) ; ok {
 			err = parseExtended(st, extStanza)
 			if err != nil {
-				log.Printf("ext unmarshal: %v",
-					err)
+				if Log != nil {
+					Log.Err("ext unmarshal: " +
+						err.String())
+				}
 				break
 			}
 		}
@@ -195,7 +213,7 @@
 }
 
 func writeXml(w io.Writer, ch <-chan interface{}) {
-	if debug {
+	if Loglevel >= syslog.LOG_DEBUG {
 		pr, pw := io.Pipe()
 		go tee(pr, w, "C: ")
 		w = pw
@@ -205,7 +223,9 @@
 	for obj := range ch {
 		err := xml.Marshal(w, obj)
 		if err != nil {
-			log.Printf("write: %v", err)
+			if Log != nil {
+				Log.Err("write: " + err.String())
+			}
 			break
 		}
 	}
@@ -243,8 +263,10 @@
 			}
 			st, ok := x.(Stanza)
 			if !ok {
-				log.Printf("Unhandled non-stanza: %v",
-					x)
+				if Log != nil {
+					Log.Warning(fmt.Sprintf(
+						"Unhandled non-stanza: %v", x))
+				}
 				continue
 			}
 			if handlers[st.GetId()] != nil {
@@ -281,7 +303,10 @@
 			}
 		case x := <- input:
 			if x == nil {
-				log.Println("Refusing to send nil stanza")
+				if Log != nil {
+					Log.Notice("Refusing to send" +
+						" nil stanza")
+				}
 				continue
 			}
 			srvOut <- x
@@ -298,7 +323,9 @@
 		select {
 		case newFilterOut := <- filterOut:
 			if newFilterOut == nil {
-				log.Println("Received nil filter")
+				if Log != nil {
+					Log.Warning("Received nil filter")
+				}
 				filterIn <- nil
 				continue
 			}
@@ -325,7 +352,9 @@
 }
 
 func (cl *Client) handleStreamError(se *streamError) {
-	log.Printf("Received stream error: %v", se)
+	if Log != nil {
+		Log.Notice(fmt.Sprintf("Received stream error: %v", se))
+	}
 	cl.Close()
 }
 
@@ -374,7 +403,9 @@
 	// reader doesn't get woken up unnecessarily.
 	tcp.SetReadTimeout(0)
 
-	log.Println("TLS negotiation succeeded.")
+	if Log != nil {
+		Log.Info("TLS negotiation succeeded.")
+	}
 	cl.Features = nil
 
 	// Now re-send the initial handshake message to start the new
@@ -421,8 +452,10 @@
 		b64 := base64.StdEncoding
 		str, err := b64.DecodeString(srv.Chardata)
 		if err != nil {
-			log.Printf("SASL challenge decode: %s",
-				err.String())
+			if Log != nil {
+				Log.Err("SASL challenge decode: " +
+					err.String())
+			}
 			return;
 		}
 		srvMap := parseSasl(string(str))
@@ -433,9 +466,13 @@
 			cl.saslDigest2(srvMap)
 		}
 	case "failure":
-		log.Println("SASL authentication failed")
+		if Log != nil {
+			Log.Notice("SASL authentication failed")
+		}
 	case "success":
-		log.Println("SASL authentication succeeded")
+		if Log != nil {
+			Log.Info("Sasl authentication succeeded")
+		}
 		cl.Features = nil
 		ss := &stream{To: cl.Jid.Domain, Version: Version}
 		cl.xmlOut <- ss
@@ -451,7 +488,9 @@
 		}
 	}
 	if !hasAuth {
-		log.Println("Server doesn't support SASL auth")
+		if Log != nil {
+			Log.Err("Server doesn't support SASL auth")
+		}
 		return;
 	}
 
@@ -481,7 +520,9 @@
 	randSize.Lsh(big.NewInt(1), 64)
 	cnonce, err := rand.Int(rand.Reader, randSize)
 	if err != nil {
-		log.Println("SASL rand: %s", err.String())
+		if Log != nil {
+			Log.Err("SASL rand: " + err.String())
+		}
 		return
 	}
 	cnonceStr := fmt.Sprintf("%016x", cnonce)
@@ -591,7 +632,9 @@
 	msg := &Iq{Type: "set", Id: <- Id, Nested: []interface{}{bindReq}}
 	f := func(st Stanza) bool {
 		if st.GetType() == "error" {
-			log.Println("Resource binding failed")
+			if Log != nil {
+				Log.Err("Resource binding failed")
+			}
 			return false
 		}
 		var bindRepl *bindIq
@@ -602,21 +645,30 @@
 			}
 		}
 		if bindRepl == nil {
-			log.Printf("bad bind reply: %v", st)
+			if Log != nil {
+				Log.Err(fmt.Sprintf("Bad bind reply: %v",
+					st))
+			}
 			return false
 		}
 		jidStr := bindRepl.Jid
 		if jidStr == nil || *jidStr == "" {
-			log.Println("empty resource")
+			if Log != nil {
+				Log.Err("Can't bind empty resource")
+			}
 			return false
 		}
 		jid := new(JID)
 		if !jid.Set(*jidStr) {
-			log.Println("Can't parse JID %s", jidStr)
+			if Log != nil {
+				Log.Err("Can't parse JID " + *jidStr)
+			}
 			return false
 		}
 		cl.Jid = *jid
-		log.Printf("Bound resource: %s", cl.Jid.String())
+		if Log != nil {
+			Log.Info("Bound resource: " + cl.Jid.String())
+		}
 		cl.bindDone()
 		return false
 	}
--- a/xmpp.go	Sat Jan 07 22:22:18 2012 -0700
+++ b/xmpp.go	Sun Jan 08 09:11:14 2012 -0700
@@ -13,10 +13,10 @@
 	"bytes"
 	"fmt"
 	"io"
-	"log"
 	"net"
 	"os"
 	"sync"
+	"syslog"
 	"xml"
 )
 
@@ -36,12 +36,14 @@
 	// DNS SRV names
 	serverSrv = "xmpp-server"
 	clientSrv = "xmpp-client"
+)
 
-	// BUG(cjyar) Make this a parameter to NewClient, not a
-	// constant. We should have both a log level and a
-	// syslog.Writer, so the app can control how much time we
-	// spend generating log messages, as well as where they go.
-	debug = false
+var (
+	// If non-nil when NewClient() is called, log messages will be
+	// sent to this writer.
+	Log *syslog.Writer
+	// Threshold for which messages are logged.
+	Loglevel syslog.Priority = syslog.LOG_NOTICE
 )
 
 // This channel may be used as a convenient way to generate a unique
@@ -239,7 +241,7 @@
 func tee(r io.Reader, w io.Writer, prefix string) {
 	defer tryClose(r, w)
 
-	buf := bytes.NewBuffer(nil)
+	buf := bytes.NewBuffer([]uint8(prefix))
 	for {
 		var c [1]byte
 		n, _ := r.Read(c[:])
@@ -252,13 +254,13 @@
 		}
 		buf.Write(c[:n])
 		if c[0] == '\n' || c[0] == '>' {
-			fmt.Printf("%s%s\n", prefix, buf.String())
+			Log.Debug(buf.String())
 			buf.Reset()
 		}
 	}
 	leftover := buf.String()
 	if leftover != "" {
-		fmt.Printf("%s%s\n", prefix, leftover)
+		Log.Debug(buf.String())
 	}
 }
 
@@ -307,7 +309,10 @@
 	ch := make(chan os.Error)
 	f := func(st Stanza) bool {
 		if st.GetType() == "error" {
-			log.Printf("Can't start session: %v", st)
+			if Log != nil {
+				Log.Err(fmt.Sprintf("Can't start session: %v",
+					st))
+			}
 			ch <- st.GetError()
 			return false
 		}