iodine 0.7.44 → 0.7.45

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.
data/ext/iodine/http.c CHANGED
@@ -18,6 +18,8 @@ Feel free to copy, use and enjoy according to the license provided.
18
18
  #include <sys/types.h>
19
19
  #include <unistd.h>
20
20
 
21
+ #include <pthread.h>
22
+
21
23
  #ifndef HAVE_TM_TM_ZONE
22
24
  #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
23
25
  defined(__DragonFly__) || defined(__bsdi__) || defined(__ultrix) || \
@@ -33,6 +35,7 @@ Feel free to copy, use and enjoy according to the license provided.
33
35
  #endif
34
36
  #endif
35
37
 
38
+ #ifndef __MINGW32__
36
39
  /* *****************************************************************************
37
40
  SSL/TLS patch
38
41
  ***************************************************************************** */
@@ -56,6 +59,7 @@ fio_tls_alpn_add(void *tls, const char *protocol_name,
56
59
  (void)udata_tls;
57
60
  }
58
61
  #pragma weak fio_tls_alpn_add
62
+ #endif
59
63
 
60
64
  /* *****************************************************************************
61
65
  Small Helpers
@@ -95,6 +99,7 @@ static inline void add_date(http_s *r) {
95
99
  if (fio_last_tick().tv_sec > last_date_added) {
96
100
  fio_lock(&date_lock);
97
101
  if (fio_last_tick().tv_sec > last_date_added) { /* retest inside lock */
102
+ /* 32 chars are ok for a while, but http_time2str below has a buffer sized 48 chars and does a memcpy ... */
98
103
  FIOBJ tmp = fiobj_str_buf(32);
99
104
  FIOBJ old = current_date;
100
105
  fiobj_str_resize(
@@ -764,6 +769,7 @@ void http_pause(http_s *h, void (*task)(http_pause_handle_s *http)) {
764
769
  http_fio_protocol_s *p = (http_fio_protocol_s *)h->private_data.flag;
765
770
  http_vtable_s *vtbl = (http_vtable_s *)h->private_data.vtbl;
766
771
  http_pause_handle_s *http = fio_malloc(sizeof(*http));
772
+ FIO_ASSERT_ALLOC(http);
767
773
  *http = (http_pause_handle_s){
768
774
  .uuid = p->uuid,
769
775
  .h = h,
@@ -845,6 +851,7 @@ static http_settings_s *http_settings_new(http_settings_s arg_settings) {
845
851
  char *home = getenv("HOME");
846
852
  size_t home_len = strlen(home);
847
853
  char *tmp = malloc(settings->public_folder_length + home_len + 1);
854
+ FIO_ASSERT_ALLOC(tmp);
848
855
  memcpy(tmp, home, home_len);
849
856
  if (home[home_len - 1] == '/')
850
857
  --home_len;
@@ -854,6 +861,7 @@ static http_settings_s *http_settings_new(http_settings_s arg_settings) {
854
861
  settings->public_folder_length = strlen(settings->public_folder);
855
862
  } else {
856
863
  settings->public_folder = malloc(settings->public_folder_length + 1);
864
+ FIO_ASSERT_ALLOC(settings->public_folder);
857
865
  memcpy((void *)settings->public_folder, arg_settings.public_folder,
858
866
  settings->public_folder_length);
859
867
  ((uint8_t *)settings->public_folder)[settings->public_folder_length] = 0;
@@ -880,7 +888,7 @@ static void http_on_server_protocol_http1(intptr_t uuid, void *set,
880
888
  if (!fio_http_at_capa)
881
889
  FIO_LOG_WARNING("HTTP server at capacity");
882
890
  fio_http_at_capa = 1;
883
- http_send_error2(uuid, 503, set);
891
+ http_send_error2(503, uuid, set);
884
892
  fio_close(uuid);
885
893
  }
886
894
  return;
@@ -927,10 +935,12 @@ intptr_t http_listen(const char *port, const char *binding,
927
935
 
928
936
  http_settings_s *settings = http_settings_new(arg_settings);
929
937
  settings->is_client = 0;
938
+ #ifndef __MINGW32__
930
939
  if (settings->tls) {
931
940
  fio_tls_alpn_add(settings->tls, "http/1.1", http_on_server_protocol_http1,
932
941
  NULL, NULL);
933
942
  }
943
+ #endif
934
944
 
935
945
  return fio_listen(.port = port, .address = binding, .tls = arg_settings.tls,
936
946
  .on_finish = http_on_finish, .on_open = http_on_open,
@@ -1187,6 +1197,7 @@ static void on_websocket_http_connection_finished(http_settings_s *settings) {
1187
1197
  #undef websocket_connect
1188
1198
  int websocket_connect(const char *address, websocket_settings_s settings) {
1189
1199
  websocket_settings_s *s = fio_malloc(sizeof(*s));
1200
+ FIO_ASSERT_ALLOC(s);
1190
1201
  *s = settings;
1191
1202
  return http_connect(address, NULL, .on_request = on_websocket_http_connected,
1192
1203
  .on_response = on_websocket_http_connected,
@@ -2331,6 +2342,30 @@ size_t http_date2rfc2109(char *target, struct tm *tmbuf) {
2331
2342
  return pos - target;
2332
2343
  }
2333
2344
 
2345
+ static pthread_key_t cached_tick_key;
2346
+ static pthread_key_t cached_httpdate_key;
2347
+ static pthread_key_t cached_len_key;
2348
+ static pthread_once_t cached_once = PTHREAD_ONCE_INIT;
2349
+ static void init_cached_key(void) {
2350
+ pthread_key_create(&cached_tick_key, free);
2351
+ pthread_key_create(&cached_httpdate_key, free);
2352
+ pthread_key_create(&cached_len_key, free);
2353
+ }
2354
+ static void init_cached_key_ptr(void) {
2355
+ time_t *cached_tick = malloc(sizeof(time_t));
2356
+ FIO_ASSERT_ALLOC(cached_tick);
2357
+ memset(cached_tick, 0, sizeof(time_t));
2358
+ char *cached_httpdate = malloc(sizeof(char)*48);
2359
+ FIO_ASSERT_ALLOC(cached_tick);
2360
+ memset(cached_httpdate, 0, 48);
2361
+ size_t *cached_len = malloc(sizeof(size_t));
2362
+ *cached_len = 0;
2363
+ FIO_ASSERT_ALLOC(cached_len);
2364
+ pthread_setspecific(cached_tick_key, cached_tick);
2365
+ pthread_setspecific(cached_httpdate_key, cached_httpdate);
2366
+ pthread_setspecific(cached_len_key, cached_len);
2367
+ }
2368
+
2334
2369
  /**
2335
2370
  * Prints Unix time to a HTTP time formatted string.
2336
2371
  *
@@ -2339,9 +2374,14 @@ size_t http_date2rfc2109(char *target, struct tm *tmbuf) {
2339
2374
  */
2340
2375
  size_t http_time2str(char *target, const time_t t) {
2341
2376
  /* pre-print time every 1 or 2 seconds or so. */
2342
- static __thread time_t cached_tick;
2343
- static __thread char cached_httpdate[48];
2344
- static __thread size_t cached_len;
2377
+ pthread_once(&cached_once, init_cached_key);
2378
+ char *cached_httpdate = pthread_getspecific(cached_httpdate_key);
2379
+ if (!cached_httpdate) {
2380
+ init_cached_key_ptr();
2381
+ cached_httpdate = pthread_getspecific(cached_httpdate_key);
2382
+ }
2383
+ time_t *cached_tick = pthread_getspecific(cached_tick_key);
2384
+ size_t *cached_len = pthread_getspecific(cached_len_key);
2345
2385
  time_t last_tick = fio_last_tick().tv_sec;
2346
2386
  if ((t | 7) < last_tick) {
2347
2387
  /* this is a custom time, not "now", pass through */
@@ -2349,14 +2389,14 @@ size_t http_time2str(char *target, const time_t t) {
2349
2389
  http_gmtime(t, &tm);
2350
2390
  return http_date2str(target, &tm);
2351
2391
  }
2352
- if (last_tick > cached_tick) {
2392
+ if (last_tick > *cached_tick) {
2353
2393
  struct tm tm;
2354
- cached_tick = last_tick; /* refresh every second */
2394
+ *cached_tick = last_tick; /* refresh every second */
2355
2395
  http_gmtime(last_tick, &tm);
2356
- cached_len = http_date2str(cached_httpdate, &tm);
2396
+ *cached_len = http_date2str(cached_httpdate, &tm);
2357
2397
  }
2358
- memcpy(target, cached_httpdate, cached_len);
2359
- return cached_len;
2398
+ memcpy(target, cached_httpdate, *cached_len);
2399
+ return *cached_len;
2360
2400
  }
2361
2401
 
2362
2402
  /* Credit to Jonathan Leffler for the idea of a unified conditional */
@@ -2519,12 +2559,28 @@ FIOBJ http_mimetype_find(char *file_ext, size_t file_ext_len) {
2519
2559
  fio_mime_set_find(&fio_http_mime_types, hash, FIOBJ_INVALID));
2520
2560
  }
2521
2561
 
2562
+ static pthread_key_t buffer_key;
2563
+ static pthread_once_t buffer_once = PTHREAD_ONCE_INIT;
2564
+ static void init_buffer_key(void) {
2565
+ pthread_key_create(&buffer_key, free);
2566
+ }
2567
+ static void init_buffer_ptr(void) {
2568
+ char *buffer = malloc(sizeof(char) * (LONGEST_FILE_EXTENSION_LENGTH + 1));
2569
+ FIO_ASSERT_ALLOC(buffer);
2570
+ memset(buffer, 0, sizeof(char) * (LONGEST_FILE_EXTENSION_LENGTH + 1));
2571
+ pthread_setspecific(buffer_key, buffer);
2572
+ }
2522
2573
  /**
2523
2574
  * Finds the mime-type associated with the URL.
2524
2575
  * Remember to call `fiobj_free`.
2525
2576
  */
2526
2577
  FIOBJ http_mimetype_find2(FIOBJ url) {
2527
- static __thread char buffer[LONGEST_FILE_EXTENSION_LENGTH + 1];
2578
+ pthread_once(&buffer_once, init_buffer_key);
2579
+ char *buffer = pthread_getspecific(buffer_key);
2580
+ if (!buffer) {
2581
+ init_buffer_ptr();
2582
+ buffer = pthread_getspecific(buffer_key);
2583
+ }
2528
2584
  fio_str_info_s ext = {.data = NULL};
2529
2585
  FIOBJ mimetype;
2530
2586
  if (!url)
data/ext/iodine/http1.c CHANGED
@@ -375,6 +375,7 @@ static int http1_http2websocket_client(http_s *h, websocket_settings_s *args) {
375
375
  p->p.settings->on_finish(p->p.settings);
376
376
  /* Copy the Websocket setting arguments to the HTTP settings `udata` */
377
377
  p->p.settings->udata = fio_malloc(sizeof(*args));
378
+ FIO_ASSERT_ALLOC(p->p.settings->udata);
378
379
  ((websocket_settings_s *)(p->p.settings->udata))[0] = *args;
379
380
  /* Set callbacks */
380
381
  p->p.settings->on_finish = http1_websocket_client_on_hangup; /* unknown */
@@ -820,7 +821,7 @@ void http1_destroy(fio_protocol_s *pr) {
820
821
  http_s_destroy(&http1_pr2handle(p), 0);
821
822
  // FIO_LOG_DEBUG("Deallocating HTTP/1.1 protocol %p(%d)=>%p", (void
822
823
  // *)p->p.uuid, (int)fio_uuid2fd(p->p.uuid), (void *)p);
823
- fio_free(p);
824
+ fio_free(p); // occasional Windows crash bug
824
825
  }
825
826
 
826
827
  /* *****************************************************************************