--- 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
}