diff --git a/src/lib_modifications.cr b/src/lib_modifications.cr index bc69f83..f97a51e 100644 --- a/src/lib_modifications.cr +++ b/src/lib_modifications.cr @@ -38,7 +38,14 @@ class HTTP::WebSocket record Pong record Close record Error - record NotFinal + # record NotFinal + + struct NotFinal + property message : String + property info : Protocol::PacketInfo + def initialize(@message, @info) + end + end # :nodoc: 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) @current_message.clear return String.new message + else + return NotFinal.new String.new(message), info end when Protocol::Opcode::BINARY message = @buffer[0, info.size] @@ -93,7 +102,7 @@ class HTTP::WebSocket end end - return NotFinal.new + raise "what the fuck?" end # Returns the websocket instance. diff --git a/src/websocketd.cr b/src/websocketd.cr index a6d7f89..5240d75 100644 --- a/src/websocketd.cr +++ b/src/websocketd.cr @@ -290,15 +290,21 @@ def websocket_connection_procedure (requested_service : String, clientfd : Int32 end end +class FragmentBuffer + property buffer : String = String.new +end + def websocket_switching_procedure (activefd : Int) begin Baguette::Log.title "activefd is #{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 client = Context.context.fd_to_tcpsocket[activefd] wsclient = Context.context.fd_to_websocket[activefd] + fb = FragmentBuffer.new + loop do begin message = wsclient.run_once @@ -358,14 +364,18 @@ def websocket_switching_procedure (activefd : Int) next end break + when WebSocket::NotFinal - Baguette::Log.warning "Received only part of a message (not supported)" - pp! + Baguette::Log.warning "Received only part of a message" + # TODO: check if the message is OK when multiplexing + # pp! message + fb.buffer = fb.buffer + message.message if still_something_to_read Baguette::Log.debug "Still something to read" next end break + when Bytes # TODO: when receiving a binary message # we should test the format and maybe its content @@ -376,6 +386,17 @@ def websocket_switching_procedure (activefd : Int) 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.print_messages j = JSON.parse message