agoo 2.5.5 → 2.5.6

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.

Potentially problematic release.


This version of agoo might be problematic. Click here for more details.

Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/README.md +1 -1
  4. data/ext/agoo/agoo.c +4 -3
  5. data/ext/agoo/atomic.h +120 -0
  6. data/ext/agoo/bind.c +52 -52
  7. data/ext/agoo/bind.h +13 -13
  8. data/ext/agoo/con.c +499 -481
  9. data/ext/agoo/con.h +47 -39
  10. data/ext/agoo/debug.c +42 -42
  11. data/ext/agoo/debug.h +1 -1
  12. data/ext/agoo/doc.c +17 -17
  13. data/ext/agoo/doc.h +12 -12
  14. data/ext/agoo/err.c +18 -18
  15. data/ext/agoo/err.h +27 -27
  16. data/ext/agoo/error_stream.c +9 -9
  17. data/ext/agoo/extconf.rb +3 -0
  18. data/ext/agoo/gqlintro.c +43 -43
  19. data/ext/agoo/gqlintro.h +1 -1
  20. data/ext/agoo/gqlvalue.c +131 -131
  21. data/ext/agoo/gqlvalue.h +32 -32
  22. data/ext/agoo/graphql.c +158 -158
  23. data/ext/agoo/graphql.h +34 -33
  24. data/ext/agoo/hook.c +15 -14
  25. data/ext/agoo/hook.h +18 -14
  26. data/ext/agoo/http.c +14 -14
  27. data/ext/agoo/http.h +4 -4
  28. data/ext/agoo/kinds.h +5 -5
  29. data/ext/agoo/log.c +232 -224
  30. data/ext/agoo/log.h +93 -93
  31. data/ext/agoo/method.h +17 -17
  32. data/ext/agoo/page.c +88 -86
  33. data/ext/agoo/page.h +21 -21
  34. data/ext/agoo/pub.c +36 -36
  35. data/ext/agoo/pub.h +23 -23
  36. data/ext/agoo/queue.c +37 -38
  37. data/ext/agoo/queue.h +20 -19
  38. data/ext/agoo/rack_logger.c +13 -13
  39. data/ext/agoo/ready.c +357 -0
  40. data/ext/agoo/ready.h +41 -0
  41. data/ext/agoo/req.c +11 -11
  42. data/ext/agoo/req.h +30 -31
  43. data/ext/agoo/request.c +46 -46
  44. data/ext/agoo/request.h +2 -2
  45. data/ext/agoo/res.c +40 -18
  46. data/ext/agoo/res.h +14 -14
  47. data/ext/agoo/response.c +6 -6
  48. data/ext/agoo/response.h +9 -9
  49. data/ext/agoo/rhook.c +3 -3
  50. data/ext/agoo/rhook.h +1 -1
  51. data/ext/agoo/rlog.c +47 -42
  52. data/ext/agoo/rlog.h +0 -1
  53. data/ext/agoo/rresponse.c +33 -33
  54. data/ext/agoo/rresponse.h +1 -1
  55. data/ext/agoo/rserver.c +184 -175
  56. data/ext/agoo/rserver.h +2 -2
  57. data/ext/agoo/rupgraded.c +41 -41
  58. data/ext/agoo/rupgraded.h +3 -3
  59. data/ext/agoo/sdl.c +80 -80
  60. data/ext/agoo/sdl.h +1 -1
  61. data/ext/agoo/seg.h +2 -2
  62. data/ext/agoo/server.c +143 -117
  63. data/ext/agoo/server.h +43 -42
  64. data/ext/agoo/sse.c +7 -7
  65. data/ext/agoo/sse.h +4 -4
  66. data/ext/agoo/subject.c +5 -5
  67. data/ext/agoo/subject.h +6 -6
  68. data/ext/agoo/text.c +21 -21
  69. data/ext/agoo/text.h +14 -13
  70. data/ext/agoo/upgraded.c +41 -40
  71. data/ext/agoo/upgraded.h +41 -40
  72. data/ext/agoo/websocket.c +42 -42
  73. data/ext/agoo/websocket.h +16 -16
  74. data/lib/agoo/version.rb +1 -1
  75. data/test/static_test.rb +2 -0
  76. metadata +5 -5
  77. data/ext/agoo/log_queue.h +0 -30
  78. data/ext/agoo/sub.c +0 -111
  79. data/ext/agoo/sub.h +0 -36
@@ -3,17 +3,18 @@
3
3
  #ifndef AGOO_QUEUE_H
4
4
  #define AGOO_QUEUE_H
5
5
 
6
- #include <stdatomic.h>
7
6
  #include <stdbool.h>
8
7
  #include <stdlib.h>
9
8
 
10
- typedef void *QItem;
9
+ #include "atomic.h"
11
10
 
12
- typedef struct _Queue {
13
- QItem *q;
14
- QItem *end;
15
- _Atomic(QItem*) head;
16
- _Atomic(QItem*) tail;
11
+ typedef void *agooQItem;
12
+
13
+ typedef struct _agooQueue {
14
+ agooQItem *q;
15
+ agooQItem *end;
16
+ _Atomic(agooQItem*) head;
17
+ _Atomic(agooQItem*) tail;
17
18
  bool multi_push;
18
19
  bool multi_pop;
19
20
  atomic_flag push_lock; // set to true when push in progress
@@ -21,20 +22,20 @@ typedef struct _Queue {
21
22
  atomic_int wait_state;
22
23
  int rsock;
23
24
  int wsock;
24
- } *Queue;
25
+ } *agooQueue;
25
26
 
26
- extern void queue_init(Queue q, size_t qsize);
27
+ extern void agoo_queue_init(agooQueue q, size_t qsize);
27
28
 
28
- extern void queue_multi_init(Queue q, size_t qsize, bool multi_push, bool multi_pop);
29
+ extern void agoo_queue_multi_init(agooQueue q, size_t qsize, bool multi_push, bool multi_pop);
29
30
 
30
- extern void queue_cleanup(Queue q);
31
- extern void queue_push(Queue q, QItem item);
32
- extern QItem queue_pop(Queue q, double timeout);
33
- extern bool queue_empty(Queue q);
34
- extern int queue_listen(Queue q);
35
- extern void queue_release(Queue q);
36
- extern int queue_count(Queue q);
31
+ extern void agoo_queue_cleanup(agooQueue q);
32
+ extern void agoo_queue_push(agooQueue q, agooQItem item);
33
+ extern agooQItem agoo_queue_pop(agooQueue q, double timeout);
34
+ extern bool agoo_queue_empty(agooQueue q);
35
+ extern int agoo_queue_listen(agooQueue q);
36
+ extern void agoo_queue_release(agooQueue q);
37
+ extern int agoo_queue_count(agooQueue q);
37
38
 
38
- extern void queue_wakeup(Queue q);
39
+ extern void agoo_queue_wakeup(agooQueue q);
39
40
 
40
- #endif /* AGOO_QUEUE_H */
41
+ #endif // AGOO_QUEUE_H
@@ -15,26 +15,26 @@ rack_logger_new() {
15
15
  }
16
16
 
17
17
  static void
18
- log_message(LogCat cat, VALUE message) {
18
+ log_message(agooLogCat cat, VALUE message) {
19
19
  volatile VALUE rs = rb_funcall(message, rb_intern("to_s"), 0);
20
20
 
21
21
  rb_check_type(rs, T_STRING);
22
- if (!the_server.active) {
22
+ if (!agoo_server.active) {
23
23
  return;
24
24
  }
25
25
  if (rb_block_given_p()) {
26
- Text text = text_create(StringValuePtr(rs), (int)RSTRING_LEN(rs));
26
+ agooText text = agoo_text_create(StringValuePtr(rs), (int)RSTRING_LEN(rs));
27
27
  volatile VALUE x = rb_yield_values(0);
28
28
 
29
29
  if (Qnil != x) {
30
30
  rs = rb_funcall(x, rb_intern("to_s"), 0);
31
- text = text_append(text, ": ", 2);
32
- text = text_append(text, StringValuePtr(rs), (int)RSTRING_LEN(rs));
31
+ text = agoo_text_append(text, ": ", 2);
32
+ text = agoo_text_append(text, StringValuePtr(rs), (int)RSTRING_LEN(rs));
33
33
  }
34
- log_cat(cat, "%s", text->text);
35
- text_release(text);
34
+ agoo_log_cat(cat, "%s", text->text);
35
+ agoo_text_release(text);
36
36
  } else {
37
- log_cat(cat, "%s", StringValuePtr(rs));
37
+ agoo_log_cat(cat, "%s", StringValuePtr(rs));
38
38
  }
39
39
  }
40
40
 
@@ -46,7 +46,7 @@ log_message(LogCat cat, VALUE message) {
46
46
  */
47
47
  static VALUE
48
48
  rl_debug(VALUE self, VALUE message) {
49
- log_message(&debug_cat, message);
49
+ log_message(&agoo_debug_cat, message);
50
50
  return Qnil;
51
51
  }
52
52
 
@@ -58,7 +58,7 @@ rl_debug(VALUE self, VALUE message) {
58
58
  */
59
59
  static VALUE
60
60
  rl_info(VALUE self, VALUE message) {
61
- log_message(&info_cat, message);
61
+ log_message(&agoo_info_cat, message);
62
62
  return Qnil;
63
63
  }
64
64
 
@@ -70,7 +70,7 @@ rl_info(VALUE self, VALUE message) {
70
70
  */
71
71
  static VALUE
72
72
  rl_warn(VALUE self, VALUE message) {
73
- log_message(&warn_cat, message);
73
+ log_message(&agoo_warn_cat, message);
74
74
  return Qnil;
75
75
  }
76
76
 
@@ -82,7 +82,7 @@ rl_warn(VALUE self, VALUE message) {
82
82
  */
83
83
  static VALUE
84
84
  rl_error(VALUE self, VALUE message) {
85
- log_message(&error_cat, message);
85
+ log_message(&agoo_error_cat, message);
86
86
  return Qnil;
87
87
  }
88
88
 
@@ -94,7 +94,7 @@ rl_error(VALUE self, VALUE message) {
94
94
  */
95
95
  static VALUE
96
96
  rl_fatal(VALUE self, VALUE message) {
97
- log_message(&fatal_cat, message);
97
+ log_message(&agoo_fatal_cat, message);
98
98
  exit(0);
99
99
  return Qnil;
100
100
  }
@@ -0,0 +1,357 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #include <stdio.h>
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+ #include <unistd.h>
7
+
8
+ #if HAVE_SYS_EPOLL_H
9
+ #include <sys/epoll.h>
10
+ #else
11
+ #include <ctype.h>
12
+ #include <netdb.h>
13
+ #include <poll.h>
14
+ #endif
15
+
16
+ #include "dtime.h"
17
+ #include "log.h"
18
+ #include "ready.h"
19
+
20
+ #define CHECK_FREQ 0.5
21
+ // milliseconds
22
+ #define MAX_WAIT 10
23
+
24
+ #if HAVE_SYS_EPOLL_H
25
+ #define EPOLL_SIZE 100
26
+ #else
27
+ #define INITIAL_POLL_SIZE 1024
28
+ #endif
29
+
30
+ typedef struct _link {
31
+ struct _link *next;
32
+ struct _link *prev;
33
+ int fd;
34
+ void *ctx;
35
+ agooHandler handler;
36
+ #if HAVE_SYS_EPOLL_H
37
+ uint32_t events; // last events set
38
+ #else
39
+ struct pollfd *pp;
40
+ #endif
41
+ } *Link;
42
+
43
+ struct _agooReady {
44
+ Link links;
45
+ int lcnt;
46
+ double next_check;
47
+ #if HAVE_SYS_EPOLL_H
48
+ int epoll_fd;
49
+ #else
50
+ struct pollfd *pa;
51
+ struct pollfd *pend;
52
+ #endif
53
+ };
54
+
55
+ static Link
56
+ link_create(agooErr err, int fd, void *ctx, agooHandler handler) {
57
+ // TBD use block allocator
58
+ Link link = (Link)malloc(sizeof(struct _link));
59
+
60
+ if (NULL == link) {
61
+ agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a connection link.");
62
+ } else {
63
+ //DEBUG_ALLOC(mem_???, c);
64
+ link->next = NULL;
65
+ link->prev = NULL;
66
+ link->fd = fd;
67
+ link->ctx = ctx;
68
+ link->handler = handler;
69
+ }
70
+ return link;
71
+ }
72
+
73
+ agooReady
74
+ agoo_ready_create(agooErr err) {
75
+ agooReady ready = (agooReady)malloc(sizeof(struct _agooReady));
76
+
77
+ if (NULL == ready) {
78
+ agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a connection manager.");
79
+ } else {
80
+ //DEBUG_ALLOC(mem_???, c);
81
+ ready->links = NULL;
82
+ ready->lcnt = 0;
83
+ ready->next_check = dtime() + CHECK_FREQ;
84
+ #if HAVE_SYS_EPOLL_H
85
+ if (0 > (ready->epoll_fd = epoll_create(1))) {
86
+ agoo_err_no(err, "epoll create failed");
87
+ return NULL;
88
+ }
89
+ #else
90
+ {
91
+ size_t size = sizeof(struct pollfd) * INITIAL_POLL_SIZE;
92
+
93
+ ready->pa = (struct pollfd*)malloc(size);
94
+ ready->pend = ready->pa + INITIAL_POLL_SIZE;
95
+ memset(ready->pa, 0, size);
96
+ }
97
+ #endif
98
+ }
99
+ return ready;
100
+ }
101
+
102
+ void
103
+ agoo_ready_destroy(agooReady ready) {
104
+ Link link;
105
+
106
+ while (NULL != (link = ready->links)) {
107
+ ready->links = link->next;
108
+ if (NULL != link->handler->destroy) {
109
+ link->handler->destroy(link->ctx);
110
+ }
111
+ free(link);
112
+ }
113
+ #if HAVE_SYS_EPOLL_H
114
+ close(ready->epoll_fd);
115
+ #else
116
+ free(ready->pa);
117
+ #endif
118
+ free(ready);
119
+ }
120
+
121
+ int
122
+ agoo_ready_add(agooErr err,
123
+ agooReady ready,
124
+ int fd,
125
+ agooHandler handler,
126
+ void *ctx) {
127
+ Link link;
128
+
129
+ if (NULL == (link = link_create(err, fd, ctx, handler))) {
130
+ return err->code;
131
+ }
132
+ link->next = ready->links;
133
+ if (NULL != ready->links) {
134
+ ready->links->prev = link;
135
+ }
136
+ ready->links = link;
137
+ ready->lcnt++;
138
+
139
+ #if HAVE_SYS_EPOLL_H
140
+ link->events = EPOLLIN;
141
+ {
142
+ struct epoll_event event = {
143
+ .events = link->events,
144
+ .data = {
145
+ .ptr = link,
146
+ },
147
+ };
148
+ if (0 > epoll_ctl(ready->epoll_fd, EPOLL_CTL_ADD, fd, &event)) {
149
+ agoo_err_no(err, "epoll add failed");
150
+ return err->code;
151
+ }
152
+ }
153
+ #else
154
+ if (ready->pend - ready->pa <= ready->lcnt) {
155
+ size_t cnt = (ready->pend - ready->pa) * 2;
156
+ size_t size = cnt * sizeof(struct pollfd);
157
+
158
+ if (NULL == (ready->pa = (struct pollfd*)realloc(ready->pa, size))) {
159
+ agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for a connection pool.");
160
+ agoo_log_cat(&agoo_error_cat, "Out of memory.");
161
+ agoo_log_close();
162
+ exit(EXIT_FAILURE);
163
+
164
+ return err->code;
165
+ }
166
+ ready->pend = ready->pa + cnt;
167
+ memset(ready->pa, 0, size);
168
+ }
169
+ #endif
170
+ return AGOO_ERR_OK;
171
+ }
172
+
173
+ static void
174
+ ready_remove(agooReady ready, Link link) {
175
+ if (NULL == link->prev) {
176
+ ready->links = link->next;
177
+ } else {
178
+ link->prev->next = link->next;
179
+ }
180
+ if (NULL != link->next) {
181
+ link->next->prev = link->prev;
182
+ }
183
+ #if HAVE_SYS_EPOLL_H
184
+ {
185
+ struct epoll_event event = {
186
+ .events = 0,
187
+ .data = {
188
+ .ptr = NULL,
189
+ },
190
+ };
191
+ if (0 > epoll_ctl(ready->epoll_fd, EPOLL_CTL_DEL, link->fd, &event)) {
192
+ agoo_log_cat(&agoo_error_cat, "epoll delete failed. %s", strerror(errno));
193
+ }
194
+ }
195
+ #endif
196
+ if (NULL != link->handler->destroy) {
197
+ link->handler->destroy(link->ctx);
198
+ }
199
+ //DEBUG_FREE(mem_???, c);
200
+ free(link);
201
+ ready->lcnt--;
202
+ }
203
+
204
+ int
205
+ agoo_ready_go(agooErr err, agooReady ready) {
206
+ double now;
207
+ Link link;
208
+ Link next;
209
+
210
+ #if HAVE_SYS_EPOLL_H
211
+ struct epoll_event events[EPOLL_SIZE];
212
+ struct epoll_event *ep;
213
+ int cnt;
214
+
215
+ for (link = ready->links; NULL != link; link = link->next) {
216
+ struct epoll_event event = {
217
+ .events = 0,
218
+ .data = {
219
+ .ptr = link,
220
+ },
221
+ };
222
+ switch (link->handler->io(link->ctx)) {
223
+ case AGOO_READY_IN:
224
+ event.events = EPOLLIN;
225
+ break;
226
+ case AGOO_READY_OUT:
227
+ event.events = EPOLLOUT;
228
+ break;
229
+ case AGOO_READY_BOTH:
230
+ event.events = EPOLLIN | EPOLLOUT;
231
+ break;
232
+ case AGOO_READY_NONE:
233
+ default:
234
+ // ignore, either dead or closing
235
+ break;
236
+ }
237
+ if (event.events != link->events) {
238
+ if (0 > epoll_ctl(ready->epoll_fd, EPOLL_CTL_MOD, link->fd, &event)) {
239
+ agoo_err_no(err, "epoll modifiy failed");
240
+ }
241
+ link->events = event.events;
242
+ }
243
+ }
244
+ if (0 > (cnt = epoll_wait(ready->epoll_fd, events, sizeof(events) / sizeof(*events), MAX_WAIT))) {
245
+ agoo_err_no(err, "Polling error.");
246
+ agoo_log_cat(&agoo_error_cat, "%s", err->msg);
247
+ return err->code;
248
+ }
249
+ for (ep = events; 0 < cnt; ep++, cnt--) {
250
+ link = (Link)ep->data.ptr;
251
+ if (0 != (ep->events & EPOLLIN) && NULL != link->handler->read) {
252
+ if (!link->handler->read(ready, link->ctx)) {
253
+ ready_remove(ready, link);
254
+ continue;
255
+ }
256
+ }
257
+ if (0 != (ep->events & EPOLLOUT && NULL != link->handler->write)) {
258
+ if (!link->handler->write(link->ctx)) {
259
+ ready_remove(ready, link);
260
+ continue;
261
+ }
262
+ }
263
+ if (0 != (ep->events & (EPOLLERR | EPOLLRDHUP | EPOLLHUP | EPOLLPRI))) {
264
+ if (NULL != link->handler->error) {
265
+ link->handler->error(link->ctx);
266
+ }
267
+ ready_remove(ready, link);
268
+ continue;
269
+ }
270
+ }
271
+ #else
272
+ struct pollfd *pp;
273
+ int i;
274
+
275
+ // Setup the poll events.
276
+ for (link = ready->links, pp = ready->pa; NULL != link; link = link->next, pp++) {
277
+ pp->fd = link->fd;
278
+ pp->revents = 0;
279
+ link->pp = pp;
280
+ switch (link->handler->io(link->ctx)) {
281
+ case AGOO_READY_IN:
282
+ pp->events = POLLIN;
283
+ break;
284
+ case AGOO_READY_OUT:
285
+ pp->events = POLLOUT;
286
+ break;
287
+ case AGOO_READY_BOTH:
288
+ pp->events = POLLIN | POLLOUT;
289
+ break;
290
+ case AGOO_READY_NONE:
291
+ default:
292
+ // ignore, either dead or closing
293
+ pp--;
294
+ break;
295
+ }
296
+ }
297
+ if (0 > (i = poll(ready->pa, (nfds_t)(pp - ready->pa), MAX_WAIT))) {
298
+ if (EAGAIN == errno) {
299
+ return AGOO_ERR_OK;
300
+ }
301
+ agoo_err_no(err, "Polling error.");
302
+ agoo_log_cat(&agoo_error_cat, "%s", err->msg);
303
+ return err->code;
304
+ }
305
+ if (0 < i) {
306
+ for (link = ready->links; NULL != link; link = next) {
307
+ next = link->next;
308
+ if (NULL == link->pp) {
309
+ continue;
310
+ }
311
+ pp = link->pp;
312
+ if (0 != (pp->revents & POLLIN) && NULL != link->handler->read) {
313
+ if (!link->handler->read(ready, link->ctx)) {
314
+ ready_remove(ready, link);
315
+ continue;
316
+ }
317
+ }
318
+ if (0 != (pp->revents & POLLOUT && NULL != link->handler->write)) {
319
+ if (!link->handler->write(link->ctx)) {
320
+ ready_remove(ready, link);
321
+ continue;
322
+ }
323
+ }
324
+ if (0 != (pp->revents & (POLLERR | POLLHUP | POLLNVAL))) {
325
+ if (NULL != link->handler->error) {
326
+ link->handler->error(link->ctx);
327
+ }
328
+ ready_remove(ready, link);
329
+ continue;
330
+ }
331
+ }
332
+ }
333
+ #endif
334
+ // Periodically check the connections to see if they are dead or not.
335
+ now = dtime();
336
+ if (ready->next_check <= now) {
337
+ for (link = ready->links; NULL != link; link = next) {
338
+ next = link->next;
339
+ if (NULL != link->handler->check) {
340
+ if (!link->handler->check(link->ctx, now)) {
341
+ ready_remove(ready, link);
342
+ }
343
+ }
344
+ }
345
+ ready->next_check = dtime() + CHECK_FREQ;
346
+ }
347
+ return AGOO_ERR_OK;
348
+ }
349
+
350
+ void
351
+ agoo_ready_iterate(agooReady ready, void (*cb)(void *ctx, void *arg), void *arg) {
352
+ Link link;
353
+
354
+ for (link = ready->links; NULL != link; link = link->next) {
355
+ cb(link->ctx, arg);
356
+ }
357
+ }