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,295 @@
1
+ module OverSIP::SIP
2
+
3
+ class ServerTransaction
4
+
5
+ include ::OverSIP::Logger
6
+
7
+ attr_reader :request
8
+ attr_accessor :last_response, :core
9
+ attr_reader :state
10
+
11
+ def initialize request
12
+ @request = request
13
+ @request.server_transaction = self
14
+ @transaction_id = request.via_branch_id
15
+ end
16
+
17
+ def retransmit_last_response
18
+ @request.send_response @last_response if @last_response
19
+ end
20
+
21
+ end # class ServerTransaction
22
+
23
+
24
+ class InviteServerTransaction < ServerTransaction
25
+
26
+ def initialize request
27
+ super
28
+ @request.connection.class.invite_server_transactions[@transaction_id] = self
29
+
30
+ @log_id = "IST #{@transaction_id}"
31
+ # Can be :proceeding, :completed, :confirmed, :accepted or :terminated.
32
+ @state = :proceeding
33
+
34
+ # NOTE: This is a timer of INVITE client transactions, but we also need it here to avoid
35
+ # that an INVITE server transaction never ends.
36
+ start_timer_C2
37
+
38
+ @request.reply 100
39
+ end
40
+
41
+ def start_timer_G
42
+ @timer_G_interval = TIMER_G
43
+ @timer_G = ::EM::PeriodicTimer.new(@timer_G_interval) do
44
+ log_system_debug "timer G expires, retransmitting last response" if $oversip_debug
45
+ retransmit_last_response
46
+ @timer_G_interval = @timer_G.interval = [2*@timer_G_interval, T2].min
47
+ end
48
+ end
49
+
50
+ def start_timer_H
51
+ @timer_H = ::EM::Timer.new(TIMER_H) do
52
+ log_system_debug "timer H expires and no ACK received, transaction terminated" if $oversip_debug
53
+ terminate_transaction
54
+ @timer_G.cancel if @timer_G
55
+ end
56
+ end
57
+
58
+ def start_timer_I
59
+ ::EM.add_timer(TIMER_I_UDP) do
60
+ log_system_debug "timer I expires, transaction terminated" if $oversip_debug
61
+ terminate_transaction
62
+ end
63
+ end
64
+
65
+ # RFC 6026.
66
+ def start_timer_L
67
+ ::EM.add_timer(TIMER_L) do
68
+ log_system_debug "timer L expires, transaction terminated" if $oversip_debug
69
+ terminate_transaction
70
+ end
71
+ end
72
+
73
+ # Timer to delete the transaction if final response is never sent by the TU.
74
+ def start_timer_C2
75
+ @timer_C2 = ::EM::Timer.new(TIMER_C2) do
76
+ log_system_debug "no final response within #{TIMER_C2} seconds, transaction terminated" if $oversip_debug
77
+ terminate_transaction
78
+ end
79
+ end
80
+
81
+ # This method is called by SipReactor#check_transaction upon receipt of an ACK
82
+ # matching an INVITE transaction (so it has been rejected with [3456]XX).
83
+ def receive_ack
84
+ case @state
85
+ when :proceeding
86
+ log_system_debug "ACK received during proceeding state, ignoring it" if $oversip_debug
87
+ when :completed
88
+ log_system_debug "ACK received during completed state, now confirmed" if $oversip_debug
89
+ @state = :confirmed
90
+ @timer_G.cancel if @timer_G
91
+ @timer_H.cancel
92
+ if @request.transport == :udp
93
+ start_timer_I
94
+ else
95
+ terminate_transaction
96
+ end
97
+ else
98
+ log_system_debug "ACK received during #{@state} state, ignoring it" if $oversip_debug
99
+ end
100
+ end
101
+
102
+ # This method is called by SipReactor#check_transaction upon receipt of an CANCEL
103
+ # matching an INVITE transaction.
104
+ def receive_cancel cancel
105
+ @core.receive_cancel(cancel) if @core
106
+ end
107
+
108
+ # Terminate current transaction and delete from the list of transactions.
109
+ def terminate_transaction
110
+ @state = :terminated
111
+ @request.connection.class.invite_server_transactions.delete(@transaction_id)
112
+ end
113
+
114
+ def receive_response status_code
115
+ # Provisional response
116
+ if status_code < 200
117
+ case @state
118
+ when :proceeding
119
+ return true
120
+ else
121
+ log_system_notice "attempt to send a provisional response while in #{@state} state"
122
+ return false
123
+ end
124
+
125
+ # 2XX final response.
126
+ elsif status_code >= 200 and status_code < 300
127
+ case @state
128
+ when :proceeding
129
+ @state = :accepted
130
+ @timer_C2.cancel
131
+ start_timer_L
132
+ return true
133
+ when :accepted
134
+ return true
135
+ else
136
+ log_system_notice "attempt to send a final 2XX response while in #{@state} state"
137
+ return false
138
+ end
139
+
140
+ # [3456]XX final response.
141
+ else
142
+ case @state
143
+ when :proceeding
144
+ @state = :completed
145
+ @timer_C2.cancel
146
+ start_timer_G if @request.transport == :udp
147
+ start_timer_H
148
+ return true
149
+ else
150
+ log_system_notice "attempt to send a final #{status_code} response while in #{@state} state"
151
+ return false
152
+ end
153
+ end
154
+ end
155
+
156
+ def valid_response? status_code
157
+ # Provisional response
158
+ if status_code < 200
159
+ case @state
160
+ when :proceeding
161
+ return true
162
+ else
163
+ return false
164
+ end
165
+
166
+ # 2XX final response.
167
+ elsif status_code >= 200 and status_code < 300
168
+ case @state
169
+ when :proceeding
170
+ return true
171
+ when :accepted
172
+ return true
173
+ else
174
+ return false
175
+ end
176
+
177
+ # [3456]XX final response.
178
+ else
179
+ case @state
180
+ when :proceeding
181
+ return true
182
+ else
183
+ return false
184
+ end
185
+ end
186
+ end
187
+
188
+ end # class InviteServerTransaction
189
+
190
+
191
+ class NonInviteServerTransaction < ServerTransaction
192
+
193
+ def initialize request
194
+ super
195
+ @request.connection.class.non_invite_server_transactions[@transaction_id] = self
196
+
197
+ @log_id = "NIST #{@transaction_id}"
198
+ # Can be :trying, :proceeding, :completed or :terminated.
199
+ @state = :trying
200
+
201
+ start_timer_INT1
202
+ end
203
+
204
+ # RFC 4320 - Section 4.1.
205
+ def start_timer_INT1
206
+ @timer_INT1 = ::EM::Timer.new(INT1) do
207
+ unless @last_response
208
+ log_system_debug "no final response within #{INT1} seconds => 100" if $oversip_debug
209
+ @request.reply 100, "I'm alive"
210
+ end
211
+ start_timer_INT2
212
+ end
213
+ end
214
+
215
+ # RFC 4320 - Section 4.2.
216
+ def start_timer_INT2
217
+ @timer_INT2 = ::EM::Timer.new(INT2) do
218
+ log_system_debug "no final response within #{INT1+INT2} seconds, transaction terminated" if $oversip_debug
219
+ terminate_transaction
220
+ end
221
+ end
222
+
223
+ def start_timer_J
224
+ ::EM.add_timer(TIMER_J_UDP) do
225
+ log_system_debug "timer J expires, transaction terminated" if $oversip_debug
226
+ terminate_transaction
227
+ end
228
+ end
229
+
230
+ # Terminate current transaction and delete from the list of transactions.
231
+ def terminate_transaction
232
+ @state = :terminated
233
+ @request.connection.class.non_invite_server_transactions.delete(@transaction_id)
234
+ end
235
+
236
+ def receive_response(status_code)
237
+ # Provisional response
238
+ if status_code < 200
239
+ case @state
240
+ when :trying
241
+ @state = :proceeding
242
+ return true
243
+ when :proceeding
244
+ return true
245
+ when :completed, :terminated
246
+ log_system_notice "attempt to send a provisional response while in #{@state} state"
247
+ return false
248
+ end
249
+
250
+ # Final response.
251
+ else
252
+ case @state
253
+ when :trying, :proceeding
254
+ @timer_INT1.cancel
255
+ @timer_INT2.cancel if @timer_INT2
256
+ @state = :completed
257
+ if @request.transport == :udp
258
+ start_timer_J
259
+ else
260
+ terminate_transaction
261
+ end
262
+ return true
263
+ when :completed, :terminated
264
+ log_system_notice "attempt to send a final response while in #{@state} state"
265
+ return false
266
+ end
267
+ end
268
+ end
269
+
270
+ def valid_response? status_code
271
+ # Provisional response
272
+ if status_code < 200
273
+ case @state
274
+ when :trying
275
+ return true
276
+ when :proceeding
277
+ return true
278
+ when :completed, :terminated
279
+ return false
280
+ end
281
+
282
+ # Final response.
283
+ else
284
+ case @state
285
+ when :trying, :proceeding
286
+ return true
287
+ when :completed, :terminated
288
+ return false
289
+ end
290
+ end
291
+ end
292
+
293
+ end # class NonInviteServerTransaction
294
+
295
+ end
@@ -0,0 +1,76 @@
1
+ module OverSIP::SIP
2
+
3
+ def self.module_init
4
+ conf = ::OverSIP.configuration
5
+
6
+ @local_ipv4 = conf[:sip][:listen_ipv4]
7
+ @local_ipv6 = conf[:sip][:listen_ipv6]
8
+
9
+ @tcp_keepalive_interval = conf[:sip][:tcp_keepalive_interval]
10
+
11
+ @local_aliases = {}
12
+
13
+ sip_local_domains = conf[:sip][:local_domains] || []
14
+ sip_local_ips = []
15
+ sip_local_ips << conf[:sip][:listen_ipv4] if conf[:sip][:enable_ipv4]
16
+ sip_local_ips << "[#{OverSIP::Utils.normalize_ipv6(conf[:sip][:listen_ipv6])}]" if conf[:sip][:enable_ipv6]
17
+ sip_local_ports = [ conf[:sip][:listen_port], conf[:sip][:listen_port_tls] ].compact
18
+ sip_local_domains.each do |domain|
19
+ @local_aliases[domain] = true
20
+ sip_local_ports.each do |port|
21
+ @local_aliases["#{domain}:#{port}"] = true
22
+ end
23
+ end
24
+ sip_local_ips.each do |ip|
25
+ sip_local_ports.each do |port|
26
+ @local_aliases["#{ip}:#{port}"] = true
27
+ end
28
+ end
29
+ sip_local_ips.each do |ip|
30
+ @local_aliases[ip] = true if conf[:sip][:listen_port] == 5060 or conf[:sip][:listen_port_tls] == 5061
31
+ end
32
+
33
+ ws_local_domains = conf[:sip][:local_domains] || []
34
+ ws_local_ips = []
35
+ ws_local_ips << conf[:websocket][:listen_ipv4] if conf[:websocket][:enable_ipv4]
36
+ ws_local_ips << "[#{OverSIP::Utils.normalize_ipv6(conf[:websocket][:listen_ipv6])}]" if conf[:websocket][:enable_ipv6]
37
+ ws_local_ports = [ conf[:websocket][:listen_port], conf[:websocket][:listen_port_tls] ].compact
38
+ ws_local_domains.each do |domain|
39
+ @local_aliases[domain] = true
40
+ ws_local_ports.each do |port|
41
+ @local_aliases["#{domain}:#{port}"] = true
42
+ end
43
+ end
44
+ ws_local_ips.each do |ip|
45
+ ws_local_ports.each do |port|
46
+ @local_aliases["#{ip}:#{port}"] = true
47
+ end
48
+ end
49
+ ws_local_ips.each do |ip|
50
+ @local_aliases[ip] = true if conf[:websocket][:listen_port] == 80 or conf[:websocket][:listen_port_tls] == 443
51
+ end
52
+
53
+ @callback_on_client_tls_handshake = conf[:sip][:callback_on_client_tls_handshake]
54
+ end
55
+
56
+ def self.local_aliases
57
+ @local_aliases
58
+ end
59
+
60
+ def self.tcp_keepalive_interval
61
+ @tcp_keepalive_interval
62
+ end
63
+
64
+ def self.local_ipv4
65
+ @local_ipv4
66
+ end
67
+
68
+ def self.local_ipv6
69
+ @local_ipv6
70
+ end
71
+
72
+ def self.callback_on_client_tls_handshake
73
+ @callback_on_client_tls_handshake
74
+ end
75
+
76
+ end
@@ -0,0 +1,39 @@
1
+ module OverSIP::SIP
2
+
3
+ module Tags
4
+
5
+ PREFIX_FOR_TOTAG_SL_REPLIED = ::SecureRandom.hex(4) + "."
6
+ REGEX_PREFIX_FOR_TOTAG_SL_REPLIED = /^#{PREFIX_FOR_TOTAG_SL_REPLIED}/
7
+
8
+ ROUTE_OVID_VALUE = ::SecureRandom.hex(4)
9
+ ROUTE_OVID_VALUE_HASH = ROUTE_OVID_VALUE.hash
10
+
11
+ ANTILOOP_CONST = ::SecureRandom.hex(1)
12
+
13
+
14
+ def self.totag_for_sl_reply
15
+ PREFIX_FOR_TOTAG_SL_REPLIED + ::SecureRandom.hex(4)
16
+ end
17
+
18
+ def self.check_totag_for_sl_reply totag
19
+ return nil unless totag
20
+ totag =~ REGEX_PREFIX_FOR_TOTAG_SL_REPLIED
21
+ end
22
+
23
+ def self.value_for_route_ovid
24
+ ROUTE_OVID_VALUE
25
+ end
26
+
27
+ def self.check_value_for_route_ovid value
28
+ return nil unless value
29
+ value.hash == ROUTE_OVID_VALUE_HASH
30
+ end
31
+
32
+ def self.create_antiloop_id request
33
+ # It produces a 32 chars string.
34
+ ::Digest::MD5.hexdigest "#{ANTILOOP_CONST}#{request.ruri.to_s}#{request.call_id}#{request.routes[0].uri if request.routes}"
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,55 @@
1
+ module OverSIP::SIP
2
+
3
+ ### SIP timer values.
4
+ #
5
+ # RTT Estimate (RFC 3261 17.1.2.1).
6
+ T1 = 0.5
7
+ # The maximum retransmit interval for non-INVITE requests and INVITE
8
+ # responses (RFC 3261 17.1.2.2).
9
+ T2 = 4
10
+ # Maximum duration a message will remain in the network (RFC 3261 17.1.2.2).
11
+ T4 = 5
12
+ # INVITE request retransmit interval, for UDP only (RFC 3261 17.1.1.2).
13
+ TIMER_A = T1 # initially T1.
14
+ # INVITE transaction timeout timer (RFC 3261 17.1.1.2).
15
+ TIMER_B = 64*T1
16
+ # Proxy INVITE transaction timeout (RFC 3261 16.6 bullet 11).
17
+ TIMER_C = 180 # > 3min.
18
+ # NOTE: This is a custom timer we use for INVITE server transactions in order to avoid they never end.
19
+ TIMER_C2 = TIMER_C + 2
20
+ # Wait time for response retransmits (RFC 3261 17.1.1.2).
21
+ TIMER_D_UDP = 32 # > 32s for UDP.
22
+ TIMER_D_TCP = 0 # 0s for TCP/SCTP.
23
+ # Non-INVITE request retransmit interval, UDP only (RFC 3261 17.1.2.2).
24
+ TIMER_E = T1 # initially T1
25
+ # Non-INVITE transaction timeout timer.
26
+ TIMER_F = 64*T1
27
+ # INVITE response retransmit interval (RFC 3261 17.2.1).
28
+ TIMER_G = T1 # initially T1.
29
+ # Wait time for ACK receipt (RFC 3261 17.2.1).
30
+ TIMER_H = 64*T1
31
+ # Wait time for ACK retransmits (RFC 3261 17.2.1).
32
+ TIMER_I_UDP = T4 # T4 for UDP.
33
+ TIMER_I_TCP = 0 # 0s for TCP/SCTP.
34
+ # Wait time for non-INVITE requests (RFC 3261 17.2.2).
35
+ TIMER_J_UDP = 64*T1 # 64*T1 for UDP.
36
+ TIMER_J_TCP = 0 # 0s for TCP/SCTP.
37
+ # Wait time for response retransmits (RFC 3261 17.1.2.2).
38
+ TIMER_K_UDP = T4 # T4 for UDP.
39
+ TIMER_K_TCP = 0 # 0s for TCP/SCTP.
40
+ # Wait time for accepted INVITE request retransmits (RFC 6026 17.2.1).
41
+ TIMER_L = 64*T1
42
+ # Wait time for retransmission of 2xx to INVITE or additional 2xx from
43
+ # other branches of a forked INVITE (RFC 6026 17.1.1).
44
+ TIMER_M = 64*T1
45
+
46
+ ### Custom values.
47
+ #
48
+ # Interval waiting in a non INVITE server transaction before sending 100
49
+ # (RFC 4320 - Section 4.1).
50
+ INT1 = T2 + 1
51
+ # Interval waiting in a non INVITE server transaction before assuming
52
+ # timeout (RFC 4320 - Section 4.2).
53
+ INT2 = TIMER_F - INT1
54
+
55
+ end
@@ -0,0 +1,130 @@
1
+ module OverSIP::SIP
2
+
3
+ module TransportManager
4
+
5
+ extend ::OverSIP::Logger
6
+
7
+ @log_id = "TransportManager"
8
+ @outbound_connections = {}
9
+
10
+
11
+ # Get an existing connection or create a new one (TCP/TLS).
12
+ # For UDP it always returns the single UDP reactor instance.
13
+ # client_transaction is passed when creating a new clien transaction. In case the
14
+ # outgoing connection is a TCP/TLS client connection and it's not connected yet,
15
+ # the client transaction is stored in the @pending_client_transactions of the client
16
+ # connection.
17
+ # This method always returns a connection object, never nil or false.
18
+ def self.get_connection klass, ip, port, client_transaction=nil, callback_on_server_tls_handshake=false
19
+ # A normal connection (so we arrive here after RFC 3263 procedures).
20
+ case klass.transport
21
+
22
+ # In UDP there is a single connection (the UDP server unique instance).
23
+ when :udp
24
+ conn = klass.connections
25
+
26
+ # In TCP/TLS first check if there is an existing connection to the given destination.
27
+ # If not create a new one.
28
+ when :tcp
29
+ case klass.ip_type
30
+ when :ipv4
31
+ conn = klass.connections["#{ip}_#{port}"] || ::EM.oversip_connect_tcp_server(::OverSIP::SIP.local_ipv4, ip, port, ::OverSIP::SIP::IPv4TcpClient, ip, port)
32
+
33
+ if conn.is_a? ::OverSIP::SIP::IPv4TcpClient and not conn.connected
34
+ conn.pending_client_transactions << client_transaction
35
+ end
36
+ when :ipv6
37
+ conn = klass.connections["#{::OverSIP::Utils.normalize_ipv6 ip}_#{port}"] || ::EM.oversip_connect_tcp_server(::OverSIP::SIP.local_ipv6, ip, port, ::OverSIP::SIP::IPv6TcpClient, ip, port)
38
+
39
+ if conn.is_a? ::OverSIP::SIP::IPv6TcpClient and not conn.connected
40
+ conn.pending_client_transactions << client_transaction
41
+ end
42
+ end
43
+
44
+ when :tls
45
+ case klass.ip_type
46
+ when :ipv4
47
+ conn = klass.connections["#{ip}_#{port}"] || ::EM.oversip_connect_tcp_server(::OverSIP::SIP.local_ipv4, ip, port, ::OverSIP::SIP::IPv4TlsClient, ip, port)
48
+
49
+ if conn.is_a? ::OverSIP::SIP::IPv4TlsClient and not conn.connected
50
+ conn.callback_on_server_tls_handshake = callback_on_server_tls_handshake
51
+ conn.pending_client_transactions << client_transaction
52
+ end
53
+ when :ipv6
54
+ conn = klass.connections["#{::OverSIP::Utils.normalize_ipv6 ip}_#{port}"] || ::EM.oversip_connect_tcp_server(::OverSIP::SIP.local_ipv6, ip, port, ::OverSIP::SIP::IPv6TlsClient, ip, port)
55
+
56
+ if conn.is_a? ::OverSIP::SIP::IPv6TlsClient and not conn.connected
57
+ conn.callback_on_server_tls_handshake = callback_on_server_tls_handshake
58
+ conn.pending_client_transactions << client_transaction
59
+ end
60
+ end
61
+ end
62
+
63
+ # NOTE: Should never happen.
64
+ unless conn
65
+ ::OverSIP::Launcher.fatal "no connection retrieved from TransportManager.get_connection(), FIXME, it should never occur!!!"
66
+ end
67
+
68
+ # Return the created/retrieved connection instance.
69
+ conn
70
+ end
71
+
72
+
73
+ def self.add_connection server, server_class, ip_type, ip, port
74
+ connection_id = case ip_type
75
+ when :ipv4
76
+ "#{ip}_#{port}"
77
+ when :ipv6
78
+ "#{::OverSIP::Utils.normalize_ipv6 ip}_#{port}"
79
+ end
80
+
81
+ server_class.connections[connection_id] = server
82
+
83
+ # Return the connection_id.
84
+ connection_id
85
+ end
86
+
87
+
88
+ # Return a SIP server instance. It could return nil (if the requested connection no longer
89
+ # exists) or false (if it's a tampered flow token).
90
+ def self.get_outbound_connection flow_token
91
+ # If the token flow has been generated for UDP it is "_" followed by the Base64
92
+ # encoded representation of "IP_port", so getbyte(0) would return 95.
93
+ if flow_token.getbyte(0) == 95
94
+ # NOTE: Doing Base64.decode64 automatically removes the leading "_".
95
+ # NOTE: Previously when the Outbound flow token was generated, "=" was replaced with "-" so it becomes
96
+ # valid for a SIP URI param (needed i.e. for the OutboundMangling module).
97
+ ip_type, ip, port = ::OverSIP::Utils.parse_outbound_udp_flow_token(::Base64.decode64 flow_token.gsub(/-/,"="))
98
+
99
+ case ip_type
100
+ when :ipv4
101
+ return [ ::OverSIP::SIP::IPv4UdpServer.connections, ip, port ]
102
+ when :ipv6
103
+ return [ ::OverSIP::SIP::IPv6UdpServer.connections, ip, port ]
104
+ else
105
+ log_system_notice "udp flow token does not contain valid IP and port encoded value"
106
+ return false
107
+ end
108
+
109
+ # If not, the flow token has been generated for a TCP/TLS/WS/WSS connection so let's lookup
110
+ # it into the Outbound connection collection and return nil for IP and port.
111
+ else
112
+ @outbound_connections[flow_token]
113
+ end
114
+ end
115
+
116
+
117
+ def self.add_outbound_connection connection
118
+ outbound_flow_token = ::SecureRandom.hex(5)
119
+ @outbound_connections[outbound_flow_token] = connection
120
+ outbound_flow_token
121
+ end
122
+
123
+
124
+ def self.delete_outbound_connection outbound_flow_token
125
+ @outbound_connections.delete outbound_flow_token
126
+ end
127
+
128
+ end # module TransportManager
129
+
130
+ end
@@ -0,0 +1,89 @@
1
+ module OverSIP::SIP
2
+
3
+ class Uac < Client
4
+
5
+ def route request, dst_host=nil, dst_port=nil, dst_transport=nil
6
+ unless (@request = request).is_a? ::OverSIP::SIP::UacRequest or @request.is_a? ::OverSIP::SIP::Request
7
+ raise ::OverSIP::RuntimeError, "request must be a OverSIP::SIP::UacRequest or OverSIP::SIP::Request instance"
8
+ end
9
+
10
+ # The destination of the request is taken from:
11
+ # - dst_xxx fields if given.
12
+ # - The request.ruri (which is an OverSIP::SIP::Uri or OverSIP::SIP::NameAddr).
13
+ # Otherwise raise an exception.
14
+
15
+ @log_id = "UAC (proxy #{@conf[:name]})"
16
+
17
+ # Force the destination.
18
+ if dst_host
19
+ dst_scheme = :sip
20
+ dst_host_type = ::OverSIP::Utils.ip_type(dst_host) || :domain
21
+
22
+ # Or use the Request URI.
23
+ else
24
+ dst_scheme = request.ruri.scheme
25
+ dst_host = request.ruri.host
26
+ dst_host_type = request.ruri.host_type
27
+ dst_port = request.ruri.port
28
+ dst_transport = request.ruri.transport_param
29
+ end
30
+
31
+ # If the destination uri_host is an IPv6 reference, convert it to real IPv6.
32
+ if dst_host_type == :ipv6_reference
33
+ dst_host = ::OverSIP::Utils.normalize_ipv6(dst_host, true)
34
+ dst_host_type = :ipv6
35
+ end
36
+
37
+ # Loockup in the DNS cache of this proxy.
38
+ result = check_dns_cache dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
39
+
40
+ case result
41
+ when true
42
+ return
43
+ else # It can be String or nil, so use it as dns_cache_key param.
44
+ # Perform RFC 3263 procedures.
45
+ do_dns result, @request.via_branch_id, dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
46
+ end
47
+
48
+ end # def route
49
+
50
+
51
+ def receive_response response
52
+ log_system_debug "received response #{response.status_code}" if $oversip_debug
53
+
54
+ if response.status_code < 200
55
+ run_on_provisional_response_cbs response
56
+ elsif response.status_code >= 200 && response.status_code <= 299
57
+ run_on_success_response_cbs response
58
+ elsif response.status_code >= 300
59
+ if response.status_code == 503
60
+ if @conf[:dns_failover_on_503]
61
+ try_next_target nil, nil, response
62
+ return
63
+ else
64
+ run_on_failure_response_cbs response
65
+ end
66
+ else
67
+ run_on_failure_response_cbs response
68
+ end
69
+ end
70
+ end
71
+
72
+
73
+
74
+ private
75
+
76
+
77
+ def no_more_targets status, reason, full_response, code
78
+ # If we have received a [3456]XX response from downstream then run @on_failure_response_cbs.
79
+ if full_response
80
+ run_on_failure_response_cbs full_response
81
+ # If not, generate the response according to the given status and reason.
82
+ else
83
+ run_on_error_cbs status, reason, code
84
+ end
85
+ end
86
+
87
+ end # class Uac
88
+
89
+ end