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