iodine 0.7.41 → 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.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- data/.gitignore +1 -0
- data/CHANGELOG.md +24 -0
- data/README.md +2 -2
- data/SPEC-PubSub-Draft.md +89 -47
- data/SPEC-WebSocket-Draft.md +92 -55
- data/examples/async_task.ru +92 -0
- data/ext/iodine/extconf.rb +21 -16
- data/ext/iodine/fio.c +1108 -162
- data/ext/iodine/fio.h +49 -13
- data/ext/iodine/fio_cli.c +1 -1
- data/ext/iodine/fio_tls_missing.c +8 -0
- data/ext/iodine/fio_tls_openssl.c +8 -0
- data/ext/iodine/fio_tmpfile.h +13 -1
- data/ext/iodine/fiobj_data.c +6 -4
- data/ext/iodine/fiobj_data.h +2 -1
- data/ext/iodine/fiobj_hash.c +32 -6
- data/ext/iodine/fiobj_mustache.c +9 -0
- data/ext/iodine/fiobj_numbers.c +86 -8
- data/ext/iodine/fiobj_str.c +24 -11
- data/ext/iodine/fiobject.c +1 -1
- data/ext/iodine/fiobject.h +5 -3
- data/ext/iodine/http.c +66 -10
- data/ext/iodine/http1.c +2 -1
- data/ext/iodine/http1_parser.h +1065 -103
- data/ext/iodine/http_internal.c +1 -0
- data/ext/iodine/http_internal.h +4 -2
- data/ext/iodine/iodine.c +66 -1
- data/ext/iodine/iodine.h +3 -0
- data/ext/iodine/iodine_caller.c +48 -8
- data/ext/iodine/iodine_connection.c +24 -8
- data/ext/iodine/iodine_http.c +32 -8
- data/ext/iodine/iodine_mustache.c +2 -4
- data/ext/iodine/iodine_rack_io.c +21 -0
- data/ext/iodine/iodine_tcp.c +14 -0
- data/ext/iodine/iodine_tls.c +8 -0
- data/ext/iodine/mustache_parser.h +4 -0
- data/ext/iodine/redis_engine.c +14 -11
- data/ext/iodine/websockets.c +7 -3
- data/iodine.gemspec +5 -4
- data/lib/iodine/version.rb +1 -1
- data/lib/rack/handler/iodine.rb +6 -0
- metadata +15 -13
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(
|
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
|
-
|
2343
|
-
|
2344
|
-
|
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
|
-
|
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
|
/* *****************************************************************************
|