24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-06-06 21:37:17 +02:00

Support gen_tcp send timeout: Close the connection if the other end has disconnected ungracefully or cannot keep up with the rate at which we are sending data (EJAB-926)

SVN Revision: 2671
This commit is contained in:
Mickaël Rémond 2009-10-19 09:36:23 +00:00
parent f86318a179
commit 006515020a
4 changed files with 31 additions and 8 deletions

View File

@ -132,6 +132,7 @@ init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
{reuseaddr, true}, {reuseaddr, true},
{nodelay, true}, {nodelay, true},
{send_timeout, ?TCP_SEND_TIMEOUT}, {send_timeout, ?TCP_SEND_TIMEOUT},
{send_timeout_close, true},
{keepalive, true} | {keepalive, true} |
SockOpts]), SockOpts]),
case Res of case Res of

View File

@ -268,6 +268,7 @@ open_socket2(Type, Addr, Port) ->
case (catch ejabberd_socket:connect(Addr, Port, case (catch ejabberd_socket:connect(Addr, Port,
[binary, {packet, 0}, [binary, {packet, 0},
{send_timeout, ?TCP_SEND_TIMEOUT}, {send_timeout, ?TCP_SEND_TIMEOUT},
{send_timeout_close, true},
{active, false}, Type], {active, false}, Type],
Timeout)) of Timeout)) of
{ok, _Socket} = R -> R; {ok, _Socket} = R -> R;

View File

@ -46,13 +46,15 @@
close/1, close/1,
sockname/1, peername/1]). sockname/1, peername/1]).
-include("ejabberd.hrl").
-record(socket_state, {sockmod, socket, receiver}). -record(socket_state, {sockmod, socket, receiver}).
%%==================================================================== %%====================================================================
%% API %% API
%%==================================================================== %%====================================================================
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Function: %% Function:
%% Description: %% Description:
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
start(Module, SockMod, Socket, Opts) -> start(Module, SockMod, Socket, Opts) ->
@ -67,7 +69,7 @@ start(Module, SockMod, Socket, Opts) ->
case catch SockMod:custom_receiver(Socket) of case catch SockMod:custom_receiver(Socket) of
{receiver, RecMod, RecPid} -> {receiver, RecMod, RecPid} ->
{RecMod, RecPid, RecMod}; {RecMod, RecPid, RecMod};
_ -> _ ->
RecPid = ejabberd_receiver:start( RecPid = ejabberd_receiver:start(
Socket, SockMod, none, MaxStanzaSize), Socket, SockMod, none, MaxStanzaSize),
{ejabberd_receiver, RecPid, RecPid} {ejabberd_receiver, RecPid, RecPid}
@ -158,10 +160,22 @@ reset_stream(SocketData) when is_atom(SocketData#socket_state.receiver) ->
(SocketData#socket_state.receiver):reset_stream( (SocketData#socket_state.receiver):reset_stream(
SocketData#socket_state.socket). SocketData#socket_state.socket).
%% sockmod=gen_tcp|tls|ejabberd_zlib
send(SocketData, Data) -> send(SocketData, Data) ->
catch (SocketData#socket_state.sockmod):send( case catch (SocketData#socket_state.sockmod):send(
SocketData#socket_state.socket, Data). SocketData#socket_state.socket, Data) of
ok -> ok;
{error, timeout} ->
?INFO_MSG("Timeout on ~p:send",[SocketData#socket_state.sockmod]),
exit(normal);
Error ->
?DEBUG("Error in ~p:send: ~p",[SocketData#socket_state.sockmod, Error]),
exit(normal)
end.
%% Can only be called when in c2s StateData#state.xml_socket is true
%% This function is used for HTTP bind
%% sockmod=ejabberd_http_poll|ejabberd_http_bind or any custom module
send_xml(SocketData, Data) -> send_xml(SocketData, Data) ->
catch (SocketData#socket_state.sockmod):send_xml( catch (SocketData#socket_state.sockmod):send_xml(
SocketData#socket_state.socket, Data). SocketData#socket_state.socket, Data).

View File

@ -101,7 +101,7 @@ start_link({SockMod, Socket}, Opts) ->
end, end,
%% XXX bard: for backward compatibility, expand in Opts: %% XXX bard: for backward compatibility, expand in Opts:
%% web_admin -> {["admin"], ejabberd_web_admin} %% web_admin -> {["admin"], ejabberd_web_admin}
%% http_bind -> {["http-bind"], mod_http_bind} %% http_bind -> {["http-bind"], mod_http_bind}
%% http_poll -> {["http-poll"], ejabberd_http_poll} %% http_poll -> {["http-poll"], ejabberd_http_poll}
@ -143,8 +143,15 @@ socket_type() ->
raw. raw.
send_text(State, Text) -> send_text(State, Text) ->
(State#state.sockmod):send(State#state.socket, Text). case catch (State#state.sockmod):send(State#state.socket, Text) of
ok -> ok;
{error, timeout} ->
?INFO_MSG("Timeout on ~p:send",[State#state.sockmod]),
exit(normal);
Error ->
?DEBUG("Error in ~p:send: ~p",[State#state.sockmod, Error]),
exit(normal)
end.
receive_headers(State) -> receive_headers(State) ->
SockMod = State#state.sockmod, SockMod = State#state.sockmod,
@ -637,7 +644,7 @@ start_dir(N, Path, "./" ++ T ) -> start_dir(N , Path, T);
start_dir(N, Path, "../" ++ T ) -> start_dir(N + 1, Path, T); start_dir(N, Path, "../" ++ T ) -> start_dir(N + 1, Path, T);
start_dir(N, Path, T ) -> rest_dir (N , Path, T). start_dir(N, Path, T ) -> rest_dir (N , Path, T).
rest_dir (_N, Path, [] ) -> case Path of rest_dir (_N, Path, [] ) -> case Path of
[] -> "/"; [] -> "/";
_ -> Path _ -> Path
end; end;