ruflet_server 0.0.6 → 0.0.8
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.
- checksums.yaml +4 -4
- data/lib/ruflet/server/web_socket_connection.rb +20 -2
- data/lib/ruflet/server/wire_codec.rb +17 -0
- data/lib/ruflet/server.rb +61 -6
- data/lib/ruflet/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f0ec355d06e9fb730a851fa6b085bc97b74bd1231aa682bfc03a93ed3078f762
|
|
4
|
+
data.tar.gz: 2c3af4192affd015f59bfc0a49dc4fe3af264f1da38f5914c78af3d8602ace57
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 250363621bf1bfaefb04a2a2a89f30336590272250239c21061d96c60cac1ae5464f5a5442a42fab0f415bea3085a5921be8bb073e59d7d968b5bc537635eac9
|
|
7
|
+
data.tar.gz: 14d25116e02035b24646f73577aa3780b5f990473191725636324d26c53cccd3a65da53d84db3d2534a4a60450aac5ce7c79799f70b44703db271819c8f8f687
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module Ruflet
|
|
4
4
|
class WebSocketConnection
|
|
5
|
+
# Ruflet control messages are small; anything much larger is invalid or hostile.
|
|
6
|
+
MAX_FRAME_PAYLOAD_BYTES = 16 * 1024 * 1024
|
|
7
|
+
|
|
5
8
|
def initialize(socket)
|
|
6
9
|
@socket = socket
|
|
7
10
|
@write_mutex = Mutex.new
|
|
@@ -70,10 +73,20 @@ module Ruflet
|
|
|
70
73
|
masked = (b2 & 0x80) != 0
|
|
71
74
|
payload_len = b2 & 0x7f
|
|
72
75
|
|
|
73
|
-
|
|
74
|
-
|
|
76
|
+
if payload_len == 126
|
|
77
|
+
ext = read_exact(2)
|
|
78
|
+
return nil if ext.nil?
|
|
79
|
+
payload_len = ext.unpack1("n")
|
|
80
|
+
elsif payload_len == 127
|
|
81
|
+
ext = read_exact(8)
|
|
82
|
+
return nil if ext.nil?
|
|
83
|
+
payload_len = ext.unpack1("Q>")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
return nil if payload_len.negative? || payload_len > MAX_FRAME_PAYLOAD_BYTES
|
|
75
87
|
|
|
76
88
|
masking_key = masked ? read_exact(4) : nil
|
|
89
|
+
return nil if masked && masking_key.nil?
|
|
77
90
|
payload = payload_len.zero? ? "".b : read_exact(payload_len)
|
|
78
91
|
return nil if payload.nil?
|
|
79
92
|
|
|
@@ -112,6 +125,9 @@ module Ruflet
|
|
|
112
125
|
end
|
|
113
126
|
|
|
114
127
|
def read_exact(length)
|
|
128
|
+
return nil unless length.is_a?(Integer)
|
|
129
|
+
return nil if length.negative? || length > MAX_FRAME_PAYLOAD_BYTES
|
|
130
|
+
|
|
115
131
|
chunk = +""
|
|
116
132
|
chunk.force_encoding(Encoding::BINARY)
|
|
117
133
|
|
|
@@ -123,6 +139,8 @@ module Ruflet
|
|
|
123
139
|
end
|
|
124
140
|
|
|
125
141
|
chunk
|
|
142
|
+
rescue IOError, SystemCallError
|
|
143
|
+
nil
|
|
126
144
|
end
|
|
127
145
|
end
|
|
128
146
|
end
|
|
@@ -128,10 +128,23 @@ module Ruflet
|
|
|
128
128
|
when 0xd9 then reader.read_string(reader.read_u8)
|
|
129
129
|
when 0xda then reader.read_string(reader.read_u16)
|
|
130
130
|
when 0xdb then reader.read_string(reader.read_u32)
|
|
131
|
+
when 0xc4 then reader.read_binary(reader.read_u8)
|
|
132
|
+
when 0xc5 then reader.read_binary(reader.read_u16)
|
|
133
|
+
when 0xc6 then reader.read_binary(reader.read_u32)
|
|
131
134
|
when 0xdc then read_array(reader, reader.read_u16)
|
|
132
135
|
when 0xdd then read_array(reader, reader.read_u32)
|
|
133
136
|
when 0xde then read_map(reader, reader.read_u16)
|
|
134
137
|
when 0xdf then read_map(reader, reader.read_u32)
|
|
138
|
+
when 0xd4
|
|
139
|
+
read_ext(reader, 1)
|
|
140
|
+
when 0xd5
|
|
141
|
+
read_ext(reader, 2)
|
|
142
|
+
when 0xd6
|
|
143
|
+
read_ext(reader, 4)
|
|
144
|
+
when 0xd7
|
|
145
|
+
read_ext(reader, 8)
|
|
146
|
+
when 0xd8
|
|
147
|
+
read_ext(reader, 16)
|
|
135
148
|
when 0xc7
|
|
136
149
|
read_ext(reader, reader.read_u8)
|
|
137
150
|
when 0xc8
|
|
@@ -231,6 +244,10 @@ module Ruflet
|
|
|
231
244
|
def read_string(size)
|
|
232
245
|
read_exact(size).force_encoding("UTF-8")
|
|
233
246
|
end
|
|
247
|
+
|
|
248
|
+
def read_binary(size)
|
|
249
|
+
read_exact(size)
|
|
250
|
+
end
|
|
234
251
|
end
|
|
235
252
|
end
|
|
236
253
|
end
|
data/lib/ruflet/server.rb
CHANGED
|
@@ -96,6 +96,33 @@ module Ruflet
|
|
|
96
96
|
end
|
|
97
97
|
end
|
|
98
98
|
|
|
99
|
+
def reload_app!
|
|
100
|
+
snapshots = @sessions_mutex.synchronize { @sessions.to_a }
|
|
101
|
+
|
|
102
|
+
snapshots.each do |session_key, current_page|
|
|
103
|
+
ws = @connections_mutex.synchronize { @connections[session_key] }
|
|
104
|
+
next unless ws
|
|
105
|
+
|
|
106
|
+
refreshed_page = Page.new(
|
|
107
|
+
session_id: current_page.session_id,
|
|
108
|
+
client_details: current_page.client_details,
|
|
109
|
+
sender: lambda do |action, payload|
|
|
110
|
+
send_message(ws, action, payload)
|
|
111
|
+
end
|
|
112
|
+
)
|
|
113
|
+
refreshed_page.title = "Ruflet App"
|
|
114
|
+
|
|
115
|
+
@sessions_mutex.synchronize do
|
|
116
|
+
@sessions[session_key] = refreshed_page
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
@app_block.call(refreshed_page)
|
|
120
|
+
refreshed_page.update
|
|
121
|
+
rescue StandardError => e
|
|
122
|
+
warn "reload error: #{e.class}: #{e.message}"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
99
126
|
private
|
|
100
127
|
|
|
101
128
|
def trap_stop_signals
|
|
@@ -159,6 +186,8 @@ module Ruflet
|
|
|
159
186
|
ws = nil
|
|
160
187
|
begin
|
|
161
188
|
path, headers = read_http_upgrade_request(socket)
|
|
189
|
+
return if path.nil?
|
|
190
|
+
|
|
162
191
|
if websocket_upgrade_request?(path, headers)
|
|
163
192
|
send_handshake_response(socket, headers["sec-websocket-key"])
|
|
164
193
|
ws = Ruflet::WebSocketConnection.new(socket)
|
|
@@ -167,6 +196,8 @@ module Ruflet
|
|
|
167
196
|
handle_http_request(socket, path)
|
|
168
197
|
end
|
|
169
198
|
rescue StandardError => e
|
|
199
|
+
return if disconnect_error?(e)
|
|
200
|
+
|
|
170
201
|
warn "server error: #{e.class}: #{e.message}"
|
|
171
202
|
warn e.backtrace.join("\n") if e.backtrace
|
|
172
203
|
send_message(ws, Protocol::ACTIONS[:session_crashed], { "message" => e.message.to_s.dup.force_encoding("UTF-8") }) if ws
|
|
@@ -182,6 +213,8 @@ module Ruflet
|
|
|
182
213
|
handle_message(ws, raw)
|
|
183
214
|
end
|
|
184
215
|
rescue StandardError => e
|
|
216
|
+
return if disconnect_error?(e)
|
|
217
|
+
|
|
185
218
|
warn "server error: #{e.class}: #{e.message}"
|
|
186
219
|
warn e.backtrace.join("\n") if e.backtrace
|
|
187
220
|
send_message(ws, Protocol::ACTIONS[:session_crashed], { "message" => e.message.to_s.dup.force_encoding("UTF-8") })
|
|
@@ -197,10 +230,12 @@ module Ruflet
|
|
|
197
230
|
|
|
198
231
|
def read_http_upgrade_request(socket)
|
|
199
232
|
request_line = socket.gets("\r\n")
|
|
200
|
-
|
|
233
|
+
return [nil, {}] if request_line.nil?
|
|
234
|
+
return [nil, {}] unless request_line.include?(" ")
|
|
201
235
|
|
|
202
236
|
method, path, _version = request_line.strip.split(" ", 3)
|
|
203
|
-
|
|
237
|
+
return [nil, {}] unless method == "GET"
|
|
238
|
+
return [nil, {}] if path.to_s.empty?
|
|
204
239
|
|
|
205
240
|
headers = {}
|
|
206
241
|
loop do
|
|
@@ -438,9 +473,9 @@ module Ruflet
|
|
|
438
473
|
raise
|
|
439
474
|
end
|
|
440
475
|
|
|
441
|
-
def on_invoke_control_method(
|
|
442
|
-
|
|
443
|
-
|
|
476
|
+
def on_invoke_control_method(ws, payload)
|
|
477
|
+
page = fetch_page(ws)
|
|
478
|
+
page.handle_invoke_method_result(payload)
|
|
444
479
|
end
|
|
445
480
|
|
|
446
481
|
def on_control_event(ws, payload)
|
|
@@ -482,10 +517,30 @@ module Ruflet
|
|
|
482
517
|
end
|
|
483
518
|
|
|
484
519
|
def send_message(ws, action, payload)
|
|
520
|
+
return if ws.nil? || ws.closed?
|
|
521
|
+
|
|
485
522
|
message = [action, payload]
|
|
486
523
|
ws.send_binary(Ruflet::WireCodec.pack(message))
|
|
487
524
|
rescue StandardError => e
|
|
488
|
-
|
|
525
|
+
unless disconnect_error?(e)
|
|
526
|
+
warn "send error: #{e.class}: #{e.message}"
|
|
527
|
+
end
|
|
528
|
+
remove_session(ws)
|
|
529
|
+
unregister_connection(ws)
|
|
530
|
+
ws&.close
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
def disconnect_error?(error)
|
|
534
|
+
return true if error.is_a?(IOError)
|
|
535
|
+
return true if error.is_a?(Errno::EPIPE)
|
|
536
|
+
return true if error.is_a?(Errno::ECONNRESET)
|
|
537
|
+
return true if error.is_a?(Errno::ECONNABORTED)
|
|
538
|
+
return true if error.is_a?(Errno::ENOTCONN)
|
|
539
|
+
return true if error.is_a?(Errno::ESHUTDOWN)
|
|
540
|
+
return true if error.is_a?(Errno::EBADF)
|
|
541
|
+
return true if error.is_a?(Errno::EINVAL)
|
|
542
|
+
|
|
543
|
+
false
|
|
489
544
|
end
|
|
490
545
|
|
|
491
546
|
def pseudo_uuid
|
data/lib/ruflet/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruflet_server
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- AdamMusa
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.0.
|
|
18
|
+
version: 0.0.8
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.0.
|
|
25
|
+
version: 0.0.8
|
|
26
26
|
description: Ruflet WebSocket server runtime compatible with Flet protocol.
|
|
27
27
|
email:
|
|
28
28
|
- adammusa2222@gmail.com
|