diff --git a/src/fd_ws.erl b/src/fd_ws.erl index 9a8e3fe..365e3da 100644 --- a/src/fd_ws.erl +++ b/src/fd_ws.erl @@ -11,9 +11,8 @@ -export([ handshake/1, - recv/2, - send/2, - pong/1, pong/2 + recv/2, recv/3, + send/2 ]). -include("http.hrl"). @@ -692,35 +691,43 @@ recv_frame_await(Frame, Sock, Received) -> --spec send(Socket, Payload) -> Result - when Socket :: gen_tcp:socket(), - Payload :: iodata(), - Result :: ok - | {error, Reason}, - Reason :: closed | {timeout, RestData} | inet:posix(), - RestData :: binary() | erlang:iovec(). +-spec send(Socket, Message) -> Result + when Socket :: gen_tcp:socket(), + Message :: ws_msg(), + Result :: ok + | {error, Reason}, + Reason :: any(). % @doc -% FIXME: this should be sending a message, not an arbitrary payload -% -% send binary data over Socket. handles frame nonsense -% -% types the payload as bytes +% send message to client over Socket. handles frame nonsense % % max payload size is 2^63 - 1 bytes % @end -send(Socket, Payload) -> - BPayload = unicode:characters_to_binary(Payload), - Frame = payload_to_frame(BPayload), +send(Socket, {Type, Payload}) -> + BPayload = payload_to_binary(Payload), + Frame = message_to_frame(Type, BPayload), send_frame(Socket, Frame). +payload_to_binary(Bin) when is_binary(Bin) -> Bin; +payload_to_binary(X) -> unicode:characters_to_binary(X). -payload_to_frame(Payload) when byte_size(Payload) < ?MAX_PAYLOAD_SIZE -> + +% data messages +message_to_frame(Data, Payload) + when ((Data =:= text) orelse (Data =:= binary)), + is_binary(Payload), + (byte_size(Payload) < ?MAX_PAYLOAD_SIZE) -> #frame{fin = true, - opcode = binary, - mask = false, + opcode = Data, + payload_length = byte_size(Payload), + payload = Payload}; +message_to_frame(Control, Payload) + when ((Control =:= close) orelse (Control =:= ping) orelse (Control =:= pong)), + is_binary(Payload), + (byte_size(Payload) =< 125) -> + #frame{fin = true, + opcode = Control, payload_length = byte_size(Payload), - masking_key = none, payload = Payload}. @@ -749,6 +756,8 @@ send_frame(Sock, Frame) -> % % TODO: this doesn't check/do masking % +% also RSV is always <<0:3>> in rendered frame +% % This is a non-issue as long as this is only used for rendering messages sent % from server to client (unmasked per protocol). However, for debugging % purposes, a user of this library might want to test how frames render with @@ -810,32 +819,3 @@ render_payload_length(Len) when 126 =< Len, Len =< 2#1111_1111_1111_1111 -> <<126:7, Len:16>>; render_payload_length(Len) when (1 bsl 16) =< Len, Len < ?MAX_PAYLOAD_SIZE -> <<127:7, Len:64>>. - - - --spec pong(Socket) -> Result - when Socket :: gen_tcp:socket(), - Result :: ok - | {error, Reason}, - Reason :: closed | {timeout, RestData} | inet:posix(), - RestData :: binary() | erlang:iovec(). - -pong(Sock) -> - pong(Sock, <<>>). - - - --spec pong(Socket, Payload) -> Result - when Socket :: gen_tcp:socket(), - Payload :: binary(), - Result :: ok - | {error, Reason}, - Reason :: closed | {timeout, RestData} | inet:posix(), - RestData :: binary() | erlang:iovec(). - -pong(Sock, Payload) when is_binary(Payload), byte_size(Payload) < ?MAX_PAYLOAD_SIZE -> - Frame = #frame{fin = true, - opcode = pong, - payload_length = byte_size(Payload), - payload = Payload}, - send_frame(Sock, Frame).