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.
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
@@ -88,13 +92,12 @@ static inline void add_date(http_s *r) {
88
92
  static uint64_t date_hash = 0;
89
93
  if (!date_hash)
90
94
  date_hash = fiobj_hash_string("date", 4);
91
- static uint64_t mod_hash = 0;
92
- if (!mod_hash)
93
- mod_hash = fiobj_hash_string("last-modified", 13);
94
95
 
95
96
  if (fio_last_tick().tv_sec > last_date_added) {
96
97
  fio_lock(&date_lock);
97
98
  if (fio_last_tick().tv_sec > last_date_added) { /* retest inside lock */
99
+ /* 32 chars are ok for a while, but http_time2str below has a buffer sized
100
+ * 48 chars and does a memcpy ... */
98
101
  FIOBJ tmp = fiobj_str_buf(32);
99
102
  FIOBJ old = current_date;
100
103
  fiobj_str_resize(
@@ -110,11 +113,6 @@ static inline void add_date(http_s *r) {
110
113
  fiobj_hash_set(r->private_data.out_headers, HTTP_HEADER_DATE,
111
114
  fiobj_dup(current_date));
112
115
  }
113
- if (r->status_str == FIOBJ_INVALID &&
114
- !fiobj_hash_get2(r->private_data.out_headers, mod_hash)) {
115
- fiobj_hash_set(r->private_data.out_headers, HTTP_HEADER_LAST_MODIFIED,
116
- fiobj_dup(current_date));
117
- }
118
116
  }
119
117
 
120
118
  struct header_writer_s {
@@ -764,6 +762,7 @@ void http_pause(http_s *h, void (*task)(http_pause_handle_s *http)) {
764
762
  http_fio_protocol_s *p = (http_fio_protocol_s *)h->private_data.flag;
765
763
  http_vtable_s *vtbl = (http_vtable_s *)h->private_data.vtbl;
766
764
  http_pause_handle_s *http = fio_malloc(sizeof(*http));
765
+ FIO_ASSERT_ALLOC(http);
767
766
  *http = (http_pause_handle_s){
768
767
  .uuid = p->uuid,
769
768
  .h = h,
@@ -845,6 +844,7 @@ static http_settings_s *http_settings_new(http_settings_s arg_settings) {
845
844
  char *home = getenv("HOME");
846
845
  size_t home_len = strlen(home);
847
846
  char *tmp = malloc(settings->public_folder_length + home_len + 1);
847
+ FIO_ASSERT_ALLOC(tmp);
848
848
  memcpy(tmp, home, home_len);
849
849
  if (home[home_len - 1] == '/')
850
850
  --home_len;
@@ -854,6 +854,7 @@ static http_settings_s *http_settings_new(http_settings_s arg_settings) {
854
854
  settings->public_folder_length = strlen(settings->public_folder);
855
855
  } else {
856
856
  settings->public_folder = malloc(settings->public_folder_length + 1);
857
+ FIO_ASSERT_ALLOC(settings->public_folder);
857
858
  memcpy((void *)settings->public_folder, arg_settings.public_folder,
858
859
  settings->public_folder_length);
859
860
  ((uint8_t *)settings->public_folder)[settings->public_folder_length] = 0;
@@ -880,7 +881,7 @@ static void http_on_server_protocol_http1(intptr_t uuid, void *set,
880
881
  if (!fio_http_at_capa)
881
882
  FIO_LOG_WARNING("HTTP server at capacity");
882
883
  fio_http_at_capa = 1;
883
- http_send_error2(uuid, 503, set);
884
+ http_send_error2(503, uuid, set);
884
885
  fio_close(uuid);
885
886
  }
886
887
  return;
@@ -927,10 +928,12 @@ intptr_t http_listen(const char *port, const char *binding,
927
928
 
928
929
  http_settings_s *settings = http_settings_new(arg_settings);
929
930
  settings->is_client = 0;
931
+ #ifndef __MINGW32__
930
932
  if (settings->tls) {
931
933
  fio_tls_alpn_add(settings->tls, "http/1.1", http_on_server_protocol_http1,
932
934
  NULL, NULL);
933
935
  }
936
+ #endif
934
937
 
935
938
  return fio_listen(.port = port, .address = binding, .tls = arg_settings.tls,
936
939
  .on_finish = http_on_finish, .on_open = http_on_open,
@@ -1187,6 +1190,7 @@ static void on_websocket_http_connection_finished(http_settings_s *settings) {
1187
1190
  #undef websocket_connect
1188
1191
  int websocket_connect(const char *address, websocket_settings_s settings) {
1189
1192
  websocket_settings_s *s = fio_malloc(sizeof(*s));
1193
+ FIO_ASSERT_ALLOC(s);
1190
1194
  *s = settings;
1191
1195
  return http_connect(address, NULL, .on_request = on_websocket_http_connected,
1192
1196
  .on_response = on_websocket_http_connected,
@@ -2331,6 +2335,30 @@ size_t http_date2rfc2109(char *target, struct tm *tmbuf) {
2331
2335
  return pos - target;
2332
2336
  }
2333
2337
 
2338
+ static pthread_key_t cached_tick_key;
2339
+ static pthread_key_t cached_httpdate_key;
2340
+ static pthread_key_t cached_len_key;
2341
+ static pthread_once_t cached_once = PTHREAD_ONCE_INIT;
2342
+ static void init_cached_key(void) {
2343
+ pthread_key_create(&cached_tick_key, free);
2344
+ pthread_key_create(&cached_httpdate_key, free);
2345
+ pthread_key_create(&cached_len_key, free);
2346
+ }
2347
+ static void init_cached_key_ptr(void) {
2348
+ time_t *cached_tick = malloc(sizeof(time_t));
2349
+ FIO_ASSERT_ALLOC(cached_tick);
2350
+ memset(cached_tick, 0, sizeof(time_t));
2351
+ char *cached_httpdate = malloc(sizeof(char) * 48);
2352
+ FIO_ASSERT_ALLOC(cached_tick);
2353
+ memset(cached_httpdate, 0, 48);
2354
+ size_t *cached_len = malloc(sizeof(size_t));
2355
+ *cached_len = 0;
2356
+ FIO_ASSERT_ALLOC(cached_len);
2357
+ pthread_setspecific(cached_tick_key, cached_tick);
2358
+ pthread_setspecific(cached_httpdate_key, cached_httpdate);
2359
+ pthread_setspecific(cached_len_key, cached_len);
2360
+ }
2361
+
2334
2362
  /**
2335
2363
  * Prints Unix time to a HTTP time formatted string.
2336
2364
  *
@@ -2339,9 +2367,14 @@ size_t http_date2rfc2109(char *target, struct tm *tmbuf) {
2339
2367
  */
2340
2368
  size_t http_time2str(char *target, const time_t t) {
2341
2369
  /* 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;
2370
+ pthread_once(&cached_once, init_cached_key);
2371
+ char *cached_httpdate = pthread_getspecific(cached_httpdate_key);
2372
+ if (!cached_httpdate) {
2373
+ init_cached_key_ptr();
2374
+ cached_httpdate = pthread_getspecific(cached_httpdate_key);
2375
+ }
2376
+ time_t *cached_tick = pthread_getspecific(cached_tick_key);
2377
+ size_t *cached_len = pthread_getspecific(cached_len_key);
2345
2378
  time_t last_tick = fio_last_tick().tv_sec;
2346
2379
  if ((t | 7) < last_tick) {
2347
2380
  /* this is a custom time, not "now", pass through */
@@ -2349,40 +2382,36 @@ size_t http_time2str(char *target, const time_t t) {
2349
2382
  http_gmtime(t, &tm);
2350
2383
  return http_date2str(target, &tm);
2351
2384
  }
2352
- if (last_tick > cached_tick) {
2385
+ if (last_tick > *cached_tick) {
2353
2386
  struct tm tm;
2354
- cached_tick = last_tick; /* refresh every second */
2387
+ *cached_tick = last_tick; /* refresh every second */
2355
2388
  http_gmtime(last_tick, &tm);
2356
- cached_len = http_date2str(cached_httpdate, &tm);
2389
+ *cached_len = http_date2str(cached_httpdate, &tm);
2357
2390
  }
2358
- memcpy(target, cached_httpdate, cached_len);
2359
- return cached_len;
2391
+ memcpy(target, cached_httpdate, *cached_len);
2392
+ return *cached_len;
2360
2393
  }
2361
2394
 
2362
2395
  /* Credit to Jonathan Leffler for the idea of a unified conditional */
2363
2396
  #define hex_val(c) \
2364
- (((c) >= '0' && (c) <= '9') \
2365
- ? ((c)-48) \
2366
- : (((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) \
2367
- ? (((c) | 32) - 87) \
2368
- : ({ \
2369
- return -1; \
2370
- 0; \
2371
- }))
2397
+ (((c) >= '0' && (c) <= '9') ? ((c)-48) \
2398
+ : (((c) | 32) >= 'a' && ((c) | 32) <= 'f') ? (((c) | 32) - 87) \
2399
+ : ({ \
2400
+ return -1; \
2401
+ 0; \
2402
+ }))
2372
2403
  static inline int hex2byte(uint8_t *dest, const uint8_t *source) {
2373
2404
  if (source[0] >= '0' && source[0] <= '9')
2374
2405
  *dest = (source[0] - '0');
2375
- else if ((source[0] >= 'a' && source[0] <= 'f') ||
2376
- (source[0] >= 'A' && source[0] <= 'F'))
2377
- *dest = (source[0] | 32) - 87;
2406
+ else if ((source[0] | 32) >= 'a' && (source[0] | 32) <= 'f')
2407
+ *dest = (source[0] | 32) - ('a' - 10);
2378
2408
  else
2379
2409
  return -1;
2380
2410
  *dest <<= 4;
2381
2411
  if (source[1] >= '0' && source[1] <= '9')
2382
2412
  *dest |= (source[1] - '0');
2383
- else if ((source[1] >= 'a' && source[1] <= 'f') ||
2384
- (source[1] >= 'A' && source[1] <= 'F'))
2385
- *dest |= (source[1] | 32) - 87;
2413
+ else if ((source[1] | 32) >= 'a' && (source[1] | 32) <= 'f')
2414
+ *dest |= (source[1] | 32) - ('a' - 10);
2386
2415
  else
2387
2416
  return -1;
2388
2417
  return 0;
@@ -2519,12 +2548,26 @@ FIOBJ http_mimetype_find(char *file_ext, size_t file_ext_len) {
2519
2548
  fio_mime_set_find(&fio_http_mime_types, hash, FIOBJ_INVALID));
2520
2549
  }
2521
2550
 
2551
+ static pthread_key_t buffer_key;
2552
+ static pthread_once_t buffer_once = PTHREAD_ONCE_INIT;
2553
+ static void init_buffer_key(void) { pthread_key_create(&buffer_key, free); }
2554
+ static void init_buffer_ptr(void) {
2555
+ char *buffer = malloc(sizeof(char) * (LONGEST_FILE_EXTENSION_LENGTH + 1));
2556
+ FIO_ASSERT_ALLOC(buffer);
2557
+ memset(buffer, 0, sizeof(char) * (LONGEST_FILE_EXTENSION_LENGTH + 1));
2558
+ pthread_setspecific(buffer_key, buffer);
2559
+ }
2522
2560
  /**
2523
2561
  * Finds the mime-type associated with the URL.
2524
2562
  * Remember to call `fiobj_free`.
2525
2563
  */
2526
2564
  FIOBJ http_mimetype_find2(FIOBJ url) {
2527
- static __thread char buffer[LONGEST_FILE_EXTENSION_LENGTH + 1];
2565
+ pthread_once(&buffer_once, init_buffer_key);
2566
+ char *buffer = pthread_getspecific(buffer_key);
2567
+ if (!buffer) {
2568
+ init_buffer_ptr();
2569
+ buffer = pthread_getspecific(buffer_key);
2570
+ }
2528
2571
  fio_str_info_s ext = {.data = NULL};
2529
2572
  FIOBJ mimetype;
2530
2573
  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
  /* *****************************************************************************