Note that there are some explanatory texts on larger screens.

plurals
  1. POError in my implementation of websocket in Erlang socket close
    primarykey
    data
    text
    <p>I am new in Erlang. I need write a implementation of RFC6455 (websocket) as server in Erlang, I write all for can respond with HTTP 101, and I think that accept header is good because I try calculate with example of RFC6455 and example of wikipedia and result is same. When I send HTTP 101 in browser run event onerror of websocket and in server I don't close socket but I see that socket is closed. I have this code:</p> <p><code>edumserver.erl</code>:</p> <pre><code>-module(edumserver). -export([start/0]). start() -&gt; ssl:start(), crypto:start(), edumhttpsserver:start(8883). </code></pre> <p><code>edumhttpsserver.erl</code>:</p> <pre><code>-module(edumhttpsserver). -export([start/1]). -define(RESP_404, &lt;&lt;"HTTP/1.1 404 Not Found Server: eDum Connection: Close "&gt;&gt;). -define(RESP_200, &lt;&lt;"HTTP/1.1 200 OK Server: eDum Connection: Close Content-type: "&gt;&gt;). start(Puerto) -&gt; spawn(fun() -&gt; edum_https_init(Puerto) end). edum_https_init(Puerto) -&gt; Op = [{certfile,"priv/server.crt"}, {keyfile, "priv/server.key"}, {reuseaddr, true}, {active, false}, {packet, http}], {ok, Socket} = ssl:listen(Puerto, Op), edum_https_bucle(Socket). edum_https_bucle(Socket) -&gt; {ok, SockCli} = ssl:transport_accept(Socket), Pid = spawn(fun() -&gt; edum_https_cliente(SockCli, []) end), ssl:controlling_process(SockCli, Pid), ssl:setopts(SockCli, [{active, true}]), edum_https_bucle(Socket). edum_https_cliente(Socket, Estado) -&gt; receive {ssl, Socket, {http_request, Metodo, {abs_path, Ruta}, _}} -&gt; edum_https_cliente(Socket, Estado ++ [ {method, Metodo}, {path, Ruta}, {secure, true} ]); {ssl, Socket, {http_header, _, Clave, _, Valor}} -&gt; edum_https_cliente(Socket, Estado ++ [{Clave, Valor}]); {ssl, Socket, http_eoh} -&gt; io:format("Estado: ~p~n", [Estado]), case proplists:get_value('Upgrade', Estado) of "websocket" -&gt; edumwebsocketserver:edum_websocket_cliente(Socket, Estado); _ -&gt; Respuesta = edum_https_send_file(Estado), ssl:send(Socket, Respuesta), ssl:close(Socket) end; {ssl_closed, Socket} -&gt; ssl:close(Socket); {ssl, _, {http_error, Msg}} -&gt; io:format("Error HTTP: ~s~n", [Msg]); Any -&gt; io:format("No reconocido ~p~n", [Any]), ssl:close(Socket) end. edum_https_send_file(Peticion) -&gt; "/" ++ Ruta = proplists:get_value(path, Peticion, "/"), {ok, CWD} = file:get_cwd(), JRuta = filename:join(CWD, "priv/html"), RRuta = filename:join(JRuta, Ruta), case file:read_file(RRuta) of {ok, Contenido} -&gt; Peso = list_to_binary( io_lib:format("~p", [byte_size(Contenido)]) ), Tipo = edum_https_tipomime(Ruta), &lt;&lt; ?RESP_200/binary, Tipo/binary, "\nContent-lenght: ", Peso/binary, "\r\n\r\n", Contenido/binary &gt;&gt;; {error, _} -&gt; ?RESP_404 end. edum_https_tipomime(Archivo) -&gt; case filename:extension(string:to_lower(Archivo)) of ".htm" -&gt; &lt;&lt;"text/html"&gt;&gt;; ".html" -&gt; &lt;&lt;"text/html"&gt;&gt;; ".js" -&gt; &lt;&lt;"application/javascript"&gt;&gt;; ".css" -&gt; &lt;&lt;"text/css"&gt;&gt;; _ -&gt; &lt;&lt;"text/plain"&gt;&gt; end. </code></pre> <p><code>edumwebsocketserver.erl</code>:</p> <pre><code>-module(edumwebsocketserver). -export([edum_websocket_cliente/2]). -define(RESP_101, &lt;&lt;"HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: "&gt;&gt;). -define(WS_UUID, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"). edum_websocket_cliente(Socket, Estado) -&gt; WSClave = proplists:get_value("Sec-Websocket-Key", Estado), WSAceptar = base64:encode(crypto:sha(WSClave ++ ?WS_UUID)), Respuesta = &lt;&lt;?RESP_101/binary, WSAceptar/binary,"\r\n\r\n"&gt;&gt;, ssl:setopts(Socket, [{keepalive, true}]), ssl:send(Socket, Respuesta), edum_websocket_cliente_bucle(Socket). edum_websocket_cliente_bucle(Socket) -&gt; EstadoSocket = ssl:connection_info(Socket), io:format("WS ~p ~p~n", [self(), EstadoSocket]), case EstadoSocket of {error, Razon} -&gt; ssl:close(Socket), exit(Razon); _ -&gt; ok end, receive {ssl_closed, Socket} -&gt; ssl:close(Socket); Any -&gt; io:format("WS: ~p~n", [Any]) after 5000 -&gt; io:format("Nada~n") end, edum_websocket_cliente_bucle(Socket). </code></pre> <p>And in function <code>edum_websocket_cliente_bucle(Socket)</code> in line <code>io:format("WS ~p ~p~n", [self(), EstadoSocket])</code> I look first the socket good and in next recursive call I look error: <code>{error,closed}</code></p> <p>But I don't close and don't understand why close, I calc accept header with:</p> <pre><code>WSAceptar = base64:encode(crypto:sha(WSClave ++ ?WS_UUID)), </code></pre> <p>That I test with this examples:</p> <blockquote> <p>Concretely, if as in the example above, the |Sec-WebSocket-Key| header field had the value "dGhlIHNhbXBsZSBub25jZQ==", the server would concatenate the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" to form the string "dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11". The server would then take the SHA-1 hash of this, giving the value 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea. This value is then base64-encoded (see Section 4 of [RFC4648]), to give the value "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=". This value would then be echoed in the |Sec-WebSocket-Accept| header field.</p> </blockquote> <p>And:</p> <blockquote> <p>GET /mychat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat Sec-WebSocket-Version: 13 Origin: <a href="http://example.com" rel="nofollow">http://example.com</a></p> <p>HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat</p> </blockquote> <p>What is the bug? I am new in Erlang. In chromium console say this error: "Status line does not end with CRLF".</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload