oversip_p 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +22 -0
  3. data/LICENSE +25 -0
  4. data/README.md +43 -0
  5. data/Rakefile +54 -0
  6. data/bin/oversip +184 -0
  7. data/etc/oversip.conf +274 -0
  8. data/etc/proxies.conf +145 -0
  9. data/etc/server.rb +315 -0
  10. data/etc/tls/ca/cacert.pem +3894 -0
  11. data/etc/tls/demo-tls.oversip.net.crt +17 -0
  12. data/etc/tls/demo-tls.oversip.net.key +15 -0
  13. data/etc/tls/upgrade-cacert.sh +12 -0
  14. data/etc/tls/utils/create-cert.rb +162 -0
  15. data/etc/tls/utils/get-sip-identities.rb +95 -0
  16. data/ext/common/c_util.h +74 -0
  17. data/ext/common/ruby_c_util.h +88 -0
  18. data/ext/sip_parser/common_headers.h +210 -0
  19. data/ext/sip_parser/ext_help.h +18 -0
  20. data/ext/sip_parser/extconf.rb +3 -0
  21. data/ext/sip_parser/sip_message_parser.c +29741 -0
  22. data/ext/sip_parser/sip_parser.h +250 -0
  23. data/ext/sip_parser/sip_parser_ruby.c +1370 -0
  24. data/ext/sip_parser/sip_uri_parser.c +39699 -0
  25. data/ext/stud/extconf.rb +43 -0
  26. data/ext/stun/ext_help.h +16 -0
  27. data/ext/stun/extconf.rb +3 -0
  28. data/ext/stun/stun_ruby.c +394 -0
  29. data/ext/utils/ext_help.h +14 -0
  30. data/ext/utils/extconf.rb +3 -0
  31. data/ext/utils/haproxy_protocol.c +6163 -0
  32. data/ext/utils/haproxy_protocol.h +27 -0
  33. data/ext/utils/ip_utils.c +5952 -0
  34. data/ext/utils/ip_utils.h +64 -0
  35. data/ext/utils/outbound_utils.c +3227 -0
  36. data/ext/utils/outbound_utils.h +27 -0
  37. data/ext/utils/utils_ruby.c +392 -0
  38. data/ext/utils/utils_ruby.h +76 -0
  39. data/ext/websocket_framing_utils/ext_help.h +18 -0
  40. data/ext/websocket_framing_utils/extconf.rb +3 -0
  41. data/ext/websocket_framing_utils/ws_framing_utils.h +47 -0
  42. data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
  43. data/ext/websocket_http_parser/ext_help.h +18 -0
  44. data/ext/websocket_http_parser/extconf.rb +3 -0
  45. data/ext/websocket_http_parser/ws_http_parser.c +1635 -0
  46. data/ext/websocket_http_parser/ws_http_parser.h +87 -0
  47. data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
  48. data/lib/oversip/config.rb +597 -0
  49. data/lib/oversip/config_validators.rb +126 -0
  50. data/lib/oversip/default_server.rb +52 -0
  51. data/lib/oversip/errors.rb +10 -0
  52. data/lib/oversip/fiber_pool.rb +56 -0
  53. data/lib/oversip/launcher.rb +635 -0
  54. data/lib/oversip/logger.rb +84 -0
  55. data/lib/oversip/modules/outbound_mangling.rb +56 -0
  56. data/lib/oversip/modules/user_assertion.rb +73 -0
  57. data/lib/oversip/proxies_config.rb +189 -0
  58. data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
  59. data/lib/oversip/sip/client.rb +428 -0
  60. data/lib/oversip/sip/client_transaction.rb +586 -0
  61. data/lib/oversip/sip/constants.rb +88 -0
  62. data/lib/oversip/sip/core.rb +217 -0
  63. data/lib/oversip/sip/launcher.rb +221 -0
  64. data/lib/oversip/sip/listeners/connection.rb +54 -0
  65. data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
  66. data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +22 -0
  67. data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
  68. data/lib/oversip/sip/listeners/ipv4_tls_server.rb +22 -0
  69. data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +22 -0
  70. data/lib/oversip/sip/listeners/ipv4_udp_server.rb +21 -0
  71. data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
  72. data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +22 -0
  73. data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
  74. data/lib/oversip/sip/listeners/ipv6_tls_server.rb +22 -0
  75. data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +22 -0
  76. data/lib/oversip/sip/listeners/ipv6_udp_server.rb +21 -0
  77. data/lib/oversip/sip/listeners/tcp_client.rb +97 -0
  78. data/lib/oversip/sip/listeners/tcp_connection.rb +202 -0
  79. data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
  80. data/lib/oversip/sip/listeners/tls_client.rb +125 -0
  81. data/lib/oversip/sip/listeners/tls_server.rb +88 -0
  82. data/lib/oversip/sip/listeners/tls_tunnel_connection.rb +89 -0
  83. data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
  84. data/lib/oversip/sip/listeners/udp_connection.rb +214 -0
  85. data/lib/oversip/sip/listeners.rb +24 -0
  86. data/lib/oversip/sip/message.rb +177 -0
  87. data/lib/oversip/sip/message_processor.rb +213 -0
  88. data/lib/oversip/sip/name_addr.rb +51 -0
  89. data/lib/oversip/sip/proxy.rb +324 -0
  90. data/lib/oversip/sip/request.rb +179 -0
  91. data/lib/oversip/sip/response.rb +37 -0
  92. data/lib/oversip/sip/rfc3263.rb +643 -0
  93. data/lib/oversip/sip/server_transaction.rb +295 -0
  94. data/lib/oversip/sip/sip.rb +76 -0
  95. data/lib/oversip/sip/tags.rb +39 -0
  96. data/lib/oversip/sip/timers.rb +55 -0
  97. data/lib/oversip/sip/transport_manager.rb +130 -0
  98. data/lib/oversip/sip/uac.rb +89 -0
  99. data/lib/oversip/sip/uac_request.rb +84 -0
  100. data/lib/oversip/sip/uri.rb +208 -0
  101. data/lib/oversip/syslog.rb +68 -0
  102. data/lib/oversip/system_callbacks.rb +45 -0
  103. data/lib/oversip/tls.rb +172 -0
  104. data/lib/oversip/utils.rb +30 -0
  105. data/lib/oversip/version.rb +21 -0
  106. data/lib/oversip/websocket/constants.rb +55 -0
  107. data/lib/oversip/websocket/http_request.rb +59 -0
  108. data/lib/oversip/websocket/launcher.rb +183 -0
  109. data/lib/oversip/websocket/listeners/connection.rb +51 -0
  110. data/lib/oversip/websocket/listeners/ipv4_ws_server.rb +22 -0
  111. data/lib/oversip/websocket/listeners/ipv4_wss_server.rb +22 -0
  112. data/lib/oversip/websocket/listeners/ipv4_wss_tunnel_server.rb +22 -0
  113. data/lib/oversip/websocket/listeners/ipv6_ws_server.rb +22 -0
  114. data/lib/oversip/websocket/listeners/ipv6_wss_server.rb +22 -0
  115. data/lib/oversip/websocket/listeners/ipv6_wss_tunnel_server.rb +22 -0
  116. data/lib/oversip/websocket/listeners/ws_server.rb +331 -0
  117. data/lib/oversip/websocket/listeners/wss_server.rb +88 -0
  118. data/lib/oversip/websocket/listeners/wss_tunnel_server.rb +133 -0
  119. data/lib/oversip/websocket/listeners.rb +13 -0
  120. data/lib/oversip/websocket/websocket.rb +13 -0
  121. data/lib/oversip/websocket/ws_framing.rb +545 -0
  122. data/lib/oversip/websocket/ws_sip_app.rb +120 -0
  123. data/lib/oversip.rb +127 -0
  124. data/test/oversip_test_helper.rb +19 -0
  125. data/test/test_http_parser.rb +73 -0
  126. data/test/test_name_addr.rb +27 -0
  127. data/test/test_name_addr_parser.rb +24 -0
  128. data/test/test_sip_message_parser.rb +168 -0
  129. data/test/test_sip_uri_parser.rb +56 -0
  130. data/test/test_uri.rb +68 -0
  131. data/thirdparty/stud/stud.tar.gz +0 -0
  132. metadata +334 -0
@@ -0,0 +1,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