oversip 1.1.2 → 1.2.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/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