agoo 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b76a004b8311f4a6966175ff830f0f38babc63efddde69c39a7b4ccc3d90b4a
4
- data.tar.gz: 3356bf438fb1ebdcf6aa9c2d22c3536e5f5fe7c23cd909962effc965d269fc7d
3
+ metadata.gz: 47d1801dcc95720dc1d86eca4a6e22d44ded5c3c4581493fb8026c9d3ff015d1
4
+ data.tar.gz: 473dfe0c24f99063efbb328ce857ef8ed77894c347445e2450cced56a5136a3f
5
5
  SHA512:
6
- metadata.gz: 200da7c5f41b3822cdcb68a0ddd79e7c66a976e33da33245eafa9a66907166be3144874c889c98ac6891a0f2c46746019fcdf100e18df8f6d4a3884355dc7986
7
- data.tar.gz: 1753cd691ec0bd0443a5a2d6e7af894ca56d705a9e6c3ebe645f4be7ae2156784bc94b4d3dcf6ecb17a5a4003831991120ebb19cade82435fb0599cf71d605e0
6
+ metadata.gz: ff2c2178fd44c3f752154835defc23568f37637730d53729f69fe31ab5d89233d4eeabe89f059825b333f4e314e6f25dfffbd0618a4b2006fddc90d11c3be8c4
7
+ data.tar.gz: 7c556c7fff8bd8f23e6f06332106d2b84b90e7df08b4129fa5fbe6452bc252dd5db90557dc079bd20368e552ad7161844f05ee5f98035d116c0cb8d54e1b0182
@@ -1,5 +1,17 @@
1
1
  # CHANGELOG
2
2
 
3
+ ### 2.5.0 - 2018-08-10
4
+
5
+ The binding release with multiple options for connecting to the server.
6
+
7
+ - Multiple connection bindings now supported
8
+
9
+ - Binding to Unix named sockets support added.
10
+
11
+ - IPv6 now supported.
12
+
13
+ - Connection address now supported to restrict connection requests.
14
+
3
15
  ### 2.4.0 - 2018-07-04
4
16
 
5
17
  - Rack hijack now supported.
@@ -12,12 +12,13 @@
12
12
  #include "request.h"
13
13
  #include "response.h"
14
14
  #include "rlog.h"
15
+ #include "rserver.h"
15
16
  #include "server.h"
16
17
  #include "upgraded.h"
17
18
 
18
19
  void
19
20
  agoo_shutdown() {
20
- server_shutdown();
21
+ rserver_shutdown(Qnil);
21
22
  log_close();
22
23
  }
23
24
 
@@ -47,7 +48,7 @@ ragoo_publish(VALUE self, VALUE subject, VALUE message) {
47
48
  const char *subj = extract_subject(subject, &slen);
48
49
 
49
50
  rb_check_type(message, T_STRING);
50
- queue_push(&the_server.pub_queue, pub_publish(subj, slen, StringValuePtr(message), (int)RSTRING_LEN(message)));
51
+ queue_push(&the_rserver.pub_queue, pub_publish(subj, slen, StringValuePtr(message), (int)RSTRING_LEN(message)));
51
52
 
52
53
  return Qnil;
53
54
  }
@@ -64,7 +65,7 @@ static VALUE
64
65
  ragoo_unsubscribe(VALUE self, VALUE subject) {
65
66
  rb_check_type(subject, T_STRING);
66
67
 
67
- queue_push(&the_server.pub_queue, pub_unsubscribe(NULL, StringValuePtr(subject), (int)RSTRING_LEN(subject)));
68
+ queue_push(&the_rserver.pub_queue, pub_unsubscribe(NULL, StringValuePtr(subject), (int)RSTRING_LEN(subject)));
68
69
 
69
70
  return Qnil;
70
71
  }
@@ -0,0 +1,275 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #include <netdb.h>
4
+ #include <netinet/tcp.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+ #include <sys/socket.h>
8
+ #include <sys/types.h>
9
+ #include <sys/un.h>
10
+ #include <unistd.h>
11
+
12
+ #include "bind.h"
13
+ #include "debug.h"
14
+ #include "log.h"
15
+
16
+ Bind
17
+ bind_port(Err err, int port) {
18
+ Bind b = (Bind)malloc(sizeof(struct _Bind));
19
+
20
+ if (NULL != b) {
21
+ char id[1024];
22
+
23
+ DEBUG_ALLOC(mem_bind, b);
24
+ memset(b, 0, sizeof(struct _Bind));
25
+ b->port = port;
26
+ b->family = AF_INET;
27
+ snprintf(id, sizeof(id) - 1, "http://:%d", port);
28
+ b->id = strdup(id);
29
+ }
30
+ return b;
31
+ }
32
+
33
+ static Bind
34
+ url_tcp(Err err, const char *url) {
35
+ char *colon = index(url, ':');
36
+ struct in_addr addr = { .s_addr = 0 };
37
+ int port;
38
+ Bind b;
39
+
40
+ if (NULL == colon) {
41
+ port = 80;
42
+ } else if (15 < colon - url) {
43
+ err_set(err, ERR_ARG, "tcp/http bind address is not valid. (%s)", url);
44
+ return NULL;
45
+ } else {
46
+ char buf[32];
47
+
48
+ strncpy(buf, url, colon - url);
49
+ buf[colon - url] = '\0';
50
+ if (0 == inet_aton(buf, &addr)) {
51
+ err_set(err, ERR_ARG, "tcp/http bind address is not valid. (%s)", url);
52
+ return NULL;
53
+ }
54
+ port = atoi(colon + 1);
55
+ }
56
+ if (NULL != (b = (Bind)malloc(sizeof(struct _Bind)))) {
57
+ char id[64];
58
+
59
+ DEBUG_ALLOC(mem_bind, b);
60
+ memset(b, 0, sizeof(struct _Bind));
61
+
62
+ b->port = port;
63
+ b->addr4 = addr;
64
+ b->family = AF_INET;
65
+ snprintf(id, sizeof(id), "http://%s:%d", inet_ntoa(addr), port);
66
+ b->id = strdup(id);
67
+
68
+ return b;
69
+ }
70
+ err_set(err, ERR_MEMORY, "Failed to allocate memory for a Bind.");
71
+
72
+ return b;
73
+ }
74
+
75
+ static Bind
76
+ url_tcp6(Err err, const char *url) {
77
+ struct in6_addr addr;
78
+ char *end = index(url, ']');
79
+ int port = 80;
80
+ char buf[256];
81
+ Bind b;
82
+
83
+ if (':' == *(end + 1)) {
84
+ port = atoi(end + 2);
85
+ }
86
+ memcpy(buf, url + 1, end - url - 1);
87
+ buf[end - url - 1] = '\0';
88
+ memset(&addr, 0, sizeof(addr));
89
+ if (0 == inet_pton(AF_INET6, buf, &addr)) {
90
+ err_set(err, ERR_ARG, "tcp/http bind address is not valid. (%s)", url);
91
+ return NULL;
92
+ }
93
+ if (NULL != (b = (Bind)malloc(sizeof(struct _Bind)))) {
94
+ char str[INET6_ADDRSTRLEN + 1];
95
+
96
+ DEBUG_ALLOC(mem_bind, b);
97
+ memset(b, 0, sizeof(struct _Bind));
98
+
99
+ b->port = port;
100
+ b->addr6 = addr;
101
+ b->family = AF_INET6;
102
+ snprintf(buf, sizeof(buf), "http://[%s]:%d", inet_ntop(AF_INET6, &addr, str, INET6_ADDRSTRLEN), port);
103
+ b->id = strdup(buf);
104
+
105
+ return b;
106
+ }
107
+ err_set(err, ERR_MEMORY, "Failed to allocate memory for a Bind.");
108
+
109
+ return b;
110
+ }
111
+
112
+ static Bind
113
+ url_named(Err err, const char *url) {
114
+ if ('\0' == *url) {
115
+ err_set(err, ERR_ARG, "Named Unix sockets names must not be empty.");
116
+ return NULL;
117
+ } else {
118
+ Bind b = (Bind)malloc(sizeof(struct _Bind));
119
+
120
+ if (NULL != b) {
121
+ const char *fmt = "unix://%s";
122
+ char id[1024];
123
+
124
+ DEBUG_ALLOC(mem_bind, b);
125
+ memset(b, 0, sizeof(struct _Bind));
126
+ b->name = strdup(url);
127
+ snprintf(id, sizeof(id) - 1, fmt, url);
128
+ b->id = strdup(id);
129
+ }
130
+ return b;
131
+ }
132
+ err_set(err, ERR_MEMORY, "Failed to allocate memory for a Bind.");
133
+
134
+ return NULL;
135
+ }
136
+
137
+ static Bind
138
+ url_ssl(Err err, const char *url) {
139
+ // TBD
140
+ return NULL;
141
+ }
142
+
143
+ Bind
144
+ bind_url(Err err, const char *url) {
145
+ if (0 == strncmp("tcp://", url, 6)) {
146
+ if ('[' == url[6]) {
147
+ return url_tcp6(err, url + 6);
148
+ }
149
+ return url_tcp(err, url + 6);
150
+ }
151
+ if (0 == strncmp("http://", url, 7)) {
152
+ if ('[' == url[7]) {
153
+ return url_tcp6(err, url + 7);
154
+ }
155
+ return url_tcp(err, url + 7);
156
+ }
157
+ if (0 == strncmp("unix://", url, 7)) {
158
+ return url_named(err, url + 7);
159
+ }
160
+ if (0 == strncmp("https://", url, 8)) {
161
+ return url_ssl(err, url + 8);
162
+ }
163
+ if (0 == strncmp("ssl://", url, 6)) {
164
+ return url_ssl(err, url + 6);
165
+ }
166
+ return NULL;
167
+ }
168
+
169
+ void
170
+ bind_destroy(Bind b) {
171
+ DEBUG_FREE(mem_bind, b);
172
+ free(b->id);
173
+ free(b->name);
174
+ free(b->key);
175
+ free(b->cert);
176
+ free(b->ca);
177
+ free(b);
178
+ }
179
+
180
+ static int
181
+ usual_listen(Err err, Bind b) {
182
+ int optval = 1;
183
+ int domain = PF_INET;
184
+
185
+ if (AF_INET6 == b->family) {
186
+ domain = PF_INET6;
187
+ }
188
+ if (0 >= (b->fd = socket(domain, SOCK_STREAM, IPPROTO_TCP))) {
189
+ log_cat(&error_cat, "Server failed to open server socket on port %d. %s.", b->port, strerror(errno));
190
+
191
+ return err_set(err, errno, "Server failed to open server socket. %s.", strerror(errno));
192
+ }
193
+ #ifdef OSX_OS
194
+ setsockopt(b->fd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));
195
+ #endif
196
+ setsockopt(b->fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
197
+ setsockopt(b->fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));
198
+ if (AF_INET6 == b->family) {
199
+ struct sockaddr_in6 addr;
200
+
201
+ memset(&addr, 0, sizeof(addr));
202
+ addr.sin6_flowinfo = 0;
203
+ addr.sin6_family = b->family;
204
+ addr.sin6_addr = b->addr6;
205
+ addr.sin6_port = htons(b->port);
206
+ if (0 > bind(b->fd, (struct sockaddr*)&addr, sizeof(addr))) {
207
+ log_cat(&error_cat, "Server failed to bind server socket. %s.", strerror(errno));
208
+
209
+ return err_set(err, errno, "Server failed to bind server socket. %s.", strerror(errno));
210
+ }
211
+ } else {
212
+ struct sockaddr_in addr;
213
+
214
+ memset(&addr, 0, sizeof(addr));
215
+ addr.sin_family = b->family;
216
+ addr.sin_addr = b->addr4;
217
+ addr.sin_port = htons(b->port);
218
+ if (0 > bind(b->fd, (struct sockaddr*)&addr, sizeof(addr))) {
219
+ log_cat(&error_cat, "Server failed to bind server socket. %s.", strerror(errno));
220
+
221
+ return err_set(err, errno, "Server failed to bind server socket. %s.", strerror(errno));
222
+ }
223
+ }
224
+ listen(b->fd, 1000);
225
+
226
+ return ERR_OK;
227
+ }
228
+
229
+ static int
230
+ named_listen(Err err, Bind b) {
231
+ struct sockaddr_un addr;
232
+
233
+ remove(b->name);
234
+ if (0 >= (b->fd = socket(AF_UNIX, SOCK_STREAM, 0))) {
235
+ log_cat(&error_cat, "Server failed to open server socket on %s. %s.", b->name, strerror(errno));
236
+
237
+ return err_set(err, errno, "Server failed to open server socket on %s. %s.", b->name, strerror(errno));
238
+ }
239
+ memset(&addr, 0, sizeof(addr));
240
+ addr.sun_family = AF_UNIX;
241
+ strcpy(addr.sun_path, b->name);
242
+ if (0 > bind(b->fd, (struct sockaddr*)&addr, sizeof(addr))) {
243
+ log_cat(&error_cat, "Server failed to bind server socket. %s.", strerror(errno));
244
+
245
+ return err_set(err, errno, "Server failed to bind server socket. %s.", strerror(errno));
246
+ }
247
+ listen(b->fd, 100);
248
+
249
+ return ERR_OK;
250
+ }
251
+
252
+ static int
253
+ ssl_listen(Err err, Bind b) {
254
+ // TBD
255
+ return ERR_OK;
256
+ }
257
+
258
+ int
259
+ bind_listen(Err err, Bind b) {
260
+ if (NULL != b->name) {
261
+ return named_listen(err, b);
262
+ }
263
+ if (NULL != b->key) {
264
+ return ssl_listen(err, b);
265
+ }
266
+ return usual_listen(err, b);
267
+ }
268
+
269
+ void
270
+ bind_close(Bind b) {
271
+ if (0 != b->fd) {
272
+ close(b->fd);
273
+ b->fd = 0;
274
+ }
275
+ }
@@ -0,0 +1,35 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #ifndef __AGOO_BIND_H__
4
+ #define __AGOO_BIND_H__
5
+
6
+ #include <sys/socket.h>
7
+ #include <netinet/in.h>
8
+ #include <arpa/inet.h>
9
+
10
+ #include "err.h"
11
+
12
+ typedef struct _Bind {
13
+ struct _Bind *next;
14
+ int fd;
15
+ int port;
16
+ sa_family_t family;
17
+ union {
18
+ struct in_addr addr4;
19
+ struct in6_addr addr6;
20
+ };
21
+ char *name; // if set then Unix file
22
+ char *key; // if set then SSL
23
+ char *cert;
24
+ char *ca;
25
+ char *id;
26
+ } *Bind;
27
+
28
+ extern Bind bind_url(Err err, const char *url);
29
+ extern Bind bind_port(Err err, int port);
30
+ extern void bind_destroy(Bind b);
31
+
32
+ extern int bind_listen(Err err, Bind b);
33
+ extern void bind_close(Bind b);
34
+
35
+ #endif // __AGOO_BIND_H__
@@ -10,9 +10,11 @@
10
10
  #include "dtime.h"
11
11
  #include "hook.h"
12
12
  #include "http.h"
13
+ #include "page.h"
13
14
  #include "pub.h"
14
15
  #include "res.h"
15
16
  #include "seg.h"
17
+ #include "rserver.h"
16
18
  #include "server.h"
17
19
  #include "sse.h"
18
20
  #include "subject.h"
@@ -152,6 +154,7 @@ page_response(Con c, Page p, char *hend) {
152
154
  return false;
153
155
  }
154
156
 
157
+ // rserver
155
158
  static void
156
159
  push_error(Upgraded up, const char *msg, int mlen) {
157
160
  if (NULL != up && Qnil != up->handler && up->on_error) {
@@ -164,10 +167,9 @@ push_error(Upgraded up, const char *msg, int mlen) {
164
167
  req->msg[mlen] = '\0';
165
168
  req->up = up;
166
169
  req->method = ON_ERROR;
167
- req->handler_type = PUSH_HOOK;
168
- req->handler = up->handler;
170
+ req->hook = hook_create(NONE, NULL, (void*)up->handler, PUSH_HOOK, &the_rserver.eval_queue);
169
171
  upgraded_ref(up);
170
- queue_push(&the_server.eval_queue, (void*)req);
172
+ queue_push(&the_rserver.eval_queue, (void*)req);
171
173
  }
172
174
  }
173
175
 
@@ -288,14 +290,14 @@ con_header_read(Con c) {
288
290
  }
289
291
  mlen = hend - c->buf + 4 + clen;
290
292
  if (GET == method &&
291
- NULL != (p = group_get(&err, &the_server.pages, path.start, (int)(path.end - path.start)))) {
293
+ NULL != (p = group_get(&err, path.start, (int)(path.end - path.start)))) {
292
294
  if (page_response(c, p, hend)) {
293
295
  return bad_request(c, 500, __LINE__);
294
296
  }
295
297
  return -mlen;
296
298
  }
297
299
  if (GET == method && the_server.root_first &&
298
- NULL != (p = page_get(&err, &the_server.pages, path.start, (int)(path.end - path.start)))) {
300
+ NULL != (p = page_get(&err, path.start, (int)(path.end - path.start)))) {
299
301
  if (page_response(c, p, hend)) {
300
302
  return bad_request(c, 500, __LINE__);
301
303
  }
@@ -312,7 +314,7 @@ con_header_read(Con c) {
312
314
  }
313
315
  return bad_request(c, 404, __LINE__);
314
316
  }
315
- if (NULL == (p = page_get(&err, &the_server.pages, path.start, (int)(path.end - path.start)))) {
317
+ if (NULL == (p = page_get(&err, path.start, (int)(path.end - path.start)))) {
316
318
  if (NULL != the_server.hook404) {
317
319
  // There would be too many parameters to pass to a
318
320
  // separate function so just goto the hook processing.
@@ -354,13 +356,8 @@ HOOKED:
354
356
  c->req->header.start = c->req->msg + (b + 2 - c->buf);
355
357
  c->req->header.len = (unsigned int)(hend - b - 2);
356
358
  c->req->res = NULL;
357
- if (NULL != hook) {
358
- c->req->handler = (VALUE)hook->handler;
359
- c->req->handler_type = hook->type;
360
- } else {
361
- c->req->handler = Qnil;
362
- c->req->handler_type = NO_HOOK;
363
- }
359
+ c->req->hook = hook;
360
+
364
361
  return mlen;
365
362
  }
366
363
 
@@ -368,7 +365,7 @@ static void
368
365
  check_upgrade(Con c) {
369
366
  const char *v;
370
367
  int vlen = 0;
371
-
368
+
372
369
  if (NULL == c->req) {
373
370
  return;
374
371
  }
@@ -470,7 +467,7 @@ con_http_read(Con c) {
470
467
  check_upgrade(c);
471
468
  req = c->req;
472
469
  c->req = NULL;
473
- queue_push(&the_server.eval_queue, (void*)req);
470
+ queue_push(req->hook->queue, (void*)req);
474
471
  if (mlen < (long)c->bcnt) {
475
472
  memmove(c->buf, c->buf + mlen, c->bcnt - mlen);
476
473
  c->bcnt -= mlen;
@@ -508,6 +505,7 @@ con_ws_read(Con c) {
508
505
  } else {
509
506
  char msg[1024];
510
507
  int len = snprintf(msg, sizeof(msg) - 1, "Failed to read WebSocket message. %s.", strerror(errno));
508
+
511
509
  push_error(c->up, msg, len);
512
510
  log_cat(&warn_cat, "Failed to read WebSocket message. %s.", strerror(errno));
513
511
  }
@@ -571,7 +569,7 @@ con_ws_read(Con c) {
571
569
  }
572
570
  }
573
571
  upgraded_ref(c->up);
574
- queue_push(&the_server.eval_queue, (void*)c->req);
572
+ queue_push(&the_rserver.eval_queue, (void*)c->req);
575
573
  if (mlen < (long)c->bcnt) {
576
574
  memmove(c->buf, c->buf + mlen, c->bcnt - mlen);
577
575
  c->bcnt -= mlen;
@@ -851,7 +849,7 @@ publish_pub(Pub pub) {
851
849
  const char *sub = pub->subject->pattern;
852
850
  int cnt = 0;
853
851
 
854
- for (up = the_server.up_list; NULL != up; up = up->next) {
852
+ for (up = the_rserver.up_list; NULL != up; up = up->next) {
855
853
  if (NULL != up->con && upgraded_match(up, sub)) {
856
854
  Res res = res_create(up->con);
857
855
 
@@ -875,7 +873,7 @@ unsubscribe_pub(Pub pub) {
875
873
  if (NULL == pub->up) {
876
874
  Upgraded up;
877
875
 
878
- for (up = the_server.up_list; NULL != up; up = up->next) {
876
+ for (up = the_rserver.up_list; NULL != up; up = up->next) {
879
877
  upgraded_del_subject(up, pub->subject);
880
878
  }
881
879
  } else {
@@ -897,10 +895,9 @@ process_pub_con(Pub pub) {
897
895
 
898
896
  req->up = up;
899
897
  req->method = ON_EMPTY;
900
- req->handler_type = PUSH_HOOK;
901
- req->handler = up->handler;
898
+ req->hook = hook_create(NONE, NULL, (void*)up->handler, PUSH_HOOK, &the_rserver.eval_queue);
902
899
  upgraded_ref(up);
903
- queue_push(&the_server.eval_queue, (void*)req);
900
+ queue_push(&the_rserver.eval_queue, (void*)req);
904
901
  }
905
902
  }
906
903
  }
@@ -967,7 +964,7 @@ poll_setup(Con c, struct pollfd *pp) {
967
964
  pp->events = POLLIN;
968
965
  pp->revents = 0;
969
966
  pp++;
970
- pp->fd = queue_listen(&the_server.pub_queue);
967
+ pp->fd = queue_listen(&the_rserver.pub_queue);
971
968
  pp->events = POLLIN;
972
969
  pp->revents = 0;
973
970
  pp++;
@@ -1063,7 +1060,7 @@ con_loop(void *x) {
1063
1060
  pend = pa + cnt;
1064
1061
  }
1065
1062
  }
1066
- while (NULL != (pub = (Pub)queue_pop(&the_server.pub_queue, 0.0))) {
1063
+ while (NULL != (pub = (Pub)queue_pop(&the_rserver.pub_queue, 0.0))) {
1067
1064
  process_pub_con(pub);
1068
1065
  }
1069
1066
 
@@ -1101,8 +1098,8 @@ con_loop(void *x) {
1101
1098
  }
1102
1099
  // Check pub_queue if an event is waiting.
1103
1100
  if (0 != (pa[1].revents & POLLIN)) {
1104
- queue_release(&the_server.pub_queue);
1105
- while (NULL != (pub = (Pub)queue_pop(&the_server.pub_queue, 0.0))) {
1101
+ queue_release(&the_rserver.pub_queue);
1102
+ while (NULL != (pub = (Pub)queue_pop(&the_rserver.pub_queue, 0.0))) {
1106
1103
  process_pub_con(pub);
1107
1104
  }
1108
1105
  }