equal
deleted
inserted
replaced
43 debug = true |
43 debug = true |
44 ) |
44 ) |
45 |
45 |
46 // The client in a client-server XMPP connection. |
46 // The client in a client-server XMPP connection. |
47 type Client struct { |
47 type Client struct { |
48 // This client's JID. This will be updated asynchronously when |
48 // This client's JID. This will be updated asynchronously by |
49 // resource binding completes; at that time an iq stanza will |
49 // the time StartSession() returns. |
50 // be published on the In channel: |
|
51 // <iq><bind><jid>jid</jid></bind></iq> |
|
52 Jid JID |
50 Jid JID |
53 password string |
51 password string |
54 socket net.Conn |
52 socket net.Conn |
55 socketSync sync.WaitGroup |
53 socketSync sync.WaitGroup |
56 saslExpected string |
54 saslExpected string |
57 authDone bool |
55 authDone bool |
58 idMutex sync.Mutex |
56 idMutex sync.Mutex |
59 nextId int64 |
57 nextId int64 |
60 handlers chan *stanzaHandler |
58 handlers chan *stanzaHandler |
|
59 inputControl chan int |
61 // Incoming XMPP stanzas from the server will be published on |
60 // Incoming XMPP stanzas from the server will be published on |
62 // this channel. Information which is only used by this |
61 // this channel. Information which is only used by this |
63 // library to set up the XMPP stream will not appear here. |
62 // library to set up the XMPP stream will not appear here. |
64 In <-chan Stanza |
63 In <-chan Stanza |
65 // Outgoing XMPP stanzas to the server should be sent to this |
64 // Outgoing XMPP stanzas to the server should be sent to this |
106 cl := new(Client) |
105 cl := new(Client) |
107 cl.password = password |
106 cl.password = password |
108 cl.Jid = *jid |
107 cl.Jid = *jid |
109 cl.socket = tcp |
108 cl.socket = tcp |
110 cl.handlers = make(chan *stanzaHandler, 1) |
109 cl.handlers = make(chan *stanzaHandler, 1) |
|
110 cl.inputControl = make(chan int) |
111 |
111 |
112 // Start the transport handler, initially unencrypted. |
112 // Start the transport handler, initially unencrypted. |
113 tlsr, tlsw := cl.startTransport() |
113 tlsr, tlsw := cl.startTransport() |
114 |
114 |
115 // Start the reader and writers that convert to and from XML. |
115 // Start the reader and writers that convert to and from XML. |
117 cl.xmlOut = startXmlWriter(tlsw) |
117 cl.xmlOut = startXmlWriter(tlsw) |
118 |
118 |
119 // Start the XMPP stream handler which filters stream-level |
119 // Start the XMPP stream handler which filters stream-level |
120 // events and responds to them. |
120 // events and responds to them. |
121 clIn := cl.startStreamReader(xmlIn, cl.xmlOut) |
121 clIn := cl.startStreamReader(xmlIn, cl.xmlOut) |
122 clOut := startStreamWriter(cl.xmlOut) |
122 clOut := cl.startStreamWriter(cl.xmlOut) |
123 |
123 |
124 // Initial handshake. |
124 // Initial handshake. |
125 hsOut := &stream{To: jid.Domain, Version: Version} |
125 hsOut := &stream{To: jid.Domain, Version: Version} |
126 cl.xmlOut <- hsOut |
126 cl.xmlOut <- hsOut |
127 |
127 |
160 ch := make(chan Stanza) |
160 ch := make(chan Stanza) |
161 go cl.readStream(xmlIn, ch) |
161 go cl.readStream(xmlIn, ch) |
162 return ch |
162 return ch |
163 } |
163 } |
164 |
164 |
165 func startStreamWriter(xmlOut chan<- interface{}) chan<- Stanza { |
165 func (cl *Client) startStreamWriter(xmlOut chan<- interface{}) chan<- Stanza { |
166 ch := make(chan Stanza) |
166 ch := make(chan Stanza) |
167 go writeStream(xmlOut, ch) |
167 go writeStream(xmlOut, ch, cl.inputControl) |
168 return ch |
168 return ch |
169 } |
169 } |
170 |
170 |
171 func tee(r io.Reader, w io.Writer, prefix string) { |
171 func tee(r io.Reader, w io.Writer, prefix string) { |
172 defer tryClose(r, w) |
172 defer tryClose(r, w) |
227 cl.idMutex.Lock() |
227 cl.idMutex.Lock() |
228 defer cl.idMutex.Unlock() |
228 defer cl.idMutex.Unlock() |
229 id := cl.nextId |
229 id := cl.nextId |
230 cl.nextId++ |
230 cl.nextId++ |
231 return fmt.Sprintf("id_%d", id) |
231 return fmt.Sprintf("id_%d", id) |
|
232 } |
|
233 |
|
234 // bindDone is called when we've finished resource binding (and all |
|
235 // the negotiations that precede it). Now we can start accepting |
|
236 // traffic from the app. |
|
237 func (cl *Client) bindDone() { |
|
238 cl.inputControl <- 1 |
232 } |
239 } |
233 |
240 |
234 // Start an XMPP session. This should typically be done immediately |
241 // Start an XMPP session. This should typically be done immediately |
235 // after creating the new Client. Once the session has been |
242 // after creating the new Client. Once the session has been |
236 // established, pr will be sent as an initial presence; nil means |
243 // established, pr will be sent as an initial presence; nil means |