oversip 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/AUTHORS.txt +11 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +16 -0
  4. data/Rakefile +55 -0
  5. data/bin/oversip +182 -0
  6. data/ext/common/c_util.h +74 -0
  7. data/ext/common/ruby_c_util.h +88 -0
  8. data/ext/sip_parser/common_headers.h +209 -0
  9. data/ext/sip_parser/ext_help.h +18 -0
  10. data/ext/sip_parser/extconf.rb +3 -0
  11. data/ext/sip_parser/sip_parser.c +29649 -0
  12. data/ext/sip_parser/sip_parser.h +227 -0
  13. data/ext/sip_parser/sip_parser_ruby.c +1292 -0
  14. data/ext/stud/extconf.rb +27 -0
  15. data/ext/stud/stud.tar.gz +0 -0
  16. data/ext/stun/ext_help.h +16 -0
  17. data/ext/stun/extconf.rb +3 -0
  18. data/ext/stun/stun_ruby.c +391 -0
  19. data/ext/utils/ext_help.h +14 -0
  20. data/ext/utils/extconf.rb +3 -0
  21. data/ext/utils/haproxy_protocol.c +6163 -0
  22. data/ext/utils/haproxy_protocol.h +27 -0
  23. data/ext/utils/ip_utils.c +5952 -0
  24. data/ext/utils/ip_utils.h +61 -0
  25. data/ext/utils/outbound_utils.c +3227 -0
  26. data/ext/utils/outbound_utils.h +27 -0
  27. data/ext/utils/utils_ruby.c +384 -0
  28. data/ext/utils/utils_ruby.h +75 -0
  29. data/ext/websocket_framing_utils/ext_help.h +18 -0
  30. data/ext/websocket_framing_utils/extconf.rb +3 -0
  31. data/ext/websocket_framing_utils/ws_framing_utils.h +46 -0
  32. data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
  33. data/ext/websocket_http_parser/ext_help.h +18 -0
  34. data/ext/websocket_http_parser/extconf.rb +3 -0
  35. data/ext/websocket_http_parser/ws_http_parser.c +2598 -0
  36. data/ext/websocket_http_parser/ws_http_parser.h +86 -0
  37. data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
  38. data/lib/oversip/config.rb +541 -0
  39. data/lib/oversip/config_validators.rb +126 -0
  40. data/lib/oversip/errors.rb +7 -0
  41. data/lib/oversip/fiber_pool.rb +56 -0
  42. data/lib/oversip/launcher.rb +507 -0
  43. data/lib/oversip/logger.rb +170 -0
  44. data/lib/oversip/master_process.rb +67 -0
  45. data/lib/oversip/posix_mq.rb +121 -0
  46. data/lib/oversip/proxies_config.rb +169 -0
  47. data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
  48. data/lib/oversip/sip/client_transaction.rb +587 -0
  49. data/lib/oversip/sip/constants.rb +87 -0
  50. data/lib/oversip/sip/grammar/name_addr.rb +27 -0
  51. data/lib/oversip/sip/grammar/uri.rb +116 -0
  52. data/lib/oversip/sip/launcher.rb +180 -0
  53. data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
  54. data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +21 -0
  55. data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
  56. data/lib/oversip/sip/listeners/ipv4_tls_server.rb +21 -0
  57. data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +21 -0
  58. data/lib/oversip/sip/listeners/ipv4_udp_server.rb +20 -0
  59. data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
  60. data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +21 -0
  61. data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
  62. data/lib/oversip/sip/listeners/ipv6_tls_server.rb +21 -0
  63. data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +21 -0
  64. data/lib/oversip/sip/listeners/ipv6_udp_server.rb +20 -0
  65. data/lib/oversip/sip/listeners/reactor.rb +39 -0
  66. data/lib/oversip/sip/listeners/tcp_client.rb +73 -0
  67. data/lib/oversip/sip/listeners/tcp_reactor.rb +185 -0
  68. data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
  69. data/lib/oversip/sip/listeners/tls_client.rb +117 -0
  70. data/lib/oversip/sip/listeners/tls_server.rb +70 -0
  71. data/lib/oversip/sip/listeners/tls_tunnel_reactor.rb +113 -0
  72. data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
  73. data/lib/oversip/sip/listeners/udp_reactor.rb +213 -0
  74. data/lib/oversip/sip/listeners.rb +28 -0
  75. data/lib/oversip/sip/logic.rb +14 -0
  76. data/lib/oversip/sip/message.rb +168 -0
  77. data/lib/oversip/sip/message_processor.rb +202 -0
  78. data/lib/oversip/sip/modules/core.rb +200 -0
  79. data/lib/oversip/sip/modules/registrar_without_path.rb +75 -0
  80. data/lib/oversip/sip/modules/user_assertion.rb +123 -0
  81. data/lib/oversip/sip/proxy.rb +460 -0
  82. data/lib/oversip/sip/request.rb +128 -0
  83. data/lib/oversip/sip/response.rb +30 -0
  84. data/lib/oversip/sip/rfc3263.rb +646 -0
  85. data/lib/oversip/sip/server_transaction.rb +295 -0
  86. data/lib/oversip/sip/sip.rb +74 -0
  87. data/lib/oversip/sip/tags.rb +39 -0
  88. data/lib/oversip/sip/timers.rb +55 -0
  89. data/lib/oversip/sip/transport_manager.rb +129 -0
  90. data/lib/oversip/syslogger_process.rb +119 -0
  91. data/lib/oversip/tls.rb +179 -0
  92. data/lib/oversip/utils.rb +25 -0
  93. data/lib/oversip/version.rb +23 -0
  94. data/lib/oversip/websocket/constants.rb +56 -0
  95. data/lib/oversip/websocket/default_policy.rb +19 -0
  96. data/lib/oversip/websocket/http_request.rb +63 -0
  97. data/lib/oversip/websocket/launcher.rb +207 -0
  98. data/lib/oversip/websocket/listeners/ipv4_tcp_server.rb +15 -0
  99. data/lib/oversip/websocket/listeners/ipv4_tls_server.rb +15 -0
  100. data/lib/oversip/websocket/listeners/ipv4_tls_tunnel_server.rb +15 -0
  101. data/lib/oversip/websocket/listeners/ipv6_tcp_server.rb +15 -0
  102. data/lib/oversip/websocket/listeners/ipv6_tls_server.rb +15 -0
  103. data/lib/oversip/websocket/listeners/ipv6_tls_tunnel_server.rb +15 -0
  104. data/lib/oversip/websocket/listeners/tcp_server.rb +265 -0
  105. data/lib/oversip/websocket/listeners/tls_server.rb +69 -0
  106. data/lib/oversip/websocket/listeners/tls_tunnel_server.rb +100 -0
  107. data/lib/oversip/websocket/listeners.rb +12 -0
  108. data/lib/oversip/websocket/ws_app.rb +75 -0
  109. data/lib/oversip/websocket/ws_apps/ipv4_ws_sip_app.rb +21 -0
  110. data/lib/oversip/websocket/ws_apps/ipv4_wss_sip_app.rb +21 -0
  111. data/lib/oversip/websocket/ws_apps/ipv6_ws_sip_app.rb +21 -0
  112. data/lib/oversip/websocket/ws_apps/ipv6_wss_sip_app.rb +22 -0
  113. data/lib/oversip/websocket/ws_apps/ws_autobahn_app.rb +23 -0
  114. data/lib/oversip/websocket/ws_apps/ws_sip_app.rb +156 -0
  115. data/lib/oversip/websocket/ws_apps.rb +9 -0
  116. data/lib/oversip/websocket/ws_framing.rb +597 -0
  117. data/lib/oversip.rb +59 -0
  118. data/test/oversip_test_helper.rb +20 -0
  119. data/test/test_http_parser.rb +73 -0
  120. data/test/test_sip_parser.rb +139 -0
  121. metadata +256 -0
@@ -0,0 +1,86 @@
1
+ #ifndef ws_http_parser_h
2
+ #define ws_http_parser_h
3
+
4
+
5
+ #include <sys/types.h>
6
+
7
+ #if defined(_WIN32)
8
+ #include <stddef.h>
9
+ #endif
10
+
11
+
12
+ enum method {
13
+ method_GET = 1,
14
+ method_POST,
15
+ method_OPTIONS,
16
+ method_unknown
17
+ };
18
+
19
+ enum uri_scheme {
20
+ uri_scheme_http = 1,
21
+ uri_scheme_https,
22
+ uri_scheme_unknown
23
+ };
24
+
25
+ typedef void (*msg_method_cb)(void *data, const char *at, size_t length, enum method method);
26
+ typedef void (*uri_scheme_cb)(void *data, const char *at, size_t length, enum uri_scheme);
27
+ typedef void (*msg_element_cb)(void *data, const char *at, size_t length);
28
+ typedef void (*header_cb)(void *data, const char *hdr_field, size_t hdr_field_len, const char *hdr_value, size_t hdr_value_len);
29
+
30
+
31
+ typedef struct struct_request {
32
+ msg_method_cb method;
33
+ uri_scheme_cb uri_scheme;
34
+ msg_element_cb request_uri;
35
+ msg_element_cb request_path;
36
+ msg_element_cb query;
37
+ msg_element_cb fragment;
38
+ msg_element_cb http_version;
39
+ msg_element_cb host;
40
+ msg_element_cb port;
41
+ msg_element_cb content_length;
42
+ msg_element_cb hdr_connection_value;
43
+ msg_element_cb hdr_upgrade;
44
+ msg_element_cb hdr_origin;
45
+ msg_element_cb hdr_sec_websocket_version;
46
+ msg_element_cb hdr_sec_websocket_key;
47
+ msg_element_cb hdr_sec_websocket_protocol_value;
48
+ } struct_request;
49
+
50
+ typedef struct ws_http_request_parser {
51
+ /* Parser stuf. */
52
+ int cs;
53
+ size_t nread;
54
+ char * error_start;
55
+ size_t error_len;
56
+ int error_pos;
57
+
58
+ size_t mark;
59
+ size_t hdr_field_start;
60
+ size_t hdr_field_len;
61
+ size_t hdr_value_start;
62
+ size_t hdr_value_len;
63
+ size_t query_start;
64
+
65
+ /* Request method. */
66
+ enum method method;
67
+ /* URI scheme type. */
68
+ enum uri_scheme uri_scheme;
69
+
70
+ header_cb header;
71
+ struct_request request;
72
+
73
+ /* OverSIP::WebSocket::Request instance. */
74
+ void * data;
75
+ } ws_http_request_parser;
76
+
77
+
78
+ int ws_http_request_parser_init(ws_http_request_parser *parser);
79
+ int ws_http_request_parser_finish(ws_http_request_parser *parser);
80
+ size_t ws_http_request_parser_execute(ws_http_request_parser *parser, const char *buffer, size_t len, size_t off);
81
+ int ws_http_request_parser_has_error(ws_http_request_parser *parser);
82
+ int ws_http_request_parser_is_finished(ws_http_request_parser *parser);
83
+ #define ws_http_request_parser_nread(parser) (parser)->nread
84
+
85
+
86
+ #endif
@@ -0,0 +1,630 @@
1
+ #include <ruby.h>
2
+ #include "ext_help.h"
3
+ #include "ws_http_parser.h"
4
+ #include "../utils/utils_ruby.h"
5
+ #include "../common/c_util.h"
6
+ #include "../common/ruby_c_util.h"
7
+
8
+
9
+ static VALUE headerize(const char*, size_t);
10
+
11
+
12
+ static VALUE mOverSIP;
13
+ static VALUE eOverSIPError;
14
+
15
+ static VALUE mWebSocket;
16
+ static VALUE cHttpRequestParser;
17
+ static VALUE eHttpRequestParserError;
18
+
19
+ static ID id_http_method;
20
+ static ID id_is_unknown_method;
21
+ static ID id_http_version;
22
+ static ID id_uri_scheme;
23
+ static ID id_uri;
24
+ static ID id_uri_path;
25
+ static ID id_uri_query;
26
+ static ID id_uri_fragment;
27
+ static ID id_host;
28
+ static ID id_port;
29
+ static ID id_content_length;
30
+ static ID id_hdr_connection;
31
+ static ID id_hdr_upgrade;
32
+ static ID id_hdr_sec_websocket_version;
33
+ static ID id_hdr_sec_websocket_key;
34
+ static ID id_hdr_sec_websocket_protocol;
35
+ static ID id_hdr_origin;
36
+
37
+ static VALUE symbol_GET;
38
+ static VALUE symbol_POST;
39
+ static VALUE symbol_OPTIONS;
40
+ static VALUE symbol_http;
41
+ static VALUE symbol_https;
42
+
43
+
44
+
45
+ static void header(void *data, const char *hdr_field, size_t hdr_field_len, const char *hdr_value, size_t hdr_value_len)
46
+ {
47
+ TRACE();
48
+ char *ch, *end;
49
+ VALUE parsed = (VALUE)data;
50
+ VALUE v, f, el;
51
+
52
+ /* Header name. */
53
+ f = headerize(hdr_field, hdr_field_len);
54
+
55
+ /* Header value. */
56
+ v = RB_STR_UTF8_NEW(hdr_value, hdr_value_len);
57
+
58
+ /* Here we have the header name capitalized in variable f. */
59
+ el = rb_hash_lookup(parsed, f);
60
+ switch(TYPE(el)) {
61
+ case T_ARRAY:
62
+ rb_ary_push(el, v);
63
+ break;
64
+ default:
65
+ rb_hash_aset(parsed, f, rb_ary_new3(1, v));
66
+ break;
67
+ }
68
+ }
69
+
70
+
71
+ static void req_method(void *data, const char *at, size_t length, enum method method)
72
+ {
73
+ TRACE();
74
+ VALUE parsed = (VALUE)data;
75
+ VALUE v;
76
+
77
+ switch(method) {
78
+ /* If the method is known store it as a symbol (i.e. :GET). */
79
+ case method_GET:
80
+ rb_ivar_set(parsed, id_http_method, symbol_GET);
81
+ break;
82
+ case method_POST:
83
+ rb_ivar_set(parsed, id_http_method, symbol_POST);
84
+ break;
85
+ case method_OPTIONS:
86
+ rb_ivar_set(parsed, id_http_method, symbol_OPTIONS);
87
+ break;
88
+ /* If the method is unknown store it as a string (i.e. "CHICKEN") and set the
89
+ attribute @is_unknown_method to true. */
90
+ case method_unknown:
91
+ v = RB_STR_UTF8_NEW(at, length);
92
+ rb_ivar_set(parsed, id_http_method, v);
93
+ rb_ivar_set(parsed, id_is_unknown_method, Qtrue);
94
+ break;
95
+ }
96
+ }
97
+
98
+
99
+ static void req_uri_scheme(void *data, const char *at, size_t length, enum uri_scheme scheme)
100
+ {
101
+ TRACE();
102
+ VALUE parsed = (VALUE)data;
103
+ VALUE v;
104
+
105
+ switch(scheme) {
106
+ case uri_scheme_http: v = symbol_http; break;
107
+ case uri_scheme_https: v = symbol_https; break;
108
+ case uri_scheme_unknown: v = my_rb_str_downcase(at, length); break;
109
+ }
110
+
111
+ rb_ivar_set(parsed, id_uri_scheme, v);
112
+ }
113
+
114
+
115
+ static void req_request_uri(void *data, const char *at, size_t length)
116
+ {
117
+ TRACE();
118
+ VALUE parsed = (VALUE)data;
119
+ VALUE v;
120
+
121
+ v = RB_STR_UTF8_NEW(at, length);
122
+ rb_ivar_set(parsed, id_uri, v);
123
+ }
124
+
125
+
126
+ static void req_request_path(void *data, const char *at, size_t length)
127
+ {
128
+ TRACE();
129
+ VALUE parsed = (VALUE)data;
130
+ VALUE v;
131
+
132
+ v = RB_STR_UTF8_NEW(at, length);
133
+ rb_ivar_set(parsed, id_uri_path, v);
134
+ }
135
+
136
+
137
+ static void req_query(void *data, const char *at, size_t length)
138
+ {
139
+ TRACE();
140
+ VALUE parsed = (VALUE)data;
141
+ VALUE v;
142
+
143
+ v = RB_STR_UTF8_NEW(at, length);
144
+ rb_ivar_set(parsed, id_uri_query, v);
145
+ }
146
+
147
+
148
+ static void req_fragment(void *data, const char *at, size_t length)
149
+ {
150
+ TRACE();
151
+ VALUE parsed = (VALUE)data;
152
+ VALUE v;
153
+
154
+ v = RB_STR_UTF8_NEW(at, length);
155
+ rb_ivar_set(parsed, id_uri_fragment, v);
156
+ }
157
+
158
+
159
+ static void req_http_version(void *data, const char *at, size_t length)
160
+ {
161
+ TRACE();
162
+ VALUE parsed = (VALUE)data;
163
+ VALUE v;
164
+
165
+ v = RB_STR_UTF8_NEW(at, length);
166
+ rb_ivar_set(parsed, id_http_version, v);
167
+ }
168
+
169
+
170
+ static void req_host(void *data, const char *at, size_t length)
171
+ {
172
+ TRACE();
173
+ VALUE parsed = (VALUE)data;
174
+ VALUE v;
175
+
176
+ /* If it's a domain and ends with ".", remove it. */
177
+ if (at[length-1] == '.')
178
+ length--;
179
+
180
+ v = my_rb_str_downcase(at, length);
181
+ rb_ivar_set(parsed, id_host, v);
182
+ }
183
+
184
+
185
+ static void req_port(void *data, const char *at, size_t length)
186
+ {
187
+ TRACE();
188
+ VALUE parsed = (VALUE)data;
189
+ VALUE v;
190
+
191
+ v = INT2FIX(str_to_int(at, length));
192
+ rb_ivar_set(parsed, id_port, v);
193
+ }
194
+
195
+
196
+ static void req_content_length(void *data, const char *at, size_t length)
197
+ {
198
+ TRACE();
199
+ VALUE parsed = (VALUE)data;
200
+ VALUE v;
201
+
202
+ v = LONG2FIX(strtol(at,NULL,0));
203
+ rb_ivar_set(parsed, id_content_length, v);
204
+ }
205
+
206
+
207
+ static void req_hdr_connection_value(void *data, const char *at, size_t length)
208
+ {
209
+ TRACE();
210
+ VALUE parsed = (VALUE)data;
211
+ VALUE v;
212
+ VALUE array;
213
+
214
+ v = my_rb_str_downcase(at, length);
215
+
216
+ array = rb_ivar_get(parsed, id_hdr_connection);
217
+ switch(TYPE(array)) {
218
+ case T_ARRAY:
219
+ rb_ary_push(array, v);
220
+ break;
221
+ default:
222
+ rb_ivar_set(parsed, id_hdr_connection, rb_ary_new3(1, v));
223
+ break;
224
+ }
225
+ }
226
+
227
+
228
+ static void req_hdr_upgrade(void *data, const char *at, size_t length)
229
+ {
230
+ TRACE();
231
+ VALUE parsed = (VALUE)data;
232
+ VALUE v;
233
+
234
+ v = my_rb_str_downcase(at, length);
235
+ rb_ivar_set(parsed, id_hdr_upgrade, v);
236
+ }
237
+
238
+
239
+ static void req_hdr_sec_websocket_version(void *data, const char *at, size_t length)
240
+ {
241
+ TRACE();
242
+ VALUE parsed = (VALUE)data;
243
+ VALUE v;
244
+
245
+ v = INT2FIX(str_to_int(at, length));
246
+ rb_ivar_set(parsed, id_hdr_sec_websocket_version, v);
247
+ }
248
+
249
+
250
+ static void req_hdr_sec_websocket_key(void *data, const char *at, size_t length)
251
+ {
252
+ TRACE();
253
+ VALUE parsed = (VALUE)data;
254
+ VALUE v;
255
+
256
+ v = rb_str_new(at, length);
257
+ rb_ivar_set(parsed, id_hdr_sec_websocket_key, v);
258
+ }
259
+
260
+
261
+ static void req_hdr_sec_websocket_protocol_value(void *data, const char *at, size_t length)
262
+ {
263
+ TRACE();
264
+ VALUE parsed = (VALUE)data;
265
+ VALUE v;
266
+ VALUE array;
267
+
268
+ v = rb_str_new(at, length);
269
+
270
+ array = rb_ivar_get(parsed, id_hdr_sec_websocket_protocol);
271
+ switch(TYPE(array)) {
272
+ case T_ARRAY:
273
+ rb_ary_push(array, v);
274
+ break;
275
+ default:
276
+ rb_ivar_set(parsed, id_hdr_sec_websocket_protocol, rb_ary_new3(1, v));
277
+ break;
278
+ }
279
+ }
280
+
281
+
282
+ static void req_hdr_origin(void *data, const char *at, size_t length)
283
+ {
284
+ TRACE();
285
+ VALUE parsed = (VALUE)data;
286
+ VALUE v;
287
+
288
+ v = my_rb_str_downcase(at, length);
289
+ rb_ivar_set(parsed, id_hdr_origin, v);
290
+ }
291
+
292
+
293
+
294
+ /*************** Custom C funcions (helpers) ****************/
295
+
296
+
297
+ /*
298
+ * Normalizes it (by capitalizing the first letter and each letter
299
+ * under a "-" or "_" symbol).
300
+ */
301
+ static VALUE headerize(const char* hname, size_t hname_len)
302
+ {
303
+ TRACE();
304
+ VALUE headerized;
305
+ char* str;
306
+ int i;
307
+
308
+ headerized = rb_str_new(hname, hname_len);
309
+ str = RSTRING_PTR(headerized);
310
+ if (*str >= 'a' && *str <= 'z')
311
+ *str &= ~0x20;
312
+
313
+ for(i = 1; i < hname_len; i++) {
314
+ if (str[i-1] == '-' || str[i-1] == '_') {
315
+ if (str[i] >= 'a' && str[i] <= 'z')
316
+ str[i] &= ~0x20;
317
+ }
318
+ else {
319
+ if (str[i] >= 'A' && str[i] <= 'Z')
320
+ str[i] += 32;
321
+ }
322
+ }
323
+
324
+ return(headerized);
325
+ }
326
+
327
+
328
+
329
+
330
+ /*************** Ruby functions ****************/
331
+
332
+ static void HttpRequestParser_free(void *parser)
333
+ {
334
+ TRACE();
335
+ if(parser) {
336
+ /* NOTE: Use always xfree() rather than free():
337
+ * http://www.mail-archive.com/libxml-devel@rubyforge.org/msg00242.html */
338
+ xfree(parser);
339
+ }
340
+ }
341
+
342
+
343
+ VALUE HttpRequestParser_alloc(VALUE klass)
344
+ {
345
+ TRACE();
346
+ VALUE obj;
347
+ /* NOTE: Use always ALLOC/ALLOC_N rather than malloc().
348
+ * ALLOC uses xmalloc:
349
+ * ALLOC(type) (type*)xmalloc(sizeof(type))
350
+ * ALLOC_N(type, n) (type*)xmalloc(sizeof(type)*(n))
351
+ */
352
+ ws_http_request_parser *parser = ALLOC(ws_http_request_parser);
353
+
354
+ parser->header = header;
355
+ parser->request.method = req_method;
356
+ parser->request.uri_scheme = req_uri_scheme;
357
+ parser->request.request_uri = req_request_uri;
358
+ parser->request.request_path = req_request_path;
359
+ parser->request.query = req_query;
360
+ parser->request.fragment = req_fragment;
361
+ parser->request.http_version = req_http_version;
362
+ parser->request.host = req_host;
363
+ parser->request.port = req_port;
364
+ parser->request.content_length = req_content_length;
365
+ parser->request.hdr_connection_value = req_hdr_connection_value;
366
+ parser->request.hdr_upgrade = req_hdr_upgrade;
367
+ parser->request.hdr_sec_websocket_version = req_hdr_sec_websocket_version;
368
+ parser->request.hdr_sec_websocket_key = req_hdr_sec_websocket_key;
369
+ parser->request.hdr_sec_websocket_protocol_value = req_hdr_sec_websocket_protocol_value;
370
+ parser->request.hdr_origin = req_hdr_origin;
371
+
372
+ ws_http_request_parser_init(parser);
373
+
374
+ obj = Data_Wrap_Struct(klass, NULL, HttpRequestParser_free, parser);
375
+ return obj;
376
+ }
377
+
378
+
379
+ /**
380
+ * call-seq:
381
+ * parser.new -> parser
382
+ *
383
+ * Creates a new parser.
384
+ */
385
+ VALUE HttpRequestParser_init(VALUE self)
386
+ {
387
+ TRACE();
388
+ ws_http_request_parser *parser = NULL;
389
+ DATA_GET(self, ws_http_request_parser, parser);
390
+ ws_http_request_parser_init(parser);
391
+
392
+ return self;
393
+ }
394
+
395
+
396
+ /**
397
+ * call-seq:
398
+ * parser.reset -> nil
399
+ *
400
+ * Resets the parser to it's initial state so that you can reuse it
401
+ * rather than making new ones.
402
+ */
403
+ VALUE HttpRequestParser_reset(VALUE self)
404
+ {
405
+ TRACE();
406
+ ws_http_request_parser *parser = NULL;
407
+ DATA_GET(self, ws_http_request_parser, parser);
408
+ ws_http_request_parser_init(parser);
409
+
410
+ return Qnil;
411
+ }
412
+
413
+
414
+ /**
415
+ * call-seq:
416
+ * parser.finish -> true/false
417
+ *
418
+ * Finishes a parser early which could put in a "good" or bad state.
419
+ * You should call reset after finish it or bad things will happen.
420
+ */
421
+ VALUE HttpRequestParser_finish(VALUE self)
422
+ {
423
+ TRACE();
424
+ ws_http_request_parser *parser = NULL;
425
+ DATA_GET(self, ws_http_request_parser, parser);
426
+ ws_http_request_parser_finish(parser);
427
+
428
+ return ws_http_request_parser_is_finished(parser) ? Qtrue : Qfalse;
429
+ }
430
+
431
+
432
+ VALUE HttpRequestParser_execute(VALUE self, VALUE req_hash, VALUE buffer, VALUE start)
433
+ {
434
+ TRACE();
435
+ ws_http_request_parser *parser = NULL;
436
+ int from = 0;
437
+ char *dptr = NULL;
438
+ long dlen = 0;
439
+
440
+ REQUIRE_TYPE(req_hash, T_HASH);
441
+ REQUIRE_TYPE(buffer, T_STRING);
442
+ REQUIRE_TYPE(start, T_FIXNUM);
443
+
444
+ DATA_GET(self, ws_http_request_parser, parser);
445
+
446
+ from = FIX2INT(start);
447
+ dptr = RSTRING_PTR(buffer);
448
+ dlen = RSTRING_LEN(buffer);
449
+
450
+ /* This should never occur or there is an error in the parser. */
451
+ if(from >= dlen)
452
+ rb_raise(eHttpRequestParserError, "requested start is after buffer end.");
453
+
454
+ parser->data = (void *)req_hash;
455
+ ws_http_request_parser_execute(parser, dptr, dlen, from);
456
+
457
+ if(ws_http_request_parser_has_error(parser))
458
+ return Qfalse;
459
+ else
460
+ return INT2FIX(ws_http_request_parser_nread(parser));
461
+ }
462
+
463
+
464
+ /**
465
+ * call-seq:
466
+ * parser.error? -> true/false
467
+ *
468
+ * Tells you whether the parser is in an error state.
469
+ */
470
+ VALUE HttpRequestParser_has_error(VALUE self)
471
+ {
472
+ TRACE();
473
+ ws_http_request_parser *parser = NULL;
474
+ DATA_GET(self, ws_http_request_parser, parser);
475
+
476
+ return ws_http_request_parser_has_error(parser) ? Qtrue : Qfalse;
477
+ }
478
+
479
+
480
+ /**
481
+ * call-seq:
482
+ * parser.error -> String
483
+ *
484
+ * Returns a String showing the error by enclosing the exact wrong char between {{{ }}}.
485
+ */
486
+ VALUE HttpRequestParser_error(VALUE self)
487
+ {
488
+ TRACE();
489
+ ws_http_request_parser *parser = NULL;
490
+ DATA_GET(self, ws_http_request_parser, parser);
491
+
492
+ if(ws_http_request_parser_has_error(parser)) {
493
+ char *parsing_error_str;
494
+ int parsing_error_str_len;
495
+ int i;
496
+ int j;
497
+ VALUE rb_error_str;
498
+
499
+ /* Duplicate error string length so '\r' and '\n' are displayed as CR and LF.
500
+ Let 6 chars more for allocating {{{ and }}}. */
501
+ parsing_error_str = ALLOC_N(char, 2*parser->error_len + 6);
502
+
503
+ parsing_error_str_len=0;
504
+ for(i=0, j=0; i < parser->error_len; i++) {
505
+ if (i != parser->error_pos) {
506
+ if (parser->error_start[i] == '\r') {
507
+ parsing_error_str[j++] = '\\';
508
+ parsing_error_str[j++] = 'r';
509
+ parsing_error_str_len += 2;
510
+ }
511
+ else if (parser->error_start[i] == '\n') {
512
+ parsing_error_str[j++] = '\\';
513
+ parsing_error_str[j++] = 'n';
514
+ parsing_error_str_len += 2;
515
+ }
516
+ else {
517
+ parsing_error_str[j++] = parser->error_start[i];
518
+ parsing_error_str_len++;
519
+ }
520
+ }
521
+ else {
522
+ parsing_error_str[j++] = '{';
523
+ parsing_error_str[j++] = '{';
524
+ parsing_error_str[j++] = '{';
525
+ if (parser->error_start[i] == '\r') {
526
+ parsing_error_str[j++] = '\\';
527
+ parsing_error_str[j++] = 'r';
528
+ parsing_error_str_len += 2;
529
+ }
530
+ else if (parser->error_start[i] == '\n') {
531
+ parsing_error_str[j++] = '\\';
532
+ parsing_error_str[j++] = 'n';
533
+ parsing_error_str_len += 2;
534
+ }
535
+ else {
536
+ parsing_error_str[j++] = parser->error_start[i];
537
+ parsing_error_str_len++;
538
+ }
539
+ parsing_error_str[j++] = '}';
540
+ parsing_error_str[j++] = '}';
541
+ parsing_error_str[j++] = '}';
542
+ parsing_error_str_len += 6;
543
+ }
544
+ }
545
+
546
+ rb_error_str = rb_str_new(parsing_error_str, parsing_error_str_len);
547
+ xfree(parsing_error_str);
548
+ return rb_error_str;
549
+ }
550
+ else
551
+ return Qnil;
552
+ }
553
+
554
+
555
+ /**
556
+ * call-seq:
557
+ * parser.finished? -> true/false
558
+ *
559
+ * Tells you whether the parser is finished or not and in a good state.
560
+ */
561
+ VALUE HttpRequestParser_is_finished(VALUE self)
562
+ {
563
+ TRACE();
564
+ ws_http_request_parser *parser = NULL;
565
+ DATA_GET(self, ws_http_request_parser, parser);
566
+
567
+ return ws_http_request_parser_is_finished(parser) ? Qtrue : Qfalse;
568
+ }
569
+
570
+
571
+ /**
572
+ * call-seq:
573
+ * parser.nread -> Integer
574
+ *
575
+ * Returns the amount of data processed so far during this processing cycle. It is
576
+ * set to 0 on initialize or reset calls and is incremented each time execute is called.
577
+ */
578
+ VALUE HttpRequestParser_nread(VALUE self)
579
+ {
580
+ TRACE();
581
+ ws_http_request_parser *parser = NULL;
582
+ DATA_GET(self, ws_http_request_parser, parser);
583
+
584
+ return INT2FIX(parser->nread);
585
+ }
586
+
587
+
588
+ void Init_ws_http_parser()
589
+ {
590
+ mOverSIP = rb_define_module("OverSIP");
591
+ eOverSIPError = rb_define_class_under(mOverSIP, "Error", rb_eStandardError);
592
+
593
+ mWebSocket = rb_define_module_under(mOverSIP, "WebSocket");
594
+ cHttpRequestParser = rb_define_class_under(mWebSocket, "HttpRequestParser", rb_cObject);
595
+ eHttpRequestParserError = rb_define_class_under(mWebSocket, "HttpRequestParserError", eOverSIPError);
596
+
597
+ rb_define_alloc_func(cHttpRequestParser, HttpRequestParser_alloc);
598
+ rb_define_method(cHttpRequestParser, "initialize", HttpRequestParser_init,0);
599
+ rb_define_method(cHttpRequestParser, "reset", HttpRequestParser_reset,0);
600
+ rb_define_method(cHttpRequestParser, "finish", HttpRequestParser_finish,0);
601
+ rb_define_method(cHttpRequestParser, "execute", HttpRequestParser_execute,3);
602
+ rb_define_method(cHttpRequestParser, "error?", HttpRequestParser_has_error,0);
603
+ rb_define_method(cHttpRequestParser, "error", HttpRequestParser_error,0);
604
+ rb_define_method(cHttpRequestParser, "finished?", HttpRequestParser_is_finished,0);
605
+ rb_define_method(cHttpRequestParser, "nread", HttpRequestParser_nread,0);
606
+
607
+ id_http_method = rb_intern("@http_method");
608
+ id_is_unknown_method = rb_intern("is_unknown_method");
609
+ id_http_version = rb_intern("@http_version");
610
+ id_uri_scheme = rb_intern("@uri_scheme");
611
+ id_uri = rb_intern("@uri");
612
+ id_uri_path = rb_intern("@uri_path");
613
+ id_uri_query = rb_intern("@uri_query");
614
+ id_uri_fragment = rb_intern("@uri_fragment");
615
+ id_host = rb_intern("@host");
616
+ id_port = rb_intern("@port");
617
+ id_content_length = rb_intern("@content_length");
618
+ id_hdr_connection = rb_intern("@hdr_connection");
619
+ id_hdr_upgrade = rb_intern("@hdr_upgrade");
620
+ id_hdr_sec_websocket_version = rb_intern("@hdr_sec_websocket_version");
621
+ id_hdr_sec_websocket_key = rb_intern("@hdr_sec_websocket_key");
622
+ id_hdr_sec_websocket_protocol = rb_intern("@hdr_sec_websocket_protocol");
623
+ id_hdr_origin = rb_intern("@hdr_origin");
624
+
625
+ symbol_GET = ID2SYM(rb_intern("GET"));
626
+ symbol_POST = ID2SYM(rb_intern("POST"));
627
+ symbol_OPTIONS = ID2SYM(rb_intern("OPTIONS"));
628
+ symbol_http = ID2SYM(rb_intern("http"));
629
+ symbol_https = ID2SYM(rb_intern("https"));
630
+ }