iodine 0.4.11 → 0.4.12

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8def4f63c04685ba532ad67250a13099e9cc2a72
4
- data.tar.gz: 9586665f6508a1fa66d2db4f62bfdd4fb5e20711
3
+ metadata.gz: aca722c23efafe6e1253f5ab4f9cea5157ded7eb
4
+ data.tar.gz: 3cd0891b931b59d0474a8dc0f4acdb67a1775923
5
5
  SHA512:
6
- metadata.gz: b2c1d1a6e6fab1cc794ac8e8148b171fa774a7c7c06055b67ccd6cfbd58da83a005f9abb8b1726e555404fe1baee9031ad73c8d5aa9b7d4660e5e2de87a38102
7
- data.tar.gz: 2126c8d8c4e370b042909b1e0c376bdbddf9d68a128894b1a2040652b96aac2e287714d755cb815b1dc0d2e0d52b50943af4ae40b75b06107c7586bf25d30a08
6
+ metadata.gz: fe7c754d170ec52fe96b77bcd2b18a79586e5d3cd6db4bff5f3ba834e32060b470fb3c5fce9799a9868af7cb832143d396ccc1216691f0a3a17887b06124b72a
7
+ data.tar.gz: '09be0eccb8cf2a065be75bb2ae96c4e4cc9ea79fc29a7864d122d59aa743ec709551fd345dbb6a79f0910685fc061edc8dee1e1c33649cd2992e931e0654eef4'
@@ -13,7 +13,7 @@ Feel free to copy, use and enjoy according to the license provided.
13
13
  #include <errno.h>
14
14
  /* *****************************************************************************
15
15
  Internal Map Array
16
- We avoid the fiobj_ary_s to prevent entanglement
16
+ We avoid the fiobj_ary_s to prevent code entanglement
17
17
  ***************************************************************************** */
18
18
 
19
19
  static inline void fio_map_reset(fio_map_s *map, uintptr_t capa) {
@@ -321,12 +321,18 @@ static VALUE iodine_start(VALUE self) {
321
321
  Debug
322
322
  ***************************************************************************** */
323
323
 
324
+ /** Used for debugging purpuses. Lists GC protected objects */
324
325
  VALUE iodine_print_registry(VALUE self) {
325
326
  Registry.print();
326
327
  return Qnil;
327
328
  (void)self;
328
329
  }
329
330
 
331
+ /* *****************************************************************************
332
+ Library Initialization
333
+ ***************************************************************************** */
334
+
335
+ /** Any patches required by the running environment for consistent behavior */
330
336
  static void patch_env(void) {
331
337
  #ifdef __APPLE__
332
338
  /* patch for dealing with the High Sierra `fork` limitations */
@@ -334,10 +340,6 @@ static void patch_env(void) {
334
340
  #endif
335
341
  }
336
342
 
337
- /* *****************************************************************************
338
- Library Initialization
339
- ***************************************************************************** */
340
-
341
343
  ////////////////////////////////////////////////////////////////////////
342
344
  // Ruby loads the library and invokes the Init_<lib_name> function...
343
345
  //
@@ -194,9 +194,29 @@ Message wrapping
194
194
  // clang-format on
195
195
 
196
196
  #ifdef __BIG_ENDIAN__
197
- /** stub byte swap 64 bit integer */
197
+ /** stub byte swap 64 bit integer from pointer */
198
+ static inline uint64_t netpiswap64(uint8_t *i) {
199
+ uint64_t ret = 0;
200
+ uint8_t *const pret = &ret;
201
+ pret[7] = i[7];
202
+ pret[6] = i[6];
203
+ pret[5] = i[5];
204
+ pret[4] = i[4];
205
+ pret[3] = i[3];
206
+ pret[2] = i[2];
207
+ pret[1] = i[1];
208
+ pret[0] = i[0];
209
+ return ret;
210
+ }
211
+ /** stub byte swap 16 bit integer from pointer */
212
+ static inline uint16_t netpiswap16(uint8_t *i) {
213
+ uint16_t ret = 0;
214
+ uint8_t *const pret = (uint8_t *)&ret;
215
+ pret[1] = i[1];
216
+ pret[0] = i[0];
217
+ return ret;
218
+ }
198
219
  #define netiswap64(i) (i)
199
- /** stub byte swap 16 bit integer */
200
220
  #define netiswap16(i) (i)
201
221
 
202
222
  #else
@@ -209,6 +229,28 @@ Message wrapping
209
229
  (((i)&0xFF000000000000ULL) >> 40) | (((i)&0xFF00000000000000ULL) >> 56))
210
230
  /** byte swap 16 bit integer */
211
231
  #define netiswap16(i) ((((i)&0x00ff) << 8) | (((i)&0xff00) >> 8))
232
+ /** byte swap 64 bit integer from pointer */
233
+ static inline uint64_t netpiswap64(uint8_t *i) {
234
+ uint64_t ret = 0;
235
+ uint8_t *const pret = (uint8_t *)&ret;
236
+ pret[0] = i[7];
237
+ pret[1] = i[6];
238
+ pret[2] = i[5];
239
+ pret[3] = i[4];
240
+ pret[4] = i[3];
241
+ pret[5] = i[2];
242
+ pret[6] = i[1];
243
+ pret[7] = i[0];
244
+ return ret;
245
+ }
246
+ /** byte swap 16 bit integer from pointer */
247
+ static inline uint16_t netpiswap16(uint8_t *i) {
248
+ uint16_t ret = 0;
249
+ uint8_t *const pret = (uint8_t *)&ret;
250
+ pret[0] = i[1];
251
+ pret[1] = i[0];
252
+ return ret;
253
+ }
212
254
 
213
255
  #endif
214
256
 
@@ -260,13 +302,23 @@ static uint64_t websocket_server_wrap(void *target, void *msg, uint64_t len,
260
302
  } else if (len < (1UL << 16)) {
261
303
  /* head is 4 bytes */
262
304
  ((uint8_t *)target)[1] = 126;
263
- ((uint16_t *)target)[1] = netiswap16(len);
305
+ const uint16_t net_len = netiswap16(len);
306
+ ((uint8_t *)target)[2] = ((uint8_t *)(&net_len))[0];
307
+ ((uint8_t *)target)[3] = ((uint8_t *)(&net_len))[1];
264
308
  memcpy((uint8_t *)target + 4, msg, len);
265
309
  return len + 4;
266
310
  }
267
311
  /* Really Long Message */
268
312
  ((uint8_t *)target)[1] = 127;
269
- ((uint64_t *)((uint8_t *)target + 2))[0] = netiswap64(len);
313
+ const uint64_t net_len = netiswap16(len);
314
+ ((uint8_t *)target)[2] = ((uint8_t *)(&net_len))[0];
315
+ ((uint8_t *)target)[3] = ((uint8_t *)(&net_len))[1];
316
+ ((uint8_t *)target)[4] = ((uint8_t *)(&net_len))[2];
317
+ ((uint8_t *)target)[5] = ((uint8_t *)(&net_len))[3];
318
+ ((uint8_t *)target)[6] = ((uint8_t *)(&net_len))[4];
319
+ ((uint8_t *)target)[7] = ((uint8_t *)(&net_len))[5];
320
+ ((uint8_t *)target)[8] = ((uint8_t *)(&net_len))[6];
321
+ ((uint8_t *)target)[9] = ((uint8_t *)(&net_len))[7];
270
322
  memcpy((uint8_t *)target + 10, msg, len);
271
323
  return len + 10;
272
324
  }
@@ -295,23 +347,42 @@ static uint64_t websocket_client_wrap(void *target, void *msg, uint64_t len,
295
347
  /*fin*/ ((last & 1) << 7);
296
348
  if (len < 126) {
297
349
  ((uint8_t *)target)[1] = len | 128;
298
- ((uint32_t *)((uint8_t *)target + 2))[0] = mask;
350
+ ((uint8_t *)target)[2] = ((uint8_t *)(&mask))[0];
351
+ ((uint8_t *)target)[3] = ((uint8_t *)(&mask))[1];
352
+ ((uint8_t *)target)[4] = ((uint8_t *)(&mask))[2];
353
+ ((uint8_t *)target)[5] = ((uint8_t *)(&mask))[3];
299
354
  memcpy(((uint8_t *)target) + 6, msg, len);
300
355
  websocket_xmask((uint8_t *)target + 6, len, mask);
301
356
  return len + 6;
302
357
  } else if (len < (1UL << 16)) {
303
358
  /* head is 4 bytes */
304
359
  ((uint8_t *)target)[1] = 126 | 128;
305
- ((uint16_t *)target)[1] = netiswap16(len);
306
- ((uint32_t *)((uint8_t *)target + 4))[0] = mask;
360
+ const uint16_t net_len = netiswap16(len);
361
+ ((uint8_t *)target)[2] = ((uint8_t *)(&net_len))[0];
362
+ ((uint8_t *)target)[3] = ((uint8_t *)(&net_len))[1];
363
+ ((uint8_t *)target)[4] = ((uint8_t *)(&mask))[0];
364
+ ((uint8_t *)target)[5] = ((uint8_t *)(&mask))[1];
365
+ ((uint8_t *)target)[6] = ((uint8_t *)(&mask))[2];
366
+ ((uint8_t *)target)[7] = ((uint8_t *)(&mask))[3];
307
367
  memcpy((uint8_t *)target + 8, msg, len);
308
368
  websocket_xmask((uint8_t *)target + 8, len, mask);
309
369
  return len + 8;
310
370
  }
311
371
  /* Really Long Message */
312
372
  ((uint8_t *)target)[1] = 255;
313
- ((uint64_t *)((uint8_t *)target + 2))[0] = netiswap64(len);
314
- ((uint32_t *)((uint8_t *)target + 10))[0] = mask;
373
+ const uint64_t net_len = netiswap16(len);
374
+ ((uint8_t *)target)[2] = ((uint8_t *)(&net_len))[0];
375
+ ((uint8_t *)target)[3] = ((uint8_t *)(&net_len))[1];
376
+ ((uint8_t *)target)[4] = ((uint8_t *)(&net_len))[2];
377
+ ((uint8_t *)target)[5] = ((uint8_t *)(&net_len))[3];
378
+ ((uint8_t *)target)[6] = ((uint8_t *)(&net_len))[4];
379
+ ((uint8_t *)target)[7] = ((uint8_t *)(&net_len))[5];
380
+ ((uint8_t *)target)[8] = ((uint8_t *)(&net_len))[6];
381
+ ((uint8_t *)target)[9] = ((uint8_t *)(&net_len))[7];
382
+ ((uint8_t *)target)[10] = ((uint8_t *)(&mask))[0];
383
+ ((uint8_t *)target)[11] = ((uint8_t *)(&mask))[1];
384
+ ((uint8_t *)target)[12] = ((uint8_t *)(&mask))[2];
385
+ ((uint8_t *)target)[13] = ((uint8_t *)(&mask))[3];
315
386
  memcpy((uint8_t *)target + 14, msg, len);
316
387
  websocket_xmask((uint8_t *)target + 14, len, mask);
317
388
  return len + 14;
@@ -331,31 +402,28 @@ Message unwrapping
331
402
  inline static struct websocket_packet_info_s
332
403
  websocket_buffer_peek(void *buffer, uint64_t len) {
333
404
  if (len < 2) {
334
- return (struct websocket_packet_info_s){0, 2, 0};
405
+ return (struct websocket_packet_info_s){0 /* packet */, 2 /* head */,
406
+ 0 /* masked? */};
335
407
  }
336
408
  const uint8_t mask_f = (((uint8_t *)buffer)[1] >> 7) & 1;
337
409
  const uint8_t mask_l = (mask_f << 2);
338
- uint8_t len_indicator = (((uint8_t *)buffer)[1] & 127);
339
- if (len < 126) {
340
- return (struct websocket_packet_info_s){len_indicator,
341
- (uint8_t)(2 + mask_l), mask_f};
342
- }
410
+ uint8_t len_indicator = ((((uint8_t *)buffer)[1]) & 127);
343
411
  switch (len_indicator) {
344
412
  case 126:
345
413
  if (len < 4)
346
414
  return (struct websocket_packet_info_s){0, (uint8_t)(4 + mask_l), mask_f};
347
415
  return (struct websocket_packet_info_s){
348
- (uint64_t)netiswap16(((uint16_t *)buffer)[1]), (uint8_t)(4 + mask_l),
416
+ (uint64_t)netpiswap16(((uint8_t *)buffer) + 2), (uint8_t)(4 + mask_l),
349
417
  mask_f};
350
418
  case 127:
351
419
  if (len < 10)
352
420
  return (struct websocket_packet_info_s){0, (uint8_t)(10 + mask_l),
353
421
  mask_f};
354
422
  return (struct websocket_packet_info_s){
355
- netiswap64(((uint64_t *)((uint8_t *)buffer + 2))[0]),
356
- (uint8_t)(10 + mask_l), mask_f};
423
+ netpiswap64(((uint8_t *)buffer) + 2), (uint8_t)(10 + mask_l), mask_f};
357
424
  default:
358
- return (struct websocket_packet_info_s){0, 0, 0};
425
+ return (struct websocket_packet_info_s){len_indicator,
426
+ (uint8_t)(2 + mask_l), mask_f};
359
427
  }
360
428
  }
361
429
 
@@ -416,13 +484,13 @@ static uint64_t websocket_consume(void *buffer, uint64_t len, void *udata,
416
484
  websocket_on_protocol_error(udata);
417
485
  }
418
486
  /* step forward */
419
- reminder -= info.head_length + info.packet_length;
487
+ reminder = reminder - (info.head_length + info.packet_length);
488
+ if (!reminder)
489
+ return 0;
420
490
  pos += info.head_length + info.packet_length;
421
491
  info = websocket_buffer_peek(pos, reminder);
422
492
  }
423
493
  /* reset buffer state - support pipelining */
424
- if (!reminder)
425
- return 0;
426
494
  memmove(buffer, (uint8_t *)buffer + len - reminder, reminder);
427
495
  return reminder;
428
496
  }
@@ -267,13 +267,12 @@ static void on_data(intptr_t sockfd, protocol_s *ws_) {
267
267
  }
268
268
  }
269
269
 
270
- ssize_t len = sock_read(sockfd, (uint8_t *)ws->buffer.data + ws->length,
271
- ws->buffer.size - ws->length);
270
+ const ssize_t len = sock_read(sockfd, (uint8_t *)ws->buffer.data + ws->length,
271
+ ws->buffer.size - ws->length);
272
272
  if (len <= 0) {
273
273
  return;
274
274
  }
275
- ws->length += len;
276
- ws->length = websocket_consume(ws->buffer.data, ws->length, ws, 1);
275
+ ws->length = websocket_consume(ws->buffer.data, ws->length + len, ws, 1);
277
276
 
278
277
  facil_force_event(sockfd, FIO_EVENT_ON_DATA);
279
278
  }
@@ -57,7 +57,7 @@ require 'iodine/iodine'
57
57
  # * {Iodine.connect} creates a new TCP/IP connection using the specified Protocol.
58
58
  # * {Iodine.listen} listens to new TCP/IP connections using the specified Protocol.
59
59
  # * {Iodine.listen2http} listens to new TCP/IP connections using the buildin HTTP / Websocket Protocol.
60
- # * {Iodine.warmup} warms up and HTTP Rack applications.
60
+ # * {Iodine.warmup} warms up any HTTP Rack applications.
61
61
  # * {Iodine.count} counts the number of connections (including HTTP / Websocket connections).
62
62
  # * {Iodine::Protocol.each} runs a code of block for every connection sharing the process (except HTTP / Websocket connections).
63
63
  # * {Iodine::Websocket.each} runs a code of block for every existing websocket sharing the process.
@@ -74,7 +74,7 @@ require 'iodine/iodine'
74
74
  # * {Iodine.publish} publishes a message to a Pub/Sub channel. The message will be sent to all subscribers - connections, other processes in the cluster and even other machines (when using the {Iodine::PubSub::RedisEngine}).
75
75
  # * {Iodine.default_pubsub=}, {Iodine.default_pubsub} sets or gets the default Pub/Sub {Iodine::PubSub::Engine}. i.e., when set to a new {Iodine::PubSub::RedisEngine} instance, all Pub/Sub method calls will use the Redis engine (unless explicitly requiring a different engine).
76
76
  #
77
- # {Iodine::Websocket} objects have a seperate Pub/Sub implementation that manages the subscription's lifetime to match the connection's lifetime and allows direct client Pub/Sub (forwards the message to the client directly).
77
+ # {Iodine::Websocket} objects have a seperate Pub/Sub implementation that manages the subscription's lifetime to match the connection's lifetime and allows direct client Pub/Sub (forwards the message to the client directly without invoking the Ruby interpreter).
78
78
  #
79
79
  # == Patching Rack
80
80
  #
@@ -149,7 +149,9 @@ module Iodine
149
149
  # Runs the warmup sequence. {warmup} attempts to get every "autoloaded" (lazy loaded)
150
150
  # file to load now instead of waiting for "first access". This allows multi-threaded safety and better memory utilization during forking.
151
151
  #
152
- # Use {warmup} when either {processes} or {threads} are set to more then 1.
152
+ # However, `warmup` might cause undefined behavior and should be avoided when using gems that initiate network / database connections or gems that spawn threads (i.e., ActiveRecord / ActiveCable).
153
+ #
154
+ # Use {warmup} when either {processes} or {threads} are set to more then 1 and gems don't spawn threads or initialize network connections.
153
155
  def self.warmup app
154
156
  # load anything marked with `autoload`, since autoload isn't thread safe nor fork friendly.
155
157
  Iodine.run do
@@ -2,8 +2,9 @@ require 'iodine'
2
2
  require 'rack'
3
3
 
4
4
  module Iodine
5
+ # The Iodine::Base namespace is reserved for internal use and is NOT part of the public API.
5
6
  module Base
6
- # Command line interface
7
+ # Command line interface. The Ruby CLI might be changed in future versions.
7
8
  module CLI
8
9
 
9
10
  def print_help
@@ -1,4 +1,5 @@
1
1
  module Iodine
2
+ # The Iodine::Base namespace is reserved for internal use and is NOT part of the public API.
2
3
  module Base
3
4
  # Iodine does NOT monkey patch automatically at this time.
4
5
  #
@@ -1,9 +1,7 @@
1
1
  module Iodine
2
2
  # Iodine is equiped with an internal pub/sub service that allows improved resource management from a deployment perspective.
3
3
  #
4
- # As described by [Wikipedia](https://en.wikipedia.org/wiki/Publish–subscribe_pattern):
5
- #
6
- # publish–subscribe is a messaging pattern where senders of messages, called publishers, do not program the messages to be sent directly to specific receivers, called subscribers, but instead characterize published messages into classes without knowledge of which subscribers, if any, there may be. Similarly, subscribers express interest in one or more classes and only receive messages that are of interest, without knowledge of which publishers, if any, there are.
4
+ # @note From {https://en.wikipedia.org/wiki/Publish–subscribe_pattern Wikipedia}: publish–subscribe is a messaging pattern where senders of messages, called publishers, do not program the messages to be sent directly to specific receivers, called subscribers, but instead characterize published messages into classes without knowledge of which subscribers, if any, there may be. Similarly, subscribers express interest in one or more classes and only receive messages that are of interest, without knowledge of which publishers, if any, there are.
7
5
  #
8
6
  # The common paradigm, which is implemented by pub/sub services like Redis,
9
7
  # is for a "client" to "subscribe" to one or more "channels". Messages are streamed
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '0.4.11'.freeze
2
+ VERSION = '0.4.12'.freeze
3
3
  end
@@ -135,7 +135,7 @@ module Iodine
135
135
  @app = app
136
136
  end
137
137
  @port = options[:Port].to_s if options[:Port]
138
- @port = options[:Address].to_s if options[:Address]
138
+ @address = options[:Address].to_s if options[:Address]
139
139
 
140
140
  # # provide Websocket features using Rack::Websocket
141
141
  # Rack.send :remove_const, :Websocket if defined?(Rack::Websocket)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iodine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.11
4
+ version: 0.4.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-10-21 00:00:00.000000000 Z
11
+ date: 2017-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack