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.
- data/AUTHORS.txt +11 -0
- data/LICENSE.txt +22 -0
- data/README.md +16 -0
- data/Rakefile +55 -0
- data/bin/oversip +182 -0
- data/ext/common/c_util.h +74 -0
- data/ext/common/ruby_c_util.h +88 -0
- data/ext/sip_parser/common_headers.h +209 -0
- data/ext/sip_parser/ext_help.h +18 -0
- data/ext/sip_parser/extconf.rb +3 -0
- data/ext/sip_parser/sip_parser.c +29649 -0
- data/ext/sip_parser/sip_parser.h +227 -0
- data/ext/sip_parser/sip_parser_ruby.c +1292 -0
- data/ext/stud/extconf.rb +27 -0
- data/ext/stud/stud.tar.gz +0 -0
- data/ext/stun/ext_help.h +16 -0
- data/ext/stun/extconf.rb +3 -0
- data/ext/stun/stun_ruby.c +391 -0
- data/ext/utils/ext_help.h +14 -0
- data/ext/utils/extconf.rb +3 -0
- data/ext/utils/haproxy_protocol.c +6163 -0
- data/ext/utils/haproxy_protocol.h +27 -0
- data/ext/utils/ip_utils.c +5952 -0
- data/ext/utils/ip_utils.h +61 -0
- data/ext/utils/outbound_utils.c +3227 -0
- data/ext/utils/outbound_utils.h +27 -0
- data/ext/utils/utils_ruby.c +384 -0
- data/ext/utils/utils_ruby.h +75 -0
- data/ext/websocket_framing_utils/ext_help.h +18 -0
- data/ext/websocket_framing_utils/extconf.rb +3 -0
- data/ext/websocket_framing_utils/ws_framing_utils.h +46 -0
- data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +135 -0
- data/ext/websocket_http_parser/ext_help.h +18 -0
- data/ext/websocket_http_parser/extconf.rb +3 -0
- data/ext/websocket_http_parser/ws_http_parser.c +2598 -0
- data/ext/websocket_http_parser/ws_http_parser.h +86 -0
- data/ext/websocket_http_parser/ws_http_parser_ruby.c +630 -0
- data/lib/oversip/config.rb +541 -0
- data/lib/oversip/config_validators.rb +126 -0
- data/lib/oversip/errors.rb +7 -0
- data/lib/oversip/fiber_pool.rb +56 -0
- data/lib/oversip/launcher.rb +507 -0
- data/lib/oversip/logger.rb +170 -0
- data/lib/oversip/master_process.rb +67 -0
- data/lib/oversip/posix_mq.rb +121 -0
- data/lib/oversip/proxies_config.rb +169 -0
- data/lib/oversip/ruby_ext/eventmachine.rb +38 -0
- data/lib/oversip/sip/client_transaction.rb +587 -0
- data/lib/oversip/sip/constants.rb +87 -0
- data/lib/oversip/sip/grammar/name_addr.rb +27 -0
- data/lib/oversip/sip/grammar/uri.rb +116 -0
- data/lib/oversip/sip/launcher.rb +180 -0
- data/lib/oversip/sip/listeners/ipv4_tcp_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tls_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tls_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv4_udp_server.rb +20 -0
- data/lib/oversip/sip/listeners/ipv6_tcp_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tls_client.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tls_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +21 -0
- data/lib/oversip/sip/listeners/ipv6_udp_server.rb +20 -0
- data/lib/oversip/sip/listeners/reactor.rb +39 -0
- data/lib/oversip/sip/listeners/tcp_client.rb +73 -0
- data/lib/oversip/sip/listeners/tcp_reactor.rb +185 -0
- data/lib/oversip/sip/listeners/tcp_server.rb +71 -0
- data/lib/oversip/sip/listeners/tls_client.rb +117 -0
- data/lib/oversip/sip/listeners/tls_server.rb +70 -0
- data/lib/oversip/sip/listeners/tls_tunnel_reactor.rb +113 -0
- data/lib/oversip/sip/listeners/tls_tunnel_server.rb +61 -0
- data/lib/oversip/sip/listeners/udp_reactor.rb +213 -0
- data/lib/oversip/sip/listeners.rb +28 -0
- data/lib/oversip/sip/logic.rb +14 -0
- data/lib/oversip/sip/message.rb +168 -0
- data/lib/oversip/sip/message_processor.rb +202 -0
- data/lib/oversip/sip/modules/core.rb +200 -0
- data/lib/oversip/sip/modules/registrar_without_path.rb +75 -0
- data/lib/oversip/sip/modules/user_assertion.rb +123 -0
- data/lib/oversip/sip/proxy.rb +460 -0
- data/lib/oversip/sip/request.rb +128 -0
- data/lib/oversip/sip/response.rb +30 -0
- data/lib/oversip/sip/rfc3263.rb +646 -0
- data/lib/oversip/sip/server_transaction.rb +295 -0
- data/lib/oversip/sip/sip.rb +74 -0
- data/lib/oversip/sip/tags.rb +39 -0
- data/lib/oversip/sip/timers.rb +55 -0
- data/lib/oversip/sip/transport_manager.rb +129 -0
- data/lib/oversip/syslogger_process.rb +119 -0
- data/lib/oversip/tls.rb +179 -0
- data/lib/oversip/utils.rb +25 -0
- data/lib/oversip/version.rb +23 -0
- data/lib/oversip/websocket/constants.rb +56 -0
- data/lib/oversip/websocket/default_policy.rb +19 -0
- data/lib/oversip/websocket/http_request.rb +63 -0
- data/lib/oversip/websocket/launcher.rb +207 -0
- data/lib/oversip/websocket/listeners/ipv4_tcp_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv4_tls_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv4_tls_tunnel_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv6_tcp_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv6_tls_server.rb +15 -0
- data/lib/oversip/websocket/listeners/ipv6_tls_tunnel_server.rb +15 -0
- data/lib/oversip/websocket/listeners/tcp_server.rb +265 -0
- data/lib/oversip/websocket/listeners/tls_server.rb +69 -0
- data/lib/oversip/websocket/listeners/tls_tunnel_server.rb +100 -0
- data/lib/oversip/websocket/listeners.rb +12 -0
- data/lib/oversip/websocket/ws_app.rb +75 -0
- data/lib/oversip/websocket/ws_apps/ipv4_ws_sip_app.rb +21 -0
- data/lib/oversip/websocket/ws_apps/ipv4_wss_sip_app.rb +21 -0
- data/lib/oversip/websocket/ws_apps/ipv6_ws_sip_app.rb +21 -0
- data/lib/oversip/websocket/ws_apps/ipv6_wss_sip_app.rb +22 -0
- data/lib/oversip/websocket/ws_apps/ws_autobahn_app.rb +23 -0
- data/lib/oversip/websocket/ws_apps/ws_sip_app.rb +156 -0
- data/lib/oversip/websocket/ws_apps.rb +9 -0
- data/lib/oversip/websocket/ws_framing.rb +597 -0
- data/lib/oversip.rb +59 -0
- data/test/oversip_test_helper.rb +20 -0
- data/test/test_http_parser.rb +73 -0
- data/test/test_sip_parser.rb +139 -0
- 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
|