Process XML-RPC requests via p1_xml and ejabberd_http

This commit is contained in:
Evgeniy Khramtsov 2014-10-03 18:53:55 +04:00
parent e109f352e3
commit 1d782db84f
5 changed files with 46 additions and 29 deletions

View File

@ -31,5 +31,6 @@
host = <<"">> :: binary(), host = <<"">> :: binary(),
port = 5280 :: inet:port_number(), port = 5280 :: inet:port_number(),
tp = http, % :: protocol(), tp = http, % :: protocol(),
opts = [] :: list(),
headers = [] :: [{atom() | binary(), binary()}]}). headers = [] :: [{atom() | binary(), binary()}]}).

View File

@ -56,7 +56,7 @@ Deps = [{p1_cache_tab, ".*", {git, "git://github.com/processone/cache_tab"}},
{esip, ".*", {git, "git://github.com/processone/p1_sip"}}, {esip, ".*", {git, "git://github.com/processone/p1_sip"}},
{p1_stun, ".*", {git, "git://github.com/processone/stun"}}, {p1_stun, ".*", {git, "git://github.com/processone/stun"}},
{p1_yaml, ".*", {git, "git://github.com/processone/p1_yaml"}}, {p1_yaml, ".*", {git, "git://github.com/processone/p1_yaml"}},
{xmlrpc, ".*", {git, "git://github.com/rds13/xmlrpc"}}, {ehyperloglog, ".*", {git, "https://github.com/vaxelfel/eHyperLogLog.git"}},
{p1_utils, ".*", {git, "git://github.com/processone/p1_utils"}}], {p1_utils, ".*", {git, "git://github.com/processone/p1_utils"}}],
ConfigureCmd = fun(Pkg, Flags) -> ConfigureCmd = fun(Pkg, Flags) ->

View File

@ -65,6 +65,7 @@
request_tp, request_tp,
request_headers = [], request_headers = [],
end_of_request = false, end_of_request = false,
options = [],
default_host, default_host,
trail = <<>> trail = <<>>
}). }).
@ -133,6 +134,10 @@ init({SockMod, Socket}, Opts) ->
true -> [{[<<"http-poll">>], ejabberd_http_poll}]; true -> [{[<<"http-poll">>], ejabberd_http_poll}];
false -> [] false -> []
end, end,
XMLRPC = case proplists:get_bool(xmlrpc, Opts) of
true -> [{[], ejabberd_xmlrpc}];
false -> []
end,
DefinedHandlers = gen_mod:get_opt( DefinedHandlers = gen_mod:get_opt(
request_handlers, Opts, request_handlers, Opts,
fun(Hs) -> fun(Hs) ->
@ -141,7 +146,7 @@ init({SockMod, Socket}, Opts) ->
Mod} || {Path, Mod} <- Hs] Mod} || {Path, Mod} <- Hs]
end, []), end, []),
RequestHandlers = DefinedHandlers ++ Captcha ++ Register ++ RequestHandlers = DefinedHandlers ++ Captcha ++ Register ++
Admin ++ Bind ++ Poll, Admin ++ Bind ++ Poll ++ XMLRPC,
?DEBUG("S: ~p~n", [RequestHandlers]), ?DEBUG("S: ~p~n", [RequestHandlers]),
DefaultHost = gen_mod:get_opt(default_host, Opts, fun(A) -> A end, undefined), DefaultHost = gen_mod:get_opt(default_host, Opts, fun(A) -> A end, undefined),
@ -150,6 +155,7 @@ init({SockMod, Socket}, Opts) ->
State = #state{sockmod = SockMod1, State = #state{sockmod = SockMod1,
socket = Socket1, socket = Socket1,
default_host = DefaultHost, default_host = DefaultHost,
options = Opts,
request_handlers = RequestHandlers}, request_handlers = RequestHandlers},
receive_headers(State). receive_headers(State).
@ -359,7 +365,7 @@ process(Handlers, Request) ->
false -> process(HandlersLeft, Request) false -> process(HandlersLeft, Request)
end. end.
process_request(#state{request_method = Method, process_request(#state{request_method = Method, options = Options,
request_path = {abs_path, Path}, request_auth = Auth, request_path = {abs_path, Path}, request_auth = Auth,
request_lang = Lang, request_handlers = RequestHandlers, request_lang = Lang, request_handlers = RequestHandlers,
request_host = Host, request_port = Port, request_host = Host, request_port = Port,
@ -389,6 +395,7 @@ process_request(#state{request_method = Method,
IP = analyze_ip_xff(IPHere, XFF, Host), IP = analyze_ip_xff(IPHere, XFF, Host),
Request = #request{method = Method, Request = #request{method = Method,
path = LPath, path = LPath,
opts = Options,
q = LQuery, q = LQuery,
auth = Auth, auth = Auth,
lang = Lang, lang = Lang,
@ -413,7 +420,7 @@ process_request(#state{request_method = Method,
make_text_output(State, Status, Headers, Output) make_text_output(State, Status, Headers, Output)
end end
end; end;
process_request(#state{request_method = Method, process_request(#state{request_method = Method, options = Options,
request_path = {abs_path, Path}, request_auth = Auth, request_path = {abs_path, Path}, request_auth = Auth,
request_content_length = Len, request_lang = Lang, request_content_length = Len, request_lang = Lang,
sockmod = SockMod, socket = Socket, request_host = Host, sockmod = SockMod, socket = Socket, request_host = Host,
@ -450,6 +457,7 @@ process_request(#state{request_method = Method,
Request = #request{method = Method, Request = #request{method = Method,
path = LPath, path = LPath,
q = LQuery, q = LQuery,
opts = Options,
auth = Auth, auth = Auth,
data = Data, data = Data,
lang = Lang, lang = Lang,

View File

@ -201,11 +201,7 @@ listen_tcp(PortIP, Module, SockOpts, Port, IPS) ->
catch catch
_:_ -> [] _:_ -> []
end, end,
DeliverAs = case Module of Res = gen_tcp:listen(Port, [binary,
ejabberd_xmlrpc -> list;
_ -> binary
end,
Res = gen_tcp:listen(Port, [DeliverAs,
{packet, 0}, {packet, 0},
{active, false}, {active, false},
{reuseaddr, true}, {reuseaddr, true},

View File

@ -17,11 +17,12 @@
-author('badlop@process-one.net'). -author('badlop@process-one.net').
-export([start/2, handler/2, socket_type/0, transform_listen_option/2]). -export([start/2, handler/2, process/2, socket_type/0,
transform_listen_option/2]).
-include("ejabberd.hrl"). -include("ejabberd.hrl").
-include("logger.hrl"). -include("logger.hrl").
-include("ejabberd_http.hrl").
-include("mod_roster.hrl"). -include("mod_roster.hrl").
-include("jlib.hrl"). -include("jlib.hrl").
@ -170,12 +171,14 @@
%% ----------------------------- %% -----------------------------
start({gen_tcp = _SockMod, Socket}, Opts) -> start({gen_tcp = _SockMod, Socket}, Opts) ->
%MaxSessions = gen_mod:get_opt(maxsessions, Opts, ejabberd_http:start({gen_tcp, Socket}, [{xmlrpc, true}|Opts]).
% fun(I) when is_integer(I), I>0 -> I end,
% 10), socket_type() -> raw.
Timeout = gen_mod:get_opt(timeout, Opts,
fun(I) when is_integer(I), I>0 -> I end, %% -----------------------------
5000), %% HTTP interface
%% -----------------------------
process(_, #request{method = 'POST', data = Data, opts = Opts}) ->
AccessCommandsOpts = gen_mod:get_opt(access_commands, Opts, AccessCommandsOpts = gen_mod:get_opt(access_commands, Opts,
fun(L) when is_list(L) -> L end, fun(L) when is_list(L) -> L end,
[]), []),
@ -201,19 +204,28 @@ start({gen_tcp = _SockMod, Socket}, Opts) ->
[?MODULE, Wrong]), [?MODULE, Wrong]),
[] []
end, AccessCommandsOpts), end, AccessCommandsOpts),
GetAuth = case [ACom GetAuth = case [ACom || {Ac, _, _} = ACom <- AccessCommands, Ac /= all] of
|| {Ac, _, _} = ACom <- AccessCommands, Ac /= all] [] -> false;
of _ -> true
[] -> false;
_ -> true
end, end,
Handler = {?MODULE, handler}, State = #state{access_commands = AccessCommands, get_auth = GetAuth},
State = #state{access_commands = AccessCommands, case xmlrpc_decode:payload(Data) of
get_auth = GetAuth}, {error, _} = Err ->
Pid = proc_lib:spawn(xmlrpc_http, handler, [Socket, Timeout, Handler, State]), ?ERROR_MSG("XML-RPC request ~s failed with reason: ~p",
{ok, Pid}. [Data, Err]),
{400, [],
socket_type() -> raw. #xmlel{name = <<"h1">>, attrs = [],
children = [{xmlcdata, <<"Malformed Request">>}]}};
{ok, RPC} ->
?DEBUG("got XML-RPC request: ~p", [RPC]),
{false, Result} = handler(State, RPC),
{ok, XML} = xmlrpc_encode:payload(Result),
{200, [], [{<<"Content-Type">>, <<"text/xml">>}], XML}
end;
process(_, _) ->
{400, [],
#xmlel{name = <<"h1">>, attrs = [],
children = [{xmlcdata, <<"400 Bad Request">>}]}}.
%% ----------------------------- %% -----------------------------
%% Access verification %% Access verification