oversip 1.1.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/etc/server.rb +34 -23
- data/ext/stun/stun_ruby.c +7 -4
- data/ext/utils/utils_ruby.c +9 -0
- data/lib/oversip/config.rb +22 -15
- data/lib/oversip/default_server.rb +13 -9
- data/lib/oversip/launcher.rb +62 -7
- data/lib/oversip/logger.rb +0 -9
- data/lib/oversip/master_process.rb +4 -7
- data/lib/oversip/modules/outbound_mangling.rb +60 -0
- data/lib/oversip/modules/user_assertion.rb +73 -0
- data/lib/oversip/posix_mq.rb +8 -8
- data/lib/oversip/proxies_config.rb +1 -1
- data/lib/oversip/sip/core.rb +189 -0
- data/lib/oversip/sip/grammar/name_addr.rb +4 -0
- data/lib/oversip/sip/grammar/uri.rb +25 -1
- data/lib/oversip/sip/launcher.rb +1 -4
- data/lib/oversip/sip/listeners/udp_connection.rb +2 -2
- data/lib/oversip/sip/message_processor.rb +1 -1
- data/lib/oversip/sip/proxy.rb +22 -6
- data/lib/oversip/sip/request.rb +16 -1
- data/lib/oversip/sip/response.rb +7 -0
- data/lib/oversip/sip/rfc3263.rb +2 -4
- data/lib/oversip/syslogger_process.rb +0 -2
- data/lib/oversip/system_callbacks.rb +45 -0
- data/lib/oversip/tls.rb +1 -4
- data/lib/oversip/utils.rb +10 -5
- data/lib/oversip/version.rb +2 -2
- data/lib/oversip/websocket/launcher.rb +1 -3
- data/lib/oversip.rb +9 -0
- data/test/test_uri.rb +11 -4
- metadata +23 -22
- data/lib/oversip/sip/modules/core.rb +0 -194
- data/lib/oversip/sip/modules/registrar_without_path.rb +0 -72
- data/lib/oversip/sip/modules/user_assertion.rb +0 -77
@@ -0,0 +1,73 @@
|
|
1
|
+
module OverSIP::Modules
|
2
|
+
|
3
|
+
module UserAssertion
|
4
|
+
|
5
|
+
extend ::OverSIP::Logger
|
6
|
+
|
7
|
+
@log_id = "UserAssertion module"
|
8
|
+
|
9
|
+
def self.assert_connection message
|
10
|
+
case message
|
11
|
+
when ::OverSIP::SIP::Request
|
12
|
+
request = message
|
13
|
+
when ::OverSIP::SIP::Response
|
14
|
+
request = message.request
|
15
|
+
else
|
16
|
+
raise ::OverSIP::RuntimeError, "message must be a OverSIP::SIP::Request or OverSIP::SIP::Response"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Don't do this stuf for UDP or for outbound connections.
|
20
|
+
return false unless request.connection.class.reliable_transport_listener?
|
21
|
+
# Return if already set.
|
22
|
+
return request.cvars[:asserted_user] if request.cvars[:asserted_user]
|
23
|
+
# Don't do this stuf in case of P-Preferred-Identity header is present.
|
24
|
+
return false if request.headers["P-Preferred-Identity"]
|
25
|
+
|
26
|
+
log_system_debug "user #{request.from.uri} asserted to connection" if $oversip_debug
|
27
|
+
# Store the request From URI as "asserted_user" for this connection.
|
28
|
+
request.cvars[:asserted_user] = request.from.uri
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.revoke_assertion message
|
32
|
+
case message
|
33
|
+
when ::OverSIP::SIP::Request
|
34
|
+
request = message
|
35
|
+
when ::OverSIP::SIP::Response
|
36
|
+
request = message.request
|
37
|
+
else
|
38
|
+
raise ::OverSIP::RuntimeError, "message must be a OverSIP::SIP::Request or OverSIP::SIP::Response"
|
39
|
+
end
|
40
|
+
|
41
|
+
request.cvars.delete :asserted_user
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.add_pai request
|
46
|
+
# Add P-Asserted-Identity if the user has previously been asserted but JUST
|
47
|
+
# in case it matches request From URI !
|
48
|
+
# NOTE: If the connection is not asserted (it's null) then it will not match this
|
49
|
+
# comparisson, so OK.
|
50
|
+
if request.cvars[:asserted_user] == request.from.uri
|
51
|
+
# Don't add P-Asserted-Identity if the request contains P-Preferred-Identity header.
|
52
|
+
unless request.headers["P-Preferred-Identity"]
|
53
|
+
log_system_debug "user asserted, adding P-Asserted-Identity for #{request.log_id}" if $oversip_debug
|
54
|
+
request.set_header "P-Asserted-Identity", "<" << request.cvars[:asserted_user] << ">"
|
55
|
+
return true
|
56
|
+
else
|
57
|
+
# Remove posible P-Asserted-Identity header!
|
58
|
+
log_system_debug "user asserted but P-Preferred-Identity header present, P-Asserted-Identity not added for #{request.log_id}" if $oversip_debug
|
59
|
+
request.headers.delete "P-Asserted-Identity"
|
60
|
+
return nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# Otherwise ensure the request has no spoofed P-Asserted-Identity headers!
|
64
|
+
else
|
65
|
+
request.headers.delete "P-Asserted-Identity"
|
66
|
+
return false
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end # module UserAssertion
|
72
|
+
|
73
|
+
end
|
data/lib/oversip/posix_mq.rb
CHANGED
@@ -27,10 +27,10 @@ module OverSIP
|
|
27
27
|
::POSIX_MQ.unlink mq_name
|
28
28
|
rescue ::Errno::ENOENT
|
29
29
|
rescue ::Errno::EACCES => e
|
30
|
-
fatal "queue already exists and cannot remove it due file permissions"
|
30
|
+
::OverSIP::Launcher.fatal "queue already exists and cannot remove it due file permissions"
|
31
31
|
# Kernel has no support for posix message queues.
|
32
32
|
rescue ::Errno::ENOSYS => e
|
33
|
-
fatal "the kernel has no support for posix messages queues, enable it (#{e.class}: #{e.message})"
|
33
|
+
::OverSIP::Launcher.fatal "the kernel has no support for posix messages queues, enable it (#{e.class}: #{e.message})"
|
34
34
|
end
|
35
35
|
|
36
36
|
# Set the UMASK in a way that the group has permission to delete the queue.
|
@@ -61,7 +61,7 @@ module OverSIP
|
|
61
61
|
begin
|
62
62
|
::Process.setrlimit(12, mq_size)
|
63
63
|
rescue ::Errno::EPERM
|
64
|
-
fatal "current user has no permissions to increase rlimits to #{mq_size} bytes (ulimit -q)"
|
64
|
+
::OverSIP::Launcher.fatal "current user has no permissions to increase rlimits to #{mq_size} bytes (ulimit -q)"
|
65
65
|
end
|
66
66
|
else
|
67
67
|
log_system_info "rlimits for Posix Message Queues is #{current_rlimit} bytes (>= #{mq_size}), no need to increase it"
|
@@ -79,7 +79,7 @@ module OverSIP
|
|
79
79
|
|
80
80
|
# Kernel has no support for posix message queues.
|
81
81
|
rescue ::Errno::ENOSYS => e
|
82
|
-
fatal "the kernel has no support for posix messages queues, enable it (#{e.class}: #{e.message})"
|
82
|
+
::OverSIP::Launcher.fatal "the kernel has no support for posix messages queues, enable it (#{e.class}: #{e.message})"
|
83
83
|
|
84
84
|
# http://linux.die.net/man/3/mq_open
|
85
85
|
#
|
@@ -93,13 +93,13 @@ module OverSIP
|
|
93
93
|
log_system_warn "cannot set queue attributes due to user permissions, using system default values"
|
94
94
|
mq = ::POSIX_MQ.new mq_name, mq_mode | ::IO::CREAT | ::IO::NONBLOCK, 00660
|
95
95
|
rescue ::Errno::ENOMEM => e
|
96
|
-
fatal "insufficient memory (#{e.class}: #{e.message})"
|
96
|
+
::OverSIP::Launcher.fatal "insufficient memory (#{e.class}: #{e.message})"
|
97
97
|
rescue ::Errno::EMFILE => e
|
98
|
-
fatal "the process already has the maximum number of files and message queues open (#{e.class}: #{e.message})"
|
98
|
+
::OverSIP::Launcher.fatal "the process already has the maximum number of files and message queues open (#{e.class}: #{e.message})"
|
99
99
|
rescue Errno::ENFILE => e
|
100
|
-
fatal "the system limit on the total number of open files and message queues has been reached (#{e.class}: #{e.message})"
|
100
|
+
::OverSIP::Launcher.fatal "the system limit on the total number of open files and message queues has been reached (#{e.class}: #{e.message})"
|
101
101
|
rescue ::Errno::ENOSPC => e
|
102
|
-
fatal "insufficient space for the creation of a new message queue, probably occurred because the queues_max limit was encountered (#{e.class}: #{e.message})"
|
102
|
+
::OverSIP::Launcher.fatal "insufficient space for the creation of a new message queue, probably occurred because the queues_max limit was encountered (#{e.class}: #{e.message})"
|
103
103
|
|
104
104
|
end
|
105
105
|
|
@@ -0,0 +1,189 @@
|
|
1
|
+
module OverSIP::SIP
|
2
|
+
|
3
|
+
# This module is included by OverSIP::SIP::Request class.
|
4
|
+
module Core
|
5
|
+
|
6
|
+
# Create a server transaction for the incoming request.
|
7
|
+
def create_transaction
|
8
|
+
return false if @server_transaction
|
9
|
+
|
10
|
+
case @sip_method
|
11
|
+
when :INVITE
|
12
|
+
::OverSIP::SIP::InviteServerTransaction.new self
|
13
|
+
return true
|
14
|
+
when :ACK
|
15
|
+
return nil
|
16
|
+
when :CANCEL
|
17
|
+
return nil
|
18
|
+
else
|
19
|
+
::OverSIP::SIP::NonInviteServerTransaction.new self
|
20
|
+
return true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def check_max_forwards max_forwards
|
26
|
+
if @max_forwards
|
27
|
+
unless @max_forwards.zero?
|
28
|
+
@new_max_forwards = ( @max_forwards > max_forwards ? max_forwards : @max_forwards - 1 )
|
29
|
+
return true
|
30
|
+
else
|
31
|
+
log_system_notice "Max-Forwards is 0 => 483"
|
32
|
+
reply 483
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
else
|
36
|
+
@new_max_forwards = max_forwards
|
37
|
+
return true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def loose_route
|
43
|
+
num_removes = 0
|
44
|
+
has_preloaded_route_with_ob_param = false
|
45
|
+
|
46
|
+
# Remove all the Route's pointing to the proxy until a Route not pointing to us is found.
|
47
|
+
if @routes
|
48
|
+
@routes.each do |route|
|
49
|
+
if ::OverSIP::SIP::Tags.check_value_for_route_ovid(route.ovid_param)
|
50
|
+
num_removes += 1
|
51
|
+
else
|
52
|
+
if local_uri? route
|
53
|
+
has_preloaded_route_with_ob_param = true if route.ob_param?
|
54
|
+
num_removes += 1
|
55
|
+
else
|
56
|
+
break
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
### Outbound stuf. RFC 5626 section 5.3.
|
63
|
+
|
64
|
+
# Outgoing initial request asking for Outbound. Just valid when:
|
65
|
+
# - It's an initial request.
|
66
|
+
# - Single Via (so there is no a proxy in front of us).
|
67
|
+
# - It's an INVITE, REGISTER, SUBSCRIBE or REFER request.
|
68
|
+
# - Has a preloaded top Route with ;ob param pointing to us, or has Contact with ;ob, or
|
69
|
+
# it's a REGISTER with ;+sip.instance.
|
70
|
+
#
|
71
|
+
if (
|
72
|
+
initial? and (
|
73
|
+
@force_outgoing_outbound or (
|
74
|
+
@num_vias == 1 and
|
75
|
+
outbound_aware? and (
|
76
|
+
( has_preloaded_route_with_ob_param or (@contact and @contact.ob_param?) ) or
|
77
|
+
( @sip_method == :REGISTER and contact_reg_id?)
|
78
|
+
)
|
79
|
+
)
|
80
|
+
)
|
81
|
+
)
|
82
|
+
@outgoing_outbound_requested = true
|
83
|
+
log_system_debug "applying outgoing Outbound support" if $oversip_debug
|
84
|
+
end
|
85
|
+
|
86
|
+
# Incoming initial request or in-dialog incoming/outgoing request. Must only perform
|
87
|
+
# Outbound for the incoming case and just when:
|
88
|
+
# - There are 2 Route headers.
|
89
|
+
# - All the Route headers point to us.
|
90
|
+
# - The latest Route has a flow token and a valid ;ovid param (so has been generated
|
91
|
+
# previously by us).
|
92
|
+
# NOTE: But don't check its value so it still would work in case of server reboot.
|
93
|
+
# - It's an incoming Outbound request (so flow token in the Route does not match the
|
94
|
+
# flow token of the incoming connection).
|
95
|
+
if (
|
96
|
+
num_removes == 2 and
|
97
|
+
@routes.size == 2 and
|
98
|
+
(outbound_route = @routes.last) and
|
99
|
+
outbound_route.ovid_param and
|
100
|
+
(@route_outbound_flow_token = outbound_route.user) != @connection_outbound_flow_token
|
101
|
+
)
|
102
|
+
@incoming_outbound_requested = true
|
103
|
+
log_system_debug "destination is an incoming Outbound connection" if $oversip_debug
|
104
|
+
end
|
105
|
+
|
106
|
+
# If there are not Route headers return false.
|
107
|
+
return false unless @routes
|
108
|
+
|
109
|
+
# Remove the Route values pointintg to us.
|
110
|
+
unless num_removes == 0
|
111
|
+
@headers["Route"].shift num_removes
|
112
|
+
@routes.shift num_removes
|
113
|
+
end
|
114
|
+
@routes.empty? and @routes = nil
|
115
|
+
|
116
|
+
# Return true if it is an in-dialog request and the top Route pointed to us.
|
117
|
+
# False otherwise as we shouldn't receive an in-dialog request with a top Route non
|
118
|
+
# pointing to us.
|
119
|
+
if in_dialog?
|
120
|
+
return ( num_removes > 0 ? true : false )
|
121
|
+
# Return true if it was an initial request and more Route headers remain after inspection.
|
122
|
+
elsif @routes
|
123
|
+
return true
|
124
|
+
# Return false if it was an initial request and all its Route headers pointed to the proxy.
|
125
|
+
else
|
126
|
+
return false
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
# Checks whether the RURI points to a local domain or address.
|
132
|
+
# Typically, prior to using this method the user has verified the return value of loose_route()
|
133
|
+
# in case it's an initial request (if it's _true_ then the request has pre-loaded Route).
|
134
|
+
def destination_myself?
|
135
|
+
return true if @destination_myself
|
136
|
+
return false if @destination_myself == false
|
137
|
+
|
138
|
+
if local_uri? @ruri
|
139
|
+
log_system_debug "RURI destination is myself" if $oversip_debug
|
140
|
+
return @destination_myself = true
|
141
|
+
else
|
142
|
+
log_system_debug "RURI destination is not myself" if $oversip_debug
|
143
|
+
return @destination_myself = false
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
def fix_nat
|
149
|
+
# Force rport usage for UDP clients.
|
150
|
+
@via_rport = @source_port
|
151
|
+
|
152
|
+
# Force outgoing Outbound.
|
153
|
+
if initial? and @num_vias == 1 and outbound_aware?
|
154
|
+
@force_outgoing_outbound = true
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
def outgoing_outbound_requested? ; @outgoing_outbound_requested end
|
160
|
+
|
161
|
+
def incoming_outbound_requested? ; @incoming_outbound_requested end
|
162
|
+
|
163
|
+
|
164
|
+
def connection_outbound_flow_token
|
165
|
+
@connection_outbound_flow_token ||= if @transport == :udp
|
166
|
+
# NOTE: Add "_" so later we can figure that this is for UDP.
|
167
|
+
# NOTE: Replace "=" with "-" so it can be added as a SIP URI param (when Contact mangling is used
|
168
|
+
# if the registrar does not support Path).
|
169
|
+
"_" << ::Base64.strict_encode64("#{@source_ip}_#{@source_port}").gsub(/=/,"-")
|
170
|
+
else
|
171
|
+
@connection.outbound_flow_token
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
|
179
|
+
def local_uri? uri
|
180
|
+
return false unless uri.scheme == :sip or uri.scheme == :sips
|
181
|
+
# NOTE: uri.host has been normalized during parsing in case it's an IPv6 and it's
|
182
|
+
# an :ipv6_reference.
|
183
|
+
( uri.port and ::OverSIP::SIP.local_aliases["#{uri.host}:#{uri.port}"] ) or
|
184
|
+
( not uri.port and ::OverSIP::SIP.local_aliases[uri.host] )
|
185
|
+
end
|
186
|
+
|
187
|
+
end # module Core
|
188
|
+
|
189
|
+
end
|
@@ -2,7 +2,6 @@ module OverSIP::SIP
|
|
2
2
|
|
3
3
|
class Uri
|
4
4
|
attr_reader :scheme, :user, :host, :host_type, :port, :params, :transport_param, :phone_context_param, :ovid_param, :headers
|
5
|
-
attr_accessor :uri_modified
|
6
5
|
|
7
6
|
def scheme= value
|
8
7
|
return nil if unknown_scheme?
|
@@ -133,6 +132,31 @@ module OverSIP::SIP
|
|
133
132
|
alias :to_s :uri
|
134
133
|
alias :inspect :uri
|
135
134
|
|
135
|
+
# Returns a String with the AoR of the URI:
|
136
|
+
# - SIP URI: sip:user@domain.
|
137
|
+
# - TEL URI: tel:number
|
138
|
+
# - Others: nil
|
139
|
+
#
|
140
|
+
def aor
|
141
|
+
case @scheme
|
142
|
+
when :sip, :sips
|
143
|
+
aor = "sip:"
|
144
|
+
( aor << ::EscapeUtils.escape_uri(@user) << "@" ) if @user
|
145
|
+
aor << @host
|
146
|
+
|
147
|
+
when :tel
|
148
|
+
aor = "tel:"
|
149
|
+
aor << @user
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
aor
|
154
|
+
end
|
155
|
+
|
156
|
+
def modified?
|
157
|
+
@uri_modified
|
158
|
+
end
|
159
|
+
|
136
160
|
end # class Uri
|
137
161
|
|
138
162
|
end
|
data/lib/oversip/sip/launcher.rb
CHANGED
@@ -31,7 +31,7 @@ module OverSIP::SIP
|
|
31
31
|
|
32
32
|
buffer_str = @buffer.to_str
|
33
33
|
|
34
|
-
# Quikly ignore single CRLF (widely used by SIP UDP clients as keep-alive.
|
34
|
+
# Quikly ignore single CRLF (widely used by SIP UDP clients as keep-alive).
|
35
35
|
if buffer_str == CRLF
|
36
36
|
@buffer.clear
|
37
37
|
@state = :init
|
@@ -57,7 +57,7 @@ module OverSIP::SIP
|
|
57
57
|
@state = :init
|
58
58
|
return false
|
59
59
|
# A valid STUN Binding Request so we get a response to be sent.
|
60
|
-
when String
|
60
|
+
when ::String
|
61
61
|
log_system_debug "STUN Binding Request received, replying to it" if $oversip_debug
|
62
62
|
send_data stun_res
|
63
63
|
@buffer.clear
|
@@ -93,7 +93,7 @@ module OverSIP::SIP
|
|
93
93
|
# Run the callback.
|
94
94
|
::OverSIP::SipEvents.on_request @msg
|
95
95
|
rescue ::Exception => e
|
96
|
-
log_system_error "error calling OverSIP::
|
96
|
+
log_system_error "error calling OverSIP::SipEvents.on_request() => 500:"
|
97
97
|
log_system_error e
|
98
98
|
@msg.reply 500, "Internal Error", ["Content-Type: text/plain"], "#{e.class}: #{e.message}"
|
99
99
|
end
|
data/lib/oversip/sip/proxy.rb
CHANGED
@@ -35,11 +35,21 @@ module OverSIP::SIP
|
|
35
35
|
@on_error_block = block
|
36
36
|
end
|
37
37
|
|
38
|
+
def on_target &block
|
39
|
+
@on_target_block = block
|
40
|
+
end
|
41
|
+
|
38
42
|
# If called, current response within the called callback won't be forwarded.
|
39
43
|
def drop_response
|
40
44
|
@drop_response = true
|
41
45
|
end
|
42
46
|
|
47
|
+
# It must only be called within the on_target() callback. By calling this method,
|
48
|
+
# the request routing is aborted, no more DNS targets are tryed, a local 403 response
|
49
|
+
# is generated and on_error() callback is called with status 403.
|
50
|
+
def abort_routing
|
51
|
+
@aborted = true
|
52
|
+
end
|
43
53
|
|
44
54
|
def route request, dst_host=nil, dst_port=nil, dst_transport=nil
|
45
55
|
unless (@request = request).is_a? ::OverSIP::SIP::Request
|
@@ -346,8 +356,6 @@ module OverSIP::SIP
|
|
346
356
|
|
347
357
|
|
348
358
|
def rfc3263_succeeded result
|
349
|
-
#log_system_debug "RFC3263 result: #{result.class}: #{result.inspect}" if $oversip_debug
|
350
|
-
|
351
359
|
# After RFC 3263 (DNS) resolution we get N targets.
|
352
360
|
@num_target = 0 # First target is 0 (rather than 1).
|
353
361
|
|
@@ -365,10 +373,6 @@ module OverSIP::SIP
|
|
365
373
|
log_system_debug "result is MultiTargets => flatting:" if $oversip_debug
|
366
374
|
@targets = result.flatten # Array of Targets.
|
367
375
|
|
368
|
-
# NOTE: Should never happen.
|
369
|
-
else
|
370
|
-
raise "rfc3263_succeeded returns a #{result.class}: #{result.inspect}"
|
371
|
-
|
372
376
|
end
|
373
377
|
|
374
378
|
try_next_target
|
@@ -416,6 +420,18 @@ module OverSIP::SIP
|
|
416
420
|
|
417
421
|
|
418
422
|
def use_target target
|
423
|
+
# Call the on_target() callback if set by the user.
|
424
|
+
@on_target_block && @on_target_block.call(target.ip_type, target.ip, target.port, target.transport)
|
425
|
+
|
426
|
+
# If the user has called to proxy.abort_routing() then stop next targets
|
427
|
+
# and call to on_error() callback.
|
428
|
+
if @aborted
|
429
|
+
log_system_notice "routing aborted for target #{target}"
|
430
|
+
@aborted = @target = @targets = nil
|
431
|
+
try_next_target 403, "Destination Not Allowed"
|
432
|
+
return
|
433
|
+
end
|
434
|
+
|
419
435
|
@client_transaction = (::OverSIP::SIP::ClientTransaction.get_class @request).new self, @request, @proxy_conf, target.transport, target.ip, target.ip_type, target.port
|
420
436
|
add_routing_headers
|
421
437
|
@client_transaction.send_request
|
data/lib/oversip/sip/request.rb
CHANGED
@@ -2,6 +2,8 @@ module OverSIP::SIP
|
|
2
2
|
|
3
3
|
class Request < Message
|
4
4
|
|
5
|
+
include ::OverSIP::SIP::Core
|
6
|
+
|
5
7
|
SECURE_TRANSPORTS = { :tls=>true, :wss=>true }
|
6
8
|
|
7
9
|
attr_accessor :server_transaction
|
@@ -9,9 +11,9 @@ module OverSIP::SIP
|
|
9
11
|
attr_reader :new_max_forwards
|
10
12
|
attr_accessor :antiloop_id
|
11
13
|
attr_accessor :route_outbound_flow_token
|
12
|
-
|
13
14
|
attr_writer :outgoing_outbound_requested, :incoming_outbound_requested
|
14
15
|
attr_accessor :proxied # If true it means that this request has been already proxied.
|
16
|
+
attr_reader :from_was_modified, :to_was_modified # Set to true if the From / To has been modified prior to routing the request.
|
15
17
|
|
16
18
|
# Used for internal purposes when doing proxy and adding the first Record-Route
|
17
19
|
# or Path.
|
@@ -114,6 +116,19 @@ module OverSIP::SIP
|
|
114
116
|
def to_s
|
115
117
|
msg = "#{@sip_method.to_s} #{self.ruri.uri} SIP/2.0\r\n"
|
116
118
|
|
119
|
+
# Update From/To/Contact headers if modified.
|
120
|
+
if @from.modified?
|
121
|
+
@headers["From"] = [ @from.to_s << (@from_tag ? ";tag=#{@from_tag}" : "") ]
|
122
|
+
@from_was_modified = true
|
123
|
+
end
|
124
|
+
if @to.modified?
|
125
|
+
@headers["To"] = [ @to.to_s << (@to_tag ? ";tag=#{@to_tag}" : "") ]
|
126
|
+
@to_was_modified = true
|
127
|
+
end
|
128
|
+
if @contact and @contact.modified?
|
129
|
+
@headers["Contact"] = [ @contact.to_s << (@contact_params ? @contact_params : "") ]
|
130
|
+
end
|
131
|
+
|
117
132
|
@headers.each do |key, values|
|
118
133
|
values.each do |value|
|
119
134
|
msg << key << ": #{value}\r\n"
|
data/lib/oversip/sip/response.rb
CHANGED
@@ -14,6 +14,13 @@ module OverSIP::SIP
|
|
14
14
|
def to_s
|
15
15
|
msg = "SIP/2.0 #{@status_code} #{@reason_phrase}\r\n"
|
16
16
|
|
17
|
+
# Revert changes to From/To headers if modified during the request processing.
|
18
|
+
@headers["From"] = [ request.hdr_from ] if request.from_was_modified
|
19
|
+
if request.to_was_modified
|
20
|
+
hdr_to = @to_tag ? "#{request.hdr_to};tag=#{@to_tag}" : request.hdr_to
|
21
|
+
@headers["To"] = [ hdr_to ] if request.to_was_modified
|
22
|
+
end
|
23
|
+
|
17
24
|
@headers.each do |key, values|
|
18
25
|
values.each do |value|
|
19
26
|
msg << key << ": #{value}\r\n"
|
data/lib/oversip/sip/rfc3263.rb
CHANGED
@@ -126,6 +126,8 @@ module OverSIP::SIP
|
|
126
126
|
@uri_port = uri_port
|
127
127
|
@uri_transport = uri_transport
|
128
128
|
|
129
|
+
@log_id ||= ("RFC3263" << " " << @id)
|
130
|
+
|
129
131
|
@use_dns = dns_conf[:use_dns]
|
130
132
|
@transport_preference = dns_conf[:transport_preference]
|
131
133
|
|
@@ -144,10 +146,6 @@ module OverSIP::SIP
|
|
144
146
|
end
|
145
147
|
end
|
146
148
|
|
147
|
-
def log_id
|
148
|
-
@log_id ||= ("RFC3263" << " " << @id)
|
149
|
-
end
|
150
|
-
|
151
149
|
def callback &block
|
152
150
|
@on_success_block = block
|
153
151
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module OverSIP
|
2
|
+
|
3
|
+
# This module is intended for 3rd party modules that need custom code to be
|
4
|
+
# executed when OverSIP is started, reloaded or terminated.
|
5
|
+
#
|
6
|
+
module SystemCallbacks
|
7
|
+
|
8
|
+
extend ::OverSIP::Logger
|
9
|
+
|
10
|
+
@log_id = "SystemCallbacks"
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_reader :on_started_callbacks
|
14
|
+
attr_reader :on_terminated_callbacks
|
15
|
+
attr_reader :on_reload_callbacks
|
16
|
+
end
|
17
|
+
|
18
|
+
@on_started_callbacks = []
|
19
|
+
@on_terminated_callbacks = []
|
20
|
+
@on_reload_callbacks = []
|
21
|
+
|
22
|
+
def self.on_started pr=nil, &bl
|
23
|
+
block = pr || bl
|
24
|
+
raise ::ArgumentError, "no block given" unless block.is_a? ::Proc
|
25
|
+
|
26
|
+
@on_started_callbacks << block
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.on_terminated pr=nil, &bl
|
30
|
+
block = pr || bl
|
31
|
+
raise ::ArgumentError, "no block given" unless block.is_a? ::Proc
|
32
|
+
|
33
|
+
@on_terminated_callbacks << block
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.on_reload pr=nil, &bl
|
37
|
+
block = pr || bl
|
38
|
+
raise ::ArgumentError, "no block given" unless block.is_a? ::Proc
|
39
|
+
|
40
|
+
@on_reload_callbacks << block
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/lib/oversip/tls.rb
CHANGED
data/lib/oversip/utils.rb
CHANGED
@@ -7,17 +7,22 @@ module OverSIP
|
|
7
7
|
# For example in Ruby the following returns false:
|
8
8
|
# "iñaki".force_encoding(::Encoding::BINARY) == "iñaki"
|
9
9
|
def self.string_compare string1, string2
|
10
|
-
string1.force_encoding(::Encoding::BINARY) == string2.force_encoding(::Encoding::BINARY)
|
10
|
+
string1.to_s.force_encoding(::Encoding::BINARY) == string2.to_s.force_encoding(::Encoding::BINARY)
|
11
11
|
end
|
12
12
|
|
13
13
|
# This avoid "invalid byte sequence in UTF-8" when the directly doing:
|
14
14
|
# string =~ /EXPRESSION/
|
15
15
|
# and string has invalid UTF-8 bytes secuence.
|
16
|
-
#
|
17
|
-
#
|
16
|
+
# Also avoids "incompatible encoding regexp match (UTF-8 regexp with ASCII-8BIT string)"
|
17
|
+
# NOTE: expression argument must be a String or a Regexp.
|
18
18
|
def self.regexp_compare string, expression
|
19
|
-
|
20
|
-
|
19
|
+
string = string.to_s.force_encoding(::Encoding::BINARY)
|
20
|
+
if expression.is_a? ::Regexp
|
21
|
+
expression = /#{expression.source.force_encoding(::Encoding::BINARY)}/
|
22
|
+
else
|
23
|
+
expression = /#{expression.to_s.force_encoding(::Encoding::BINARY)}/
|
24
|
+
end
|
25
|
+
string =~ expression
|
21
26
|
end
|
22
27
|
|
23
28
|
end
|
data/lib/oversip/version.rb
CHANGED