yong-stropheruby 0.0.5
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/.autotest +9 -0
- data/History.txt +4 -0
- data/Manifest.txt +39 -0
- data/PostInstall.txt +4 -0
- data/README.rdoc +143 -0
- data/Rakefile +21 -0
- data/ext/auth.c +990 -0
- data/ext/common.h +287 -0
- data/ext/conn.c +609 -0
- data/ext/ctx.c +416 -0
- data/ext/event.c +345 -0
- data/ext/extconf.rb +6 -0
- data/ext/handler.c +592 -0
- data/ext/hash.c +278 -0
- data/ext/hash.h +64 -0
- data/ext/jid.c +177 -0
- data/ext/md5.c +289 -0
- data/ext/md5.h +41 -0
- data/ext/ostypes.h +27 -0
- data/ext/parser.c +206 -0
- data/ext/sasl.c +614 -0
- data/ext/sasl.h +44 -0
- data/ext/sha1.c +389 -0
- data/ext/sha1.h +31 -0
- data/ext/snprintf.c +839 -0
- data/ext/sock.c +911 -0
- data/ext/sock.h +51 -0
- data/ext/stanza.c +908 -0
- data/ext/strophe.h +372 -0
- data/ext/strophe_ruby.c +687 -0
- data/ext/thread.c +119 -0
- data/ext/thread.h +43 -0
- data/ext/tls.h +46 -0
- data/ext/tls_dummy.c +89 -0
- data/ext/util.c +107 -0
- data/ext/util.h +32 -0
- data/lib/strophe_ruby.rb +6 -0
- data/test/test_helper.rb +3 -0
- data/test/test_strophe_ruby.rb +11 -0
- data/test/test_strophe_ruby_extn.rb +9 -0
- metadata +108 -0
data/ext/strophe_ruby.c
ADDED
@@ -0,0 +1,687 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include "strophe.h"
|
3
|
+
#include "common.h"
|
4
|
+
|
5
|
+
VALUE mStropheRuby;
|
6
|
+
VALUE mErrorTypes;
|
7
|
+
VALUE mLogging;
|
8
|
+
VALUE mConnectionEvents;
|
9
|
+
VALUE cConnection;
|
10
|
+
VALUE cContext;
|
11
|
+
VALUE cStreamError;
|
12
|
+
VALUE cEventLoop;
|
13
|
+
VALUE client_conn_handler;
|
14
|
+
VALUE cStanza;
|
15
|
+
|
16
|
+
/* release the stanza. Called automatically by the GC */
|
17
|
+
static void t_xmpp_stanza_release(void *stanza) {
|
18
|
+
//if(stanza != NULL)
|
19
|
+
// xmpp_stanza_release(stanza);
|
20
|
+
}
|
21
|
+
|
22
|
+
/* Initialize the strophe library */
|
23
|
+
VALUE t_xmpp_initialize(VALUE self) {
|
24
|
+
xmpp_initialize();
|
25
|
+
return Qtrue;
|
26
|
+
}
|
27
|
+
|
28
|
+
/* shutdown the library */
|
29
|
+
VALUE t_xmpp_shutdown(VALUE self) {
|
30
|
+
xmpp_shutdown();
|
31
|
+
return Qnil;
|
32
|
+
}
|
33
|
+
|
34
|
+
/* check Strophe version */
|
35
|
+
VALUE t_xmpp_version_check(VALUE self, VALUE major, VALUE minor) {
|
36
|
+
int res = xmpp_version_check(FIX2INT(major), FIX2INT(minor));
|
37
|
+
return INT2FIX(res);
|
38
|
+
}
|
39
|
+
|
40
|
+
/* parse the stream one time */
|
41
|
+
VALUE t_xmpp_run_once(VALUE self, VALUE rb_ctx, VALUE timeout) {
|
42
|
+
xmpp_ctx_t *ctx;
|
43
|
+
Data_Get_Struct(rb_ctx,xmpp_ctx_t,ctx);
|
44
|
+
int i = xmpp_run_once(ctx, NUM2INT(timeout));
|
45
|
+
return INT2FIX(i);
|
46
|
+
}
|
47
|
+
|
48
|
+
/* parse the stream continuously (by calling xmpp_run_once in a while loop) */
|
49
|
+
VALUE t_xmpp_run(VALUE self, VALUE rb_ctx) {
|
50
|
+
xmpp_ctx_t *ctx;
|
51
|
+
Data_Get_Struct(rb_ctx,xmpp_ctx_t,ctx);
|
52
|
+
xmpp_run(ctx);
|
53
|
+
return Qtrue;
|
54
|
+
}
|
55
|
+
|
56
|
+
/* Set a flag to indicate to our event loop that it must exit */
|
57
|
+
VALUE t_xmpp_stop(VALUE self, VALUE rb_ctx) {
|
58
|
+
xmpp_ctx_t *ctx;
|
59
|
+
Data_Get_Struct(rb_ctx, xmpp_ctx_t, ctx);
|
60
|
+
xmpp_stop(ctx);
|
61
|
+
return Qtrue;
|
62
|
+
}
|
63
|
+
|
64
|
+
/* free the context object (because it causes segmentation error once in a while) */
|
65
|
+
static VALUE t_xmpp_ctx_free(VALUE self) {
|
66
|
+
xmpp_ctx_t *ctx;
|
67
|
+
Data_Get_Struct(self,xmpp_ctx_t,ctx);
|
68
|
+
xmpp_ctx_free(ctx);
|
69
|
+
}
|
70
|
+
|
71
|
+
/* Get the status of the control loop
|
72
|
+
TODO: Define ruby constants for the loop statuses. Currently we have to know them by heart (0 = NOTSTARTED, 1 = RUNNING, 2 = QUIT)
|
73
|
+
*/
|
74
|
+
static VALUE t_xmpp_get_loop_status(VALUE self) {
|
75
|
+
xmpp_ctx_t *ctx;
|
76
|
+
Data_Get_Struct(self, xmpp_ctx_t, ctx);
|
77
|
+
return INT2FIX(ctx->loop_status);
|
78
|
+
}
|
79
|
+
|
80
|
+
/* Set the loop status. Don't call this method if you want to exit the control loop. Call xmpp_stop instead. This method
|
81
|
+
will set the loop status at QUIT */
|
82
|
+
static VALUE t_xmpp_set_loop_status(VALUE self, VALUE rb_loop_status) {
|
83
|
+
xmpp_ctx_t *ctx;
|
84
|
+
Data_Get_Struct(self, xmpp_ctx_t, ctx);
|
85
|
+
ctx->loop_status=FIX2INT(rb_loop_status);
|
86
|
+
return rb_loop_status;
|
87
|
+
}
|
88
|
+
|
89
|
+
/* Initialize a run time context */
|
90
|
+
VALUE t_xmpp_ctx_new(VALUE class, VALUE log_level) {
|
91
|
+
xmpp_log_t *log;
|
92
|
+
xmpp_log_level_t level;
|
93
|
+
level=FIX2INT(log_level);
|
94
|
+
log = xmpp_get_default_logger((xmpp_log_level_t)level);
|
95
|
+
xmpp_ctx_t *ctx = xmpp_ctx_new(NULL, log);
|
96
|
+
VALUE tdata = Data_Wrap_Struct(class, 0, free, ctx);
|
97
|
+
VALUE argv[1];
|
98
|
+
argv[0] = log_level;
|
99
|
+
rb_obj_call_init(tdata,1,argv);
|
100
|
+
return tdata;
|
101
|
+
}
|
102
|
+
|
103
|
+
/* Ruby initialize for the context. Hmm... do we really need this? */
|
104
|
+
static VALUE t_xmpp_ctx_init(VALUE self, VALUE log_level) {
|
105
|
+
rb_iv_set(self, "@log_level", log_level);
|
106
|
+
return self;
|
107
|
+
}
|
108
|
+
|
109
|
+
/* Release the connection object. (Currently not called at all... because it causes segmentation error once in a while) */
|
110
|
+
static VALUE t_xmpp_conn_release(VALUE self) {
|
111
|
+
xmpp_conn_t *conn;
|
112
|
+
Data_Get_Struct(self,xmpp_conn_t,conn);
|
113
|
+
xmpp_conn_release(conn);
|
114
|
+
}
|
115
|
+
|
116
|
+
/* Initialize a connection object. We register instance variables that will hold the various callbacks
|
117
|
+
You should not manipulate instance variables. Use add_handler instead.
|
118
|
+
Maybe put this into xmpp_conn_new?
|
119
|
+
*/
|
120
|
+
static VALUE t_xmpp_conn_init(VALUE self, VALUE ctx) {
|
121
|
+
rb_iv_set(self, "@ctx", ctx);
|
122
|
+
rb_iv_set(self, "@presence_handlers", rb_ary_new());
|
123
|
+
rb_iv_set(self, "@message_handlers", rb_ary_new());
|
124
|
+
rb_iv_set(self, "@iq_handlers", rb_ary_new());
|
125
|
+
rb_iv_set(self, "@id_handlers", rb_ary_new());
|
126
|
+
rb_gv_set("rb_conn",self);
|
127
|
+
return self;
|
128
|
+
}
|
129
|
+
|
130
|
+
/* create a connection object then call the initialize method for it*/
|
131
|
+
VALUE t_xmpp_conn_new(VALUE class, VALUE rb_ctx) {
|
132
|
+
//Get the context in a format that C can understand
|
133
|
+
xmpp_ctx_t *ctx;
|
134
|
+
Data_Get_Struct(rb_ctx, xmpp_ctx_t, ctx);
|
135
|
+
|
136
|
+
xmpp_conn_t *conn = xmpp_conn_new(ctx);
|
137
|
+
VALUE tdata = Data_Wrap_Struct(class, 0, free, conn);
|
138
|
+
VALUE argv[1];
|
139
|
+
argv[0] = rb_ctx;
|
140
|
+
|
141
|
+
//call ruby "initialize"
|
142
|
+
rb_obj_call_init(tdata, 1, argv);
|
143
|
+
return tdata;
|
144
|
+
}
|
145
|
+
|
146
|
+
/* Clone a connection */
|
147
|
+
static VALUE t_xmpp_conn_clone(VALUE self) {
|
148
|
+
xmpp_conn_t *conn = xmpp_conn_clone((xmpp_conn_t *)self);
|
149
|
+
return Data_Wrap_Struct(cConnection, 0, t_xmpp_conn_release, conn);
|
150
|
+
}
|
151
|
+
|
152
|
+
|
153
|
+
/* Get the jid */
|
154
|
+
static VALUE t_xmpp_conn_get_jid(VALUE self) {
|
155
|
+
xmpp_conn_t *conn;
|
156
|
+
Data_Get_Struct(self, xmpp_conn_t, conn);
|
157
|
+
return rb_str_new2(xmpp_conn_get_jid(conn));
|
158
|
+
}
|
159
|
+
|
160
|
+
/* Set the jid */
|
161
|
+
static VALUE t_xmpp_conn_set_jid(VALUE self, VALUE jid) {
|
162
|
+
xmpp_conn_t *conn;
|
163
|
+
Data_Get_Struct(self, xmpp_conn_t, conn);
|
164
|
+
xmpp_conn_set_jid(conn, STR2CSTR(jid));
|
165
|
+
return jid;
|
166
|
+
}
|
167
|
+
|
168
|
+
/* get the password */
|
169
|
+
static VALUE t_xmpp_conn_get_pass(VALUE self) {
|
170
|
+
xmpp_conn_t *conn;
|
171
|
+
Data_Get_Struct(self, xmpp_conn_t, conn);
|
172
|
+
return rb_str_new2(xmpp_conn_get_pass(conn));
|
173
|
+
}
|
174
|
+
|
175
|
+
/* set the password */
|
176
|
+
static VALUE t_xmpp_conn_set_pass(VALUE self, VALUE pass) {
|
177
|
+
xmpp_conn_t *conn;
|
178
|
+
Data_Get_Struct(self, xmpp_conn_t, conn);
|
179
|
+
xmpp_conn_set_pass(conn, STR2CSTR(pass));
|
180
|
+
return pass;
|
181
|
+
}
|
182
|
+
|
183
|
+
|
184
|
+
/* Parent handler for the connection... we call yield to invoke the client callback*/
|
185
|
+
static void _conn_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status,
|
186
|
+
const int error, xmpp_stream_error_t * const stream_error,
|
187
|
+
void * const userdata) {
|
188
|
+
//yield code block for connection
|
189
|
+
if (RTEST(client_conn_handler))
|
190
|
+
rb_funcall(client_conn_handler, rb_intern("call"), 1, INT2FIX(status));
|
191
|
+
}
|
192
|
+
|
193
|
+
/*this is called in a loop (rb_iterate). We invoke the block passed by the user*/
|
194
|
+
static VALUE _call_handler(VALUE obj, VALUE stanza) {
|
195
|
+
rb_funcall(obj, rb_intern("call"),1, stanza);
|
196
|
+
return Qnil;
|
197
|
+
}
|
198
|
+
|
199
|
+
/* Called when a message is received in the stream. From there we invoke all code blocks for stanzas of type 'message'*/
|
200
|
+
int _message_handler(xmpp_conn_t * const conn,
|
201
|
+
xmpp_stanza_t * const stanza,
|
202
|
+
void * const userdata) {
|
203
|
+
VALUE arr;
|
204
|
+
VALUE rb_conn;
|
205
|
+
rb_conn = rb_gv_get("rb_conn");
|
206
|
+
VALUE rb_stanza = Data_Wrap_Struct(cStanza, 0, t_xmpp_stanza_release, stanza);
|
207
|
+
|
208
|
+
arr=rb_iv_get(rb_conn,"@message_handlers");
|
209
|
+
rb_iterate(rb_each,arr,_call_handler, rb_stanza);
|
210
|
+
return 1;
|
211
|
+
}
|
212
|
+
|
213
|
+
/* Called when a presence is received in the stream. From there we invoke all code blocks for stanzas of type 'presence'*/
|
214
|
+
int _presence_handler(xmpp_conn_t * const conn,
|
215
|
+
xmpp_stanza_t * const stanza,
|
216
|
+
void * const userdata) {
|
217
|
+
VALUE arr;
|
218
|
+
VALUE rb_conn;
|
219
|
+
rb_conn = rb_gv_get("rb_conn");
|
220
|
+
VALUE rb_stanza = Data_Wrap_Struct(cStanza, 0, t_xmpp_stanza_release, stanza);
|
221
|
+
|
222
|
+
arr=rb_iv_get(rb_conn,"@presence_handlers");
|
223
|
+
rb_iterate(rb_each,arr,_call_handler, rb_stanza);
|
224
|
+
return 1;
|
225
|
+
}
|
226
|
+
|
227
|
+
/* Called when a iq is received in the stream. From there we invoke all code blocks for stanzas of type 'iq'*/
|
228
|
+
int _iq_handler(xmpp_conn_t * const conn,
|
229
|
+
xmpp_stanza_t * const stanza,
|
230
|
+
void * const userdata) {
|
231
|
+
VALUE arr;
|
232
|
+
VALUE rb_conn;
|
233
|
+
rb_conn = rb_gv_get("rb_conn");
|
234
|
+
VALUE rb_stanza = Data_Wrap_Struct(cStanza, 0, t_xmpp_stanza_release, stanza);
|
235
|
+
|
236
|
+
arr=rb_iv_get(rb_conn,"@iq_handlers");
|
237
|
+
rb_iterate(rb_each,arr,_call_handler, rb_stanza);
|
238
|
+
return 1;
|
239
|
+
}
|
240
|
+
|
241
|
+
/* Called when a id stanza is received TODO: Test this!*/
|
242
|
+
int _id_handler(xmpp_conn_t * const conn,
|
243
|
+
xmpp_stanza_t * const stanza,
|
244
|
+
void * const userdata) {
|
245
|
+
VALUE arr;
|
246
|
+
VALUE rb_conn;
|
247
|
+
rb_conn = rb_gv_get("rb_conn");
|
248
|
+
VALUE rb_stanza = Data_Wrap_Struct(cStanza, 0, t_xmpp_stanza_release, stanza);
|
249
|
+
|
250
|
+
arr=rb_iv_get(rb_conn,"@id_handlers");
|
251
|
+
rb_iterate(rb_each,arr,_call_handler, rb_stanza);
|
252
|
+
return 1;
|
253
|
+
}
|
254
|
+
|
255
|
+
|
256
|
+
/* Add an handler for events in the stream (message, presence or iqs), We store the block we just received in the correct instance variable
|
257
|
+
to invoke it later*/
|
258
|
+
static VALUE t_xmpp_handler_add(VALUE self,VALUE rb_name) {
|
259
|
+
xmpp_conn_t *conn;
|
260
|
+
Data_Get_Struct(self, xmpp_conn_t, conn);
|
261
|
+
char *name = STR2CSTR(rb_name);
|
262
|
+
VALUE arr;
|
263
|
+
xmpp_handler handler;
|
264
|
+
|
265
|
+
if(strcmp(name,"message") == 0) {
|
266
|
+
arr = rb_iv_get(self, "@message_handlers");
|
267
|
+
handler = _message_handler;
|
268
|
+
} else {
|
269
|
+
if(strcmp(name,"presence") == 0) {
|
270
|
+
arr = rb_iv_get(self, "@presence_handlers");
|
271
|
+
handler = _presence_handler;
|
272
|
+
} else {
|
273
|
+
arr = rb_iv_get(self, "@iq_handlers");
|
274
|
+
handler = _iq_handler;
|
275
|
+
}
|
276
|
+
}
|
277
|
+
|
278
|
+
xmpp_handler_add(conn, handler, NULL, name, NULL, conn->ctx);
|
279
|
+
rb_ary_push(arr, rb_block_proc());
|
280
|
+
return Qnil;
|
281
|
+
}
|
282
|
+
|
283
|
+
/* Add an handler for ID stanzas. TODO:Test this!*/
|
284
|
+
static VALUE t_xmpp_id_handler_add(VALUE self, VALUE rb_id) {
|
285
|
+
xmpp_conn_t *conn;
|
286
|
+
Data_Get_Struct(self, xmpp_conn_t, conn);
|
287
|
+
char *id = STR2CSTR(rb_id);
|
288
|
+
VALUE arr;
|
289
|
+
|
290
|
+
arr = rb_iv_get(self, "@id_handlers");
|
291
|
+
rb_ary_push(arr, rb_block_proc());
|
292
|
+
xmpp_id_handler_add(conn, _id_handler, STR2CSTR(id), conn->ctx);
|
293
|
+
return Qnil;
|
294
|
+
}
|
295
|
+
|
296
|
+
/* Connect and authenticate. We store the block in the client_conn_handler variable to invoke it later*/
|
297
|
+
static VALUE t_xmpp_connect_client(VALUE self) {
|
298
|
+
xmpp_conn_t *conn;
|
299
|
+
xmpp_ctx_t *ctx;
|
300
|
+
Data_Get_Struct(rb_iv_get(self, "@ctx"), xmpp_ctx_t, ctx);
|
301
|
+
Data_Get_Struct(self, xmpp_conn_t, conn);
|
302
|
+
|
303
|
+
/*The user might have passed a block... however we don't want to invoke it right now.
|
304
|
+
We store it to invoke it later in _xmpp_conn_handler */
|
305
|
+
if (rb_block_given_p())
|
306
|
+
client_conn_handler = rb_block_proc();
|
307
|
+
|
308
|
+
int result = xmpp_connect_client(conn, NULL, 0, _conn_handler, ctx);
|
309
|
+
return INT2FIX(result);
|
310
|
+
}
|
311
|
+
|
312
|
+
/* Disconnect from the stream. Is it needed? Not too sure about it. Normally if you just call xmpp_stop you should be fine*/
|
313
|
+
static VALUE t_xmpp_disconnect(VALUE self) {
|
314
|
+
xmpp_conn_t *conn;
|
315
|
+
Data_Get_Struct(self, xmpp_conn_t, conn);
|
316
|
+
xmpp_disconnect(conn);
|
317
|
+
conn_disconnect(conn);
|
318
|
+
return Qtrue;
|
319
|
+
}
|
320
|
+
|
321
|
+
/* Send a stanza in the stream */
|
322
|
+
static VALUE t_xmpp_send(VALUE self, VALUE rb_stanza) {
|
323
|
+
|
324
|
+
xmpp_conn_t *conn;
|
325
|
+
xmpp_stanza_t *stanza;
|
326
|
+
|
327
|
+
Data_Get_Struct(self, xmpp_conn_t, conn);
|
328
|
+
Data_Get_Struct(rb_stanza, xmpp_stanza_t, stanza);
|
329
|
+
|
330
|
+
xmpp_send(conn,stanza);
|
331
|
+
return Qtrue;
|
332
|
+
}
|
333
|
+
|
334
|
+
/* Send a stanza in the stream */
|
335
|
+
static VALUE t_xmpp_send_raw_string(VALUE self, VALUE rb_text) {
|
336
|
+
|
337
|
+
xmpp_conn_t *conn;
|
338
|
+
char *text;
|
339
|
+
|
340
|
+
Data_Get_Struct(self, xmpp_conn_t, conn);
|
341
|
+
text = STR2CSTR(rb_text);
|
342
|
+
|
343
|
+
xmpp_send_raw_string(conn, "%s", text);
|
344
|
+
return Qtrue;
|
345
|
+
}
|
346
|
+
|
347
|
+
/* Create a new stanza */
|
348
|
+
VALUE t_xmpp_stanza_new(VALUE class) {
|
349
|
+
//Get the context in a format that C can understand
|
350
|
+
xmpp_ctx_t *ctx;
|
351
|
+
VALUE rb_conn = rb_gv_get("rb_conn");
|
352
|
+
Data_Get_Struct(rb_iv_get(rb_conn,"@ctx"), xmpp_ctx_t, ctx);
|
353
|
+
|
354
|
+
xmpp_stanza_t *stanza = xmpp_stanza_new(ctx);
|
355
|
+
VALUE tdata = Data_Wrap_Struct(class, 0, t_xmpp_stanza_release, stanza);
|
356
|
+
}
|
357
|
+
|
358
|
+
/*Clone a stanza. TODO: Test this!*/
|
359
|
+
static VALUE t_xmpp_stanza_clone(VALUE self) {
|
360
|
+
xmpp_stanza_t *stanza;
|
361
|
+
xmpp_stanza_t *new_stanza;
|
362
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
363
|
+
new_stanza = xmpp_stanza_clone(stanza);
|
364
|
+
VALUE tdata = Data_Wrap_Struct(cStanza, 0, t_xmpp_stanza_release, new_stanza);
|
365
|
+
return tdata;
|
366
|
+
}
|
367
|
+
|
368
|
+
/*Copy a stanza. TODO: Test this!*/
|
369
|
+
static VALUE t_xmpp_stanza_copy(VALUE self) {
|
370
|
+
xmpp_stanza_t *stanza;
|
371
|
+
xmpp_stanza_t *new_stanza;
|
372
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
373
|
+
new_stanza = xmpp_stanza_copy(stanza);
|
374
|
+
VALUE tdata = Data_Wrap_Struct(cStanza, 0, t_xmpp_stanza_release, new_stanza);
|
375
|
+
return tdata;
|
376
|
+
}
|
377
|
+
|
378
|
+
|
379
|
+
/*Get the children of the stanza. For example, message stanzas have a "body" child that contains another stanza that contains the actual
|
380
|
+
message. If you have the top level stanza you can do something like : body_stanza = message_stanza.children */
|
381
|
+
static VALUE t_xmpp_stanza_get_children(VALUE self) {
|
382
|
+
xmpp_stanza_t *stanza;
|
383
|
+
xmpp_stanza_t *children;
|
384
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
385
|
+
children = xmpp_stanza_get_children(stanza);
|
386
|
+
|
387
|
+
if(children) {
|
388
|
+
VALUE tdata = Data_Wrap_Struct(cStanza, 0, t_xmpp_stanza_release, children);
|
389
|
+
return tdata;
|
390
|
+
}
|
391
|
+
else
|
392
|
+
return Qnil;
|
393
|
+
}
|
394
|
+
|
395
|
+
/*Get the child of a stanza by its name. eg. body_stanza = message_stanza.child_by_name("body")*/
|
396
|
+
static VALUE t_xmpp_stanza_get_child_by_name(VALUE self, VALUE rb_name) {
|
397
|
+
xmpp_stanza_t *stanza;
|
398
|
+
xmpp_stanza_t *child;
|
399
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
400
|
+
|
401
|
+
char *name = STR2CSTR(rb_name);
|
402
|
+
child = xmpp_stanza_get_child_by_name(stanza, name);
|
403
|
+
|
404
|
+
if(child) {
|
405
|
+
VALUE rb_child = Data_Wrap_Struct(cStanza, 0, t_xmpp_stanza_release, child);
|
406
|
+
return rb_child;
|
407
|
+
} else {
|
408
|
+
return Qnil;
|
409
|
+
}
|
410
|
+
}
|
411
|
+
|
412
|
+
/*TODO: Test this!*/
|
413
|
+
static VALUE t_xmpp_stanza_get_next(VALUE self) {
|
414
|
+
xmpp_stanza_t *stanza;
|
415
|
+
xmpp_stanza_t *next;
|
416
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
417
|
+
|
418
|
+
next = xmpp_stanza_get_next(stanza);
|
419
|
+
|
420
|
+
VALUE tdata = Data_Wrap_Struct(cStanza, 0, t_xmpp_stanza_release, next);
|
421
|
+
return tdata;
|
422
|
+
}
|
423
|
+
|
424
|
+
/*Get the attribute of a stanza. eg. message_stanza.child_by_name("body").text*/
|
425
|
+
static VALUE t_xmpp_stanza_get_attribute(VALUE self, VALUE rb_attribute) {
|
426
|
+
xmpp_stanza_t *stanza;
|
427
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
428
|
+
|
429
|
+
char *val = xmpp_stanza_get_attribute(stanza,STR2CSTR(rb_attribute));
|
430
|
+
return rb_str_new2(val);
|
431
|
+
}
|
432
|
+
|
433
|
+
/*Get the namespace of a stanza TODO: Test this!*/
|
434
|
+
static VALUE t_xmpp_stanza_get_ns(VALUE self) {
|
435
|
+
xmpp_stanza_t *stanza;
|
436
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
437
|
+
|
438
|
+
char *ns = xmpp_stanza_get_ns(stanza);
|
439
|
+
return rb_str_new2(ns);
|
440
|
+
}
|
441
|
+
|
442
|
+
/*Get the text of a stanza. */
|
443
|
+
static VALUE t_xmpp_stanza_get_text(VALUE self) {
|
444
|
+
xmpp_stanza_t *stanza;
|
445
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
446
|
+
|
447
|
+
char *text = xmpp_stanza_get_text(stanza);
|
448
|
+
|
449
|
+
if(text)
|
450
|
+
return rb_str_new2(text);
|
451
|
+
else
|
452
|
+
return rb_str_new2("");
|
453
|
+
}
|
454
|
+
|
455
|
+
/*Get the name of a stanza (message, presence, iq) */
|
456
|
+
static VALUE t_xmpp_stanza_get_name(VALUE self) {
|
457
|
+
xmpp_stanza_t *stanza;
|
458
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
459
|
+
|
460
|
+
char *name = xmpp_stanza_get_name(stanza);
|
461
|
+
return rb_str_new2(name);
|
462
|
+
}
|
463
|
+
|
464
|
+
/*Get the type of a stanza. For example, if the name is 'message', type can be 'chat', 'normal' and so on */
|
465
|
+
static VALUE t_xmpp_stanza_get_type(VALUE self) {
|
466
|
+
xmpp_stanza_t *stanza;
|
467
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
468
|
+
|
469
|
+
char *type = xmpp_stanza_get_type(stanza);
|
470
|
+
|
471
|
+
if(type)
|
472
|
+
return rb_str_new2(type);
|
473
|
+
else
|
474
|
+
return Qnil;
|
475
|
+
}
|
476
|
+
|
477
|
+
/*Get the id of a stanza. TODO:Test this!*/
|
478
|
+
static VALUE t_xmpp_stanza_get_id(VALUE self) {
|
479
|
+
xmpp_stanza_t *stanza;
|
480
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
481
|
+
|
482
|
+
char *id = xmpp_stanza_get_id(stanza);
|
483
|
+
return rb_str_new2(id);
|
484
|
+
}
|
485
|
+
|
486
|
+
/*Set the value of a stanza attribute (eg. stanza.set_attribute("to","johnsmith@example.com") */
|
487
|
+
static VALUE t_xmpp_stanza_set_attribute(VALUE self, VALUE rb_attribute, VALUE rb_val) {
|
488
|
+
xmpp_stanza_t *stanza;
|
489
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
490
|
+
|
491
|
+
char *attribute = STR2CSTR(rb_attribute);
|
492
|
+
char *val = STR2CSTR(rb_val);
|
493
|
+
|
494
|
+
xmpp_stanza_set_attribute(stanza, attribute, val);
|
495
|
+
return Qtrue;
|
496
|
+
}
|
497
|
+
|
498
|
+
/*Set the namespace of a stanza. TODO:Test this!*/
|
499
|
+
static VALUE t_xmpp_stanza_set_ns(VALUE self, VALUE rb_ns) {
|
500
|
+
xmpp_stanza_t *stanza;
|
501
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
502
|
+
|
503
|
+
char *ns = STR2CSTR(rb_ns);
|
504
|
+
|
505
|
+
xmpp_stanza_set_ns(stanza, ns);
|
506
|
+
return Qtrue;
|
507
|
+
}
|
508
|
+
|
509
|
+
static VALUE t_xmpp_stanza_to_text(VALUE self) {
|
510
|
+
xmpp_stanza_t *stanza;
|
511
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
512
|
+
|
513
|
+
char* buffer;
|
514
|
+
size_t len;
|
515
|
+
xmpp_stanza_to_text(stanza, &buffer, &len);
|
516
|
+
if (NULL == buffer)
|
517
|
+
return rb_str_new(0, 0);
|
518
|
+
else
|
519
|
+
return rb_str_buf_new2(buffer);
|
520
|
+
}
|
521
|
+
|
522
|
+
/*Set the text of a stanza */
|
523
|
+
static VALUE t_xmpp_stanza_set_text(VALUE self, VALUE rb_text) {
|
524
|
+
xmpp_stanza_t *stanza;
|
525
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
526
|
+
|
527
|
+
char *text = STR2CSTR(rb_text);
|
528
|
+
|
529
|
+
xmpp_stanza_set_text(stanza, text);
|
530
|
+
return rb_text;
|
531
|
+
}
|
532
|
+
|
533
|
+
/*Set the name of a stanza (message, presence, iq) */
|
534
|
+
static VALUE t_xmpp_stanza_set_name(VALUE self, VALUE rb_name) {
|
535
|
+
xmpp_stanza_t *stanza;
|
536
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
537
|
+
|
538
|
+
char *name = STR2CSTR(rb_name);
|
539
|
+
|
540
|
+
xmpp_stanza_set_name(stanza, name);
|
541
|
+
return Qtrue;
|
542
|
+
}
|
543
|
+
|
544
|
+
/*Set the type of a stanza. For example if the name is 'message', the type can be 'chat', 'normal' and so on*/
|
545
|
+
static VALUE t_xmpp_stanza_set_type(VALUE self, VALUE rb_type) {
|
546
|
+
xmpp_stanza_t *stanza;
|
547
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
548
|
+
|
549
|
+
char *type = STR2CSTR(rb_type);
|
550
|
+
|
551
|
+
xmpp_stanza_set_type(stanza, type);
|
552
|
+
return Qtrue;
|
553
|
+
}
|
554
|
+
|
555
|
+
/*Set the id of a stanza. TODO:Test this!*/
|
556
|
+
static VALUE t_xmpp_stanza_set_id(VALUE self, VALUE rb_id) {
|
557
|
+
xmpp_stanza_t *stanza;
|
558
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
559
|
+
|
560
|
+
char *id = STR2CSTR(rb_id);
|
561
|
+
|
562
|
+
xmpp_stanza_set_id(stanza, id);
|
563
|
+
return Qtrue;
|
564
|
+
}
|
565
|
+
|
566
|
+
/*Add a child element to a stanza (hint: message stanzas have a body element...) */
|
567
|
+
static VALUE t_xmpp_stanza_add_child(VALUE self, VALUE rb_child) {
|
568
|
+
xmpp_stanza_t *stanza;
|
569
|
+
Data_Get_Struct(self, xmpp_stanza_t, stanza);
|
570
|
+
|
571
|
+
xmpp_stanza_t *child;
|
572
|
+
Data_Get_Struct(rb_child, xmpp_stanza_t, child);
|
573
|
+
int res = xmpp_stanza_add_child(stanza,child);
|
574
|
+
return INT2FIX(res);
|
575
|
+
}
|
576
|
+
|
577
|
+
|
578
|
+
void Init_strophe_ruby() {
|
579
|
+
/*Main module that contains everything*/
|
580
|
+
mStropheRuby = rb_define_module("StropheRuby");
|
581
|
+
|
582
|
+
/*Wrap the stream_error_t structure into a ruby class named StreamError*/
|
583
|
+
cStreamError = rb_define_class_under(mStropheRuby, "StreamError", rb_cObject);
|
584
|
+
|
585
|
+
cEventLoop = rb_define_class_under(mStropheRuby, "EventLoop", rb_cObject);
|
586
|
+
rb_define_singleton_method(cEventLoop, "run_once", t_xmpp_run_once, 2);
|
587
|
+
rb_define_singleton_method(cEventLoop, "prepare", t_xmpp_initialize, 0);
|
588
|
+
rb_define_singleton_method(cEventLoop, "run", t_xmpp_run, 1);
|
589
|
+
rb_define_singleton_method(cEventLoop, "stop", t_xmpp_stop, 1);
|
590
|
+
rb_define_singleton_method(cEventLoop, "shutdown", t_xmpp_shutdown, 0);
|
591
|
+
rb_define_singleton_method(cEventLoop, "version", t_xmpp_version_check, 2);
|
592
|
+
rb_define_const(cEventLoop, "LOOP_RUNNING", INT2FIX(XMPP_LOOP_RUNNING));
|
593
|
+
rb_define_const(cEventLoop, "LOOP_NOTSTARTED", INT2FIX(XMPP_LOOP_NOTSTARTED));
|
594
|
+
rb_define_const(cEventLoop, "LOOP_QUIT", INT2FIX(XMPP_LOOP_QUIT));
|
595
|
+
|
596
|
+
/*Logs*/
|
597
|
+
mLogging = rb_define_module_under(mStropheRuby, "Logging");
|
598
|
+
rb_define_const(mLogging, "DEBUG", INT2FIX(XMPP_LEVEL_DEBUG));
|
599
|
+
rb_define_const(mLogging, "INFO", INT2FIX(XMPP_LEVEL_INFO));
|
600
|
+
rb_define_const(mLogging, "WARN", INT2FIX(XMPP_LEVEL_WARN));
|
601
|
+
rb_define_const(mLogging, "ERROR", INT2FIX(XMPP_LEVEL_ERROR));
|
602
|
+
|
603
|
+
/*Connection Events*/
|
604
|
+
mConnectionEvents = rb_define_module_under(mStropheRuby, "ConnectionEvents");
|
605
|
+
rb_define_const(mConnectionEvents, "CONNECT", INT2FIX(XMPP_CONN_CONNECT));
|
606
|
+
rb_define_const(mConnectionEvents, "DISCONNECT", INT2FIX(XMPP_CONN_DISCONNECT));
|
607
|
+
rb_define_const(mConnectionEvents, "FAIL", INT2FIX(XMPP_CONN_FAIL));
|
608
|
+
|
609
|
+
/*Error types*/
|
610
|
+
mErrorTypes = rb_define_module_under(mStropheRuby, "ErrorTypes");
|
611
|
+
rb_define_const(mErrorTypes, "BAD_FORMAT", INT2FIX(XMPP_SE_BAD_FORMAT));
|
612
|
+
rb_define_const(mErrorTypes, "BAD_NS_PREFIX", INT2FIX(XMPP_SE_BAD_NS_PREFIX));
|
613
|
+
rb_define_const(mErrorTypes, "CONFLICT", INT2FIX(XMPP_SE_CONFLICT));
|
614
|
+
rb_define_const(mErrorTypes, "CONN_TIMEOUT", INT2FIX(XMPP_SE_CONN_TIMEOUT));
|
615
|
+
rb_define_const(mErrorTypes, "HOST_GONE", INT2FIX(XMPP_SE_HOST_GONE));
|
616
|
+
rb_define_const(mErrorTypes, "HOST_UNKNOWN", INT2FIX(XMPP_SE_HOST_UNKNOWN));
|
617
|
+
rb_define_const(mErrorTypes, "IMPROPER_ADDR", INT2FIX(XMPP_SE_IMPROPER_ADDR));
|
618
|
+
rb_define_const(mErrorTypes, "INTERNAL_SERVER_ERROR", INT2FIX(XMPP_SE_INTERNAL_SERVER_ERROR));
|
619
|
+
rb_define_const(mErrorTypes, "INVALID_FROM", INT2FIX(XMPP_SE_INVALID_FROM));
|
620
|
+
rb_define_const(mErrorTypes, "INVALID_ID", INT2FIX(XMPP_SE_INVALID_ID));
|
621
|
+
rb_define_const(mErrorTypes, "INVALID_NS", INT2FIX(XMPP_SE_INVALID_NS));
|
622
|
+
rb_define_const(mErrorTypes, "INVALID_XML", INT2FIX(XMPP_SE_INVALID_XML));
|
623
|
+
rb_define_const(mErrorTypes, "NOT_AUTHORIZED", INT2FIX(XMPP_SE_NOT_AUTHORIZED));
|
624
|
+
rb_define_const(mErrorTypes, "POLICY_VIOLATION", INT2FIX(XMPP_SE_POLICY_VIOLATION));
|
625
|
+
rb_define_const(mErrorTypes, "REMOTE_CONN_FAILED", INT2FIX(XMPP_SE_REMOTE_CONN_FAILED));
|
626
|
+
rb_define_const(mErrorTypes, "RESOURCE_CONSTRAINT", INT2FIX(XMPP_SE_RESOURCE_CONSTRAINT));
|
627
|
+
rb_define_const(mErrorTypes, "RESTRICTED_XML", INT2FIX(XMPP_SE_RESTRICTED_XML));
|
628
|
+
rb_define_const(mErrorTypes, "SEE_OTHER_HOST", INT2FIX(XMPP_SE_SEE_OTHER_HOST));
|
629
|
+
rb_define_const(mErrorTypes, "SYSTEM_SHUTDOWN", INT2FIX(XMPP_SE_SYSTEM_SHUTDOWN));
|
630
|
+
rb_define_const(mErrorTypes, "UNDEFINED_CONDITION", INT2FIX(XMPP_SE_UNDEFINED_CONDITION));
|
631
|
+
rb_define_const(mErrorTypes, "UNSUPPORTED_ENCODING", INT2FIX(XMPP_SE_UNSUPPORTED_ENCODING));
|
632
|
+
rb_define_const(mErrorTypes, "UNSUPPORTED_STANZA_TYPE", INT2FIX(XMPP_SE_UNSUPPORTED_STANZA_TYPE));
|
633
|
+
rb_define_const(mErrorTypes, "UNSUPPORTED_VERSION", INT2FIX(XMPP_SE_UNSUPPORTED_VERSION));
|
634
|
+
rb_define_const(mErrorTypes, "XML_NOT_WELL_FORMED", INT2FIX(XMPP_SE_XML_NOT_WELL_FORMED));
|
635
|
+
|
636
|
+
|
637
|
+
/*Context*/
|
638
|
+
cContext = rb_define_class_under(mStropheRuby, "Context", rb_cObject);
|
639
|
+
rb_define_singleton_method(cContext, "new", t_xmpp_ctx_new, 1);
|
640
|
+
rb_define_method(cContext, "initialize", t_xmpp_ctx_init, 1);
|
641
|
+
rb_define_method(cContext, "free", t_xmpp_ctx_free, 0);
|
642
|
+
rb_define_method(cContext, "loop_status", t_xmpp_get_loop_status, 0);
|
643
|
+
rb_define_method(cContext, "loop_status=", t_xmpp_set_loop_status, 1);
|
644
|
+
|
645
|
+
/*Connection*/
|
646
|
+
cConnection = rb_define_class_under(mStropheRuby, "Connection", rb_cObject);
|
647
|
+
rb_define_singleton_method(cConnection, "new", t_xmpp_conn_new, 1);
|
648
|
+
rb_define_method(cConnection, "initialize", t_xmpp_conn_init, 1);
|
649
|
+
rb_define_method(cConnection, "clone", t_xmpp_conn_clone, 1);
|
650
|
+
rb_define_method(cConnection, "release", t_xmpp_conn_release, 0);
|
651
|
+
rb_define_method(cConnection, "jid", t_xmpp_conn_get_jid,0);
|
652
|
+
rb_define_method(cConnection, "jid=", t_xmpp_conn_set_jid,1);
|
653
|
+
rb_define_method(cConnection, "password", t_xmpp_conn_get_pass,0);
|
654
|
+
rb_define_method(cConnection, "password=", t_xmpp_conn_set_pass,1);
|
655
|
+
rb_define_method(cConnection, "connect", t_xmpp_connect_client,0);
|
656
|
+
rb_define_method(cConnection, "disconnect", t_xmpp_disconnect, 0);
|
657
|
+
rb_define_method(cConnection, "send", t_xmpp_send, 1);
|
658
|
+
rb_define_method(cConnection, "send_raw_string", t_xmpp_send_raw_string, 1);
|
659
|
+
|
660
|
+
/*Handlers*/
|
661
|
+
rb_define_method(cConnection, "add_handler", t_xmpp_handler_add, 1);
|
662
|
+
rb_define_method(cConnection, "add_id_handler", t_xmpp_id_handler_add, 3);
|
663
|
+
|
664
|
+
/*Stanza*/
|
665
|
+
cStanza = rb_define_class_under(mStropheRuby, "Stanza", rb_cObject);
|
666
|
+
rb_define_singleton_method(cStanza, "new", t_xmpp_stanza_new, 0);
|
667
|
+
rb_define_method(cStanza, "clone", t_xmpp_stanza_clone, 0);
|
668
|
+
rb_define_method(cStanza, "copy", t_xmpp_stanza_copy, 0);
|
669
|
+
//rb_define_method(cStanza, "release", t_xmpp_stanza_release, 0);
|
670
|
+
rb_define_method(cStanza, "children", t_xmpp_stanza_get_children, 0);
|
671
|
+
rb_define_method(cStanza, "child_by_name", t_xmpp_stanza_get_child_by_name, 1);
|
672
|
+
rb_define_method(cStanza, "next", t_xmpp_stanza_get_next, 0);
|
673
|
+
rb_define_method(cStanza, "attribute", t_xmpp_stanza_get_attribute, 1);
|
674
|
+
rb_define_method(cStanza, "ns", t_xmpp_stanza_get_ns, 0);
|
675
|
+
rb_define_method(cStanza, "text", t_xmpp_stanza_get_text, 0);
|
676
|
+
rb_define_method(cStanza, "name", t_xmpp_stanza_get_name, 0);
|
677
|
+
rb_define_method(cStanza, "add_child", t_xmpp_stanza_add_child, 1);
|
678
|
+
rb_define_method(cStanza, "ns=", t_xmpp_stanza_set_ns, 1);
|
679
|
+
rb_define_method(cStanza, "to_s", t_xmpp_stanza_to_text, 0);
|
680
|
+
rb_define_method(cStanza, "set_attribute", t_xmpp_stanza_set_attribute, 2);
|
681
|
+
rb_define_method(cStanza, "name=", t_xmpp_stanza_set_name, 1);
|
682
|
+
rb_define_method(cStanza, "text=", t_xmpp_stanza_set_text, 1);
|
683
|
+
rb_define_method(cStanza, "type", t_xmpp_stanza_get_type, 0);
|
684
|
+
rb_define_method(cStanza, "id", t_xmpp_stanza_get_id, 0);
|
685
|
+
rb_define_method(cStanza, "id=", t_xmpp_stanza_set_id, 1);
|
686
|
+
rb_define_method(cStanza, "type=", t_xmpp_stanza_set_type, 1);
|
687
|
+
}
|