Implement demo of DER comms
This commit is contained in:
@@ -11,10 +11,16 @@ start_link(Port, CertDir) ->
|
||||
supervisor:start_link({local, ?MODULE}, ?MODULE, [Port, CertDir]).
|
||||
|
||||
init([Port, CertDir]) ->
|
||||
SupFlags = #{stragegy => one_for_all,
|
||||
SupFlags = #{stragegy => one_for_one,
|
||||
intensity => 1,
|
||||
period => 5},
|
||||
ChildSpecs = [#{id => tcp_server,
|
||||
ChildSpecs = [#{id => session_sup,
|
||||
start => {session_sup, start_link, []},
|
||||
restart => permanent,
|
||||
shutdown => 5000,
|
||||
type => supervisor,
|
||||
modules => [session_sup]},
|
||||
#{id => tcp_server,
|
||||
start => {tcp_server, start_link, [Port, CertDir]},
|
||||
restart => permanent,
|
||||
shutdown => 5000,
|
||||
|
||||
42
server/src/session_server.erl
Normal file
42
server/src/session_server.erl
Normal file
@@ -0,0 +1,42 @@
|
||||
% Copyright (c) Camden Dixie O'Brien
|
||||
% SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
-module(session_server).
|
||||
-behaviour(gen_server).
|
||||
|
||||
-export([start_link/1]).
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
|
||||
start_link(Socket) ->
|
||||
gen_server:start_link(?MODULE, Socket, []).
|
||||
|
||||
init(Socket) ->
|
||||
ssl:setopts(Socket, [{active, true}]),
|
||||
{ok, #{socket => Socket}}.
|
||||
|
||||
handle_call(_Request, _From, State) ->
|
||||
{reply, ok, State}.
|
||||
|
||||
handle_cast(_Msg, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
handle_info({ssl, Socket, Data}, State) ->
|
||||
case 'StudySystemProtocol':decode('Request', Data) of
|
||||
{ok, {foo, _}} ->
|
||||
{ok, Encoded}
|
||||
= 'StudySystemProtocol':encode('Response', {msg, "Foo"}),
|
||||
ssl:send(Socket, Encoded);
|
||||
Result ->
|
||||
io:format("Invalid message: ~p~n", [Result]),
|
||||
ok
|
||||
end,
|
||||
{noreply, State};
|
||||
handle_info(_Info, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
terminate(_Reason, #{socket := Socket}) ->
|
||||
ssl:close(Socket).
|
||||
|
||||
code_change(_OldVsn, State, _Extra) ->
|
||||
{ok, State}.
|
||||
25
server/src/session_sup.erl
Normal file
25
server/src/session_sup.erl
Normal file
@@ -0,0 +1,25 @@
|
||||
% Copyright (c) Camden Dixie O'Brien
|
||||
% SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
-module(session_sup).
|
||||
-behaviour(supervisor).
|
||||
|
||||
-export([start_link/0, init/1, start_session/1]).
|
||||
|
||||
start_link() ->
|
||||
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
||||
|
||||
init([]) ->
|
||||
SupFlags = #{strategy => simple_one_for_one,
|
||||
intensity => 10,
|
||||
period => 1},
|
||||
ChildSpec = #{id => session_server,
|
||||
start => {session_server, start_link, []},
|
||||
restart => temporary,
|
||||
shutdown => 5000,
|
||||
type => worker,
|
||||
modules => [session_server]},
|
||||
{ok, {SupFlags, [ChildSpec]}}.
|
||||
|
||||
start_session(Socket) ->
|
||||
supervisor:start_child(?MODULE, [Socket]).
|
||||
@@ -20,8 +20,8 @@ init([Port, CertDir]) ->
|
||||
{verify, verify_peer},
|
||||
{fail_if_no_peer_cert, true}],
|
||||
{ok, Socket} = ssl:listen(Port, TcpOpts ++ SslOpts),
|
||||
Pid = spawn_link(fun() -> acceptor_loop(Socket) end),
|
||||
{ok, #state{socket = Socket, acceptor = Pid}}.
|
||||
self() ! accept,
|
||||
{ok, #state{socket = Socket}}.
|
||||
|
||||
handle_call(_Request, _From, State) ->
|
||||
{reply, ok, State}.
|
||||
@@ -29,46 +29,30 @@ handle_call(_Request, _From, State) ->
|
||||
handle_cast(_Msg, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
handle_info({'EXIT', Pid, Reason}, State = #state{acceptor = Pid}) ->
|
||||
{stop, {acceptor_died, Reason}, State};
|
||||
handle_info(accept, State = #state{socket = Socket}) ->
|
||||
case ssl:transport_accept(Socket) of
|
||||
{ok, TlsSocket} ->
|
||||
self() ! {handshake, TlsSocket},
|
||||
self() ! accept;
|
||||
{error, closed} ->
|
||||
ok
|
||||
end,
|
||||
{noreply, State};
|
||||
handle_info({handshake, TlsSocket}, State) ->
|
||||
case ssl:handshake(TlsSocket) of
|
||||
{ok, ClientSocket} ->
|
||||
{ok, Pid} = session_sup:start_session(ClientSocket),
|
||||
ok = ssl:controlling_process(ClientSocket, Pid);
|
||||
{error, _Reason} ->
|
||||
ok
|
||||
end,
|
||||
{noreply, State};
|
||||
handle_info(_Info, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
terminate(_Reason, #state{socket = Socket}) ->
|
||||
gen_tcp:close(Socket),
|
||||
ssl:close(Socket),
|
||||
ok.
|
||||
|
||||
code_change(_OldVsn, State, _Extra) ->
|
||||
{ok, State}.
|
||||
|
||||
acceptor_loop(Socket) ->
|
||||
case ssl:transport_accept(Socket) of
|
||||
{ok, TlsSocket} ->
|
||||
case ssl:handshake(TlsSocket) of
|
||||
{ok, ClientSocket} ->
|
||||
Pid = spawn(
|
||||
fun() -> handle_connection(ClientSocket) end),
|
||||
ok = ssl:controlling_process(ClientSocket, Pid),
|
||||
acceptor_loop(Socket);
|
||||
{error, _Reason} ->
|
||||
acceptor_loop(Socket)
|
||||
end;
|
||||
{error, closed} ->
|
||||
ok
|
||||
end.
|
||||
|
||||
handle_connection(Socket) ->
|
||||
ssl:setopts(Socket, [{active, true}]),
|
||||
handle_connection_loop(Socket).
|
||||
|
||||
handle_connection_loop(Socket) ->
|
||||
receive
|
||||
{ssl, Socket, Data} ->
|
||||
handle_client_msg(Socket, Data),
|
||||
handle_connection_loop(Socket);
|
||||
{ssl_closed, Socket} ->
|
||||
ok
|
||||
end.
|
||||
|
||||
handle_client_msg(Socket, Msg) ->
|
||||
ssl:send(Socket, Msg).
|
||||
|
||||
Reference in New Issue
Block a user