iodine 0.2.17 → 0.3.0

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.

Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +36 -3
  4. data/bin/config.ru +23 -2
  5. data/bin/http-hello +1 -1
  6. data/bin/ws-shootout +5 -0
  7. data/ext/iodine/defer.c +468 -0
  8. data/ext/iodine/defer.h +105 -0
  9. data/ext/iodine/evio.c +263 -0
  10. data/ext/iodine/evio.h +133 -0
  11. data/ext/iodine/extconf.rb +2 -1
  12. data/ext/iodine/facil.c +958 -0
  13. data/ext/iodine/facil.h +423 -0
  14. data/ext/iodine/http.c +90 -0
  15. data/ext/iodine/http.h +50 -12
  16. data/ext/iodine/http1.c +200 -267
  17. data/ext/iodine/http1.h +17 -26
  18. data/ext/iodine/http1_request.c +81 -0
  19. data/ext/iodine/http1_request.h +58 -0
  20. data/ext/iodine/http1_response.c +403 -0
  21. data/ext/iodine/http1_response.h +90 -0
  22. data/ext/iodine/http1_simple_parser.c +124 -108
  23. data/ext/iodine/http1_simple_parser.h +8 -3
  24. data/ext/iodine/http_request.c +104 -0
  25. data/ext/iodine/http_request.h +58 -102
  26. data/ext/iodine/http_response.c +212 -208
  27. data/ext/iodine/http_response.h +89 -252
  28. data/ext/iodine/iodine_core.c +57 -46
  29. data/ext/iodine/iodine_core.h +3 -1
  30. data/ext/iodine/iodine_http.c +105 -81
  31. data/ext/iodine/iodine_websocket.c +17 -13
  32. data/ext/iodine/iodine_websocket.h +1 -0
  33. data/ext/iodine/rb-call.c +9 -7
  34. data/ext/iodine/{rb-libasync.h → rb-defer.c} +57 -49
  35. data/ext/iodine/rb-rack-io.c +12 -6
  36. data/ext/iodine/rb-rack-io.h +1 -1
  37. data/ext/iodine/rb-registry.c +5 -2
  38. data/ext/iodine/sock.c +1159 -0
  39. data/ext/iodine/{libsock.h → sock.h} +138 -142
  40. data/ext/iodine/spnlock.inc +77 -0
  41. data/ext/iodine/websockets.c +101 -112
  42. data/ext/iodine/websockets.h +38 -19
  43. data/iodine.gemspec +3 -3
  44. data/lib/iodine/version.rb +1 -1
  45. data/lib/rack/handler/iodine.rb +6 -6
  46. metadata +23 -19
  47. data/ext/iodine/http_response_http1.h +0 -382
  48. data/ext/iodine/libasync.c +0 -570
  49. data/ext/iodine/libasync.h +0 -122
  50. data/ext/iodine/libreact.c +0 -350
  51. data/ext/iodine/libreact.h +0 -244
  52. data/ext/iodine/libserver.c +0 -957
  53. data/ext/iodine/libserver.h +0 -481
  54. data/ext/iodine/libsock.c +0 -1025
  55. data/ext/iodine/spnlock.h +0 -243
@@ -1,481 +0,0 @@
1
- /*
2
- Copyright: Boaz Segev, 2016-2017
3
- License: MIT
4
-
5
- Feel free to copy, use and enjoy according to the license provided.
6
- */
7
- #ifndef LIB_SERVER
8
- #define LIB_SERVER "0.4.1"
9
- #define LIB_SERVER_VERSION_MAJOR 0
10
- #define LIB_SERVER_VERSION_MINOR 4
11
- #define LIB_SERVER_VERSION_PATCH 1
12
-
13
- #ifndef _GNU_SOURCE
14
- #define _GNU_SOURCE
15
- #endif
16
-
17
- #include <stdint.h>
18
- #include <stdio.h>
19
- #include <stdlib.h>
20
- #include <unistd.h>
21
-
22
- /* lib server is based off and requires the following libraries: */
23
- #include "libasync.h"
24
- #include "libreact.h"
25
- #include "libsock.h"
26
- #include "spnlock.h"
27
-
28
- /** Set `SERVER_DELAY_IO` to 1 in order to delay the IO reactor review
29
- * until the queue for scheduled tasks and events is empty.
30
- */
31
- #ifndef SERVER_DELAY_IO
32
- #define SERVER_DELAY_IO 0
33
- #endif
34
-
35
- #ifndef SERVER_PRINT_STATE
36
- /**
37
- When SERVER_PRINT_STATE is set to 1, the server API will print out common
38
- messages regarding the server state (start / finish / listen messages).
39
- */
40
- #define SERVER_PRINT_STATE 1
41
- #endif
42
-
43
- #if LIB_ASYNC_VERSION_MINOR != 4 || LIB_REACT_VERSION_MINOR != 3 || \
44
- LIB_SOCK_VERSION_MINOR != 2
45
- #warning Lib-Server dependency versions are not in sync. Please review API versions.
46
- #endif
47
-
48
- #ifndef UNUSED_FUNC
49
- #define UNUSED_FUNC __attribute__((unused))
50
- #endif
51
- /** \file
52
- ## LibServer - a dynamic protocol network services library
53
-
54
- * Library (not a framework): meanning, closer to the metal, abstracting only
55
- what is required for API simplicity, error protection and performance.
56
-
57
- * Dynamic Protocol: meanning a service can change protocols mid-stream. Example
58
- usecase: Websockets (HTTP Upgrade).
59
-
60
- * Network services: meanning multiple listening network ports, each with it's
61
- own logic.
62
-
63
- `libserver` utilizes `libreact`, `libasync` and `libsock` to create a simple
64
- API wrapper around these minimalistic libraries and managing the "glue" that
65
- makes them work together.
66
-
67
- It's simple and it's awesome :-)
68
-
69
- Here's a simple example that emulates an HTTP hello world server. This example
70
- will count the number of client and messages using the server and demonstrates
71
- some recommended implementation techniques, such as protocol inheritance.
72
-
73
- #include "libserver.h" // the reactor library
74
- #include <stdatomic.h> // We'll use atomics to safely count client events
75
-
76
- #define THREADS 4
77
- #define PROCESSES 4
78
-
79
- void on_close(protocol_s* protocol);
80
- void on_shutdown(intptr_t sock, protocol_s* protocol);
81
- void on_data(intptr_t sock, protocol_s* protocol);
82
- protocol_s* demo_on_open(intptr_t fd, void* udata);
83
-
84
- // Our demo protocol object uses "C" style inheritance,
85
- // where pointers location are the same so that a simple cast
86
- // from one object to the other, allows us to access more data.
87
- struct DemoProtocol {
88
- protocol_s protocol; // must be first for C style inheritance
89
- size_t _Atomic opened;
90
- size_t _Atomic closed;
91
- size_t _Atomic shutdown;
92
- size_t _Atomic messages;
93
- } demo_protocol = {
94
- .protocol.service = "Demo", // This allows us to ID the protocol type.
95
- .protocol.on_data = on_data,
96
- .protocol.on_shutdown = on_shutdown,
97
- .protocol.on_close = on_close,
98
- };
99
-
100
- // type-casting helper
101
- #define pr2demo(protocol) ((struct DemoProtocol*)(protocol))
102
-
103
- // A simple Hello World HTTP response emulation
104
- char hello_message[] =
105
- "HTTP/1.1 200 OK\r\n"
106
- "Content-Length: 12\r\n"
107
- "Connection: keep-alive\r\n"
108
- "Keep-Alive: 1;timeout=5\r\n"
109
- "\r\n"
110
- "Hello World!";
111
-
112
- protocol_s* on_open(intptr_t fd, void* udata) {
113
- // Count events
114
- atomic_fetch_add(&demo_protocol.opened, 1);
115
- // Set timeout
116
- server_set_timeout(fd, 5);
117
- // * return pointer to the protocol.
118
- // * This is the same as `(protocol_s *)&demo_protocol`
119
- return &demo_protocol.protocol;
120
- }
121
-
122
- void on_data(intptr_t sock, protocol_s* protocol) {
123
- // read data
124
- char data[1024];
125
- if (sock_read(sock, data, 1024)) {
126
- // Count event
127
- atomic_fetch_add(&pr2demo(protocol)->messages, 1);
128
- // send reply
129
- sock_write(sock, hello_message, sizeof(hello_message) - 1);
130
- }
131
- }
132
-
133
- void on_close(protocol_s* protocol) {
134
- // Count event
135
- atomic_fetch_add(&pr2demo(protocol)->closed, 1);
136
- }
137
-
138
- void on_shutdown(intptr_t sock, protocol_s* protocol) {
139
- // Count event
140
- atomic_fetch_add(&pr2demo(protocol)->shutdown, 1);
141
- }
142
-
143
- void on_idle(void) {
144
- // idle event example
145
- fprintf(stderr, "Server was idle, with %lu connections.\n",
146
- server_count(NULL));
147
- }
148
-
149
- int main() {
150
- // this isn't required normally,
151
- // but some systems require atomics to be initialized.
152
- atomic_store(&demo_protocol.opened, 0);
153
- atomic_store(&demo_protocol.closed, 0);
154
- atomic_store(&demo_protocol.shutdown, 0);
155
- atomic_store(&demo_protocol.messages, 0);
156
- // run the server
157
- server_listen(.port = "3000", .on_open = on_open, .udata = NULL);
158
- server_run(.threads = THREADS, .processes = PROCESSES,
159
- .on_idle = on_idle);
160
- // print results
161
- fprintf(stderr,
162
- "** Server returned\n"
163
- "** %lu clients connected.\n"
164
- "** %lu clients disconnected.\n"
165
- "** %lu clients were connected when shutdown was called.\n"
166
- "** %lu messages were sent\n",
167
- atomic_load(&demo_protocol.opened),
168
- atomic_load(&demo_protocol.closed),
169
- atomic_load(&demo_protocol.shutdown),
170
- atomic_load(&demo_protocol.messages));
171
- }
172
-
173
-
174
- */
175
-
176
- /**************************************************************************/ /**
177
- * General info
178
- */
179
-
180
- /* The following types are defined for the userspace of this library: */
181
-
182
- // struct Server; /** used internally. no public data exposed */
183
- struct ServerSettings; /** sets up the server's behavior */
184
- struct ServerServiceSettings; /** sets up a listening socket's behavior */
185
- typedef struct Protocol protocol_s; /** controls connection events */
186
-
187
- /**************************************************************************/ /**
188
- * The Protocol
189
-
190
- The Protocol struct defines the callbacks used for the connection and sets the
191
- behaviour for the connection's protocol.
192
-
193
- All the callbacks recieve a unique connection ID (a semi UUID) that can be
194
- converted to the original file descriptor if in need.
195
-
196
- This allows the Server API to prevent old connection handles from sending data
197
- to new connections after a file descriptor is "recycled" by the OS.
198
- */
199
- struct Protocol {
200
- /**
201
- * A string to identify the protocol's service (i.e. "http").
202
- *
203
- * The string should be a global constant, only a pointer comparison will be
204
- * made (not `strcmp`).
205
- */
206
- const char *service;
207
- /** called when a data is available, but will not run concurrently */
208
- void (*on_data)(intptr_t fduuid, protocol_s *protocol);
209
- /** called when the socket is ready to be written to. */
210
- void (*on_ready)(intptr_t fduuid, protocol_s *protocol);
211
- /** called when the server is shutting down,
212
- * but before closing the connection. */
213
- void (*on_shutdown)(intptr_t fduuid, protocol_s *protocol);
214
- /** called when the connection was closed, but will not run concurrently */
215
- void (*on_close)(protocol_s *protocol);
216
- /** called when a connection's timeout was reached */
217
- void (*ping)(intptr_t fduuid, protocol_s *protocol);
218
- /** private metadata used for object protection */
219
- spn_lock_i callback_lock;
220
- };
221
-
222
- /**************************************************************************/ /**
223
- * The Service Settings
224
-
225
- These settings will be used to setup listening sockets.
226
- */
227
- struct ServerServiceSettings {
228
- /** Called whenever a new connection is accepted. Should return a pointer to
229
- * the connection's protocol. */
230
- protocol_s *(*on_open)(intptr_t fduuid, void *udata);
231
- /** The network service / port. Defaults to "3000". */
232
- const char *port;
233
- /** The socket binding address. Defaults to the recommended NULL. */
234
- const char *address;
235
- /** Opaque user data. */
236
- void *udata;
237
- /**
238
- * Called when the server starts, allowing for further initialization, such as
239
- * timed event scheduling.
240
- *
241
- * This will be called seperately for every process. */
242
- void (*on_start)(void *udata);
243
- /** called when the server is done, to clean up any leftovers. */
244
- void (*on_finish)(void *udata);
245
- };
246
-
247
- /**************************************************************************/ /**
248
- * The Server Settings
249
-
250
- These settings will be used to setup server behaviour. missing settings will be
251
- filled in with default values.
252
- */
253
- struct ServerSettings {
254
- /** called if the event loop in cycled with no pending events. */
255
- void (*on_idle)(void);
256
- /**
257
- * Called when the server starts, allowing for further initialization, such as
258
- * timed event scheduling.
259
- *
260
- * This will be called seperately for every process. */
261
- void (*on_init)(void);
262
- /** called when the server is done, to clean up any leftovers. */
263
- void (*on_finish)(void);
264
- /**
265
- Sets the amount of threads to be created for the server's thread-pool.
266
- Defaults to 1 - the reactor and all callbacks will work using a single working
267
- thread, allowing for an evented single threaded design. Limited to 1024.
268
- */
269
- unsigned threads : 10;
270
- /** Sets the amount of processes to be used (processes will be forked).
271
- Defaults to 1 working processes (no forking), limited to 127.*/
272
- unsigned processes : 7;
273
- };
274
-
275
- /* *****************************************************************************
276
- * The Server API
277
- * (and helper functions)
278
- */
279
-
280
- /* *****************************************************************************
281
- * Server actions
282
- */
283
-
284
- /**
285
- Listens to a server with any of the available service settings:
286
-
287
- * `.on_open` called whenever a new connection is accepted.
288
-
289
- Should return a pointer to the connection's protocol.
290
-
291
- * `.port` the network service / port. Defaults to "3000".
292
-
293
- * `.address` the socket binding address. Defaults to the recommended NULL.
294
-
295
- * `.udata`opaque user data.
296
-
297
- * `.on_start` called when the server starts, allowing for further
298
- initialization, such as timed event scheduling.
299
-
300
- This will be called seperately for every process.
301
-
302
- * `.on_finish` called when the server is done, to clean up any leftovers.
303
-
304
- */
305
- int server_listen(struct ServerServiceSettings);
306
- #define server_listen(...) \
307
- server_listen((struct ServerServiceSettings){__VA_ARGS__})
308
- /**
309
- Runs a server with any of the following server settings:
310
-
311
- * `.threads` the number of threads to initiate in the server's thread pool.
312
-
313
- * `.processes` the number of processes to use (a value of more then 1 will
314
- initiate a `fork`).
315
-
316
- * `.on_init` an on initialization callback (for every process forked).
317
- `void (*callback)(void);``
318
-
319
- * `.on_finish` a post run callback (for every process forked).
320
- `void (*callback)(void);``
321
-
322
- * `.on_idle` an idle server callback (for every process forked).
323
- `void (*callback)(void);``
324
-
325
- This method blocks the current thread until the server is stopped when a
326
- SIGINT/SIGTERM is received.
327
-
328
- To shutdown the server use the `kill` function with a SIGINT.
329
-
330
- This function only returns after the server had completed it's shutdown process.
331
-
332
- */
333
- ssize_t server_run(struct ServerSettings);
334
- #define server_run(...) server_run((struct ServerSettings){__VA_ARGS__})
335
- /** Stops the server, shouldn't be called unless int's impossible to send an
336
- * INTR signal. */
337
- void server_stop(void);
338
- /**
339
- Returns the last time the server reviewed any pending IO events.
340
- */
341
- time_t server_last_tick(void);
342
- /****************************************************************************
343
- * Socket actions
344
- */
345
-
346
- /**
347
- Gets the active protocol object for the requested file descriptor.
348
-
349
- Returns NULL on error (i.e. connection closed), otherwise returns a `protocol_s`
350
- pointer.
351
- */
352
- protocol_s *server_get_protocol(intptr_t uuid);
353
- /**
354
- Sets a new active protocol object for the requested file descriptor.
355
-
356
- This also schedules the old protocol's `on_close` callback to run, making sure
357
- all resources are released.
358
-
359
- Returns -1 on error (i.e. connection closed), otherwise returns 0.
360
- */
361
- ssize_t server_switch_protocol(intptr_t fd, protocol_s *new_protocol);
362
- /**
363
- Sets a connection's timeout.
364
-
365
- Returns -1 on error (i.e. connection closed), otherwise returns 0.
366
- */
367
- void server_set_timeout(intptr_t uuid, uint8_t timeout);
368
- /**
369
- Returns a connection's timeout, as a `uint8_t` value.
370
-
371
- A value of 0 might mean that no timeout was set OR that the connection inquired
372
- about was invalid.
373
- */
374
- uint8_t server_get_timeout(intptr_t uuid);
375
-
376
- /** Attaches an existing connection (fd) to the server's reactor and protocol
377
- management system, so that the server can be used also to manage connection
378
- based resources asynchronously (i.e. database resources etc').
379
-
380
- On failure the fduuid_u.data.fd value will be -1.
381
- */
382
- intptr_t server_attach(int fd, protocol_s *protocol);
383
- /** Hijack a socket (file descriptor) from the server, clearing up it's
384
- resources and calling the protocol's `on_close` callback (making sure allocated
385
- resources are freed).
386
-
387
- The control of the socket is totally relinquished.
388
-
389
- This method will block until all the data in the buffer is sent before
390
- releasing control of the socket.
391
-
392
- The returned value is the fd for the socket, or -1 on error.
393
- */
394
- int server_hijack(intptr_t uuid);
395
- /** Counts the number of connections for the specified protocol (NULL = all
396
- protocols). */
397
- long server_count(char *service);
398
-
399
- /****************************************************************************
400
- * Read and Write
401
- *
402
- * Simpley use `libsock` API for read/write.
403
- */
404
-
405
- /****************************************************************************
406
- * Tasks + Async
407
- */
408
-
409
- /**
410
- Performs a task for each connection except the origin connection, unsafely and
411
- synchronously.
412
-
413
- The task will be performed synchronously (blocking), without waiting for a lock.
414
-
415
- The task will be performed unsafely. For example, the protocol object might be
416
- invalid midway through (or at the beginning) the execution, as there is no
417
- protection against memory deallocation.
418
-
419
- This function should probably be avoided except when implementing publication or
420
- broadcast algorithms.
421
- */
422
- void server_each_unsafe(intptr_t origin_uuid,
423
- void (*task)(intptr_t origin_uuid, intptr_t target_uuid,
424
- protocol_s *target_protocol, void *arg),
425
- void *arg);
426
-
427
- /**
428
- Schedules a specific task to run asyncronously for each connection (except the
429
- origin connection).
430
-
431
- The task is performed within each target connection's busy "lock", meanning no
432
- two tasks (or `on_data` events) should be performed at the same time
433
- (concurrency will be avoided within the context of each connection, except for
434
- `on_shutdown`, `on_close` and `ping`).
435
-
436
- The `on_finish` callback will be called once the task is finished and it will
437
- receive the originating connection's UUID (could be 0). The originating
438
- connection might have been closed by that time.
439
-
440
- The `service` identifier is required. The comparison is pointer value comparison
441
- and isn't related to the content of the service string.
442
-
443
- It is recommended the `on_finish` callback is only used to perform any
444
- resource cleanup necessary.
445
- */
446
- void server_each(intptr_t origin_uuid, const char *service,
447
- void (*task)(intptr_t uuid, protocol_s *protocol, void *arg),
448
- void *arg, void (*on_finish)(intptr_t origin_uuid,
449
- protocol_s *protocol, void *arg));
450
- /** Schedules a specific task to run asyncronously for a specific connection.
451
-
452
- returns -1 on failure, 0 on success (success being scheduling the task).
453
-
454
- If a connection was terminated before performing their sceduled tasks, the
455
- `fallback` task will be performed instead.
456
-
457
- It is recommended to perform any resource cleanup within the fallback function
458
- and call the fallback function from within the main task, but other designes
459
- are valid as well.
460
- */
461
- void server_task(intptr_t uuid,
462
- void (*task)(intptr_t uuid, protocol_s *protocol, void *arg),
463
- void *arg, void (*fallback)(intptr_t uuid, void *arg));
464
- /** Creates a system timer (at the cost of 1 file descriptor) and pushes the
465
- timer to the reactor. The task will repeat `repetitions` times. if
466
- `repetitions` is set to 0, task will repeat forever. Returns -1 on error
467
- or the new file descriptor on succeess.
468
- */
469
- int server_run_every(size_t milliseconds, size_t repetitions,
470
- void (*task)(void *), void *arg,
471
- void (*on_finish)(void *));
472
-
473
- /** Creates a system timer (at the cost of 1 file descriptor) and pushes the
474
- timer to the reactor. The task will NOT repeat. Returns -1 on error or the
475
- new file descriptor on succeess. */
476
- UNUSED_FUNC static inline int server_run_after(size_t milliseconds,
477
- void task(void *), void *arg) {
478
- return server_run_every(milliseconds, 1, task, arg, NULL);
479
- }
480
-
481
- #endif