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,27 @@
1
+ #ifndef outbound_utils_h
2
+ #define outbound_utils_h
3
+
4
+
5
+ #include <sys/types.h>
6
+
7
+
8
+ enum enum_outbound_udp_flow_token_ip_type {
9
+ outbound_udp_flow_token_ip_type_ipv4 = 1,
10
+ outbound_udp_flow_token_ip_type_ipv6
11
+ };
12
+
13
+
14
+ typedef struct struct_outbound_udp_flow_token {
15
+ unsigned short int valid;
16
+ enum enum_outbound_udp_flow_token_ip_type ip_type;
17
+ size_t ip_s;
18
+ size_t ip_len;
19
+ size_t port_s;
20
+ size_t port_len;
21
+ } struct_outbound_udp_flow_token;
22
+
23
+
24
+ struct_outbound_udp_flow_token outbound_udp_flow_token_parser_execute(const char *str, size_t len);
25
+
26
+
27
+ #endif
@@ -0,0 +1,384 @@
1
+ #include <ruby.h>
2
+ #include "ext_help.h"
3
+ #include "ip_utils.h"
4
+ #include "utils_ruby.h"
5
+ #include "../common/c_util.h"
6
+
7
+
8
+ static VALUE mOverSIP;
9
+ static VALUE mUtils;
10
+
11
+ static VALUE symbol_ipv4;
12
+ static VALUE symbol_ipv6;
13
+ static VALUE symbol_ipv6_reference;
14
+
15
+
16
+
17
+ /*
18
+ * Ruby functions.
19
+ */
20
+
21
+ VALUE Utils_is_ip(VALUE self, VALUE string)
22
+ {
23
+ TRACE();
24
+ char *str;
25
+ long len;
26
+
27
+ if (TYPE(string) != T_STRING)
28
+ rb_raise(rb_eTypeError, "Argument must be a String");
29
+
30
+ str = RSTRING_PTR(string);
31
+ len = RSTRING_LEN(string);
32
+
33
+ if (utils_ip_parser_execute(str, len) != ip_type_error)
34
+ return Qtrue;
35
+ else
36
+ return Qfalse;
37
+ }
38
+
39
+
40
+ VALUE Utils_is_pure_ip(VALUE self, VALUE string)
41
+ {
42
+ TRACE();
43
+ char *str;
44
+ long len;
45
+
46
+ if (TYPE(string) != T_STRING)
47
+ rb_raise(rb_eTypeError, "Argument must be a String");
48
+
49
+ str = RSTRING_PTR(string);
50
+ len = RSTRING_LEN(string);
51
+
52
+ switch(utils_ip_parser_execute(str, len)) {
53
+ case(ip_type_ipv4):
54
+ return Qtrue;
55
+ break;
56
+ case(ip_type_ipv6):
57
+ return Qtrue;
58
+ break;
59
+ default:
60
+ return Qfalse;
61
+ break;
62
+ }
63
+ }
64
+
65
+
66
+ VALUE Utils_ip_type(VALUE self, VALUE string)
67
+ {
68
+ TRACE();
69
+ char *str;
70
+ long len;
71
+
72
+ if (TYPE(string) != T_STRING)
73
+ rb_raise(rb_eTypeError, "Argument must be a String");
74
+
75
+ str = RSTRING_PTR(string);
76
+ len = RSTRING_LEN(string);
77
+
78
+ switch(utils_ip_parser_execute(str, len)) {
79
+ case(ip_type_ipv4):
80
+ return symbol_ipv4;
81
+ break;
82
+ case(ip_type_ipv6):
83
+ return symbol_ipv6;
84
+ break;
85
+ case(ip_type_ipv6_reference):
86
+ return symbol_ipv6_reference;
87
+ break;
88
+ default:
89
+ return Qfalse;
90
+ break;
91
+ }
92
+ }
93
+
94
+
95
+ /*
96
+ * Returns true if both IP's are equal (binary comparison).
97
+ * Returns false if both IP's are not equal.
98
+ * Returns nil if at least one of the IP's is not valid IPv4, IPv6 or IPv6 reference.
99
+ * This function also allows comparing an IPv6 with an IPv6 reference.
100
+ */
101
+ VALUE Utils_compare_ips(VALUE self, VALUE string1, VALUE string2)
102
+ {
103
+ TRACE();
104
+ char *str1, *str2;
105
+ long len1, len2;
106
+ enum enum_ip_type ip1_type, ip2_type;
107
+
108
+ if (TYPE(string1) != T_STRING || TYPE(string2) != T_STRING)
109
+ rb_raise(rb_eTypeError, "Arguments must be two String");
110
+
111
+ str1 = RSTRING_PTR(string1);
112
+ len1 = RSTRING_LEN(string1);
113
+ str2 = RSTRING_PTR(string2);
114
+ len2 = RSTRING_LEN(string2);
115
+
116
+ switch(ip1_type = utils_ip_parser_execute(str1, len1)) {
117
+ case(ip_type_error):
118
+ return Qnil;
119
+ break;
120
+ case(ip_type_ipv6_reference):
121
+ str1 += 1;
122
+ len1 -= 2;
123
+ ip1_type = ip_type_ipv6;
124
+ break;
125
+ default:
126
+ break;
127
+ }
128
+ switch(ip2_type = utils_ip_parser_execute(str2, len2)) {
129
+ case(ip_type_error):
130
+ return Qnil;
131
+ break;
132
+ case(ip_type_ipv6_reference):
133
+ str2 += 1;
134
+ len2 -= 2;
135
+ ip2_type = ip_type_ipv6;
136
+ break;
137
+ default:
138
+ break;
139
+ }
140
+
141
+ if (utils_compare_pure_ips(str1, len1, ip1_type, str2, len2, ip2_type))
142
+ return Qtrue;
143
+ else
144
+ return Qfalse;
145
+ }
146
+
147
+
148
+ /*
149
+ * Returns true if both IP's are equal (binary comparison).
150
+ * Returns false if both IP's are not equal.
151
+ * Returns nil if at least one of the IP's is not valid IPv4 or IPv6.
152
+ * This function does not allow comparing an IPv6 with an IPv6 reference.
153
+ */
154
+ VALUE Utils_compare_pure_ips(VALUE self, VALUE string1, VALUE string2)
155
+ {
156
+ TRACE();
157
+ char *str1, *str2;
158
+ long len1, len2;
159
+ enum enum_ip_type ip1_type, ip2_type;
160
+
161
+ if (TYPE(string1) != T_STRING || TYPE(string2) != T_STRING)
162
+ rb_raise(rb_eTypeError, "Arguments must be two String");
163
+
164
+ str1 = RSTRING_PTR(string1);
165
+ len1 = RSTRING_LEN(string1);
166
+ str2 = RSTRING_PTR(string2);
167
+ len2 = RSTRING_LEN(string2);
168
+
169
+ switch(ip1_type = utils_ip_parser_execute(str1, len1)) {
170
+ case(ip_type_error):
171
+ return Qnil;
172
+ break;
173
+ case(ip_type_ipv6_reference):
174
+ return Qnil;
175
+ break;
176
+ default:
177
+ break;
178
+ }
179
+ switch(ip2_type = utils_ip_parser_execute(str2, len2)) {
180
+ case(ip_type_error):
181
+ return Qnil;
182
+ break;
183
+ case(ip_type_ipv6_reference):
184
+ return Qnil;
185
+ break;
186
+ default:
187
+ break;
188
+ }
189
+
190
+ if (utils_compare_pure_ips(str1, len1, ip1_type, str2, len2, ip2_type))
191
+ return Qtrue;
192
+ else
193
+ return Qfalse;
194
+ }
195
+
196
+
197
+ /*
198
+ * Returns the normalized printable string of the given IPv6.
199
+ * - First argument is a string to normalize. It must be a valid IPv6 or
200
+ * IPv6 reference. If not, the method returns false.
201
+ * - Second argument is optional. If true, returned value is a pure IPv6 even
202
+ * if the first argument is a IPv6 reference.
203
+ */
204
+ VALUE Utils_normalize_ipv6(int argc, VALUE *argv, VALUE self)
205
+ {
206
+ TRACE();
207
+ VALUE string;
208
+ int force_pure_ipv6 = 0;
209
+
210
+ if (argc == 0 || argc > 2)
211
+ rb_raise(rb_eTypeError, "Wrong number of arguments (pass one or two)");
212
+
213
+ string = argv[0];
214
+ if (TYPE(string) != T_STRING)
215
+ rb_raise(rb_eTypeError, "First argument must be a String");
216
+
217
+ if (argc == 2 && TYPE(argv[1]) != T_NIL && TYPE(argv[1]) != T_FALSE)
218
+ force_pure_ipv6 = 1;
219
+
220
+ return utils_normalize_ipv6(string, force_pure_ipv6);
221
+ }
222
+
223
+
224
+ /*
225
+ * Returns the normalized printable string of the given IPv4 or IPv6.
226
+ * - First argument is a string to normalize. It must be a valid IPv4, IPv6 or
227
+ * IPv6 reference. If not, the method returns the string itself.
228
+ * - Second argument is the type of host (:ipv4, :ipv6, :ipv6_reference or :domain).
229
+ * - Third argument is optional. If true, returned value is a pure IPv6 even
230
+ * if the first argument is a IPv6 reference.
231
+ */
232
+ VALUE Utils_normalize_host(int argc, VALUE *argv, VALUE self)
233
+ {
234
+ TRACE();
235
+ VALUE host, ip_type;
236
+ int force_pure_ipv6 = 0;
237
+
238
+ if (argc == 0 || argc > 3)
239
+ rb_raise(rb_eTypeError, "Wrong number of arguments (pass one, two or three)");
240
+
241
+ host = argv[0];
242
+ if (TYPE(host) != T_STRING)
243
+ rb_raise(rb_eTypeError, "First argument must be a String");
244
+
245
+ ip_type = argv[1];
246
+ if (TYPE(ip_type) != T_SYMBOL)
247
+ rb_raise(rb_eTypeError, "Second argument must be a Symbol (:ipv4, :ipv6 or :domain)");
248
+
249
+ if (argc == 3 && TYPE(argv[2]) != T_NIL && TYPE(argv[2]) != T_FALSE)
250
+ force_pure_ipv6 = 1;
251
+
252
+ if (ip_type == symbol_ipv6 || ip_type == symbol_ipv6_reference)
253
+ return utils_normalize_ipv6(host, force_pure_ipv6);
254
+ else
255
+ return host;
256
+ }
257
+
258
+
259
+ /*
260
+ * If the given argument is a IPV6 reference it returns a new string with the pure IPv6.
261
+ * In any other case, return the given argument.
262
+ */
263
+ VALUE Utils_to_pure_ip(VALUE self, VALUE string)
264
+ {
265
+ TRACE();
266
+ char *str;
267
+
268
+ str = StringValueCStr(string);
269
+ if (str[0] == '[')
270
+ return rb_str_new(RSTRING_PTR(string)+1, RSTRING_LEN(string)-2);
271
+ else
272
+ return string;
273
+ }
274
+
275
+
276
+ /*
277
+ * Expects a string like "1.2.3.4_5060" or "1af:43::ab_9090" and returns
278
+ * an Array as follows:
279
+ * [ ip_type, ip, port ]
280
+ * where:
281
+ * - ip_type is :ipv4 or :ipv6,
282
+ * - ip is a String,
283
+ * - port is a Fixnum
284
+ * If the string is invalid it returns false.
285
+ */
286
+ VALUE Utils_parser_outbound_udp_flow_token(VALUE self, VALUE string)
287
+ {
288
+ TRACE();
289
+ char *str = NULL;
290
+ long len = 0;
291
+ struct_outbound_udp_flow_token outbound_udp_flow_token;
292
+ VALUE ip_type, ip, port;
293
+
294
+ if (TYPE(string) != T_STRING)
295
+ rb_raise(rb_eTypeError, "Argument must be a String");
296
+
297
+ str = RSTRING_PTR(string);
298
+ len = RSTRING_LEN(string);
299
+
300
+ /* Remove the leading "_" from the string. */
301
+ outbound_udp_flow_token = outbound_udp_flow_token_parser_execute(str, len);
302
+
303
+ if (outbound_udp_flow_token.valid == 0)
304
+ return Qfalse;
305
+ else {
306
+ if (outbound_udp_flow_token.ip_type == outbound_udp_flow_token_ip_type_ipv4)
307
+ ip_type = symbol_ipv4;
308
+ else
309
+ ip_type = symbol_ipv6;
310
+
311
+ ip = rb_str_new((char *)outbound_udp_flow_token.ip_s, outbound_udp_flow_token.ip_len);
312
+ port = INT2FIX(str_to_int((char *)outbound_udp_flow_token.port_s, outbound_udp_flow_token.port_len));
313
+
314
+ return rb_ary_new3(3, ip_type, ip, port);
315
+ }
316
+ }
317
+
318
+
319
+ /*
320
+ * Expects a string like "PROXY TCP4 192.168.0.1 192.168.0.11 56324 443\r\n" and returns
321
+ * an Array as follows:
322
+ * [ num_bytes, ip_type, ip, port ]
323
+ * where:
324
+ * - num_bytes is the length of the HAProxy Protocol line (to be removed), a Fixnum.
325
+ * - ip_type is :ipv4 or :ipv6,
326
+ * - ip is a String,
327
+ * - port is a Fixnum
328
+ * If the string is invalid it returns false.
329
+ */
330
+ VALUE Utils_parser_haproxy_protocol(VALUE self, VALUE string)
331
+ {
332
+ TRACE();
333
+ char *str = NULL;
334
+ long len = 0;
335
+ struct_haproxy_protocol haproxy_protocol;
336
+ VALUE num_bytes, ip_type, ip, port;
337
+
338
+ if (TYPE(string) != T_STRING)
339
+ rb_raise(rb_eTypeError, "Argument must be a String");
340
+
341
+ str = RSTRING_PTR(string);
342
+ len = RSTRING_LEN(string);
343
+
344
+ haproxy_protocol = struct_haproxy_protocol_parser_execute(str, len);
345
+
346
+ if (haproxy_protocol.valid == 0)
347
+ return Qfalse;
348
+ else {
349
+ if (haproxy_protocol.ip_type == haproxy_protocol_ip_type_ipv4)
350
+ ip_type = symbol_ipv4;
351
+ else
352
+ ip_type = symbol_ipv6;
353
+
354
+ ip = rb_str_new((char *)haproxy_protocol.ip_s, haproxy_protocol.ip_len);
355
+ port = INT2FIX(str_to_int((char *)haproxy_protocol.port_s, haproxy_protocol.port_len));
356
+ num_bytes = INT2FIX(haproxy_protocol.total_len);
357
+
358
+ return rb_ary_new3(4, num_bytes, ip_type, ip, port);
359
+ }
360
+ }
361
+
362
+
363
+ void Init_utils()
364
+ {
365
+ TRACE();
366
+
367
+ mOverSIP = rb_define_module("OverSIP");
368
+ mUtils = rb_define_module_under(mOverSIP, "Utils");
369
+
370
+ rb_define_module_function(mUtils, "ip?", Utils_is_ip, 1);
371
+ rb_define_module_function(mUtils, "pure_ip?", Utils_is_pure_ip, 1);
372
+ rb_define_module_function(mUtils, "ip_type", Utils_ip_type, 1);
373
+ rb_define_module_function(mUtils, "compare_ips", Utils_compare_ips, 2);
374
+ rb_define_module_function(mUtils, "compare_pure_ips", Utils_compare_pure_ips, 2);
375
+ rb_define_module_function(mUtils, "normalize_ipv6", Utils_normalize_ipv6, -1);
376
+ rb_define_module_function(mUtils, "normalize_host", Utils_normalize_host, -1);
377
+ rb_define_module_function(mUtils, "to_pure_ip", Utils_to_pure_ip, 1);
378
+ rb_define_module_function(mUtils, "parse_outbound_udp_flow_token", Utils_parser_outbound_udp_flow_token, 1);
379
+ rb_define_module_function(mUtils, "parse_haproxy_protocol", Utils_parser_haproxy_protocol, 1);
380
+
381
+ symbol_ipv4 = ID2SYM(rb_intern("ipv4"));
382
+ symbol_ipv6 = ID2SYM(rb_intern("ipv6"));
383
+ symbol_ipv6_reference = ID2SYM(rb_intern("ipv6_reference"));
384
+ }
@@ -0,0 +1,75 @@
1
+ /*
2
+ * This file is not used by Ruby OverSIP::Utils module itself, its aim is to
3
+ * be included by other OverSIP Ruby C extensions.
4
+ */
5
+
6
+ #ifndef utils_ruby_h
7
+ #define utils_ruby_h
8
+
9
+
10
+ #include "ip_utils.h"
11
+ #include "outbound_utils.h"
12
+ #include "haproxy_protocol.h"
13
+
14
+
15
+ /* Export the Ruby C functions so other C libraries within OverSIP can use them. */
16
+ VALUE Utils_is_ip(VALUE self, VALUE string);
17
+ VALUE Utils_is_pure_ip(VALUE self, VALUE string);
18
+ VALUE Utils_ip_type(VALUE self, VALUE string);
19
+ VALUE Utils_compare_ips(VALUE self, VALUE string1, VALUE string2);
20
+ VALUE Utils_compare_pure_ips(VALUE self, VALUE string1, VALUE string2);
21
+ VALUE Utils_normalize_ipv6(int argc, VALUE *argv, VALUE self);
22
+ VALUE Utils_normalize_host(int argc, VALUE *argv, VALUE self);
23
+ VALUE Utils_to_pure_ip(VALUE self, VALUE string);
24
+ VALUE Utils_parser_outbound_udp_flow_token(VALUE self, VALUE string);
25
+ VALUE Utils_parser_haproxy_protocol(VALUE self, VALUE string);
26
+
27
+
28
+ VALUE utils_normalize_ipv6(VALUE string, int force_pure_ipv6)
29
+ {
30
+ struct in6_addr addr;
31
+ char normalized_ipv6[INET6_ADDRSTRLEN + 1];
32
+ char normalized_ipv6_reference[INET6_ADDRSTRLEN + 3];
33
+ char *str, str2[INET6_ADDRSTRLEN + 3], *str_pointer;
34
+ int is_ipv6_reference = 0;
35
+
36
+ str = StringValueCStr(string);
37
+ if (str[0] != '[') {
38
+ str_pointer = str;
39
+ }
40
+ else {
41
+ is_ipv6_reference = 1;
42
+ memcpy(str2, str + 1, strlen(str) - 2);
43
+ str2[strlen(str) - 2] = '\0';
44
+ str_pointer = str2;
45
+ }
46
+
47
+ switch(inet_pton(AF_INET6, str_pointer, &addr)) {
48
+ /* Not a valid IPv6. */
49
+ case 0:
50
+ return Qfalse;
51
+ break;
52
+ /* Some error ocurred. */
53
+ case -1:
54
+ return Qnil;
55
+ break;
56
+ default:
57
+ break;
58
+ }
59
+
60
+ if (inet_ntop(AF_INET6, &addr, normalized_ipv6, INET6_ADDRSTRLEN))
61
+ if (is_ipv6_reference && !force_pure_ipv6) {
62
+ memcpy(normalized_ipv6_reference, "[", 1);
63
+ memcpy(normalized_ipv6_reference + 1, normalized_ipv6, strlen(normalized_ipv6));
64
+ memcpy(normalized_ipv6_reference + strlen(normalized_ipv6) + 1, "]\0", 2);
65
+ return rb_str_new_cstr(normalized_ipv6_reference);
66
+ }
67
+ else
68
+ return rb_str_new_cstr(normalized_ipv6);
69
+ /* Some error ocurred. */
70
+ else
71
+ return Qnil;
72
+ }
73
+
74
+
75
+ #endif
@@ -0,0 +1,18 @@
1
+ #ifndef ext_help_h
2
+ #define ext_help_h
3
+
4
+ #define RAISE_NOT_NULL(T) if(T == NULL) rb_raise(rb_eArgError, "NULL found for " # T " when shouldn't be.");
5
+ #define DATA_GET(from,type,name) Data_Get_Struct(from,type,name); RAISE_NOT_NULL(name);
6
+ #define REQUIRE_TYPE(V, T) if(TYPE(V) != T) rb_raise(rb_eTypeError, "Wrong argument type for " # V " required " # T);
7
+
8
+
9
+ /* Uncomment for enabling TRACE() function. */
10
+ /*#define DEBUG*/
11
+
12
+ #ifdef DEBUG
13
+ #define TRACE() fprintf(stderr, "TRACE: %s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__)
14
+ #else
15
+ #define TRACE()
16
+ #endif
17
+
18
+ #endif
@@ -0,0 +1,3 @@
1
+ require "mkmf"
2
+
3
+ create_makefile("oversip/websocket/ws_framing_utils")
@@ -0,0 +1,46 @@
1
+ #ifndef ws_framing_utils_h
2
+ #define ws_framing_utils_h
3
+
4
+
5
+ #include <stdint.h>
6
+
7
+
8
+ /* Extracted from http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ */
9
+
10
+ #define UTF8_ACCEPT 0
11
+ #define UTF8_REJECT 1
12
+ #define UTF8D_SIZE 400
13
+
14
+ static const uint8_t utf8d[] = {
15
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 00..1f */
16
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 20..3f */
17
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40..5f */
18
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60..7f */
19
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, /* 80..9f */
20
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* a0..bf */
21
+ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* c0..df */
22
+ 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, /* e0..ef */
23
+ 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, /* f0..ff */
24
+ 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, /* s0..s0 */
25
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, /* s1..s2 */
26
+ 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, /* s3..s4 */
27
+ 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, /* s5..s6 */
28
+ 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1 /* s7..s8 */
29
+ };
30
+
31
+ uint32_t inline utf8_decode(uint32_t* state, uint32_t* codep, uint32_t byte) {
32
+ uint32_t type = utf8d[byte];
33
+
34
+ *codep = (*state != UTF8_ACCEPT) ? (byte & 0x3fu) | (*codep << 6) : (0xff >> type) & (byte);
35
+ *state = utf8d[256 + *state*16 + type];
36
+ return *state;
37
+ }
38
+
39
+
40
+ typedef struct utf8_validator {
41
+ uint32_t codepoint;
42
+ uint32_t state;
43
+ } utf8_validator;
44
+
45
+
46
+ #endif
@@ -0,0 +1,135 @@
1
+ #include <ruby.h>
2
+ #include "ws_framing_utils.h"
3
+ #include "ext_help.h"
4
+
5
+
6
+ static VALUE mOverSIP;
7
+ static VALUE mWebSocket;
8
+ static VALUE mFramingUtils;
9
+ static VALUE cUtf8Validator;
10
+
11
+
12
+
13
+ /*
14
+ * Ruby functions.
15
+ */
16
+
17
+ VALUE WsFrammingUtils_unmask(VALUE self, VALUE payload, VALUE mask)
18
+ {
19
+ char *payload_str, *mask_str;
20
+ long payload_len; /* mask length is always 4 bytes. */
21
+ char *unmasked_payload_str;
22
+ VALUE rb_unmasked_payload;
23
+ int i;
24
+
25
+ if (TYPE(payload) != T_STRING)
26
+ rb_raise(rb_eTypeError, "Argument must be a String");
27
+
28
+ if (TYPE(mask) != T_STRING)
29
+ rb_raise(rb_eTypeError, "Argument must be a String");
30
+
31
+ if (RSTRING_LEN(mask) != 4)
32
+ rb_raise(rb_eTypeError, "mask size must be 4 bytes");
33
+
34
+ payload_str = RSTRING_PTR(payload);
35
+ payload_len = RSTRING_LEN(payload);
36
+ mask_str = RSTRING_PTR(mask);
37
+
38
+ /* NOTE: In Ruby C extensions always use:
39
+ * pointer = ALLOC_N(type, n)
40
+ * which means: pointer = (type*)xmalloc(sizeof(type)*(n))
41
+ * and:
42
+ * xfree()
43
+ */
44
+
45
+ unmasked_payload_str = ALLOC_N(char, payload_len);
46
+
47
+ for(i=0; i < payload_len; i++)
48
+ unmasked_payload_str[i] = payload_str[i] ^ mask_str[i % 4];
49
+
50
+ rb_unmasked_payload = rb_str_new(unmasked_payload_str, payload_len);
51
+ xfree(unmasked_payload_str);
52
+ return(rb_unmasked_payload);
53
+ }
54
+
55
+
56
+ static void Utf8Validator_free(void *validator)
57
+ {
58
+ TRACE();
59
+ if(validator) {
60
+ xfree(validator);
61
+ }
62
+ }
63
+
64
+
65
+ VALUE Utf8Validator_alloc(VALUE klass)
66
+ {
67
+ TRACE();
68
+ VALUE obj;
69
+ utf8_validator *validator = ALLOC(utf8_validator);
70
+
71
+ validator->state = UTF8_ACCEPT;
72
+
73
+ obj = Data_Wrap_Struct(klass, NULL, Utf8Validator_free, validator);
74
+ return obj;
75
+ }
76
+
77
+
78
+ VALUE Utf8Validator_reset(VALUE self)
79
+ {
80
+ TRACE();
81
+ utf8_validator *validator = NULL;
82
+ DATA_GET(self, utf8_validator, validator);
83
+
84
+ validator->state = UTF8_ACCEPT;
85
+
86
+ return Qnil;
87
+ }
88
+
89
+
90
+ /*
91
+ * Returns:
92
+ * - true: Valid UTF-8 string.
93
+ * - nil: Valid but not terminated UTF-8 string.
94
+ * - false: Invalid UTF-8 string.
95
+ */
96
+ VALUE Utf8Validator_validate(VALUE self, VALUE string)
97
+ {
98
+ TRACE();
99
+ utf8_validator *validator = NULL;
100
+ uint8_t *str = NULL;
101
+ int i;
102
+
103
+ REQUIRE_TYPE(string, T_STRING);
104
+ str = RSTRING_PTR(string);
105
+
106
+ DATA_GET(self, utf8_validator, validator);
107
+
108
+ for(i=0; i < RSTRING_LEN(string); i++)
109
+ if (utf8_decode(&validator->state, &validator->codepoint, str[i]) == UTF8_REJECT)
110
+ return Qfalse;
111
+
112
+ switch(validator->state) {
113
+ case UTF8_ACCEPT:
114
+ return Qtrue;
115
+ break;
116
+ default:
117
+ return Qnil;
118
+ break;
119
+ }
120
+ }
121
+
122
+
123
+ void Init_ws_framing_utils()
124
+ {
125
+ mOverSIP = rb_define_module("OverSIP");
126
+ mWebSocket = rb_define_module_under(mOverSIP, "WebSocket");
127
+ mFramingUtils = rb_define_module_under(mWebSocket, "FramingUtils");
128
+ cUtf8Validator = rb_define_class_under(mFramingUtils, "Utf8Validator", rb_cObject);
129
+
130
+ rb_define_module_function(mFramingUtils, "unmask", WsFrammingUtils_unmask,2);
131
+
132
+ rb_define_alloc_func(cUtf8Validator, Utf8Validator_alloc);
133
+ rb_define_method(cUtf8Validator, "reset", Utf8Validator_reset,0);
134
+ rb_define_method(cUtf8Validator, "validate", Utf8Validator_validate,1);
135
+ }
@@ -0,0 +1,18 @@
1
+ #ifndef ext_help_h
2
+ #define ext_help_h
3
+
4
+ #define RAISE_NOT_NULL(T) if(T == NULL) rb_raise(rb_eArgError, "NULL found for " # T " when shouldn't be.");
5
+ #define DATA_GET(from,type,name) Data_Get_Struct(from,type,name); RAISE_NOT_NULL(name);
6
+ #define REQUIRE_TYPE(V, T) if(TYPE(V) != T) rb_raise(rb_eTypeError, "Wrong argument type for " # V " required " # T);
7
+
8
+
9
+ /* Uncomment for enabling TRACE() function. */
10
+ /*#define DEBUG*/
11
+
12
+ #ifdef DEBUG
13
+ #define TRACE() fprintf(stderr, "TRACE: %s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__)
14
+ #else
15
+ #define TRACE()
16
+ #endif
17
+
18
+ #endif