oversip 1.1.0.beta5 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/etc/oversip.conf +16 -4
- data/etc/proxies.conf +8 -9
- data/etc/server.rb +59 -0
- data/ext/sip_parser/sip_parser.c +12066 -11975
- data/ext/sip_parser/sip_parser.h +1 -0
- data/ext/sip_parser/sip_parser_ruby.c +15 -4
- data/ext/utils/haproxy_protocol.c +4 -1
- data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +2 -2
- data/lib/oversip/config.rb +50 -38
- data/lib/oversip/default_server.rb +12 -0
- data/lib/oversip/launcher.rb +10 -35
- data/lib/oversip/master_process.rb +2 -2
- data/lib/oversip/proxies_config.rb +2 -2
- data/lib/oversip/sip/client_transaction.rb +1 -7
- data/lib/oversip/sip/grammar/uri.rb +23 -1
- data/lib/oversip/sip/listeners/{reactor.rb → connection.rb} +16 -2
- data/lib/oversip/sip/listeners/ipv4_udp_server.rb +1 -1
- data/lib/oversip/sip/listeners/ipv6_udp_server.rb +1 -1
- data/lib/oversip/sip/listeners/tcp_client.rb +2 -3
- data/lib/oversip/sip/listeners/{tcp_reactor.rb → tcp_connection.rb} +14 -2
- data/lib/oversip/sip/listeners/tcp_server.rb +2 -5
- data/lib/oversip/sip/listeners/tls_client.rb +15 -12
- data/lib/oversip/sip/listeners/tls_server.rb +11 -11
- data/lib/oversip/sip/listeners/{tls_tunnel_reactor.rb → tls_tunnel_connection.rb} +20 -20
- data/lib/oversip/sip/listeners/tls_tunnel_server.rb +2 -5
- data/lib/oversip/sip/listeners/{udp_reactor.rb → udp_connection.rb} +4 -4
- data/lib/oversip/sip/listeners.rb +6 -10
- data/lib/oversip/sip/message.rb +4 -3
- data/lib/oversip/sip/message_processor.rb +17 -17
- data/lib/oversip/sip/modules/core.rb +18 -13
- data/lib/oversip/sip/modules/user_assertion.rb +7 -53
- data/lib/oversip/sip/proxy.rb +3 -3
- data/lib/oversip/sip/request.rb +2 -0
- data/lib/oversip/sip/rfc3263.rb +3 -3
- data/lib/oversip/sip/sip.rb +6 -0
- data/lib/oversip/sip/transport_manager.rb +8 -8
- data/lib/oversip/tls.rb +18 -22
- data/lib/oversip/version.rb +1 -1
- data/lib/oversip/websocket/constants.rb +0 -1
- data/lib/oversip/websocket/http_request.rb +4 -8
- data/lib/oversip/websocket/launcher.rb +83 -139
- data/lib/oversip/websocket/listeners/connection.rb +47 -0
- data/lib/oversip/websocket/{ws_apps/ipv4_ws_sip_app.rb → listeners/ipv4_ws_server.rb} +3 -3
- data/lib/oversip/websocket/{ws_apps/ipv4_wss_sip_app.rb → listeners/ipv4_wss_server.rb} +2 -2
- data/lib/oversip/websocket/listeners/ipv4_wss_tunnel_server.rb +21 -0
- data/lib/oversip/websocket/{ws_apps/ipv6_ws_sip_app.rb → listeners/ipv6_ws_server.rb} +3 -3
- data/lib/oversip/websocket/{ws_apps/ipv6_wss_sip_app.rb → listeners/ipv6_wss_server.rb} +2 -3
- data/lib/oversip/websocket/listeners/ipv6_wss_tunnel_server.rb +21 -0
- data/lib/oversip/websocket/listeners/{tcp_server.rb → ws_server.rb} +63 -43
- data/lib/oversip/websocket/listeners/{tls_server.rb → wss_server.rb} +14 -13
- data/lib/oversip/websocket/listeners/{tls_tunnel_server.rb → wss_tunnel_server.rb} +36 -10
- data/lib/oversip/websocket/listeners.rb +10 -9
- data/lib/oversip/websocket/websocket.rb +13 -0
- data/lib/oversip/websocket/ws_framing.rb +35 -97
- data/lib/oversip/websocket/ws_sip_app.rb +120 -0
- data/lib/oversip.rb +1 -1
- data/test/oversip_test_helper.rb +2 -2
- data/test/test_http_parser.rb +2 -2
- data/test/test_sip_parser.rb +18 -3
- data/test/test_uri.rb +44 -0
- metadata +39 -42
- data/lib/oversip/websocket/listeners/ipv4_tcp_server.rb +0 -15
- data/lib/oversip/websocket/listeners/ipv4_tls_server.rb +0 -15
- data/lib/oversip/websocket/listeners/ipv4_tls_tunnel_server.rb +0 -15
- data/lib/oversip/websocket/listeners/ipv6_tcp_server.rb +0 -15
- data/lib/oversip/websocket/listeners/ipv6_tls_server.rb +0 -15
- data/lib/oversip/websocket/listeners/ipv6_tls_tunnel_server.rb +0 -15
- data/lib/oversip/websocket/ws_app.rb +0 -77
- data/lib/oversip/websocket/ws_apps/ws_autobahn_app.rb +0 -23
- data/lib/oversip/websocket/ws_apps/ws_sip_app.rb +0 -156
- data/lib/oversip/websocket/ws_apps.rb +0 -9
@@ -1,10 +1,8 @@
|
|
1
1
|
module OverSIP::WebSocket
|
2
2
|
|
3
|
-
class
|
3
|
+
class WsServer < Connection
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
# Max size (bytes) of the buffered data when receiving message headers
|
5
|
+
# Max size (bytes) of the buffered data when receiving HTTP headers
|
8
6
|
# (avoid DoS attacks).
|
9
7
|
HEADERS_MAX_SIZE = 2048
|
10
8
|
|
@@ -13,23 +11,25 @@ module OverSIP::WebSocket
|
|
13
11
|
HDR_SUPPORTED_WEBSOCKET_VERSIONS = [ "X-Supported-WebSocket-Versions: #{WS_VERSIONS.keys.join(", ")}" ]
|
14
12
|
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
attr_reader :outbound_flow_token
|
15
|
+
attr_writer :ws_established, :client_closed
|
16
|
+
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
attr_accessor :ws_locally_closed
|
18
|
+
def remote_ip_type
|
19
|
+
@remote_ip_type || self.class.ip_type
|
20
|
+
end
|
24
21
|
|
22
|
+
def remote_ip
|
23
|
+
@remote_ip
|
24
|
+
end
|
25
25
|
|
26
|
-
def
|
27
|
-
@
|
28
|
-
@buffer = ::IO::Buffer.new
|
29
|
-
@state = :init
|
30
|
-
@cvars = {}
|
26
|
+
def remote_port
|
27
|
+
@remote_port
|
31
28
|
end
|
32
29
|
|
30
|
+
def transport
|
31
|
+
self.class.transport
|
32
|
+
end
|
33
33
|
|
34
34
|
def post_connection
|
35
35
|
begin
|
@@ -40,9 +40,13 @@ module OverSIP::WebSocket
|
|
40
40
|
@state = :ignore
|
41
41
|
return
|
42
42
|
end
|
43
|
-
@connection_log_id = ::SecureRandom.hex(4)
|
44
43
|
|
45
|
-
|
44
|
+
@connection_id = ::OverSIP::SIP::TransportManager.add_connection self, self.class, self.class.ip_type, @remote_ip, @remote_port
|
45
|
+
|
46
|
+
# Create an Outbound (RFC 5626) flow token for this connection.
|
47
|
+
@outbound_flow_token = ::OverSIP::SIP::TransportManager.add_outbound_connection self
|
48
|
+
|
49
|
+
log_system_debug("connection opened from " << remote_desc) if $oversip_debug
|
46
50
|
end
|
47
51
|
|
48
52
|
|
@@ -62,7 +66,16 @@ module OverSIP::WebSocket
|
|
62
66
|
|
63
67
|
|
64
68
|
def unbind cause=nil
|
69
|
+
@state = :ignore
|
70
|
+
|
71
|
+
# Remove the connection.
|
72
|
+
self.class.connections.delete @connection_id
|
73
|
+
|
74
|
+
# Remove the Outbound token flow.
|
75
|
+
::OverSIP::SIP::TransportManager.delete_outbound_connection @outbound_flow_token
|
76
|
+
|
65
77
|
@local_closed = true if cause == ::Errno::ETIMEDOUT
|
78
|
+
@local_closed = false if @client_closed
|
66
79
|
|
67
80
|
if $oversip_debug
|
68
81
|
log_msg = "connection from #{remote_desc} "
|
@@ -71,11 +84,9 @@ module OverSIP::WebSocket
|
|
71
84
|
log_system_debug log_msg
|
72
85
|
end unless $!
|
73
86
|
|
74
|
-
|
75
|
-
|
76
|
-
if @ws_handshake_done
|
87
|
+
if @ws_established
|
77
88
|
begin
|
78
|
-
::OverSIP::WebSocketEvents.on_disconnection self, !@
|
89
|
+
::OverSIP::WebSocketEvents.on_disconnection self, !@local_closed
|
79
90
|
rescue ::Exception => e
|
80
91
|
log_system_error "error calling OverSIP::WebSocketEvents.on_disconnection():"
|
81
92
|
log_system_error e
|
@@ -90,8 +101,8 @@ module OverSIP::WebSocket
|
|
90
101
|
|
91
102
|
while (case @state
|
92
103
|
when :init
|
104
|
+
@http_parser = ::OverSIP::WebSocket::HttpRequestParser.new
|
93
105
|
@http_request = ::OverSIP::WebSocket::HttpRequest.new
|
94
|
-
@http_parser.reset
|
95
106
|
@http_parser_nbytes = 0
|
96
107
|
@bytes_remaining = 0
|
97
108
|
@state = :http_headers
|
@@ -103,14 +114,13 @@ module OverSIP::WebSocket
|
|
103
114
|
check_http_request
|
104
115
|
|
105
116
|
when :ws_connection_callback
|
106
|
-
|
117
|
+
ws_connection_callback
|
107
118
|
|
108
119
|
when :accept_ws_handshake
|
109
120
|
accept_ws_handshake
|
110
121
|
|
111
|
-
when :
|
112
|
-
|
113
|
-
|
122
|
+
when :websocket
|
123
|
+
@ws_established = true
|
114
124
|
@ws_framing.receive_data
|
115
125
|
false
|
116
126
|
|
@@ -147,10 +157,6 @@ module OverSIP::WebSocket
|
|
147
157
|
@buffer.read(@http_parser_nbytes)
|
148
158
|
|
149
159
|
@http_request.connection = self
|
150
|
-
@http_request.transport = self.class.transport
|
151
|
-
@http_request.source_ip = @remote_ip
|
152
|
-
@http_request.source_port = @remote_port
|
153
|
-
@http_request.source_ip_type = @remote_ip_type ||= self.class.ip_type
|
154
160
|
|
155
161
|
@state = :check_http_request
|
156
162
|
true
|
@@ -200,7 +206,7 @@ module OverSIP::WebSocket
|
|
200
206
|
|
201
207
|
# Check Sec-WebSocket-Protocol.
|
202
208
|
if @http_request.hdr_sec_websocket_protocol
|
203
|
-
if @http_request.hdr_sec_websocket_protocol.include?
|
209
|
+
if @http_request.hdr_sec_websocket_protocol.include? WS_SIP_PROTOCOL
|
204
210
|
@websocket_protocol_negotiated = true
|
205
211
|
else
|
206
212
|
log_system_notice "Sec-WebSocket-Protocol does not contain a supported protocol but #{@http_request.hdr_sec_websocket_protocol} => 501"
|
@@ -214,7 +220,7 @@ module OverSIP::WebSocket
|
|
214
220
|
end
|
215
221
|
|
216
222
|
|
217
|
-
def
|
223
|
+
def ws_connection_callback
|
218
224
|
begin
|
219
225
|
::OverSIP::WebSocketEvents.on_connection self, @http_request
|
220
226
|
rescue ::Exception => e
|
@@ -245,7 +251,7 @@ module OverSIP::WebSocket
|
|
245
251
|
]
|
246
252
|
|
247
253
|
if @websocket_protocol_negotiated
|
248
|
-
extra_headers << "Sec-WebSocket-Protocol: #{
|
254
|
+
extra_headers << "Sec-WebSocket-Protocol: #{WS_SIP_PROTOCOL}"
|
249
255
|
end
|
250
256
|
|
251
257
|
if @websocket_extensions
|
@@ -254,12 +260,12 @@ module OverSIP::WebSocket
|
|
254
260
|
|
255
261
|
@http_request.reply 101, nil, extra_headers
|
256
262
|
|
257
|
-
# Set the WS
|
258
|
-
@ws_framing = ::OverSIP::WebSocket::WsFraming.new
|
259
|
-
|
263
|
+
# Set the WS framing layer and WS application layer.
|
264
|
+
@ws_framing = ::OverSIP::WebSocket::WsFraming.new self, @buffer
|
265
|
+
ws_sip_app = ::OverSIP::WebSocket::WsSipApp.new self, @ws_framing
|
266
|
+
@ws_framing.ws_app = ws_sip_app
|
260
267
|
|
261
|
-
@
|
262
|
-
@state = :websocket_frames
|
268
|
+
@state = :websocket
|
263
269
|
true
|
264
270
|
end
|
265
271
|
|
@@ -271,12 +277,26 @@ module OverSIP::WebSocket
|
|
271
277
|
end
|
272
278
|
|
273
279
|
|
274
|
-
|
275
|
-
|
276
|
-
|
280
|
+
# Parameters ip and port are just included because they are needed in UDP, so the API remains equal.
|
281
|
+
def send_sip_msg msg, ip=nil, port=nil
|
282
|
+
if self.error?
|
283
|
+
log_system_notice "SIP message could not be sent, connection is closed"
|
284
|
+
return false
|
285
|
+
end
|
286
|
+
|
287
|
+
# If the SIP message is fully valid UTF-8 send a WS text frame.
|
288
|
+
if msg.force_encoding(::Encoding::UTF_8).valid_encoding?
|
289
|
+
@ws_framing.send_text_frame msg
|
290
|
+
|
291
|
+
# If not, send a WS binary frame.
|
292
|
+
else
|
293
|
+
@ws_framing.send_binary_frame msg
|
294
|
+
end
|
295
|
+
|
296
|
+
true
|
277
297
|
end
|
278
298
|
|
279
|
-
end
|
299
|
+
end
|
280
300
|
|
281
301
|
end
|
282
302
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module OverSIP::WebSocket
|
2
2
|
|
3
|
-
class
|
3
|
+
class WssServer < WsServer
|
4
4
|
|
5
|
-
TLS_HANDSHAKE_MAX_TIME =
|
5
|
+
TLS_HANDSHAKE_MAX_TIME = 4
|
6
6
|
|
7
7
|
|
8
8
|
def post_init
|
@@ -44,25 +44,26 @@ module OverSIP::WebSocket
|
|
44
44
|
def ssl_handshake_completed
|
45
45
|
log_system_info "TLS connection established from " << remote_desc
|
46
46
|
|
47
|
-
#
|
48
|
-
|
49
|
-
validated, cert, tls_error, tls_error_string = ::OverSIP::TLS.validate @client_pems.pop, @client_pems
|
50
|
-
if validated
|
51
|
-
log_system_info "client provides a valid TLS certificate"
|
52
|
-
else
|
53
|
-
log_system_notice "client's TLS certificate validation failed (TLS error: #{tls_error.inspect}, description: #{tls_error_string.inspect})"
|
54
|
-
end
|
55
|
-
|
56
|
-
# @connected in TlsServer means "TLS connection" rather than
|
47
|
+
# @connected in WssServer means "TLS connection" rather than
|
57
48
|
# just "TCP connection".
|
58
49
|
@connected = true
|
59
50
|
@timer_tls_handshake.cancel if @timer_tls_handshake
|
51
|
+
|
52
|
+
if ::OverSIP::WebSocket.callback_on_client_tls_handshake
|
53
|
+
begin
|
54
|
+
::OverSIP::WebSocketEvents.on_client_tls_handshake self, @client_pems
|
55
|
+
rescue ::Exception => e
|
56
|
+
log_system_error "error calling OverSIP::WebSocketEvents.on_client_tls_handshake():"
|
57
|
+
log_system_error e
|
58
|
+
close_connection
|
59
|
+
end
|
60
|
+
end
|
60
61
|
end
|
61
62
|
|
62
63
|
|
63
64
|
def unbind cause=nil
|
64
|
-
@timer_tls_handshake.cancel if @timer_tls_handshake
|
65
65
|
super
|
66
|
+
@timer_tls_handshake.cancel if @timer_tls_handshake
|
66
67
|
end
|
67
68
|
|
68
69
|
end
|
@@ -1,16 +1,10 @@
|
|
1
1
|
module OverSIP::WebSocket
|
2
2
|
|
3
|
-
class
|
4
|
-
|
5
|
-
def initialize
|
6
|
-
@http_parser = ::OverSIP::WebSocket::HttpRequestParser.new
|
7
|
-
@buffer = ::IO::Buffer.new
|
8
|
-
@state = :init
|
9
|
-
end
|
10
|
-
|
3
|
+
class WssTunnelServer < WsServer
|
11
4
|
|
12
5
|
def post_connection
|
13
6
|
begin
|
7
|
+
# Temporal @remote_ip and @remote_port until the HAProxy protocol line is parsed.
|
14
8
|
@remote_port, @remote_ip = ::Socket.unpack_sockaddr_in(get_peername)
|
15
9
|
rescue => e
|
16
10
|
log_system_error "error obtaining remote IP/port (#{e.class}: #{e.message}), closing connection"
|
@@ -18,9 +12,40 @@ module OverSIP::WebSocket
|
|
18
12
|
@state = :ignore
|
19
13
|
return
|
20
14
|
end
|
21
|
-
@connection_log_id = ::SecureRandom.hex(4)
|
22
15
|
|
23
|
-
|
16
|
+
# Create an Outbound (RFC 5626) flow token for this connection.
|
17
|
+
@outbound_flow_token = ::OverSIP::SIP::TransportManager.add_outbound_connection self
|
18
|
+
|
19
|
+
log_system_debug ("connection from the TLS tunnel " << remote_desc) if $oversip_debug
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def unbind cause=nil
|
24
|
+
@state = :ignore
|
25
|
+
|
26
|
+
# Remove the connection.
|
27
|
+
self.class.connections.delete @connection_id if @connection_id
|
28
|
+
|
29
|
+
# Remove the Outbound token flow.
|
30
|
+
::OverSIP::SIP::TransportManager.delete_outbound_connection @outbound_flow_token
|
31
|
+
|
32
|
+
@local_closed = true if cause == ::Errno::ETIMEDOUT
|
33
|
+
|
34
|
+
if $oversip_debug
|
35
|
+
log_msg = "connection from the TLS tunnel #{remote_desc} "
|
36
|
+
log_msg << ( @local_closed ? "locally closed" : "remotely closed" )
|
37
|
+
log_msg << " (cause: #{cause.inspect})" if cause
|
38
|
+
log_system_debug log_msg
|
39
|
+
end unless $!
|
40
|
+
|
41
|
+
if @state == :websocket
|
42
|
+
begin
|
43
|
+
::OverSIP::WebSocketEvents.on_disconnection self, !@local_closed
|
44
|
+
rescue ::Exception => e
|
45
|
+
log_system_error "error calling OverSIP::WebSocketEvents.on_disconnection():"
|
46
|
+
log_system_error e
|
47
|
+
end
|
48
|
+
end unless $!
|
24
49
|
end
|
25
50
|
|
26
51
|
|
@@ -30,6 +55,7 @@ module OverSIP::WebSocket
|
|
30
55
|
|
31
56
|
while (case @state
|
32
57
|
when :init
|
58
|
+
@http_parser = ::OverSIP::WebSocket::HttpRequestParser.new
|
33
59
|
@http_request = ::OverSIP::WebSocket::HttpRequest.new
|
34
60
|
@http_parser.reset
|
35
61
|
@http_parser_nbytes = 0
|
@@ -1,12 +1,13 @@
|
|
1
1
|
# OverSIP files
|
2
2
|
|
3
|
-
require "oversip/websocket/listeners/
|
4
|
-
require "oversip/websocket/listeners/
|
5
|
-
require "oversip/websocket/listeners/
|
3
|
+
require "oversip/websocket/listeners/connection"
|
4
|
+
require "oversip/websocket/listeners/ws_server"
|
5
|
+
require "oversip/websocket/listeners/wss_server"
|
6
|
+
require "oversip/websocket/listeners/wss_tunnel_server"
|
6
7
|
|
7
|
-
require "oversip/websocket/listeners/
|
8
|
-
require "oversip/websocket/listeners/
|
9
|
-
require "oversip/websocket/listeners/
|
10
|
-
require "oversip/websocket/listeners/
|
11
|
-
require "oversip/websocket/listeners/
|
12
|
-
require "oversip/websocket/listeners/
|
8
|
+
require "oversip/websocket/listeners/ipv4_ws_server"
|
9
|
+
require "oversip/websocket/listeners/ipv6_ws_server"
|
10
|
+
require "oversip/websocket/listeners/ipv4_wss_server"
|
11
|
+
require "oversip/websocket/listeners/ipv6_wss_server"
|
12
|
+
require "oversip/websocket/listeners/ipv4_wss_tunnel_server"
|
13
|
+
require "oversip/websocket/listeners/ipv6_wss_tunnel_server"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module OverSIP::WebSocket
|
2
|
+
|
3
|
+
def self.module_init
|
4
|
+
conf = ::OverSIP.configuration
|
5
|
+
|
6
|
+
@callback_on_client_tls_handshake = conf[:websocket][:callback_on_client_tls_handshake]
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.callback_on_client_tls_handshake
|
10
|
+
@callback_on_client_tls_handshake
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -20,16 +20,17 @@ module OverSIP::WebSocket
|
|
20
20
|
KEEPALIVE_PING_FRAME = keepalive_ping_frame
|
21
21
|
|
22
22
|
|
23
|
-
attr_writer :ws_app
|
24
|
-
|
25
|
-
|
26
23
|
def self.class_init
|
27
24
|
@@max_frame_size = ::OverSIP.configuration[:websocket][:max_ws_frame_size]
|
28
25
|
end
|
29
26
|
|
30
27
|
|
28
|
+
attr_writer :ws_app
|
29
|
+
|
30
|
+
|
31
|
+
LOG_ID = "WsFraming"
|
31
32
|
def log_id
|
32
|
-
|
33
|
+
LOG_ID
|
33
34
|
end
|
34
35
|
|
35
36
|
|
@@ -43,7 +44,7 @@ module OverSIP::WebSocket
|
|
43
44
|
|
44
45
|
def do_keep_alive interval
|
45
46
|
@keep_alive_timer = ::EM::PeriodicTimer.new(interval) do
|
46
|
-
log_system_debug "sending keep-alive ping frame
|
47
|
+
log_system_debug "sending keep-alive ping frame" if $oversip_debug
|
47
48
|
@connection.send_data KEEPALIVE_PING_FRAME
|
48
49
|
end
|
49
50
|
end
|
@@ -67,21 +68,21 @@ module OverSIP::WebSocket
|
|
67
68
|
|
68
69
|
if @rsv1 or @rsv2 or @rsv3
|
69
70
|
log_system_notice "frame has RSV bits set, clossing the connection"
|
70
|
-
|
71
|
+
@connection.close 1002, "RSV bit set not supported"
|
71
72
|
return false
|
72
73
|
end
|
73
74
|
|
74
75
|
# opcode are bits 4-7.
|
75
76
|
@opcode = byte1 & 0b00001111
|
76
77
|
unless (@sym_opcode = OPCODE[@opcode])
|
77
|
-
|
78
|
+
@connection.close 1002, "unknown opcode=#{@opcode}"
|
78
79
|
return false
|
79
80
|
end
|
80
81
|
|
81
82
|
# MASK is bit 8.
|
82
83
|
@mask = (byte2 & 0b10000000) == 0b10000000
|
83
84
|
unless @mask
|
84
|
-
|
85
|
+
@connection.close 1002, "MASK bit not set"
|
85
86
|
return false
|
86
87
|
end
|
87
88
|
|
@@ -124,7 +125,7 @@ module OverSIP::WebSocket
|
|
124
125
|
|
125
126
|
if @buffer.read(4).unpack('N').first != 0
|
126
127
|
log_system_notice "frame size bigger than 4 GB, rejected"
|
127
|
-
|
128
|
+
@connection.close 1008
|
128
129
|
return false
|
129
130
|
end
|
130
131
|
|
@@ -148,13 +149,13 @@ module OverSIP::WebSocket
|
|
148
149
|
# less and MUST NOT be fragmented.
|
149
150
|
if control_frame? and @payload_length > 125
|
150
151
|
log_system_notice "received invalid control frame (payload_length > 125), sending close frame"
|
151
|
-
|
152
|
+
@connection.close 1002
|
152
153
|
return false
|
153
154
|
end
|
154
155
|
|
155
156
|
if control_frame? and not @fin
|
156
157
|
log_system_notice "received invalid control frame (FIN=0), sending close frame"
|
157
|
-
|
158
|
+
@connection.close 1002, "forbidden FIN=0 in control frame"
|
158
159
|
return false
|
159
160
|
end
|
160
161
|
|
@@ -162,7 +163,7 @@ module OverSIP::WebSocket
|
|
162
163
|
# arrived with FIN=0.
|
163
164
|
if continuation_frame? and not @msg_sym_opcode
|
164
165
|
log_system_notice "invalid continuation frame received (no previous unfinished message), sending close frame"
|
165
|
-
|
166
|
+
@connection.close 1002, "invalid continuation frame received"
|
166
167
|
return false
|
167
168
|
end
|
168
169
|
|
@@ -170,13 +171,13 @@ module OverSIP::WebSocket
|
|
170
171
|
# a new frame with opcode=text/binary.
|
171
172
|
if @msg_sym_opcode and text_or_binary_frame?
|
172
173
|
log_system_notice "invalid text/binary frame received (expecting a continuation frame), sending close frame"
|
173
|
-
|
174
|
+
@connection.close 1002, "expected a continuation frame"
|
174
175
|
return false
|
175
176
|
end
|
176
177
|
|
177
178
|
# Check max frame size.
|
178
179
|
if @payload_length > @@max_frame_size
|
179
|
-
|
180
|
+
@connection.close 1009, "frame too big"
|
180
181
|
return false
|
181
182
|
end
|
182
183
|
|
@@ -214,17 +215,22 @@ module OverSIP::WebSocket
|
|
214
215
|
if @payload
|
215
216
|
if (valid_utf8 = @utf8_validator.validate(@payload)) == false
|
216
217
|
log_system_notice "received single text frame contains invalid UTF-8, closing the connection"
|
217
|
-
|
218
|
+
@connection.close 1007, "single text frame contains invalid UTF-8"
|
218
219
|
return false
|
219
220
|
end
|
220
221
|
|
221
222
|
if @fin and not valid_utf8
|
222
223
|
log_system_notice "received single text frame contains incomplete UTF-8, closing the connection"
|
223
|
-
|
224
|
+
@connection.close 1007, "single text frame contains incomplete UTF-8"
|
224
225
|
return false
|
225
226
|
end
|
226
227
|
|
227
|
-
|
228
|
+
# If @ws_app.receive_payload_data returns false it means that total
|
229
|
+
# message size is too big.
|
230
|
+
unless @ws_app.receive_payload_data @payload
|
231
|
+
@connection.close 1009, "message too big"
|
232
|
+
return false
|
233
|
+
end
|
228
234
|
end
|
229
235
|
|
230
236
|
# If message is finished tell it to the WS application.
|
@@ -241,7 +247,12 @@ module OverSIP::WebSocket
|
|
241
247
|
@msg_sym_opcode = @sym_opcode
|
242
248
|
|
243
249
|
if @payload
|
244
|
-
|
250
|
+
# If @ws_app.receive_payload_data returns false it means that total
|
251
|
+
# message size is too big.
|
252
|
+
unless @ws_app.receive_payload_data @payload
|
253
|
+
@connection.close 1009, "message too big"
|
254
|
+
return false
|
255
|
+
end
|
245
256
|
end
|
246
257
|
|
247
258
|
# If message is finished tell it to the WS application.
|
@@ -257,13 +268,13 @@ module OverSIP::WebSocket
|
|
257
268
|
if @msg_sym_opcode == :text
|
258
269
|
if (valid_utf8 = @utf8_validator.validate(@payload)) == false
|
259
270
|
log_system_notice "received continuation text frame contains invalid UTF-8, closing the connection"
|
260
|
-
|
271
|
+
@connection.close 1007, "continuation text frame contains invalid UTF-8"
|
261
272
|
return false
|
262
273
|
end
|
263
274
|
|
264
275
|
if @fin and not valid_utf8
|
265
276
|
log_system_notice "received continuation final text frame contains incomplete UTF-8, closing the connection"
|
266
|
-
|
277
|
+
@connection.close 1007, "continuation final text frame contains incomplete UTF-8"
|
267
278
|
return false
|
268
279
|
end
|
269
280
|
end
|
@@ -293,7 +304,7 @@ module OverSIP::WebSocket
|
|
293
304
|
# So it must be true for the close frame reason.
|
294
305
|
unless @utf8_validator.validate(reason)
|
295
306
|
log_system_notice "received close frame with invalid UTF-8 data in the reason: status=#{status.inspect}"
|
296
|
-
|
307
|
+
@connection.close 1007, "close frame reason contains incomplete UTF-8"
|
297
308
|
return false
|
298
309
|
end
|
299
310
|
end
|
@@ -316,7 +327,8 @@ module OverSIP::WebSocket
|
|
316
327
|
log_system_debug "received close frame: status=#{status.inspect}, reason=#{reason.inspect}" if $oversip_debug
|
317
328
|
end
|
318
329
|
|
319
|
-
|
330
|
+
@connection.client_closed = true
|
331
|
+
@connection.close nil, nil
|
320
332
|
return false
|
321
333
|
|
322
334
|
when :ping
|
@@ -329,13 +341,6 @@ module OverSIP::WebSocket
|
|
329
341
|
end
|
330
342
|
|
331
343
|
true
|
332
|
-
|
333
|
-
when :ws_closed
|
334
|
-
false
|
335
|
-
|
336
|
-
when :tcp_closed
|
337
|
-
false
|
338
|
-
|
339
344
|
end)
|
340
345
|
end # while
|
341
346
|
|
@@ -359,14 +364,6 @@ module OverSIP::WebSocket
|
|
359
364
|
|
360
365
|
# NOTE: A WS message is always set in a single WS frame.
|
361
366
|
def send_text_frame message
|
362
|
-
case @state
|
363
|
-
when :ws_closed
|
364
|
-
log_system_debug "cannot send text frame, WebSocket session is closed" if $oversip_debug
|
365
|
-
return false
|
366
|
-
when :tcp_closed
|
367
|
-
log_system_debug "cannot send text frame, TCP session is closed" if $oversip_debug
|
368
|
-
return false
|
369
|
-
end
|
370
367
|
log_system_debug "sending text frame: payload_length=#{message.bytesize}" if $oversip_debug
|
371
368
|
|
372
369
|
frame = "".encode ::Encoding::BINARY
|
@@ -401,14 +398,6 @@ module OverSIP::WebSocket
|
|
401
398
|
|
402
399
|
|
403
400
|
def send_binary_frame message
|
404
|
-
case @state
|
405
|
-
when :ws_closed
|
406
|
-
log_system_debug "cannot send binary frame, WebSocket session is closed" if $oversip_debug
|
407
|
-
return false
|
408
|
-
when :tcp_closed
|
409
|
-
log_system_debug "cannot send binary frame, TCP session is closed" if $oversip_debug
|
410
|
-
return false
|
411
|
-
end
|
412
401
|
log_system_debug "sending binary frame: payload_length=#{message.bytesize}" if $oversip_debug
|
413
402
|
|
414
403
|
frame = "".encode ::Encoding::BINARY
|
@@ -443,14 +432,6 @@ module OverSIP::WebSocket
|
|
443
432
|
|
444
433
|
|
445
434
|
def send_ping_frame data=nil
|
446
|
-
case @state
|
447
|
-
when :ws_closed
|
448
|
-
log_system_debug "cannot send ping frame, WebSocket session is closed" if $oversip_debug
|
449
|
-
return false
|
450
|
-
when :tcp_closed
|
451
|
-
log_system_debug "cannot send ping frame, TCP session is closed" if $oversip_debug
|
452
|
-
return false
|
453
|
-
end
|
454
435
|
if data
|
455
436
|
log_system_debug "sending ping frame: payload_length=#{data.bytesize}" if $oversip_debug
|
456
437
|
else
|
@@ -483,14 +464,6 @@ module OverSIP::WebSocket
|
|
483
464
|
|
484
465
|
|
485
466
|
def send_pong_frame data=nil
|
486
|
-
case @state
|
487
|
-
when :ws_closed
|
488
|
-
log_system_debug "cannot send pong frame, WebSocket session is closed" if $oversip_debug
|
489
|
-
return false
|
490
|
-
when :tcp_closed
|
491
|
-
log_system_debug "cannot send pong frame, TCP session is closed" if $oversip_debug
|
492
|
-
return false
|
493
|
-
end
|
494
467
|
if data
|
495
468
|
log_system_debug "sending pong frame: payload_length=#{data.bytesize}" if $oversip_debug
|
496
469
|
else
|
@@ -525,22 +498,12 @@ module OverSIP::WebSocket
|
|
525
498
|
def send_close_frame status=nil, reason=nil, in_reply_to_close=nil
|
526
499
|
@keep_alive_timer.cancel if @keep_alive_timer
|
527
500
|
|
528
|
-
case @state
|
529
|
-
when :ws_closed
|
530
|
-
log_system_debug "cannot send close frame, WebSocket session is closed" if $oversip_debug
|
531
|
-
return false
|
532
|
-
when :tcp_closed
|
533
|
-
log_system_debug "cannot send close frame, TCP session is closed" if $oversip_debug
|
534
|
-
return false
|
535
|
-
end
|
536
|
-
|
537
501
|
unless in_reply_to_close
|
538
502
|
log_system_debug "sending close frame: status=#{status.inspect}, reason=#{reason.inspect}" if $oversip_debug
|
539
503
|
else
|
540
504
|
log_system_debug "sending reply close frame: status=#{status.inspect}, reason=#{reason.inspect}" if $oversip_debug
|
541
505
|
end
|
542
506
|
|
543
|
-
@state = :ws_closed
|
544
507
|
@buffer.clear
|
545
508
|
|
546
509
|
frame = "".encode ::Encoding::BINARY
|
@@ -569,35 +532,10 @@ module OverSIP::WebSocket
|
|
569
532
|
end
|
570
533
|
end
|
571
534
|
|
572
|
-
@connection.ignore_incoming_data
|
573
535
|
@connection.send_data frame
|
574
|
-
|
575
|
-
# NOTE: Don't do it since it "seems" that the connection has been closed
|
576
|
-
# by the client.
|
577
|
-
#unless in_reply_to_close
|
578
|
-
# Let's some time for the client to send us a close frame (it will
|
579
|
-
# be ignored anyway) before closing the TCP connection.
|
580
|
-
# NOTE: Don't do it since it "seems" that the connection has been closed
|
581
|
-
# by the client.
|
582
|
-
#::EM.add_timer(0.2) do
|
583
|
-
#@connection.close_connection_after_writing
|
584
|
-
#end
|
585
|
-
#else
|
586
|
-
#@connection.close_connection_after_writing
|
587
|
-
#end
|
588
|
-
|
589
|
-
@connection.close_connection_after_writing
|
590
536
|
true
|
591
537
|
end
|
592
538
|
|
593
|
-
|
594
|
-
def tcp_closed
|
595
|
-
@keep_alive_timer.cancel if @keep_alive_timer
|
596
|
-
@state = :tcp_closed
|
597
|
-
# Tell it to the WS application.
|
598
|
-
@ws_app.tcp_closed rescue nil
|
599
|
-
end
|
600
|
-
|
601
|
-
end # class WsFraming
|
539
|
+
end
|
602
540
|
|
603
541
|
end
|