Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
better accept state h/t @seancribbs
  • Loading branch information
joedevivo committed Sep 1, 2015
1 parent af6825e commit cb16fd6
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 41 deletions.
5 changes: 3 additions & 2 deletions include/http2.hrl
Expand Up @@ -187,15 +187,16 @@


-type transport() :: gen_tcp | ssl.
-type socket() :: {gen_tcp, gen_tcp:socket()} | {ssl, ssl:sslsocket()}.
-type socket() :: {gen_tcp, gen_tcp:socket()|undefined} | {ssl, ssl:sslsocket()|undefined}.

-define(PREAMBLE, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n").

-define(DEFAULT_INITIAL_WINDOW_SIZE, 65535).


-record(connection_state, {
listen_socket :: socket(),
ssl_options = [],
listen_ref :: non_neg_integer(),
socket = undefined :: undefined | socket(),
send_settings = #settings{} :: settings(),
recv_settings = #settings{} :: settings(),
Expand Down
14 changes: 7 additions & 7 deletions src/chatterbox_sup.erl
Expand Up @@ -13,27 +13,27 @@ start_link() ->

init([]) ->
{ok, Port} = application:get_env(port),
ListenerOptions = [
Options = [
binary,
{reuseaddr, true},
{packet, raw},
{backlog, 1024},
{active, false}
],
{ok, SSLEnabled} = application:get_env(ssl),
{Transport, Options} = case SSLEnabled of
{Transport, SSLOptions} = case SSLEnabled of
true ->
{ok, SSLOptions} = application:get_env(ssl_options),
{ssl, ListenerOptions ++ SSLOptions};
{ok, SSLOpts} = application:get_env(ssl_options),
{ssl, SSLOpts};
false ->
{gen_tcp, ListenerOptions}
{gen_tcp, []}
end,

spawn_link(fun empty_listeners/0),
{ok, ListenSocket} = Transport:listen(Port, Options),
{ok, ListenSocket} = gen_tcp:listen(Port, Options),
Restart = {simple_one_for_one, 60, 3600},
Children = [{socket,
{http2_connection, start_link, [{Transport, ListenSocket}]}, % pass the socket!
{http2_connection, start_link, [[{Transport, ListenSocket}, SSLOptions]]}, % pass the socket!
temporary, 1000, worker, [http2_connection]}],
{ok, {Restart, Children}}.

Expand Down
71 changes: 40 additions & 31 deletions src/http2_connection.erl
Expand Up @@ -24,7 +24,7 @@
terminate/3
]).

-export([accept/2,
-export([handshake/2,
connected/2,
continuation/2,
closing/2
Expand Down Expand Up @@ -63,41 +63,25 @@ send_promise(Pid, StreamId, NewStreamId, Headers) ->
gen_fsm:send_all_state_event(Pid, {send_promise, StreamId, NewStreamId, Headers}),
ok.

-spec init(socket()) ->
{ok, accept, #connection_state{}, non_neg_integer()}.
init({Transport, ListenSocket}) ->
-spec init([socket() | term()]) ->
{ok, accept, #connection_state{}}.
init([{Transport, ListenSocket}, SSLOptions]) ->
{ok, Ref} = prim_inet:async_accept(ListenSocket, -1),
{ok,
accept,
#connection_state{listen_socket={Transport, ListenSocket}},
0}.
#connection_state{
listen_ref=Ref,
socket = {Transport, undefined},
ssl_options = SSLOptions
}}.

%% accepting connection state:
-spec accept(timeout, #connection_state{}) ->
-spec handshake(timeout, #connection_state{}) ->
{next_state, connected|closing, #connection_state{}, non_neg_integer()}.
accept(timeout,
InitialState=#connection_state{listen_socket={Transport, ListenSocket}}) ->
Socket = case Transport of
gen_tcp ->
%%TCP Version
{ok, AcceptSocket} = Transport:accept(ListenSocket),
AcceptSocket;
ssl ->
%% SSL conditional stuff
{ok, AcceptSocket} = Transport:transport_accept(ListenSocket),
_Accept = ssl:ssl_accept(AcceptSocket),
%% TODO: Erlang 18 uses ALPN
{ok, _Upgrayedd} = ssl:negotiated_next_protocol(AcceptSocket),
AcceptSocket
end,

StateWithSocket = InitialState#connection_state{
socket={Transport, Socket}
},

%% Start up a listening socket to take the place of this socket,
%% that's no longer listening
chatterbox_sup:start_socket(),

handshake(timeout,
StateWithSocket=#connection_state{
socket={Transport, Socket}
}) ->
case Transport:recv(Socket, length(?PREAMBLE), 5000) of
{ok, <<?PREAMBLE>>} ->
%% From Section 6.5 of the HTTP/2 Specification A SETTINGS
Expand Down Expand Up @@ -603,6 +587,31 @@ handle_sync_event(is_push, _F, StateName,
handle_sync_event(_E, _F, StateName, State) ->
{next_state, StateName, State, 0}.

handle_info({inet_async, _ListSock, Ref, {ok, CliSocket}},
accept,
S=#connection_state{
ssl_options = SSLOptions,
socket = {Transport, undefined},
listen_ref = Ref
}) ->
inet_db:register_socket(CliSocket, inet_tcp),
Socket = case Transport of
gen_tcp ->
CliSocket;
ssl ->
{ok, AcceptSocket} = ssl:ssl_accept(CliSocket, SSLOptions),
%% TODO: Erlang 18 uses ALPN
{ok, _Upgrayedd} = ssl:negotiated_next_protocol(AcceptSocket),
AcceptSocket
end,
chatterbox_sup:start_socket(),

{next_state,
handshake,
S#connection_state{
socket = {Transport, Socket}
},
0};
%% TODO: Handle_info when ssl socket is closed
handle_info({tcp_closed, _Socket}, _StateName, S) ->
lager:debug("tcp_close"),
Expand Down
2 changes: 1 addition & 1 deletion test/chatterbox_test_buddy.erl
Expand Up @@ -16,7 +16,7 @@ start(Config) ->
{versions, ['tlsv1.2']},
{next_protocols_advertised, [<<"h2">>]}]}
],
io:format("Settings ~p", [Settings]),
ct:pal("Settings ~p", [Settings]),
[ok = application:set_env(chatterbox, Key, Value) || {Key, Value} <- Settings ],
{ok, List} = application:ensure_all_started(chatterbox),
ct:pal("Started: ~p", [List]),
Expand Down

0 comments on commit cb16fd6

Please sign in to comment.