summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Huwald <jh@sotun.de>2012-06-06 13:07:14 (GMT)
committerJan Huwald <jh@sotun.de>2012-06-06 13:07:14 (GMT)
commitfb4ff27d8d9ff00a10d9ee52b2e0404323186fc2 (patch)
tree9382a498782d187c36c858e381c49e49e6a4776a
parentf33aa706efbcfd0663a9bda060972081ea47e8f4 (diff)
correctly handle half-open connections
-rw-r--r--ereproxy_server.erl25
1 files changed, 15 insertions, 10 deletions
diff --git a/ereproxy_server.erl b/ereproxy_server.erl
index ef59144..a6e9803 100644
--- a/ereproxy_server.erl
+++ b/ereproxy_server.erl
@@ -1,6 +1,6 @@
-module(ereproxy_server).
-behavior(supervisor).
--export([start_link/1, init/1, start_link_acceptor/2, acceptor/2, con/2, pass_through/1]).
+-export([start_link/1, init/1, start_link_acceptor/2, acceptor/2, con/2, pass_through/2]).
-include("ereproxy_config.hrl").
@@ -36,7 +36,8 @@ tp_t2c(ssl) -> ssl_closed.
%%% listen and accept on a single port
start_link_acceptor(CfgMod, {Method, ListenPort}) ->
- DefaultOpts = [binary, {packet, 0}, {active, false}, {reuseaddr, true}],
+ DefaultOpts = [binary, {packet, 0}, {active, false},
+ {exit_on_close, false}, {reuseaddr, true}],
{TP, Opts} =
case Method of
http -> {tcp, DefaultOpts};
@@ -67,7 +68,8 @@ con(CfgMod, ClientCon = {TP, ClientSock}) ->
{ConHead, HostName} = parse_header(MaxCache, ClientCon),
{Host, Port} = CfgMod:select_destination(HostName),
% connect to destination
- {ok, ServerSock} = gen_tcp:connect(Host, Port, [binary, {packet, 0}, {active, once}]),
+ TCPOpts = [binary, {packet, 0}, {active, once}, {exit_on_close, false}],
+ {ok, ServerSock} = gen_tcp:connect(Host, Port, TCPOpts),
% log redirection details
{ok, {SrcAddr, SrcPort}} = tp(TP, peername, [ClientSock]),
{ok, {RedAddr, RedPort}} = inet:sockname(ServerSock),
@@ -75,7 +77,7 @@ con(CfgMod, ClientCon = {TP, ClientSock}) ->
ereproxy_log ! {{SrcAddr, SrcPort}, {RedAddr, RedPort}, {DstAddr, DstPort}},
% pass through connection
gen_tcp:send(ServerSock, ConHead),
- pass_through([ClientCon, {tcp, ServerSock}]).
+ pass_through([ClientCon, {tcp, ServerSock}], 2).
%% parse_header: search for the "^Host: " field
@@ -114,18 +116,21 @@ parse_header(MaxCache, Con) ->
parse_header(MaxCache, Con, <<>>, <<>>, <<>>).
%% connect client and destination server
-pass_through(Cons) ->
+pass_through(_Cons, 0) ->
+ connections_closed;
+pass_through(Cons, NumOpen) ->
receive
{STP, Src, Data} ->
[{DTP, Dst}] = lists:subtract(Cons, [{STP, Src}]),
ok = tp(STP, setopts, [Src, [{active, once}]]),
ok = tp(DTP, send, [Dst, Data]),
- ?MODULE:pass_through(Cons); % allow code update
+ ?MODULE:pass_through(Cons, NumOpen); % allow code update
{STP_Closed, Src} ->
STP = tp_c2t(STP_Closed),
[{DTP, Dst}] = lists:subtract(Cons, [{STP, Src}]),
- ok = tp(DTP, close, [Dst]),
- connections_closed
- % TODO: check if this is standart compliant; we close both
- % sides if one side closes one channel!
+ ok = case NumOpen of
+ 2 -> tp(DTP, shutdown, [Dst, write]);
+ 1 -> ok
+ end,
+ ?MODULE:pass_through(Cons, NumOpen-1)
end.
contact: Jan Huwald // Impressum