stropheruby 0.1.5 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
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;