aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2014-05-08 16:08:07 +0400
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2014-05-08 16:14:21 +0400
commit90a5c054d4471caff13915ac347bf4ccac7f462b (patch)
tree717195c3020edd46ab3c8ddd1e3afce98aa1feed /src
parentMerge pull request #203 from hamano/added_get_random_pid_error_handling (diff)
TURN support (EJAB-1017)
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_listener.erl12
-rw-r--r--src/ejabberd_stun.erl83
-rw-r--r--src/shaper.erl14
3 files changed, 96 insertions, 13 deletions
diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl
index 844080a04..02a2f3fbd 100644
--- a/src/ejabberd_listener.erl
+++ b/src/ejabberd_listener.erl
@@ -366,7 +366,6 @@ start_listener2(Port, Module, Opts) ->
%% It is only required to start the supervisor in some cases.
%% But it doesn't hurt to attempt to start it for any listener.
%% So, it's normal (and harmless) that in most cases this call returns: {error, {already_started, pid()}}
- maybe_start_stun(Module),
maybe_start_sip(Module),
start_module_sup(Port, Module),
start_listener_sup(Port, Module, Opts).
@@ -482,13 +481,6 @@ is_frontend(_) -> false.
strip_frontend({frontend, Module}) -> Module;
strip_frontend(Module) when is_atom(Module) -> Module.
--spec maybe_start_stun(module()) -> any().
-
-maybe_start_stun(ejabberd_stun) ->
- ejabberd:start_app(p1_stun);
-maybe_start_stun(_) ->
- ok.
-
maybe_start_sip(esip_socket) ->
ejabberd:start_app(esip);
maybe_start_sip(_) ->
@@ -671,12 +663,8 @@ prepare_ip(IP) when is_list(IP) ->
prepare_ip(IP) when is_binary(IP) ->
prepare_ip(binary_to_list(IP)).
-prepare_mod(ejabberd_stun) ->
- prepare_mod(stun);
prepare_mod(ejabberd_sip) ->
prepare_mod(sip);
-prepare_mod(stun) ->
- stun;
prepare_mod(sip) ->
esip_socket;
prepare_mod(Mod) when is_atom(Mod) ->
diff --git a/src/ejabberd_stun.erl b/src/ejabberd_stun.erl
new file mode 100644
index 000000000..89cbebf84
--- /dev/null
+++ b/src/ejabberd_stun.erl
@@ -0,0 +1,83 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2014, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 8 May 2014 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(ejabberd_stun).
+
+%% API
+-export([tcp_init/2, udp_init/2, udp_recv/5, start/2, socket_type/0]).
+
+-include("ejabberd.hrl").
+-include("logger.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+tcp_init(Socket, Opts) ->
+ ejabberd:start_app(p1_stun),
+ stun:tcp_init(Socket, prepare_turn_opts(Opts)).
+
+udp_init(Socket, Opts) ->
+ ejabberd:start_app(p1_stun),
+ stun:udp_init(Socket, prepare_turn_opts(Opts)).
+
+udp_recv(Socket, Addr, Port, Packet, Opts) ->
+ stun:udp_recv(Socket, Addr, Port, Packet, Opts).
+
+start(Opaque, Opts) ->
+ stun:start(Opaque, Opts).
+
+socket_type() ->
+ raw.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+prepare_turn_opts(Opts) ->
+ UseTurn = proplists:get_bool(use_turn, Opts),
+ prepare_turn_opts(Opts, UseTurn).
+
+prepare_turn_opts(Opts, _UseTurn = false) ->
+ Opts;
+prepare_turn_opts(Opts, _UseTurn = true) ->
+ NumberOfMyHosts = length(?MYHOSTS),
+ case proplists:get_value(turn_ip, Opts) of
+ undefined ->
+ ?WARNING_MSG("option 'turn_ip' is undefined, "
+ "more likely the TURN relay won't be working "
+ "properly", []);
+ _ ->
+ ok
+ end,
+ AuthFun = fun ejabberd_auth:get_password_s/2,
+ Shaper = gen_mod:get_opt(shaper, Opts,
+ fun(S) when is_atom(S) -> S end,
+ none),
+ AuthType = gen_mod:get_opt(auth_type, Opts,
+ fun(anonymous) -> anonymous;
+ (user) -> user
+ end, user),
+ Realm = case gen_mod:get_opt(auth_realm, Opts, fun iolist_to_binary/1) of
+ undefined when AuthType == user ->
+ if NumberOfMyHosts > 1 ->
+ ?WARNING_MSG("you have several virtual "
+ "hosts configured, but option "
+ "'auth_realm' is undefined and "
+ "'auth_type' is set to 'user', "
+ "more likely the TURN relay won't "
+ "be working properly. Using ~s as "
+ "a fallback", [?MYNAME]);
+ true ->
+ ok
+ end,
+ [{auth_realm, ?MYNAME}];
+ _ ->
+ []
+ end,
+ MaxRate = shaper:get_max_rate(Shaper),
+ Realm ++ [{auth_fun, AuthFun},{shaper, MaxRate} |
+ lists:keydelete(shaper, 1, Opts)].
diff --git a/src/shaper.erl b/src/shaper.erl
index a31ec5560..4904d391e 100644
--- a/src/shaper.erl
+++ b/src/shaper.erl
@@ -27,7 +27,7 @@
-author('alexey@process-one.net').
--export([start/0, new/1, new1/1, update/2,
+-export([start/0, new/1, new1/1, update/2, get_max_rate/1,
transform_options/1, load_from_config/0]).
-include("ejabberd.hrl").
@@ -74,6 +74,18 @@ load_from_config() ->
{error, Err}
end.
+-spec get_max_rate(atom()) -> none | non_neg_integer().
+
+get_max_rate(none) ->
+ none;
+get_max_rate(Name) ->
+ case ets:lookup(shaper, {Name, global}) of
+ [#shaper{maxrate = R}] ->
+ R;
+ [] ->
+ none
+ end.
+
-spec new(atom()) -> shaper().
new(none) ->