iodine 0.7.43 → 0.7.46

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.
@@ -98,6 +98,7 @@ int http_send_error2(size_t error, intptr_t uuid, http_settings_s *settings) {
98
98
  return -1;
99
99
  fio_protocol_s *pr = http1_new(uuid, settings, NULL, 0);
100
100
  http_s *r = fio_malloc(sizeof(*r));
101
+ FIO_ASSERT_ALLOC(r);
101
102
  FIO_ASSERT(pr, "Couldn't allocate response object for error report.")
102
103
  http_s_new(r, (http_fio_protocol_s *)pr, http1_vtable());
103
104
  int ret = http_send_error(r, error);
@@ -15,7 +15,9 @@ Feel free to copy, use and enjoy according to the license provided.
15
15
 
16
16
  #include <http.h>
17
17
 
18
+ #ifndef __MINGW32__
18
19
  #include <arpa/inet.h>
20
+ #endif
19
21
  #include <errno.h>
20
22
 
21
23
  /* *****************************************************************************
@@ -121,8 +123,8 @@ static inline void http_s_destroy(http_s *h, uint8_t log) {
121
123
  fiobj_free(h->params);
122
124
 
123
125
  *h = (http_s){
124
- .private_data.vtbl = h->private_data.vtbl,
125
- .private_data.flag = h->private_data.flag,
126
+ .private_data.vtbl = h->private_data.vtbl,
127
+ .private_data.flag = h->private_data.flag,
126
128
  };
127
129
  }
128
130
 
data/ext/iodine/iodine.c CHANGED
@@ -413,7 +413,7 @@ static VALUE iodine_cli_parse(VALUE self) {
413
413
  FIO_CLI_PRINT_HEADER("WebSocket Settings:"),
414
414
  FIO_CLI_INT("-max-msg -maxms incoming WebSocket message limit in Kb. "
415
415
  "Default: 250Kb"),
416
- FIO_CLI_INT("-ping websocket ping interval (0..255). Default: 40s"),
416
+ FIO_CLI_INT("-ping websocket ping interval (1..255). Default: 40s"),
417
417
  FIO_CLI_PRINT_HEADER("SSL/TLS:"),
418
418
  FIO_CLI_BOOL("-tls enable SSL/TLS using a self-signed certificate."),
419
419
  FIO_CLI_STRING(
@@ -519,6 +519,7 @@ static VALUE iodine_cli_parse(VALUE self) {
519
519
  rb_hash_aset(defaults, max_headers_sym,
520
520
  INT2NUM((fio_cli_get_i("-maxhd") /* * 1024 */)));
521
521
  }
522
+ #ifndef __MINGW32__
522
523
  if (fio_cli_get_bool("-tls") || fio_cli_get("-key") || fio_cli_get("-cert")) {
523
524
  VALUE rbtls = IodineCaller.call(IodineTLSClass, rb_intern2("new", 3));
524
525
  if (rbtls == Qnil) {
@@ -543,6 +544,7 @@ static VALUE iodine_cli_parse(VALUE self) {
543
544
  }
544
545
  rb_hash_aset(defaults, tls_sym, rbtls);
545
546
  }
547
+ #endif
546
548
  if (fio_cli_unnamed_count()) {
547
549
  rb_hash_aset(defaults, ID2SYM(rb_intern("filename_")),
548
550
  rb_str_new_cstr(fio_cli_unnamed(0)));
@@ -634,8 +636,10 @@ FIO_FUNC void iodine_connect_args_cleanup(iodine_connection_args_s *s) {
634
636
  fio_free(s->port.data);
635
637
  if (s->address.capa)
636
638
  fio_free(s->address.data);
639
+ #ifndef __MINGW32__
637
640
  if (s->tls)
638
641
  fio_tls_destroy(s->tls);
642
+ #endif
639
643
  }
640
644
 
641
645
  /*
@@ -686,7 +690,9 @@ FIO_FUNC iodine_connection_args_s iodine_connect_args(VALUE s, uint8_t is_srv) {
686
690
  VALUE r_public = rb_hash_aref(s, public_sym);
687
691
  VALUE service = rb_hash_aref(s, service_sym);
688
692
  VALUE timeout = rb_hash_aref(s, timeout_sym);
693
+ #ifndef __MINGW32__
689
694
  VALUE tls = rb_hash_aref(s, tls_sym);
695
+ #endif
690
696
  VALUE r_url = rb_hash_aref(s, url_sym);
691
697
  fio_str_info_s service_str = {.data = NULL};
692
698
 
@@ -726,8 +732,10 @@ FIO_FUNC iodine_connection_args_s iodine_connect_args(VALUE s, uint8_t is_srv) {
726
732
  // service = rb_hash_aref(iodine_default_args, service_sym);
727
733
  if (timeout == Qnil)
728
734
  timeout = rb_hash_aref(iodine_default_args, timeout_sym);
735
+ #ifndef __MINGW32__
729
736
  if (tls == Qnil)
730
737
  tls = rb_hash_aref(iodine_default_args, tls_sym);
738
+ #endif
731
739
 
732
740
  /* TODO: deprecation */
733
741
  if (handler == Qnil) {
@@ -824,11 +832,13 @@ FIO_FUNC iodine_connection_args_s iodine_connect_args(VALUE s, uint8_t is_srv) {
824
832
  else
825
833
  r.timeout = FIX2ULONG(timeout);
826
834
  }
835
+ #ifndef __MINGW32__
827
836
  if (tls != Qnil) {
828
837
  r.tls = iodine_tls2c(tls);
829
838
  if (r.tls)
830
839
  fio_tls_dup(r.tls);
831
840
  }
841
+ #endif
832
842
  /* URL parsing */
833
843
  if (r_url != Qnil && RB_TYPE_P(r_url, T_STRING)) {
834
844
  r.url = IODINE_RSTRINFO(r_url);
@@ -888,6 +898,56 @@ FIO_FUNC iodine_connection_args_s iodine_connect_args(VALUE s, uint8_t is_srv) {
888
898
  /* test/set service type */
889
899
  r.service = IODINE_SERVICE_RAW;
890
900
  if (service_str.data) {
901
+ #ifdef __MINGW32__
902
+ switch (service_str.data[0]) {
903
+ case 't': /* overflow */
904
+ /* tcp or tls */
905
+ if (service_str.data[1] == 'l') {
906
+ char *local = NULL;
907
+ char buf[1024];
908
+ buf[1023] = 0;
909
+ if (is_srv) {
910
+ local = buf;
911
+ if (fio_local_addr(buf, 1023) >= 1022)
912
+ local = NULL;
913
+ }
914
+ }
915
+ /* overflow */
916
+ case 'u': /* overflow */
917
+ /* unix */
918
+ case 'r':
919
+ /* raw */
920
+ r.service = IODINE_SERVICE_RAW;
921
+ break;
922
+ case 'h':
923
+ /* http(s) */
924
+ r.service = IODINE_SERVICE_HTTP;
925
+ if (service_str.len == 5) {
926
+ char *local = NULL;
927
+ char buf[1024];
928
+ buf[1023] = 0;
929
+ if (is_srv) {
930
+ local = buf;
931
+ if (fio_local_addr(buf, 1023) >= 1022)
932
+ local = NULL;
933
+ }
934
+ }
935
+ case 'w':
936
+ /* ws(s) */
937
+ r.service = IODINE_SERVICE_WS;
938
+ if (service_str.len == 3) {
939
+ char *local = NULL;
940
+ char buf[1024];
941
+ buf[1023] = 0;
942
+ if (is_srv) {
943
+ local = buf;
944
+ if (fio_local_addr(buf, 1023) >= 1022)
945
+ local = NULL;
946
+ }
947
+ }
948
+ break;
949
+ }
950
+ #else
891
951
  switch (service_str.data[0]) {
892
952
  case 't': /* overflow */
893
953
  /* tcp or tls */
@@ -939,6 +999,7 @@ FIO_FUNC iodine_connection_args_s iodine_connect_args(VALUE s, uint8_t is_srv) {
939
999
  }
940
1000
  break;
941
1001
  }
1002
+ #endif
942
1003
  }
943
1004
  return r;
944
1005
  }
@@ -1349,8 +1410,10 @@ void Init_iodine(void) {
1349
1410
  // initialize the HTTP module
1350
1411
  iodine_init_http();
1351
1412
 
1413
+ #ifndef __MINGW32__
1352
1414
  // initialize SSL/TLS support module
1353
1415
  iodine_init_tls();
1416
+ #endif
1354
1417
 
1355
1418
  // initialize JSON helpers
1356
1419
  iodine_init_json();
data/ext/iodine/iodine.h CHANGED
@@ -15,7 +15,9 @@ typedef struct {
15
15
  fio_str_info_s body;
16
16
  fio_str_info_s public;
17
17
  fio_str_info_s url;
18
+ #ifndef __MINGW32__
18
19
  fio_tls_s *tls;
20
+ #endif
19
21
  VALUE handler;
20
22
  FIOBJ headers;
21
23
  FIOBJ cookies;
@@ -5,7 +5,19 @@
5
5
 
6
6
  #include <fio.h>
7
7
 
8
- static __thread volatile uint8_t iodine_GVL_state = 1;
8
+ #include <pthread.h>
9
+
10
+ static pthread_key_t iodine_GVL_state_key;
11
+ static pthread_once_t iodine_GVL_state_once = PTHREAD_ONCE_INIT;
12
+ static void init_iodine_GVL_state_key(void) {
13
+ pthread_key_create(&iodine_GVL_state_key, NULL);
14
+ }
15
+ static void init_iodine_GVL_state_init(void) {
16
+ uint8_t *gvl = malloc(sizeof(uint8_t));
17
+ FIO_ASSERT_ALLOC(gvl);
18
+ *gvl = 1;
19
+ pthread_setspecific(iodine_GVL_state_key, gvl);
20
+ }
9
21
 
10
22
  /* *****************************************************************************
11
23
  Calling protected Ruby methods
@@ -84,25 +96,37 @@ API
84
96
 
85
97
  /** Calls a C function within the GVL. */
86
98
  static void *iodine_enterGVL(void *(*func)(void *), void *arg) {
87
- if (iodine_GVL_state) {
99
+ pthread_once(&iodine_GVL_state_once, init_iodine_GVL_state_key);
100
+ uint8_t *iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
101
+ if (!iodine_GVL_state) {
102
+ init_iodine_GVL_state_init();
103
+ iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
104
+ }
105
+ if (*iodine_GVL_state) {
88
106
  return func(arg);
89
107
  }
90
108
  void *rv = NULL;
91
- iodine_GVL_state = 1;
109
+ *iodine_GVL_state = 1;
92
110
  rv = rb_thread_call_with_gvl(func, arg);
93
- iodine_GVL_state = 0;
111
+ *iodine_GVL_state = 0;
94
112
  return rv;
95
113
  }
96
114
 
97
115
  /** Calls a C function outside the GVL. */
98
116
  static void *iodine_leaveGVL(void *(*func)(void *), void *arg) {
117
+ pthread_once(&iodine_GVL_state_once, init_iodine_GVL_state_key);
118
+ uint8_t *iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
99
119
  if (!iodine_GVL_state) {
120
+ init_iodine_GVL_state_init();
121
+ iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
122
+ }
123
+ if (!*iodine_GVL_state) {
100
124
  return func(arg);
101
125
  }
102
126
  void *rv = NULL;
103
- iodine_GVL_state = 0;
127
+ *iodine_GVL_state = 0;
104
128
  rv = rb_thread_call_without_gvl(func, arg, NULL, NULL);
105
- iodine_GVL_state = 1;
129
+ *iodine_GVL_state = 1;
106
130
  return rv;
107
131
  }
108
132
 
@@ -151,10 +175,26 @@ static VALUE iodine_call_block(VALUE obj, ID method, int argc, VALUE *argv,
151
175
  }
152
176
 
153
177
  /** Returns the GVL state flag. */
154
- static uint8_t iodine_in_GVL(void) { return iodine_GVL_state; }
178
+ static uint8_t iodine_in_GVL(void) {
179
+ pthread_once(&iodine_GVL_state_once, init_iodine_GVL_state_key);
180
+ uint8_t *iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
181
+ if (!iodine_GVL_state) {
182
+ init_iodine_GVL_state_init();
183
+ iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
184
+ }
185
+ return *iodine_GVL_state;
186
+ }
155
187
 
156
188
  /** Forces the GVL state flag. */
157
- static void iodine_set_GVL(uint8_t state) { iodine_GVL_state = state; }
189
+ static void iodine_set_GVL(uint8_t state) {
190
+ pthread_once(&iodine_GVL_state_once, init_iodine_GVL_state_key);
191
+ uint8_t *iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
192
+ if (!iodine_GVL_state) {
193
+ init_iodine_GVL_state_init();
194
+ iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
195
+ }
196
+ *iodine_GVL_state = state;
197
+ }
158
198
 
159
199
  /* *****************************************************************************
160
200
  Caller Initialization
@@ -403,8 +403,12 @@ static void *iodine_on_pubsub_call_block(void *msg_) {
403
403
  fio_msg_s *msg = msg_;
404
404
  VALUE args[2];
405
405
  args[0] = rb_str_new(msg->channel.data, msg->channel.len);
406
+ IodineStore.add(args[0]);
406
407
  args[1] = rb_str_new(msg->msg.data, msg->msg.len);
408
+ IodineStore.add(args[1]);
407
409
  IodineCaller.call2((VALUE)msg->udata2, call_id, 2, args);
410
+ IodineStore.remove(args[1]);
411
+ IodineStore.remove(args[0]);
408
412
  return NULL;
409
413
  }
410
414
 
@@ -12,11 +12,15 @@ Feel free to copy, use and enjoy according to the license provided.
12
12
  #include <ruby/io.h>
13
13
  // #include "iodine_websockets.h"
14
14
 
15
+ #ifndef __MINGW32__
15
16
  #include <arpa/inet.h>
17
+ #endif
16
18
  #include <ctype.h>
17
19
  #include <stdlib.h>
18
20
  #include <string.h>
21
+ #ifndef __MINGW32__
19
22
  #include <sys/socket.h>
23
+ #endif
20
24
 
21
25
  /* *****************************************************************************
22
26
  Available Globals
@@ -555,9 +559,11 @@ static inline int ruby2c_response_send(iodine_http_request_handle_s *handle,
555
559
 
556
560
  if (TYPE(body) == T_STRING) {
557
561
  // fprintf(stderr, "Review body as String\n");
558
- if (RSTRING_LEN(body))
562
+ handle->type = IODINE_HTTP_NONE;
563
+ if (RSTRING_LEN(body)) {
559
564
  handle->body = fiobj_str_new(RSTRING_PTR(body), RSTRING_LEN(body));
560
- handle->type = IODINE_HTTP_SENDBODY;
565
+ handle->type = IODINE_HTTP_SENDBODY;
566
+ }
561
567
  return 0;
562
568
  } else if (rb_respond_to(body, each_method_id)) {
563
569
  // fprintf(stderr, "Review body as for-each ...\n");
@@ -936,6 +942,15 @@ intptr_t iodine_http_listen(iodine_connection_args_s args){
936
942
  support_xsendfile = 1;
937
943
  }
938
944
  IodineStore.add(args.handler);
945
+ #ifdef __MINGW32__
946
+ intptr_t uuid = http_listen(
947
+ args.port.data, args.address.data, .on_request = on_rack_request,
948
+ .on_upgrade = on_rack_upgrade, .udata = (void *)args.handler,
949
+ .timeout = args.timeout, .ws_timeout = args.ping,
950
+ .ws_max_msg_size = args.max_msg, .max_header_size = args.max_headers,
951
+ .on_finish = free_iodine_http, .log = args.log,
952
+ .max_body_size = args.max_body, .public_folder = args.public.data);
953
+ #else
939
954
  intptr_t uuid = http_listen(
940
955
  args.port.data, args.address.data, .on_request = on_rack_request,
941
956
  .on_upgrade = on_rack_upgrade, .udata = (void *)args.handler,
@@ -943,6 +958,7 @@ intptr_t iodine_http_listen(iodine_connection_args_s args){
943
958
  .ws_max_msg_size = args.max_msg, .max_header_size = args.max_headers,
944
959
  .on_finish = free_iodine_http, .log = args.log,
945
960
  .max_body_size = args.max_body, .public_folder = args.public.data);
961
+ #endif
946
962
  if (uuid == -1)
947
963
  return uuid;
948
964
 
@@ -1052,9 +1068,11 @@ intptr_t iodine_ws_connect(iodine_connection_args_s args) {
1052
1068
  FIOBJ url_tmp = FIOBJ_INVALID;
1053
1069
  if (!args.url.data) {
1054
1070
  url_tmp = fiobj_str_buf(64);
1071
+ #ifndef __MINGW32__
1055
1072
  if (args.tls)
1056
1073
  fiobj_str_write(url_tmp, "wss://", 6);
1057
1074
  else
1075
+ #endif
1058
1076
  fiobj_str_write(url_tmp, "ws://", 5);
1059
1077
  if (!is_unix_socket) {
1060
1078
  fiobj_str_write(url_tmp, args.address.data, args.address.len);
@@ -1070,11 +1088,19 @@ intptr_t iodine_ws_connect(iodine_connection_args_s args) {
1070
1088
  args.url = fiobj_obj2cstr(url_tmp);
1071
1089
  }
1072
1090
 
1091
+ #ifdef __MINGW32__
1092
+ intptr_t uuid = http_connect(
1093
+ args.url.data, (is_unix_socket ? args.address.data : NULL),
1094
+ .udata = request_data_create(&args),
1095
+ .on_response = ws_client_http_connected,
1096
+ .on_finish = ws_client_http_connection_finished);
1097
+ #else
1073
1098
  intptr_t uuid = http_connect(
1074
1099
  args.url.data, (is_unix_socket ? args.address.data : NULL),
1075
1100
  .udata = request_data_create(&args),
1076
1101
  .on_response = ws_client_http_connected,
1077
1102
  .on_finish = ws_client_http_connection_finished, .tls = args.tls);
1103
+ #endif
1078
1104
  fiobj_free(url_tmp);
1079
1105
  return uuid;
1080
1106
  }
@@ -61,6 +61,9 @@ static VALUE TCPSOCKET_CLASS;
61
61
  static ID for_fd_id;
62
62
  static ID iodine_fd_var_id;
63
63
  static ID iodine_new_func_id;
64
+ #ifdef __MINGW32__
65
+ static ID iodine_osffd_id;
66
+ #endif
64
67
  static rb_encoding *IodineUTF8Encoding;
65
68
  static rb_encoding *IodineBinaryEncoding;
66
69
 
@@ -69,7 +72,7 @@ static rb_encoding *IodineBinaryEncoding;
69
72
 
70
73
  inline static http_s *get_handle(VALUE obj) {
71
74
  VALUE i = rb_ivar_get(obj, iodine_fd_var_id);
72
- return (http_s *)FIX2ULONG(i);
75
+ return (http_s *)NUM2ULL(i);
73
76
  }
74
77
 
75
78
  /* *****************************************************************************
@@ -78,7 +81,7 @@ IO API
78
81
 
79
82
  static inline FIOBJ get_data(VALUE self) {
80
83
  VALUE i = rb_ivar_get(self, io_id);
81
- return (FIOBJ)FIX2ULONG(i);
84
+ return (FIOBJ)NUM2ULL(i);
82
85
  }
83
86
 
84
87
  static VALUE rio_rewind(VALUE self) {
@@ -196,7 +199,14 @@ static VALUE rio_get_io(int argc, VALUE *argv, VALUE self) {
196
199
  set_handle(self, NULL);
197
200
  // hijack the IO object
198
201
  intptr_t uuid = http_hijack(h, NULL);
202
+ #ifdef __MINGW32__
203
+ int osffd = fio_osffd4fd(fio_uuid2fd(uuid));
204
+ if (osffd == -1)
205
+ return Qfalse;
206
+ VALUE fd = INT2FIX(osffd);
207
+ #else
199
208
  VALUE fd = INT2FIX(fio_uuid2fd(uuid));
209
+ #endif
200
210
  // VALUE new_io = how the fuck do we create a new IO from the fd?
201
211
  VALUE new_io = IodineCaller.call2(TCPSOCKET_CLASS, for_fd_id, 1,
202
212
  &fd); // TCPSocket.for_fd(fd) ... cool...
@@ -238,6 +248,9 @@ static void init_rack_io(void) {
238
248
  for_fd_id = rb_intern("for_fd");
239
249
  iodine_fd_var_id = rb_intern("fd");
240
250
  iodine_new_func_id = rb_intern("new");
251
+ #ifdef __MINGW32__
252
+ iodine_osffd_id = rb_intern("osffd");
253
+ #endif
241
254
  hijack_func_sym = ID2SYM(rb_intern("_hijack"));
242
255
 
243
256
  TCPSOCKET_CLASS = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
@@ -209,10 +209,17 @@ Returns the handler object used.
209
209
  intptr_t iodine_tcp_listen(iodine_connection_args_s args) {
210
210
  // clang-format on
211
211
  IodineStore.add(args.handler);
212
+ #ifdef __MINGW32__
213
+ return fio_listen(.port = args.port.data, .address = args.address.data,
214
+ .on_open = iodine_tcp_on_open,
215
+ .on_finish = iodine_tcp_on_finish,
216
+ .udata = (void *)args.handler);
217
+ #else
212
218
  return fio_listen(.port = args.port.data, .address = args.address.data,
213
219
  .on_open = iodine_tcp_on_open,
214
220
  .on_finish = iodine_tcp_on_finish, .tls = args.tls,
215
221
  .udata = (void *)args.handler);
222
+ #endif
216
223
  }
217
224
 
218
225
  // clang-format off
@@ -238,10 +245,17 @@ Returns the handler object used.
238
245
  intptr_t iodine_tcp_connect(iodine_connection_args_s args){
239
246
  // clang-format on
240
247
  IodineStore.add(args.handler);
248
+ #ifdef __MINGW32__
249
+ return fio_connect(.port = args.port.data, .address = args.address.data,
250
+ .on_connect = iodine_tcp_on_connect,
251
+ .on_fail = iodine_tcp_on_fail, .timeout = args.ping,
252
+ .udata = (void *)args.handler);
253
+ #else
241
254
  return fio_connect(.port = args.port.data, .address = args.address.data,
242
255
  .on_connect = iodine_tcp_on_connect, .tls = args.tls,
243
256
  .on_fail = iodine_tcp_on_fail, .timeout = args.ping,
244
257
  .udata = (void *)args.handler);
258
+ #endif
245
259
  }
246
260
 
247
261
  // clang-format off
@@ -1,3 +1,10 @@
1
+ #ifdef __MINGW32__
2
+ // make pedantic compiler happy
3
+ typedef struct {
4
+ int bogus;
5
+ } bogus_s;
6
+
7
+ #else
1
8
  #include <ruby.h>
2
9
 
3
10
  #include <fio.h>
@@ -251,3 +258,4 @@ void iodine_init_tls(void) {
251
258
  #endif
252
259
  }
253
260
  #undef IODINE_MAKE_SYM
261
+ #endif
@@ -28,6 +28,10 @@ Feel free to copy, use and enjoy according to the license provided.
28
28
  #include <sys/stat.h>
29
29
  #include <sys/types.h>
30
30
 
31
+ #ifdef __MINGW32__
32
+ ssize_t pread(int, void*, size_t, off_t);
33
+ #endif
34
+
31
35
  #if !defined(__GNUC__) && !defined(__clang__) && !defined(FIO_GNUC_BYPASS)
32
36
  #define __attribute__(...)
33
37
  #define __has_include(...) 0
@@ -493,6 +493,7 @@ static void redis_pub_ping(intptr_t uuid, fio_protocol_s *pr) {
493
493
  return;
494
494
  }
495
495
  redis_commands_s *cmd = fio_malloc(sizeof(*cmd) + 15);
496
+ FIO_ASSERT_ALLOC(cmd);
496
497
  *cmd = (redis_commands_s){.cmd_len = 14};
497
498
  memcpy(cmd->cmd, "*1\r\n$4\r\nPING\r\n\0", 15);
498
499
  redis_attach_cmd(r, cmd);
@@ -534,6 +535,7 @@ static void redis_on_connect(intptr_t uuid, void *i_) {
534
535
  r = pub2redis(i);
535
536
  if (r->auth_len) {
536
537
  redis_commands_s *cmd = fio_malloc(sizeof(*cmd) + r->auth_len);
538
+ FIO_ASSERT_ALLOC(cmd);
537
539
  *cmd =
538
540
  (redis_commands_s){.cmd_len = r->auth_len, .callback = redis_on_auth};
539
541
  memcpy(cmd->cmd, r->auth, r->auth_len);
@@ -638,6 +640,7 @@ static void redis_on_publish_root(const fio_pubsub_engine_s *eng,
638
640
  uint8_t is_json) {
639
641
  redis_engine_s *r = (redis_engine_s *)eng;
640
642
  redis_commands_s *cmd = fio_malloc(sizeof(*cmd) + channel.len + msg.len + 96);
643
+ FIO_ASSERT_ALLOC(cmd);
641
644
  *cmd = (redis_commands_s){.cmd_len = 0};
642
645
  memcpy(cmd->cmd, "*3\r\n$7\r\nPUBLISH\r\n$", 18);
643
646
  char *buf = (char *)cmd->cmd + 18;
@@ -684,7 +687,7 @@ static void redis_on_publish_child(const fio_pubsub_engine_s *eng,
684
687
  fio_str_s tmp = FIO_STR_INIT;
685
688
  /* by using fio_str_s, short names are allocated on the stack */
686
689
  fio_str_info_s tmp_info = fio_str_resize(&tmp, channel.len + 8);
687
- fio_u2str64(tmp_info.data, (uint64_t)eng);
690
+ fio_u2str64(tmp_info.data, (uintptr_t)eng);
688
691
  memcpy(tmp_info.data + 8, channel.data, channel.len);
689
692
  /* forward publication request to Root */
690
693
  fio_publish(.filter = -1, .channel = tmp_info, .message = msg,
@@ -701,7 +704,7 @@ Root Publication Handler
701
704
  static void redis_on_internal_publish(fio_msg_s *msg) {
702
705
  if (msg->channel.len < 8)
703
706
  return; /* internal error, unexpected data */
704
- void *en = (void *)fio_str2u64(msg->channel.data);
707
+ void *en = (void *)(uintptr_t)fio_str2u64(msg->channel.data);
705
708
  if (en != msg->udata1)
706
709
  return; /* should be delivered by a different engine */
707
710
  /* step after the engine data */
@@ -721,8 +724,8 @@ Sending commands using the Root connection
721
724
  static void redis_forward_reply(fio_pubsub_engine_s *e, FIOBJ reply,
722
725
  void *udata) {
723
726
  uint8_t *data = udata;
724
- fio_pubsub_engine_s *engine = (fio_pubsub_engine_s *)fio_str2u64(data + 0);
725
- void *callback = (void *)fio_str2u64(data + 8);
727
+ fio_pubsub_engine_s *engine = (fio_pubsub_engine_s *)(uintptr_t)fio_str2u64(data + 0);
728
+ void *callback = (void *)(uintptr_t)fio_str2u64(data + 8);
726
729
  if (engine != e || !callback) {
727
730
  FIO_LOG_DEBUG("Redis reply not forwarded (callback: %p)", callback);
728
731
  return;
@@ -738,7 +741,7 @@ static void redis_forward_reply(fio_pubsub_engine_s *e, FIOBJ reply,
738
741
  static void redis_on_internal_cmd(fio_msg_s *msg) {
739
742
  // void*(void *)fio_str2u64(msg->msg.data);
740
743
  fio_pubsub_engine_s *engine =
741
- (fio_pubsub_engine_s *)fio_str2u64(msg->channel.data + 0);
744
+ (fio_pubsub_engine_s *)(uintptr_t)fio_str2u64(msg->channel.data + 0);
742
745
  if (engine != msg->udata1) {
743
746
  return;
744
747
  }
@@ -756,7 +759,7 @@ static void redis_on_internal_cmd(fio_msg_s *msg) {
756
759
  /* Listens on filter `-10 -getpid()` for incoming reply data */
757
760
  static void redis_on_internal_reply(fio_msg_s *msg) {
758
761
  fio_pubsub_engine_s *engine =
759
- (fio_pubsub_engine_s *)fio_str2u64(msg->channel.data + 0);
762
+ (fio_pubsub_engine_s *)(uintptr_t)fio_str2u64(msg->channel.data + 0);
760
763
  if (engine != msg->udata1) {
761
764
  FIO_LOG_DEBUG("Redis reply not forwarded (engine mismatch: %p != %p)",
762
765
  (void *)engine, msg->udata1);
@@ -765,8 +768,8 @@ static void redis_on_internal_reply(fio_msg_s *msg) {
765
768
  FIOBJ reply;
766
769
  fiobj_json2obj(&reply, msg->msg.data, msg->msg.len);
767
770
  void (*callback)(fio_pubsub_engine_s *, FIOBJ, void *) = (void (*)(
768
- fio_pubsub_engine_s *, FIOBJ, void *))fio_str2u64(msg->channel.data + 8);
769
- void *udata = (void *)fio_str2u64(msg->channel.data + 16);
771
+ fio_pubsub_engine_s *, FIOBJ, void *))(uintptr_t)fio_str2u64(msg->channel.data + 8);
772
+ void *udata = (void *)(uintptr_t)fio_str2u64(msg->channel.data + 16);
770
773
  callback(engine, reply, udata);
771
774
  fiobj_free(reply);
772
775
  }
@@ -788,9 +791,9 @@ intptr_t redis_engine_send(fio_pubsub_engine_s *engine, FIOBJ command,
788
791
  fio_str_s tmp = FIO_STR_INIT;
789
792
  fio_str_info_s ti = fio_str_resize(&tmp, 28);
790
793
  /* combine metadata */
791
- fio_u2str64(ti.data + 0, (uint64_t)engine);
792
- fio_u2str64(ti.data + 8, (uint64_t)callback);
793
- fio_u2str64(ti.data + 16, (uint64_t)udata);
794
+ fio_u2str64(ti.data + 0, (uintptr_t)engine);
795
+ fio_u2str64(ti.data + 8, (uintptr_t)callback);
796
+ fio_u2str64(ti.data + 16, (uintptr_t)udata);
794
797
  fio_u2str32(ti.data + 24, (uint32_t)getpid());
795
798
  FIOBJ cmd = fiobj2resp_tmp(command);
796
799
  fio_publish(.filter = -2, .channel = ti, .message = fiobj_obj2cstr(cmd),
@@ -17,7 +17,9 @@ Feel free to copy, use and enjoy according to the license provided.
17
17
  #include <http.h>
18
18
  #include <http_internal.h>
19
19
 
20
+ #ifndef __MINGW32__
20
21
  #include <arpa/inet.h>
22
+ #endif
21
23
  #include <errno.h>
22
24
  #include <stdio.h>
23
25
  #include <stdlib.h>
@@ -26,7 +28,7 @@ Feel free to copy, use and enjoy according to the license provided.
26
28
 
27
29
  #include <websocket_parser.h>
28
30
 
29
- #if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
31
+ #if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) && !defined(__MINGW32__)
30
32
  #include <endian.h>
31
33
  #if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) && \
32
34
  __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
@@ -71,6 +73,7 @@ struct buffer_s create_ws_buffer(ws_s *owner) {
71
73
  struct buffer_s buff;
72
74
  buff.size = WS_INITIAL_BUFFER_SIZE;
73
75
  buff.data = malloc(buff.size);
76
+ FIO_ASSERT_ALLOC(buff.data);
74
77
  return buff;
75
78
  }
76
79
 
@@ -79,7 +82,6 @@ struct buffer_s resize_ws_buffer(ws_s *owner, struct buffer_s buff) {
79
82
  void *tmp = realloc(buff.data, buff.size);
80
83
  if (!tmp) {
81
84
  free_ws_buffer(owner, buff);
82
- buff.data = NULL;
83
85
  buff.size = 0;
84
86
  }
85
87
  buff.data = tmp;
@@ -174,6 +176,7 @@ static void websocket_on_protocol_ping(void *ws_p, void *msg_, uint64_t len) {
174
176
  ws_s *ws = ws_p;
175
177
  if (msg_) {
176
178
  void *buff = malloc(len + 16);
179
+ FIO_ASSERT_ALLOC(buff);
177
180
  len = (((ws_s *)ws)->is_client
178
181
  ? websocket_client_wrap(buff, msg_, len, 10, 1, 1, 0)
179
182
  : websocket_server_wrap(buff, msg_, len, 10, 1, 1, 0));
@@ -305,6 +308,7 @@ Create/Destroy the websocket object
305
308
  static ws_s *new_websocket(intptr_t uuid) {
306
309
  // allocate the protocol object
307
310
  ws_s *ws = malloc(sizeof(*ws));
311
+ FIO_ASSERT_ALLOC(ws);
308
312
  *ws = (ws_s){
309
313
  .protocol.ping = ws_ping,
310
314
  .protocol.on_data = on_data_first,
@@ -330,7 +334,6 @@ static void destroy_ws(ws_s *ws) {
330
334
  void websocket_attach(intptr_t uuid, http_settings_s *http_settings,
331
335
  websocket_settings_s *args, void *data, size_t length) {
332
336
  ws_s *ws = new_websocket(uuid);
333
- FIO_ASSERT_ALLOC(ws);
334
337
  // we have an active websocket connection - prep the connection buffer
335
338
  ws->buffer = create_ws_buffer(ws);
336
339
  // Setup ws callbacks
@@ -383,6 +386,7 @@ static void websocket_write_impl(intptr_t fd, void *data, size_t len, char text,
383
386
  char first, char last, char client) {
384
387
  if (len <= WS_MAX_FRAME_SIZE) {
385
388
  void *buff = fio_malloc(len + 16);
389
+ FIO_ASSERT_ALLOC(buff);
386
390
  len = (client ? websocket_client_wrap(buff, data, len, (text ? 1 : 2),
387
391
  first, last, 0)
388
392
  : websocket_server_wrap(buff, data, len, (text ? 1 : 2),
data/iodine.gemspec CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['Boaz Segev']
10
10
  spec.email = ['bo@plezi.io']
11
11
 
12
- spec.summary = 'iodine - a fast HTTP / Websocket Server with Pub/Sub support, optimized for Ruby MRI on Linux / BSD'
13
- spec.description = 'A fast HTTP / Websocket Server with built-in Pub/Sub support (with or without Redis), static file support and many other features, optimized for Ruby MRI on Linux / BSD / macOS'
12
+ spec.summary = 'iodine - a fast HTTP / Websocket Server with Pub/Sub support, optimized for Ruby MRI on Linux / BSD / Windows'
13
+ spec.description = 'A fast HTTP / Websocket Server with built-in Pub/Sub support (with or without Redis), static file support and many other features, optimized for Ruby MRI on Linux / BSD / macOS / Windows'
14
14
  spec.homepage = 'https://github.com/boazsegev/iodine'
15
15
  spec.license = 'MIT'
16
16
 
@@ -35,10 +35,11 @@ Gem::Specification.new do |spec|
35
35
  spec.requirements << 'An updated C compiler.'
36
36
  spec.requirements << 'Ruby >= 2.3.8 (Ruby EOL).'
37
37
  spec.requirements << 'Ruby >= 2.5.0 recommended.'
38
- spec.requirements << 'TLS requires OpenSSL >= 1.1.0'
38
+ spec.requirements << 'TLS requires OpenSSL >= 1.1.0.'
39
+ spec.requirements << 'Or Windows with Ruby >= 3.0.0 build with MingW and MingW as compiler.'
39
40
 
40
41
  # spec.add_development_dependency 'bundler', '>= 1.10', '< 2.0'
41
- spec.add_development_dependency 'rake', '~> 12.0', '< 13.0'
42
+ spec.add_development_dependency 'rake', '>= 12.0', '< 14.0'
42
43
  spec.add_development_dependency 'minitest', '>=5', '< 6.0'
43
44
  spec.add_development_dependency 'rspec', '>=3.9.0', '< 4.0'
44
45
  spec.add_development_dependency 'spec', '>=5.3.0', '< 6.0'
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '0.7.43'.freeze
2
+ VERSION = '0.7.46'.freeze
3
3
  end