diff options
author | Mickaël Rémond <mickael.remond@process-one.net> | 2009-10-19 09:36:23 +0000 |
---|---|---|
committer | Mickaël Rémond <mickael.remond@process-one.net> | 2009-10-19 09:36:23 +0000 |
commit | 006515020acfd880b02733628d0c07e142ac266e (patch) | |
tree | 79336f4745c1e225a722323c5268e2038948756f /src | |
parent | Fixed more gcc signedness warnings (diff) |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/ejabberd_listener.erl | 1 | ||||
-rw-r--r-- | src/ejabberd_s2s_out.erl | 1 | ||||
-rw-r--r-- | src/ejabberd_socket.erl | 22 | ||||
-rw-r--r-- | src/web/ejabberd_http.erl | 15 |
4 files changed, 31 insertions, 8 deletions
diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index 26167351..dad7aa5b 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -132,6 +132,7 @@ init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) -> {reuseaddr, true}, {nodelay, true}, {send_timeout, ?TCP_SEND_TIMEOUT}, + {send_timeout_close, true}, {keepalive, true} | SockOpts]), case Res of diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 66396e1e..8fb82c07 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -268,6 +268,7 @@ open_socket2(Type, Addr, Port) -> case (catch ejabberd_socket:connect(Addr, Port, [binary, {packet, 0}, {send_timeout, ?TCP_SEND_TIMEOUT}, + {send_timeout_close, true}, {active, false}, Type], Timeout)) of {ok, _Socket} = R -> R; diff --git a/src/ejabberd_socket.erl b/src/ejabberd_socket.erl index d629a77d..a3c008c9 100644 --- a/src/ejabberd_socket.erl +++ b/src/ejabberd_socket.erl @@ -46,13 +46,15 @@ close/1, sockname/1, peername/1]). +-include("ejabberd.hrl"). + -record(socket_state, {sockmod, socket, receiver}). %%==================================================================== %% API %%==================================================================== %%-------------------------------------------------------------------- -%% Function: +%% Function: %% Description: %%-------------------------------------------------------------------- start(Module, SockMod, Socket, Opts) -> @@ -67,7 +69,7 @@ start(Module, SockMod, Socket, Opts) -> case catch SockMod:custom_receiver(Socket) of {receiver, RecMod, RecPid} -> {RecMod, RecPid, RecMod}; - _ -> + _ -> RecPid = ejabberd_receiver:start( Socket, SockMod, none, MaxStanzaSize), {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.socket). +%% sockmod=gen_tcp|tls|ejabberd_zlib send(SocketData, Data) -> - catch (SocketData#socket_state.sockmod):send( - SocketData#socket_state.socket, Data). + case catch (SocketData#socket_state.sockmod):send( + 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) -> catch (SocketData#socket_state.sockmod):send_xml( SocketData#socket_state.socket, Data). diff --git a/src/web/ejabberd_http.erl b/src/web/ejabberd_http.erl index bed6c28a..bff4b4d4 100644 --- a/src/web/ejabberd_http.erl +++ b/src/web/ejabberd_http.erl @@ -101,7 +101,7 @@ start_link({SockMod, Socket}, Opts) -> end, %% 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_poll -> {["http-poll"], ejabberd_http_poll} @@ -143,8 +143,15 @@ socket_type() -> raw. 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) -> 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 ) -> rest_dir (N , Path, T). -rest_dir (_N, Path, [] ) -> case Path of +rest_dir (_N, Path, [] ) -> case Path of [] -> "/"; _ -> Path end; |