Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 787 lines (682 sloc) 21.997 kb
f27235b @rillian Move the xmpp library to its new name.
rillian authored
1 /* conn.c
b6027cf @metajack Updated copyright years and fixed LLC typo.
metajack authored
2 ** strophe XMPP client library -- connection object functions
f27235b @rillian Move the xmpp library to its new name.
rillian authored
3 **
370a371 Dual licensed libstrophe under MIT and GPLv3.
Jack Moffitt authored
4 ** Copyright (C) 2005-2009 Collecta, Inc.
f2335ad @rillian Conform the copyright headers.
rillian authored
5 **
6 ** This software is provided AS-IS with no warranty, either express
7 ** or implied.
8 **
9 ** This software is distributed under license and may not be copied,
10 ** modified or distributed except as expressly authorized under the
11 ** terms of the license contained in the file LICENSE.txt in this
12 ** distribution.
f27235b @rillian Move the xmpp library to its new name.
rillian authored
13 */
14
65a174e @metajack Most public API points are now documented.
metajack authored
15 /** @file
16 * Connection management.
17 */
18
19 /** @defgroup Connections Connection management
20 */
21
f27235b @rillian Move the xmpp library to its new name.
rillian authored
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
3fd7515 @metajack Abstracted XML parser library and switched to autotools building.
metajack authored
26 #include <strophe.h>
27
f27235b @rillian Move the xmpp library to its new name.
rillian authored
28 #include "common.h"
68c9a71 @metajack Partial fix for #11. Correctly calls connection handler on timeout now,
metajack authored
29 #include "util.h"
3fd7515 @metajack Abstracted XML parser library and switched to autotools building.
metajack authored
30 #include "parser.h"
f27235b @rillian Move the xmpp library to its new name.
rillian authored
31
65a174e @metajack Most public API points are now documented.
metajack authored
32 #ifndef DEFAULT_SEND_QUEUE_MAX
33 /** @def DEFAULT_SEND_QUEUE_MAX
34 * The default maximum send queue size. This is currently unused.
35 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
36 #define DEFAULT_SEND_QUEUE_MAX 64
65a174e @metajack Most public API points are now documented.
metajack authored
37 #endif
38 #ifndef DISCONNECT_TIMEOUT
39 /** @def DISCONNECT_TIMEOUT
40 * The time to wait (in milliseconds) for graceful disconnection to
41 * complete before the connection is reset. The default is 2 seconds.
42 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
43 #define DISCONNECT_TIMEOUT 2000 /* 2 seconds */
65a174e @metajack Most public API points are now documented.
metajack authored
44 #endif
45 #ifndef CONNECT_TIMEOUT
46 /** @def CONNECT_TIMEOUT
47 * The time to wait (in milliseconds) for a connection attempt to succeed
48 * or error. The default is 5 seconds.
49 */
68c9a71 @metajack Partial fix for #11. Correctly calls connection handler on timeout now,
metajack authored
50 #define CONNECT_TIMEOUT 5000 /* 5 seconds */
65a174e @metajack Most public API points are now documented.
metajack authored
51 #endif
f27235b @rillian Move the xmpp library to its new name.
rillian authored
52
53 static int _disconnect_cleanup(xmpp_conn_t * const conn,
54 void * const userdata);
55
3fd7515 @metajack Abstracted XML parser library and switched to autotools building.
metajack authored
56 static void _handle_stream_start(char *name, char **attrs,
57 void * const userdata);
58 static void _handle_stream_end(char *name,
59 void * const userdata);
60 static void _handle_stream_stanza(xmpp_stanza_t *stanza,
61 void * const userdata);
62
65a174e @metajack Most public API points are now documented.
metajack authored
63 /** Create a new Strophe connection object.
64 *
65 * @param ctx a Strophe context object
66 *
67 * @return a Strophe connection object or NULL on an error
68 *
69 * @ingroup Connections
70 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
71 xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx)
72 {
73 xmpp_conn_t *conn = NULL;
74 xmpp_connlist_t *tail, *item;
75
76 if (ctx == NULL) return NULL;
77 conn = xmpp_alloc(ctx, sizeof(xmpp_conn_t));
78
79 if (conn != NULL) {
80 conn->ctx = ctx;
81
82 conn->type = XMPP_UNKNOWN;
83 conn->sock = -1;
f45380b Added OpenSSL support.
James Canete authored
84 conn->tls = NULL;
68c9a71 @metajack Partial fix for #11. Correctly calls connection handler on timeout now,
metajack authored
85 conn->timeout_stamp = 0;
f27235b @rillian Move the xmpp library to its new name.
rillian authored
86 conn->error = 0;
87 conn->stream_error = NULL;
88
89 /* default send parameters */
90 conn->blocking_send = 0;
91 conn->send_queue_max = DEFAULT_SEND_QUEUE_MAX;
92 conn->send_queue_len = 0;
93 conn->send_queue_head = NULL;
94 conn->send_queue_tail = NULL;
95
68c9a71 @metajack Partial fix for #11. Correctly calls connection handler on timeout now,
metajack authored
96 /* default timeouts */
97 conn->connect_timeout = CONNECT_TIMEOUT;
98
f27235b @rillian Move the xmpp library to its new name.
rillian authored
99 conn->lang = xmpp_strdup(conn->ctx, "en");
100 if (!conn->lang) {
101 xmpp_free(conn->ctx, conn);
102 return NULL;
103 }
104 conn->domain = NULL;
105 conn->jid = NULL;
106 conn->pass = NULL;
107 conn->stream_id = NULL;
d048124 @dustin Capture the bound jid.
dustin authored
108 conn->bound_jid = NULL;
f27235b @rillian Move the xmpp library to its new name.
rillian authored
109
110 conn->tls_support = 0;
6f9be5e Add alternate domain and port to xmpp_client_connect() for when SRV look...
James Canete authored
111 conn->tls_failed = 0;
f27235b @rillian Move the xmpp library to its new name.
rillian authored
112 conn->sasl_support = 0;
3fd7515 @metajack Abstracted XML parser library and switched to autotools building.
metajack authored
113 conn->secured = 0;
f27235b @rillian Move the xmpp library to its new name.
rillian authored
114
b992133 @metajack Implement session establishment, which is required if the server
metajack authored
115 conn->bind_required = 0;
116 conn->session_required = 0;
117
3fd7515 @metajack Abstracted XML parser library and switched to autotools building.
metajack authored
118 conn->parser = parser_new(conn->ctx,
119 _handle_stream_start,
120 _handle_stream_end,
121 _handle_stream_stanza,
122 conn);
123 conn->reset_parser = 0;
124 conn_prepare_reset(conn, auth_handle_open);
f27235b @rillian Move the xmpp library to its new name.
rillian authored
125
126 conn->authenticated = 0;
127 conn->conn_handler = NULL;
128 conn->userdata = NULL;
129 conn->timed_handlers = NULL;
130 /* we own (and will free) the hash values */
131 conn->id_handlers = hash_new(conn->ctx, 32, NULL);
132 conn->handlers = NULL;
133
134 /* give the caller a reference to connection */
135 conn->ref = 1;
136
137 /* add connection to ctx->connlist */
138 tail = conn->ctx->connlist;
139 while (tail && tail->next) tail = tail->next;
140
141 item = xmpp_alloc(conn->ctx, sizeof(xmpp_connlist_t));
142 if (!item) {
143 xmpp_error(conn->ctx, "xmpp", "failed to allocate memory");
144 xmpp_free(conn->ctx, conn->lang);
3fd7515 @metajack Abstracted XML parser library and switched to autotools building.
metajack authored
145 parser_free(conn->parser);
f27235b @rillian Move the xmpp library to its new name.
rillian authored
146 xmpp_free(conn->ctx, conn);
147 conn = NULL;
148 } else {
149 item->conn = conn;
150 item->next = NULL;
151
152 if (tail) tail->next = item;
153 else conn->ctx->connlist = item;
154 }
155 }
156
157 return conn;
158 }
159
65a174e @metajack Most public API points are now documented.
metajack authored
160 /** Clone a Strophe connection object.
161 *
162 * @param conn a Strophe connection object
163 *
164 * @return the same conn object passed in with its reference count
165 * incremented by 1
166 *
167 * @ingroup Connections
168 */
fbb6a6b @metajack Implement stream:error handling.
metajack authored
169 xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t * const conn)
f27235b @rillian Move the xmpp library to its new name.
rillian authored
170 {
171 conn->ref++;
172 return conn;
173 }
174
65a174e @metajack Most public API points are now documented.
metajack authored
175 /** Release a Strophe connection object.
176 * Decrement the reference count by one for a connection, freeing the
177 * connection object if the count reaches 0.
178 *
179 * @param conn a Strophe connection object
180 *
181 * @return TRUE if the connection object was freed and FALSE otherwise
182 *
183 * @ingroup Connections
184 */
359c47f @metajack Another pass at C++ification.
metajack authored
185 int xmpp_conn_release(xmpp_conn_t * const conn)
f27235b @rillian Move the xmpp library to its new name.
rillian authored
186 {
187 xmpp_ctx_t *ctx;
188 xmpp_connlist_t *item, *prev;
189 xmpp_handlist_t *hlitem, *thli;
190 hash_iterator_t *iter;
191 const char *key;
359c47f @metajack Another pass at C++ification.
metajack authored
192 int released = 0;
f27235b @rillian Move the xmpp library to its new name.
rillian authored
193
194 if (conn->ref > 1)
195 conn->ref--;
196 else {
197 ctx = conn->ctx;
198
199 /* remove connection from context's connlist */
200 if (ctx->connlist->conn == conn) {
201 item = ctx->connlist;
202 ctx->connlist = item->next;
203 xmpp_free(ctx, item);
204 } else {
205 prev = NULL;
206 item = ctx->connlist;
207 while (item && item->conn != conn) {
208 prev = item;
209 item = item->next;
210 }
211
212 if (!item) {
213 xmpp_error(ctx, "xmpp", "Connection not in context's list\n");
214 } else {
215 prev->next = item->next;
216 xmpp_free(ctx, item);
217 }
218 }
219
220 /* free handler stuff
221 * note that userdata is the responsibility of the client
222 * and the handler pointers don't need to be freed since they
223 * are pointers to functions */
224
225 hlitem = conn->timed_handlers;
226 while (hlitem) {
227 thli = hlitem;
228 hlitem = hlitem->next;
229
230 xmpp_free(ctx, thli);
231 }
232
233 /* id handlers
234 * we have to traverse the hash table freeing list elements
235 * then release the hash table */
236 iter = hash_iter_new(conn->id_handlers);
237 while ((key = hash_iter_next(iter))) {
238 hlitem = (xmpp_handlist_t *)hash_get(conn->id_handlers, key);
239 while (hlitem) {
240 thli = hlitem;
241 hlitem = hlitem->next;
242 xmpp_free(conn->ctx, thli->id);
243 xmpp_free(conn->ctx, thli);
244 }
245 }
246 hash_iter_release(iter);
247 hash_release(conn->id_handlers);
248
249 hlitem = conn->handlers;
250 while (hlitem) {
251 thli = hlitem;
252 hlitem = hlitem->next;
253
fe4d7be @metajack Fix minor memory bug. We were freeing the _next_ item's attributes,
metajack authored
254 if (thli->ns) xmpp_free(ctx, thli->ns);
255 if (thli->name) xmpp_free(ctx, thli->name);
256 if (thli->type) xmpp_free(ctx, thli->type);
f27235b @rillian Move the xmpp library to its new name.
rillian authored
257 xmpp_free(ctx, thli);
258 }
259
260 if (conn->stream_error) {
261 xmpp_stanza_release(conn->stream_error->stanza);
fbb6a6b @metajack Implement stream:error handling.
metajack authored
262 if (conn->stream_error->text)
263 xmpp_free(ctx, conn->stream_error->text);
f27235b @rillian Move the xmpp library to its new name.
rillian authored
264 xmpp_free(ctx, conn->stream_error);
265 }
266
3fd7515 @metajack Abstracted XML parser library and switched to autotools building.
metajack authored
267 parser_free(conn->parser);
f27235b @rillian Move the xmpp library to its new name.
rillian authored
268
269 if (conn->domain) xmpp_free(ctx, conn->domain);
270 if (conn->jid) xmpp_free(ctx, conn->jid);
d048124 @dustin Capture the bound jid.
dustin authored
271 if (conn->bound_jid) xmpp_free(ctx, conn->bound_jid);
f27235b @rillian Move the xmpp library to its new name.
rillian authored
272 if (conn->pass) xmpp_free(ctx, conn->pass);
273 if (conn->stream_id) xmpp_free(ctx, conn->stream_id);
3156f50 @dustin Free the connection language.
dustin authored
274 if (conn->lang) xmpp_free(ctx, conn->lang);
f27235b @rillian Move the xmpp library to its new name.
rillian authored
275 xmpp_free(ctx, conn);
359c47f @metajack Another pass at C++ification.
metajack authored
276 released = 1;
f27235b @rillian Move the xmpp library to its new name.
rillian authored
277 }
359c47f @metajack Another pass at C++ification.
metajack authored
278
279 return released;
f27235b @rillian Move the xmpp library to its new name.
rillian authored
280 }
281
65a174e @metajack Most public API points are now documented.
metajack authored
282 /** Get the JID which is or will be bound to the connection.
283 *
284 * @param conn a Strophe connection object
285 *
286 * @return a string containing the full JID or NULL if it has not been set
287 *
288 * @ingroup Connections
289 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
290 const char *xmpp_conn_get_jid(const xmpp_conn_t * const conn)
291 {
292 return conn->jid;
293 }
294
d048124 @dustin Capture the bound jid.
dustin authored
295 /**
296 * Get the JID discovered during binding time.
297 *
298 * This JID will contain the resource used by the current connection.
299 * This is useful in the case where a resource was not specified for
300 * binding.
301 *
302 * @param conn a Strophe connection object.
303 *
304 * @return a string containing the full JID or NULL if it's not been discovered
305 *
306 * @ingroup Connections
307 */
308 const char *xmpp_conn_get_bound_jid(const xmpp_conn_t * const conn)
309 {
310 return conn->bound_jid;
311 }
312
65a174e @metajack Most public API points are now documented.
metajack authored
313 /** Set the JID of the user that will be bound to the connection.
314 * If any JID was previously set, it will be discarded. This should not be
2b8691f @metajack Documentation changes for SASL ANONYMOUS.
metajack authored
315 * be used after a connection is created. The function will make a copy of
316 * the JID string. If the supllied JID is missing the node, SASL
317 * ANONYMOUS authentication will be used.
65a174e @metajack Most public API points are now documented.
metajack authored
318 *
319 * @param conn a Strophe connection object
320 * @param jid a full or bare JID
321 *
322 * @ingroup Connections
f27235b @rillian Move the xmpp library to its new name.
rillian authored
323 */
324 void xmpp_conn_set_jid(xmpp_conn_t * const conn, const char * const jid)
325 {
326 if (conn->jid) xmpp_free(conn->ctx, conn->jid);
327 conn->jid = xmpp_strdup(conn->ctx, jid);
328 }
329
65a174e @metajack Most public API points are now documented.
metajack authored
330 /** Get the password used for authentication of a connection.
331 *
332 * @param conn a Strophe connection object
333 *
334 * @return a string containing the password or NULL if it has not been set
335 *
336 * @ingroup Connections
337 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
338 const char *xmpp_conn_get_pass(const xmpp_conn_t * const conn)
339 {
340 return conn->pass;
341 }
342
65a174e @metajack Most public API points are now documented.
metajack authored
343 /** Set the password used to authenticate the connection.
344 * If any password was previously set, it will be discarded. The function
345 * will make a copy of the password string.
346 *
347 * @param conn a Strophe connection object
348 * @param pass the password
349 *
350 * @ingroup Connections
351 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
352 void xmpp_conn_set_pass(xmpp_conn_t * const conn, const char * const pass)
353 {
354 if (conn->pass) xmpp_free(conn->ctx, conn->pass);
355 conn->pass = xmpp_strdup(conn->ctx, pass);
356 }
357
757d5ba @mwild1 + Add xmpp_conn_get_context() to get the ctx a connection belongs to. Fi...
mwild1 authored
358 /** Get the strophe context that the connection is associated with.
359 * @param conn a Strophe connection object
360 *
361 * @return a Strophe context
362 *
363 * @ingroup Connections
364 */
365 xmpp_ctx_t* xmpp_conn_get_context(xmpp_conn_t * const conn)
366 {
367 return conn->ctx;
368 }
369
332744b @catap Add lazy registration support
authored
370 /** Get the lazy registration flag.
371 *
372 * @param conn a Strophe connection object
373 *
374 * @return not NULL if flag set or NULL if it has not been set
375 *
376 * @ingroup Connections
377 */
378 const int xmpp_conn_get_lazy_registration(const xmpp_conn_t * const conn)
379 {
380 return conn->lazy_registration;
381 }
382
383 /** Set the lazy registration flag.
384 * If authentication failed try register selected jid/password
385 *
386 * @param conn a Strophe connection object
387 * @param value a not NULL for enabled or NULL for dissable
388 *
389 * @ingroup Connections
390 */
391 void xmpp_conn_set_lazy_registration(xmpp_conn_t * const conn, int value)
392 {
393 conn->lazy_registration = value;
394 }
395
65a174e @metajack Most public API points are now documented.
metajack authored
396 /** Initiate a connection to the XMPP server.
397 * This function returns immediately after starting the connection
398 * process to the XMPP server, and notifiations of connection state changes
399 * will be sent to the callback function. The domain and port to connect to
400 * are usually determined by an SRV lookup for the xmpp-client service at
401 * the domain specified in the JID. If SRV lookup fails, altdomain and
402 * altport will be used instead if specified.
403 *
404 * @param conn a Strophe connection object
3b47afa @metajack Fix warnings and line endings from previous SRV commit. Get rid of doma...
metajack authored
405 * @param altdomain a string with domain to use if SRV lookup fails. If this
406 * is NULL, the domain from the JID will be used.
407 * @param altport an integer port number to use if SRV lookup fails. If this
408 * is 0, the default port (5222) will be assumed.
65a174e @metajack Most public API points are now documented.
metajack authored
409 * @param callback a xmpp_conn_handler callback function that will receive
410 * notifications of connection status
411 * @param userdata an opaque data pointer that will be passed to the callback
412 *
413 * @return 0 on success and -1 on an error
414 *
415 * @ingroup Connections
416 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
417 int xmpp_connect_client(xmpp_conn_t * const conn,
6f9be5e Add alternate domain and port to xmpp_client_connect() for when SRV look...
James Canete authored
418 const char * const altdomain,
419 unsigned short altport,
f27235b @rillian Move the xmpp library to its new name.
rillian authored
420 xmpp_conn_handler callback,
421 void * const userdata)
422 {
f45380b Added OpenSSL support.
James Canete authored
423 char connectdomain[2048];
424 int connectport;
3fd7515 @metajack Abstracted XML parser library and switched to autotools building.
metajack authored
425 const char * domain;
f45380b Added OpenSSL support.
James Canete authored
426
f27235b @rillian Move the xmpp library to its new name.
rillian authored
427 conn->type = XMPP_CLIENT;
428
3b47afa @metajack Fix warnings and line endings from previous SRV commit. Get rid of doma...
metajack authored
429 conn->domain = xmpp_jid_domain(conn->ctx, conn->jid);
f27235b @rillian Move the xmpp library to its new name.
rillian authored
430 if (!conn->domain) return -1;
431
e852bfb @dustin If an altdomain was specified, use it instead of SRV lookups.
dustin authored
432 if (altdomain) {
433 xmpp_debug(conn->ctx, "xmpp", "Connecting via altdomain.");
434 strcpy(connectdomain, altdomain);
435 connectport = altport ? altport : 5222;
436 } else if (!sock_srv_lookup("xmpp-client", "tcp", conn->domain,
437 connectdomain, 2048, &connectport)) {
561fac8 Add linux/unix version of SRV lookup.
James Canete authored
438 xmpp_debug(conn->ctx, "xmpp", "SRV lookup failed.");
757d5ba @mwild1 + Add xmpp_conn_get_context() to get the ctx a connection belongs to. Fi...
mwild1 authored
439 if (!altdomain)
440 domain = conn->domain;
441 else
442 domain = altdomain;
e852bfb @dustin If an altdomain was specified, use it instead of SRV lookups.
dustin authored
443 xmpp_debug(conn->ctx, "xmpp", "Using alternate domain %s, port %d",
444 altdomain, altport);
3b47afa @metajack Fix warnings and line endings from previous SRV commit. Get rid of doma...
metajack authored
445 strcpy(connectdomain, domain);
446 connectport = altport ? altport : 5222;
6f9be5e Add alternate domain and port to xmpp_client_connect() for when SRV look...
James Canete authored
447 }
f45380b Added OpenSSL support.
James Canete authored
448 conn->sock = sock_connect(connectdomain, connectport);
690c0c1 @dustin Log the result of a connect.
dustin authored
449 xmpp_debug(conn->ctx, "xmpp", "sock_connect to %s:%d returned %d",
450 connectdomain, connectport, conn->sock);
6f9be5e Add alternate domain and port to xmpp_client_connect() for when SRV look...
James Canete authored
451 if (conn->sock == -1) return -1;
f27235b @rillian Move the xmpp library to its new name.
rillian authored
452
453 /* setup handler */
454 conn->conn_handler = callback;
455 conn->userdata = userdata;
456
457 /* FIXME: it could happen that the connect returns immediately as
458 * successful, though this is pretty unlikely. This would be a little
459 * hard to fix, since we'd have to detect and fire off the callback
460 * from within the event loop */
461
462 conn->state = XMPP_STATE_CONNECTING;
68c9a71 @metajack Partial fix for #11. Correctly calls connection handler on timeout now,
metajack authored
463 conn->timeout_stamp = time_stamp();
f45380b Added OpenSSL support.
James Canete authored
464 xmpp_debug(conn->ctx, "xmpp", "attempting to connect to %s", connectdomain);
f27235b @rillian Move the xmpp library to its new name.
rillian authored
465
466 return 0;
467 }
468
65a174e @metajack Most public API points are now documented.
metajack authored
469 /** Cleanly disconnect the connection.
470 * This function is only called by the stream parser when </stream:stream>
471 * is received, and it not intended to be called by code outside of Strophe.
472 *
473 * @param conn a Strophe connection object
474 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
475 void conn_disconnect_clean(xmpp_conn_t * const conn)
476 {
477 /* remove the timed handler */
478 xmpp_timed_handler_delete(conn, _disconnect_cleanup);
479
480 conn_disconnect(conn);
481 }
482
65a174e @metajack Most public API points are now documented.
metajack authored
483 /** Disconnect from the XMPP server.
484 * This function immediately disconnects from the XMPP server, and should
485 * not be used outside of the Strophe library.
486 *
487 * @param conn a Strophe connection object
488 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
489 void conn_disconnect(xmpp_conn_t * const conn)
490 {
68c9a71 @metajack Partial fix for #11. Correctly calls connection handler on timeout now,
metajack authored
491 xmpp_debug(conn->ctx, "xmpp", "Closing socket.");
f27235b @rillian Move the xmpp library to its new name.
rillian authored
492 conn->state = XMPP_STATE_DISCONNECTED;
f45380b Added OpenSSL support.
James Canete authored
493 if (conn->tls) {
494 tls_stop(conn->tls);
495 tls_free(conn->tls);
496 conn->tls = NULL;
497 }
f27235b @rillian Move the xmpp library to its new name.
rillian authored
498 sock_close(conn->sock);
499
500 /* fire off connection handler */
501 conn->conn_handler(conn, XMPP_CONN_DISCONNECT, conn->error,
502 conn->stream_error, conn->userdata);
503 }
504
3fd7515 @metajack Abstracted XML parser library and switched to autotools building.
metajack authored
505 /* prepares a parser reset. this is called from handlers. we can't
506 * reset the parser immediately as it is not re-entrant. */
507 void conn_prepare_reset(xmpp_conn_t * const conn, xmpp_open_handler handler)
508 {
509 conn->reset_parser = 1;
510 conn->open_handler = handler;
511 }
512
513 /* reset the parser */
514 void conn_parser_reset(xmpp_conn_t * const conn)
515 {
516 conn->reset_parser = 0;
517 parser_reset(conn->parser);
518 }
519
f27235b @rillian Move the xmpp library to its new name.
rillian authored
520 /* timed handler for cleanup if normal disconnect procedure takes too long */
521 static int _disconnect_cleanup(xmpp_conn_t * const conn,
522 void * const userdata)
523 {
524 xmpp_debug(conn->ctx, "xmpp",
525 "disconnection forced by cleanup timeout");
526
527 conn_disconnect(conn);
528
529 return 0;
530 }
531
65a174e @metajack Most public API points are now documented.
metajack authored
532 /** Initiate termination of the connection to the XMPP server.
533 * This function starts the disconnection sequence by sending
534 * </stream:stream> to the XMPP server. This function will do nothing
535 * if the connection state is CONNECTING or CONNECTED.
536 *
537 * @param conn a Strophe connection object
538 *
539 * @ingroup Connections
540 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
541 void xmpp_disconnect(xmpp_conn_t * const conn)
542 {
543 if (conn->state != XMPP_STATE_CONNECTING &&
544 conn->state != XMPP_STATE_CONNECTED)
545 return;
546
547 /* close the stream */
548 xmpp_send_raw_string(conn, "</stream:stream>");
549
550 /* setup timed handler in case disconnect takes too long */
551 handler_add_timed(conn, _disconnect_cleanup,
552 DISCONNECT_TIMEOUT, NULL);
553 }
554
65a174e @metajack Most public API points are now documented.
metajack authored
555 /** Send a raw string to the XMPP server.
556 * This function is a convenience function to send raw string data to the
557 * XMPP server. It is used by Strophe to send short messages instead of
558 * building up an XML stanza with DOM methods. This should be used with care
559 * as it does not validate the data; invalid data may result in immediate
560 * stream termination by the XMPP server.
561 *
562 * @param conn a Strophe connection object
563 * @param fmt a printf-style format string followed by a variable list of
564 * arguments to format
565 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
566 void xmpp_send_raw_string(xmpp_conn_t * const conn,
567 const char * const fmt, ...)
568 {
569 va_list ap;
570 size_t len;
571 char buf[1024]; /* small buffer for common case */
572 char *bigbuf;
573
574 va_start(ap, fmt);
c52d0aa @metajack Add new snprintf/vsnprintf implementation. This should fix the compabil...
metajack authored
575 len = xmpp_vsnprintf(buf, 1024, fmt, ap);
f27235b @rillian Move the xmpp library to its new name.
rillian authored
576 va_end(ap);
577
578 if (len >= 1024) {
579 /* we need more space for this data, so we allocate a big
580 * enough buffer and print to that */
581 len++; /* account for trailing \0 */
582 bigbuf = xmpp_alloc(conn->ctx, len);
583 if (!bigbuf) {
584 xmpp_debug(conn->ctx, "xmpp", "Could not allocate memory for send_raw_string");
585 return;
586 }
587 va_start(ap, fmt);
c52d0aa @metajack Add new snprintf/vsnprintf implementation. This should fix the compabil...
metajack authored
588 xmpp_vsnprintf(bigbuf, len, fmt, ap);
f27235b @rillian Move the xmpp library to its new name.
rillian authored
589 va_end(ap);
590
591 xmpp_debug(conn->ctx, "conn", "SENT: %s", bigbuf);
592
593 /* len - 1 so we don't send trailing \0 */
594 xmpp_send_raw(conn, bigbuf, len - 1);
595
596 xmpp_free(conn->ctx, bigbuf);
597 } else {
598 xmpp_debug(conn->ctx, "conn", "SENT: %s", buf);
599
600 xmpp_send_raw(conn, buf, len);
601 }
602 }
603
65a174e @metajack Most public API points are now documented.
metajack authored
604 /** Send raw bytes to the XMPP server.
605 * This function is a convenience function to send raw bytes to the
606 * XMPP server. It is usedly primarly by xmpp_send_raw_string. This
607 * function should be used with care as it does not validate the bytes and
608 * invalid data may result in stream termination by the XMPP server.
609 *
610 * @param conn a Strophe connection object
611 * @param data a buffer of raw bytes
612 * @param len the length of the data in the buffer
613 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
614 void xmpp_send_raw(xmpp_conn_t * const conn,
615 const char * const data, const size_t len)
616 {
617 xmpp_send_queue_t *item;
618
619 if (conn->state != XMPP_STATE_CONNECTED) return;
620
621 /* create send queue item for queue */
622 item = xmpp_alloc(conn->ctx, sizeof(xmpp_send_queue_t));
623 if (!item) return;
624
625 item->data = xmpp_alloc(conn->ctx, len);
626 if (!item->data) {
627 xmpp_free(conn->ctx, item);
628 return;
629 }
630 memcpy(item->data, data, len);
631 item->len = len;
632 item->next = NULL;
633 item->written = 0;
634
635 /* add item to the send queue */
636 if (!conn->send_queue_tail) {
637 /* first item, set head and tail */
638 conn->send_queue_head = item;
639 conn->send_queue_tail = item;
640 } else {
641 /* add to the tail */
642 conn->send_queue_tail->next = item;
643 conn->send_queue_tail = item;
644 }
645 conn->send_queue_len++;
646 }
647
65a174e @metajack Most public API points are now documented.
metajack authored
648 /** Send an XML stanza to the XMPP server.
649 * This is the main way to send data to the XMPP server. The function will
650 * terminate without action if the connection state is not CONNECTED.
651 *
652 * @param conn a Strophe connection object
653 * @param stanza a Strophe stanza object
654 *
655 * @ingroup Connections
656 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
657 void xmpp_send(xmpp_conn_t * const conn,
658 xmpp_stanza_t * const stanza)
659 {
660 char *buf;
661 size_t len;
662 int ret;
663
664 if (conn->state == XMPP_STATE_CONNECTED) {
665 if ((ret = xmpp_stanza_to_text(stanza, &buf, &len)) == 0) {
666 xmpp_send_raw(conn, buf, len);
c52d0aa @metajack Add new snprintf/vsnprintf implementation. This should fix the compabil...
metajack authored
667 xmpp_debug(conn->ctx, "conn", "SENT: %s", buf);
f27235b @rillian Move the xmpp library to its new name.
rillian authored
668 xmpp_free(conn->ctx, buf);
669 }
670 }
671 }
672
65a174e @metajack Most public API points are now documented.
metajack authored
673 /** Send the opening &lt;stream:stream&gt; tag to the server.
674 * This function is used by Strophe to begin an XMPP stream. It should
675 * not be used outside of the library.
676 *
677 * @param conn a Strophe connection object
678 */
f27235b @rillian Move the xmpp library to its new name.
rillian authored
679 void conn_open_stream(xmpp_conn_t * const conn)
680 {
681 xmpp_send_raw_string(conn,
682 "<?xml version=\"1.0\"?>" \
683 "<stream:stream to=\"%s\" " \
684 "xml:lang=\"%s\" " \
685 "version=\"1.0\" " \
686 "xmlns=\"%s\" " \
687 "xmlns:stream=\"%s\">",
688 conn->domain,
689 conn->lang,
690 conn->type == XMPP_CLIENT ? XMPP_NS_CLIENT : XMPP_NS_COMPONENT,
691 XMPP_NS_STREAMS);
692 }
3fd7515 @metajack Abstracted XML parser library and switched to autotools building.
metajack authored
693
694 static void _log_open_tag(xmpp_conn_t *conn, char **attrs)
695 {
696 char buf[4096];
697 size_t len, pos;
698 int i;
699
700 if (!attrs) return;
701
702 pos = 0;
703 len = xmpp_snprintf(buf, 4096, "<stream:stream");
704 if (len < 0) return;
705
706 pos += len;
707
708 for (i = 0; attrs[i]; i += 2) {
709 len = xmpp_snprintf(&buf[pos], 4096 - pos, " %s='%s'",
710 attrs[i], attrs[i+1]);
711 if (len < 0) return;
712 pos += len;
713 }
714
715 len = xmpp_snprintf(&buf[pos], 4096 - pos, ">");
716 if (len < 0) return;
717
718 xmpp_debug(conn->ctx, "xmpp", "RECV: %s", buf);
719 }
720
721 static char *_get_stream_attribute(char **attrs, char *name)
722 {
723 int i;
724
725 if (!attrs) return NULL;
726
727 for (i = 0; attrs[i]; i += 2)
728 if (strcmp(name, attrs[i]) == 0)
729 return attrs[i+1];
730
731 return NULL;
732 }
733
734 static void _handle_stream_start(char *name, char **attrs,
735 void * const userdata)
736 {
737 xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
738 char *id;
739
740 if (strcmp(name, "stream:stream") != 0) {
741 printf("name = %s\n", name);
742 xmpp_error(conn->ctx, "conn", "Server did not open valid stream.");
743 conn_disconnect(conn);
744 } else {
745 _log_open_tag(conn, attrs);
746
747 if (conn->stream_id) xmpp_free(conn->ctx, conn->stream_id);
748
749 id = _get_stream_attribute(attrs, "id");
750 if (id)
751 conn->stream_id = xmpp_strdup(conn->ctx, id);
752
753 if (!conn->stream_id) {
754 xmpp_error(conn->ctx, "conn", "Memory allocation failed.");
755 conn_disconnect(conn);
756 }
757 }
758
759 /* call stream open handler */
760 conn->open_handler(conn);
761 }
762
763 static void _handle_stream_end(char *name,
764 void * const userdata)
765 {
766 xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
767
768 /* stream is over */
769 xmpp_debug(conn->ctx, "xmpp", "RECV: </stream:stream>");
770 conn_disconnect_clean(conn);
771 }
772
773 static void _handle_stream_stanza(xmpp_stanza_t *stanza,
774 void * const userdata)
775 {
776 xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
777 char *buf;
778 size_t len;
779
780 if (xmpp_stanza_to_text(stanza, &buf, &len) == 0) {
781 xmpp_debug(conn->ctx, "xmpp", "RECV: %s", buf);
782 xmpp_free(conn->ctx, buf);
783 }
784
785 handler_fire_stanza(conn, stanza);
786 }
Something went wrong with that request. Please try again.