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.
Files changed (71) hide show
  1. data/etc/oversip.conf +16 -4
  2. data/etc/proxies.conf +8 -9
  3. data/etc/server.rb +59 -0
  4. data/ext/sip_parser/sip_parser.c +12066 -11975
  5. data/ext/sip_parser/sip_parser.h +1 -0
  6. data/ext/sip_parser/sip_parser_ruby.c +15 -4
  7. data/ext/utils/haproxy_protocol.c +4 -1
  8. data/ext/websocket_framing_utils/ws_framing_utils_ruby.c +2 -2
  9. data/lib/oversip/config.rb +50 -38
  10. data/lib/oversip/default_server.rb +12 -0
  11. data/lib/oversip/launcher.rb +10 -35
  12. data/lib/oversip/master_process.rb +2 -2
  13. data/lib/oversip/proxies_config.rb +2 -2
  14. data/lib/oversip/sip/client_transaction.rb +1 -7
  15. data/lib/oversip/sip/grammar/uri.rb +23 -1
  16. data/lib/oversip/sip/listeners/{reactor.rb → connection.rb} +16 -2
  17. data/lib/oversip/sip/listeners/ipv4_udp_server.rb +1 -1
  18. data/lib/oversip/sip/listeners/ipv6_udp_server.rb +1 -1
  19. data/lib/oversip/sip/listeners/tcp_client.rb +2 -3
  20. data/lib/oversip/sip/listeners/{tcp_reactor.rb → tcp_connection.rb} +14 -2
  21. data/lib/oversip/sip/listeners/tcp_server.rb +2 -5
  22. data/lib/oversip/sip/listeners/tls_client.rb +15 -12
  23. data/lib/oversip/sip/listeners/tls_server.rb +11 -11
  24. data/lib/oversip/sip/listeners/{tls_tunnel_reactor.rb → tls_tunnel_connection.rb} +20 -20
  25. data/lib/oversip/sip/listeners/tls_tunnel_server.rb +2 -5
  26. data/lib/oversip/sip/listeners/{udp_reactor.rb → udp_connection.rb} +4 -4
  27. data/lib/oversip/sip/listeners.rb +6 -10
  28. data/lib/oversip/sip/message.rb +4 -3
  29. data/lib/oversip/sip/message_processor.rb +17 -17
  30. data/lib/oversip/sip/modules/core.rb +18 -13
  31. data/lib/oversip/sip/modules/user_assertion.rb +7 -53
  32. data/lib/oversip/sip/proxy.rb +3 -3
  33. data/lib/oversip/sip/request.rb +2 -0
  34. data/lib/oversip/sip/rfc3263.rb +3 -3
  35. data/lib/oversip/sip/sip.rb +6 -0
  36. data/lib/oversip/sip/transport_manager.rb +8 -8
  37. data/lib/oversip/tls.rb +18 -22
  38. data/lib/oversip/version.rb +1 -1
  39. data/lib/oversip/websocket/constants.rb +0 -1
  40. data/lib/oversip/websocket/http_request.rb +4 -8
  41. data/lib/oversip/websocket/launcher.rb +83 -139
  42. data/lib/oversip/websocket/listeners/connection.rb +47 -0
  43. data/lib/oversip/websocket/{ws_apps/ipv4_ws_sip_app.rb → listeners/ipv4_ws_server.rb} +3 -3
  44. data/lib/oversip/websocket/{ws_apps/ipv4_wss_sip_app.rb → listeners/ipv4_wss_server.rb} +2 -2
  45. data/lib/oversip/websocket/listeners/ipv4_wss_tunnel_server.rb +21 -0
  46. data/lib/oversip/websocket/{ws_apps/ipv6_ws_sip_app.rb → listeners/ipv6_ws_server.rb} +3 -3
  47. data/lib/oversip/websocket/{ws_apps/ipv6_wss_sip_app.rb → listeners/ipv6_wss_server.rb} +2 -3
  48. data/lib/oversip/websocket/listeners/ipv6_wss_tunnel_server.rb +21 -0
  49. data/lib/oversip/websocket/listeners/{tcp_server.rb → ws_server.rb} +63 -43
  50. data/lib/oversip/websocket/listeners/{tls_server.rb → wss_server.rb} +14 -13
  51. data/lib/oversip/websocket/listeners/{tls_tunnel_server.rb → wss_tunnel_server.rb} +36 -10
  52. data/lib/oversip/websocket/listeners.rb +10 -9
  53. data/lib/oversip/websocket/websocket.rb +13 -0
  54. data/lib/oversip/websocket/ws_framing.rb +35 -97
  55. data/lib/oversip/websocket/ws_sip_app.rb +120 -0
  56. data/lib/oversip.rb +1 -1
  57. data/test/oversip_test_helper.rb +2 -2
  58. data/test/test_http_parser.rb +2 -2
  59. data/test/test_sip_parser.rb +18 -3
  60. data/test/test_uri.rb +44 -0
  61. metadata +39 -42
  62. data/lib/oversip/websocket/listeners/ipv4_tcp_server.rb +0 -15
  63. data/lib/oversip/websocket/listeners/ipv4_tls_server.rb +0 -15
  64. data/lib/oversip/websocket/listeners/ipv4_tls_tunnel_server.rb +0 -15
  65. data/lib/oversip/websocket/listeners/ipv6_tcp_server.rb +0 -15
  66. data/lib/oversip/websocket/listeners/ipv6_tls_server.rb +0 -15
  67. data/lib/oversip/websocket/listeners/ipv6_tls_tunnel_server.rb +0 -15
  68. data/lib/oversip/websocket/ws_app.rb +0 -77
  69. data/lib/oversip/websocket/ws_apps/ws_autobahn_app.rb +0 -23
  70. data/lib/oversip/websocket/ws_apps/ws_sip_app.rb +0 -156
  71. data/lib/oversip/websocket/ws_apps.rb +0 -9
@@ -1,10 +1,8 @@
1
1
  module OverSIP::WebSocket
2
2
 
3
- class TcpServer < ::EM::Connection
3
+ class WsServer < Connection
4
4
 
5
- include ::OverSIP::Logger
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
- class << self
17
- attr_accessor :ip_type, :transport
18
- end
14
+ attr_reader :outbound_flow_token
15
+ attr_writer :ws_established, :client_closed
16
+
19
17
 
20
- attr_accessor :ws_protocol, :ws_app_klass
21
- attr_reader :connection_log_id, :remote_ip_type, :remote_ip, :remote_port
22
- attr_reader :cvars # A Hash for storing user provided data.
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 initialize
27
- @http_parser = ::OverSIP::WebSocket::HttpRequestParser.new
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
- log_system_info "connection opened from " << remote_desc
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
- @ws_framing.tcp_closed if @ws_framing
75
-
76
- if @ws_handshake_done
87
+ if @ws_established
77
88
  begin
78
- ::OverSIP::WebSocketEvents.on_disconnection self, !@ws_locally_closed
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
- check_ws_connection_callback
117
+ ws_connection_callback
107
118
 
108
119
  when :accept_ws_handshake
109
120
  accept_ws_handshake
110
121
 
111
- when :websocket_frames
112
- return false if @buffer.size.zero?
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? @ws_protocol
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 check_ws_connection_callback
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: #{@ws_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 framming layer and WS application layer.
258
- @ws_framing = ::OverSIP::WebSocket::WsFraming.new(self, @buffer)
259
- @ws_framing.ws_app = @ws_app_klass.new(self, @ws_framing)
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
- @ws_handshake_done = true
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
- def ignore_incoming_data
275
- @state = :ignore # The WS application needs to set the connection in :ignore state
276
- # after sending a close frame to the client.
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 # class TcpServer
299
+ end
280
300
 
281
301
  end
282
302
 
@@ -1,8 +1,8 @@
1
1
  module OverSIP::WebSocket
2
2
 
3
- class TlsServer < TcpServer
3
+ class WssServer < WsServer
4
4
 
5
- TLS_HANDSHAKE_MAX_TIME = 8
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
- # TODO: What to do it falidation fails? always do validation?
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 TlsTunnelServer < TcpServer
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
- log_system_info "connection from the TLS tunnel " << remote_desc
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/tcp_server"
4
- require "oversip/websocket/listeners/tls_server"
5
- require "oversip/websocket/listeners/tls_tunnel_server"
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/ipv4_tcp_server"
8
- require "oversip/websocket/listeners/ipv6_tcp_server"
9
- require "oversip/websocket/listeners/ipv4_tls_server"
10
- require "oversip/websocket/listeners/ipv6_tls_server"
11
- require "oversip/websocket/listeners/ipv4_tls_tunnel_server"
12
- require "oversip/websocket/listeners/ipv6_tls_tunnel_server"
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
- @log_id ||= "WsFramming #{@connection.connection_log_id}"
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: payload_length=10" if $oversip_debug
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
- send_close_frame 1002, "RSV bit set not supported"
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
- send_close_frame 1002, "unknown opcode=#{@opcode}"
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
- send_close_frame 1002, "MASK bit not set"
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
- send_close_frame 1008
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
- send_close_frame 1002
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
- send_close_frame 1002, "forbidden FIN=0 in control frame"
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
- send_close_frame 1002, "invalid continuation frame received"
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
- send_close_frame 1002, "expected a continuation frame"
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
- send_close_frame 1009, "frame too big"
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
- send_close_frame 1007, "single text frame contains invalid UTF-8"
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
- send_close_frame 1007, "single text frame contains incomplete UTF-8"
224
+ @connection.close 1007, "single text frame contains incomplete UTF-8"
224
225
  return false
225
226
  end
226
227
 
227
- return false unless @ws_app.receive_payload_data @payload
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
- return false unless @ws_app.receive_payload_data @payload
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
- send_close_frame 1007, "continuation text frame contains invalid UTF-8"
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
- send_close_frame 1007, "continuation final text frame contains incomplete UTF-8"
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
- send_close_frame 1007, "close frame reason contains incomplete UTF-8"
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
- send_close_frame nil, nil, true
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