summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMickaël Rémond <mickael.remond@process-one.net>2009-10-19 09:36:23 +0000
committerMickaël Rémond <mickael.remond@process-one.net>2009-10-19 09:36:23 +0000
commit006515020acfd880b02733628d0c07e142ac266e (patch)
tree79336f4745c1e225a722323c5268e2038948756f /src
parentFixed 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.erl1
-rw-r--r--src/ejabberd_s2s_out.erl1
-rw-r--r--src/ejabberd_socket.erl22
-rw-r--r--src/web/ejabberd_http.erl15
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;