stropheruby 0.1.5 → 0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt CHANGED
@@ -1,3 +1,6 @@
1
+ == 0.2 2010-02-26
2
+ * update the libstrophe src to 20090526
3
+
1
4
  == 0.1.4 2010-02-26
2
5
 
3
6
  * accessor of the connect_timeout in Connection class
data/README.txt CHANGED
@@ -4,6 +4,7 @@ Stropheruby is a ruby bindings for Strophe, a C library for writing XMPP clients
4
4
 
5
5
  This is a fork of flamontagne's stropheruby (http://github.com/flamontagne/stropheruby/tree/master) with the following improvements:
6
6
 
7
+ * accessor of the connect_timeout in the Connection class
7
8
  * A patched version of libstrophe (trunk) is included. So there is no extra library to install.
8
9
  * (libstrophe) Fixed a timeout issue on Mac OSX: http://groups.google.com/group/strophe-dev/browse_thread/thread/ef4cb19785020fb6
9
10
  * (libstrophe) Fixed basic auth: http://groups.google.com/group/strophe-dev/browse_thread/thread/b770f72c83d1a0b9
@@ -17,11 +18,15 @@ This is a fork of flamontagne's stropheruby (http://github.com/flamontagne/strop
17
18
 
18
19
  == INSTALLATION
19
20
 
20
- sudo gem sources -a http://gems.github.com
21
- sudo gem install yong-stropheruby
21
+ sudo gem sources -a http://gemcutter.org
22
+ sudo gem install stropheruby
22
23
 
23
24
  For Rails app, add this line in your config/environment.rb:
24
- config.gem "yong-stropheruby", :source => "http://gems.github.com", :lib => "strophe_ruby"
25
+ config.gem "stropheruby", :source => "http://gemcutter.org", :lib => "strophe_ruby"
26
+
27
+ == NOTES
28
+
29
+ Stropheruby v2.0 has upgraded the libstrophe to the upstream which is 20090526
25
30
 
26
31
  == EXAMPLE
27
32
 
data/ext/auth.c CHANGED
@@ -1,7 +1,7 @@
1
1
  /* auth.c
2
2
  ** strophe XMPP client library -- auth functions and handlers
3
3
  **
4
- ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
4
+ ** Copyright (C) 2005-2009 Collecta, Inc.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express or
7
7
  ** implied.
@@ -208,9 +208,11 @@ static int _handle_features(xmpp_conn_t * const conn,
208
208
  xmpp_timed_handler_delete(conn, _handle_missing_features);
209
209
 
210
210
  /* check for TLS */
211
- child = xmpp_stanza_get_child_by_name(stanza, "starttls");
212
- if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_TLS) == 0))
213
- conn->tls_support = 1;
211
+ if (!conn->secured) {
212
+ child = xmpp_stanza_get_child_by_name(stanza, "starttls");
213
+ if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_TLS) == 0))
214
+ conn->tls_support = 1;
215
+ }
214
216
 
215
217
  /* check for SASL */
216
218
  child = xmpp_stanza_get_child_by_name(stanza, "mechanisms");
@@ -234,13 +236,13 @@ static int _handle_features(xmpp_conn_t * const conn,
234
236
  if (conn->pass == NULL || conn->pass[0] == '\0') {
235
237
  xmpp_debug(conn->ctx, "auth", "do not attempt auth as there is no password given");
236
238
  //If no password, do not login, this will give 'register' a chance to run
237
- conn->authenticated = 1;
238
- /* call connection handler */
239
- conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
239
+ conn->authenticated = 1;
240
+ /* call connection handler */
241
+ conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
240
242
  } else {
241
243
  _auth(conn);
242
244
  }
243
-
245
+
244
246
  return 0;
245
247
  }
246
248
 
@@ -265,7 +267,7 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn,
265
267
  {
266
268
  char *name;
267
269
  name = xmpp_stanza_get_name(stanza);
268
- xmpp_debug(conn->ctx, "xmpp",
270
+ xmpp_debug(conn->ctx, "xmpp",
269
271
  "handle proceedtls called for %s", name);
270
272
 
271
273
  if (strcmp(name, "proceed") == 0) {
@@ -285,7 +287,8 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn,
285
287
  }
286
288
  else
287
289
  {
288
- parser_prepare_reset(conn, _handle_open_tls);
290
+ conn->secured = 1;
291
+ conn_prepare_reset(conn, auth_handle_open);
289
292
 
290
293
  conn_open_stream(conn);
291
294
  }
@@ -315,7 +318,7 @@ static int _handle_sasl_result(xmpp_conn_t * const conn,
315
318
  (char *)userdata);
316
319
 
317
320
  /* reset parser */
318
- parser_prepare_reset(conn, _handle_open_sasl);
321
+ conn_prepare_reset(conn, _handle_open_sasl);
319
322
 
320
323
  /* send stream tag */
321
324
  conn_open_stream(conn);
@@ -700,16 +703,6 @@ void auth_handle_open(xmpp_conn_t * const conn)
700
703
  FEATURES_TIMEOUT, NULL);
701
704
  }
702
705
 
703
- /* called when stream:stream tag received after TLS connection */
704
- static void _handle_open_tls(xmpp_conn_t * const conn)
705
- {
706
- xmpp_debug(conn->ctx, "xmpp", "TLS successful, proceeding with SASL");
707
-
708
- /* go straight to SASL auth */
709
- _auth(conn);
710
- }
711
-
712
-
713
706
  /* called when stream:stream tag received after SASL auth */
714
707
  static void _handle_open_sasl(xmpp_conn_t * const conn)
715
708
  {
@@ -848,9 +841,17 @@ static int _handle_bind(xmpp_conn_t * const conn,
848
841
  xmpp_error(conn->ctx, "xmpp", "Binding failed.");
849
842
  xmpp_disconnect(conn);
850
843
  } else if (type && strcmp(type, "result") == 0) {
851
- /* TODO: extract resource if present */
844
+ xmpp_stanza_t *binding = xmpp_stanza_get_child_by_name(stanza, "bind");
852
845
  xmpp_debug(conn->ctx, "xmpp", "Bind successful.");
853
846
 
847
+ if (binding) {
848
+ xmpp_stanza_t *jid_stanza = xmpp_stanza_get_child_by_name(binding,
849
+ "jid");
850
+ if (jid_stanza) {
851
+ conn->bound_jid = xmpp_stanza_get_text(jid_stanza);
852
+ }
853
+ }
854
+
854
855
  /* establish a session if required */
855
856
  if (conn->session_required) {
856
857
  /* setup response handlers */
data/ext/common.h CHANGED
@@ -1,7 +1,7 @@
1
1
  /* common.h
2
2
  ** strophe XMPP client library -- internal common structures
3
3
  **
4
- ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
4
+ ** Copyright (C) 2005-2009 Collecta, Inc.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express or
7
7
  ** implied.
@@ -31,8 +31,7 @@
31
31
  #include "tls.h"
32
32
  #include "hash.h"
33
33
  #include "util.h"
34
-
35
- #include "expat.h"
34
+ #include "parser.h"
36
35
 
37
36
  /** run-time context **/
38
37
 
@@ -163,10 +162,11 @@ struct _xmpp_conn_t {
163
162
  sock_t sock;
164
163
  tls_t *tls;
165
164
 
166
- int tls_support;
165
+ int tls_support;
167
166
  int tls_failed; /* set when tls fails, so we don't try again */
168
167
  int sasl_support; /* if true, field is a bitfield of supported
169
168
  mechanisms */
169
+ int secured; /* set when stream is secured with TLS */
170
170
 
171
171
  /* if server returns <bind/> or <session/> we must do them */
172
172
  int bind_required;
@@ -178,6 +178,7 @@ struct _xmpp_conn_t {
178
178
  char *connectport;
179
179
  char *jid;
180
180
  char *pass;
181
+ char *bound_jid;
181
182
  char *stream_id;
182
183
 
183
184
  /* send queue and parameters */
@@ -189,9 +190,7 @@ struct _xmpp_conn_t {
189
190
 
190
191
  /* xml parser */
191
192
  int reset_parser;
192
- XML_Parser parser;
193
- int depth;
194
- xmpp_stanza_t *stanza;
193
+ parser_t *parser;
195
194
 
196
195
  /* timeouts */
197
196
  unsigned int connect_timeout;
@@ -217,6 +216,8 @@ struct _xmpp_conn_t {
217
216
  void conn_disconnect(xmpp_conn_t * const conn);
218
217
  void conn_disconnect_clean(xmpp_conn_t * const conn);
219
218
  void conn_open_stream(xmpp_conn_t * const conn);
219
+ void conn_prepare_reset(xmpp_conn_t * const conn, xmpp_open_handler handler);
220
+ void conn_parser_reset(xmpp_conn_t * const conn);
220
221
 
221
222
 
222
223
  typedef enum {
@@ -241,19 +242,6 @@ struct _xmpp_stanza_t {
241
242
  hash_t *attributes;
242
243
  };
243
244
 
244
- int xmpp_stanza_set_attributes(xmpp_stanza_t * const stanza,
245
- const char * const * const attr);
246
-
247
- /* parser functions */
248
- void parser_handle_start(void *userdata,
249
- const XML_Char *name,
250
- const XML_Char **attr);
251
- void parser_handle_character(void *userdata, const XML_Char *s, int len);
252
- void parser_handle_end(void *userdata, const XML_Char *name);
253
- void parser_prepare_reset(xmpp_conn_t * const conn,
254
- xmpp_open_handler handler);
255
- int parser_reset(xmpp_conn_t * const conn);
256
-
257
245
  /* handler management */
258
246
  void handler_fire_stanza(xmpp_conn_t * const conn,
259
247
  xmpp_stanza_t * const stanza);
data/ext/conn.c CHANGED
@@ -1,7 +1,7 @@
1
1
  /* conn.c
2
2
  ** strophe XMPP client library -- connection object functions
3
3
  **
4
- ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
4
+ ** Copyright (C) 2005-2009 Collecta, Inc.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express
7
7
  ** or implied.
@@ -23,9 +23,11 @@
23
23
  #include <stdlib.h>
24
24
  #include <string.h>
25
25
 
26
- #include "strophe.h"
26
+ #include <strophe.h>
27
+
27
28
  #include "common.h"
28
29
  #include "util.h"
30
+ #include "parser.h"
29
31
 
30
32
  #ifndef DEFAULT_SEND_QUEUE_MAX
31
33
  /** @def DEFAULT_SEND_QUEUE_MAX
@@ -51,6 +53,13 @@
51
53
  static int _disconnect_cleanup(xmpp_conn_t * const conn,
52
54
  void * const userdata);
53
55
 
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
+
54
63
  /** Create a new Strophe connection object.
55
64
  *
56
65
  * @param ctx a Strophe context object
@@ -96,17 +105,23 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx)
96
105
  conn->jid = NULL;
97
106
  conn->pass = NULL;
98
107
  conn->stream_id = NULL;
108
+ conn->bound_jid = NULL;
99
109
 
100
110
  conn->tls_support = 0;
101
111
  conn->tls_failed = 0;
102
112
  conn->sasl_support = 0;
113
+ conn->secured = 0;
103
114
 
104
115
  conn->bind_required = 0;
105
116
  conn->session_required = 0;
106
117
 
107
- conn->parser = NULL;
108
- conn->stanza = NULL;
109
- parser_prepare_reset(conn, auth_handle_open);
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);
110
125
 
111
126
  conn->authenticated = 0;
112
127
  conn->conn_handler = NULL;
@@ -127,7 +142,7 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx)
127
142
  if (!item) {
128
143
  xmpp_error(conn->ctx, "xmpp", "failed to allocate memory");
129
144
  xmpp_free(conn->ctx, conn->lang);
130
- XML_ParserFree(conn->parser);
145
+ parser_free(conn->parser);
131
146
  xmpp_free(conn->ctx, conn);
132
147
  conn = NULL;
133
148
  } else {
@@ -151,7 +166,7 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx)
151
166
  *
152
167
  * @ingroup Connections
153
168
  */
154
- xmpp_conn_t * xmpp_conn_clone(xmpp_conn_t * const conn)
169
+ xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t * const conn)
155
170
  {
156
171
  conn->ref++;
157
172
  return conn;
@@ -249,12 +264,14 @@ int xmpp_conn_release(xmpp_conn_t * const conn)
249
264
  xmpp_free(ctx, conn->stream_error);
250
265
  }
251
266
 
252
- XML_ParserFree(conn->parser);
267
+ parser_free(conn->parser);
253
268
 
254
269
  if (conn->domain) xmpp_free(ctx, conn->domain);
255
270
  if (conn->jid) xmpp_free(ctx, conn->jid);
271
+ if (conn->bound_jid) xmpp_free(ctx, conn->bound_jid);
256
272
  if (conn->pass) xmpp_free(ctx, conn->pass);
257
273
  if (conn->stream_id) xmpp_free(ctx, conn->stream_id);
274
+ if (conn->lang) xmpp_free(ctx, conn->lang);
258
275
  xmpp_free(ctx, conn);
259
276
  released = 1;
260
277
  }
@@ -275,6 +292,24 @@ const char *xmpp_conn_get_jid(const xmpp_conn_t * const conn)
275
292
  return conn->jid;
276
293
  }
277
294
 
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
+
278
313
  /** Set the JID of the user that will be bound to the connection.
279
314
  * If any JID was previously set, it will be discarded. This should not be
280
315
  * be used after a connection is created. The function will make a copy of
@@ -379,25 +414,32 @@ int xmpp_connect_client(xmpp_conn_t * const conn,
379
414
  {
380
415
  char connectdomain[2048];
381
416
  int connectport;
382
- char *domain;
417
+ const char * domain;
383
418
 
384
419
  conn->type = XMPP_CLIENT;
385
420
 
386
421
  conn->domain = xmpp_jid_domain(conn->ctx, conn->jid);
387
422
  if (!conn->domain) return -1;
388
423
 
389
- if (!sock_srv_lookup("xmpp-client", "tcp", conn->domain, connectdomain, 2048, &connectport))
390
- {
424
+ if (altdomain) {
425
+ xmpp_debug(conn->ctx, "xmpp", "Connecting via altdomain.");
426
+ strcpy(connectdomain, altdomain);
427
+ connectport = altport ? altport : 5222;
428
+ } else if (!sock_srv_lookup("xmpp-client", "tcp", conn->domain,
429
+ connectdomain, 2048, &connectport)) {
391
430
  xmpp_debug(conn->ctx, "xmpp", "SRV lookup failed.");
392
431
  if (!altdomain)
393
432
  domain = conn->domain;
394
433
  else
395
434
  domain = altdomain;
396
- xmpp_debug(conn->ctx, "xmpp", "Using alternate domain %s, port %d", altdomain, altport);
435
+ xmpp_debug(conn->ctx, "xmpp", "Using alternate domain %s, port %d",
436
+ altdomain, altport);
397
437
  strcpy(connectdomain, domain);
398
438
  connectport = altport ? altport : 5222;
399
439
  }
400
440
  conn->sock = sock_connect(connectdomain, connectport);
441
+ xmpp_debug(conn->ctx, "xmpp", "sock_connect to %s:%d returned %d",
442
+ connectdomain, connectport, conn->sock);
401
443
  if (conn->sock == -1) return -1;
402
444
 
403
445
  /* setup handler */
@@ -426,7 +468,7 @@ void conn_disconnect_clean(xmpp_conn_t * const conn)
426
468
  {
427
469
  /* remove the timed handler */
428
470
  xmpp_timed_handler_delete(conn, _disconnect_cleanup);
429
- conn->error = -4;
471
+
430
472
  conn_disconnect(conn);
431
473
  }
432
474
 
@@ -445,13 +487,26 @@ void conn_disconnect(xmpp_conn_t * const conn)
445
487
  tls_free(conn->tls);
446
488
  conn->tls = NULL;
447
489
  }
448
-
449
490
  sock_close(conn->sock);
491
+
450
492
  /* fire off connection handler */
451
- if (NULL != conn->conn_handler) {
452
- conn->conn_handler(conn, XMPP_CONN_DISCONNECT, conn->error,
493
+ conn->conn_handler(conn, XMPP_CONN_DISCONNECT, conn->error,
453
494
  conn->stream_error, conn->userdata);
454
- }
495
+ }
496
+
497
+ /* prepares a parser reset. this is called from handlers. we can't
498
+ * reset the parser immediately as it is not re-entrant. */
499
+ void conn_prepare_reset(xmpp_conn_t * const conn, xmpp_open_handler handler)
500
+ {
501
+ conn->reset_parser = 1;
502
+ conn->open_handler = handler;
503
+ }
504
+
505
+ /* reset the parser */
506
+ void conn_parser_reset(xmpp_conn_t * const conn)
507
+ {
508
+ conn->reset_parser = 0;
509
+ parser_reset(conn->parser);
455
510
  }
456
511
 
457
512
  /* timed handler for cleanup if normal disconnect procedure takes too long */
@@ -460,7 +515,7 @@ static int _disconnect_cleanup(xmpp_conn_t * const conn,
460
515
  {
461
516
  xmpp_debug(conn->ctx, "xmpp",
462
517
  "disconnection forced by cleanup timeout");
463
- conn->error = -5;
518
+
464
519
  conn_disconnect(conn);
465
520
 
466
521
  return 0;
@@ -627,3 +682,97 @@ void conn_open_stream(xmpp_conn_t * const conn)
627
682
  conn->type == XMPP_CLIENT ? XMPP_NS_CLIENT : XMPP_NS_COMPONENT,
628
683
  XMPP_NS_STREAMS);
629
684
  }
685
+
686
+ static void _log_open_tag(xmpp_conn_t *conn, char **attrs)
687
+ {
688
+ char buf[4096];
689
+ size_t len, pos;
690
+ int i;
691
+
692
+ if (!attrs) return;
693
+
694
+ pos = 0;
695
+ len = xmpp_snprintf(buf, 4096, "<stream:stream");
696
+ if (len < 0) return;
697
+
698
+ pos += len;
699
+
700
+ for (i = 0; attrs[i]; i += 2) {
701
+ len = xmpp_snprintf(&buf[pos], 4096 - pos, " %s='%s'",
702
+ attrs[i], attrs[i+1]);
703
+ if (len < 0) return;
704
+ pos += len;
705
+ }
706
+
707
+ len = xmpp_snprintf(&buf[pos], 4096 - pos, ">");
708
+ if (len < 0) return;
709
+
710
+ xmpp_debug(conn->ctx, "xmpp", "RECV: %s", buf);
711
+ }
712
+
713
+ static char *_get_stream_attribute(char **attrs, char *name)
714
+ {
715
+ int i;
716
+
717
+ if (!attrs) return NULL;
718
+
719
+ for (i = 0; attrs[i]; i += 2)
720
+ if (strcmp(name, attrs[i]) == 0)
721
+ return attrs[i+1];
722
+
723
+ return NULL;
724
+ }
725
+
726
+ static void _handle_stream_start(char *name, char **attrs,
727
+ void * const userdata)
728
+ {
729
+ xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
730
+ char *id;
731
+
732
+ if (strcmp(name, "stream:stream") != 0) {
733
+ printf("name = %s\n", name);
734
+ xmpp_error(conn->ctx, "conn", "Server did not open valid stream.");
735
+ conn_disconnect(conn);
736
+ } else {
737
+ _log_open_tag(conn, attrs);
738
+
739
+ if (conn->stream_id) xmpp_free(conn->ctx, conn->stream_id);
740
+
741
+ id = _get_stream_attribute(attrs, "id");
742
+ if (id)
743
+ conn->stream_id = xmpp_strdup(conn->ctx, id);
744
+
745
+ if (!conn->stream_id) {
746
+ xmpp_error(conn->ctx, "conn", "Memory allocation failed.");
747
+ conn_disconnect(conn);
748
+ }
749
+ }
750
+
751
+ /* call stream open handler */
752
+ conn->open_handler(conn);
753
+ }
754
+
755
+ static void _handle_stream_end(char *name,
756
+ void * const userdata)
757
+ {
758
+ xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
759
+
760
+ /* stream is over */
761
+ xmpp_debug(conn->ctx, "xmpp", "RECV: </stream:stream>");
762
+ conn_disconnect_clean(conn);
763
+ }
764
+
765
+ static void _handle_stream_stanza(xmpp_stanza_t *stanza,
766
+ void * const userdata)
767
+ {
768
+ xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
769
+ char *buf;
770
+ size_t len;
771
+
772
+ if (xmpp_stanza_to_text(stanza, &buf, &len) == 0) {
773
+ xmpp_debug(conn->ctx, "xmpp", "RECV: %s", buf);
774
+ xmpp_free(conn->ctx, buf);
775
+ }
776
+
777
+ handler_fire_stanza(conn, stanza);
778
+ }
data/ext/ctx.c CHANGED
@@ -1,7 +1,7 @@
1
1
  /* ctx.c
2
2
  ** strophe XMPP client library -- run-time context implementation
3
3
  **
4
- ** Copyright (C) 2005-2008 OGG, LLC. All rights reserved.
4
+ ** Copyright (C) 2005-2009 Collecta, Inc.
5
5
  **
6
6
  ** This software is provided AS-IS with no warranty, either express
7
7
  ** or implied.
@@ -58,7 +58,7 @@
58
58
  *
59
59
  * @ingroup Init
60
60
  */
61
- void xmpp_initialize(void)
61
+ void xmpp_initialize(void)
62
62
  {
63
63
  sock_initialize();
64
64
  tls_initialize();
@@ -248,12 +248,12 @@ void xmpp_log(const xmpp_ctx_t * const ctx,
248
248
  va_list ap)
249
249
  {
250
250
  int oldret, ret;
251
- char smbuf[4096] = {0};
251
+ char smbuf[1024];
252
252
  char *buf;
253
253
 
254
254
  buf = smbuf;
255
- ret = xmpp_vsnprintf(buf, 4096 - 1, fmt, ap);
256
- if (ret > 4096 - 1) {
255
+ ret = xmpp_vsnprintf(buf, 1023, fmt, ap);
256
+ if (ret > 1023) {
257
257
  buf = (char *)xmpp_alloc(ctx, ret + 1);
258
258
  if (!buf) {
259
259
  buf = NULL;