# HG changeset patch # User Chris Jones # Date 1324757496 25200 # Node ID faef59c8db058582086020cc5cf5756fb675eb94 # Parent a8fbec71a194a21c98c48439b76aa95d8842fd83 Added a goroutine to read data from the remote and parse it into appropriate structures. diff -r a8fbec71a194 -r faef59c8db05 structs.go --- a/structs.go Sat Dec 24 11:18:52 2011 -0700 +++ b/structs.go Sat Dec 24 13:11:36 2011 -0700 @@ -13,6 +13,7 @@ "io" "os" "regexp" + "strings" "xml" ) @@ -62,6 +63,10 @@ } var _ xml.Marshaler = &errText{} +type Unrecognized struct { + XMLName xml.Name +} + func (jid *JID) String() string { result := jid.Domain if jid.Node != nil { @@ -106,6 +111,26 @@ return buf.Bytes(), nil } +func parseStream(se xml.StartElement) (*Stream, os.Error) { + s := &Stream{} + se = se.Copy() + for _, attr := range se.Attr { + switch strings.ToLower(attr.Name.Local) { + case "to": + s.to = attr.Value + case "from": + s.from = attr.Value + case "id": + s.id = attr.Value + case "lang": + s.lang = attr.Value + case "version": + s.version = attr.Value + } + } + return s, nil +} + func (s *StreamError) MarshalXML() ([]byte, os.Error) { buf := bytes.NewBuffer(nil) buf.WriteString("") diff -r a8fbec71a194 -r faef59c8db05 xmpp.go --- a/xmpp.go Sat Dec 24 11:18:52 2011 -0700 +++ b/xmpp.go Sat Dec 24 13:11:36 2011 -0700 @@ -9,8 +9,10 @@ import ( "fmt" "io" + "log" "net" "os" + "xml" ) const ( @@ -20,8 +22,10 @@ // The client in a client-server XMPP connection. type Client struct { - //In <-chan *Stanza - //Out chan<- *Stanza + In <-chan interface{} + in chan interface{} + Out chan<- interface{} + out chan interface{} tcp *net.TCPConn } var _ io.Closer = &Client{} @@ -58,9 +62,63 @@ cl := Client{} cl.tcp = c + cl.in = make(chan interface{}) + cl.In = cl.in + // TODO Send readXml a reader that we can close when we + // negotiate TLS. + go readXml(cl.tcp, cl.in) + // TODO go writeXml(&cl) + return &cl, nil } func (c *Client) Close() os.Error { return c.tcp.Close() } + +func readXml(r io.Reader, ch chan<- interface{}) { + p := xml.NewParser(r) + for { + // Sniff the next token on the stream. + t, err := p.Token() + if t == nil { + if err != os.EOF { + log.Printf("read: %v", err) + } + break + } + var se xml.StartElement + var ok bool + if se, ok = t.(xml.StartElement) ; !ok { + continue + } + + // Allocate the appropriate structure for this token. + var obj interface{} + switch se.Name.Space + se.Name.Local { + case "stream stream": + st, err := parseStream(se) + if err != nil { + log.Printf("unmarshal stream: %v", + err) + break + } + ch <- st + continue + case nsStreams + " stream:error": + obj = &StreamError{} + default: + obj = &Unrecognized{} + } + + // Read the complete XML stanza. + err = p.Unmarshal(obj, &se) + if err != nil { + log.Printf("unmarshal: %v", err) + break + } + + // Put it on the channel. + ch <- obj + } +}