iodine 0.7.44 → 0.7.47

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -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
@@ -365,7 +369,6 @@ static inline VALUE copy2env(iodine_http_request_handle_s *handle) {
365
369
  if (*pos == 0) {
366
370
  rb_hash_aset(env, SERVER_NAME,
367
371
  rb_enc_str_new(tmp.data, tmp.len, IodineBinaryEncoding));
368
- rb_hash_aset(env, SERVER_PORT, QUERY_ESTRING);
369
372
  } else {
370
373
  rb_hash_aset(
371
374
  env, SERVER_NAME,
@@ -865,7 +868,6 @@ static void initialize_env_template(void) {
865
868
  rb_hash_aset(env_template_no_upgrade, REMOTE_ADDR, QUERY_STRING);
866
869
  rb_hash_aset(env_template_no_upgrade, REQUEST_METHOD, QUERY_STRING);
867
870
  rb_hash_aset(env_template_no_upgrade, SERVER_NAME, QUERY_STRING);
868
- rb_hash_aset(env_template_no_upgrade, SERVER_PORT, QUERY_ESTRING);
869
871
  rb_hash_aset(env_template_no_upgrade, SERVER_PROTOCOL, QUERY_STRING);
870
872
 
871
873
  /* WebSocket upgrade support */
@@ -938,6 +940,15 @@ intptr_t iodine_http_listen(iodine_connection_args_s args){
938
940
  support_xsendfile = 1;
939
941
  }
940
942
  IodineStore.add(args.handler);
943
+ #ifdef __MINGW32__
944
+ intptr_t uuid = http_listen(
945
+ args.port.data, args.address.data, .on_request = on_rack_request,
946
+ .on_upgrade = on_rack_upgrade, .udata = (void *)args.handler,
947
+ .timeout = args.timeout, .ws_timeout = args.ping,
948
+ .ws_max_msg_size = args.max_msg, .max_header_size = args.max_headers,
949
+ .on_finish = free_iodine_http, .log = args.log,
950
+ .max_body_size = args.max_body, .public_folder = args.public.data);
951
+ #else
941
952
  intptr_t uuid = http_listen(
942
953
  args.port.data, args.address.data, .on_request = on_rack_request,
943
954
  .on_upgrade = on_rack_upgrade, .udata = (void *)args.handler,
@@ -945,6 +956,7 @@ intptr_t iodine_http_listen(iodine_connection_args_s args){
945
956
  .ws_max_msg_size = args.max_msg, .max_header_size = args.max_headers,
946
957
  .on_finish = free_iodine_http, .log = args.log,
947
958
  .max_body_size = args.max_body, .public_folder = args.public.data);
959
+ #endif
948
960
  if (uuid == -1)
949
961
  return uuid;
950
962
 
@@ -1054,9 +1066,11 @@ intptr_t iodine_ws_connect(iodine_connection_args_s args) {
1054
1066
  FIOBJ url_tmp = FIOBJ_INVALID;
1055
1067
  if (!args.url.data) {
1056
1068
  url_tmp = fiobj_str_buf(64);
1069
+ #ifndef __MINGW32__
1057
1070
  if (args.tls)
1058
1071
  fiobj_str_write(url_tmp, "wss://", 6);
1059
1072
  else
1073
+ #endif
1060
1074
  fiobj_str_write(url_tmp, "ws://", 5);
1061
1075
  if (!is_unix_socket) {
1062
1076
  fiobj_str_write(url_tmp, args.address.data, args.address.len);
@@ -1072,11 +1086,19 @@ intptr_t iodine_ws_connect(iodine_connection_args_s args) {
1072
1086
  args.url = fiobj_obj2cstr(url_tmp);
1073
1087
  }
1074
1088
 
1089
+ #ifdef __MINGW32__
1090
+ intptr_t uuid = http_connect(
1091
+ args.url.data, (is_unix_socket ? args.address.data : NULL),
1092
+ .udata = request_data_create(&args),
1093
+ .on_response = ws_client_http_connected,
1094
+ .on_finish = ws_client_http_connection_finished);
1095
+ #else
1075
1096
  intptr_t uuid = http_connect(
1076
1097
  args.url.data, (is_unix_socket ? args.address.data : NULL),
1077
1098
  .udata = request_data_create(&args),
1078
1099
  .on_response = ws_client_http_connected,
1079
1100
  .on_finish = ws_client_http_connection_finished, .tls = args.tls);
1101
+ #endif
1080
1102
  fiobj_free(url_tmp);
1081
1103
  return uuid;
1082
1104
  }
@@ -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.44'.freeze
2
+ VERSION = '0.7.47'.freeze
3
3
  end