# HG changeset patch # User Chris Jones # Date 1324745726 25200 # Node ID 4dabfef08c8c9138a3a49a5fb7b44955111d619c # Parent a01e06faf0db3c34a9abf23229b7251f58daad7f Forgot to add the new xmpp.go from my last commit. Also added some simple tests of data type marshaling. diff -r a01e06faf0db -r 4dabfef08c8c structs.go --- a/structs.go Sat Dec 24 00:39:18 2011 -0700 +++ b/structs.go Sat Dec 24 09:55:26 2011 -0700 @@ -44,7 +44,7 @@ type StreamError struct { cond definedCondition - text errText + text *errText } var _ xml.Marshaler = &StreamError{} @@ -54,7 +54,6 @@ } type errText struct { - XMLName xml.Name Lang string text string `xml:"chardata"` } @@ -88,7 +87,9 @@ buf := bytes.NewBuffer(nil) buf.WriteString("") xml.Marshal(buf, s.cond) - xml.Marshal(buf, s.text) + if s.text != nil { + xml.Marshal(buf, s.text) + } buf.WriteString("") return buf.Bytes(), nil } diff -r a01e06faf0db -r 4dabfef08c8c structs_test.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/structs_test.go Sat Dec 24 09:55:26 2011 -0700 @@ -0,0 +1,50 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xmpp + +import ( + "bytes" + "testing" + "xml" +) + +func TestStreamMarshal(t *testing.T) { + s := &Stream{to: "bob"} + exp := `` + assertMarshal(t, exp, s) + + s = &Stream{to: "bob", from: "alice", id: "#3", version: "5.3"} + exp = `` + assertMarshal(t, exp, s) + + s = &Stream{lang: "en_US"} + exp = `` + assertMarshal(t, exp, s) +} + +func TestStreamErrorMarshal(t *testing.T) { + name := xml.Name{Space: nsStreams, Local: "ack"} + e := &StreamError{cond: definedCondition{name}} + exp := ``; + assertMarshal(t, exp, e) + + txt := errText{Lang: "pt", text: "things happen"} + e = &StreamError{cond: definedCondition{name}, text: &txt} + exp = `things happen` + assertMarshal(t, exp, e) +} + +func assertMarshal(t *testing.T, expected string, marshal interface{}) { + buf := bytes.NewBuffer(nil) + xml.Marshal(buf, marshal) + observed := string(buf.Bytes()) + if expected != observed { + t.Errorf("Expected:\n%s\nObserved:\n%s\n", expected, + observed) + } +} diff -r a01e06faf0db -r 4dabfef08c8c xmpp.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xmpp.go Sat Dec 24 09:55:26 2011 -0700 @@ -0,0 +1,60 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This package implements a simple XMPP client according to RFCs 3920 +// and 3921, plus the various XEPs at http://xmpp.org/protocols/. +package xmpp + +import ( + "fmt" + "net" + "os" +) + +const ( + serverSrv = "xmpp-server" + clientSrv = "xmpp-client" +) + +// The client in a client-server XMPP connection. +type Client struct { + //In <-chan *Stanza + //Out chan<- *Stanza + tcp *net.TCPConn +} + +// Connect to the appropriate server and authenticate as the given JID +// with the given password. +func NewClient(jid *JID, password string) (*Client, os.Error) { + // Resolve the domain in the JID. + _, srvs, err := net.LookupSRV(clientSrv, "tcp", jid.Domain) + if err != nil { + return nil, os.NewError("LookupSrv " + jid.Domain + + ": " + err.String()) + } + + var c *net.TCPConn + for _, srv := range srvs { + addrStr := fmt.Sprintf("%s:%d", srv.Target, srv.Port) + addr, err := net.ResolveTCPAddr("tcp", addrStr) + if err != nil { + err = os.NewError(fmt.Sprintf("ResolveTCPAddr(%s): %s", + addrStr, err.String())) + continue + } + c, err = net.DialTCP("tcp", nil, addr) + if err != nil { + err = os.NewError(fmt.Sprintf("DialTCP(%s): %s", + addr, err.String())) + continue + } + } + if c == nil { + return nil, err + } + + cl := Client{} + cl.tcp = c + return &cl, nil +}