# HG changeset patch # User Chris Jones # Date 1334510455 21600 # Node ID fbd51fa6b7eab672c03694faa173f48e578514d2 # Parent d19b556d4ea62da30e7203f826f3d4803fae87fc Cleanup for Go 1. diff -r d19b556d4ea6 -r fbd51fa6b7ea roster_test.go --- a/roster_test.go Mon Jan 23 21:58:53 2012 -0700 +++ b/roster_test.go Sun Apr 15 11:20:55 2012 -0600 @@ -7,7 +7,6 @@ import ( "encoding/xml" "reflect" - "strings" "testing" ) @@ -23,9 +22,8 @@ func TestRosterIqUnmarshal(t *testing.T) { str := `` - r := strings.NewReader(str) var st Stanza = &Iq{} - err := xml.Unmarshal(r, st) + err := xml.Unmarshal([]byte(str), st) if err != nil { t.Fatalf("Unmarshal: %v", err) } diff -r d19b556d4ea6 -r fbd51fa6b7ea stream.go --- 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() diff -r d19b556d4ea6 -r fbd51fa6b7ea structs.go --- a/structs.go Mon Jan 23 21:58:53 2012 -0700 +++ b/structs.go Sun Apr 15 11:20:55 2012 -0600 @@ -31,6 +31,7 @@ // XMPP's XML element type stream struct { + XMLName xml.Name `xml:"stream stream"` To string `xml:"to,attr"` From string `xml:"from,attr"` Id string `xml:"id,attr"` @@ -38,30 +39,26 @@ Version string `xml:"version,attr"` } -var _ xml.Marshaler = &stream{} var _ fmt.Stringer = &stream{} // type streamError struct { - Any Generic `xml:",any"` + Any Generic `xml:",any"` Text *errText `xml:"text"` } -var _ xml.Marshaler = &streamError{} - type errText struct { + XMLName xml.Name `xml:"urn:ietf:params:xml:ns:xmpp-streams text"` Lang string `xml:"lang,attr"` Text string `xml:",chardata"` } -var _ xml.Marshaler = &errText{} - type Features struct { Starttls *starttls `xml:"starttls"` - Mechanisms mechs `xml:"mechanisms"` - Bind *bindIq `xml:"bind"` - Session *Generic `xml:"session"` - Any *Generic `xml:",any"` + Mechanisms mechs `xml:"mechanisms"` + Bind *bindIq `xml:"bind"` + Session *Generic `xml:"session"` + Any *Generic `xml:",any"` } type starttls struct { @@ -75,8 +72,8 @@ type auth struct { XMLName xml.Name - Chardata string `xml:",chardata"` - Mechanism string `xml:"mechanism,attr"` + Chardata string `xml:",chardata"` + Mechanism string `xml:"mechanism,attr"` Any *Generic `xml:",any"` } @@ -106,53 +103,53 @@ // message stanza type Message struct { - To string `xml:"to,attr"` - From string `xml:"from,attr"` - Id string `xml:"id,attr"` - Type string `xml:"type,attr"` - Lang string `xml:"lang,attr"` - Innerxml string `xml:",innerxml"` - Error *Error `xml:"error"` + XMLName xml.Name `xml:"message"` + To string `xml:"to,attr,omitempty"` + From string `xml:"from,attr,omitempty"` + Id string `xml:"id,attr,omitempty"` + Type string `xml:"type,attr,omitempty"` + Lang string `xml:"lang,attr,omitempty"` + Innerxml string `xml:",innerxml"` + Error *Error `xml:"error"` Subject *Generic `xml:"subject"` Body *Generic `xml:"body"` Thread *Generic `xml:"thread"` Nested []interface{} } -var _ xml.Marshaler = &Message{} var _ Stanza = &Message{} // presence stanza type Presence struct { - To string `xml:"to,attr"` - From string `xml:"from,attr"` - Id string `xml:"id,attr"` - Type string `xml:"type,attr"` - Lang string `xml:"lang,attr"` - Innerxml string `xml:",innerxml"` - Error *Error `xml:"error"` + XMLName xml.Name `xml:"presence"` + To string `xml:"to,attr,omitempty"` + From string `xml:"from,attr,omitempty"` + Id string `xml:"id,attr,omitempty"` + Type string `xml:"type,attr,omitempty"` + Lang string `xml:"lang,attr,omitempty"` + Innerxml string `xml:",innerxml"` + Error *Error `xml:"error"` Show *Generic `xml:"show"` Status *Generic `xml:"status"` Priority *Generic `xml:"priority"` Nested []interface{} } -var _ xml.Marshaler = &Presence{} var _ Stanza = &Presence{} // iq stanza type Iq struct { - To string `xml:"to,attr"` - From string `xml:"from,attr"` - Id string `xml:"id,attr"` - Type string `xml:"type,attr"` - Lang string `xml:"lang,attr"` + XMLName xml.Name `xml:"iq"` + To string `xml:"to,attr,omitempty"` + From string `xml:"from,attr,omitempty"` + Id string `xml:"id,attr,omitempty"` + Type string `xml:"type,attr,omitempty"` + Lang string `xml:"xml lang,attr,omitempty"` Innerxml string `xml:",innerxml"` Error *Error `xml:"error"` Nested []interface{} } -var _ xml.Marshaler = &Iq{} var _ Stanza = &Iq{} // Describes an XMPP stanza error. See RFC 3920, Section 9.3. @@ -177,7 +174,7 @@ type Generic struct { XMLName xml.Name Any *Generic `xml:",any"` - Chardata string `xml:",chardata"` + Chardata string `xml:",chardata"` } var _ fmt.Stringer = &Generic{} @@ -207,24 +204,16 @@ return nil } -func (s *stream) MarshalXML() ([]byte, error) { +func (s *stream) String() string { buf := bytes.NewBuffer(nil) buf.WriteString("") - // We never write - return buf.Bytes(), nil -} - -func (s *stream) String() string { - result, _ := s.MarshalXML() - return string(result) + return buf.String() } func parseStream(se xml.StartElement) (*stream, error) { @@ -246,28 +235,6 @@ return s, nil } -func (s *streamError) MarshalXML() ([]byte, error) { - buf := bytes.NewBuffer(nil) - buf.WriteString("") - xml.Marshal(buf, s.Any) - if s.Text != nil { - xml.Marshal(buf, s.Text) - } - buf.WriteString("") - return buf.Bytes(), nil -} - -func (e *errText) MarshalXML() ([]byte, error) { - buf := bytes.NewBuffer(nil) - buf.WriteString("") - xml.Escape(buf, []byte(e.Text)) - buf.WriteString("") - return buf.Bytes(), nil -} - func writeField(w io.Writer, field, value string) { if value != "" { io.WriteString(w, " ") @@ -291,72 +258,9 @@ u.XMLName.Local) } -func marshalXML(st Stanza) ([]byte, error) { - buf := bytes.NewBuffer(nil) - buf.WriteString("<") - buf.WriteString(st.GetName()) - if st.GetTo() != "" { - writeField(buf, "to", st.GetTo()) - } - if st.GetFrom() != "" { - writeField(buf, "from", st.GetFrom()) - } - if st.GetId() != "" { - writeField(buf, "id", st.GetId()) - } - if st.GetType() != "" { - writeField(buf, "type", st.GetType()) - } - if st.GetLang() != "" { - writeField(buf, "xml:lang", st.GetLang()) - } - buf.WriteString(">") - - if m, ok := st.(*Message); ok { - err := xml.Marshal(buf, m.Subject) - if err != nil { - return nil, err - } - err = xml.Marshal(buf, m.Body) - if err != nil { - return nil, err - } - err = xml.Marshal(buf, m.Thread) - if err != nil { - return nil, err - } - } - if p, ok := st.(*Presence); ok { - err := xml.Marshal(buf, p.Show) - if err != nil { - return nil, err - } - err = xml.Marshal(buf, p.Status) - if err != nil { - return nil, err - } - err = xml.Marshal(buf, p.Priority) - if err != nil { - return nil, err - } - } - if nested := st.GetNested(); nested != nil { - for _, n := range nested { - xml.Marshal(buf, n) - } - } else if st.innerxml() != "" { - buf.WriteString(st.innerxml()) - } - - buf.WriteString("") - return buf.Bytes(), nil -} - func (er *Error) Error() string { buf := bytes.NewBuffer(nil) - xml.Marshal(buf, er) + xml.NewEncoder(buf).Encode(er) return buf.String() } @@ -400,10 +304,6 @@ return m.Innerxml } -func (m *Message) MarshalXML() ([]byte, error) { - return marshalXML(m) -} - func (p *Presence) GetName() string { return "presence" } @@ -444,10 +344,6 @@ return p.Innerxml } -func (p *Presence) MarshalXML() ([]byte, error) { - return marshalXML(p) -} - func (iq *Iq) GetName() string { return "iq" } @@ -488,15 +384,11 @@ return iq.Innerxml } -func (iq *Iq) MarshalXML() ([]byte, error) { - return marshalXML(iq) -} - // Parse a string into a struct implementing Stanza -- this will be // either an Iq, a Message, or a Presence. func ParseStanza(str string) (Stanza, error) { r := strings.NewReader(str) - p := xml.NewParser(r) + p := xml.NewDecoder(r) tok, err := p.Token() if err != nil { return nil, err @@ -516,7 +408,7 @@ default: return nil, errors.New("Not iq, message, or presence") } - err = p.Unmarshal(stan, &se) + err = p.DecodeElement(stan, &se) if err != nil { return nil, err } diff -r d19b556d4ea6 -r fbd51fa6b7ea structs_test.go --- a/structs_test.go Mon Jan 23 21:58:53 2012 -0700 +++ b/structs_test.go Sun Apr 15 11:20:55 2012 -0600 @@ -44,7 +44,7 @@ func assertMarshal(t *testing.T, expected string, marshal interface{}) { buf := bytes.NewBuffer(nil) - xml.Marshal(buf, marshal) + xml.NewEncoder(buf).Encode(marshal) observed := string(buf.Bytes()) assertEquals(t, expected, observed) } diff -r d19b556d4ea6 -r fbd51fa6b7ea xmpp.go --- a/xmpp.go Mon Jan 23 21:58:53 2012 -0700 +++ b/xmpp.go Sun Apr 15 11:20:55 2012 -0600 @@ -14,7 +14,6 @@ "fmt" "io" "log" - "log/syslog" "net" "sync" ) @@ -37,12 +36,26 @@ clientSrv = "xmpp-client" ) +// This is copied from log/syslog, because that's not implemented on +// Windows. +type Priority int +const ( + LOG_EMERG Priority = iota + LOG_ALERT + LOG_CRIT + LOG_ERR + LOG_WARNING + LOG_NOTICE + LOG_INFO + LOG_DEBUG +) + var ( // If non-nil when NewClient() is called, log messages will be // sent to this writer. Log *log.Logger // Threshold for which messages are logged. - Loglevel syslog.Priority = syslog.LOG_NOTICE + Loglevel Priority = LOG_NOTICE // Use this Config to negotiate TLS connections. TLSConfig *tls.Config = nil )