oversip 1.2.1 → 1.3.0.dev1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/README.md +28 -4
  2. data/bin/oversip +1 -1
  3. data/etc/proxies.conf +10 -0
  4. data/etc/server.rb +13 -9
  5. data/ext/utils/haproxy_protocol.c +0 -3
  6. data/ext/utils/outbound_utils.c +1 -1
  7. data/ext/utils/utils_ruby.c +0 -1
  8. data/ext/websocket_http_parser/ws_http_parser.c +940 -1903
  9. data/ext/websocket_http_parser/ws_http_parser.h +1 -0
  10. data/lib/oversip/config_validators.rb +2 -2
  11. data/lib/oversip/launcher.rb +275 -240
  12. data/lib/oversip/master_process.rb +7 -2
  13. data/lib/oversip/proxies_config.rb +8 -1
  14. data/lib/oversip/sip/client.rb +304 -0
  15. data/lib/oversip/sip/client_transaction.rb +31 -36
  16. data/lib/oversip/sip/core.rb +7 -4
  17. data/lib/oversip/sip/launcher.rb +30 -30
  18. data/lib/oversip/sip/listeners/connection.rb +4 -0
  19. data/lib/oversip/sip/listeners/ipv4_tcp_server.rb +1 -0
  20. data/lib/oversip/sip/listeners/ipv4_tls_server.rb +1 -0
  21. data/lib/oversip/sip/listeners/ipv4_tls_tunnel_server.rb +1 -0
  22. data/lib/oversip/sip/listeners/ipv4_udp_server.rb +1 -0
  23. data/lib/oversip/sip/listeners/ipv6_tcp_server.rb +1 -0
  24. data/lib/oversip/sip/listeners/ipv6_tls_server.rb +1 -0
  25. data/lib/oversip/sip/listeners/ipv6_tls_tunnel_server.rb +1 -0
  26. data/lib/oversip/sip/listeners/ipv6_udp_server.rb +1 -0
  27. data/lib/oversip/sip/listeners/tcp_client.rb +26 -0
  28. data/lib/oversip/sip/listeners/tcp_connection.rb +7 -1
  29. data/lib/oversip/sip/listeners/tcp_server.rb +1 -1
  30. data/lib/oversip/sip/listeners/tls_client.rb +28 -24
  31. data/lib/oversip/sip/listeners/tls_server.rb +25 -8
  32. data/lib/oversip/sip/listeners/tls_tunnel_connection.rb +1 -24
  33. data/lib/oversip/sip/message.rb +2 -2
  34. data/lib/oversip/sip/message_processor.rb +23 -13
  35. data/lib/oversip/sip/{grammar/name_addr.rb → name_addr.rb} +11 -0
  36. data/lib/oversip/sip/proxy.rb +53 -227
  37. data/lib/oversip/sip/request.rb +15 -11
  38. data/lib/oversip/sip/response.rb +3 -3
  39. data/lib/oversip/sip/rfc3263.rb +2 -3
  40. data/lib/oversip/sip/tags.rb +1 -1
  41. data/lib/oversip/sip/transport_manager.rb +6 -5
  42. data/lib/oversip/sip/uac.rb +93 -0
  43. data/lib/oversip/sip/uac_request.rb +82 -0
  44. data/lib/oversip/sip/{grammar/uri.rb → uri.rb} +22 -0
  45. data/lib/oversip/version.rb +3 -3
  46. data/lib/oversip/websocket/launcher.rb +25 -25
  47. data/lib/oversip/websocket/listeners/connection.rb +4 -0
  48. data/lib/oversip/websocket/listeners/ipv4_ws_server.rb +1 -0
  49. data/lib/oversip/websocket/listeners/ipv4_wss_server.rb +1 -0
  50. data/lib/oversip/websocket/listeners/ipv4_wss_tunnel_server.rb +1 -0
  51. data/lib/oversip/websocket/listeners/ipv6_ws_server.rb +1 -0
  52. data/lib/oversip/websocket/listeners/ipv6_wss_server.rb +1 -0
  53. data/lib/oversip/websocket/listeners/ipv6_wss_tunnel_server.rb +1 -0
  54. data/lib/oversip/websocket/listeners/ws_server.rb +55 -26
  55. data/lib/oversip/websocket/listeners/wss_server.rb +26 -9
  56. data/lib/oversip/websocket/listeners/wss_tunnel_server.rb +14 -11
  57. data/lib/oversip/websocket/ws_framing.rb +6 -2
  58. data/lib/oversip.rb +3 -1
  59. data/test/test_http_parser.rb +3 -3
  60. data/test/test_uri.rb +18 -12
  61. metadata +91 -77
@@ -0,0 +1,82 @@
1
+ module OverSIP::SIP
2
+
3
+ class UacRequest
4
+
5
+ DEFAULT_MAX_FORWARDS = "20"
6
+ DEFAULT_FROM = "\"OverSIP #{::OverSIP::VERSION}\" <sip:uac@oversip.net>"
7
+
8
+ attr_reader :sip_method, :ruri, :from, :from_tag, :to, :body, :call_id, :cseq
9
+ attr_reader :antiloop_id
10
+ attr_reader :routes # Always nil (needed for OverSIP::SIP::Tags.create_antiloop_id().
11
+ attr_accessor :tvars # Transaction variables (a hash).
12
+
13
+
14
+ def initialize data, extra_headers=[], body=nil
15
+ unless (@sip_method = data[:sip_method])
16
+ raise ::OverSIP::RuntimeError, "no data[:sip_method] given"
17
+ end
18
+ unless (@ruri = data[:ruri])
19
+ raise ::OverSIP::RuntimeError, "no data[:ruri] given"
20
+ end
21
+
22
+ @from = data[:from] || DEFAULT_FROM
23
+ @from_tag = data[:from_tag] || ::SecureRandom.hex(4)
24
+ @to = data[:to] || @ruri
25
+ @call_id = data[:call_id] || ::SecureRandom.hex(8)
26
+ @cseq = data[:cseq] || rand(1000)
27
+ @max_forwards = data[:max_forwards] || DEFAULT_MAX_FORWARDS
28
+
29
+ @headers = {}
30
+ @extra_headers = extra_headers
31
+
32
+ @body = body
33
+
34
+ @antiloop_id = ::OverSIP::SIP::Tags.create_antiloop_id(self)
35
+ end
36
+
37
+
38
+ def insert_header name, value
39
+ @headers[name] = value.to_s
40
+ end
41
+
42
+
43
+ def delete_header_top name
44
+ @headers.delete name
45
+ end
46
+
47
+
48
+ def to_s
49
+ # Let @ruri to be an String, an OverSIP::SIP::Uri or an OverSIP::SIP::NameAddr instance.
50
+ ruri = case @ruri
51
+ when ::String
52
+ @ruri
53
+ when ::OverSIP::SIP::Uri, ::OverSIP::SIP::NameAddr
54
+ @ruri.uri
55
+ end
56
+
57
+ msg = "#{@sip_method.to_s} #{ruri} SIP/2.0\r\n"
58
+
59
+ @headers.each do |name, value|
60
+ msg << name << ": #{value}\r\n"
61
+ end
62
+
63
+ msg << "From: #{@from.to_s};tag=#{@from_tag}\r\n"
64
+ msg << "To: #{@to.to_s}\r\n"
65
+ msg << "Call-ID: #{@call_id}\r\n"
66
+ msg << "CSeq: #{@cseq.to_s} #{@sip_method.to_s}\r\n"
67
+ msg << "Content-Length: #{@body ? @body.bytesize : "0"}\r\n"
68
+ msg << "Max-Forwards: #{@max_forwards.to_s}\r\n"
69
+ msg << HDR_USER_AGENT << CRLF
70
+
71
+ @extra_headers.each do |header|
72
+ msg << header << CRLF
73
+ end
74
+
75
+ msg << CRLF
76
+ msg << @body if @body
77
+ msg
78
+ end
79
+
80
+ end # class Request
81
+
82
+ end
@@ -3,6 +3,24 @@ module OverSIP::SIP
3
3
  class Uri
4
4
  attr_reader :scheme, :user, :host, :host_type, :port, :params, :transport_param, :phone_context_param, :ovid_param, :headers
5
5
 
6
+ def initialize scheme=:sip, user=nil, host=nil, port=nil
7
+ @scheme = scheme.to_sym
8
+ @user = user
9
+ @host = host
10
+ @host_type = ::OverSIP::Utils.ip_type(host) || :domain if host
11
+ @port = port
12
+
13
+ @uri_modified = true
14
+ end
15
+
16
+ def sip?
17
+ @scheme == :sip or @scheme == :sips
18
+ end
19
+
20
+ def tel?
21
+ @scheme == :tel
22
+ end
23
+
6
24
  def scheme= value
7
25
  return nil if unknown_scheme?
8
26
  @scheme = value
@@ -45,6 +63,10 @@ module OverSIP::SIP
45
63
  @params ||= {}
46
64
  end
47
65
 
66
+ def get_param k
67
+ params[k.to_s.downcase]
68
+ end
69
+
48
70
  def set_param k, v
49
71
  return nil if unknown_scheme?
50
72
  @params ||= {}
@@ -4,9 +4,9 @@ module OverSIP
4
4
 
5
5
  module Version
6
6
  MAJOR = 1
7
- MINOR = 2
8
- TINY = 1
9
- DEVEL = nil # Set to nil for stable releases.
7
+ MINOR = 3
8
+ TINY = 0
9
+ DEVEL = "dev1" # Set to nil for stable releases.
10
10
  end
11
11
 
12
12
  PROGRAM_NAME = "OverSIP"
@@ -2,7 +2,7 @@ module OverSIP::WebSocket
2
2
 
3
3
  module Launcher
4
4
 
5
- extend OverSIP::Logger
5
+ extend ::OverSIP::Logger
6
6
 
7
7
  IP_TYPE = {
8
8
  :ipv4 => "IPv4",
@@ -29,18 +29,18 @@ module OverSIP::WebSocket
29
29
  klass = case transport
30
30
  when :ws
31
31
  case ip_type
32
- when :ipv4 ; OverSIP::WebSocket::IPv4WsServer
33
- when :ipv6 ; OverSIP::WebSocket::IPv6WsServer
32
+ when :ipv4 ; ::OverSIP::WebSocket::IPv4WsServer
33
+ when :ipv6 ; ::OverSIP::WebSocket::IPv6WsServer
34
34
  end
35
35
  when :wss
36
36
  case ip_type
37
- when :ipv4 ; OverSIP::WebSocket::IPv4WssServer
38
- when :ipv6 ; OverSIP::WebSocket::IPv6WssServer
37
+ when :ipv4 ; ::OverSIP::WebSocket::IPv4WssServer
38
+ when :ipv6 ; ::OverSIP::WebSocket::IPv6WssServer
39
39
  end
40
40
  when :wss_tunnel
41
41
  case ip_type
42
- when :ipv4 ; OverSIP::WebSocket::IPv4WssTunnelServer
43
- when :ipv6 ; OverSIP::WebSocket::IPv6WssTunnelServer
42
+ when :ipv4 ; ::OverSIP::WebSocket::IPv4WssTunnelServer
43
+ when :ipv6 ; ::OverSIP::WebSocket::IPv6WssTunnelServer
44
44
  end
45
45
  end
46
46
 
@@ -49,33 +49,33 @@ module OverSIP::WebSocket
49
49
 
50
50
  case
51
51
 
52
- when klass == OverSIP::WebSocket::IPv4WsServer
52
+ when klass == ::OverSIP::WebSocket::IPv4WsServer
53
53
  klass.via_core = "SIP/2.0/WS #{uri_ip}:#{port}"
54
54
  klass.record_route = "<sip:#{uri_ip}:#{port};transport=ws;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid}>"
55
55
  klass.outbound_record_route_fragment = "@#{uri_ip}:#{port};transport=ws;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid}>"
56
56
  klass.outbound_path_fragment = "@#{uri_ip}:#{port};transport=ws;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid};ob>"
57
57
 
58
58
  if enabled
59
- EM.start_server(ip, port, klass) do |conn|
59
+ ::EM.start_server(ip, port, klass) do |conn|
60
60
  conn.post_connection
61
- conn.set_comm_inactivity_timeout 3600 # TODO
61
+ conn.set_comm_inactivity_timeout 300
62
62
  end
63
63
  end
64
64
 
65
- when klass == OverSIP::WebSocket::IPv6WsServer
65
+ when klass == ::OverSIP::WebSocket::IPv6WsServer
66
66
  klass.via_core = "SIP/2.0/WS #{uri_ip}:#{port}"
67
67
  klass.record_route = "<sip:#{uri_ip}:#{port};transport=ws;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid}>"
68
68
  klass.outbound_record_route_fragment = "@#{uri_ip}:#{port};transport=ws;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid}>"
69
69
  klass.outbound_path_fragment = "@#{uri_ip}:#{port};transport=ws;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid};ob>"
70
70
 
71
71
  if enabled
72
- EM.start_server(ip, port, klass) do |conn|
72
+ ::EM.start_server(ip, port, klass) do |conn|
73
73
  conn.post_connection
74
- conn.set_comm_inactivity_timeout 3600 # TODO
74
+ conn.set_comm_inactivity_timeout 300
75
75
  end
76
76
  end
77
77
 
78
- when klass == OverSIP::WebSocket::IPv4WssServer
78
+ when klass == ::OverSIP::WebSocket::IPv4WssServer
79
79
  klass.via_core = "SIP/2.0/WSS #{uri_ip}:#{port}"
80
80
  rr_host = ::OverSIP.configuration[:sip][:record_route_hostname_tls_ipv4] || uri_ip
81
81
  klass.record_route = "<sip:#{rr_host}:#{port};transport=wss;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid}>"
@@ -83,13 +83,13 @@ module OverSIP::WebSocket
83
83
  klass.outbound_path_fragment = "@#{rr_host}:#{port};transport=wss;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid};ob>"
84
84
 
85
85
  if enabled
86
- EM.start_server(ip, port, klass) do |conn|
86
+ ::EM.start_server(ip, port, klass) do |conn|
87
87
  conn.post_connection
88
- conn.set_comm_inactivity_timeout 3600 # TODO
88
+ conn.set_comm_inactivity_timeout 300
89
89
  end
90
90
  end
91
91
 
92
- when klass == OverSIP::WebSocket::IPv6WssServer
92
+ when klass == ::OverSIP::WebSocket::IPv6WssServer
93
93
  klass.via_core = "SIP/2.0/WSS #{uri_ip}:#{port}"
94
94
  rr_host = ::OverSIP.configuration[:sip][:record_route_hostname_tls_ipv6] || uri_ip
95
95
  klass.record_route = "<sips:#{rr_host}:#{port};transport=ws;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid}>"
@@ -97,13 +97,13 @@ module OverSIP::WebSocket
97
97
  klass.outbound_path_fragment = "@#{rr_host}:#{port};transport=wss;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid};ob>"
98
98
 
99
99
  if enabled
100
- EM.start_server(ip, port, klass) do |conn|
100
+ ::EM.start_server(ip, port, klass) do |conn|
101
101
  conn.post_connection
102
- conn.set_comm_inactivity_timeout 3600 # TODO
102
+ conn.set_comm_inactivity_timeout 300
103
103
  end
104
104
  end
105
105
 
106
- when klass == OverSIP::WebSocket::IPv4WssTunnelServer
106
+ when klass == ::OverSIP::WebSocket::IPv4WssTunnelServer
107
107
  klass.via_core = "SIP/2.0/WSS #{uri_virtual_ip}:#{virtual_port}"
108
108
  rr_host = ::OverSIP.configuration[:sip][:record_route_hostname_tls_ipv4] || uri_virtual_ip
109
109
  klass.record_route = "<sip:#{rr_host}:#{virtual_port};transport=wss;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid}>"
@@ -111,13 +111,13 @@ module OverSIP::WebSocket
111
111
  klass.outbound_path_fragment = "@#{rr_host}:#{virtual_port};transport=wss;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid};ob>"
112
112
 
113
113
  if enabled
114
- EM.start_server(ip, port, klass) do |conn|
114
+ ::EM.start_server(ip, port, klass) do |conn|
115
115
  conn.post_connection
116
- conn.set_comm_inactivity_timeout 3600 # TODO
116
+ conn.set_comm_inactivity_timeout 300
117
117
  end
118
118
  end
119
119
 
120
- when klass == OverSIP::WebSocket::IPv6WssTunnelServer
120
+ when klass == ::OverSIP::WebSocket::IPv6WssTunnelServer
121
121
  klass.via_core = "SIP/2.0/WSS #{uri_virtual_ip}:#{virtual_port}"
122
122
  rr_host = ::OverSIP.configuration[:sip][:record_route_hostname_tls_ipv6] || uri_virtual_ip
123
123
  klass.record_route = "<sip:#{rr_host}:#{virtual_port};transport=wss;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid}>"
@@ -125,9 +125,9 @@ module OverSIP::WebSocket
125
125
  klass.outbound_path_fragment = "@#{rr_host}:#{virtual_port};transport=wss;lr;ovid=#{OverSIP::SIP::Tags.value_for_route_ovid};ob>"
126
126
 
127
127
  if enabled
128
- EM.start_server(ip, port, klass) do |conn|
128
+ ::EM.start_server(ip, port, klass) do |conn|
129
129
  conn.post_connection
130
- conn.set_comm_inactivity_timeout 3600 # TODO
130
+ conn.set_comm_inactivity_timeout 300
131
131
  end
132
132
  end
133
133
 
@@ -17,6 +17,10 @@ module OverSIP::WebSocket
17
17
  def reliable_transport_listener?
18
18
  @is_reliable_transport_listener
19
19
  end
20
+
21
+ def outbound_listener?
22
+ @is_outbound_listener
23
+ end
20
24
  end
21
25
 
22
26
 
@@ -10,6 +10,7 @@ module OverSIP::WebSocket
10
10
  @invite_client_transactions = {}
11
11
  @non_invite_client_transactions = {}
12
12
  @is_reliable_transport_listener = true
13
+ @is_outbound_listener = true
13
14
 
14
15
  LOG_ID = "SIP WS IPv4 server"
15
16
  def log_id
@@ -10,6 +10,7 @@ module OverSIP::WebSocket
10
10
  @invite_client_transactions = {}
11
11
  @non_invite_client_transactions = {}
12
12
  @is_reliable_transport_listener = true
13
+ @is_outbound_listener = true
13
14
 
14
15
  LOG_ID = "SIP WSS IPv4 server"
15
16
  def log_id
@@ -10,6 +10,7 @@ module OverSIP::WebSocket
10
10
  @invite_client_transactions = {}
11
11
  @non_invite_client_transactions = {}
12
12
  @is_reliable_transport_listener = true
13
+ @is_outbound_listener = true
13
14
 
14
15
  LOG_ID = "SIP WSS-Tunnel IPv4 server"
15
16
  def log_id
@@ -10,6 +10,7 @@ module OverSIP::WebSocket
10
10
  @invite_client_transactions = {}
11
11
  @non_invite_client_transactions = {}
12
12
  @is_reliable_transport_listener = true
13
+ @is_outbound_listener = true
13
14
 
14
15
  LOG_ID = "SIP WS IPv6 server"
15
16
  def log_id
@@ -10,6 +10,7 @@ module OverSIP::WebSocket
10
10
  @invite_client_transactions = {}
11
11
  @non_invite_client_transactions = {}
12
12
  @is_reliable_transport_listener = true
13
+ @is_outbound_listener = true
13
14
 
14
15
  LOG_ID = "SIP WSS IPv6 server"
15
16
  def log_id
@@ -10,6 +10,7 @@ module OverSIP::WebSocket
10
10
  @invite_client_transactions = {}
11
11
  @non_invite_client_transactions = {}
12
12
  @is_reliable_transport_listener = true
13
+ @is_outbound_listener = true
13
14
 
14
15
  LOG_ID = "SIP WSS-Tunnel IPv6 server"
15
16
  def log_id
@@ -85,12 +85,15 @@ module OverSIP::WebSocket
85
85
  end unless $!
86
86
 
87
87
  if @ws_established
88
- begin
89
- ::OverSIP::WebSocketEvents.on_disconnection self, !@local_closed
90
- rescue ::Exception => e
91
- log_system_error "error calling OverSIP::WebSocketEvents.on_disconnection():"
92
- log_system_error e
93
- end
88
+ # Run OverSIP::WebSocketEvents.on_disconnection
89
+ ::Fiber.new do
90
+ begin
91
+ ::OverSIP::WebSocketEvents.on_disconnection self, !@local_closed
92
+ rescue ::Exception => e
93
+ log_system_error "error calling OverSIP::WebSocketEvents.on_disconnection():"
94
+ log_system_error e
95
+ end
96
+ end.resume
94
97
  end unless $!
95
98
  end
96
99
 
@@ -98,6 +101,14 @@ module OverSIP::WebSocket
98
101
  def receive_data data
99
102
  @state == :ignore and return
100
103
  @buffer << data
104
+ @state == :waiting_for_on_client_tls_handshake and return
105
+ @state == :waiting_for_on_connection and return
106
+
107
+ process_received_data
108
+ end
109
+
110
+ def process_received_data
111
+ @state == :ignore and return
101
112
 
102
113
  while (case @state
103
114
  when :init
@@ -113,8 +124,9 @@ module OverSIP::WebSocket
113
124
  when :check_http_request
114
125
  check_http_request
115
126
 
116
- when :ws_connection_callback
117
- ws_connection_callback
127
+ when :on_connection_callback
128
+ do_on_connection_callback
129
+ false
118
130
 
119
131
  when :accept_ws_handshake
120
132
  accept_ws_handshake
@@ -164,6 +176,16 @@ module OverSIP::WebSocket
164
176
 
165
177
 
166
178
  def check_http_request
179
+ # Check OverSIP status.
180
+ unless ::OverSIP.status == :running
181
+ case ::OverSIP.status
182
+ when :loading
183
+ http_reject 500, "Server Still Loading", [ "Retry-After: 5" ]
184
+ when :terminating
185
+ http_reject 500, "Server is Being Stopped"
186
+ end
187
+ return false
188
+ end
167
189
 
168
190
  # HTTP method must be GET.
169
191
  if @http_request.http_method != :GET
@@ -215,29 +237,36 @@ module OverSIP::WebSocket
215
237
  end
216
238
  end
217
239
 
218
- @state = :ws_connection_callback
240
+ @state = :on_connection_callback
219
241
  true
220
242
  end
221
243
 
222
244
 
223
- def ws_connection_callback
224
- begin
225
- ::OverSIP::WebSocketEvents.on_connection self, @http_request
226
- rescue ::Exception => e
227
- log_system_error "error calling OverSIP::WebSocketEvents.on_connection() => 500:"
228
- log_system_error e
229
- http_reject 500
230
- return false
231
- end
245
+ def do_on_connection_callback
246
+ # Set the state to :waiting_for_on_connection so data received before
247
+ # user callback validation is just stored.
248
+ @state = :waiting_for_on_connection
232
249
 
233
- # The user provided callback could have reject the WS connection, so
234
- # check it not to reply a 101 after the reply sent by the user.
235
- if @state == :ws_connection_callback
236
- @state = :accept_ws_handshake
237
- true
238
- else
239
- false
240
- end
250
+ # Run OverSIP::WebSocketEvents.on_connection.
251
+ ::Fiber.new do
252
+ begin
253
+ log_system_debug "running OverSIP::WebSocketEvents.on_connection()..." if $oversip_debug
254
+ ::OverSIP::WebSocketEvents.on_connection self, @http_request
255
+ # If the user of the peer has not closed the connection then continue.
256
+ unless @local_closed or error?
257
+ @state = :accept_ws_handshake
258
+ # Call process_received_data() to process possible data received in the meanwhile.
259
+ process_received_data
260
+ else
261
+ log_system_debug "connection closed during OverSIP::WebSocketEvents.on_connection(), aborting" if $oversip_debug
262
+ end
263
+
264
+ rescue ::Exception => e
265
+ log_system_error "error calling OverSIP::WebSocketEvents.on_connection() => 500:"
266
+ log_system_error e
267
+ http_reject 500
268
+ end
269
+ end.resume
241
270
  end
242
271
 
243
272
 
@@ -43,7 +43,7 @@ module OverSIP::WebSocket
43
43
 
44
44
 
45
45
  def ssl_handshake_completed
46
- log_system_info "TLS connection established from " << remote_desc
46
+ log_system_debug ("TLS connection established from " << remote_desc) if $oversip_debug
47
47
 
48
48
  # @connected in WssServer means "TLS connection" rather than
49
49
  # just "TCP connection".
@@ -51,20 +51,37 @@ module OverSIP::WebSocket
51
51
  @timer_tls_handshake.cancel if @timer_tls_handshake
52
52
 
53
53
  if ::OverSIP::WebSocket.callback_on_client_tls_handshake
54
- begin
55
- ::OverSIP::WebSocketEvents.on_client_tls_handshake self, @client_pems
56
- rescue ::Exception => e
57
- log_system_error "error calling OverSIP::WebSocketEvents.on_client_tls_handshake():"
58
- log_system_error e
59
- close_connection
60
- end
54
+ # Set the state to :waiting_for_on_client_tls_handshake so data received after TLS handshake but before
55
+ # user callback validation is just stored.
56
+ @state = :waiting_for_on_client_tls_handshake
57
+
58
+ # Run OverSIP::WebSocketEvents.on_client_tls_handshake.
59
+ ::Fiber.new do
60
+ begin
61
+ log_system_debug "running OverSIP::SipWebSocketEvents.on_client_tls_handshake()..." if $oversip_debug
62
+ ::OverSIP::WebSocketEvents.on_client_tls_handshake self, @client_pems
63
+ # If the user of the peer has not closed the connection then continue.
64
+ unless @local_closed or error?
65
+ @state = :init
66
+ # Call process_received_data() to process possible data received in the meanwhile.
67
+ process_received_data
68
+ else
69
+ log_system_debug "connection closed during OverSIP::SipWebSocketEvents.on_client_tls_handshake(), aborting" if $oversip_debug
70
+ end
71
+
72
+ rescue ::Exception => e
73
+ log_system_error "error calling OverSIP::WebSocketEvents.on_client_tls_handshake():"
74
+ log_system_error e
75
+ close_connection
76
+ end
77
+ end.resume
61
78
  end
62
79
  end
63
80
 
64
81
 
65
82
  def unbind cause=nil
66
- super
67
83
  @timer_tls_handshake.cancel if @timer_tls_handshake
84
+ super
68
85
  end
69
86
 
70
87
  end
@@ -40,19 +40,21 @@ module OverSIP::WebSocket
40
40
  end unless $!
41
41
 
42
42
  if @ws_established
43
- begin
44
- ::OverSIP::WebSocketEvents.on_disconnection self, !@local_closed
45
- rescue ::Exception => e
46
- log_system_error "error calling OverSIP::WebSocketEvents.on_disconnection():"
47
- log_system_error e
48
- end
43
+ # Run OverSIP::WebSocketEvents.on_disconnection
44
+ ::Fiber.new do
45
+ begin
46
+ ::OverSIP::WebSocketEvents.on_disconnection self, !@local_closed
47
+ rescue ::Exception => e
48
+ log_system_error "error calling OverSIP::WebSocketEvents.on_disconnection():"
49
+ log_system_error e
50
+ end
51
+ end.resume
49
52
  end unless $!
50
53
  end
51
54
 
52
55
 
53
- def receive_data data
56
+ def process_received_data
54
57
  @state == :ignore and return
55
- @buffer << data
56
58
 
57
59
  while (case @state
58
60
  when :init
@@ -78,13 +80,14 @@ module OverSIP::WebSocket
78
80
  when :check_http_request
79
81
  check_http_request
80
82
 
81
- when :ws_connection_callback
82
- ws_connection_callback
83
+ when :on_connection_callback
84
+ do_on_connection_callback
85
+ false
83
86
 
84
87
  when :accept_ws_handshake
85
88
  accept_ws_handshake
86
89
 
87
- when :websocket_frames
90
+ when :websocket
88
91
  @ws_established = true
89
92
  return false if @buffer.size.zero?
90
93
  @ws_framing.receive_data
@@ -44,8 +44,12 @@ module OverSIP::WebSocket
44
44
 
45
45
  def do_keep_alive interval
46
46
  @keep_alive_timer = ::EM::PeriodicTimer.new(interval) do
47
- log_system_debug "sending keep-alive ping frame" if $oversip_debug
48
- @connection.send_data KEEPALIVE_PING_FRAME
47
+ unless @connection.error? # Ensure it.
48
+ log_system_debug "sending keep-alive ping frame" if $oversip_debug
49
+ @connection.send_data KEEPALIVE_PING_FRAME
50
+ else
51
+ @keep_alive_timer.cancel
52
+ end
49
53
  end
50
54
  end
51
55
 
data/lib/oversip.rb CHANGED
@@ -46,7 +46,9 @@ module OverSIP
46
46
  :configuration,
47
47
  :proxies,
48
48
  :tls_public_cert, :tls_private_cert,
49
- :stud_pids
49
+ :stud_pids,
50
+ :is_ready, # true, false
51
+ :status # :loading, :running, :terminating
50
52
 
51
53
  def master?
52
54
  @master_pid == $$
@@ -34,7 +34,7 @@ class TestHttpParser < OverSIPTest
34
34
 
35
35
  def test_parse_http_get
36
36
  parser, request = parse <<-END
37
- GET http://server.example.coM./chat?qwe=QWE&asd=#fragment HTTP/1.1\r
37
+ GET /chat?qwe=QWE&asd=#fragment HTTP/1.1\r
38
38
  Host: server.example.Com.\r
39
39
  Upgrade: WebSocket\r
40
40
  Connection: keep-Alive , Upgrade\r
@@ -51,11 +51,11 @@ END
51
51
  assert_equal request.http_method, :GET
52
52
  assert_equal request.http_version, "HTTP/1.1"
53
53
 
54
- assert_equal "/chat?qwe=QWE&asd=", request.uri
54
+ assert_equal "/chat?qwe=QWE&asd=#fragment", request.uri
55
55
  assert_equal "/chat", request.uri_path
56
56
  assert_equal "qwe=QWE&asd=", request.uri_query
57
57
  assert_equal "fragment", request.uri_fragment
58
- assert_equal request.uri_scheme, :http
58
+ assert_equal request.uri_scheme, nil
59
59
  assert_equal "server.example.com", request.host
60
60
  assert_nil request.port
61
61
 
data/test/test_uri.rb CHANGED
@@ -9,17 +9,17 @@ class TestUri < OverSIPTest
9
9
  full_uri = "sips:i%C3%B1aki@aliax.net:5060;transport=tcp;foo=123;baz?X-Header-1=qwe&X-Header-2=asd"
10
10
  aor = "sip:i%C3%B1aki@aliax.net"
11
11
 
12
- uri = ::OverSIP::SIP::Uri.new
13
- uri.instance_variable_set :@scheme, :sips
14
- uri.user = "iñaki"
15
- uri.host = "aliax.net"
16
- uri.host_type = :domain
17
- uri.port = 5060
12
+ uri = ::OverSIP::SIP::Uri.new :sips, "iñaki", "aliax.net", 5060
18
13
  uri.transport_param = :tcp
19
- uri.instance_variable_set :@params, {"transport"=>"tcp", "foo"=>"123", "baz"=>nil}
14
+ uri.set_param "FOO", "123"
15
+ uri.set_param "baz", nil
20
16
  uri.headers = "?X-Header-1=qwe&X-Header-2=asd"
21
17
 
18
+ assert_true uri.sip?
19
+ assert_false uri.tel?
20
+ assert_false uri.unknown_scheme?
22
21
  assert_equal "iñaki", uri.user
22
+ assert_equal "123", uri.get_param("Foo")
23
23
  assert_equal aor, uri.aor
24
24
  assert_equal full_uri, uri.to_s
25
25
  end
@@ -28,12 +28,15 @@ class TestUri < OverSIPTest
28
28
  full_uri = "tel:944991212;foo=bar;phone-context=+34"
29
29
  aor = "tel:944991212"
30
30
 
31
- uri = ::OverSIP::SIP::Uri.new
32
- uri.instance_variable_set :@scheme, :tel
33
- uri.user = "944991212"
34
- uri.instance_variable_set :@params, {"foo"=>"bar"}
31
+ uri = ::OverSIP::SIP::Uri.new :tel, "944991212"
32
+ uri.set_param "FOO", "bar"
35
33
  uri.phone_context_param = "+34"
36
34
 
35
+ assert_false uri.sip?
36
+ assert_true uri.tel?
37
+ assert_false uri.unknown_scheme?
38
+ assert_equal "944991212", uri.number
39
+ assert_equal "bar", uri.get_param("Foo")
37
40
  assert_equal aor, uri.aor
38
41
  assert_equal full_uri, uri.to_s
39
42
  end
@@ -42,9 +45,12 @@ class TestUri < OverSIPTest
42
45
  full_uri = "http://oversip.net/authors/"
43
46
  aor = nil
44
47
 
45
- uri = ::OverSIP::SIP::Uri.new
48
+ uri = ::OverSIP::SIP::Uri.allocate
46
49
  uri.instance_variable_set :@uri, full_uri
47
50
 
51
+ assert_false uri.sip?
52
+ assert_false uri.tel?
53
+ assert_true uri.unknown_scheme?
48
54
  assert_nil uri.aor
49
55
  assert_equal full_uri, uri.to_s
50
56
  end