oversip_p 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +22 -0
  3. data/LICENSE +25 -0
  4. data/README.md +43 -0
  5. data/Rakefile +54 -0
  6. data/bin/oversip +184 -0
  7. data/etc/oversip.conf +274 -0
  8. data/etc/proxies.conf +145 -0
  9. data/etc/server.rb +315 -0
  10. data/etc/tls/ca/cacert.pem +3894 -0
  11. data/etc/tls/demo-tls.oversip.net.crt +17 -0
  12. data/etc/tls/demo-tls.oversip.net.key +15 -0
  13. data/etc/tls/upgrade-cacert.sh +12 -0
  14. data/etc/tls/utils/create-cert.rb +162 -0
  15. data/etc/tls/utils/get-sip-identities.rb +95 -0
  16. data/ext/common/c_util.h +74 -0
  17. data/ext/common/ruby_c_util.h +88 -0
  18. data/ext/sip_parser/common_headers.h +210 -0
  19. data/ext/sip_parser/ext_help.h +18 -0
  20. data/ext/sip_parser/extconf.rb +3 -0
  21. data/ext/sip_parser/sip_message_parser.c +29741 -0
  22. data/ext/sip_parser/sip_parser.h +250 -0
  23. data/ext/sip_parser/sip_parser_ruby.c +1370 -0
  24. data/ext/sip_parser/sip_uri_parser.c +39699 -0
  25. data/ext/stud/extconf.rb +43 -0
  26. data/ext/stun/ext_help.h +16 -0
  27. data/ext/stun/extconf.rb +3 -0
  28. data/ext/stun/stun_ruby.c +394 -0
  29. data/ext/utils/ext_help.h +14 -0
  30. data/ext/utils/extconf.rb +3 -0
  31. data/ext/utils/haproxy_protocol.c +6163 -0
  32. data/ext/utils/haproxy_protocol.h +27 -0
  33. data/ext/utils/ip_utils.c +5952 -0
  34. data/ext/utils/ip_utils.h +64 -0
  35. data/ext/utils/outbound_utils.c +3227 -0
  36. data/ext/utils/outbound_utils.h +27 -0
  37. data/ext/utils/utils_ruby.c +392 -0
  38. data/ext/utils/utils_ruby.h +76 -0
  39. data/ext/websocket_framing_utils/ext_help.h +18 -0
  40. data/ext/websocket_framing_utils/extconf.rb +3 -0
  41. data/ext/websocket_framing_utils/ws_framing_utils.h +47 -0
  42. data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
  43. data/ext/websocket_http_parser/ext_help.h +18 -0
  44. data/ext/websocket_http_parser/extconf.rb +3 -0
  45. data/ext/websocket_http_parser/ws_http_parser.c +1635 -0
  46. data/ext/websocket_http_parser/ws_http_parser.h +87 -0
  47. data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
  48. data/lib/oversip/config.rb +597 -0
  49. data/lib/oversip/config_validators.rb +126 -0
  50. data/lib/oversip/default_server.rb +52 -0
  51. data/lib/oversip/errors.rb +10 -0
  52. data/lib/oversip/fiber_pool.rb +56 -0
  53. data/lib/oversip/launcher.rb +635 -0
  54. data/lib/oversip/logger.rb +84 -0
  55. data/lib/oversip/modules/outbound_mangling.rb +56 -0
  56. data/lib/oversip/modules/user_assertion.rb +73 -0
  57. data/lib/oversip/proxies_config.rb +189 -0
  58. data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
  59. data/lib/oversip/sip/client.rb +428 -0
  60. data/lib/oversip/sip/client_transaction.rb +586 -0
  61. data/lib/oversip/sip/constants.rb +88 -0
  62. data/lib/oversip/sip/core.rb +217 -0
  63. data/lib/oversip/sip/launcher.rb +221 -0
  64. data/lib/oversip/sip/listeners/connection.rb +54 -0
  65. data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
  66. data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +22 -0
  67. data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
  68. data/lib/oversip/sip/listeners/ipv4_tls_server.rb +22 -0
  69. data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +22 -0
  70. data/lib/oversip/sip/listeners/ipv4_udp_server.rb +21 -0
  71. data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
  72. data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +22 -0
  73. data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
  74. data/lib/oversip/sip/listeners/ipv6_tls_server.rb +22 -0
  75. data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +22 -0
  76. data/lib/oversip/sip/listeners/ipv6_udp_server.rb +21 -0
  77. data/lib/oversip/sip/listeners/tcp_client.rb +97 -0
  78. data/lib/oversip/sip/listeners/tcp_connection.rb +202 -0
  79. data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
  80. data/lib/oversip/sip/listeners/tls_client.rb +125 -0
  81. data/lib/oversip/sip/listeners/tls_server.rb +88 -0
  82. data/lib/oversip/sip/listeners/tls_tunnel_connection.rb +89 -0
  83. data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
  84. data/lib/oversip/sip/listeners/udp_connection.rb +214 -0
  85. data/lib/oversip/sip/listeners.rb +24 -0
  86. data/lib/oversip/sip/message.rb +177 -0
  87. data/lib/oversip/sip/message_processor.rb +213 -0
  88. data/lib/oversip/sip/name_addr.rb +51 -0
  89. data/lib/oversip/sip/proxy.rb +324 -0
  90. data/lib/oversip/sip/request.rb +179 -0
  91. data/lib/oversip/sip/response.rb +37 -0
  92. data/lib/oversip/sip/rfc3263.rb +643 -0
  93. data/lib/oversip/sip/server_transaction.rb +295 -0
  94. data/lib/oversip/sip/sip.rb +76 -0
  95. data/lib/oversip/sip/tags.rb +39 -0
  96. data/lib/oversip/sip/timers.rb +55 -0
  97. data/lib/oversip/sip/transport_manager.rb +130 -0
  98. data/lib/oversip/sip/uac.rb +89 -0
  99. data/lib/oversip/sip/uac_request.rb +84 -0
  100. data/lib/oversip/sip/uri.rb +208 -0
  101. data/lib/oversip/syslog.rb +68 -0
  102. data/lib/oversip/system_callbacks.rb +45 -0
  103. data/lib/oversip/tls.rb +172 -0
  104. data/lib/oversip/utils.rb +30 -0
  105. data/lib/oversip/version.rb +21 -0
  106. data/lib/oversip/websocket/constants.rb +55 -0
  107. data/lib/oversip/websocket/http_request.rb +59 -0
  108. data/lib/oversip/websocket/launcher.rb +183 -0
  109. data/lib/oversip/websocket/listeners/connection.rb +51 -0
  110. data/lib/oversip/websocket/listeners/ipv4_ws_server.rb +22 -0
  111. data/lib/oversip/websocket/listeners/ipv4_wss_server.rb +22 -0
  112. data/lib/oversip/websocket/listeners/ipv4_wss_tunnel_server.rb +22 -0
  113. data/lib/oversip/websocket/listeners/ipv6_ws_server.rb +22 -0
  114. data/lib/oversip/websocket/listeners/ipv6_wss_server.rb +22 -0
  115. data/lib/oversip/websocket/listeners/ipv6_wss_tunnel_server.rb +22 -0
  116. data/lib/oversip/websocket/listeners/ws_server.rb +331 -0
  117. data/lib/oversip/websocket/listeners/wss_server.rb +88 -0
  118. data/lib/oversip/websocket/listeners/wss_tunnel_server.rb +133 -0
  119. data/lib/oversip/websocket/listeners.rb +13 -0
  120. data/lib/oversip/websocket/websocket.rb +13 -0
  121. data/lib/oversip/websocket/ws_framing.rb +545 -0
  122. data/lib/oversip/websocket/ws_sip_app.rb +120 -0
  123. data/lib/oversip.rb +127 -0
  124. data/test/oversip_test_helper.rb +19 -0
  125. data/test/test_http_parser.rb +73 -0
  126. data/test/test_name_addr.rb +27 -0
  127. data/test/test_name_addr_parser.rb +24 -0
  128. data/test/test_sip_message_parser.rb +168 -0
  129. data/test/test_sip_uri_parser.rb +56 -0
  130. data/test/test_uri.rb +68 -0
  131. data/thirdparty/stud/stud.tar.gz +0 -0
  132. metadata +334 -0
@@ -0,0 +1,1370 @@
1
+ #include <ruby.h>
2
+ #include "ext_help.h"
3
+ #include "sip_parser.h"
4
+ #include "common_headers.h"
5
+ #include "../utils/utils_ruby.h"
6
+ #include "../common/c_util.h"
7
+ #include "../common/ruby_c_util.h"
8
+
9
+
10
+ static VALUE my_rb_str_tel_number_clean(const char*, size_t);
11
+
12
+ static VALUE mOverSIP;
13
+ static VALUE eOverSIPError;
14
+
15
+ static VALUE mSIP;
16
+ static VALUE cSIPMessageParser;
17
+ static VALUE eSIPMessageParserError;
18
+ static VALUE cSIPMessage;
19
+ static VALUE cSIPRequest;
20
+ static VALUE cSIPResponse;
21
+ static VALUE cUri;
22
+ static VALUE cNameAddr;
23
+
24
+ static ID id_headers;
25
+ static ID id_parsed;
26
+ static ID id_sip_method;
27
+ static ID id_is_unknown_method;
28
+ static ID id_ruri;
29
+ static ID id_status_code;
30
+ static ID id_reason_phrase;
31
+ static ID id_sip_version;
32
+ static ID id_via_sent_by_host;
33
+ static ID id_via_sent_by_port;
34
+ static ID id_via_branch;
35
+ static ID id_via_branch_rfc3261;
36
+ static ID id_via_received;
37
+ static ID id_via_has_rport;
38
+ static ID id_via_has_alias;
39
+ static ID id_via_core_value;
40
+ static ID id_via_params;
41
+ static ID id_num_vias;
42
+ static ID id_call_id;
43
+ static ID id_cseq;
44
+ static ID id_max_forwards;
45
+ static ID id_content_length;
46
+ static ID id_from;
47
+ static ID id_from_tag;
48
+ static ID id_to;
49
+ static ID id_to_tag;
50
+ static ID id_routes;
51
+ static ID id_contact;
52
+ static ID id_contact_params;
53
+ static ID id_contact_has_reg_id;
54
+ static ID id_require;
55
+ static ID id_proxy_require;
56
+ static ID id_supported;
57
+ static ID id_hdr_via;
58
+ static ID id_hdr_from;
59
+ static ID id_hdr_to;
60
+ static ID id_hdr_route;
61
+
62
+ static ID id_display_name;
63
+ static ID id_uri;
64
+ static ID id_uri_scheme;
65
+ static ID id_uri_user;
66
+ static ID id_uri_host;
67
+ static ID id_uri_host_type;
68
+ static ID id_uri_port;
69
+ static ID id_uri_params;
70
+ static ID id_uri_transport_param;
71
+ static ID id_uri_lr_param;
72
+ static ID id_uri_ob_param;
73
+ static ID id_uri_ovid_param;
74
+ static ID id_uri_phone_context_param;
75
+ static ID id_uri_headers;
76
+
77
+ static VALUE symbol_outbound_keepalive;
78
+ static VALUE symbol_INVITE;
79
+ static VALUE symbol_OPTIONS;
80
+ static VALUE symbol_INVITE;
81
+ static VALUE symbol_ACK;
82
+ static VALUE symbol_CANCEL;
83
+ static VALUE symbol_PRACK;
84
+ static VALUE symbol_BYE;
85
+ static VALUE symbol_REFER;
86
+ static VALUE symbol_INFO;
87
+ static VALUE symbol_UPDATE;
88
+ static VALUE symbol_OPTIONS;
89
+ static VALUE symbol_REGISTER;
90
+ static VALUE symbol_MESSAGE;
91
+ static VALUE symbol_SUBSCRIBE;
92
+ static VALUE symbol_NOTIFY;
93
+ static VALUE symbol_PUBLISH;
94
+ static VALUE symbol_PULL;
95
+ static VALUE symbol_PUSH;
96
+ static VALUE symbol_STORE;
97
+ static VALUE symbol_sip;
98
+ static VALUE symbol_sips;
99
+ static VALUE symbol_tel;
100
+ static VALUE symbol_udp;
101
+ static VALUE symbol_tcp;
102
+ static VALUE symbol_tls;
103
+ static VALUE symbol_sctp;
104
+ static VALUE symbol_ws;
105
+ static VALUE symbol_wss;
106
+ static VALUE symbol_domain;
107
+ static VALUE symbol_ipv4;
108
+ static VALUE symbol_ipv6;
109
+ static VALUE symbol_ipv6_reference;
110
+
111
+ static VALUE string_Via;
112
+ static VALUE string_From;
113
+ static VALUE string_To;
114
+ static VALUE string_CSeq;
115
+ static VALUE string_Call_ID;
116
+ static VALUE string_Max_Forwards;
117
+ static VALUE string_Content_Length;
118
+
119
+ /* A single and global SIP URI parser. */
120
+ static sip_uri_parser *global_sip_uri_parser;
121
+
122
+
123
+ static void data_type(void *parser, enum data_type data_type)
124
+ {
125
+ TRACE();
126
+ VALUE parsed;
127
+ sip_message_parser *sp = (sip_message_parser*)parser;
128
+
129
+ switch(data_type) {
130
+ case sip_request:
131
+ parsed = rb_obj_alloc(cSIPRequest);
132
+ rb_ivar_set(parsed, id_headers, rb_hash_new());
133
+ sp->parsed = parsed;
134
+ break;
135
+ case sip_response:
136
+ parsed = rb_obj_alloc(cSIPResponse);
137
+ rb_ivar_set(parsed, id_headers, rb_hash_new());
138
+ sp->parsed = parsed;
139
+ break;
140
+ case outbound_keepalive:
141
+ parsed = symbol_outbound_keepalive;
142
+ sp->parsed = parsed;
143
+ break;
144
+ }
145
+ /* NOTE: The parsing can require multiple invocations of the parser#execute() so
146
+ * we need to store the in-process message (Request or Response) in an attribute
147
+ * within the parser (if not it would be garbage collected as it has been declared
148
+ * as a VALUE variable). */
149
+ rb_ivar_set(sp->ruby_sip_parser, id_parsed, parsed);
150
+ }
151
+
152
+
153
+ static void init_component(VALUE parsed, enum component msg_component)
154
+ {
155
+ switch(msg_component) {
156
+ case component_ruri: rb_ivar_set(parsed, id_ruri, rb_obj_alloc(cUri)); break;
157
+ case component_from: rb_ivar_set(parsed, id_from, rb_obj_alloc(cNameAddr)); break;
158
+ case component_to: rb_ivar_set(parsed, id_to, rb_obj_alloc(cNameAddr)); break;
159
+ case component_route: rb_ivar_set(parsed, id_routes, rb_ary_new()); break;
160
+ case component_route_uri: rb_ary_push(rb_ivar_get(parsed, id_routes), rb_obj_alloc(cNameAddr)); break;
161
+ case component_contact: rb_ivar_set(parsed, id_contact, rb_obj_alloc(cNameAddr)); break;
162
+ }
163
+ }
164
+
165
+
166
+ static void header(VALUE parsed, const char *hdr_field, size_t hdr_field_len, const char *hdr_value, size_t hdr_value_len, enum header_field hdr_field_name)
167
+ {
168
+ TRACE();
169
+ char *ch, *end;
170
+ VALUE v, f, el;
171
+ VALUE headers, array;
172
+
173
+ /* Header name. */
174
+ f = headerize(hdr_field, hdr_field_len);
175
+
176
+ /* Header value. */
177
+ v = RB_STR_UTF8_NEW(hdr_value, hdr_value_len);
178
+
179
+ headers = rb_ivar_get(parsed, id_headers);
180
+
181
+ /* Here we have the header name capitalized in variable f. */
182
+ el = rb_hash_lookup(headers, f);
183
+ switch(TYPE(el)) {
184
+ case T_ARRAY:
185
+ rb_ary_push(el, v);
186
+ break;
187
+ default:
188
+ array = rb_hash_aset(headers, f, rb_ary_new3(1, v));
189
+ switch(hdr_field_name) {
190
+ case header_field_any:
191
+ break;
192
+ case header_field_via:
193
+ rb_ivar_set(parsed, id_hdr_via, array);
194
+ break;
195
+ case header_field_from:
196
+ rb_ivar_set(parsed, id_hdr_from, v);
197
+ break;
198
+ case header_field_to:
199
+ rb_ivar_set(parsed, id_hdr_to, v);
200
+ break;
201
+ case header_field_route:
202
+ rb_ivar_set(parsed, id_hdr_route, array);
203
+ break;
204
+ default:
205
+ break;
206
+ }
207
+ }
208
+ }
209
+
210
+
211
+ static void msg_method(VALUE parsed, const char *at, size_t length, enum method method)
212
+ {
213
+ TRACE();
214
+ VALUE v;
215
+
216
+ switch(method) {
217
+ /* If the method is known store it as a symbol (i.e. :INVITE). */
218
+ case method_INVITE:
219
+ rb_ivar_set(parsed, id_sip_method, symbol_INVITE);
220
+ break;
221
+ case method_ACK:
222
+ rb_ivar_set(parsed, id_sip_method, symbol_ACK);
223
+ break;
224
+ case method_CANCEL:
225
+ rb_ivar_set(parsed, id_sip_method, symbol_CANCEL);
226
+ break;
227
+ case method_PRACK:
228
+ rb_ivar_set(parsed, id_sip_method, symbol_PRACK);
229
+ break;
230
+ case method_BYE:
231
+ rb_ivar_set(parsed, id_sip_method, symbol_BYE);
232
+ break;
233
+ case method_REFER:
234
+ rb_ivar_set(parsed, id_sip_method, symbol_REFER);
235
+ break;
236
+ case method_INFO:
237
+ rb_ivar_set(parsed, id_sip_method, symbol_INFO);
238
+ break;
239
+ case method_UPDATE:
240
+ rb_ivar_set(parsed, id_sip_method, symbol_UPDATE);
241
+ break;
242
+ case method_OPTIONS:
243
+ rb_ivar_set(parsed, id_sip_method, symbol_OPTIONS);
244
+ break;
245
+ case method_REGISTER:
246
+ rb_ivar_set(parsed, id_sip_method, symbol_REGISTER);
247
+ break;
248
+ case method_MESSAGE:
249
+ rb_ivar_set(parsed, id_sip_method, symbol_MESSAGE);
250
+ break;
251
+ case method_SUBSCRIBE:
252
+ rb_ivar_set(parsed, id_sip_method, symbol_SUBSCRIBE);
253
+ break;
254
+ case method_NOTIFY:
255
+ rb_ivar_set(parsed, id_sip_method, symbol_NOTIFY);
256
+ break;
257
+ case method_PUBLISH:
258
+ rb_ivar_set(parsed, id_sip_method, symbol_PUBLISH);
259
+ break;
260
+ case method_PULL:
261
+ rb_ivar_set(parsed, id_sip_method, symbol_PULL);
262
+ break;
263
+ case method_PUSH:
264
+ rb_ivar_set(parsed, id_sip_method, symbol_PUSH);
265
+ break;
266
+ case method_STORE:
267
+ rb_ivar_set(parsed, id_sip_method, symbol_STORE);
268
+ break;
269
+ /* If the method is unknown store it as a string (i.e. "CHICKEN") and set the
270
+ attribute @is_unknown_method to true. */
271
+ case method_unknown:
272
+ v = RB_STR_UTF8_NEW(at, length);
273
+ rb_ivar_set(parsed, id_sip_method, v);
274
+ rb_ivar_set(parsed, id_is_unknown_method, Qtrue);
275
+ break;
276
+ }
277
+ }
278
+
279
+
280
+ static void msg_status_code(VALUE parsed, const char *at, size_t length)
281
+ {
282
+ TRACE();
283
+ VALUE v;
284
+
285
+ v = INT2FIX(str_to_int(at, length));
286
+ rb_ivar_set(parsed, id_status_code, v);
287
+ }
288
+
289
+
290
+ static void msg_reason_phrase(VALUE parsed, const char *at, size_t length)
291
+ {
292
+ TRACE();
293
+ VALUE v;
294
+
295
+ v = RB_STR_UTF8_NEW(at, length);
296
+ rb_ivar_set(parsed, id_reason_phrase, v);
297
+ }
298
+
299
+
300
+ static void msg_sip_version(VALUE parsed, const char *at, size_t length)
301
+ {
302
+ TRACE();
303
+ VALUE v;
304
+
305
+ v = RB_STR_UTF8_NEW(at, length);
306
+ rb_ivar_set(parsed, id_sip_version, v);
307
+ }
308
+
309
+
310
+ static void msg_via_sent_by_host(VALUE parsed, const char *at, size_t length)
311
+ {
312
+ TRACE();
313
+ VALUE v;
314
+
315
+ v = RB_STR_UTF8_NEW(at, length);
316
+ rb_ivar_set(parsed, id_via_sent_by_host, v);
317
+ }
318
+
319
+
320
+ static void msg_via_sent_by_port(VALUE parsed, const char *at, size_t length)
321
+ {
322
+ TRACE();
323
+ VALUE v;
324
+
325
+ v = INT2FIX(str_to_int(at, length));
326
+ rb_ivar_set(parsed, id_via_sent_by_port, v);
327
+ }
328
+
329
+
330
+ static void msg_via_branch(VALUE parsed, const char *at, size_t length)
331
+ {
332
+ TRACE();
333
+ VALUE v;
334
+
335
+ v = RB_STR_UTF8_NEW(at, length);
336
+ rb_ivar_set(parsed, id_via_branch, v);
337
+ }
338
+
339
+
340
+ static void msg_via_branch_rfc3261(VALUE parsed, const char *at, size_t length)
341
+ {
342
+ TRACE();
343
+
344
+ rb_ivar_set(parsed, id_via_branch_rfc3261, Qtrue);
345
+ }
346
+
347
+
348
+ static void msg_via_received(VALUE parsed, const char *at, size_t length)
349
+ {
350
+ TRACE();
351
+ VALUE v;
352
+
353
+ v = RB_STR_UTF8_NEW(at, length);
354
+ rb_ivar_set(parsed, id_via_received, v);
355
+ }
356
+
357
+
358
+ static void msg_via_has_rport(VALUE parsed)
359
+ {
360
+ TRACE();
361
+
362
+ rb_ivar_set(parsed, id_via_has_rport, Qtrue);
363
+ }
364
+
365
+
366
+ static void msg_via_has_alias(VALUE parsed)
367
+ {
368
+ TRACE();
369
+
370
+ rb_ivar_set(parsed, id_via_has_alias, Qtrue);
371
+ }
372
+
373
+
374
+ static void msg_call_id(VALUE parsed, const char *at, size_t length)
375
+ {
376
+ TRACE();
377
+ VALUE v;
378
+
379
+ v = RB_STR_UTF8_NEW(at, length);
380
+ rb_ivar_set(parsed, id_call_id, v);
381
+ }
382
+
383
+
384
+ static void msg_cseq_number(VALUE parsed, const char *at, size_t length)
385
+ {
386
+ TRACE();
387
+ VALUE v;
388
+
389
+ v = LONG2FIX(strtol(at,NULL,0));
390
+ rb_ivar_set(parsed, id_cseq, v);
391
+ }
392
+
393
+
394
+ static void msg_max_forwards(VALUE parsed, const char *at, size_t length)
395
+ {
396
+ TRACE();
397
+ VALUE v;
398
+
399
+ v = INT2FIX(str_to_int(at, length));
400
+ rb_ivar_set(parsed, id_max_forwards, v);
401
+ }
402
+
403
+
404
+ static void msg_content_length(VALUE parsed, const char *at, size_t length)
405
+ {
406
+ TRACE();
407
+ VALUE v;
408
+
409
+ v = LONG2FIX(strtol(at,NULL,0));
410
+ rb_ivar_set(parsed, id_content_length, v);
411
+ }
412
+
413
+
414
+ static void msg_from_tag(VALUE parsed, const char *at, size_t length)
415
+ {
416
+ TRACE();
417
+ VALUE v;
418
+
419
+ v = RB_STR_UTF8_NEW(at, length);
420
+ rb_ivar_set(parsed, id_from_tag, v);
421
+ }
422
+
423
+
424
+ static void msg_to_tag(VALUE parsed, const char *at, size_t length)
425
+ {
426
+ TRACE();
427
+ VALUE v;
428
+
429
+ v = RB_STR_UTF8_NEW(at, length);
430
+ rb_ivar_set(parsed, id_to_tag, v);
431
+ }
432
+
433
+
434
+ static VALUE get_uri_object(VALUE parsed, enum uri_owner owner)
435
+ {
436
+ TRACE();
437
+ VALUE routes_array;
438
+
439
+ switch(owner) {
440
+ case uri_owner_ruri: return rb_ivar_get(parsed, id_ruri); break;
441
+ case uri_owner_from: return rb_ivar_get(parsed, id_from); break;
442
+ case uri_owner_to: return rb_ivar_get(parsed, id_to); break;
443
+ /* If we are in Route header, then return the last NameAddr entry. */
444
+ case uri_owner_route:
445
+ routes_array = rb_ivar_get(parsed, id_routes);
446
+ return RARRAY_PTR(routes_array)[RARRAY_LEN(routes_array)-1];
447
+ break;
448
+ case uri_owner_contact: return rb_ivar_get(parsed, id_contact); break;
449
+ /* Otherwise return the parsed object itself (useful for OverSIP::SIP::MessageParser.parse_uri method). */
450
+ default:
451
+ return parsed;
452
+ }
453
+ return Qnil;
454
+ }
455
+
456
+
457
+ static void uri_scheme(VALUE parsed, enum uri_owner owner, const char *at, size_t length, enum uri_scheme scheme)
458
+ {
459
+ TRACE();
460
+ VALUE v;
461
+
462
+ switch(scheme) {
463
+ case uri_scheme_sip: v = symbol_sip; break;
464
+ case uri_scheme_sips: v = symbol_sips; break;
465
+ case uri_scheme_tel: v = symbol_tel; break;
466
+ case uri_scheme_unknown: v = my_rb_str_downcase(at, length); break;
467
+ }
468
+
469
+ rb_ivar_set(get_uri_object(parsed, owner), id_uri_scheme, v);
470
+ }
471
+
472
+
473
+ static void uri_full(VALUE parsed, enum uri_owner owner, const char *at, size_t length, enum uri_scheme scheme)
474
+ {
475
+ TRACE();
476
+ VALUE v;
477
+
478
+ v = RB_STR_UTF8_NEW(at, length);
479
+ rb_ivar_set(get_uri_object(parsed, owner), id_uri, v);
480
+ }
481
+
482
+
483
+ static void uri_user(VALUE parsed, enum uri_owner owner, const char *at, size_t length, enum uri_scheme scheme)
484
+ {
485
+ TRACE();
486
+ VALUE v;
487
+
488
+ if (scheme == uri_scheme_tel)
489
+ v = my_rb_str_tel_number_clean(at, length);
490
+ else
491
+ v = my_rb_str_hex_unescape(at, length);
492
+
493
+ rb_ivar_set(get_uri_object(parsed, owner), id_uri_user, v);
494
+ }
495
+
496
+
497
+ static void uri_host(VALUE parsed, enum uri_owner owner, const char *at, size_t length, int type)
498
+ {
499
+ TRACE();
500
+ VALUE v;
501
+ VALUE host_type;
502
+
503
+ /* If it's a domain and ends with ".", remove it. */
504
+ if (at[length-1] == '.')
505
+ length--;
506
+
507
+ /* Downcase the host part. */
508
+ v = my_rb_str_downcase(at, length);
509
+
510
+ switch(type) {
511
+ case host_type_domain: host_type = symbol_domain; break;
512
+ case host_type_ipv4: host_type = symbol_ipv4; break;
513
+ case host_type_ipv6: host_type = symbol_ipv6_reference; break;
514
+ }
515
+
516
+ /* NOTE: In case of an IPv6 we normalize it so comparissons are easier later. */
517
+ if (host_type == symbol_ipv6_reference)
518
+ rb_ivar_set(get_uri_object(parsed, owner), id_uri_host, utils_normalize_ipv6(v, 0));
519
+ else
520
+ rb_ivar_set(get_uri_object(parsed, owner), id_uri_host, v);
521
+
522
+ rb_ivar_set(get_uri_object(parsed, owner), id_uri_host_type, host_type);
523
+ }
524
+
525
+
526
+ static void uri_port(VALUE parsed, enum uri_owner owner, const char *at, size_t length, enum uri_scheme scheme)
527
+ {
528
+ TRACE();
529
+ VALUE v;
530
+
531
+ v = INT2FIX(str_to_int(at, length));
532
+ rb_ivar_set(get_uri_object(parsed, owner), id_uri_port, v);
533
+ }
534
+
535
+
536
+ static void uri_param(VALUE parsed, enum uri_owner owner, const char *key, size_t key_len, const char *value, size_t value_len)
537
+ {
538
+ TRACE();
539
+ VALUE uri, params, v;
540
+
541
+ if ((uri = get_uri_object(parsed, owner)) == Qnil)
542
+ return;
543
+
544
+ if ((params = rb_ivar_get(uri, id_uri_params)) == Qnil) {
545
+ params = rb_hash_new();
546
+ rb_ivar_set(uri, id_uri_params, params);
547
+ }
548
+ if (value_len > 0)
549
+ v = RB_STR_UTF8_NEW(value, value_len);
550
+ else
551
+ v = Qnil;
552
+ rb_hash_aset(params, my_rb_str_downcase(key, key_len), v);
553
+ }
554
+
555
+
556
+ static void uri_known_param(VALUE parsed, enum uri_owner owner, enum uri_param_name param_name, const char *at, size_t length, int param_value)
557
+ {
558
+ TRACE();
559
+ VALUE p, v;
560
+
561
+ switch(param_name) {
562
+ case uri_param_transport:
563
+ p = id_uri_transport_param;
564
+ switch(param_value) {
565
+ case transport_udp: v = symbol_udp; break;
566
+ case transport_tcp: v = symbol_tcp; break;
567
+ case transport_tls: v = symbol_tls; break;
568
+ case transport_sctp: v = symbol_sctp; break;
569
+ case transport_ws: v = symbol_ws; break;
570
+ case transport_wss: v = symbol_wss; break;
571
+ case transport_unknown: v = my_rb_str_downcase(at, length); break;
572
+ default: break;
573
+ }
574
+ break;
575
+ case uri_param_ovid:
576
+ p = id_uri_ovid_param;
577
+ v = rb_str_new(at, length);
578
+ break;
579
+ case uri_tel_phone_context:
580
+ if (length == 0)
581
+ return;
582
+ /* If it's a domain and ends with ".", remove it. */
583
+ if (at[length-1] == '.')
584
+ length--;
585
+ p = id_uri_phone_context_param;
586
+ v = my_rb_str_downcase(at, length);
587
+ break;
588
+ default:
589
+ break;
590
+ }
591
+
592
+ rb_ivar_set(get_uri_object(parsed, owner), p, v);
593
+ }
594
+
595
+
596
+ static void uri_has_param(VALUE parsed, enum uri_owner owner, enum uri_param_name param_name)
597
+ {
598
+ TRACE();
599
+
600
+ VALUE p;
601
+
602
+ switch(param_name) {
603
+ case uri_param_lr: p = id_uri_lr_param; break;
604
+ case uri_param_ob: p = id_uri_ob_param; break;
605
+ default: break;
606
+ }
607
+
608
+ rb_ivar_set(get_uri_object(parsed, owner), p, Qtrue);
609
+ }
610
+
611
+
612
+ static void uri_headers(VALUE parsed, enum uri_owner owner, const char *at, size_t length, enum uri_scheme scheme)
613
+ {
614
+ TRACE();
615
+ VALUE v;
616
+
617
+ v = RB_STR_UTF8_NEW(at, length);
618
+ rb_ivar_set(get_uri_object(parsed, owner), id_uri_headers, v);
619
+ }
620
+
621
+
622
+ static void uri_display_name(VALUE parsed, enum uri_owner owner, const char *at, size_t length, enum uri_scheme scheme)
623
+ {
624
+ TRACE();
625
+ VALUE v;
626
+
627
+ if (length == 0)
628
+ return;
629
+
630
+ v = RB_STR_UTF8_NEW(at, length);
631
+ rb_ivar_set(get_uri_object(parsed, owner), id_display_name, v);
632
+ }
633
+
634
+
635
+ static void header_core_value(VALUE parsed, enum header_field header_field, const char *at, size_t length)
636
+ {
637
+ TRACE();
638
+ VALUE v;
639
+
640
+ if (length == 0)
641
+ return;
642
+
643
+ v = RB_STR_UTF8_NEW(at, length);
644
+
645
+ switch(header_field) {
646
+ case header_field_via: rb_ivar_set(parsed, id_via_core_value, v); break;
647
+ default: break;
648
+ }
649
+ }
650
+
651
+
652
+ static void header_param(VALUE parsed, enum header_field header_field, const char *key, size_t key_len, const char *value, size_t value_len)
653
+ {
654
+ TRACE();
655
+ VALUE v;
656
+ VALUE header_params;
657
+
658
+ switch(header_field) {
659
+ case header_field_via:
660
+ if ((header_params = rb_ivar_get(parsed, id_via_params)) == Qnil) {
661
+ header_params = rb_hash_new();
662
+ rb_ivar_set(parsed, id_via_params, header_params);
663
+ }
664
+ if (value_len > 0)
665
+ v = RB_STR_UTF8_NEW(value, value_len);
666
+ else
667
+ v = Qnil;
668
+ rb_hash_aset(header_params, my_rb_str_downcase(key, key_len), v);
669
+ break;
670
+ /* case header_field_contact:
671
+ if ((header_params = rb_ivar_get(parsed, id_contact_params)) == Qnil) {
672
+ header_params = rb_hash_new();
673
+ rb_ivar_set(parsed, id_contact_params, header_params);
674
+ }
675
+ if (value_len > 0)
676
+ v = RB_STR_UTF8_NEW(value, value_len);
677
+ else
678
+ v = Qnil;
679
+ rb_hash_aset(header_params, my_rb_str_downcase(key, key_len), v);
680
+ break; */
681
+ default:
682
+ break;
683
+ }
684
+ }
685
+
686
+
687
+ static void msg_contact_params(VALUE parsed, const char *at, size_t length)
688
+ {
689
+ TRACE();
690
+ VALUE v;
691
+
692
+ if (length == 0)
693
+ return;
694
+
695
+ v = RB_STR_UTF8_NEW(at, length);
696
+ rb_ivar_set(parsed, id_contact_params, v);
697
+ }
698
+
699
+
700
+ static void msg_contact_has_reg_id(VALUE parsed)
701
+ {
702
+ TRACE();
703
+
704
+ rb_ivar_set(parsed, id_contact_has_reg_id, Qtrue);
705
+ }
706
+
707
+
708
+ static void option_tag(VALUE parsed, enum header_field header_field, const char *at, size_t length)
709
+ {
710
+ TRACE();
711
+ VALUE v;
712
+ VALUE id_option_tag_owner;
713
+ VALUE option_tag_owner;
714
+
715
+ switch(header_field) {
716
+ case header_field_require: id_option_tag_owner = id_require; break;
717
+ case header_field_proxy_require: id_option_tag_owner = id_proxy_require; break;
718
+ case header_field_supported: id_option_tag_owner = id_supported; break;
719
+ default: break;
720
+ }
721
+
722
+ if ((option_tag_owner = rb_ivar_get(parsed, id_option_tag_owner)) == Qnil) {
723
+ option_tag_owner = rb_ary_new();
724
+ rb_ivar_set(parsed, id_option_tag_owner, option_tag_owner);
725
+ }
726
+ rb_ary_push(option_tag_owner,my_rb_str_downcase(at, length));
727
+ }
728
+
729
+
730
+ /*************** Custom C funcions (helpers) ****************/
731
+
732
+
733
+ /*
734
+ * my_rb_str_tel_number_clean: Remove separators from a TEL URI number and downcase letters.
735
+ */
736
+ static VALUE my_rb_str_tel_number_clean(const char *str, size_t len)
737
+ {
738
+ TRACE();
739
+ char *new_str;
740
+ VALUE str_clean;
741
+
742
+ new_str = ALLOC_N(char, len);
743
+
744
+ char *s;
745
+ int i, j;
746
+ int new_len;
747
+
748
+ for (s = (char *)str, i = 0, j = 0, new_len = len; i < len ; s++, i++)
749
+ /* The char is not a separator so keep it. */
750
+ if (*s != '-' && *s != '.' && *s != '(' && *s != ')')
751
+ /* Downcase if it's A-F. */
752
+ if (*s >= 'A' && *s <= 'F')
753
+ new_str[j++] = *s + 32;
754
+ else
755
+ new_str[j++] = *s;
756
+ else
757
+ new_len--;
758
+
759
+ str_clean = RB_STR_UTF8_NEW(new_str, new_len);
760
+ xfree(new_str);
761
+ return(str_clean);
762
+ }
763
+
764
+
765
+
766
+ /*************** Ruby functions ****************/
767
+
768
+ static void SipMessageParser_free(void *parser)
769
+ {
770
+ TRACE();
771
+ if(parser) {
772
+ /* NOTE: Use always xfree() rather than free():
773
+ * http://www.mail-archive.com/libxml-devel@rubyforge.org/msg00242.html */
774
+ xfree(parser);
775
+ }
776
+ }
777
+
778
+
779
+ VALUE SipMessageParser_alloc(VALUE klass)
780
+ {
781
+ TRACE();
782
+ VALUE obj;
783
+ /* NOTE: Use always ALLOC/ALLOC_N rather than malloc().
784
+ * ALLOC uses xmalloc:
785
+ * ALLOC(type) (type*)xmalloc(sizeof(type))
786
+ * ALLOC_N(type, n) (type*)xmalloc(sizeof(type)*(n))
787
+ */
788
+ sip_message_parser *parser = ALLOC(sip_message_parser);
789
+
790
+ /* Asign functions to the pointers of sip_message_parser struct. */
791
+ parser->data_type = data_type;
792
+ parser->header = header;
793
+
794
+ parser->message.method = msg_method;
795
+ parser->message.status_code = msg_status_code;
796
+ parser->message.reason_phrase = msg_reason_phrase;
797
+ parser->message.sip_version = msg_sip_version;
798
+ parser->message.via_sent_by_host = msg_via_sent_by_host;
799
+ parser->message.via_sent_by_port = msg_via_sent_by_port;
800
+ parser->message.via_branch = msg_via_branch;
801
+ parser->message.via_branch_rfc3261 = msg_via_branch_rfc3261;
802
+ parser->message.via_received = msg_via_received;
803
+ parser->message.via_has_rport = msg_via_has_rport;
804
+ parser->message.via_has_alias = msg_via_has_alias;
805
+ parser->message.call_id = msg_call_id;
806
+ parser->message.cseq_number = msg_cseq_number;
807
+ parser->message.max_forwards = msg_max_forwards;
808
+ parser->message.content_length = msg_content_length;
809
+ parser->message.from_tag = msg_from_tag;
810
+ parser->message.to_tag = msg_to_tag;
811
+ parser->message.contact_params = msg_contact_params;
812
+ parser->message.contact_has_reg_id = msg_contact_has_reg_id;
813
+ parser->message.header_core_value = header_core_value;
814
+ parser->message.header_param = header_param;
815
+ parser->message.option_tag = option_tag;
816
+ parser->message.init_component = init_component;
817
+
818
+ parser->uri.full = uri_full;
819
+ parser->uri.scheme = uri_scheme;
820
+ parser->uri.user = uri_user;
821
+ parser->uri.host = uri_host;
822
+ parser->uri.port = uri_port;
823
+ parser->uri.param = uri_param;
824
+ parser->uri.known_param = uri_known_param;
825
+ parser->uri.has_param = uri_has_param;
826
+ parser->uri.headers = uri_headers;
827
+ parser->uri.display_name = uri_display_name;
828
+
829
+ sip_message_parser_init(parser);
830
+
831
+ obj = Data_Wrap_Struct(klass, NULL, SipMessageParser_free, parser);
832
+ return obj;
833
+ }
834
+
835
+
836
+ /**
837
+ * call-seq:
838
+ * parser.new -> parser
839
+ *
840
+ * Creates a new parser.
841
+ */
842
+ VALUE SipMessageParser_init(VALUE self)
843
+ {
844
+ TRACE();
845
+ sip_message_parser *parser = NULL;
846
+ DATA_GET(self, sip_message_parser, parser);
847
+ sip_message_parser_init(parser);
848
+
849
+ /* NOTE: This allows the C struct to access to the VALUE element of the Ruby
850
+ MessageParser instance. */
851
+ parser->ruby_sip_parser = self;
852
+
853
+ return self;
854
+ }
855
+
856
+
857
+ /**
858
+ * call-seq:
859
+ * parser.reset -> nil
860
+ *
861
+ * Resets the parser to it's initial state so that you can reuse it
862
+ * rather than making new ones.
863
+ */
864
+ VALUE SipMessageParser_reset(VALUE self)
865
+ {
866
+ TRACE();
867
+ sip_message_parser *parser = NULL;
868
+ DATA_GET(self, sip_message_parser, parser);
869
+ sip_message_parser_init(parser);
870
+
871
+ return Qnil;
872
+ }
873
+
874
+
875
+ /**
876
+ * call-seq:
877
+ * parser.finish -> true/false
878
+ *
879
+ * Finishes a parser early which could put in a "good" or bad state.
880
+ * You should call reset after finish it or bad things will happen.
881
+ */
882
+ VALUE SipMessageParser_finish(VALUE self)
883
+ {
884
+ TRACE();
885
+ sip_message_parser *parser = NULL;
886
+ DATA_GET(self, sip_message_parser, parser);
887
+ sip_message_parser_finish(parser);
888
+
889
+ return sip_message_parser_is_finished(parser) ? Qtrue : Qfalse;
890
+ }
891
+
892
+
893
+ /**
894
+ * call-seq:
895
+ * parser.execute(buffer, start) -> Integer
896
+ */
897
+ VALUE SipMessageParser_execute(VALUE self, VALUE buffer, VALUE start)
898
+ {
899
+ TRACE();
900
+ sip_message_parser *parser = NULL;
901
+ int from = 0;
902
+ char *dptr = NULL;
903
+ long dlen = 0;
904
+
905
+ REQUIRE_TYPE(buffer, T_STRING);
906
+ REQUIRE_TYPE(start, T_FIXNUM);
907
+
908
+ DATA_GET(self, sip_message_parser, parser);
909
+
910
+ from = FIX2INT(start);
911
+ dptr = RSTRING_PTR(buffer);
912
+ dlen = RSTRING_LEN(buffer);
913
+
914
+ /* This should never occur or there is an error in the parser. */
915
+ if(from >= dlen)
916
+ rb_raise(eSIPMessageParserError, "requested start is after buffer end.");
917
+
918
+ sip_message_parser_execute(parser, dptr, dlen, from);
919
+
920
+ if (sip_message_parser_has_error(parser))
921
+ return Qfalse;
922
+ else
923
+ return INT2FIX(sip_message_parser_nread(parser));
924
+ }
925
+
926
+
927
+ /**
928
+ * call-seq:
929
+ * parser.error? -> true/false
930
+ *
931
+ * Tells you whether the parser is in an error state.
932
+ */
933
+ VALUE SipMessageParser_has_error(VALUE self)
934
+ {
935
+ TRACE();
936
+ sip_message_parser *parser = NULL;
937
+ DATA_GET(self, sip_message_parser, parser);
938
+
939
+ return sip_message_parser_has_error(parser) ? Qtrue : Qfalse;
940
+ }
941
+
942
+
943
+ /**
944
+ * call-seq:
945
+ * parser.error -> String
946
+ *
947
+ * Returns a String showing the error by enclosing the exact wrong char between {{{ }}}.
948
+ */
949
+ VALUE SipMessageParser_error(VALUE self)
950
+ {
951
+ TRACE();
952
+ sip_message_parser *parser = NULL;
953
+ DATA_GET(self, sip_message_parser, parser);
954
+
955
+ if(sip_message_parser_has_error(parser)) {
956
+ char *parsing_error_str;
957
+ int parsing_error_str_len;
958
+ int i;
959
+ int j;
960
+ VALUE rb_error_str;
961
+
962
+ /* Duplicate error string length so '\r' and '\n' are displayed as CR and LF.
963
+ Let 6 chars more for allocating {{{ and }}}. */
964
+ parsing_error_str = ALLOC_N(char, 2*parser->error_len + 6);
965
+
966
+ parsing_error_str_len=0;
967
+ for(i=0, j=0; i < parser->error_len; i++) {
968
+ if (i != parser->error_pos) {
969
+ if (parser->error_start[i] == '\r') {
970
+ parsing_error_str[j++] = '\\';
971
+ parsing_error_str[j++] = 'r';
972
+ parsing_error_str_len += 2;
973
+ }
974
+ else if (parser->error_start[i] == '\n') {
975
+ parsing_error_str[j++] = '\\';
976
+ parsing_error_str[j++] = 'n';
977
+ parsing_error_str_len += 2;
978
+ }
979
+ else {
980
+ parsing_error_str[j++] = parser->error_start[i];
981
+ parsing_error_str_len++;
982
+ }
983
+ }
984
+ else {
985
+ parsing_error_str[j++] = '{';
986
+ parsing_error_str[j++] = '{';
987
+ parsing_error_str[j++] = '{';
988
+ if (parser->error_start[i] == '\r') {
989
+ parsing_error_str[j++] = '\\';
990
+ parsing_error_str[j++] = 'r';
991
+ parsing_error_str_len += 2;
992
+ }
993
+ else if (parser->error_start[i] == '\n') {
994
+ parsing_error_str[j++] = '\\';
995
+ parsing_error_str[j++] = 'n';
996
+ parsing_error_str_len += 2;
997
+ }
998
+ else {
999
+ parsing_error_str[j++] = parser->error_start[i];
1000
+ parsing_error_str_len++;
1001
+ }
1002
+ parsing_error_str[j++] = '}';
1003
+ parsing_error_str[j++] = '}';
1004
+ parsing_error_str[j++] = '}';
1005
+ parsing_error_str_len += 6;
1006
+ }
1007
+ }
1008
+
1009
+ rb_error_str = rb_str_new(parsing_error_str, parsing_error_str_len);
1010
+ xfree(parsing_error_str);
1011
+ return rb_error_str;
1012
+ }
1013
+ else
1014
+ return Qnil;
1015
+ }
1016
+
1017
+
1018
+ /**
1019
+ * call-seq:
1020
+ * parser.finished? -> true/false
1021
+ *
1022
+ * Tells you whether the parser is finished or not and in a good state.
1023
+ */
1024
+ VALUE SipMessageParser_is_finished(VALUE self)
1025
+ {
1026
+ TRACE();
1027
+ sip_message_parser *parser = NULL;
1028
+ DATA_GET(self, sip_message_parser, parser);
1029
+
1030
+ return sip_message_parser_is_finished(parser) ? Qtrue : Qfalse;
1031
+ }
1032
+
1033
+
1034
+ /**
1035
+ * call-seq:
1036
+ * parser.parsed -> OverSIP::Request or OverSIP::Response or :outbound_keepalive or nil
1037
+ *
1038
+ * Returns the parsed object. It doesn't meant that the parsing has succedded. The returned
1039
+ * object could be a message identified as a Request or Response or :outbound_keepalive, but later
1040
+ * the message has been detected as invalid. So the parsed object is incomplete.
1041
+ *
1042
+ * In case the parsing has failed in the first char the method returns nil.
1043
+ */
1044
+ VALUE SipMessageParser_parsed(VALUE self)
1045
+ {
1046
+ TRACE();
1047
+ sip_message_parser *parser = NULL;
1048
+ DATA_GET(self, sip_message_parser, parser);
1049
+
1050
+ /* NOTE: We can safely access here to parser->parsed as its content is also referenced
1051
+ * by id_parsed so it cannot be garbage collected while the OverSIP::MessageParser
1052
+ * still alives. */
1053
+ return parser->parsed;
1054
+ }
1055
+
1056
+
1057
+ /**
1058
+ * call-seq:
1059
+ * parser.nread -> Integer
1060
+ *
1061
+ * Returns the amount of data processed so far during this processing cycle. It is
1062
+ * set to 0 on initialize or reset calls and is incremented each time execute is called.
1063
+ */
1064
+ VALUE SipMessageParser_nread(VALUE self)
1065
+ {
1066
+ TRACE();
1067
+ sip_message_parser *parser = NULL;
1068
+ DATA_GET(self, sip_message_parser, parser);
1069
+
1070
+ return INT2FIX(parser->nread);
1071
+ }
1072
+
1073
+
1074
+ /**
1075
+ * call-seq:
1076
+ * parser.duplicated_core_header? -> true/false
1077
+ *
1078
+ * In case a core header is duplicated its name is returned as string.
1079
+ * False otherwise.
1080
+ */
1081
+ VALUE SipMessageParser_has_duplicated_core_header(VALUE self)
1082
+ {
1083
+ TRACE();
1084
+ sip_message_parser *parser = NULL;
1085
+ DATA_GET(self, sip_message_parser, parser);
1086
+
1087
+ /* NOTE: Good moment for counting the num of Via values and store it. */
1088
+ rb_ivar_set(parser->parsed, id_num_vias, INT2FIX(parser->num_via));
1089
+
1090
+ if (parser->num_from > 1)
1091
+ return string_From;
1092
+ else if (parser->num_to > 1)
1093
+ return string_To;
1094
+ else if (parser->num_cseq > 1)
1095
+ return string_CSeq;
1096
+ else if (parser->num_call_id > 1)
1097
+ return string_Call_ID;
1098
+ else if (parser->num_max_forwards > 1)
1099
+ return string_Max_Forwards;
1100
+ else if (parser->num_content_length > 1)
1101
+ return string_Content_Length;
1102
+
1103
+ return Qfalse;
1104
+ }
1105
+
1106
+
1107
+ /**
1108
+ * call-seq:
1109
+ * parser.missing_core_header? -> true/false
1110
+ *
1111
+ * In case a core header is missing its name is returned as string.
1112
+ * False otherwise.
1113
+ */
1114
+ VALUE SipMessageParser_has_missing_core_header(VALUE self)
1115
+ {
1116
+ TRACE();
1117
+ sip_message_parser *parser = NULL;
1118
+ DATA_GET(self, sip_message_parser, parser);
1119
+
1120
+ if (parser->num_via == 0)
1121
+ return string_Via;
1122
+ else if (parser->num_from == 0)
1123
+ return string_From;
1124
+ else if (parser->num_to == 0)
1125
+ return string_To;
1126
+ else if (parser->num_cseq == 0)
1127
+ return string_CSeq;
1128
+ else if (parser->num_call_id == 0)
1129
+ return string_Call_ID;
1130
+
1131
+ return Qfalse;
1132
+ }
1133
+
1134
+
1135
+ VALUE SipMessageParser_post_parsing(VALUE self)
1136
+ {
1137
+ TRACE();
1138
+ sip_message_parser *parser = NULL;
1139
+ DATA_GET(self, sip_message_parser, parser);
1140
+
1141
+ /* We just parse Contact if it's a single header with a single Name Addr within it. */
1142
+ if (! (parser->contact_is_valid == 1 && parser->num_contact == 1))
1143
+ rb_ivar_set(parser->parsed, id_contact, Qnil);
1144
+
1145
+ return Qnil;
1146
+ }
1147
+
1148
+
1149
+ /**
1150
+ * call-seq:
1151
+ * OverSIP::SIP::MessageParser.headarize -> String
1152
+ *
1153
+ * Tries to lookup the header name in a list of well-known headers. If so,
1154
+ * returns the retrieved VALUE. It also works for short headers.
1155
+ * In case the header is unknown, it normalizes it (by capitalizing the
1156
+ * first letter and each letter under a "-" or "_" symbol).
1157
+ */
1158
+ VALUE SipMessageParser_Class_headerize(VALUE self, VALUE string)
1159
+ {
1160
+ TRACE();
1161
+ if (TYPE(string) != T_STRING)
1162
+ rb_raise(rb_eTypeError, "Argument must be a String");
1163
+
1164
+ if ((RSTRING_LEN(string)) == 0)
1165
+ rb_str_new(RSTRING_PTR(string), RSTRING_LEN(string));
1166
+
1167
+ return(headerize(RSTRING_PTR(string), RSTRING_LEN(string)));
1168
+ }
1169
+
1170
+
1171
+ /**
1172
+ * call-seq:
1173
+ * OverSIP::SIP::MessageParser.parse_uri(string) -> OverSIP::SIP::Uri
1174
+ */
1175
+ VALUE SipMessageParser_Class_parse_uri(VALUE self, VALUE string, VALUE allow_name_addr)
1176
+ {
1177
+ TRACE();
1178
+ char *dptr = NULL;
1179
+ long dlen = 0;
1180
+ sip_uri_parser *parser;
1181
+ VALUE parsed;
1182
+ int int_allow_name_addr;
1183
+
1184
+ /* Initialize the global SIP URI parser if not set yet. */
1185
+ if (global_sip_uri_parser == NULL) {
1186
+ /* Asign functions to the pointers of global_sip_uri_parser struct. */
1187
+ global_sip_uri_parser = ALLOC(sip_uri_parser);
1188
+ global_sip_uri_parser->uri.full = uri_full;
1189
+ global_sip_uri_parser->uri.scheme = uri_scheme;
1190
+ global_sip_uri_parser->uri.user = uri_user;
1191
+ global_sip_uri_parser->uri.host = uri_host;
1192
+ global_sip_uri_parser->uri.port = uri_port;
1193
+ global_sip_uri_parser->uri.param = uri_param;
1194
+ global_sip_uri_parser->uri.known_param = uri_known_param;
1195
+ global_sip_uri_parser->uri.has_param = uri_has_param;
1196
+ global_sip_uri_parser->uri.headers = uri_headers;
1197
+ global_sip_uri_parser->uri.display_name = uri_display_name;
1198
+ }
1199
+
1200
+ REQUIRE_TYPE(string, T_STRING);
1201
+
1202
+ /* NOTE: We need to pass a \0 terminated string to the URI parser. StringValueCStr() gives
1203
+ * exactly that. So also increment dlen in 1. */
1204
+ dptr = StringValueCStr(string);
1205
+ dlen = RSTRING_LEN(string) + 1;
1206
+
1207
+ if (TYPE(allow_name_addr) == T_TRUE) {
1208
+ parsed = rb_obj_alloc(cNameAddr);
1209
+ int_allow_name_addr = 1;
1210
+ }
1211
+ else {
1212
+ parsed = rb_obj_alloc(cUri);
1213
+ int_allow_name_addr = 0;
1214
+ }
1215
+
1216
+ if (sip_uri_parser_execute(global_sip_uri_parser, dptr, dlen, parsed, int_allow_name_addr) == 0)
1217
+ return parsed;
1218
+ else
1219
+ return Qfalse;
1220
+ }
1221
+
1222
+
1223
+
1224
+
1225
+ void Init_sip_parser()
1226
+ {
1227
+ TRACE();
1228
+
1229
+ mOverSIP = rb_define_module("OverSIP");
1230
+ eOverSIPError = rb_define_class_under(mOverSIP, "Error", rb_eStandardError);
1231
+
1232
+ mSIP = rb_define_module_under(mOverSIP, "SIP");
1233
+ cSIPMessageParser = rb_define_class_under(mSIP, "MessageParser", rb_cObject);
1234
+ cSIPMessage = rb_define_class_under(mSIP, "Message", rb_cObject);
1235
+ cSIPRequest = rb_define_class_under(mSIP, "Request", cSIPMessage);
1236
+ cSIPResponse = rb_define_class_under(mSIP, "Response", cSIPMessage);
1237
+ cUri = rb_define_class_under(mSIP, "Uri", rb_cObject);
1238
+ cNameAddr = rb_define_class_under(mSIP, "NameAddr", cUri);
1239
+ eSIPMessageParserError = rb_define_class_under(mSIP, "MessageParserError", eOverSIPError);
1240
+
1241
+ rb_define_alloc_func(cSIPMessageParser, SipMessageParser_alloc);
1242
+ rb_define_method(cSIPMessageParser, "initialize", SipMessageParser_init,0);
1243
+ rb_define_method(cSIPMessageParser, "reset", SipMessageParser_reset,0);
1244
+ rb_define_method(cSIPMessageParser, "finish", SipMessageParser_finish,0);
1245
+ rb_define_method(cSIPMessageParser, "execute", SipMessageParser_execute,2);
1246
+ rb_define_method(cSIPMessageParser, "error?", SipMessageParser_has_error,0);
1247
+ rb_define_method(cSIPMessageParser, "error", SipMessageParser_error,0);
1248
+ rb_define_method(cSIPMessageParser, "finished?", SipMessageParser_is_finished,0);
1249
+ rb_define_method(cSIPMessageParser, "parsed", SipMessageParser_parsed,0);
1250
+ rb_define_method(cSIPMessageParser, "nread", SipMessageParser_nread,0);
1251
+ rb_define_method(cSIPMessageParser, "duplicated_core_header?", SipMessageParser_has_duplicated_core_header,0);
1252
+ rb_define_method(cSIPMessageParser, "missing_core_header?", SipMessageParser_has_missing_core_header,0);
1253
+ rb_define_method(cSIPMessageParser, "post_parsing", SipMessageParser_post_parsing,0);
1254
+
1255
+ rb_define_module_function(cSIPMessageParser, "headerize", SipMessageParser_Class_headerize,1);
1256
+ rb_define_module_function(cSIPMessageParser, "parse_uri", SipMessageParser_Class_parse_uri,2);
1257
+
1258
+ init_common_headers();
1259
+ init_short_headers();
1260
+
1261
+ id_headers = rb_intern("@headers");
1262
+ id_parsed = rb_intern("@parsed");
1263
+ id_sip_method = rb_intern("@sip_method");
1264
+ id_is_unknown_method = rb_intern("@is_unknown_method");
1265
+ id_ruri = rb_intern("@ruri");
1266
+ id_status_code = rb_intern("@status_code");
1267
+ id_reason_phrase = rb_intern("@reason_phrase");
1268
+ id_sip_version = rb_intern("@sip_version");
1269
+ id_via_sent_by_host = rb_intern("@via_sent_by_host");
1270
+ id_via_sent_by_port = rb_intern("@via_sent_by_port");
1271
+ id_via_branch = rb_intern("@via_branch");
1272
+ id_via_branch_rfc3261 = rb_intern("@via_branch_rfc3261");
1273
+ id_via_received = rb_intern("@via_received");
1274
+ id_via_has_rport = rb_intern("@via_has_rport");
1275
+ id_via_has_alias = rb_intern("@via_has_alias");
1276
+ id_via_core_value = rb_intern("@via_core_value");
1277
+ id_via_params = rb_intern("@via_params");
1278
+ id_num_vias = rb_intern("@num_vias");
1279
+ id_call_id = rb_intern("@call_id");
1280
+ id_cseq = rb_intern("@cseq");
1281
+ id_max_forwards = rb_intern("@max_forwards");
1282
+ id_content_length = rb_intern("@content_length");
1283
+ id_from = rb_intern("@from");
1284
+ id_from_tag = rb_intern("@from_tag");
1285
+ id_to = rb_intern("@to");
1286
+ id_to_tag = rb_intern("@to_tag");
1287
+ id_routes = rb_intern("@routes");
1288
+ id_contact = rb_intern("@contact");
1289
+ id_contact_params = rb_intern("@contact_params");
1290
+ id_contact_has_reg_id = rb_intern("@contact_has_reg_id");
1291
+ id_require = rb_intern("@require");
1292
+ id_proxy_require = rb_intern("@proxy_require");
1293
+ id_supported = rb_intern("@supported");
1294
+ id_hdr_via = rb_intern("@hdr_via");
1295
+ id_hdr_from = rb_intern("@hdr_from");
1296
+ id_hdr_to = rb_intern("@hdr_to");
1297
+ id_hdr_route = rb_intern("@hdr_route");
1298
+
1299
+ id_display_name = rb_intern("@display_name");
1300
+ id_uri = rb_intern("@uri");
1301
+ id_uri_scheme = rb_intern("@scheme");
1302
+ id_uri_user = rb_intern("@user");
1303
+ id_uri_host = rb_intern("@host");
1304
+ id_uri_host_type = rb_intern("@host_type");
1305
+ id_uri_port = rb_intern("@port");
1306
+ id_uri_params = rb_intern("@params");
1307
+ id_uri_transport_param = rb_intern("@transport_param");
1308
+ id_uri_lr_param = rb_intern("@lr_param");
1309
+ id_uri_ob_param = rb_intern("@ob_param");
1310
+ id_uri_ovid_param = rb_intern("@ovid_param");
1311
+ id_uri_phone_context_param = rb_intern("@phone_context_param");
1312
+ id_uri_headers = rb_intern("@headers");
1313
+
1314
+ symbol_outbound_keepalive = ID2SYM(rb_intern("outbound_keepalive"));
1315
+ symbol_INVITE = ID2SYM(rb_intern("INVITE"));
1316
+ symbol_ACK = ID2SYM(rb_intern("ACK"));
1317
+ symbol_CANCEL = ID2SYM(rb_intern("CANCEL"));
1318
+ symbol_PRACK = ID2SYM(rb_intern("PRACK"));
1319
+ symbol_BYE = ID2SYM(rb_intern("BYE"));
1320
+ symbol_REFER = ID2SYM(rb_intern("REFER"));
1321
+ symbol_INFO = ID2SYM(rb_intern("INFO"));
1322
+ symbol_UPDATE = ID2SYM(rb_intern("UPDATE"));
1323
+ symbol_OPTIONS = ID2SYM(rb_intern("OPTIONS"));
1324
+ symbol_REGISTER = ID2SYM(rb_intern("REGISTER"));
1325
+ symbol_MESSAGE = ID2SYM(rb_intern("MESSAGE"));
1326
+ symbol_SUBSCRIBE = ID2SYM(rb_intern("SUBSCRIBE"));
1327
+ symbol_NOTIFY = ID2SYM(rb_intern("NOTIFY"));
1328
+ symbol_PUBLISH = ID2SYM(rb_intern("PUBLISH"));
1329
+ symbol_PULL = ID2SYM(rb_intern("PULL"));
1330
+ symbol_PUSH = ID2SYM(rb_intern("PUSH"));
1331
+ symbol_STORE = ID2SYM(rb_intern("STORE"));
1332
+ symbol_sip = ID2SYM(rb_intern("sip"));
1333
+ symbol_sips = ID2SYM(rb_intern("sips"));
1334
+ symbol_tel = ID2SYM(rb_intern("tel"));
1335
+ symbol_udp = ID2SYM(rb_intern("udp"));
1336
+ symbol_tcp = ID2SYM(rb_intern("tcp"));
1337
+ symbol_tls = ID2SYM(rb_intern("tls"));
1338
+ symbol_sctp = ID2SYM(rb_intern("sctp"));
1339
+ symbol_ws = ID2SYM(rb_intern("ws"));
1340
+ symbol_wss = ID2SYM(rb_intern("wss"));
1341
+ symbol_domain = ID2SYM(rb_intern("domain"));
1342
+ symbol_ipv4 = ID2SYM(rb_intern("ipv4"));
1343
+ symbol_ipv6 = ID2SYM(rb_intern("ipv6"));
1344
+ symbol_ipv6_reference = ID2SYM(rb_intern("ipv6_reference"));
1345
+
1346
+ string_Via = rb_str_new2("Via");
1347
+ string_Via = rb_obj_freeze(string_Via);
1348
+ rb_global_variable(&string_Via);
1349
+ string_From = rb_str_new2("From");
1350
+ string_From = rb_obj_freeze(string_From);
1351
+ rb_global_variable(&string_From);
1352
+ string_To = rb_str_new2("To");
1353
+ string_To = rb_obj_freeze(string_To);
1354
+ rb_global_variable(&string_To);
1355
+ string_CSeq = rb_str_new2("CSeq");
1356
+ string_CSeq = rb_obj_freeze(string_CSeq);
1357
+ rb_global_variable(&string_CSeq);
1358
+ string_Call_ID = rb_str_new2("Call-ID");
1359
+ string_Call_ID = rb_obj_freeze(string_Call_ID);
1360
+ rb_global_variable(&string_Call_ID);
1361
+ string_Max_Forwards = rb_str_new2("Max-Forwards");
1362
+ string_Max_Forwards = rb_obj_freeze(string_Max_Forwards);
1363
+ rb_global_variable(&string_Max_Forwards);
1364
+ string_Content_Length = rb_str_new2("Content-Length");
1365
+ string_Content_Length = rb_obj_freeze(string_Content_Length);
1366
+ rb_global_variable(&string_Content_Length);
1367
+
1368
+ /* Initialize global_sip_uri_parser struct to NULL. */
1369
+ global_sip_uri_parser = NULL;
1370
+ }