oversip 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/AUTHORS.txt +11 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +16 -0
  4. data/Rakefile +55 -0
  5. data/bin/oversip +182 -0
  6. data/ext/common/c_util.h +74 -0
  7. data/ext/common/ruby_c_util.h +88 -0
  8. data/ext/sip_parser/common_headers.h +209 -0
  9. data/ext/sip_parser/ext_help.h +18 -0
  10. data/ext/sip_parser/extconf.rb +3 -0
  11. data/ext/sip_parser/sip_parser.c +29649 -0
  12. data/ext/sip_parser/sip_parser.h +227 -0
  13. data/ext/sip_parser/sip_parser_ruby.c +1292 -0
  14. data/ext/stud/extconf.rb +27 -0
  15. data/ext/stud/stud.tar.gz +0 -0
  16. data/ext/stun/ext_help.h +16 -0
  17. data/ext/stun/extconf.rb +3 -0
  18. data/ext/stun/stun_ruby.c +391 -0
  19. data/ext/utils/ext_help.h +14 -0
  20. data/ext/utils/extconf.rb +3 -0
  21. data/ext/utils/haproxy_protocol.c +6163 -0
  22. data/ext/utils/haproxy_protocol.h +27 -0
  23. data/ext/utils/ip_utils.c +5952 -0
  24. data/ext/utils/ip_utils.h +61 -0
  25. data/ext/utils/outbound_utils.c +3227 -0
  26. data/ext/utils/outbound_utils.h +27 -0
  27. data/ext/utils/utils_ruby.c +384 -0
  28. data/ext/utils/utils_ruby.h +75 -0
  29. data/ext/websocket_framing_utils/ext_help.h +18 -0
  30. data/ext/websocket_framing_utils/extconf.rb +3 -0
  31. data/ext/websocket_framing_utils/ws_framing_utils.h +46 -0
  32. data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
  33. data/ext/websocket_http_parser/ext_help.h +18 -0
  34. data/ext/websocket_http_parser/extconf.rb +3 -0
  35. data/ext/websocket_http_parser/ws_http_parser.c +2598 -0
  36. data/ext/websocket_http_parser/ws_http_parser.h +86 -0
  37. data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
  38. data/lib/oversip/config.rb +541 -0
  39. data/lib/oversip/config_validators.rb +126 -0
  40. data/lib/oversip/errors.rb +7 -0
  41. data/lib/oversip/fiber_pool.rb +56 -0
  42. data/lib/oversip/launcher.rb +507 -0
  43. data/lib/oversip/logger.rb +170 -0
  44. data/lib/oversip/master_process.rb +67 -0
  45. data/lib/oversip/posix_mq.rb +121 -0
  46. data/lib/oversip/proxies_config.rb +169 -0
  47. data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
  48. data/lib/oversip/sip/client_transaction.rb +587 -0
  49. data/lib/oversip/sip/constants.rb +87 -0
  50. data/lib/oversip/sip/grammar/name_addr.rb +27 -0
  51. data/lib/oversip/sip/grammar/uri.rb +116 -0
  52. data/lib/oversip/sip/launcher.rb +180 -0
  53. data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
  54. data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +21 -0
  55. data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
  56. data/lib/oversip/sip/listeners/ipv4_tls_server.rb +21 -0
  57. data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +21 -0
  58. data/lib/oversip/sip/listeners/ipv4_udp_server.rb +20 -0
  59. data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
  60. data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +21 -0
  61. data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
  62. data/lib/oversip/sip/listeners/ipv6_tls_server.rb +21 -0
  63. data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +21 -0
  64. data/lib/oversip/sip/listeners/ipv6_udp_server.rb +20 -0
  65. data/lib/oversip/sip/listeners/reactor.rb +39 -0
  66. data/lib/oversip/sip/listeners/tcp_client.rb +73 -0
  67. data/lib/oversip/sip/listeners/tcp_reactor.rb +185 -0
  68. data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
  69. data/lib/oversip/sip/listeners/tls_client.rb +117 -0
  70. data/lib/oversip/sip/listeners/tls_server.rb +70 -0
  71. data/lib/oversip/sip/listeners/tls_tunnel_reactor.rb +113 -0
  72. data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
  73. data/lib/oversip/sip/listeners/udp_reactor.rb +213 -0
  74. data/lib/oversip/sip/listeners.rb +28 -0
  75. data/lib/oversip/sip/logic.rb +14 -0
  76. data/lib/oversip/sip/message.rb +168 -0
  77. data/lib/oversip/sip/message_processor.rb +202 -0
  78. data/lib/oversip/sip/modules/core.rb +200 -0
  79. data/lib/oversip/sip/modules/registrar_without_path.rb +75 -0
  80. data/lib/oversip/sip/modules/user_assertion.rb +123 -0
  81. data/lib/oversip/sip/proxy.rb +460 -0
  82. data/lib/oversip/sip/request.rb +128 -0
  83. data/lib/oversip/sip/response.rb +30 -0
  84. data/lib/oversip/sip/rfc3263.rb +646 -0
  85. data/lib/oversip/sip/server_transaction.rb +295 -0
  86. data/lib/oversip/sip/sip.rb +74 -0
  87. data/lib/oversip/sip/tags.rb +39 -0
  88. data/lib/oversip/sip/timers.rb +55 -0
  89. data/lib/oversip/sip/transport_manager.rb +129 -0
  90. data/lib/oversip/syslogger_process.rb +119 -0
  91. data/lib/oversip/tls.rb +179 -0
  92. data/lib/oversip/utils.rb +25 -0
  93. data/lib/oversip/version.rb +23 -0
  94. data/lib/oversip/websocket/constants.rb +56 -0
  95. data/lib/oversip/websocket/default_policy.rb +19 -0
  96. data/lib/oversip/websocket/http_request.rb +63 -0
  97. data/lib/oversip/websocket/launcher.rb +207 -0
  98. data/lib/oversip/websocket/listeners/ipv4_tcp_server.rb +15 -0
  99. data/lib/oversip/websocket/listeners/ipv4_tls_server.rb +15 -0
  100. data/lib/oversip/websocket/listeners/ipv4_tls_tunnel_server.rb +15 -0
  101. data/lib/oversip/websocket/listeners/ipv6_tcp_server.rb +15 -0
  102. data/lib/oversip/websocket/listeners/ipv6_tls_server.rb +15 -0
  103. data/lib/oversip/websocket/listeners/ipv6_tls_tunnel_server.rb +15 -0
  104. data/lib/oversip/websocket/listeners/tcp_server.rb +265 -0
  105. data/lib/oversip/websocket/listeners/tls_server.rb +69 -0
  106. data/lib/oversip/websocket/listeners/tls_tunnel_server.rb +100 -0
  107. data/lib/oversip/websocket/listeners.rb +12 -0
  108. data/lib/oversip/websocket/ws_app.rb +75 -0
  109. data/lib/oversip/websocket/ws_apps/ipv4_ws_sip_app.rb +21 -0
  110. data/lib/oversip/websocket/ws_apps/ipv4_wss_sip_app.rb +21 -0
  111. data/lib/oversip/websocket/ws_apps/ipv6_ws_sip_app.rb +21 -0
  112. data/lib/oversip/websocket/ws_apps/ipv6_wss_sip_app.rb +22 -0
  113. data/lib/oversip/websocket/ws_apps/ws_autobahn_app.rb +23 -0
  114. data/lib/oversip/websocket/ws_apps/ws_sip_app.rb +156 -0
  115. data/lib/oversip/websocket/ws_apps.rb +9 -0
  116. data/lib/oversip/websocket/ws_framing.rb +597 -0
  117. data/lib/oversip.rb +59 -0
  118. data/test/oversip_test_helper.rb +20 -0
  119. data/test/test_http_parser.rb +73 -0
  120. data/test/test_sip_parser.rb +139 -0
  121. metadata +256 -0
@@ -0,0 +1,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