agoo 2.15.6 → 2.15.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/bin/agoo +47 -39
- data/ext/agoo/bind.c +209 -198
- data/ext/agoo/rgraphql.c +7 -4
- data/ext/agoo/rserver.c +689 -688
- data/ext/agoo/sdl.c +13 -2
- data/ext/agoo/server.c +255 -253
- data/lib/agoo/version.rb +1 -1
- data/lib/rack/handler/agoo.rb +130 -128
- metadata +3 -3
data/ext/agoo/server.c
CHANGED
@@ -26,11 +26,11 @@
|
|
26
26
|
|
27
27
|
#include "server.h"
|
28
28
|
|
29
|
-
#define LOOP_UP
|
29
|
+
#define LOOP_UP 100
|
30
30
|
|
31
|
-
struct _agooServer
|
31
|
+
struct _agooServer agoo_server = {false};
|
32
32
|
|
33
|
-
double
|
33
|
+
double agoo_io_loop_ratio = 0.5;
|
34
34
|
|
35
35
|
int
|
36
36
|
agoo_server_setup(agooErr err) {
|
@@ -41,19 +41,19 @@ agoo_server_setup(agooErr err) {
|
|
41
41
|
agoo_server.max_push_pending = 32;
|
42
42
|
|
43
43
|
if (AGOO_ERR_OK != agoo_pages_init(err) ||
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
AGOO_ERR_OK != agoo_queue_multi_init(err, &agoo_server.con_queue, 1024, false, true) ||
|
45
|
+
AGOO_ERR_OK != agoo_queue_multi_init(err, &agoo_server.eval_queue, 1024, true, true)) {
|
46
|
+
return err->code;
|
47
47
|
}
|
48
|
-
long
|
48
|
+
long i;
|
49
49
|
|
50
50
|
agoo_server.loop_max = 4;
|
51
51
|
if (0 < (i = sysconf(_SC_NPROCESSORS_ONLN))) {
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
i = (int)(i * agoo_io_loop_ratio);
|
53
|
+
if (1 >= i) {
|
54
|
+
i = 1;
|
55
|
+
}
|
56
|
+
agoo_server.loop_max = (int)i;
|
57
57
|
}
|
58
58
|
return AGOO_ERR_OK;
|
59
59
|
}
|
@@ -61,8 +61,8 @@ agoo_server_setup(agooErr err) {
|
|
61
61
|
#ifdef HAVE_OPENSSL_SSL_H
|
62
62
|
static int
|
63
63
|
ssl_error(agooErr err, const char *filename, int line) {
|
64
|
-
char
|
65
|
-
unsigned long
|
64
|
+
char buf[224];
|
65
|
+
unsigned long e = ERR_get_error();
|
66
66
|
|
67
67
|
ERR_error_string_n(e, buf, sizeof(buf));
|
68
68
|
|
@@ -76,18 +76,18 @@ agoo_server_ssl_init(agooErr err, const char *cert_pem, const char *key_pem) {
|
|
76
76
|
SSL_load_error_strings();
|
77
77
|
SSL_library_init();
|
78
78
|
if (NULL == (agoo_server.ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
|
79
|
-
|
79
|
+
return ssl_error(err, __FILE__, __LINE__);
|
80
80
|
}
|
81
81
|
SSL_CTX_set_ecdh_auto(agoo_server.ssl_ctx, 1);
|
82
82
|
|
83
83
|
if (!SSL_CTX_use_certificate_file(agoo_server.ssl_ctx, cert_pem, SSL_FILETYPE_PEM)) {
|
84
|
-
|
84
|
+
return ssl_error(err, __FILE__, __LINE__);
|
85
85
|
}
|
86
86
|
if (!SSL_CTX_use_PrivateKey_file(agoo_server.ssl_ctx, key_pem, SSL_FILETYPE_PEM)) {
|
87
|
-
|
87
|
+
return ssl_error(err, __FILE__, __LINE__);
|
88
88
|
}
|
89
89
|
if (!SSL_CTX_check_private_key(agoo_server.ssl_ctx)) {
|
90
|
-
|
90
|
+
return agoo_err_set(err, AGOO_ERR_TLS, "TLS private key check failed");
|
91
91
|
}
|
92
92
|
#endif
|
93
93
|
return AGOO_ERR_OK;
|
@@ -95,94 +95,96 @@ agoo_server_ssl_init(agooErr err, const char *cert_pem, const char *key_pem) {
|
|
95
95
|
|
96
96
|
static void
|
97
97
|
add_con_loop() {
|
98
|
-
struct _agooErr
|
99
|
-
agooConLoop
|
98
|
+
struct _agooErr err = AGOO_ERR_INIT;
|
99
|
+
agooConLoop loop = agoo_conloop_create(&err, 0);
|
100
100
|
|
101
101
|
if (NULL != loop) {
|
102
|
-
|
103
|
-
|
104
|
-
|
102
|
+
loop->next = agoo_server.con_loops;
|
103
|
+
agoo_server.con_loops = loop;
|
104
|
+
agoo_server.loop_cnt++;
|
105
105
|
}
|
106
106
|
}
|
107
107
|
|
108
108
|
static void*
|
109
109
|
listen_loop(void *x) {
|
110
|
-
int
|
111
|
-
struct pollfd
|
112
|
-
struct pollfd
|
113
|
-
struct _agooErr
|
114
|
-
struct sockaddr_in
|
115
|
-
int
|
116
|
-
int
|
117
|
-
socklen_t
|
118
|
-
agooCon
|
119
|
-
int
|
120
|
-
uint64_t
|
121
|
-
agooBind
|
110
|
+
int optval = 1;
|
111
|
+
struct pollfd pa[100];
|
112
|
+
struct pollfd *p;
|
113
|
+
struct _agooErr err = AGOO_ERR_INIT;
|
114
|
+
struct sockaddr_in client_addr;
|
115
|
+
int client_sock;
|
116
|
+
int pcnt = 0;
|
117
|
+
socklen_t alen = 0;
|
118
|
+
agooCon con;
|
119
|
+
int i;
|
120
|
+
uint64_t cnt = 0;
|
121
|
+
agooBind b;
|
122
122
|
|
123
123
|
for (b = agoo_server.binds, p = pa; NULL != b; b = b->next, p++, pcnt++) {
|
124
|
-
|
125
|
-
|
126
|
-
|
124
|
+
p->fd = b->fd;
|
125
|
+
p->events = POLLIN;
|
126
|
+
p->revents = 0;
|
127
127
|
}
|
128
128
|
memset(&client_addr, 0, sizeof(client_addr));
|
129
129
|
atomic_fetch_add(&agoo_server.running, 1);
|
130
130
|
while (agoo_server.active) {
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
131
|
+
if (0 > (i = poll(pa, pcnt, 200))) {
|
132
|
+
if (EAGAIN == errno) {
|
133
|
+
continue;
|
134
|
+
}
|
135
|
+
agoo_log_cat(&agoo_error_cat, "Server polling error. %s.", strerror(errno));
|
136
|
+
// Either a signal or something bad like out of memory. Might as well exit.
|
137
|
+
break;
|
138
|
+
}
|
139
|
+
if (0 == i) { // nothing to read
|
140
|
+
continue;
|
141
|
+
}
|
142
|
+
for (b = agoo_server.binds, p = pa; NULL != b; b = b->next, p++) {
|
143
|
+
if (0 != (p->revents & POLLIN)) {
|
144
|
+
if (0 > (client_sock = accept(p->fd, (struct sockaddr*)&client_addr, &alen))) {
|
145
|
+
agoo_log_cat(&agoo_error_cat, "Server with pid %d accept connection failed. %s.", getpid(), strerror(errno));
|
146
|
+
} else if (NULL == (con = agoo_con_create(&err, client_sock, ++cnt, b))) {
|
147
|
+
agoo_log_cat(&agoo_error_cat, "Server with pid %d accept connection failed. %s.", getpid(), err.msg);
|
148
|
+
close(client_sock);
|
149
|
+
cnt--;
|
150
|
+
agoo_err_clear(&err);
|
151
|
+
} else {
|
152
|
+
int con_cnt;
|
153
153
|
#ifdef OSX_OS
|
154
|
-
|
154
|
+
setsockopt(client_sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));
|
155
155
|
#endif
|
156
156
|
#ifdef PLATFORM_LINUX
|
157
|
-
|
157
|
+
setsockopt(client_sock, IPPROTO_TCP, TCP_QUICKACK, &optval, sizeof(optval));
|
158
158
|
#endif
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
159
|
+
fcntl(client_sock, F_SETFL, O_NONBLOCK);
|
160
|
+
//fcntl(client_sock, F_SETFL, FNDELAY);
|
161
|
+
setsockopt(client_sock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
|
162
|
+
setsockopt(client_sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));
|
163
|
+
agoo_log_cat(&agoo_con_cat, "Server with pid %d accepted connection %llu on %s [%d] from %s",
|
164
|
+
getpid(), (unsigned long long)cnt, b->id, con->sock, con->remote);
|
165
|
+
|
166
|
+
con_cnt = atomic_fetch_add(&agoo_server.con_cnt, 1);
|
167
|
+
/* TBD
|
168
|
+
if (agoo_server.loop_max > agoo_server.loop_cnt && agoo_server.loop_cnt * LOOP_UP < con_cnt) {
|
169
|
+
add_con_loop();
|
170
|
+
}
|
171
|
+
*/
|
172
|
+
agoo_queue_push(&agoo_server.con_queue, (void*)con);
|
173
|
+
}
|
174
|
+
}
|
175
|
+
if (0 != (p->revents & (POLLERR | POLLHUP | POLLNVAL))) {
|
176
|
+
if (0 != (p->revents & (POLLHUP | POLLNVAL))) {
|
177
|
+
agoo_log_cat(&agoo_error_cat, "Agoo server with pid %d socket on %s closed.", getpid(), b->id);
|
178
|
+
} else {
|
179
|
+
agoo_log_cat(&agoo_error_cat, "Agoo server with pid %d socket on %s error.", getpid(), b->id);
|
180
|
+
}
|
181
|
+
agoo_server.active = false;
|
182
|
+
}
|
183
|
+
p->revents = 0;
|
184
|
+
}
|
183
185
|
}
|
184
186
|
for (b = agoo_server.binds; NULL != b; b = b->next) {
|
185
|
-
|
187
|
+
agoo_bind_close(b);
|
186
188
|
}
|
187
189
|
atomic_fetch_sub(&agoo_server.running, 1);
|
188
190
|
|
@@ -191,12 +193,12 @@ listen_loop(void *x) {
|
|
191
193
|
|
192
194
|
int
|
193
195
|
agoo_server_start(agooErr err, const char *app_name, const char *version) {
|
194
|
-
double
|
195
|
-
int
|
196
|
-
int
|
196
|
+
double giveup;
|
197
|
+
int xcnt = 0;
|
198
|
+
int stat;
|
197
199
|
|
198
200
|
if (0 != (stat = pthread_create(&agoo_server.listen_thread, NULL, listen_loop, NULL))) {
|
199
|
-
|
201
|
+
return agoo_err_set(err, stat, "Failed to create server listener thread. %s", strerror(stat));
|
200
202
|
}
|
201
203
|
xcnt++;
|
202
204
|
agoo_server.con_loops = agoo_conloop_create(err, 0);
|
@@ -207,36 +209,36 @@ agoo_server_start(agooErr err, const char *app_name, const char *version) {
|
|
207
209
|
// might as well create the maximum number of con threads as is
|
208
210
|
// reasonable.
|
209
211
|
if (1 >= agoo_server.thread_cnt) {
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
212
|
+
while (agoo_server.loop_cnt < agoo_server.loop_max) {
|
213
|
+
add_con_loop();
|
214
|
+
xcnt++;
|
215
|
+
}
|
214
216
|
}
|
215
217
|
giveup = dtime() + 1.0;
|
216
218
|
while (dtime() < giveup) {
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
219
|
+
if (xcnt <= (long)atomic_load(&agoo_server.running)) {
|
220
|
+
break;
|
221
|
+
}
|
222
|
+
dsleep(0.01);
|
221
223
|
}
|
222
224
|
if (agoo_info_cat.on) {
|
223
|
-
|
225
|
+
agooBind b;
|
224
226
|
|
225
|
-
|
226
|
-
|
227
|
-
|
227
|
+
for (b = agoo_server.binds; NULL != b; b = b->next) {
|
228
|
+
agoo_log_cat(&agoo_info_cat, "%s %s with pid %d is listening on %s.", app_name, version, getpid(), b->id);
|
229
|
+
}
|
228
230
|
}
|
229
231
|
return AGOO_ERR_OK;
|
230
232
|
}
|
231
233
|
|
232
234
|
int
|
233
235
|
setup_listen(agooErr err) {
|
234
|
-
agooBind
|
236
|
+
agooBind b;
|
235
237
|
|
236
238
|
for (b = agoo_server.binds; NULL != b; b = b->next) {
|
237
|
-
|
238
|
-
|
239
|
-
|
239
|
+
if (AGOO_ERR_OK != agoo_bind_listen(err, b)) {
|
240
|
+
return err->code;
|
241
|
+
}
|
240
242
|
}
|
241
243
|
agoo_server.active = true;
|
242
244
|
|
@@ -246,55 +248,55 @@ setup_listen(agooErr err) {
|
|
246
248
|
void
|
247
249
|
agoo_server_shutdown(const char *app_name, void (*stop)()) {
|
248
250
|
if (agoo_server.inited) {
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
251
|
+
agooConLoop loop;
|
252
|
+
|
253
|
+
agoo_log_cat(&agoo_info_cat, "%s with pid %d shutting down.", app_name, getpid());
|
254
|
+
agoo_server.inited = false;
|
255
|
+
if (agoo_server.active) {
|
256
|
+
double giveup = dtime() + 1.0;
|
257
|
+
|
258
|
+
agoo_server.active = false;
|
259
|
+
pthread_detach(agoo_server.listen_thread);
|
260
|
+
for (loop = agoo_server.con_loops; NULL != loop; loop = loop->next) {
|
261
|
+
pthread_detach(loop->thread);
|
262
|
+
}
|
263
|
+
while (0 < (long)atomic_load(&agoo_server.running)) {
|
264
|
+
dsleep(0.1);
|
265
|
+
if (giveup < dtime()) {
|
266
|
+
break;
|
267
|
+
}
|
268
|
+
}
|
269
|
+
if (NULL != stop) {
|
270
|
+
stop();
|
271
|
+
}
|
272
|
+
while (NULL != agoo_server.hooks) {
|
273
|
+
agooHook h = agoo_server.hooks;
|
274
|
+
|
275
|
+
agoo_server.hooks = h->next;
|
276
|
+
agoo_hook_destroy(h);
|
277
|
+
}
|
278
|
+
}
|
279
|
+
while (NULL != agoo_server.binds) {
|
280
|
+
agooBind b = agoo_server.binds;
|
281
|
+
|
282
|
+
agoo_server.binds = b->next;
|
283
|
+
agoo_bind_destroy(b);
|
284
|
+
}
|
285
|
+
agoo_queue_cleanup(&agoo_server.con_queue);
|
286
|
+
while (NULL != (loop = agoo_server.con_loops)) {
|
287
|
+
agoo_server.con_loops = loop->next;
|
288
|
+
agoo_conloop_destroy(loop);
|
289
|
+
}
|
290
|
+
agoo_queue_cleanup(&agoo_server.eval_queue);
|
291
|
+
|
292
|
+
agoo_pages_cleanup();
|
293
|
+
agoo_http_cleanup();
|
294
|
+
agoo_domain_cleanup();
|
293
295
|
#ifdef HAVE_OPENSSL_SSL_H
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
296
|
+
if (NULL != agoo_server.ssl_ctx) {
|
297
|
+
SSL_CTX_free(agoo_server.ssl_ctx);
|
298
|
+
EVP_cleanup();
|
299
|
+
}
|
298
300
|
#endif
|
299
301
|
}
|
300
302
|
}
|
@@ -302,30 +304,30 @@ agoo_server_shutdown(const char *app_name, void (*stop)()) {
|
|
302
304
|
void
|
303
305
|
agoo_server_bind(agooBind b) {
|
304
306
|
// If a bind with the same port already exists, replace it.
|
305
|
-
agooBind
|
306
|
-
agooBind
|
307
|
+
agooBind prev = NULL;
|
308
|
+
agooBind bx = NULL;
|
307
309
|
|
308
310
|
if (NULL == b->read) {
|
309
|
-
|
311
|
+
b->read = agoo_con_http_read;
|
310
312
|
}
|
311
313
|
if (NULL == b->write) {
|
312
|
-
|
314
|
+
b->write = agoo_con_http_write;
|
313
315
|
}
|
314
316
|
if (NULL == b->events) {
|
315
|
-
|
317
|
+
b->events = agoo_con_http_events;
|
316
318
|
}
|
317
319
|
for (bx = agoo_server.binds; NULL != bx; bx = bx->next) {
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
320
|
+
if (bx->port == b->port) {
|
321
|
+
b->next = bx->next;
|
322
|
+
if (NULL == prev) {
|
323
|
+
agoo_server.binds = b;
|
324
|
+
} else {
|
325
|
+
prev->next = b;
|
326
|
+
}
|
327
|
+
agoo_bind_destroy(bx);
|
328
|
+
return;
|
329
|
+
}
|
330
|
+
prev = bx;
|
329
331
|
}
|
330
332
|
b->next = agoo_server.binds;
|
331
333
|
agoo_server.binds = b;
|
@@ -335,9 +337,9 @@ void
|
|
335
337
|
agoo_server_add_upgraded(agooUpgraded up) {
|
336
338
|
pthread_mutex_lock(&agoo_server.up_lock);
|
337
339
|
if (NULL == agoo_server.up_list) {
|
338
|
-
|
340
|
+
up->next = NULL;
|
339
341
|
} else {
|
340
|
-
|
342
|
+
agoo_server.up_list->prev = up;
|
341
343
|
}
|
342
344
|
up->next = agoo_server.up_list;
|
343
345
|
agoo_server.up_list = up;
|
@@ -346,41 +348,41 @@ agoo_server_add_upgraded(agooUpgraded up) {
|
|
346
348
|
}
|
347
349
|
|
348
350
|
int
|
349
|
-
agoo_server_add_func_hook(agooErr
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
agooHook
|
356
|
-
agooHook
|
357
|
-
agooHook
|
351
|
+
agoo_server_add_func_hook(agooErr err,
|
352
|
+
agooMethod method,
|
353
|
+
const char *pattern,
|
354
|
+
void (*func)(agooReq req),
|
355
|
+
agooQueue queue,
|
356
|
+
bool quick) {
|
357
|
+
agooHook h;
|
358
|
+
agooHook prev = NULL;
|
359
|
+
agooHook hook = agoo_hook_func_create(method, pattern, func, queue);
|
358
360
|
|
359
361
|
if (NULL == hook) {
|
360
|
-
|
362
|
+
return AGOO_ERR_MEM(err, "HTTP Server Hook");
|
361
363
|
}
|
362
364
|
hook->no_queue = quick;
|
363
365
|
for (h = agoo_server.hooks; NULL != h; h = h->next) {
|
364
|
-
|
366
|
+
prev = h;
|
365
367
|
}
|
366
368
|
if (NULL != prev) {
|
367
|
-
|
369
|
+
prev->next = hook;
|
368
370
|
} else {
|
369
|
-
|
371
|
+
agoo_server.hooks = hook;
|
370
372
|
}
|
371
373
|
return AGOO_ERR_OK;
|
372
374
|
}
|
373
375
|
|
374
376
|
void
|
375
377
|
agoo_server_publish(struct _agooPub *pub) {
|
376
|
-
agooConLoop
|
378
|
+
agooConLoop loop;
|
377
379
|
|
378
380
|
for (loop = agoo_server.con_loops; NULL != loop; loop = loop->next) {
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
381
|
+
if (NULL == loop->next) {
|
382
|
+
agoo_queue_push(&loop->pub_queue, pub);
|
383
|
+
} else {
|
384
|
+
agoo_queue_push(&loop->pub_queue, agoo_pub_dup(pub));
|
385
|
+
}
|
384
386
|
}
|
385
387
|
}
|
386
388
|
|
@@ -394,19 +396,19 @@ agoo_server_add_gsub(gqlSub sub) {
|
|
394
396
|
|
395
397
|
void
|
396
398
|
agoo_server_del_gsub(gqlSub sub) {
|
397
|
-
gqlSub
|
398
|
-
gqlSub
|
399
|
+
gqlSub s;
|
400
|
+
gqlSub prev = NULL;
|
399
401
|
|
400
402
|
pthread_mutex_lock(&agoo_server.up_lock);
|
401
403
|
for (s = agoo_server.gsub_list; NULL != s; s = s->next) {
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
404
|
+
if (s == sub) {
|
405
|
+
if (NULL == prev) {
|
406
|
+
agoo_server.gsub_list = s->next;
|
407
|
+
} else {
|
408
|
+
prev->next = s->next;
|
409
|
+
}
|
410
|
+
}
|
411
|
+
prev = s;
|
410
412
|
}
|
411
413
|
pthread_mutex_unlock(&agoo_server.up_lock);
|
412
414
|
}
|
@@ -414,79 +416,79 @@ agoo_server_del_gsub(gqlSub sub) {
|
|
414
416
|
static bool
|
415
417
|
subject_check(const char *pattern, const char *subject) {
|
416
418
|
for (; '\0' != *pattern && '\0' != *subject; subject++) {
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
419
|
+
if (*subject == *pattern) {
|
420
|
+
pattern++;
|
421
|
+
} else if ('*' == *pattern) {
|
422
|
+
for (; '\0' != *subject && '.' != *subject; subject++) {
|
423
|
+
}
|
424
|
+
if ('\0' == *subject) {
|
425
|
+
return true;
|
426
|
+
}
|
427
|
+
pattern++;
|
428
|
+
} else if ('>' == *pattern) {
|
429
|
+
return true;
|
430
|
+
} else {
|
431
|
+
break;
|
432
|
+
}
|
431
433
|
}
|
432
434
|
return '\0' == *pattern && '\0' == *subject;
|
433
435
|
}
|
434
436
|
|
435
437
|
static agooText
|
436
438
|
gpub_eval(agooErr err, gqlDoc query, gqlRef event) {
|
437
|
-
agooText
|
438
|
-
gqlSel
|
439
|
-
gqlValue
|
439
|
+
agooText t = NULL;
|
440
|
+
gqlSel sel;
|
441
|
+
gqlValue result;
|
440
442
|
|
441
443
|
if (NULL == query->ops || NULL == query->ops->sels) {
|
442
|
-
|
443
|
-
|
444
|
+
agoo_err_set(err, AGOO_ERR_TYPE, "subscription not valid");
|
445
|
+
return NULL;
|
444
446
|
}
|
445
447
|
sel = query->ops->sels;
|
446
448
|
if (NULL != (result = gql_object_create(err))) {
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
449
|
+
struct _gqlField field;
|
450
|
+
|
451
|
+
memset(&field, 0, sizeof(field));
|
452
|
+
field.type = sel->type;
|
453
|
+
if (AGOO_ERR_OK != gql_eval_sels(err, query, event, &field, sel->sels, result, 0)) {
|
454
|
+
gql_value_destroy(result);
|
455
|
+
return NULL;
|
456
|
+
}
|
457
|
+
if (NULL == (t = agoo_text_allocate(1024))) {
|
458
|
+
AGOO_ERR_MEM(err, "Text");
|
459
|
+
return NULL;
|
460
|
+
}
|
461
|
+
t = gql_value_json(t, result, 0, 0);
|
462
|
+
gql_value_destroy(result);
|
461
463
|
}
|
462
464
|
return t;
|
463
465
|
}
|
464
466
|
|
465
467
|
int
|
466
468
|
agoo_server_gpublish(agooErr err, const char *subject, gqlRef event) {
|
467
|
-
gqlSub
|
468
|
-
gqlType
|
469
|
+
gqlSub sub;
|
470
|
+
gqlType type;
|
469
471
|
|
470
472
|
if (NULL == gql_type_func || NULL == (type = gql_type_func(event))) {
|
471
|
-
|
473
|
+
return agoo_err_set(err, AGOO_ERR_TYPE, "Not able to determine the type for a GraphQL publish.");
|
472
474
|
}
|
473
475
|
pthread_mutex_lock(&agoo_server.up_lock);
|
474
476
|
for (sub = agoo_server.gsub_list; NULL != sub; sub = sub->next) {
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
477
|
+
if (subject_check(sub->subject, subject)) {
|
478
|
+
agooRes res;
|
479
|
+
agooText t;
|
480
|
+
|
481
|
+
if (NULL == (res = agoo_res_create(sub->con))) {
|
482
|
+
AGOO_ERR_MEM(err, "Response");
|
483
|
+
break;
|
484
|
+
}
|
485
|
+
if (NULL == (t = gpub_eval(err, sub->query, event))) {
|
486
|
+
break;
|
487
|
+
}
|
488
|
+
res->con_kind = AGOO_CON_ANY;
|
489
|
+
agoo_res_message_push(res, t);
|
490
|
+
agoo_con_res_append(sub->con, res);
|
491
|
+
}
|
490
492
|
}
|
491
493
|
pthread_mutex_unlock(&agoo_server.up_lock);
|
492
494
|
|