Web sockets fragments are supported (silly implementation).

master
Karchnu 2020-09-01 02:32:46 +02:00
parent af1c7e1875
commit b1ac2dacee
2 changed files with 35 additions and 5 deletions

View File

@ -38,7 +38,14 @@ class HTTP::WebSocket
record Pong record Pong
record Close record Close
record Error record Error
record NotFinal # record NotFinal
struct NotFinal
property message : String
property info : Protocol::PacketInfo
def initialize(@message, @info)
end
end
# :nodoc: # :nodoc:
def run_once : Bytes | String | Close | Ping | Pong | NotFinal | Error def run_once : Bytes | String | Close | Ping | Pong | NotFinal | Error
@ -73,6 +80,8 @@ class HTTP::WebSocket
@on_message.try &.call(@current_message.to_s) @on_message.try &.call(@current_message.to_s)
@current_message.clear @current_message.clear
return String.new message return String.new message
else
return NotFinal.new String.new(message), info
end end
when Protocol::Opcode::BINARY when Protocol::Opcode::BINARY
message = @buffer[0, info.size] message = @buffer[0, info.size]
@ -93,7 +102,7 @@ class HTTP::WebSocket
end end
end end
return NotFinal.new raise "what the fuck?"
end end
# Returns the websocket instance. # Returns the websocket instance.

View File

@ -290,15 +290,21 @@ def websocket_connection_procedure (requested_service : String, clientfd : Int32
end end
end end
class FragmentBuffer
property buffer : String = String.new
end
def websocket_switching_procedure (activefd : Int) def websocket_switching_procedure (activefd : Int)
begin begin
Baguette::Log.title "activefd is #{activefd}" Baguette::Log.title "activefd is #{activefd}"
if Context.context.is_client[activefd] if Context.context.is_client[activefd]
Baguette::Log.title "activefd #{activefd} is a client" # Baguette::Log.title "activefd #{activefd} is a client"
# The client is a WebSocket on top of a TCP connection # The client is a WebSocket on top of a TCP connection
client = Context.context.fd_to_tcpsocket[activefd] client = Context.context.fd_to_tcpsocket[activefd]
wsclient = Context.context.fd_to_websocket[activefd] wsclient = Context.context.fd_to_websocket[activefd]
fb = FragmentBuffer.new
loop do loop do
begin begin
message = wsclient.run_once message = wsclient.run_once
@ -358,14 +364,18 @@ def websocket_switching_procedure (activefd : Int)
next next
end end
break break
when WebSocket::NotFinal when WebSocket::NotFinal
Baguette::Log.warning "Received only part of a message (not supported)" Baguette::Log.warning "Received only part of a message"
pp! # TODO: check if the message is OK when multiplexing
# pp! message
fb.buffer = fb.buffer + message.message
if still_something_to_read if still_something_to_read
Baguette::Log.debug "Still something to read" Baguette::Log.debug "Still something to read"
next next
end end
break break
when Bytes when Bytes
# TODO: when receiving a binary message # TODO: when receiving a binary message
# we should test the format and maybe its content # we should test the format and maybe its content
@ -376,6 +386,17 @@ def websocket_switching_procedure (activefd : Int)
end end
end end
# In case there was a previous messagee within a fragment.
if fb.buffer.size > 0
Baguette::Log.warning "SHOULD reconstitute the message!!"
end
if message.is_a?(String) && fb.buffer.size > 0
Baguette::Log.warning "Reconstitute the message!!"
message = fb.buffer + message
fb.buffer = String.new
end
if Context.context.is_json[activefd] && message.is_a?(String) if Context.context.is_json[activefd] && message.is_a?(String)
if Context.print_messages if Context.print_messages
j = JSON.parse message j = JSON.parse message