oversip 0.9.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 (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,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,74 @@
1
+ module OverSIP::SIP
2
+
3
+ # This hash contains the proxies defined by the user. It will be filled after loading the
4
+ # configuration (proxies.conf file).
5
+ PROXIES = {}
6
+
7
+ def self.module_init
8
+ conf = ::OverSIP.configuration
9
+
10
+ @local_ipv4 = conf[:sip][:listen_ipv4]
11
+ @local_ipv6 = conf[:sip][:listen_ipv6]
12
+
13
+ @tcp_keepalive_interval = conf[:sip][:tcp_keepalive_interval]
14
+
15
+ @local_aliases = {}
16
+
17
+ sip_local_domains = conf[:sip][:local_domains] || []
18
+ sip_local_ips = []
19
+ sip_local_ips << conf[:sip][:listen_ipv4] if conf[:sip][:enable_ipv4]
20
+ sip_local_ips << "[#{OverSIP::Utils.normalize_ipv6(conf[:sip][:listen_ipv6])}]" if conf[:sip][:enable_ipv6]
21
+ sip_local_ports = [ conf[:sip][:listen_port], conf[:sip][:listen_port_tls] ].compact
22
+ sip_local_domains.each do |domain|
23
+ @local_aliases[domain] = true
24
+ sip_local_ports.each do |port|
25
+ @local_aliases["#{domain}:#{port}"] = true
26
+ end
27
+ end
28
+ sip_local_ips.each do |ip|
29
+ sip_local_ports.each do |port|
30
+ @local_aliases["#{ip}:#{port}"] = true
31
+ end
32
+ end
33
+ sip_local_ips.each do |ip|
34
+ @local_aliases[ip] = true if conf[:sip][:listen_port] == 5060 or conf[:sip][:listen_port_tls] == 5061
35
+ end
36
+
37
+ ws_local_domains = conf[:sip][:local_domains] || []
38
+ ws_local_ips = []
39
+ ws_local_ips << conf[:websocket][:listen_ipv4] if conf[:websocket][:enable_ipv4]
40
+ ws_local_ips << "[#{OverSIP::Utils.normalize_ipv6(conf[:websocket][:listen_ipv6])}]" if conf[:websocket][:enable_ipv6]
41
+ ws_local_ports = [ conf[:websocket][:listen_port], conf[:websocket][:listen_port_tls] ].compact
42
+ ws_local_domains.each do |domain|
43
+ @local_aliases[domain] = true
44
+ ws_local_ports.each do |port|
45
+ @local_aliases["#{domain}:#{port}"] = true
46
+ end
47
+ end
48
+ ws_local_ips.each do |ip|
49
+ ws_local_ports.each do |port|
50
+ @local_aliases["#{ip}:#{port}"] = true
51
+ end
52
+ end
53
+ ws_local_ips.each do |ip|
54
+ @local_aliases[ip] = true if conf[:websocket][:listen_port] == 80 or conf[:websocket][:listen_port_tls] == 443
55
+ end
56
+ end
57
+
58
+ def self.local_aliases
59
+ @local_aliases
60
+ end
61
+
62
+ def self.tcp_keepalive_interval
63
+ @tcp_keepalive_interval
64
+ end
65
+
66
+ def self.local_ipv4
67
+ @local_ipv4
68
+ end
69
+
70
+ def self.local_ipv6
71
+ @local_ipv6
72
+ end
73
+
74
+ 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.uri}#{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,129 @@
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 return 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, tls_validation=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, 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, 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, IPv4TlsClient, ip, port)
48
+
49
+ if conn.is_a? ::OverSIP::SIP::IPv4TlsClient and not conn.connected
50
+ conn.tls_validation = tls_validation
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, IPv6TlsClient, ip, port)
55
+
56
+ if conn.is_a? ::OverSIP::SIP::IPv6TlsClient and not conn.connected
57
+ conn.tls_validation = tls_validation
58
+ conn.pending_client_transactions << client_transaction
59
+ end
60
+ end
61
+ end
62
+
63
+ # NOTE: Should never happen.
64
+ unless conn
65
+ log_system_error "no connection (nil) retrieved from TransportManager.get_connection(), FIXME, it should never occur!!!"
66
+ raise "no connection (nil) retrieved from TransportManager.get_connection(), FIXME, it should never occur!!!"
67
+ end
68
+ conn
69
+ end
70
+
71
+
72
+ def self.add_connection server, server_class, ip_type, ip, port
73
+ connection_id = case ip_type
74
+ when :ipv4
75
+ "#{ip}_#{port}"
76
+ when :ipv6
77
+ "#{::OverSIP::Utils.normalize_ipv6 ip}_#{port}"
78
+ end
79
+
80
+ server_class.connections[connection_id] = server
81
+
82
+ # Return the connection_id.
83
+ connection_id
84
+ end
85
+
86
+
87
+ # Return a SIP server instance. It could return nil (if the requested connection no longer
88
+ # exists) or false (if it's a tampered flow token).
89
+ def self.get_outbound_connection flow_token
90
+ # If the token flow has been generated for UDP it is "_" followed by the Base64
91
+ # encoded representation of "IP_port", so getbyte(0) would return 95.
92
+ if flow_token.getbyte(0) == 95
93
+ # NOTE: Doing Base64.decode64 automatically removes the leading "_".
94
+ # NOTE: Previously when the Outbound flow token was generated, "=" was replaced with "-" so it becomes
95
+ # valid for a SIP URI param (in case of using Contact mangling if the registrar does not support Path).
96
+ ip_type, ip, port = ::OverSIP::Utils.parse_outbound_udp_flow_token(::Base64.decode64 flow_token.gsub(/-/,"="))
97
+
98
+ case ip_type
99
+ when :ipv4
100
+ return [ ::OverSIP::SIP::IPv4UdpServer.connections, ip, port ]
101
+ when :ipv6
102
+ return [ ::OverSIP::SIP::IPv6UdpServer.connections, ip, port ]
103
+ else
104
+ log_system_notice "udp flow token does not contain valid IP and port encoded value"
105
+ return false
106
+ end
107
+
108
+ # It not, the flow token has been generated for a TCP/TLS/WS connection so let's lookup
109
+ # it into the Outbound connection collection and return nil for IP and port.
110
+ else
111
+ @outbound_connections[flow_token]
112
+ end
113
+ end
114
+
115
+
116
+ def self.add_outbound_connection connection
117
+ outbound_flow_token = ::SecureRandom.hex(5)
118
+ @outbound_connections[outbound_flow_token] = connection
119
+ outbound_flow_token
120
+ end
121
+
122
+
123
+ def self.delete_outbound_connection outbound_flow_token
124
+ @outbound_connections.delete outbound_flow_token
125
+ end
126
+
127
+ end # module TransportManager
128
+
129
+ end