Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ff257ae976 | |||
| e12466d5f2 |
@ -1,3 +1,10 @@
|
||||
OPEN LOOPS - 2025-11-12
|
||||
- websockets
|
||||
- separate websocket handling from websocket parsing/sending
|
||||
- do renaming
|
||||
- make wfc not terrible
|
||||
|
||||
|
||||
VIDEO 1 - 2025-09-16
|
||||
TODONE
|
||||
- add qhl as dep
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
%%% See: http://erlang.org/doc/apps/kernel/application.html
|
||||
%%% @end
|
||||
|
||||
-module(fd_clients).
|
||||
-module(fd_http).
|
||||
-vsn("0.1.0").
|
||||
-behavior(supervisor).
|
||||
-author("Peter Harpending <peterharpending@qpq.swiss>").
|
||||
@ -32,17 +32,17 @@ start_link() ->
|
||||
|
||||
init(none) ->
|
||||
RestartStrategy = {rest_for_one, 1, 60},
|
||||
ClientMan = {fd_client_man,
|
||||
{fd_client_man, start_link, []},
|
||||
permanent,
|
||||
5000,
|
||||
worker,
|
||||
[fd_client_man]},
|
||||
ClientSup = {fd_client_sup,
|
||||
{fd_client_sup, start_link, []},
|
||||
permanent,
|
||||
5000,
|
||||
supervisor,
|
||||
[fd_client_sup]},
|
||||
Children = [ClientSup, ClientMan],
|
||||
HttpClientMan = {fd_http_client_man,
|
||||
{fd_http_client_man, start_link, []},
|
||||
permanent,
|
||||
5000,
|
||||
worker,
|
||||
[fd_http_client_man]},
|
||||
HttpClientSup = {fd_http_client_sup,
|
||||
{fd_http_client_sup, start_link, []},
|
||||
permanent,
|
||||
5000,
|
||||
supervisor,
|
||||
[fd_http_client_sup]},
|
||||
Children = [HttpClientSup, HttpClientMan],
|
||||
{ok, {RestartStrategy, Children}}.
|
||||
@ -13,7 +13,7 @@
|
||||
%%% http://erlang.org/doc/design_principles/spec_proc.html
|
||||
%%% @end
|
||||
|
||||
-module(fd_client).
|
||||
-module(fd_http_client).
|
||||
-vsn("0.1.0").
|
||||
-author("Peter Harpending <peterharpending@qpq.swiss>").
|
||||
-copyright("Peter Harpending <peterharpending@qpq.swiss>").
|
||||
@ -291,7 +291,7 @@ respond_static(Sock, not_found) ->
|
||||
NewReceived :: binary().
|
||||
|
||||
ws_tetris(Sock, Request, Received) ->
|
||||
.
|
||||
error(nyi).
|
||||
|
||||
|
||||
|
||||
@ -303,7 +303,7 @@ ws_tetris(Sock, Request, Received) ->
|
||||
|
||||
ws_tetris2(Sock, Request, Received) ->
|
||||
%tell("~p: ws_tetris request: ~tp", [?LINE, Request]),
|
||||
case fd_ws:handshake(Request) of
|
||||
case qhl_ws:handshake(Request) of
|
||||
{ok, Response} ->
|
||||
fd_http_utils:respond(Sock, Response),
|
||||
{ok, TetrisPid} = fd_tetris:start_link(),
|
||||
@ -317,7 +317,7 @@ ws_tetris2(Sock, Request, Received) ->
|
||||
-spec ws_tetris_loop(Sock, Tetris, Frames, Received) -> NewReceived
|
||||
when Sock :: gen_tcp:socket(),
|
||||
Tetris :: pid(),
|
||||
Frames :: [fd_ws:frame()],
|
||||
Frames :: [qhl_ws:frame()],
|
||||
Received :: binary(),
|
||||
NewReceived :: binary().
|
||||
|
||||
@ -329,7 +329,7 @@ ws_tetris_loop(Sock, Tetris, Frames, Received) ->
|
||||
receive
|
||||
{tcp, Sock, Bin} ->
|
||||
Rcv1 = <<Received/binary, Bin/binary>>,
|
||||
case fd_ws:recv(Sock, Rcv1, 3_000, Frames) of
|
||||
case qhl_ws:recv(Sock, Rcv1, 3_000, Frames) of
|
||||
{ok, WsMsg, NewFrames, Rcv2} ->
|
||||
ok = fd_tetris:ws_msg(Tetris, WsMsg),
|
||||
ws_tetris_loop(Sock, Tetris, NewFrames, Rcv2);
|
||||
@ -338,7 +338,7 @@ ws_tetris_loop(Sock, Tetris, Frames, Received) ->
|
||||
end;
|
||||
{tetris, Message} ->
|
||||
ok = log(info, "~p tetris: ~p", [self(), Message]),
|
||||
ok = fd_ws:send(Sock, {text, Message}),
|
||||
ok = qhl_ws:send(Sock, {text, Message}),
|
||||
ws_tetris_loop(Sock, Tetris, Frames, Received);
|
||||
{tcp_closed, Sock} -> {error, tcp_closed};
|
||||
{tcp_error, Sock, Reason} -> {error, {tcp_error, Reason}}
|
||||
@ -363,7 +363,7 @@ ws_echo(Sock, Request) ->
|
||||
end.
|
||||
|
||||
ws_echo2(Sock, Request) ->
|
||||
case fd_ws:handshake(Request) of
|
||||
case qhl_ws:handshake(Request) of
|
||||
{ok, Response} ->
|
||||
fd_http_utils:respond(Sock, Response),
|
||||
ws_echo_loop(Sock);
|
||||
@ -377,15 +377,15 @@ ws_echo_loop(Sock) ->
|
||||
|
||||
ws_echo_loop(Sock, Frames, Received) ->
|
||||
tell("~p ws_echo_loop(Sock, ~tp, ~tp)", [self(), Frames, Received]),
|
||||
case fd_ws:recv(Sock, Received, 5*fd_ws:min(), Frames) of
|
||||
case qhl_ws:recv(Sock, Received, 5*qhl_ws:min(), Frames) of
|
||||
{ok, Message, NewFrames, NewReceived} ->
|
||||
tell("~p echo message: ~tp", [self(), Message]),
|
||||
% send the same message back
|
||||
ok = fd_ws:send(Sock, Message),
|
||||
ok = qhl_ws:send(Sock, Message),
|
||||
ws_echo_loop(Sock, NewFrames, NewReceived);
|
||||
Error ->
|
||||
tell(error, "ws_echo_loop: error: ~tp", [Error]),
|
||||
fd_ws:send(Sock, {close, <<>>}),
|
||||
qhl_ws:send(Sock, {close, <<>>}),
|
||||
error(Error)
|
||||
end.
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
%%% OTP should take care of for us.
|
||||
%%% @end
|
||||
|
||||
-module(fd_client_man).
|
||||
-module(fd_http_client_man).
|
||||
-vsn("0.1.0").
|
||||
-behavior(gen_server).
|
||||
-author("Peter Harpending <peterharpending@qpq.swiss>").
|
||||
@ -13,7 +13,7 @@
|
||||
%%% http://erlang.org/doc/design_principles/sup_princ.html#id79244
|
||||
%%% @end
|
||||
|
||||
-module(fd_client_sup).
|
||||
-module(fd_http_client_sup).
|
||||
-vsn("0.1.0").
|
||||
-behaviour(supervisor).
|
||||
-author("Peter Harpending <peterharpending@qpq.swiss>").
|
||||
@ -7,7 +7,10 @@
|
||||
http_err/2,
|
||||
respond/2,
|
||||
fmtresp/1
|
||||
])
|
||||
]).
|
||||
|
||||
-include("http.hrl").
|
||||
-include("$zx_include/zx_logger.hrl").
|
||||
|
||||
|
||||
-spec new_cookie() -> Cookie
|
||||
|
||||
@ -36,8 +36,8 @@ start_link() ->
|
||||
|
||||
init([]) ->
|
||||
RestartStrategy = {one_for_one, 1, 60},
|
||||
Clients = {fd_clients,
|
||||
{fd_clients, start_link, []},
|
||||
Httpd = {fd_http,
|
||||
{fd_http, start_link, []},
|
||||
permanent,
|
||||
5000,
|
||||
supervisor,
|
||||
@ -60,5 +60,5 @@ init([]) ->
|
||||
5000,
|
||||
worker,
|
||||
[fd_cache]},
|
||||
Children = [Clients, Chat, FileCache, Cache],
|
||||
Children = [Httpd, Chat, FileCache, Cache],
|
||||
{ok, {RestartStrategy, Children}}.
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
|
||||
-spec ws_msg(Tetris, Message) -> ok
|
||||
when Tetris :: pid(),
|
||||
Message :: fd_ws:ws_msg().
|
||||
Message :: qhl_ws:ws_msg().
|
||||
|
||||
ws_msg(Tetris, Msg) ->
|
||||
gen_server:cast(Tetris, {ws_msg, Msg}).
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
% hands the TCP socket over to this process, also this process does the
|
||||
% handshake.
|
||||
%
|
||||
% this process sends back `{ws, self(), Message: fd_ws:ws_msg()}'
|
||||
% this process sends back `{ws, self(), Message: qhl_ws:ws_msg()}'
|
||||
%
|
||||
% for each websocket message it gets
|
||||
-module(fd_wsp).
|
||||
@ -16,8 +16,8 @@
|
||||
|
||||
-export([
|
||||
%% caller context
|
||||
handshake/0,
|
||||
start_link/0,
|
||||
%handshake/0,
|
||||
start_link/3,
|
||||
|
||||
%% process context
|
||||
init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
@ -27,7 +27,7 @@
|
||||
-include("http.hrl").
|
||||
-include("$zx_include/zx_logger.hrl").
|
||||
|
||||
-record(s, {socket :: gen_tcp:socket()})
|
||||
-record(s, {socket :: gen_tcp:socket()}).
|
||||
-type state() :: #s{}.
|
||||
|
||||
|
||||
@ -63,13 +63,14 @@ start_link(Socket, HandshakeReq, Received) ->
|
||||
|
||||
init([Socket, HandshakeReq, Received]) ->
|
||||
log("~p:~p init", [?MODULE, self()]),
|
||||
case fd_ws:handshake(HandshakeReq) of
|
||||
case qhl_ws:handshake(HandshakeReq) of
|
||||
{ok, Response} ->
|
||||
ok = fd_http_utils:respond(Sock, Response),
|
||||
ok = fd_http_utils:respond(Socket, Response),
|
||||
InitState = #s{socket = Socket},
|
||||
{ok, InitState};
|
||||
Error ->
|
||||
tell("~p:~p websocket handshake err: ~p", [?MODULE, self(), Error]),
|
||||
fd_http_utils:http_err(Socket, 400)
|
||||
fd_http_utils:http_err(Socket, 400),
|
||||
Error
|
||||
end.
|
||||
|
||||
@ -85,6 +86,7 @@ handle_cast(Unexpected, State) ->
|
||||
|
||||
|
||||
handle_info({tcp, Sock, Bytes}, State = #s{socket = Sock}) ->
|
||||
{noreply, State};
|
||||
handle_info(Unexpected, State) ->
|
||||
tell("~tp: unexpected info: ~tp", [?MODULE, Unexpected]),
|
||||
{noreply, State}.
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
%% Returns an {error, Reason} tuple if it is already listening.
|
||||
|
||||
listen(PortNum) ->
|
||||
fd_client_man:listen(PortNum).
|
||||
fd_http:listen(PortNum).
|
||||
|
||||
|
||||
-spec ignore() -> ok.
|
||||
@ -32,7 +32,7 @@ listen(PortNum) ->
|
||||
%% Make the server stop listening if it is, or continue to do nothing if it isn't.
|
||||
|
||||
ignore() ->
|
||||
fd_client_man:ignore().
|
||||
fd_http:ignore().
|
||||
|
||||
|
||||
-spec start(normal, term()) -> {ok, pid()}.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
% @doc websockets
|
||||
%
|
||||
% ref: https://datatracker.ietf.org/doc/html/rfc6455
|
||||
-module(fd_ws).
|
||||
-module(qhl_ws).
|
||||
|
||||
-export_type([
|
||||
opcode/0,
|
||||
@ -19,7 +19,6 @@
|
||||
]).
|
||||
|
||||
-include("http.hrl").
|
||||
-include("$zx_include/zx_logger.hrl").
|
||||
|
||||
|
||||
-define(MAX_PAYLOAD_SIZE, ((1 bsl 63) - 1)).
|
||||
@ -632,11 +631,8 @@ recv_frame_await(Frame, Sock, Received, Timeout) ->
|
||||
% @end
|
||||
|
||||
send(Socket, {Type, Payload}) ->
|
||||
log(info, "fd_ws: send(~tp, {~tp, ~tp})", [Socket, Type, Payload]),
|
||||
BPayload = payload_to_binary(Payload),
|
||||
log(info, "fd_ws: BPayload = ~tp", [BPayload]),
|
||||
Frame = message_to_frame(Type, BPayload),
|
||||
log(info, "fd_ws: Frame = ~tp", [Frame]),
|
||||
send_frame(Socket, Frame).
|
||||
|
||||
payload_to_binary(Bin) when is_binary(Bin) -> Bin;
|
||||
@ -675,7 +671,6 @@ message_to_frame(Control, Payload)
|
||||
|
||||
send_frame(Sock, Frame) ->
|
||||
Binary = render_frame(Frame),
|
||||
log(info, "send_frame: rendered frame: ~tp", [Binary]),
|
||||
gen_tcp:send(Sock, Binary).
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user