iodine 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of iodine might be problematic. Click here for more details.

Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/README.md +63 -100
  4. data/bin/raw-rbhttp +12 -7
  5. data/examples/config.ru +8 -7
  6. data/examples/echo.ru +8 -7
  7. data/examples/info.md +41 -35
  8. data/examples/pubsub_engine.ru +12 -12
  9. data/examples/redis.ru +10 -12
  10. data/examples/shootout.ru +19 -42
  11. data/exe/iodine +116 -1
  12. data/ext/iodine/defer.c +1 -1
  13. data/ext/iodine/facil.c +12 -8
  14. data/ext/iodine/facil.h +2 -2
  15. data/ext/iodine/iodine.c +177 -343
  16. data/ext/iodine/iodine.h +18 -72
  17. data/ext/iodine/iodine_caller.c +132 -0
  18. data/ext/iodine/iodine_caller.h +21 -0
  19. data/ext/iodine/iodine_connection.c +841 -0
  20. data/ext/iodine/iodine_connection.h +55 -0
  21. data/ext/iodine/iodine_defer.c +391 -0
  22. data/ext/iodine/iodine_defer.h +7 -0
  23. data/ext/iodine/{rb-fiobj2rb.h → iodine_fiobj2rb.h} +6 -6
  24. data/ext/iodine/iodine_helpers.c +51 -5
  25. data/ext/iodine/iodine_helpers.h +2 -3
  26. data/ext/iodine/iodine_http.c +284 -141
  27. data/ext/iodine/iodine_http.h +2 -2
  28. data/ext/iodine/iodine_json.c +13 -13
  29. data/ext/iodine/iodine_json.h +1 -1
  30. data/ext/iodine/iodine_pubsub.c +573 -823
  31. data/ext/iodine/iodine_pubsub.h +15 -27
  32. data/ext/iodine/{rb-rack-io.c → iodine_rack_io.c} +30 -8
  33. data/ext/iodine/{rb-rack-io.h → iodine_rack_io.h} +1 -0
  34. data/ext/iodine/iodine_store.c +136 -0
  35. data/ext/iodine/iodine_store.h +20 -0
  36. data/ext/iodine/iodine_tcp.c +385 -0
  37. data/ext/iodine/iodine_tcp.h +9 -0
  38. data/lib/iodine.rb +73 -171
  39. data/lib/iodine/connection.rb +34 -0
  40. data/lib/iodine/pubsub.rb +5 -18
  41. data/lib/iodine/rack_utils.rb +43 -0
  42. data/lib/iodine/version.rb +1 -1
  43. data/lib/rack/handler/iodine.rb +1 -182
  44. metadata +17 -18
  45. data/ext/iodine/iodine_protocol.c +0 -689
  46. data/ext/iodine/iodine_protocol.h +0 -13
  47. data/ext/iodine/iodine_websockets.c +0 -550
  48. data/ext/iodine/iodine_websockets.h +0 -17
  49. data/ext/iodine/rb-call.c +0 -156
  50. data/ext/iodine/rb-call.h +0 -70
  51. data/ext/iodine/rb-defer.c +0 -124
  52. data/ext/iodine/rb-registry.c +0 -150
  53. data/ext/iodine/rb-registry.h +0 -34
  54. data/lib/iodine/cli.rb +0 -89
  55. data/lib/iodine/monkeypatch.rb +0 -46
  56. data/lib/iodine/protocol.rb +0 -42
  57. data/lib/iodine/websocket.rb +0 -16
@@ -1,13 +0,0 @@
1
- #ifndef H_IODINE_PROTOCOL_H
2
- #define H_IODINE_PROTOCOL_H
3
- /*
4
- Copyright: Boaz segev, 2016-2017
5
- License: MIT
6
-
7
- Feel free to copy, use and enjoy according to the license provided.
8
- */
9
- #include "iodine.h"
10
-
11
- void Iodine_init_protocol(void);
12
-
13
- #endif
@@ -1,550 +0,0 @@
1
- /*
2
- Copyright: Boaz segev, 2016-2017
3
- License: MIT
4
-
5
- Feel free to copy, use and enjoy according to the license provided.
6
- */
7
- #include "iodine_websockets.h"
8
- #include "iodine_pubsub.h"
9
-
10
- #include "pubsub.h"
11
- #include "websockets.h"
12
-
13
- #include <arpa/inet.h>
14
- #include <ruby/io.h>
15
-
16
- /* *****************************************************************************
17
- Core helpers and data
18
- ***************************************************************************** */
19
-
20
- static VALUE IodineWebsocket; // The Iodine::Http::Websocket class
21
- static ID ws_var_id; // id for websocket pointer
22
- static ID dup_func_id; // id for the buffer.dup method
23
- static ID iodine_on_ready_id; // id for the on_ready method
24
-
25
- #define set_uuid(object, uuid) \
26
- rb_ivar_set((object), iodine_fd_var_id, ULONG2NUM((uuid)))
27
-
28
- inline static intptr_t get_uuid(VALUE obj) {
29
- VALUE i = rb_ivar_get(obj, iodine_fd_var_id);
30
- return i != Qnil ? (intptr_t)FIX2ULONG(i) : 0;
31
- }
32
-
33
- #define set_ws(object, ws) \
34
- rb_ivar_set((object), ws_var_id, ULONG2NUM(((VALUE)(ws))))
35
-
36
- inline static ws_s *get_ws(VALUE obj) {
37
- VALUE i = rb_ivar_get(obj, ws_var_id);
38
- if (i == Qnil)
39
- return NULL;
40
- return (ws_s *)FIX2ULONG(i);
41
- }
42
-
43
- #define set_handler(ws, handler) websocket_udata_set((ws), (VALUE)handler)
44
- #define get_handler(ws) ((VALUE)websocket_udata((ws_s *)(ws)))
45
-
46
- /* *****************************************************************************
47
- SSE / Websocket Ruby API
48
- ***************************************************************************** */
49
-
50
- /** Closes the websocket connection. The connection is only closed after
51
- * existing data in the outgoing buffer is sent. */
52
- static VALUE iodine_ws_close(VALUE self) {
53
- void *ws = get_ws(self);
54
- if (!ws) {
55
- return Qfalse;
56
- }
57
- iodine_pubsub_type_e c_type = (iodine_pubsub_type_e)iodine_get_cdata(self);
58
- switch (c_type) {
59
- case IODINE_PUBSUB_WEBSOCKET:
60
- /* WebSockets*/
61
- if (((protocol_s *)ws)->service != WEBSOCKET_ID_STR) {
62
- return Qfalse;
63
- }
64
- websocket_close(ws);
65
- break;
66
- case IODINE_PUBSUB_SSE:
67
- /* SSE */
68
- http_sse_close(ws);
69
- break;
70
- case IODINE_PUBSUB_GLOBAL:
71
- /* fallthrough */
72
- default:
73
- return Qfalse;
74
- break;
75
- }
76
- return self;
77
- }
78
-
79
- /**
80
- * Writes data to the websocket.
81
- *
82
- * Returns `true` on success or `false if the websocket was closed or an error
83
- * occurred.
84
- *
85
- * `write` will return immediately, adding the data to the outgoing queue.
86
- *
87
- * If the connection is closed, `write` will raise an exception.
88
- */
89
- static VALUE iodine_ws_write(VALUE self, VALUE data) {
90
- Check_Type(data, T_STRING);
91
- void *ws = get_ws(self);
92
- iodine_pubsub_type_e c_type = (iodine_pubsub_type_e)iodine_get_cdata(self);
93
- if (!ws || !c_type) {
94
- rb_raise(rb_eIOError, "Connection is closed");
95
- return Qfalse;
96
- }
97
- switch (c_type) {
98
- case IODINE_PUBSUB_WEBSOCKET:
99
- /* WebSockets*/
100
- if (((protocol_s *)ws)->service != WEBSOCKET_ID_STR)
101
- goto error;
102
- websocket_write(ws, RSTRING_PTR(data), RSTRING_LEN(data),
103
- rb_enc_get(data) == IodineUTF8Encoding);
104
- return Qtrue;
105
- break;
106
- case IODINE_PUBSUB_SSE:
107
- /* SSE */
108
- http_sse_write(
109
- ws, .data = {.data = RSTRING_PTR(data), .len = RSTRING_LEN(data)});
110
- return Qtrue;
111
- break;
112
- case IODINE_PUBSUB_GLOBAL:
113
- /* fallthrough */
114
- default:
115
- error:
116
- rb_raise(rb_eIOError, "Connection is closed");
117
- return Qfalse;
118
- }
119
- return Qfalse;
120
- }
121
-
122
- /**
123
- Returns the number of pending writes or -1 if the connection is closed
124
- */
125
- static VALUE iodine_ws_has_pending(VALUE self) {
126
- intptr_t uuid = get_uuid(self);
127
- if (!uuid || sock_isclosed(uuid))
128
- return INT2NUM(-1);
129
- return SIZET2NUM(sock_pending(uuid));
130
- }
131
-
132
- /**
133
- Returns true is the connection is open, false if it isn't.
134
- */
135
- static VALUE iodine_ws_is_open(VALUE self) {
136
- intptr_t uuid = get_uuid(self);
137
- if (uuid && sock_isvalid(uuid))
138
- return Qtrue;
139
- return Qfalse;
140
- }
141
-
142
- /** Returns a local (per process) unique identifier for the conection. */
143
- // static VALUE iodine_ws_uuid(VALUE self) {
144
- // intptr_t uuid = get_uuid(self);
145
- // return ULL2NUM(uuid);
146
- // if (uuid && sock_isvalid(uuid))
147
- // return Qtrue;
148
- // return Qfalse;
149
- // }
150
-
151
- /* *****************************************************************************
152
- Websocket defer
153
- ***************************************************************************** */
154
-
155
- static void iodine_perform_defer(intptr_t uuid, protocol_s *protocol,
156
- void *arg) {
157
- (void)(uuid);
158
- VALUE obj = protocol->service == WEBSOCKET_ID_STR ? get_handler(protocol)
159
- : (VALUE)(protocol + 1);
160
- RubyCaller.call2((VALUE)arg, iodine_call_proc_id, 1, &obj);
161
- Registry.remove((VALUE)arg);
162
- }
163
-
164
- static void iodine_defer_fallback(intptr_t uuid, void *arg) {
165
- (void)(uuid);
166
- Registry.remove((VALUE)arg);
167
- }
168
-
169
- /**
170
- Schedules a block of code to execute at a later time, **if** the connection is
171
- still open and while preventing concurent code from running for the same
172
- connection object.
173
-
174
- An optional `conn_id` argument can be passed along, so that the block of code
175
- will run for the requested connection rather then this connection.
176
-
177
- **Careful**: as this might cause this connection's object to run code
178
- concurrently when data owned by this connection is accessed from within the
179
- block of code.
180
-
181
- On success returns the block, otherwise (connection invalid) returns `false`. A
182
- sucessful event registration doesn't guaranty that the block will be called (the
183
- connection might close between the event registration and the execution).
184
- */
185
- static VALUE iodine_defer(int argc, VALUE *argv, VALUE self) {
186
- intptr_t fd;
187
- // check arguments.
188
- if (argc > 1)
189
- rb_raise(rb_eArgError, "this function expects no more then 1 (optional) "
190
- "argument.");
191
- else if (argc == 1) {
192
- Check_Type(*argv, T_FIXNUM);
193
- fd = FIX2LONG(*argv);
194
- if (!sock_isvalid(fd))
195
- return Qfalse;
196
- } else
197
- fd = iodine_get_fd(self);
198
- if (!fd)
199
- rb_raise(rb_eArgError, "This method requires a target connection.");
200
- // requires a block to be passed
201
- rb_need_block();
202
- VALUE block = rb_block_proc();
203
- if (block == Qnil)
204
- return Qfalse;
205
- Registry.add(block);
206
-
207
- facil_defer(.uuid = fd, .task = iodine_perform_defer, .arg = (void *)block,
208
- .fallback = iodine_defer_fallback);
209
- return block;
210
- }
211
-
212
- #if 0 /* deprecated */
213
- /**
214
- Schedules a block of code to run for the specified websocket at a later time,
215
- (**if** the connection is open). The block will run within the connection's
216
- lock, offering a fast concurrency synchronizing tool.
217
-
218
- The block of code will receive the websocket's callback object. i.e.
219
-
220
- Iodine::Websocket.defer(uuid) {|ws| ws.write "I'm doing this" }
221
-
222
- On success returns the block, otherwise (connection invalid) returns `false`.
223
-
224
- A sucessful event registration doesn't guaranty that the block will be called
225
- (the connection might close between the event registration and the execution).
226
- */
227
- static VALUE iodine_class_defer(VALUE self, VALUE ws_uuid) {
228
- (void)(self);
229
- intptr_t fd = FIX2LONG(ws_uuid);
230
- if (!sock_isvalid(fd))
231
- return Qfalse;
232
- // requires a block to be passed
233
- rb_need_block();
234
- VALUE block = rb_block_proc();
235
- if (block == Qnil)
236
- return Qfalse;
237
- Registry.add(block);
238
-
239
- facil_defer(.uuid = fd, .task = iodine_perform_defer, .arg = (void *)block,
240
- .fallback = iodine_defer_fallback);
241
- return block;
242
- }
243
-
244
- #endif
245
-
246
- /* *****************************************************************************
247
- Websocket Pub/Sub API
248
- ***************************************************************************** */
249
-
250
- // clang-format off
251
- /**
252
- Subscribes the connection to a Pub/Sub channel.
253
-
254
- The method accepts 1-2 arguments and an optional block. These are all valid ways
255
- to call the method:
256
-
257
- subscribe("my_stream") {|from, msg| p msg }
258
- subscribe("my_stream", match: :redis) {|from, msg| p msg }
259
- subscribe(to: "my_stream") {|from, msg| p msg }
260
- subscribe to: "my_stream", match: :redis, handler: MyProc
261
-
262
- The first argument must be either a String or a Hash.
263
-
264
- The second, optional, argument must be a Hash (if given).
265
-
266
- The options Hash supports the following possible keys (other keys are ignored,
267
- all keys are Symbols):
268
-
269
- :match :: The channel / subject name matching type to be used. Valid value is: `:redis`. Future versions hope to support `:nats` and `:rabbit` patern matching as well.
270
-
271
- :to :: The channel / subject to subscribe to.
272
-
273
- :as :: valid for WebSocket connections only. can be either `:text` or `:binary`. `:text` is the default transport for pub/sub events.
274
-
275
- Returns an {Iodine::PubSub::Subscription} object that answers to:
276
-
277
- #.close :: closes the connection.
278
-
279
- #.to_s :: returns the subscription's target (stream / channel / subject).
280
-
281
- #.==(str) :: returns true if the string is an exact match for the target (even if the target itself is a pattern).
282
-
283
- */
284
- static VALUE iodine_ws_subscribe(int argc, VALUE *argv, VALUE self) {
285
- // clang-format on
286
- ws_s *owner = get_ws(self);
287
- return iodine_subscribe(argc, argv, owner,
288
- (iodine_pubsub_type_e)iodine_get_cdata(self));
289
- }
290
-
291
- /* *****************************************************************************
292
- WebSocket Callbacks
293
- ***************************************************************************** */
294
-
295
- static void ws_on_open(ws_s *ws) {
296
- VALUE handler = get_handler(ws);
297
- if (!handler)
298
- return;
299
- set_uuid(handler, websocket_uuid(ws));
300
- set_ws(handler, ws);
301
- iodine_set_cdata(handler, (void *)IODINE_PUBSUB_WEBSOCKET);
302
- RubyCaller.call(handler, iodine_on_open_func_id);
303
- }
304
- static void ws_on_close(intptr_t uuid, void *handler_) {
305
- VALUE handler = (VALUE)handler_;
306
- if (!handler) {
307
- fprintf(stderr,
308
- "ERROR: (iodine websockets) Closing a handlerless websocket?!\n");
309
- return;
310
- }
311
- set_ws(handler, NULL);
312
- set_uuid(handler, 0);
313
- iodine_set_cdata(handler, (void *)IODINE_PUBSUB_GLOBAL);
314
- RubyCaller.call(handler, iodine_on_close_func_id);
315
- Registry.remove(handler);
316
- (void)uuid;
317
- }
318
- static void ws_on_shutdown(ws_s *ws) {
319
- VALUE handler = get_handler(ws);
320
- if (!handler)
321
- return;
322
- RubyCaller.call(handler, iodine_on_shutdown_func_id);
323
- }
324
- static void ws_on_ready(ws_s *ws) {
325
- VALUE handler = get_handler(ws);
326
- if (!handler)
327
- return;
328
- RubyCaller.call(handler, iodine_on_drained_func_id);
329
- }
330
-
331
- struct ws_on_data_args_s {
332
- ws_s *ws;
333
- void *data;
334
- size_t length;
335
- uint8_t is_text;
336
- };
337
- static void *ws_on_data_inGIL(void *args_) {
338
- struct ws_on_data_args_s *a = args_;
339
- VALUE handler = get_handler(a->ws);
340
- if (!handler) {
341
- fprintf(stderr, "ERROR: iodine can't find Websocket handler!\n");
342
- return NULL;
343
- }
344
- VALUE buffer = rb_str_new(a->data, a->length);
345
- if (a->is_text)
346
- rb_enc_associate(buffer, IodineUTF8Encoding);
347
- else
348
- rb_enc_associate(buffer, IodineBinaryEncoding);
349
- rb_funcallv(handler, iodine_on_message_func_id, 1, &buffer);
350
- return NULL;
351
- }
352
- static void ws_on_data(ws_s *ws, char *data, size_t length, uint8_t is_text) {
353
- struct ws_on_data_args_s a = {
354
- .ws = ws, .data = data, .length = length, .is_text = is_text};
355
- RubyCaller.call_c(ws_on_data_inGIL, &a);
356
- (void)(data);
357
- }
358
-
359
- //////////////
360
- // Empty callbacks for default implementations.
361
-
362
- /** Please implement your own callback for this event. */
363
- static VALUE empty_func(VALUE self) {
364
- (void)(self);
365
- return Qnil;
366
- }
367
-
368
- /** Please implement your own callback for this event. */
369
- static VALUE empty_func_drained(VALUE self) {
370
- RubyCaller.call(self, iodine_on_ready_id);
371
- (void)(self);
372
- return Qnil;
373
- }
374
-
375
- /** DEPRECATED! Please override {on_drained} instead. */
376
- static VALUE empty_func_on_ready(VALUE self) {
377
- (void)(self);
378
- return Qnil;
379
- }
380
-
381
- /* *****************************************************************************
382
- SSE Callbacks
383
- ***************************************************************************** */
384
-
385
- /**
386
- * The (optional) on_open callback will be called once the EventSource
387
- * connection is established.
388
- */
389
- static void iodine_sse_on_open(http_sse_s *sse) {
390
- VALUE handler = (VALUE)sse->udata;
391
- if (!handler)
392
- return;
393
- set_uuid(handler, http_sse2uuid(sse));
394
- set_ws(handler, sse);
395
- iodine_set_cdata(handler, (void *)IODINE_PUBSUB_SSE);
396
- RubyCaller.call(handler, iodine_on_open_func_id);
397
- }
398
-
399
- /**
400
- * The (optional) on_ready callback will be after a the underlying socket's
401
- * buffer changes it's state to empty.
402
- *
403
- * If the socket's buffer is never used, the callback is never called.
404
- */
405
- static void iodine_sse_on_ready(http_sse_s *sse) {
406
- VALUE handler = (VALUE)sse->udata;
407
- if (!handler)
408
- return;
409
- RubyCaller.call(handler, iodine_on_drained_func_id);
410
- }
411
-
412
- /**
413
- * The (optional) on_shutdown callback will be called if a connection is still
414
- * open while the server is shutting down (called before `on_close`).
415
- */
416
- static void iodine_sse_on_shutdown(http_sse_s *sse) {
417
- VALUE handler = (VALUE)sse->udata;
418
- if (!handler)
419
- return;
420
- RubyCaller.call(handler, iodine_on_shutdown_func_id);
421
- }
422
- /**
423
- * The (optional) on_close callback will be called once a connection is
424
- * terminated or failed to be established.
425
- *
426
- * The `uuid` is the connection's unique ID that can identify the Websocket. A
427
- * value of `uuid == 0` indicates the Websocket connection wasn't established
428
- * (an error occured).
429
- *
430
- * The `udata` is the user data as set during the upgrade or using the
431
- * `websocket_udata_set` function.
432
- */
433
- static void iodine_sse_on_close(http_sse_s *sse) {
434
- VALUE handler = (VALUE)sse->udata;
435
- if (!handler) {
436
- fprintf(stderr,
437
- "ERROR: (iodine websockets) Closing a handlerless websocket?!\n");
438
- return;
439
- }
440
- set_ws(handler, NULL);
441
- set_uuid(handler, 0);
442
- iodine_set_cdata(handler, (void *)IODINE_PUBSUB_GLOBAL);
443
- RubyCaller.call(handler, iodine_on_close_func_id);
444
- Registry.remove(handler);
445
- }
446
-
447
- /* *****************************************************************************
448
- Upgrading
449
- ***************************************************************************** */
450
-
451
- static VALUE iodine_prep_ws_handler(VALUE handler) {
452
- // make sure we have a valid handler, with the Websocket Protocol mixin.
453
- if (handler == Qnil || handler == Qfalse || TYPE(handler) == T_FIXNUM ||
454
- TYPE(handler) == T_STRING || TYPE(handler) == T_SYMBOL)
455
- return Qnil;
456
- if (TYPE(handler) == T_CLASS || TYPE(handler) == T_MODULE) {
457
- // include the Protocol module
458
- rb_include_module(handler, IodineWebsocket);
459
- rb_extend_object(handler, IodineWebsocket);
460
- handler = RubyCaller.call(handler, iodine_new_func_id);
461
- if (handler == Qnil || handler == Qfalse)
462
- return Qnil;
463
- Registry.add(handler);
464
- // check that we created a handler
465
- } else {
466
- Registry.add(handler);
467
- // include the Protocol module in the object's class
468
- VALUE p_class = rb_obj_class(handler);
469
- rb_include_module(p_class, IodineWebsocket);
470
- rb_extend_object(p_class, IodineWebsocket);
471
- }
472
- return handler;
473
- }
474
-
475
- void iodine_upgrade_websocket(http_s *h, VALUE handler) {
476
- // add the handler to the registry
477
- handler = iodine_prep_ws_handler(handler);
478
- if (handler == Qnil)
479
- goto failed;
480
- // send upgrade response and set new protocol
481
- http_upgrade2ws(.http = h, .udata = (void *)handler, .on_close = ws_on_close,
482
- .on_open = ws_on_open, .on_shutdown = ws_on_shutdown,
483
- .on_ready = ws_on_ready, .on_message = ws_on_data);
484
- return;
485
- failed:
486
- http_send_error(h, 400);
487
- return;
488
- }
489
-
490
- void iodine_upgrade_sse(http_s *h, VALUE handler) {
491
- // add the handler to the registry
492
- handler = iodine_prep_ws_handler(handler);
493
- if (handler == Qnil)
494
- goto failed;
495
- // send upgrade response and set new protocol
496
- http_upgrade2sse(h, .udata = (void *)handler, .on_open = iodine_sse_on_open,
497
- .on_ready = iodine_sse_on_ready,
498
- .on_shutdown = iodine_sse_on_shutdown,
499
- .on_close = iodine_sse_on_close);
500
- return;
501
- failed:
502
- http_send_error(h, 400);
503
- return;
504
- }
505
-
506
- /* *****************************************************************************
507
- Initialization
508
- ***************************************************************************** */
509
-
510
- void Iodine_init_websocket(void) {
511
- // get IDs and data that's used often
512
- ws_var_id = rb_intern("iodine_ws_ptr"); // when upgrading
513
- dup_func_id = rb_intern("dup"); // when upgrading
514
- iodine_on_ready_id = rb_intern2("on_ready", 8);
515
-
516
- // the Ruby websockets protocol class.
517
- IodineWebsocket = rb_define_module_under(Iodine, "Websocket");
518
- if (IodineWebsocket == Qfalse)
519
- fprintf(stderr, "WTF?!\n"), exit(-1);
520
- // // callbacks and handlers
521
- rb_define_method(IodineWebsocket, "on_open", empty_func, 0);
522
-
523
- // rb_define_method(IodineWebsocket, "on_message", empty_func_message, 1);
524
-
525
- rb_define_method(IodineWebsocket, "on_shutdown", empty_func, 0);
526
- rb_define_method(IodineWebsocket, "on_close", empty_func, 0);
527
- rb_define_method(IodineWebsocket, "on_drained", empty_func_drained, 0);
528
- rb_define_method(IodineWebsocket, "write", iodine_ws_write, 1);
529
- rb_define_method(IodineWebsocket, "close", iodine_ws_close, 0);
530
-
531
- /// Deprectaed!
532
- rb_define_method(IodineWebsocket, "on_ready", empty_func_on_ready, 0);
533
-
534
- // rb_define_method(IodineWebsocket, "_cid", iodine_ws_uuid, 0);
535
- // rb_define_method(IodineWebsocket, "_sock", iodine_ws_uuid, 0);
536
-
537
- rb_define_method(IodineWebsocket, "pending", iodine_ws_has_pending, 0);
538
- rb_define_method(IodineWebsocket, "open?", iodine_ws_is_open, 0);
539
- rb_define_method(IodineWebsocket, "defer", iodine_defer, -1);
540
-
541
- // rb_define_method(IodineWebsocket, "each", iodine_ws_each, 0);
542
-
543
- rb_define_method(IodineWebsocket, "subscribe", iodine_ws_subscribe, -1);
544
- rb_define_method(IodineWebsocket, "publish", iodine_publish, -1);
545
-
546
- // rb_define_singleton_method(IodineWebsocket, "defer", iodine_class_defer,
547
- // 1);
548
-
549
- rb_define_singleton_method(IodineWebsocket, "publish", iodine_publish, -1);
550
- }