xmpp.go
changeset 62 6e2eea62ccca
parent 61 16513974d273
child 63 c7f2edd25f4a
equal deleted inserted replaced
61:16513974d273 62:6e2eea62ccca
    11 
    11 
    12 import (
    12 import (
    13 	"bytes"
    13 	"bytes"
    14 	"fmt"
    14 	"fmt"
    15 	"io"
    15 	"io"
    16 	"log"
       
    17 	"net"
    16 	"net"
    18 	"os"
    17 	"os"
    19 	"sync"
    18 	"sync"
       
    19 	"syslog"
    20 	"xml"
    20 	"xml"
    21 )
    21 )
    22 
    22 
    23 const (
    23 const (
    24 	// Version of RFC 3920 that we implement.
    24 	// Version of RFC 3920 that we implement.
    34 	NsRoster = "jabber:iq:roster"
    34 	NsRoster = "jabber:iq:roster"
    35 
    35 
    36 	// DNS SRV names
    36 	// DNS SRV names
    37 	serverSrv = "xmpp-server"
    37 	serverSrv = "xmpp-server"
    38 	clientSrv = "xmpp-client"
    38 	clientSrv = "xmpp-client"
    39 
    39 )
    40 	// BUG(cjyar) Make this a parameter to NewClient, not a
    40 
    41 	// constant. We should have both a log level and a
    41 var (
    42 	// syslog.Writer, so the app can control how much time we
    42 	// If non-nil when NewClient() is called, log messages will be
    43 	// spend generating log messages, as well as where they go.
    43 	// sent to this writer.
    44 	debug = false
    44 	Log *syslog.Writer
       
    45 	// Threshold for which messages are logged.
       
    46 	Loglevel syslog.Priority = syslog.LOG_NOTICE
    45 )
    47 )
    46 
    48 
    47 // This channel may be used as a convenient way to generate a unique
    49 // This channel may be used as a convenient way to generate a unique
    48 // id for an iq, message, or presence stanza.
    50 // id for an iq, message, or presence stanza.
    49 var Id <-chan string
    51 var Id <-chan string
   237 }
   239 }
   238 
   240 
   239 func tee(r io.Reader, w io.Writer, prefix string) {
   241 func tee(r io.Reader, w io.Writer, prefix string) {
   240 	defer tryClose(r, w)
   242 	defer tryClose(r, w)
   241 
   243 
   242 	buf := bytes.NewBuffer(nil)
   244 	buf := bytes.NewBuffer([]uint8(prefix))
   243 	for {
   245 	for {
   244 		var c [1]byte
   246 		var c [1]byte
   245 		n, _ := r.Read(c[:])
   247 		n, _ := r.Read(c[:])
   246 		if n == 0 {
   248 		if n == 0 {
   247 			break
   249 			break
   250 		if n == 0 {
   252 		if n == 0 {
   251 			break
   253 			break
   252 		}
   254 		}
   253 		buf.Write(c[:n])
   255 		buf.Write(c[:n])
   254 		if c[0] == '\n' || c[0] == '>' {
   256 		if c[0] == '\n' || c[0] == '>' {
   255 			fmt.Printf("%s%s\n", prefix, buf.String())
   257 			Log.Debug(buf.String())
   256 			buf.Reset()
   258 			buf.Reset()
   257 		}
   259 		}
   258 	}
   260 	}
   259 	leftover := buf.String()
   261 	leftover := buf.String()
   260 	if leftover != "" {
   262 	if leftover != "" {
   261 		fmt.Printf("%s%s\n", prefix, leftover)
   263 		Log.Debug(buf.String())
   262 	}
   264 	}
   263 }
   265 }
   264 
   266 
   265 func tryClose(xs ...interface{}) {
   267 func tryClose(xs ...interface{}) {
   266 	f1 := func(ch chan<- interface{}) {
   268 	f1 := func(ch chan<- interface{}) {
   305 		[]interface{}{ Generic{XMLName: xml.Name{Space:
   307 		[]interface{}{ Generic{XMLName: xml.Name{Space:
   306 					NsSession, Local: "session"}}}}
   308 					NsSession, Local: "session"}}}}
   307 	ch := make(chan os.Error)
   309 	ch := make(chan os.Error)
   308 	f := func(st Stanza) bool {
   310 	f := func(st Stanza) bool {
   309 		if st.GetType() == "error" {
   311 		if st.GetType() == "error" {
   310 			log.Printf("Can't start session: %v", st)
   312 			if Log != nil {
       
   313 				Log.Err(fmt.Sprintf("Can't start session: %v",
       
   314 					st))
       
   315 			}
   311 			ch <- st.GetError()
   316 			ch <- st.GetError()
   312 			return false
   317 			return false
   313 		}
   318 		}
   314 		ch <- nil
   319 		ch <- nil
   315 		return false
   320 		return false