agoo 2.5.1 → 2.5.2

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.

Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -1
  3. data/README.md +12 -1
  4. data/ext/agoo/agoo.c +4 -3
  5. data/ext/agoo/bind.c +51 -11
  6. data/ext/agoo/bind.h +9 -0
  7. data/ext/agoo/con.c +127 -89
  8. data/ext/agoo/con.h +24 -8
  9. data/ext/agoo/debug.c +2 -0
  10. data/ext/agoo/debug.h +1 -0
  11. data/ext/agoo/err.c +1 -1
  12. data/ext/agoo/err.h +2 -5
  13. data/ext/agoo/foo/agoo.c +109 -0
  14. data/ext/agoo/foo/con.c +1220 -0
  15. data/ext/agoo/foo/con.h +65 -0
  16. data/ext/agoo/foo/page.c +699 -0
  17. data/ext/agoo/foo/pub.c +131 -0
  18. data/ext/agoo/foo/pub.h +40 -0
  19. data/ext/agoo/foo/rserver.c +1016 -0
  20. data/ext/agoo/foo/server.c +303 -0
  21. data/ext/agoo/foo/server.h +67 -0
  22. data/ext/agoo/foo/upgraded.c +182 -0
  23. data/ext/agoo/hook.c +31 -0
  24. data/ext/agoo/hook.h +9 -10
  25. data/ext/agoo/{types.h → kinds.h} +3 -3
  26. data/ext/agoo/log.c +168 -83
  27. data/ext/agoo/log.h +6 -2
  28. data/ext/agoo/page.c +38 -32
  29. data/ext/agoo/pub.c +16 -0
  30. data/ext/agoo/pub.h +1 -0
  31. data/ext/agoo/queue.h +1 -0
  32. data/ext/agoo/req.c +95 -0
  33. data/ext/agoo/req.h +48 -0
  34. data/ext/agoo/request.c +10 -38
  35. data/ext/agoo/request.h +1 -34
  36. data/ext/agoo/res.h +1 -3
  37. data/ext/agoo/response.c +6 -248
  38. data/ext/agoo/response.h +2 -6
  39. data/ext/agoo/rlog.c +2 -1
  40. data/ext/agoo/rresponse.c +252 -0
  41. data/ext/agoo/rresponse.h +14 -0
  42. data/ext/agoo/rserver.c +43 -45
  43. data/ext/agoo/rserver.h +3 -24
  44. data/ext/agoo/rupgraded.c +303 -0
  45. data/ext/agoo/rupgraded.h +17 -0
  46. data/ext/agoo/server.c +125 -8
  47. data/ext/agoo/server.h +26 -4
  48. data/ext/agoo/sse.c +3 -1
  49. data/ext/agoo/upgraded.c +42 -280
  50. data/ext/agoo/upgraded.h +16 -8
  51. data/ext/agoo/websocket.c +13 -9
  52. data/lib/agoo/base.rb +84 -0
  53. data/lib/agoo/client.rb +25 -0
  54. data/lib/agoo/version.rb +1 -1
  55. data/test/bind_test.rb +2 -2
  56. metadata +22 -4
@@ -7,43 +7,10 @@
7
7
 
8
8
  #include <ruby.h>
9
9
 
10
- #include "hook.h"
11
- #include "res.h"
12
- #include "types.h"
10
+ #include "req.h"
13
11
 
14
- struct _Server;
15
- struct _Upgraded;
16
-
17
- typedef enum {
18
- UP_NONE = '\0',
19
- UP_WS = 'W',
20
- UP_SSE = 'S',
21
- } Upgrade;
22
-
23
- typedef struct _Str {
24
- char *start;
25
- unsigned int len;
26
- } *Str;
27
-
28
- typedef struct _Req {
29
- Method method;
30
- Upgrade upgrade;
31
- struct _Upgraded *up;
32
- struct _Str path;
33
- struct _Str query;
34
- struct _Str header;
35
- struct _Str body;
36
- Hook hook;
37
- VALUE env;
38
- Res res;
39
- size_t mlen; // allocated msg length
40
- char msg[8]; // expanded to be full message
41
- } *Req;
42
-
43
- extern Req request_create(size_t mlen);
44
12
  extern void request_init(VALUE mod);
45
13
  extern VALUE request_wrap(Req req);
46
14
  extern VALUE request_env(Req req, VALUE self);
47
- extern void request_destroy(Req req);
48
15
 
49
16
  #endif // __AGOO_REQUEST_H__
@@ -6,10 +6,8 @@
6
6
  #include <stdatomic.h>
7
7
  #include <stdbool.h>
8
8
 
9
- #include <ruby.h>
10
-
11
9
  #include "text.h"
12
- #include "types.h"
10
+ #include "con.h"
13
11
 
14
12
  struct _Con;
15
13
 
@@ -1,19 +1,18 @@
1
1
  // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
2
 
3
+ #include <stdio.h>
3
4
  #include <stdlib.h>
5
+ #include <string.h>
4
6
 
5
7
  #include "debug.h"
6
8
  #include "http.h"
7
9
  #include "response.h"
8
- #include "text.h"
9
10
 
10
- static VALUE res_class = Qundef;
11
-
12
- static int
11
+ int
13
12
  response_len(Response res) {
14
- char c;
13
+ char buf[256];
15
14
  const char *msg = http_code_message(res->code);
16
- int len = snprintf(&c, 1, "HTTP/1.1 %d %s\r\nContent-Length: %d\r\n", res->code, msg, res->blen);
15
+ int len = snprintf(buf, sizeof(buf), "HTTP/1.1 %d %s\r\nContent-Length: %d\r\n", res->code, msg, res->blen);
17
16
  Header h;
18
17
 
19
18
  for (h = res->headers; NULL != h; h = h->next) {
@@ -25,7 +24,7 @@ response_len(Response res) {
25
24
  return len;
26
25
  }
27
26
 
28
- static void
27
+ void
29
28
  response_fill(Response res, char *buf) {
30
29
  Header h;
31
30
  const char *msg = http_code_message(res->code);
@@ -44,244 +43,3 @@ response_fill(Response res, char *buf) {
44
43
  }
45
44
  *buf = '\0';
46
45
  }
47
-
48
- static void
49
- response_free(void *ptr) {
50
- Response res = (Response)ptr;
51
- Header h;
52
-
53
- while (NULL != (h = res->headers)) {
54
- res->headers = h->next;
55
- DEBUG_FREE(mem_header, h);
56
- xfree(h);
57
- }
58
- DEBUG_FREE(mem_res_body, res->body);
59
- DEBUG_FREE(mem_response, ptr);
60
- free(res->body); // allocated with strdup
61
- xfree(ptr);
62
- }
63
-
64
- VALUE
65
- response_new( ) {
66
- Response res = ALLOC(struct _Response);
67
-
68
- DEBUG_ALLOC(mem_response, res)
69
- memset(res, 0, sizeof(struct _Response));
70
- res->code = 200;
71
-
72
- return Data_Wrap_Struct(res_class, NULL, response_free, res);
73
- }
74
-
75
- /* Document-method: to_s
76
- *
77
- * call-seq: to_s()
78
- *
79
- * Returns a string representation of the response.
80
- */
81
- static VALUE
82
- to_s(VALUE self) {
83
- Response res = (Response)DATA_PTR(self);
84
- int len = response_len(res);
85
- char *s = ALLOC_N(char, len + 1);
86
-
87
- DEBUG_ALLOC(mem_to_s, s)
88
- response_fill(res, s);
89
-
90
- return rb_str_new(s, len);
91
- }
92
-
93
- /* Document-method: content
94
- *
95
- * call-seq: content()
96
- *
97
- * alias for _body_
98
- */
99
-
100
- /* Document-method: body
101
- *
102
- * call-seq: body()
103
- *
104
- * Gets the HTTP body for the response.
105
- */
106
- static VALUE
107
- body_get(VALUE self) {
108
- Response res = (Response)DATA_PTR(self);
109
-
110
- if (NULL == res->body) {
111
- return Qnil;
112
- }
113
- return rb_str_new(res->body, res->blen);
114
- }
115
-
116
- /* Document-method: content=
117
- *
118
- * call-seq: content=(str)
119
- *
120
- * alias for _body=_
121
- */
122
-
123
- /* Document-method: body=
124
- *
125
- * call-seq: body=(str)
126
- *
127
- * Sets the HTTP body for the response.
128
- */
129
- static VALUE
130
- body_set(VALUE self, VALUE val) {
131
- Response res = (Response)DATA_PTR(self);
132
-
133
- if (T_STRING == rb_type(val)) {
134
- res->body = strdup(StringValuePtr(val));
135
- DEBUG_ALLOC(mem_res_body, res->body)
136
- res->blen = (int)RSTRING_LEN(val);
137
- } else {
138
- rb_raise(rb_eArgError, "Expected a string");
139
- // TBD use Oj to encode val
140
- }
141
- return Qnil;
142
- }
143
-
144
- /* Document-method: code
145
- *
146
- * call-seq: code()
147
- *
148
- * Gets the HTTP status code for the response.
149
- */
150
- static VALUE
151
- code_get(VALUE self) {
152
- return INT2NUM(((Response)DATA_PTR(self))->code);
153
- }
154
-
155
- /* Document-method: code=
156
- *
157
- * call-seq: code=(value)
158
- *
159
- * Sets the HTTP status code for the response.
160
- */
161
- static VALUE
162
- code_set(VALUE self, VALUE val) {
163
- int code = NUM2INT(val);
164
-
165
- if (100 <= code && code < 600) {
166
- ((Response)DATA_PTR(self))->code = code;
167
- } else {
168
- rb_raise(rb_eArgError, "%d is not a valid HTTP status code.", code);
169
- }
170
- return Qnil;
171
- }
172
-
173
- /* Document-method: []
174
- *
175
- * call-seq: [](key)
176
- *
177
- * Gets a header element associated with the _key_.
178
- */
179
- static VALUE
180
- head_get(VALUE self, VALUE key) {
181
- Response res = (Response)DATA_PTR(self);
182
- Header h;
183
- const char *ks = StringValuePtr(key);
184
- int klen = (int)RSTRING_LEN(key);
185
-
186
- for (h = res->headers; NULL != h; h = h->next) {
187
- if (0 == strncasecmp(h->text, ks, klen) && klen + 1 < h->len && ':' == h->text[klen]) {
188
- return rb_str_new(h->text + klen + 2, h->len - klen - 4);
189
- }
190
- }
191
- return Qnil;
192
- }
193
-
194
- /* Document-method: []=
195
- *
196
- * call-seq: []=(key, value)
197
- *
198
- * Sets a header element with the _key_ and _value_ provided.
199
- */
200
- static VALUE
201
- head_set(VALUE self, VALUE key, VALUE val) {
202
- Response res = (Response)DATA_PTR(self);
203
- Header h;
204
- Header prev = NULL;
205
- const char *ks = StringValuePtr(key);
206
- const char *vs;
207
- int klen = (int)RSTRING_LEN(key);
208
- int vlen;
209
- int hlen;
210
-
211
- for (h = res->headers; NULL != h; h = h->next) {
212
- if (0 == strncasecmp(h->text, ks, klen) && klen + 1 < h->len && ':' == h->text[klen]) {
213
- if (NULL == prev) {
214
- res->headers = h->next;
215
- } else {
216
- prev->next = h->next;
217
- }
218
- DEBUG_FREE(mem_header, h);
219
- xfree(h);
220
- break;
221
- }
222
- prev = h;
223
- }
224
- if (T_STRING != rb_type(val)) {
225
- val = rb_funcall(val, rb_intern("to_s"), 0);
226
- }
227
- vs = StringValuePtr(val);
228
- vlen = (int)RSTRING_LEN(val);
229
-
230
- if (the_server.pedantic) {
231
- struct _Err err = ERR_INIT;
232
-
233
- if (ERR_OK != http_header_ok(&err, ks, klen, vs, vlen)) {
234
- rb_raise(rb_eArgError, "%s", err.msg);
235
- }
236
- }
237
- hlen = klen + vlen + 4;
238
- h = (Header)ALLOC_N(char, sizeof(struct _Header) - 8 + hlen + 1);
239
- DEBUG_ALLOC(mem_header, h)
240
-
241
- h->next = NULL;
242
- h->len = hlen;
243
- strncpy(h->text, ks, klen);
244
- strcpy(h->text + klen, ": ");
245
- strncpy(h->text + klen + 2, vs, vlen);
246
- strcpy(h->text + klen + 2 + vlen, "\r\n");
247
- if (NULL == res->headers) {
248
- res->headers = h;
249
- } else {
250
- for (prev = res->headers; NULL != prev->next; prev = prev->next) {
251
- }
252
- prev->next = h;
253
- }
254
- return Qnil;
255
- }
256
-
257
- Text
258
- response_text(VALUE self) {
259
- Response res = (Response)DATA_PTR(self);
260
- int len = response_len(res);
261
- Text t = text_allocate(len);
262
-
263
- response_fill(res, t->text);
264
- t->len = len;
265
-
266
- return t;
267
- }
268
-
269
- /* Document-class: Agoo::Response
270
- *
271
- * A response passed to a handler that responds to the _on_request_
272
- * method. The expected response is modified by the handler before returning.
273
- */
274
- void
275
- response_init(VALUE mod) {
276
- res_class = rb_define_class_under(mod, "Response", rb_cObject);
277
-
278
- rb_define_method(res_class, "to_s", to_s, 0);
279
- rb_define_method(res_class, "body", body_get, 0);
280
- rb_define_method(res_class, "body=", body_set, 1);
281
- rb_define_method(res_class, "content", body_get, 0);
282
- rb_define_method(res_class, "content=", body_set, 1);
283
- rb_define_method(res_class, "code", code_get, 0);
284
- rb_define_method(res_class, "code=", code_set, 1);
285
- rb_define_method(res_class, "[]", head_get, 1);
286
- rb_define_method(res_class, "[]=", head_set, 2);
287
- }
@@ -6,8 +6,6 @@
6
6
  #include <stdatomic.h>
7
7
  #include <stdbool.h>
8
8
 
9
- #include <ruby.h>
10
-
11
9
  #include "server.h"
12
10
  #include "text.h"
13
11
 
@@ -24,9 +22,7 @@ typedef struct _Response {
24
22
  char *body;
25
23
  } *Response;
26
24
 
27
- extern void response_init(VALUE mod);
28
-
29
- extern VALUE response_new();
30
- extern Text response_text(VALUE self);
25
+ extern int response_len(Response res);
26
+ extern void response_fill(Response res, char *buf);
31
27
 
32
28
  #endif // __AGOO_RESPONSE_H__
@@ -465,5 +465,6 @@ rlog_init(VALUE mod) {
465
465
 
466
466
  the_log.on_error = on_error;
467
467
 
468
- log_init();
468
+ log_init("agoo");
469
+ log_start(false);
469
470
  }
@@ -0,0 +1,252 @@
1
+ // Copyright (c) 2018, Peter Ohler, All rights reserved.
2
+
3
+ #include <stdlib.h>
4
+
5
+ #include "debug.h"
6
+ #include "http.h"
7
+ #include "response.h"
8
+ #include "rresponse.h"
9
+ #include "text.h"
10
+
11
+ static VALUE res_class = Qundef;
12
+
13
+ static void
14
+ response_free(void *ptr) {
15
+ Response res = (Response)ptr;
16
+ Header h;
17
+
18
+ while (NULL != (h = res->headers)) {
19
+ res->headers = h->next;
20
+ DEBUG_FREE(mem_header, h);
21
+ xfree(h);
22
+ }
23
+ DEBUG_FREE(mem_res_body, res->body);
24
+ DEBUG_FREE(mem_response, ptr);
25
+ free(res->body); // allocated with strdup
26
+ xfree(ptr);
27
+ }
28
+
29
+ VALUE
30
+ response_new( ) {
31
+ Response res = ALLOC(struct _Response);
32
+
33
+ DEBUG_ALLOC(mem_response, res)
34
+ memset(res, 0, sizeof(struct _Response));
35
+ res->code = 200;
36
+
37
+ return Data_Wrap_Struct(res_class, NULL, response_free, res);
38
+ }
39
+
40
+ /* Document-method: to_s
41
+ *
42
+ * call-seq: to_s()
43
+ *
44
+ * Returns a string representation of the response.
45
+ */
46
+ static VALUE
47
+ to_s(VALUE self) {
48
+ Response res = (Response)DATA_PTR(self);
49
+ int len = response_len(res);
50
+ char *s = ALLOC_N(char, len + 1);
51
+
52
+ DEBUG_ALLOC(mem_to_s, s)
53
+ response_fill(res, s);
54
+
55
+ return rb_str_new(s, len);
56
+ }
57
+
58
+ /* Document-method: content
59
+ *
60
+ * call-seq: content()
61
+ *
62
+ * alias for _body_
63
+ */
64
+
65
+ /* Document-method: body
66
+ *
67
+ * call-seq: body()
68
+ *
69
+ * Gets the HTTP body for the response.
70
+ */
71
+ static VALUE
72
+ body_get(VALUE self) {
73
+ Response res = (Response)DATA_PTR(self);
74
+
75
+ if (NULL == res->body) {
76
+ return Qnil;
77
+ }
78
+ return rb_str_new(res->body, res->blen);
79
+ }
80
+
81
+ /* Document-method: content=
82
+ *
83
+ * call-seq: content=(str)
84
+ *
85
+ * alias for _body=_
86
+ */
87
+
88
+ /* Document-method: body=
89
+ *
90
+ * call-seq: body=(str)
91
+ *
92
+ * Sets the HTTP body for the response.
93
+ */
94
+ static VALUE
95
+ body_set(VALUE self, VALUE val) {
96
+ Response res = (Response)DATA_PTR(self);
97
+
98
+ if (T_STRING == rb_type(val)) {
99
+ res->body = strdup(StringValuePtr(val));
100
+ DEBUG_ALLOC(mem_res_body, res->body)
101
+ res->blen = (int)RSTRING_LEN(val);
102
+ } else {
103
+ rb_raise(rb_eArgError, "Expected a string");
104
+ // TBD use Oj to encode val
105
+ }
106
+ return Qnil;
107
+ }
108
+
109
+ /* Document-method: code
110
+ *
111
+ * call-seq: code()
112
+ *
113
+ * Gets the HTTP status code for the response.
114
+ */
115
+ static VALUE
116
+ code_get(VALUE self) {
117
+ return INT2NUM(((Response)DATA_PTR(self))->code);
118
+ }
119
+
120
+ /* Document-method: code=
121
+ *
122
+ * call-seq: code=(value)
123
+ *
124
+ * Sets the HTTP status code for the response.
125
+ */
126
+ static VALUE
127
+ code_set(VALUE self, VALUE val) {
128
+ int code = NUM2INT(val);
129
+
130
+ if (100 <= code && code < 600) {
131
+ ((Response)DATA_PTR(self))->code = code;
132
+ } else {
133
+ rb_raise(rb_eArgError, "%d is not a valid HTTP status code.", code);
134
+ }
135
+ return Qnil;
136
+ }
137
+
138
+ /* Document-method: []
139
+ *
140
+ * call-seq: [](key)
141
+ *
142
+ * Gets a header element associated with the _key_.
143
+ */
144
+ static VALUE
145
+ head_get(VALUE self, VALUE key) {
146
+ Response res = (Response)DATA_PTR(self);
147
+ Header h;
148
+ const char *ks = StringValuePtr(key);
149
+ int klen = (int)RSTRING_LEN(key);
150
+
151
+ for (h = res->headers; NULL != h; h = h->next) {
152
+ if (0 == strncasecmp(h->text, ks, klen) && klen + 1 < h->len && ':' == h->text[klen]) {
153
+ return rb_str_new(h->text + klen + 2, h->len - klen - 4);
154
+ }
155
+ }
156
+ return Qnil;
157
+ }
158
+
159
+ /* Document-method: []=
160
+ *
161
+ * call-seq: []=(key, value)
162
+ *
163
+ * Sets a header element with the _key_ and _value_ provided.
164
+ */
165
+ static VALUE
166
+ head_set(VALUE self, VALUE key, VALUE val) {
167
+ Response res = (Response)DATA_PTR(self);
168
+ Header h;
169
+ Header prev = NULL;
170
+ const char *ks = StringValuePtr(key);
171
+ const char *vs;
172
+ int klen = (int)RSTRING_LEN(key);
173
+ int vlen;
174
+ int hlen;
175
+
176
+ for (h = res->headers; NULL != h; h = h->next) {
177
+ if (0 == strncasecmp(h->text, ks, klen) && klen + 1 < h->len && ':' == h->text[klen]) {
178
+ if (NULL == prev) {
179
+ res->headers = h->next;
180
+ } else {
181
+ prev->next = h->next;
182
+ }
183
+ DEBUG_FREE(mem_header, h);
184
+ xfree(h);
185
+ break;
186
+ }
187
+ prev = h;
188
+ }
189
+ if (T_STRING != rb_type(val)) {
190
+ val = rb_funcall(val, rb_intern("to_s"), 0);
191
+ }
192
+ vs = StringValuePtr(val);
193
+ vlen = (int)RSTRING_LEN(val);
194
+
195
+ if (the_server.pedantic) {
196
+ struct _Err err = ERR_INIT;
197
+
198
+ if (ERR_OK != http_header_ok(&err, ks, klen, vs, vlen)) {
199
+ rb_raise(rb_eArgError, "%s", err.msg);
200
+ }
201
+ }
202
+ hlen = klen + vlen + 4;
203
+ h = (Header)ALLOC_N(char, sizeof(struct _Header) - 8 + hlen + 1);
204
+ DEBUG_ALLOC(mem_header, h)
205
+
206
+ h->next = NULL;
207
+ h->len = hlen;
208
+ strncpy(h->text, ks, klen);
209
+ strcpy(h->text + klen, ": ");
210
+ strncpy(h->text + klen + 2, vs, vlen);
211
+ strcpy(h->text + klen + 2 + vlen, "\r\n");
212
+ if (NULL == res->headers) {
213
+ res->headers = h;
214
+ } else {
215
+ for (prev = res->headers; NULL != prev->next; prev = prev->next) {
216
+ }
217
+ prev->next = h;
218
+ }
219
+ return Qnil;
220
+ }
221
+
222
+ Text
223
+ response_text(VALUE self) {
224
+ Response res = (Response)DATA_PTR(self);
225
+ int len = response_len(res);
226
+ Text t = text_allocate(len);
227
+
228
+ response_fill(res, t->text);
229
+ t->len = len;
230
+
231
+ return t;
232
+ }
233
+
234
+ /* Document-class: Agoo::Response
235
+ *
236
+ * A response passed to a handler that responds to the _on_request_
237
+ * method. The expected response is modified by the handler before returning.
238
+ */
239
+ void
240
+ response_init(VALUE mod) {
241
+ res_class = rb_define_class_under(mod, "Response", rb_cObject);
242
+
243
+ rb_define_method(res_class, "to_s", to_s, 0);
244
+ rb_define_method(res_class, "body", body_get, 0);
245
+ rb_define_method(res_class, "body=", body_set, 1);
246
+ rb_define_method(res_class, "content", body_get, 0);
247
+ rb_define_method(res_class, "content=", body_set, 1);
248
+ rb_define_method(res_class, "code", code_get, 0);
249
+ rb_define_method(res_class, "code=", code_set, 1);
250
+ rb_define_method(res_class, "[]", head_get, 1);
251
+ rb_define_method(res_class, "[]=", head_set, 2);
252
+ }