iodine 0.3.4 → 0.3.5

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: c4de811f5a2734382cc86765e77dcecf4b997fc6
4
- data.tar.gz: 55422a643eab1c3cc0b3b18048521dc0aeac463b
3
+ metadata.gz: 84f989dded41a91d68df5799a63f428dec2dedd9
4
+ data.tar.gz: 7810e73f1f50a5ac9428419d8f17fa6d31aeb8b4
5
5
  SHA512:
6
- metadata.gz: 59195e229155fc2ae56e240767a2707d6936758d4a3cfb999343856a753ffcd93ad2c82922a245f13ef95f32c968edaf49af504b64cc5b3152b6fa94bde4f1f5
7
- data.tar.gz: a875bc77077fcfd0c1ca8d6d4d5fd6c9e53ff5759d578461f343af6ab226b3b26b1b5228765e4c156a37516338f802c1f3207040ac286e775d69b24758af92d2
6
+ metadata.gz: 607d4b9e6956149302d33e4f3b9a097a83ace382be08a7b55a80c86e4f57630c5dc0abcb7668ab69469a6aeb834f68606087d40f10ac5e3d8cc1f1714cd73e2b
7
+ data.tar.gz: 4651ef17299e34d1eb83d7fd673e57340b3ec060c3d0b633918ef6876644624072e02f9c930acec4c1a010a4a5ce4ead2a5aa106d134b9882bbe75a36b0a00d2
@@ -8,6 +8,14 @@ Please notice that this change log contains changes for upcoming releases as wel
8
8
 
9
9
  ***
10
10
 
11
+ #### Change log v.0.3.5
12
+
13
+ **Fix**: (`sock`) Fixed an issue with the `sendfile` implementation on macOS and BSD, where medium to large files wouldn't be sent correctly.
14
+
15
+ **Minor changes**: This release incorporates some more minor changes from the [`facil.io` 0.4.2 update](https://github.com/boazsegev/facil.io/releases/tag/v.0.4.2).
16
+
17
+ ***
18
+
11
19
  #### Change log v.0.3.4
12
20
 
13
21
  **Fix**: (`sock`, `facil`, bscrypt) Add missing `static` keywords to prevent state collisions with other libraries.
@@ -83,6 +83,9 @@ end
83
83
  # ab -n 1000000 -c 2000 -k http://127.0.0.1:3000/
84
84
  # wrk -c400 -d5 -t12 http://localhost:3000/
85
85
  #
86
+ # ab -n 1000000 -c 2000 -r http://127.0.0.1:3000/
87
+ # wrk -c400 -d5 -t12 -H"Connection: close" http://localhost:3000/
88
+ #
86
89
  # def cycle
87
90
  # puts `wrk -c4000 -d5 -t12 http://localhost:3000/`
88
91
  # sleep(2)
@@ -255,11 +255,19 @@ struct ListenerProtocol {
255
255
  protocol_s protocol;
256
256
  protocol_s *(*on_open)(intptr_t uuid, void *udata);
257
257
  void *udata;
258
+ void *rw_udata;
259
+ sock_rw_hook_s *(*set_rw_hooks)(intptr_t uuid, void *udata);
258
260
  void (*on_start)(void *udata);
259
261
  void (*on_finish)(void *udata);
260
262
  const char *port;
261
263
  };
262
264
 
265
+ static sock_rw_hook_s *listener_set_rw_hooks(intptr_t uuid, void *udata) {
266
+ (void)udata;
267
+ (void)uuid;
268
+ return NULL; /* (sock_rw_hook_s *)&SOCK_DEFAULT_HOOKS; */
269
+ }
270
+
263
271
  static void listener_ping(intptr_t uuid, protocol_s *plistener) {
264
272
  // fprintf(stderr, "*** Listener Ping Called for %ld\n", sock_uuid2fd(uuid));
265
273
  uuid_data(uuid).active = facil_data->last_cycle;
@@ -274,15 +282,22 @@ static void listener_deferred_on_open(void *uuid_, void *srv_uuid_) {
274
282
  (struct ListenerProtocol *)protocol_try_lock(sock_uuid2fd(srv_uuid),
275
283
  FIO_PR_LOCK_WRITE);
276
284
  if (!listener) {
277
- if (errno != EBADF)
285
+ if (sock_isvalid(uuid) && sock_isvalid(srv_uuid))
278
286
  defer(listener_deferred_on_open, uuid_, srv_uuid_);
287
+ else
288
+ sock_close(uuid);
279
289
  return;
280
290
  }
291
+ {
292
+ sock_rw_hook_s *hooks = listener->set_rw_hooks(uuid, listener->rw_udata);
293
+ if (hooks)
294
+ sock_rw_hook_set(uuid, hooks);
295
+ }
281
296
  protocol_s *pr = listener->on_open(uuid, listener->udata);
297
+ protocol_unlock((protocol_s *)listener, FIO_PR_LOCK_WRITE);
282
298
  facil_attach(uuid, pr);
283
299
  if (!pr)
284
300
  sock_close(uuid);
285
- protocol_unlock((protocol_s *)listener, FIO_PR_LOCK_WRITE);
286
301
  }
287
302
 
288
303
  static void listener_on_data(intptr_t uuid, protocol_s *plistener) {
@@ -323,6 +338,8 @@ listener_alloc(struct facil_listen_args settings) {
323
338
  settings.on_start = (void (*)(void *))mock_on_close;
324
339
  if (!settings.on_finish)
325
340
  settings.on_finish = (void (*)(void *))mock_on_close;
341
+ if (!settings.set_rw_hooks)
342
+ settings.set_rw_hooks = listener_set_rw_hooks;
326
343
  struct ListenerProtocol *listener = malloc(sizeof(*listener));
327
344
  if (listener) {
328
345
  *listener = (struct ListenerProtocol){
@@ -334,6 +351,8 @@ listener_alloc(struct facil_listen_args settings) {
334
351
  .udata = settings.udata,
335
352
  .on_start = settings.on_start,
336
353
  .on_finish = settings.on_finish,
354
+ .set_rw_hooks = settings.set_rw_hooks,
355
+ .rw_udata = settings.rw_udata,
337
356
  .port = settings.port,
338
357
  };
339
358
  return listener;
@@ -391,21 +410,26 @@ struct ConnectProtocol {
391
410
  protocol_s protocol;
392
411
  protocol_s *(*on_connect)(intptr_t uuid, void *udata);
393
412
  void (*on_fail)(void *udata);
413
+ sock_rw_hook_s *(*set_rw_hooks)(intptr_t uuid, void *udata);
394
414
  void *udata;
415
+ void *rw_udata;
395
416
  int opened;
396
417
  };
397
418
 
398
419
  static void connector_on_ready(intptr_t uuid, protocol_s *_connector) {
399
420
  struct ConnectProtocol *connector = (void *)_connector;
400
- connector->opened = 1;
401
421
  // fprintf(stderr, "connector_on_ready called\n");
402
- if (connector->on_connect) {
403
- sock_touch(uuid);
404
- if (facil_attach(uuid, connector->on_connect(uuid, connector->udata)) == -1)
405
- goto error;
406
- uuid_data(uuid).protocol->on_ready(uuid, uuid_data(uuid).protocol);
407
- return;
422
+ if (!connector->opened) {
423
+ sock_rw_hook_s *hooks = connector->set_rw_hooks(uuid, connector->rw_udata);
424
+ if (hooks)
425
+ sock_rw_hook_set(uuid, hooks);
408
426
  }
427
+ connector->opened = 1;
428
+ sock_touch(uuid);
429
+ if (facil_attach(uuid, connector->on_connect(uuid, connector->udata)) == -1)
430
+ goto error;
431
+ uuid_data(uuid).protocol->on_ready(uuid, uuid_data(uuid).protocol);
432
+ return;
409
433
  error:
410
434
  sock_close(uuid);
411
435
  }
@@ -426,6 +450,8 @@ static void connector_on_close(protocol_s *pconnector) {
426
450
  intptr_t facil_connect(struct facil_connect_args opt) {
427
451
  if (!opt.address || !opt.port || !opt.on_connect)
428
452
  return -1;
453
+ if (!opt.set_rw_hooks)
454
+ opt.set_rw_hooks = listener_set_rw_hooks;
429
455
  if (!facil_data->last_cycle)
430
456
  time(&facil_data->last_cycle);
431
457
  struct ConnectProtocol *connector = malloc(sizeof(*connector));
@@ -437,6 +463,8 @@ intptr_t facil_connect(struct facil_connect_args opt) {
437
463
  .protocol.on_data = connector_on_data,
438
464
  .protocol.on_ready = connector_on_ready,
439
465
  .protocol.on_close = connector_on_close,
466
+ .set_rw_hooks = opt.set_rw_hooks,
467
+ .rw_udata = opt.rw_udata,
440
468
  .opened = 0,
441
469
  };
442
470
  if (!connector)
@@ -656,6 +684,7 @@ static void facil_cleanup(void *arg) {
656
684
  facil_cycle(arg, NULL);
657
685
  ((struct facil_run_args *)arg)->on_finish();
658
686
  defer_perform();
687
+ evio_close();
659
688
  }
660
689
 
661
690
  #undef facil_run
@@ -15,7 +15,7 @@ extern "C" {
15
15
  #define H_FACIL_H
16
16
  #define FACIL_VERSION_MAJOR 0
17
17
  #define FACIL_VERSION_MINOR 4
18
- #define FACIL_VERSION_PATCH 1
18
+ #define FACIL_VERSION_PATCH 2
19
19
 
20
20
  #ifndef FACIL_PRINT_STATE
21
21
  /**
@@ -154,8 +154,8 @@ int main() {
154
154
  struct facil_listen_args {
155
155
  /**
156
156
  * Called whenever a new connection is accepted.
157
- * Should return a pointer to
158
- * the connection's protocol. */
157
+ * Should return a pointer to the connection's protocol
158
+ */
159
159
  protocol_s *(*on_open)(intptr_t fduuid, void *udata);
160
160
  /** The network service / port. Defaults to "3000". */
161
161
  const char *port;
@@ -163,6 +163,16 @@ struct facil_listen_args {
163
163
  const char *address;
164
164
  /** Opaque user data. */
165
165
  void *udata;
166
+ /** Opaque user data for `set_rw_hooks`. */
167
+ void *rw_udata;
168
+ /** (optional)
169
+ * Called before `on_open`, allowing Read/Write hook initialization.
170
+ * Should return a pointer to the new RW hooks or NULL (to use default hooks).
171
+ *
172
+ * This allows a seperation between the transport layer (i.e. TLS) and the
173
+ * protocol (i.e. HTTP).
174
+ */
175
+ sock_rw_hook_s *(*set_rw_hooks)(intptr_t fduuid, void *rw_udata);
166
176
  /**
167
177
  * Called when the server starts, allowing for further initialization, such as
168
178
  * timed event scheduling.
@@ -210,6 +220,16 @@ struct facil_connect_args {
210
220
  void (*on_fail)(void *udata);
211
221
  /** Opaque user data. */
212
222
  void *udata;
223
+ /** Opaque user data for `set_rw_hooks`. */
224
+ void *rw_udata;
225
+ /** (optional)
226
+ * Called before `on_connect`, allowing Read/Write hook initialization.
227
+ * Should return a pointer to the new RW hooks or NULL (to use default hooks).
228
+ *
229
+ * This allows a seperation between the transport layer (i.e. TLS) and the
230
+ * protocol (i.e. HTTP).
231
+ */
232
+ sock_rw_hook_s *(*set_rw_hooks)(intptr_t fduuid, void *udata);
213
233
  };
214
234
 
215
235
  /**
@@ -88,6 +88,8 @@ int http_listen(const char *port, const char *address,
88
88
  }
89
89
 
90
90
  return facil_listen(.port = port, .address = address,
91
+ .set_rw_hooks = arg_settings.set_rw_hooks,
92
+ .rw_udata = arg_settings.rw_udata,
91
93
  .on_finish = http_on_finish, .on_open = on_open_callback,
92
94
  .udata = settings);
93
95
  }
@@ -74,6 +74,13 @@ typedef struct {
74
74
  The length of the public_folder string.
75
75
  */
76
76
  size_t public_folder_length;
77
+ /** (optional)
78
+ * Allows a an implementation for the transport layer (i.e. TLS) without
79
+ * effecting the HTTP protocol.
80
+ */
81
+ sock_rw_hook_s *(*set_rw_hooks)(intptr_t fduuid, void *rw_udata);
82
+ /** Opaque user data for `set_rw_hooks`. */
83
+ void *rw_udata;
77
84
  /**
78
85
  Logging flag - set to TRUE to log static file requests.
79
86
 
@@ -200,7 +200,7 @@ static ssize_t sock_default_hooks_flush(intptr_t uuid) {
200
200
  return (((void)(uuid)), 0);
201
201
  }
202
202
 
203
- static sock_rw_hook_s sock_default_hooks = {
203
+ const sock_rw_hook_s SOCK_DEFAULT_HOOKS = {
204
204
  .read = sock_default_hooks_read,
205
205
  .write = sock_default_hooks_write,
206
206
  .flush = sock_default_hooks_flush,
@@ -271,10 +271,11 @@ static inline int initialize_sock_lib(size_t capacity) {
271
271
  if (new_collection) {
272
272
  sock_data_store.fds = new_collection;
273
273
  for (size_t i = sock_data_store.capacity; i < capacity; i++) {
274
- fdinfo(i) = (struct fd_data_s){.open = 0,
275
- .lock = SPN_LOCK_INIT,
276
- .rw_hooks = &sock_default_hooks,
277
- .counter = 0};
274
+ fdinfo(i) =
275
+ (struct fd_data_s){.open = 0,
276
+ .lock = SPN_LOCK_INIT,
277
+ .rw_hooks = (sock_rw_hook_s *)&SOCK_DEFAULT_HOOKS,
278
+ .counter = 0};
278
279
  }
279
280
  sock_data_store.capacity = capacity;
280
281
 
@@ -313,7 +314,7 @@ clear:
313
314
  sock_data_store.fds[fd] =
314
315
  (struct fd_data_s){.open = is_open,
315
316
  .lock = fdinfo(fd).lock,
316
- .rw_hooks = &sock_default_hooks,
317
+ .rw_hooks = (sock_rw_hook_s *)&SOCK_DEFAULT_HOOKS,
317
318
  .counter = fdinfo(fd).counter + 1};
318
319
  spn_unlock(&(fdinfo(fd).lock));
319
320
  packet = old_data.packet;
@@ -324,7 +325,7 @@ clear:
324
325
  }
325
326
  old_data.rw_hooks->on_close(((fd << 8) | old_data.counter),
326
327
  old_data.rw_hooks);
327
- if (old_data.open || (old_data.rw_hooks != &sock_default_hooks)) {
328
+ if (old_data.open || (old_data.rw_hooks != &SOCK_DEFAULT_HOOKS)) {
328
329
  sock_on_close((fd << 8) | old_data.counter);
329
330
  evio_remove((fd << 8) | old_data.counter);
330
331
  }
@@ -455,25 +456,57 @@ static int sock_sendfile_from_fd(int fd, struct packet_s *packet) {
455
456
  static int sock_sendfile_from_fd(int fd, struct packet_s *packet) {
456
457
  struct sock_packet_file_data_s *ext = (void *)packet->buffer.buf;
457
458
  off_t act_sent = 0;
458
- ssize_t count = 0;
459
- do {
460
- fdinfo(fd).sent += act_sent;
461
- packet->buffer.len -= act_sent;
459
+ ssize_t ret = 0;
460
+ while (packet->buffer.len) {
462
461
  act_sent = packet->buffer.len;
463
462
  #if defined(__APPLE__)
464
- count = sendfile(ext->fd, fd, ext->offset + fdinfo(fd).sent, &act_sent,
465
- NULL, 0);
463
+ ret = sendfile(ext->fd, fd, ext->offset + fdinfo(fd).sent, &act_sent, NULL,
464
+ 0);
466
465
  #else
467
- count = sendfile(ext->fd, fd, ext->offset + fdinfo(fd).sent,
468
- (size_t)act_sent, NULL, &act_sent, 0);
466
+ ret = sendfile(ext->fd, fd, ext->offset + fdinfo(fd).sent, (size_t)act_sent,
467
+ NULL, &act_sent, 0);
469
468
  #endif
470
- } while (count >= 0 && packet->buffer.len > (size_t)act_sent);
471
- if (count < 0)
472
- return -1;
469
+ if (ret < 0)
470
+ goto error;
471
+ fdinfo(fd).sent += act_sent;
472
+ packet->buffer.len -= act_sent;
473
+ }
473
474
  sock_packet_rotate_unsafe(fd);
474
475
  return act_sent;
476
+ error:
477
+ if (errno == EAGAIN) {
478
+ fdinfo(fd).sent += act_sent;
479
+ packet->buffer.len -= act_sent;
480
+ }
481
+ return -1;
475
482
  }
476
483
 
484
+ // static int sock_sendfile_from_fd(int fd, struct packet_s *packet) {
485
+ // struct sock_packet_file_data_s *ext = (void *)packet->buffer.buf;
486
+ // off_t act_sent = 0;
487
+ // ssize_t count = 0;
488
+ // do {
489
+ // fdinfo(fd).sent += act_sent;
490
+ // packet->buffer.len -= act_sent;
491
+ // act_sent = packet->buffer.len;
492
+ // #if defined(__APPLE__)
493
+ // count = sendfile(ext->fd, fd, ext->offset + fdinfo(fd).sent, &act_sent,
494
+ // NULL, 0);
495
+ // #else
496
+ // count = sendfile(ext->fd, fd, ext->offset + fdinfo(fd).sent,
497
+ // (size_t)act_sent, NULL, &act_sent, 0);
498
+ // #endif
499
+ // } while (count >= 0 && packet->buffer.len > (size_t)act_sent);
500
+ // if (!act_sent) {
501
+ // fprintf(stderr, "Rotating after sent == %lu and length == %lu\n",
502
+ // (size_t)act_sent, packet->buffer.len);
503
+ // sock_packet_rotate_unsafe(fd);
504
+ // }
505
+ // if (count < 0)
506
+ // return -1;
507
+ // return act_sent;
508
+ // }
509
+
477
510
  #else
478
511
  static int (*sock_sendfile_from_fd)(int fd, struct packet_s *packet) =
479
512
  sock_write_from_fd;
@@ -891,7 +924,7 @@ ssize_t sock_write2_fn(sock_write_info_s options) {
891
924
  ext->offset = options.offset;
892
925
  packet->metadata = (struct packet_metadata_s){
893
926
  .write_func =
894
- (fdinfo(sock_uuid2fd(options.uuid)).rw_hooks == &sock_default_hooks
927
+ (fdinfo(sock_uuid2fd(options.uuid)).rw_hooks == &SOCK_DEFAULT_HOOKS
895
928
  ? sock_sendfile_from_fd
896
929
  : sock_write_from_fd),
897
930
  .free_func = options.move ? sock_close_from_fd
@@ -1046,7 +1079,8 @@ ssize_t sock_buffer_send(intptr_t uuid, sock_buffer_s *buffer) {
1046
1079
  return -1;
1047
1080
  }
1048
1081
  packet_s **tmp, *packet = (packet_s *)((uintptr_t)(buffer) -
1049
- sizeof(struct packet_metadata_s));
1082
+ (uintptr_t)(&((packet_s *)0)->buffer));
1083
+ // (packet_s *)((uintptr_t)(buffer) - sizeof(struct packet_metadata_s));
1050
1084
  packet->metadata = (struct packet_metadata_s){
1051
1085
  .write_func = sock_write_buffer,
1052
1086
  .free_func = (void (*)(packet_s *))SOCK_DEALLOC_NOOP};
@@ -1075,7 +1109,8 @@ Use `sock_buffer_free` to free unused buffers that were checked-out using
1075
1109
  */
1076
1110
  void sock_buffer_free(sock_buffer_s *buffer) {
1077
1111
  packet_s *packet =
1078
- (packet_s *)((uintptr_t)(buffer) - sizeof(struct packet_metadata_s));
1112
+ (packet_s *)((uintptr_t)(buffer) - (uintptr_t)(&((packet_s *)0)->buffer));
1113
+ // (packet_s *)((uintptr_t)(buffer) - sizeof(struct packet_metadata_s));
1079
1114
  sock_packet_free(packet);
1080
1115
  }
1081
1116
 
@@ -1089,7 +1124,7 @@ Experimental
1089
1124
  struct sock_rw_hook_s *sock_rw_hook_get(intptr_t uuid) {
1090
1125
  if (validate_uuid(uuid) || !fdinfo(sock_uuid2fd(uuid)).open ||
1091
1126
  ((uuid = sock_uuid2fd(uuid)),
1092
- fdinfo(uuid).rw_hooks == &sock_default_hooks))
1127
+ fdinfo(uuid).rw_hooks == &SOCK_DEFAULT_HOOKS))
1093
1128
  return NULL;
1094
1129
  return fdinfo(uuid).rw_hooks;
1095
1130
  }
@@ -1107,7 +1142,7 @@ int sock_rw_hook_set(intptr_t uuid, sock_rw_hook_s *rw_hooks) {
1107
1142
  if (!rw_hooks->on_close)
1108
1143
  rw_hooks->on_close = sock_default_hooks_on_close;
1109
1144
  uuid = sock_uuid2fd(uuid);
1110
- lock_fd(sock_uuid2fd(uuid));
1145
+ lock_fd(uuid);
1111
1146
  fdinfo(uuid).rw_hooks = rw_hooks;
1112
1147
  unlock_fd(uuid);
1113
1148
  return 0;
@@ -474,6 +474,9 @@ struct sock_rw_hook_s *sock_rw_hook_get(intptr_t fduuid);
474
474
  /** Sets a socket hook state (a pointer to the struct). */
475
475
  int sock_rw_hook_set(intptr_t fduuid, sock_rw_hook_s *rw_hooks);
476
476
 
477
+ /** The default Read/Write hooks used for system Read/Write */
478
+ extern const sock_rw_hook_s SOCK_DEFAULT_HOOKS;
479
+
477
480
  /* *****************************************************************************
478
481
  test
479
482
  */
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '0.3.4'.freeze
2
+ VERSION = '0.3.5'.freeze
3
3
  end
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.3.4
4
+ version: 0.3.5
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-05-29 00:00:00.000000000 Z
11
+ date: 2017-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack