oversip_p 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,428 @@
1
+ module OverSIP::SIP
2
+
3
+ class Client
4
+
5
+ include ::OverSIP::Logger
6
+
7
+ attr_reader :request, :current_target
8
+
9
+ def initialize proxy_profile=:default_proxy
10
+ unless (@conf = ::OverSIP.proxies[proxy_profile.to_sym])
11
+ raise ::OverSIP::RuntimeError, "proxy profile '#{proxy_profile}' is not defined"
12
+ end
13
+
14
+ @on_provisional_response_cbs = []
15
+ @on_success_response_cbs = []
16
+ @on_failure_response_cbs = []
17
+ @on_canceled_cbs = []
18
+ @on_invite_timeout_cbs = []
19
+ @on_error_cbs = []
20
+ @on_target_cbs = []
21
+ end
22
+
23
+ def on_provisional_response &block
24
+ @on_provisional_response_cbs << block
25
+ end
26
+
27
+ def on_success_response &block
28
+ @on_success_response_cbs << block
29
+ end
30
+
31
+ def on_failure_response &block
32
+ @on_failure_response_cbs << block
33
+ end
34
+
35
+ def on_canceled &block
36
+ @on_canceled_cbs << block
37
+ end
38
+
39
+ def on_invite_timeout &block
40
+ @on_invite_timeout_cbs << block
41
+ end
42
+
43
+ def on_error &block
44
+ @on_error_cbs << block
45
+ end
46
+
47
+ def on_target &block
48
+ @on_target_cbs << block
49
+ end
50
+
51
+ def clear_on_provisional_response
52
+ @on_provisional_response_cbs.clear
53
+ end
54
+
55
+ def clear_on_success_response
56
+ @on_success_response_cbs.clear
57
+ end
58
+
59
+ def clear_on_failure_response
60
+ @on_failure_response_cbs.clear
61
+ end
62
+
63
+ def clear_on_canceled
64
+ @on_canceled_cbs.clear
65
+ end
66
+
67
+ def clear_on_invite_timeout
68
+ @on_invite_timeout_cbs.clear
69
+ end
70
+
71
+ def clear_on_error
72
+ @on_error_cbs.clear
73
+ end
74
+
75
+ def clear_on_target
76
+ @on_target_cbs.clear
77
+ end
78
+
79
+ def clear_callbacks
80
+ @on_provisional_response_cbs.clear
81
+ @on_success_response_cbs.clear
82
+ @on_failure_response_cbs.clear
83
+ @on_canceled_cbs.clear
84
+ @on_invite_timeout_cbs.clear
85
+ @on_error_cbs.clear
86
+ @on_target_cbs.clear
87
+ end
88
+
89
+ # By calling this method the request routing is aborted, no more DNS targets are tryed,
90
+ # a local 403 response is generated and on_error() callback is called with status 403.
91
+ def abort_routing
92
+ @aborted = true
93
+ end
94
+
95
+ # Manually insert the last target into the blacklist. Optionally a timeout value can be given
96
+ # (otherwise the proxy blacklist_time is used). The timeout must be between 2 and 600 seconds.
97
+ # Also the SIP code and reason can be passed.
98
+ def add_target_to_blacklist timeout=nil, status_code=403, reason_phrase="Destination Blacklisted"
99
+ return false unless @current_target
100
+
101
+ if timeout
102
+ timeout = timeout.to_i
103
+ if timeout < 2 or timeout > 600
104
+ raise ::OverSIP::RuntimeError, "timeout must be between a and 600 seconds"
105
+ end
106
+ else
107
+ timeout = @conf[:blacklist_time]
108
+ end
109
+
110
+ blacklist_entry = @current_target.to_s
111
+ @conf[:blacklist][blacklist_entry] = [status_code, reason_phrase, nil, :destination_blacklisted]
112
+ ::EM.add_timer(timeout) { @conf[:blacklist].delete blacklist_entry }
113
+ end
114
+
115
+
116
+ ### Methods called by the client transaction.
117
+
118
+ def client_timeout
119
+ # Store the target and error in the blacklist.
120
+ if @conf[:use_blacklist]
121
+ blacklist_entry = @current_target.to_s
122
+ @conf[:blacklist][blacklist_entry] = [408, "Client Timeout", nil, :client_timeout]
123
+ ::EM.add_timer(@conf[:blacklist_time]) { @conf[:blacklist].delete blacklist_entry }
124
+ end
125
+
126
+ try_next_target 408, "Client Timeout", nil, :client_timeout
127
+ end
128
+
129
+ def connection_failed
130
+ # Store the target and error in the blacklist.
131
+ if @conf[:use_blacklist]
132
+ blacklist_entry = @current_target.to_s
133
+ @conf[:blacklist][blacklist_entry] = [500, "Connection Error", nil, :connection_error]
134
+ ::EM.add_timer(@conf[:blacklist_time]) { @conf[:blacklist].delete blacklist_entry }
135
+ end
136
+
137
+ try_next_target 500, "Connection Error", nil, :connection_error
138
+ end
139
+
140
+ def tls_validation_failed
141
+ # Store the target and error in the blacklist.
142
+ if @conf[:use_blacklist]
143
+ blacklist_entry = @current_target.to_s
144
+ @conf[:blacklist][blacklist_entry] = [500, "TLS Validation Failed", nil, :tls_validation_failed]
145
+ ::EM.add_timer(@conf[:blacklist_time]) { @conf[:blacklist].delete blacklist_entry }
146
+ end
147
+
148
+ try_next_target 500, "TLS Validation Failed", nil, :tls_validation_failed
149
+ end
150
+
151
+ # Timer C for INVITE.
152
+ def invite_timeout
153
+ run_on_invite_timeout_cbs
154
+ end
155
+
156
+
157
+
158
+ private
159
+
160
+
161
+ def run_on_provisional_response_cbs response
162
+ @on_provisional_response_cbs.each do |cb|
163
+ begin
164
+ cb.call response
165
+ rescue => e
166
+ log_system_error "error executing on_provisional_response callback:"
167
+ log_system_error e
168
+ end
169
+ end
170
+ end
171
+
172
+ def run_on_success_response_cbs response
173
+ @on_success_response_cbs.each do |cb|
174
+ begin
175
+ cb.call response
176
+ rescue => e
177
+ log_system_error "error executing on_success_response callback:"
178
+ log_system_error e
179
+ end
180
+ end
181
+ end
182
+
183
+ def run_on_failure_response_cbs response
184
+ @on_failure_response_cbs.each do |cb|
185
+ begin
186
+ cb.call response
187
+ rescue => e
188
+ log_system_error "error executing on_failure_response callback:"
189
+ log_system_error e
190
+ end
191
+ end
192
+ end
193
+
194
+ def run_on_canceled_cbs
195
+ @on_canceled_cbs.each do |cb|
196
+ begin
197
+ cb.call
198
+ rescue => e
199
+ log_system_error "error executing on_canceled callback:"
200
+ log_system_error e
201
+ end
202
+ end
203
+ end
204
+
205
+ def run_on_invite_timeout_cbs
206
+ @on_invite_timeout_cbs.each do |cb|
207
+ begin
208
+ cb.call
209
+ rescue => e
210
+ log_system_error "error executing on_invite_timeout callback:"
211
+ log_system_error e
212
+ end
213
+ end
214
+ end
215
+
216
+ def run_on_error_cbs status, reason, code
217
+ @on_error_cbs.each do |cb|
218
+ begin
219
+ cb.call status, reason, code
220
+ rescue => e
221
+ log_system_error "error executing on_error callback:"
222
+ log_system_error e
223
+ end
224
+ end
225
+ end
226
+
227
+ def run_on_target_cbs target
228
+ @on_target_cbs.each do |cb|
229
+ begin
230
+ cb.call target
231
+ rescue => e
232
+ log_system_error "error executing on_target callback:"
233
+ log_system_error e
234
+ end
235
+ end
236
+ end
237
+
238
+
239
+ def add_routing_headers
240
+ end
241
+
242
+
243
+ # Check the given URI into the DNS cache.
244
+ # - If the cache is not enabled it returns nil.
245
+ # - If present it returns true.
246
+ # - If not it returns dns_cache_key (String).
247
+ def check_dns_cache dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
248
+ if dst_host_type == :domain and @conf[:use_dns_cache]
249
+ dns_cache_key = "#{dst_scheme}|#{dst_host}|#{dst_port}|#{dst_transport}"
250
+ if (result = @conf[:dns_cache][dns_cache_key])
251
+ log_system_debug "destination found in the DNS cache" if $oversip_debug
252
+ if result.is_a? ::Symbol
253
+ rfc3263_failed result
254
+ else
255
+ rfc3263_succeeded result
256
+ end
257
+ return true
258
+ else
259
+ return dns_cache_key
260
+ end
261
+ else
262
+ return nil
263
+ end
264
+ end
265
+
266
+
267
+ def do_dns dns_cache_key, id, dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
268
+ # Perform RFC 3261 procedures.
269
+ dns_query = ::OverSIP::SIP::RFC3263::Query.new @conf, id, dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
270
+ case result = dns_query.resolve
271
+
272
+ # Async result so DNS took place.
273
+ when nil
274
+ # Async success.
275
+ dns_query.callback do |result|
276
+ # Store the result in the DNS cache.
277
+ if dns_cache_key
278
+ @conf[:dns_cache][dns_cache_key] = result
279
+ ::EM.add_timer(@conf[:dns_cache_time]) { @conf[:dns_cache].delete dns_cache_key }
280
+ end
281
+ rfc3263_succeeded result
282
+ end
283
+ # Async error.
284
+ dns_query.errback do |result|
285
+ # Store the result in the DNS cache.
286
+ if dns_cache_key
287
+ @conf[:dns_cache][dns_cache_key] = result
288
+ ::EM.add_timer(@conf[:dns_cache_time]) { @conf[:dns_cache].delete dns_cache_key }
289
+ end
290
+ rfc3263_failed result
291
+ end
292
+ # Instant error.
293
+ when ::Symbol
294
+ # Store the result in the DNS cache.
295
+ if dns_cache_key
296
+ @conf[:dns_cache][dns_cache_key] = result
297
+ ::EM.add_timer(@conf[:dns_cache_time]) { @conf[:dns_cache].delete dns_cache_key }
298
+ end
299
+ rfc3263_failed result
300
+ # Instant success so it's not a domain (no DNS performed).
301
+ else
302
+ rfc3263_succeeded result
303
+ end
304
+ end
305
+
306
+
307
+ def rfc3263_succeeded result
308
+ # After RFC 3263 (DNS) resolution we get N targets.
309
+ @num_target = 0
310
+ @target = @targets = nil # Avoid conflicts if same Proxy is used for serial forking to a new destination.
311
+
312
+ case result
313
+
314
+ when RFC3263::Target
315
+ @target = result # Single Target.
316
+
317
+ when RFC3263::SrvTargets
318
+ log_system_debug "DNS result has multiple values, randomizing" if $oversip_debug
319
+ @targets = result.randomize # Array of Targets.
320
+
321
+ # This can contain Target and SrvTargets entries.
322
+ when RFC3263::MultiTargets
323
+ log_system_debug "DNS result has multiple values, randomizing" if $oversip_debug
324
+ @targets = result.flatten # Array of Targets.
325
+
326
+ end
327
+
328
+ try_next_target
329
+ end # rfc3263_succeeded
330
+
331
+
332
+ def try_next_target status=nil, reason=nil, full_response=nil, code=nil
333
+ # Single target.
334
+ if @target and @num_target == 0
335
+ @current_target = @target
336
+ @num_target = 1
337
+ log_system_debug "trying single target: #{@current_target}" if $oversip_debug
338
+ use_target @current_target
339
+
340
+ # Multiple targets (so @targets is set).
341
+ elsif @targets and @num_target < @targets.size
342
+ @current_target = @targets[@num_target]
343
+ @num_target += 1
344
+ log_system_debug "trying target #{@num_target} of #{@targets.size}: #{@current_target}" if $oversip_debug
345
+ use_target @current_target
346
+
347
+ # No more targets.
348
+ else
349
+ no_more_targets status, reason, full_response, code
350
+ end
351
+ end # try_next_target
352
+
353
+
354
+ def use_target target
355
+ # Lookup the target in the blacklist.
356
+ if @conf[:blacklist].any? and (blacklist_entry = @conf[:blacklist][target.to_s])
357
+ log_system_notice "destination found in the blacklist" if $oversip_debug
358
+ try_next_target blacklist_entry[0], blacklist_entry[1], blacklist_entry[2], blacklist_entry[3]
359
+ return
360
+ end
361
+
362
+ # Call the on_target() callback if set by the user.
363
+ run_on_target_cbs target
364
+
365
+ # If the user has called to proxy.abort_routing() then stop next targets
366
+ # and call to on_error() callback.
367
+ if @aborted
368
+ log_system_notice "routing aborted for target #{target}"
369
+ @aborted = @target = @targets = nil
370
+ try_next_target 403, "Destination Aborted", nil, :destination_aborted
371
+ return
372
+ end
373
+
374
+ @client_transaction = (::OverSIP::SIP::ClientTransaction.get_class @request).new self, @request, @conf, target.transport, target.ip, target.ip_type, target.port
375
+ add_routing_headers
376
+ @client_transaction.send_request
377
+ end
378
+
379
+
380
+ def no_more_targets status, reason, full_response, code
381
+ end
382
+
383
+
384
+ def rfc3263_failed error
385
+ case error
386
+ when :rfc3263_domain_not_found
387
+ log_system_debug "no resolution" if $oversip_debug
388
+ status = 404
389
+ reason = "No DNS Resolution"
390
+ code = :no_dns_resolution
391
+ when :rfc3263_unsupported_scheme
392
+ log_system_debug "unsupported URI scheme" if $oversip_debug
393
+ status = 416
394
+ reason = "Unsupported URI scheme"
395
+ code = :unsupported_uri_scheme
396
+ when :rfc3263_unsupported_transport
397
+ log_system_debug "unsupported transport" if $oversip_debug
398
+ status = 478
399
+ reason = "Unsupported Transport"
400
+ code = :unsupported_transport
401
+ when :rfc3263_no_ipv4
402
+ log_system_debug "destination requires unsupported IPv4" if $oversip_debug
403
+ status = 478
404
+ reason = "Destination Requires Unsupported IPv4"
405
+ code = :no_ipv4
406
+ when :rfc3263_no_ipv6
407
+ log_system_debug "destination requires unsupported IPv6" if $oversip_debug
408
+ status = 478
409
+ reason = "Destination Requires Unsupported IPv6"
410
+ code = :no_ipv6
411
+ when :rfc3263_no_dns
412
+ log_system_debug "destination requires unsupported DNS query" if $oversip_debug
413
+ status = 478
414
+ reason = "Destination Requires Unsupported DNS Query"
415
+ code = :no_dns
416
+ end
417
+
418
+ do_dns_fail status, reason, code
419
+ end # def rfc3263_failed
420
+
421
+
422
+ def do_dns_fail status, reason, code
423
+ run_on_error_cbs status, reason, code
424
+ end
425
+
426
+ end # class Client
427
+
428
+ end