iodine 0.4.5 → 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/ext/iodine/defer.c +53 -5
- data/ext/iodine/facil.c +44 -10
- data/ext/iodine/facil.h +6 -5
- data/ext/iodine/fio_dict.h +9 -0
- data/ext/iodine/http.h +9 -0
- data/ext/iodine/http_request.h +9 -0
- data/ext/iodine/http_response.h +9 -0
- data/ext/iodine/pubsub.c +1 -2
- data/ext/iodine/pubsub.h +10 -1
- data/ext/iodine/redis_connection.h +9 -0
- data/ext/iodine/redis_engine.c +1 -1
- data/ext/iodine/redis_engine.h +11 -1
- data/ext/iodine/resp.h +9 -0
- data/ext/iodine/websockets.h +9 -0
- data/lib/iodine/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9f26da78f47f0d2d44534b5a0930862ac5c1092
|
4
|
+
data.tar.gz: 13b1d9adfa9e1df5f4544448ec551f879c6a32ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0381cd3d98e09b440636e7d4fd53a60139d7673b9595a2b7c9e2c6050d593f4920294496b462cf8661cd7cb3af464077664a78d6ba7afa27143b73bc16087678'
|
7
|
+
data.tar.gz: bb0f81ea6a19da939cf733a3a934c7d2396b9bc980abdff4331fb0c2e03c65a96918341df0ff41fb50e5379de758fa75e4df31e0f8db15b3d3b41bd38e5fcdb6
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,12 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
6
6
|
|
7
7
|
## Changes:
|
8
8
|
|
9
|
+
#### Change log v.0.4.6
|
10
|
+
|
11
|
+
**Update**: Now using `facil.io` v.0.5.2.
|
12
|
+
|
13
|
+
**Fix**: (from `facil.io`) fix `SIGTERM` handling, make sure sibling processes exit when a sibling dies.
|
14
|
+
|
9
15
|
#### Change log v.0.4.5
|
10
16
|
|
11
17
|
**Fix**: fix static file service for `X-Sendfile` as well as static error file fallback pages (404.html etc').
|
data/ext/iodine/defer.c
CHANGED
@@ -30,24 +30,33 @@ Compile time settings
|
|
30
30
|
Data Structures
|
31
31
|
***************************************************************************** */
|
32
32
|
|
33
|
+
/* task node data */
|
33
34
|
typedef struct {
|
34
35
|
void (*func)(void *, void *);
|
35
36
|
void *arg1;
|
36
37
|
void *arg2;
|
37
38
|
} task_s;
|
38
39
|
|
40
|
+
/* a single linked list for tasks */
|
39
41
|
typedef struct task_node_s {
|
40
42
|
task_s task;
|
41
43
|
struct task_node_s *next;
|
42
44
|
} task_node_s;
|
43
45
|
|
46
|
+
/* static memory allocation for a task node buffer */
|
44
47
|
static task_node_s tasks_buffer[DEFER_QUEUE_BUFFER];
|
45
48
|
|
49
|
+
/* the state machine - this holds all the data about the task queue and pool */
|
46
50
|
static struct {
|
51
|
+
/* the next task to be performed */
|
47
52
|
task_node_s *first;
|
53
|
+
/* a pointer to the linked list's tail, where the next task will be stored */
|
48
54
|
task_node_s **last;
|
55
|
+
/* a linked list for task nodes (staticly allocated) */
|
49
56
|
task_node_s *pool;
|
57
|
+
/* a lock for the state machine, used for multi-threading support */
|
50
58
|
spn_lock_i lock;
|
59
|
+
/* a flag indicating whether the task pool was initialized */
|
51
60
|
unsigned char initialized;
|
52
61
|
} deferred = {.first = NULL,
|
53
62
|
.last = &deferred.first,
|
@@ -61,9 +70,11 @@ API
|
|
61
70
|
|
62
71
|
/** Defer an execution of a function for later. */
|
63
72
|
int defer(void (*func)(void *, void *), void *arg1, void *arg2) {
|
73
|
+
/* must have a task to defer */
|
64
74
|
if (!func)
|
65
75
|
goto call_error;
|
66
76
|
task_node_s *task;
|
77
|
+
/* lock the state machine, to grab/create a task and place it at the tail */
|
67
78
|
spn_lock(&deferred.lock);
|
68
79
|
if (deferred.pool) {
|
69
80
|
task = deferred.pool;
|
@@ -74,6 +85,7 @@ int defer(void (*func)(void *, void *), void *arg1, void *arg2) {
|
|
74
85
|
goto error;
|
75
86
|
} else
|
76
87
|
goto initialize;
|
88
|
+
|
77
89
|
schedule:
|
78
90
|
*deferred.last = task;
|
79
91
|
deferred.last = &task->next;
|
@@ -83,13 +95,18 @@ schedule:
|
|
83
95
|
task->next = NULL;
|
84
96
|
spn_unlock(&deferred.lock);
|
85
97
|
return 0;
|
98
|
+
|
86
99
|
error:
|
87
100
|
spn_unlock(&deferred.lock);
|
88
101
|
perror("ERROR CRITICAL: defer can't allocate task");
|
89
102
|
kill(0, SIGINT), exit(errno);
|
103
|
+
|
90
104
|
call_error:
|
91
105
|
return -1;
|
106
|
+
|
92
107
|
initialize:
|
108
|
+
/* initialize the task pool using all the items in the static buffer */
|
109
|
+
/* also assign `task` one of the tasks from the pool and schedule the task */
|
93
110
|
deferred.initialized = 1;
|
94
111
|
task = tasks_buffer;
|
95
112
|
deferred.pool = tasks_buffer + 1;
|
@@ -105,7 +122,7 @@ void defer_perform(void) {
|
|
105
122
|
task_node_s *tmp;
|
106
123
|
task_s task;
|
107
124
|
restart:
|
108
|
-
spn_lock(&deferred.lock);
|
125
|
+
spn_lock(&deferred.lock); /* remember never to perform tasks within a lock! */
|
109
126
|
tmp = deferred.first;
|
110
127
|
if (tmp) {
|
111
128
|
deferred.first = tmp->next;
|
@@ -119,7 +136,9 @@ restart:
|
|
119
136
|
free(tmp);
|
120
137
|
}
|
121
138
|
spn_unlock(&deferred.lock);
|
139
|
+
/* perform the task outside the lock. */
|
122
140
|
task.func(task.arg1, task.arg2);
|
141
|
+
/* I used `goto` to optimize assembly instruction flow. maybe it helps. */
|
123
142
|
goto restart;
|
124
143
|
}
|
125
144
|
spn_unlock(&deferred.lock);
|
@@ -136,6 +155,8 @@ Thread Pool Support
|
|
136
155
|
defined(DEBUG)
|
137
156
|
#include <pthread.h>
|
138
157
|
|
158
|
+
/* `weak` functions can be overloaded to change the thread implementation. */
|
159
|
+
|
139
160
|
#pragma weak defer_new_thread
|
140
161
|
void *defer_new_thread(void *(*thread_func)(void *), pool_pt arg) {
|
141
162
|
pthread_t *thread = malloc(sizeof(*thread));
|
@@ -161,7 +182,7 @@ void defer_thread_throttle(unsigned long microsec) {
|
|
161
182
|
throttle_thread(microsec);
|
162
183
|
}
|
163
184
|
|
164
|
-
#else /* No pthreads... BYO thread implementation. */
|
185
|
+
#else /* No pthreads... BYO thread implementation. This one simply fails. */
|
165
186
|
|
166
187
|
#pragma weak defer_new_thread
|
167
188
|
void *defer_new_thread(void *(*thread_func)(void *), void *arg) {
|
@@ -186,13 +207,17 @@ struct defer_pool {
|
|
186
207
|
void *threads[];
|
187
208
|
};
|
188
209
|
|
210
|
+
/* a thread's cycle. This is what a worker thread does... repeatedly. */
|
189
211
|
static void *defer_worker_thread(void *pool_) {
|
190
212
|
volatile pool_pt pool = pool_;
|
191
213
|
signal(SIGPIPE, SIG_IGN);
|
214
|
+
/* the throttle replaces conditional variables for better performance */
|
192
215
|
size_t throttle = (pool->count) * DEFER_THROTTLE;
|
193
216
|
if (!throttle || throttle > 1572864UL)
|
194
217
|
throttle = 1572864UL;
|
218
|
+
/* perform any available tasks */
|
195
219
|
defer_perform();
|
220
|
+
/* as long as the flag is true, wait for and perform tasks. */
|
196
221
|
do {
|
197
222
|
throttle_thread(throttle);
|
198
223
|
defer_perform();
|
@@ -200,10 +225,13 @@ static void *defer_worker_thread(void *pool_) {
|
|
200
225
|
return NULL;
|
201
226
|
}
|
202
227
|
|
228
|
+
/** Signals a running thread pool to stop. Returns immediately. */
|
203
229
|
void defer_pool_stop(pool_pt pool) { pool->flag = 0; }
|
204
230
|
|
231
|
+
/** Returns TRUE (1) if the pool is hadn't been signaled to finish up. */
|
205
232
|
int defer_pool_is_active(pool_pt pool) { return pool->flag; }
|
206
233
|
|
234
|
+
/** Waits for a running thread pool, joining threads and finishing all tasks. */
|
207
235
|
void defer_pool_wait(pool_pt pool) {
|
208
236
|
while (pool->count) {
|
209
237
|
pool->count--;
|
@@ -211,6 +239,7 @@ void defer_pool_wait(pool_pt pool) {
|
|
211
239
|
}
|
212
240
|
}
|
213
241
|
|
242
|
+
/** The logic behind `defer_pool_start`. */
|
214
243
|
static inline pool_pt defer_pool_initialize(unsigned int thread_count,
|
215
244
|
pool_pt pool) {
|
216
245
|
pool->flag = 1;
|
@@ -226,6 +255,7 @@ static inline pool_pt defer_pool_initialize(unsigned int thread_count,
|
|
226
255
|
return NULL;
|
227
256
|
}
|
228
257
|
|
258
|
+
/** Starts a thread pool that will run deferred tasks in the background. */
|
229
259
|
pool_pt defer_pool_start(unsigned int thread_count) {
|
230
260
|
if (thread_count == 0)
|
231
261
|
return NULL;
|
@@ -239,22 +269,23 @@ pool_pt defer_pool_start(unsigned int thread_count) {
|
|
239
269
|
Child Process support (`fork`)
|
240
270
|
***************************************************************************** */
|
241
271
|
|
272
|
+
/* forked `defer` workers use a global thread pool object. */
|
242
273
|
static pool_pt forked_pool;
|
243
274
|
|
275
|
+
/* handles the SIGINT and SIGTERM signals by shutting down workers */
|
244
276
|
static void sig_int_handler(int sig) {
|
245
|
-
if (sig != SIGINT)
|
277
|
+
if (sig != SIGINT && sig != SIGTERM)
|
246
278
|
return;
|
247
279
|
if (!forked_pool)
|
248
280
|
return;
|
249
281
|
defer_pool_stop(forked_pool);
|
250
282
|
}
|
251
283
|
|
252
|
-
/*
|
284
|
+
/*
|
253
285
|
Zombie Reaping
|
254
286
|
With thanks to Dr Graham D Shaw.
|
255
287
|
http://www.microhowto.info/howto/reap_zombie_processes_using_a_sigchld_handler.html
|
256
288
|
*/
|
257
|
-
|
258
289
|
void reap_child_handler(int sig) {
|
259
290
|
(void)(sig);
|
260
291
|
int old_errno = errno;
|
@@ -263,6 +294,7 @@ void reap_child_handler(int sig) {
|
|
263
294
|
errno = old_errno;
|
264
295
|
}
|
265
296
|
|
297
|
+
/* initializes zombie reaping for the process */
|
266
298
|
inline static void reap_children(void) {
|
267
299
|
struct sigaction sa;
|
268
300
|
sa.sa_handler = reap_child_handler;
|
@@ -274,7 +306,9 @@ inline static void reap_children(void) {
|
|
274
306
|
}
|
275
307
|
}
|
276
308
|
|
309
|
+
/* a global process identifier (0 == root) */
|
277
310
|
static int defer_fork_pid_id = 0;
|
311
|
+
|
278
312
|
/**
|
279
313
|
* Forks the process, starts up a thread pool and waits for all tasks to run.
|
280
314
|
* All existing tasks will run in all processes (multiple times).
|
@@ -287,8 +321,12 @@ int defer_perform_in_fork(unsigned int process_count,
|
|
287
321
|
if (forked_pool)
|
288
322
|
return -1; /* we're already running inside an active `fork` */
|
289
323
|
|
324
|
+
/* we use a placeholder while initializing the forked thread pool, so calls to
|
325
|
+
* `defer_fork_is_active` don't fail.
|
326
|
+
*/
|
290
327
|
static struct defer_pool pool_placeholder = {.count = 1, .flag = 1};
|
291
328
|
|
329
|
+
/* setup signal handling */
|
292
330
|
struct sigaction act, old, old_term, old_pipe;
|
293
331
|
pid_t *pids = NULL;
|
294
332
|
int ret = 0;
|
@@ -302,20 +340,26 @@ int defer_perform_in_fork(unsigned int process_count,
|
|
302
340
|
perror("couldn't set signal handler");
|
303
341
|
goto finish;
|
304
342
|
};
|
343
|
+
|
305
344
|
if (sigaction(SIGTERM, &act, &old_term)) {
|
306
345
|
perror("couldn't set signal handler");
|
307
346
|
goto finish;
|
308
347
|
};
|
348
|
+
|
309
349
|
act.sa_handler = SIG_IGN;
|
310
350
|
if (sigaction(SIGPIPE, &act, &old_pipe)) {
|
311
351
|
perror("couldn't set signal handler");
|
312
352
|
goto finish;
|
313
353
|
};
|
354
|
+
|
355
|
+
/* setup zomie reaping */
|
314
356
|
reap_children();
|
315
357
|
|
316
358
|
if (!process_count)
|
317
359
|
process_count = 1;
|
318
360
|
--process_count;
|
361
|
+
|
362
|
+
/* for `process_count == 0` nothing happens */
|
319
363
|
pids = calloc(process_count, sizeof(*pids));
|
320
364
|
if (process_count && !pids)
|
321
365
|
goto finish;
|
@@ -334,12 +378,16 @@ int defer_perform_in_fork(unsigned int process_count,
|
|
334
378
|
goto finish;
|
335
379
|
}
|
336
380
|
}
|
381
|
+
|
337
382
|
pids_count++;
|
338
383
|
forked_pool = &pool_placeholder;
|
339
384
|
forked_pool = defer_pool_start(thread_count);
|
385
|
+
|
340
386
|
defer_pool_wait(forked_pool);
|
341
387
|
forked_pool = NULL;
|
388
|
+
|
342
389
|
defer_perform();
|
390
|
+
|
343
391
|
finish:
|
344
392
|
if (pids) {
|
345
393
|
for (size_t j = 0; j < pids_count; j++) {
|
data/ext/iodine/facil.c
CHANGED
@@ -326,6 +326,7 @@ static void listener_ping(intptr_t uuid, protocol_s *plistener) {
|
|
326
326
|
(void)plistener;
|
327
327
|
}
|
328
328
|
|
329
|
+
/* called asynchronously after a new connection was opened */
|
329
330
|
static void listener_deferred_on_open(void *uuid_, void *srv_uuid_) {
|
330
331
|
intptr_t uuid = (intptr_t)uuid_;
|
331
332
|
intptr_t srv_uuid = (intptr_t)srv_uuid_;
|
@@ -468,6 +469,7 @@ struct ConnectProtocol {
|
|
468
469
|
int opened;
|
469
470
|
};
|
470
471
|
|
472
|
+
/* The first `ready` signal is fired when a connection was established */
|
471
473
|
static void connector_on_ready(intptr_t uuid, protocol_s *_connector) {
|
472
474
|
struct ConnectProtocol *connector = (void *)_connector;
|
473
475
|
// fprintf(stderr, "connector_on_ready called\n");
|
@@ -486,11 +488,13 @@ error:
|
|
486
488
|
sock_close(uuid);
|
487
489
|
}
|
488
490
|
|
491
|
+
/* If data events reach this protocol, delay their execution. */
|
489
492
|
static void connector_on_data(intptr_t uuid, protocol_s *connector) {
|
490
493
|
(void)connector;
|
491
|
-
|
494
|
+
facil_force_event(uuid, FIO_EVENT_ON_DATA);
|
492
495
|
}
|
493
496
|
|
497
|
+
/* Failed to connect */
|
494
498
|
static void connector_on_close(intptr_t uuid, protocol_s *pconnector) {
|
495
499
|
struct ConnectProtocol *connector = (void *)pconnector;
|
496
500
|
if (connector->opened == 0 && connector->on_fail)
|
@@ -521,11 +525,12 @@ intptr_t facil_connect(struct facil_connect_args opt) {
|
|
521
525
|
.opened = 0,
|
522
526
|
};
|
523
527
|
intptr_t uuid = connector->uuid = sock_connect(opt.address, opt.port);
|
528
|
+
/* check for errors, always invoke the on_fail if required */
|
524
529
|
if (uuid == -1)
|
525
530
|
goto error;
|
526
531
|
if (facil_attach(uuid, &connector->protocol) == -1) {
|
527
532
|
sock_close(uuid);
|
528
|
-
|
533
|
+
goto error;
|
529
534
|
}
|
530
535
|
return uuid;
|
531
536
|
error:
|
@@ -710,6 +715,22 @@ static void facil_cluster_on_close(intptr_t uuid, protocol_s *pr_) {
|
|
710
715
|
(void)uuid;
|
711
716
|
}
|
712
717
|
|
718
|
+
/* React when a sibling process closes / crashes */
|
719
|
+
static void facil_cluster_on_sibling_close(intptr_t uuid, protocol_s *pr_) {
|
720
|
+
if (facil_cluster_data.pipes[defer_fork_pid()].in == uuid)
|
721
|
+
return;
|
722
|
+
if (defer_fork_is_active()) {
|
723
|
+
kill(getpid(), SIGINT);
|
724
|
+
#if DEBUG
|
725
|
+
fprintf(stderr,
|
726
|
+
"* Sibling death detected, signaling self exit process %d\n",
|
727
|
+
getpid());
|
728
|
+
#endif
|
729
|
+
}
|
730
|
+
(void)uuid;
|
731
|
+
(void)pr_;
|
732
|
+
}
|
733
|
+
|
713
734
|
/* cluster protocol on_data callback */
|
714
735
|
static void facil_cluster_on_data(intptr_t uuid, protocol_s *pr_) {
|
715
736
|
struct facil_cluster_protocol *pr = (struct facil_cluster_protocol *)pr_;
|
@@ -755,12 +776,22 @@ static void facil_cluster_register(void *arg1, void *arg2) {
|
|
755
776
|
(void)arg2;
|
756
777
|
if (facil_cluster_data.count < 2)
|
757
778
|
return;
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
779
|
+
|
780
|
+
/* used to watch for sibling crashes and prevent other events from firing */
|
781
|
+
static protocol_s sentinel_protocol = {
|
782
|
+
.service = NULL,
|
783
|
+
.ping = listener_ping,
|
784
|
+
.on_close = facil_cluster_on_sibling_close,
|
785
|
+
};
|
786
|
+
/* close what we don't need and watch the connections we do need */
|
787
|
+
for (size_t i = 0; i < facil_cluster_data.count; i++) {
|
788
|
+
if (i == (size_t)defer_fork_pid())
|
789
|
+
continue;
|
790
|
+
sock_close(facil_cluster_data.pipes[i].in);
|
791
|
+
facil_attach(facil_cluster_data.pipes[i].out, &sentinel_protocol);
|
792
|
+
}
|
793
|
+
sock_close(facil_cluster_data.pipes[defer_fork_pid()].out);
|
794
|
+
|
764
795
|
struct facil_cluster_protocol *pr = malloc(sizeof(*pr));
|
765
796
|
if (!pr)
|
766
797
|
perror("ERROR: (critical) cannot allocate memory for cluster."),
|
@@ -787,7 +818,10 @@ static void facil_cluster_init(uint16_t count) {
|
|
787
818
|
if (!facil_cluster_data.pipes)
|
788
819
|
goto error;
|
789
820
|
|
790
|
-
|
821
|
+
/* used to prevent any events from firing */
|
822
|
+
static protocol_s stub_protocol = {
|
823
|
+
.service = NULL, .ping = listener_ping,
|
824
|
+
};
|
791
825
|
stub_protocol.service = facil_cluster_protocol_id;
|
792
826
|
|
793
827
|
facil_cluster_data.count = count;
|
@@ -799,8 +833,8 @@ static void facil_cluster_init(uint16_t count) {
|
|
799
833
|
sock_set_non_block(p_tmp[0]);
|
800
834
|
sock_set_non_block(p_tmp[1]);
|
801
835
|
facil_cluster_data.pipes[i].in = sock_open(p_tmp[0]);
|
802
|
-
facil_cluster_data.pipes[i].out = sock_open(p_tmp[1]);
|
803
836
|
facil_attach(facil_cluster_data.pipes[i].in, &stub_protocol);
|
837
|
+
facil_cluster_data.pipes[i].out = sock_open(p_tmp[1]);
|
804
838
|
facil_attach(facil_cluster_data.pipes[i].out, &stub_protocol);
|
805
839
|
}
|
806
840
|
defer(facil_cluster_register, NULL, NULL);
|
data/ext/iodine/facil.h
CHANGED
@@ -8,14 +8,10 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
8
8
|
/**
|
9
9
|
"facil.h" is the main header for the facil.io server platform.
|
10
10
|
*/
|
11
|
-
#ifdef __cplusplus
|
12
|
-
extern "C" {
|
13
|
-
#endif
|
14
|
-
|
15
11
|
#define H_FACIL_H
|
16
12
|
#define FACIL_VERSION_MAJOR 0
|
17
13
|
#define FACIL_VERSION_MINOR 5
|
18
|
-
#define FACIL_VERSION_PATCH
|
14
|
+
#define FACIL_VERSION_PATCH 2
|
19
15
|
|
20
16
|
#ifndef FACIL_PRINT_STATE
|
21
17
|
/**
|
@@ -30,6 +26,11 @@ Required facil libraries
|
|
30
26
|
#include "defer.h"
|
31
27
|
#include "sock.h"
|
32
28
|
|
29
|
+
/* support C++ */
|
30
|
+
#ifdef __cplusplus
|
31
|
+
extern "C" {
|
32
|
+
#endif
|
33
|
+
|
33
34
|
/* *****************************************************************************
|
34
35
|
Core object types
|
35
36
|
***************************************************************************** */
|
data/ext/iodine/fio_dict.h
CHANGED
@@ -21,6 +21,11 @@ the key "hello1" will cost only 272 bytes... brrr.
|
|
21
21
|
#include <stdint.h>
|
22
22
|
#include <stdlib.h>
|
23
23
|
|
24
|
+
/* support C++ */
|
25
|
+
#ifdef __cplusplus
|
26
|
+
extern "C" {
|
27
|
+
#endif
|
28
|
+
|
24
29
|
typedef struct fio_dict_s {
|
25
30
|
struct fio_dict_s *parent;
|
26
31
|
struct fio_dict_s *trie[16];
|
@@ -87,4 +92,8 @@ int fio_glob_match(uint8_t *data, size_t data_len, uint8_t *pattern,
|
|
87
92
|
(dict)->trie[12] || (dict)->trie[13] || (dict)->trie[14] || \
|
88
93
|
(dict)->trie[15]))
|
89
94
|
|
95
|
+
#ifdef __cplusplus
|
96
|
+
} /* extern "C" */
|
97
|
+
#endif
|
98
|
+
|
90
99
|
#endif
|
data/ext/iodine/http.h
CHANGED
@@ -54,6 +54,11 @@ Hard Coded Settings
|
|
54
54
|
#define HTTP_DEFAULT_BODY_LIMIT (1024 * 1024 * 50)
|
55
55
|
#endif
|
56
56
|
|
57
|
+
/* support C++ */
|
58
|
+
#ifdef __cplusplus
|
59
|
+
extern "C" {
|
60
|
+
#endif
|
61
|
+
|
57
62
|
/* *****************************************************************************
|
58
63
|
HTTP Core API & data structure
|
59
64
|
*/
|
@@ -200,4 +205,8 @@ ssize_t http_decode_path_unsafe(char *dest, const char *url_data);
|
|
200
205
|
*/
|
201
206
|
ssize_t http_decode_path(char *dest, const char *url_data, size_t length);
|
202
207
|
|
208
|
+
#ifdef __cplusplus
|
209
|
+
} /* extern "C" */
|
210
|
+
#endif
|
211
|
+
|
203
212
|
#endif
|
data/ext/iodine/http_request.h
CHANGED
@@ -10,6 +10,11 @@ typedef struct http_request_s http_request_s;
|
|
10
10
|
|
11
11
|
#include "http.h"
|
12
12
|
|
13
|
+
/* support C++ */
|
14
|
+
#ifdef __cplusplus
|
15
|
+
extern "C" {
|
16
|
+
#endif
|
17
|
+
|
13
18
|
struct http_request_s {
|
14
19
|
/** the HTTP version, also controlls the `http_request_s` flavor. */
|
15
20
|
enum HTTP_VERSION http_version;
|
@@ -90,4 +95,8 @@ http_header_s http_request_header_first(http_request_s *request);
|
|
90
95
|
* Header itteration is NOT thread-safe. */
|
91
96
|
http_header_s http_request_header_next(http_request_s *request);
|
92
97
|
|
98
|
+
#ifdef __cplusplus
|
99
|
+
} /* extern "C" */
|
100
|
+
#endif
|
101
|
+
|
93
102
|
#endif /* H_HTTP_REQUEST_H */
|
data/ext/iodine/http_response.h
CHANGED
@@ -10,6 +10,11 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
10
10
|
#include <stdio.h>
|
11
11
|
#include <time.h>
|
12
12
|
|
13
|
+
/* support C++ */
|
14
|
+
#ifdef __cplusplus
|
15
|
+
extern "C" {
|
16
|
+
#endif
|
17
|
+
|
13
18
|
typedef struct {
|
14
19
|
/** The protocol version family (HTTP/1.1 / HTTP/2 etc'). */
|
15
20
|
enum HTTP_VERSION http_version;
|
@@ -238,4 +243,8 @@ const char *http_response_ext2mime(const char *ext);
|
|
238
243
|
/** Starts counting miliseconds for log results. */
|
239
244
|
void http_response_log_start(http_response_s *);
|
240
245
|
|
246
|
+
#ifdef __cplusplus
|
247
|
+
} /* extern "C" */
|
248
|
+
#endif
|
249
|
+
|
241
250
|
#endif
|
data/ext/iodine/pubsub.c
CHANGED
@@ -266,8 +266,7 @@ const pubsub_engine_s PUBSUB_PROCESS_ENGINE_S = {
|
|
266
266
|
};
|
267
267
|
const pubsub_engine_s *PUBSUB_PROCESS_ENGINE = &PUBSUB_PROCESS_ENGINE_S;
|
268
268
|
|
269
|
-
pubsub_engine_s *PUBSUB_DEFAULT_ENGINE =
|
270
|
-
(pubsub_engine_s *)&PUBSUB_CLUSTER_ENGINE_S;
|
269
|
+
const pubsub_engine_s *PUBSUB_DEFAULT_ENGINE = &PUBSUB_CLUSTER_ENGINE_S;
|
271
270
|
|
272
271
|
/* *****************************************************************************
|
273
272
|
External Engine Bridge
|
data/ext/iodine/pubsub.h
CHANGED
@@ -20,6 +20,11 @@ between all of an application's processes, enhancing overall performance.
|
|
20
20
|
#define H_FACIL_PUBSUB_H
|
21
21
|
#include "facil.h"
|
22
22
|
|
23
|
+
/* support C++ */
|
24
|
+
#ifdef __cplusplus
|
25
|
+
extern "C" {
|
26
|
+
#endif
|
27
|
+
|
23
28
|
#ifndef FIO_PUBBSUB_MAX_CHANNEL_LEN
|
24
29
|
#define FIO_PUBBSUB_MAX_CHANNEL_LEN 1024
|
25
30
|
#endif
|
@@ -191,7 +196,7 @@ extern const pubsub_engine_s *PUBSUB_CLUSTER_ENGINE;
|
|
191
196
|
extern const pubsub_engine_s *PUBSUB_PROCESS_ENGINE;
|
192
197
|
|
193
198
|
/** Allows process wide changes to the default Pub/Sub Engine. */
|
194
|
-
extern pubsub_engine_s *PUBSUB_DEFAULT_ENGINE;
|
199
|
+
extern const pubsub_engine_s *PUBSUB_DEFAULT_ENGINE;
|
195
200
|
|
196
201
|
/**
|
197
202
|
* The function used by engines to distribute received messages.
|
@@ -212,4 +217,8 @@ void pubsub_engine_distribute(pubsub_message_s msg);
|
|
212
217
|
*/
|
213
218
|
void pubsub_engine_resubscribe(pubsub_engine_s *eng);
|
214
219
|
|
220
|
+
#ifdef __cplusplus
|
221
|
+
} /* extern "C" */
|
222
|
+
#endif
|
223
|
+
|
215
224
|
#endif /* H_FACIL_PUBSUB_H */
|
@@ -10,6 +10,11 @@ Feel free to copy, use and enjoy in accordance with to the license(s).
|
|
10
10
|
#include "facil.h"
|
11
11
|
#include "resp.h"
|
12
12
|
|
13
|
+
/* support C++ */
|
14
|
+
#ifdef __cplusplus
|
15
|
+
extern "C" {
|
16
|
+
#endif
|
17
|
+
|
13
18
|
/* *****************************************************************************
|
14
19
|
Connectivity
|
15
20
|
***************************************************************************** */
|
@@ -74,4 +79,8 @@ protocol_s *redis_create_server_protocol(intptr_t uuid, void *settings);
|
|
74
79
|
*/
|
75
80
|
void redis_protocol_cleanup(intptr_t uuid, void *settings);
|
76
81
|
|
82
|
+
#ifdef __cplusplus
|
83
|
+
} /* extern "C" */
|
84
|
+
#endif
|
85
|
+
|
77
86
|
#endif
|
data/ext/iodine/redis_engine.c
CHANGED
@@ -346,7 +346,7 @@ See the {pubsub.h} file for documentation about engines.
|
|
346
346
|
|
347
347
|
function names speak for themselves ;-)
|
348
348
|
*/
|
349
|
-
void redis_engine_destroy(pubsub_engine_s *engine) {
|
349
|
+
void redis_engine_destroy(const pubsub_engine_s *engine) {
|
350
350
|
redis_engine_s *r = (redis_engine_s *)engine;
|
351
351
|
|
352
352
|
spn_lock(&r->lock);
|
data/ext/iodine/redis_engine.h
CHANGED
@@ -17,6 +17,11 @@ subscription or publication... it will simply try until successful.
|
|
17
17
|
#include "pubsub.h"
|
18
18
|
#include "resp.h"
|
19
19
|
|
20
|
+
/* support C++ */
|
21
|
+
#ifdef __cplusplus
|
22
|
+
extern "C" {
|
23
|
+
#endif
|
24
|
+
|
20
25
|
/** possible arguments for the `redis_engine_create` function call */
|
21
26
|
struct redis_engine_create_args {
|
22
27
|
/** Redis server's address */
|
@@ -64,5 +69,10 @@ See the {pubsub.h} file for documentation about engines.
|
|
64
69
|
|
65
70
|
function names speak for themselves ;-)
|
66
71
|
*/
|
67
|
-
void redis_engine_destroy(pubsub_engine_s *engine);
|
72
|
+
void redis_engine_destroy(const pubsub_engine_s *engine);
|
73
|
+
|
74
|
+
#ifdef __cplusplus
|
75
|
+
} /* extern "C" */
|
76
|
+
#endif
|
77
|
+
|
68
78
|
#endif
|
data/ext/iodine/resp.h
CHANGED
@@ -14,6 +14,11 @@ This is a neive implementation of the RESP protocol for Redis.
|
|
14
14
|
#include <stdint.h>
|
15
15
|
#include <stdlib.h>
|
16
16
|
|
17
|
+
/* support C++ */
|
18
|
+
#ifdef __cplusplus
|
19
|
+
extern "C" {
|
20
|
+
#endif
|
21
|
+
|
17
22
|
/** The RESP Parser Type */
|
18
23
|
typedef struct resp_parser_s *resp_parser_pt;
|
19
24
|
|
@@ -250,4 +255,8 @@ void resp_enable_duplex_pubsub(resp_parser_pt parser);
|
|
250
255
|
void resp_test(void);
|
251
256
|
#endif
|
252
257
|
|
258
|
+
#ifdef __cplusplus
|
259
|
+
} /* extern "C" */
|
260
|
+
#endif
|
261
|
+
|
253
262
|
#endif
|
data/ext/iodine/websockets.h
CHANGED
@@ -9,6 +9,11 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
9
9
|
|
10
10
|
#include "http.h"
|
11
11
|
|
12
|
+
/* support C++ */
|
13
|
+
#ifdef __cplusplus
|
14
|
+
extern "C" {
|
15
|
+
#endif
|
16
|
+
|
12
17
|
/* *****************************************************************************
|
13
18
|
Upgrading from HTTP to Websockets
|
14
19
|
***************************************************************************** */
|
@@ -342,4 +347,8 @@ int websocket_write_each(struct websocket_write_each_args_s args);
|
|
342
347
|
#define websocket_write_each(...) \
|
343
348
|
websocket_write_each((struct websocket_write_each_args_s){__VA_ARGS__})
|
344
349
|
|
350
|
+
#ifdef __cplusplus
|
351
|
+
} /* extern "C" */
|
352
|
+
#endif
|
353
|
+
|
345
354
|
#endif
|
data/lib/iodine/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iodine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boaz Segev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-07-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|