oversip 1.1.0.beta5 → 1.1.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/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
|