equal
deleted
inserted
replaced
7 package xmpp |
7 package xmpp |
8 |
8 |
9 import ( |
9 import ( |
10 "fmt" |
10 "fmt" |
11 "io" |
11 "io" |
|
12 "log" |
12 "net" |
13 "net" |
13 "os" |
14 "os" |
|
15 "xml" |
14 ) |
16 ) |
15 |
17 |
16 const ( |
18 const ( |
17 serverSrv = "xmpp-server" |
19 serverSrv = "xmpp-server" |
18 clientSrv = "xmpp-client" |
20 clientSrv = "xmpp-client" |
19 ) |
21 ) |
20 |
22 |
21 // The client in a client-server XMPP connection. |
23 // The client in a client-server XMPP connection. |
22 type Client struct { |
24 type Client struct { |
23 //In <-chan *Stanza |
25 In <-chan interface{} |
24 //Out chan<- *Stanza |
26 in chan interface{} |
|
27 Out chan<- interface{} |
|
28 out chan interface{} |
25 tcp *net.TCPConn |
29 tcp *net.TCPConn |
26 } |
30 } |
27 var _ io.Closer = &Client{} |
31 var _ io.Closer = &Client{} |
28 |
32 |
29 // Connect to the appropriate server and authenticate as the given JID |
33 // Connect to the appropriate server and authenticate as the given JID |
56 return nil, err |
60 return nil, err |
57 } |
61 } |
58 |
62 |
59 cl := Client{} |
63 cl := Client{} |
60 cl.tcp = c |
64 cl.tcp = c |
|
65 cl.in = make(chan interface{}) |
|
66 cl.In = cl.in |
|
67 // TODO Send readXml a reader that we can close when we |
|
68 // negotiate TLS. |
|
69 go readXml(cl.tcp, cl.in) |
|
70 // TODO go writeXml(&cl) |
|
71 |
61 return &cl, nil |
72 return &cl, nil |
62 } |
73 } |
63 |
74 |
64 func (c *Client) Close() os.Error { |
75 func (c *Client) Close() os.Error { |
65 return c.tcp.Close() |
76 return c.tcp.Close() |
66 } |
77 } |
|
78 |
|
79 func readXml(r io.Reader, ch chan<- interface{}) { |
|
80 p := xml.NewParser(r) |
|
81 for { |
|
82 // Sniff the next token on the stream. |
|
83 t, err := p.Token() |
|
84 if t == nil { |
|
85 if err != os.EOF { |
|
86 log.Printf("read: %v", err) |
|
87 } |
|
88 break |
|
89 } |
|
90 var se xml.StartElement |
|
91 var ok bool |
|
92 if se, ok = t.(xml.StartElement) ; !ok { |
|
93 continue |
|
94 } |
|
95 |
|
96 // Allocate the appropriate structure for this token. |
|
97 var obj interface{} |
|
98 switch se.Name.Space + se.Name.Local { |
|
99 case "stream stream": |
|
100 st, err := parseStream(se) |
|
101 if err != nil { |
|
102 log.Printf("unmarshal stream: %v", |
|
103 err) |
|
104 break |
|
105 } |
|
106 ch <- st |
|
107 continue |
|
108 case nsStreams + " stream:error": |
|
109 obj = &StreamError{} |
|
110 default: |
|
111 obj = &Unrecognized{} |
|
112 } |
|
113 |
|
114 // Read the complete XML stanza. |
|
115 err = p.Unmarshal(obj, &se) |
|
116 if err != nil { |
|
117 log.Printf("unmarshal: %v", err) |
|
118 break |
|
119 } |
|
120 |
|
121 // Put it on the channel. |
|
122 ch <- obj |
|
123 } |
|
124 } |