59 lines
1.5 KiB
Erlang
59 lines
1.5 KiB
Erlang
% Copyright (c) Camden Dixie O'Brien
|
|
% SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
-module(tcp_server).
|
|
-behaviour(gen_server).
|
|
|
|
-export([start_link/2]).
|
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
|
terminate/2, code_change/3]).
|
|
|
|
-record(state, {socket, acceptor}).
|
|
|
|
start_link(Port, CertDir) ->
|
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [Port, CertDir], []).
|
|
|
|
init([Port, CertDir]) ->
|
|
TcpOpts = [binary, inet6, {active, false}, {reuseaddr, true}],
|
|
SslOpts = [{certfile, filename:join([CertDir, "server.pem"])},
|
|
{cacertfile, filename:join([CertDir, "ca.pem"])},
|
|
{verify, verify_peer},
|
|
{fail_if_no_peer_cert, true}],
|
|
{ok, Socket} = ssl:listen(Port, TcpOpts ++ SslOpts),
|
|
self() ! accept,
|
|
{ok, #state{socket = Socket}}.
|
|
|
|
handle_call(_Request, _From, State) ->
|
|
{reply, ok, State}.
|
|
|
|
handle_cast(_Msg, State) ->
|
|
{noreply, 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, 5000) 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}) ->
|
|
ssl:close(Socket),
|
|
ok.
|
|
|
|
code_change(_OldVsn, State, _Extra) ->
|
|
{ok, State}.
|