aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd_s2s_in.erl
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2002-12-06 20:59:19 +0000
committerAlexey Shchepin <alexey@process-one.net>2002-12-06 20:59:19 +0000
commite6c062fe407545134cb8c500ef6871f57b08dfb9 (patch)
tree5b35519f882fd2fad347f8c9accdfaae8e85854d /src/ejabberd_s2s_in.erl
parent*** empty log message *** (diff)
*** empty log message ***
SVN Revision: 12
Diffstat (limited to 'src/ejabberd_s2s_in.erl')
-rw-r--r--src/ejabberd_s2s_in.erl274
1 files changed, 274 insertions, 0 deletions
diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl
new file mode 100644
index 000000000..b0300b81f
--- /dev/null
+++ b/src/ejabberd_s2s_in.erl
@@ -0,0 +1,274 @@
+%%%----------------------------------------------------------------------
+%%% File : ejabberd_s2s_in.erl
+%%% Author : Alexey Shchepin <alexey@sevcom.net>
+%%% Purpose :
+%%% Created : 6 Dec 2002 by Alexey Shchepin <alexey@sevcom.net>
+%%% Id : $Id$
+%%%----------------------------------------------------------------------
+
+-module(ejabberd_s2s_in).
+-author('alexey@sevcom.net').
+-vsn('$Revision$ ').
+
+-behaviour(gen_fsm).
+
+%% External exports
+-export([start/1, receiver/2, send_text/2, send_element/2]).
+
+%% gen_fsm callbacks
+-export([init/1, wait_for_stream/2, wait_for_key/2, session_established/2,
+ handle_info/3,
+ terminate/3]).
+
+-record(state, {socket, receiver, streamid,
+ myself = "localhost", server}).
+
+-include("ejabberd.hrl").
+
+-define(DBGFSM, true).
+
+-ifdef(DBGFSM).
+-define(FSMOPTS, [{debug, [trace]}]).
+-else.
+-define(FSMOPTS, []).
+-endif.
+
+-define(STREAM_HEADER,
+ "<?xml version='1.0'?>"
+ "<stream:stream "
+ "xmlns:stream='http://etherx.jabber.org/streams' "
+ "xmlns='jabber:server' "
+ "xmlns:db='jabber:server:dialback'>"
+ ).
+
+-define(STREAM_TRAILER, "</stream:stream>").
+
+-define(INVALID_HEADER_ERR,
+ "<stream:stream>"
+ "<stream:error>Invalid Stream Header</stream:error>"
+ "</stream:stream>"
+ ).
+
+%%%----------------------------------------------------------------------
+%%% API
+%%%----------------------------------------------------------------------
+start(Socket) ->
+ gen_fsm:start(ejabberd_s2s_in, [Socket], ?FSMOPTS).
+
+%%%----------------------------------------------------------------------
+%%% Callback functions from gen_fsm
+%%%----------------------------------------------------------------------
+
+%%----------------------------------------------------------------------
+%% Func: init/1
+%% Returns: {ok, StateName, StateData} |
+%% {ok, StateName, StateData, Timeout} |
+%% ignore |
+%% {stop, StopReason}
+%%----------------------------------------------------------------------
+init([Socket]) ->
+ ReceiverPid = spawn(?MODULE, receiver, [Socket, self()]),
+ {ok, wait_for_stream, #state{socket = Socket,
+ receiver = ReceiverPid,
+ streamid = new_id()}}.
+
+%%----------------------------------------------------------------------
+%% Func: StateName/2
+%% Returns: {next_state, NextStateName, NextStateData} |
+%% {next_state, NextStateName, NextStateData, Timeout} |
+%% {stop, Reason, NewStateData}
+%%----------------------------------------------------------------------
+state_name(Event, StateData) ->
+ {next_state, state_name, StateData}.
+
+wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
+ % TODO
+ case {xml:get_attr_s("xmlns", Attrs), xml:get_attr_s("xmlns:db", Attrs)} of
+ {"jabber:server", "jabber:server:dialback"} ->
+ send_text(StateData#state.socket, ?STREAM_HEADER),
+ {next_state, wait_for_key, StateData};
+ _ ->
+ send_text(StateData#state.socket, ?INVALID_HEADER_ERR),
+ {stop, normal, StateData}
+ end;
+
+wait_for_stream(closed, StateData) ->
+ {stop, normal, StateData}.
+
+
+wait_for_key({xmlstreamelement, El}, StateData) ->
+ case is_key_packet(El) of
+ {key, To, From, Id, Key} ->
+ io:format("GET KEY: ~p~n", [{To, From, Id, Key}]),
+ % TODO
+ ejabberd_s2s_out:start(From, {verify, self(), Key}),
+ {next_state, wait_for_key, StateData};
+ {verify, To, From, Id, Key} ->
+ io:format("VERIFY KEY: ~p~n", [{To, From, Id, Key}]),
+ % TODO
+ {next_state, wait_for_key, StateData};
+ _ ->
+ {next_state, wait_for_key, StateData}
+ end;
+
+wait_for_key({xmlstreamend, Name}, StateData) ->
+ % TODO
+ {stop, normal, StateData};
+
+wait_for_key(closed, StateData) ->
+ {stop, normal, StateData}.
+
+session_established({xmlstreamelement, El}, StateData) ->
+ {xmlelement, Name, Attrs, Els} = El,
+ % TODO
+ FromJID = {StateData#state.server},
+ To = xml:get_attr_s("to", Attrs),
+ ToJID = case To of
+ "" ->
+ {"", StateData#state.server, ""};
+ _ ->
+ jlib:string_to_jid(To)
+ end,
+ case ToJID of
+ error ->
+ % TODO
+ error;
+ _ ->
+ %?DEBUG("FromJID=~w, ToJID=~w, El=~w~n", [FromJID, ToJID, El]),
+ ejabberd_router:route(FromJID, ToJID, El)
+ end,
+ {next_state, session_established, StateData};
+
+session_established(closed, StateData) ->
+ % TODO
+ {stop, normal, StateData}.
+
+
+
+%%----------------------------------------------------------------------
+%% Func: StateName/3
+%% Returns: {next_state, NextStateName, NextStateData} |
+%% {next_state, NextStateName, NextStateData, Timeout} |
+%% {reply, Reply, NextStateName, NextStateData} |
+%% {reply, Reply, NextStateName, NextStateData, Timeout} |
+%% {stop, Reason, NewStateData} |
+%% {stop, Reason, Reply, NewStateData}
+%%----------------------------------------------------------------------
+state_name(Event, From, StateData) ->
+ Reply = ok,
+ {reply, Reply, state_name, StateData}.
+
+%%----------------------------------------------------------------------
+%% Func: handle_event/3
+%% Returns: {next_state, NextStateName, NextStateData} |
+%% {next_state, NextStateName, NextStateData, Timeout} |
+%% {stop, Reason, NewStateData}
+%%----------------------------------------------------------------------
+handle_event(Event, StateName, StateData) ->
+ {next_state, StateName, StateData}.
+
+%%----------------------------------------------------------------------
+%% Func: handle_sync_event/4
+%% Returns: {next_state, NextStateName, NextStateData} |
+%% {next_state, NextStateName, NextStateData, Timeout} |
+%% {reply, Reply, NextStateName, NextStateData} |
+%% {reply, Reply, NextStateName, NextStateData, Timeout} |
+%% {stop, Reason, NewStateData} |
+%% {stop, Reason, Reply, NewStateData}
+%%----------------------------------------------------------------------
+handle_sync_event(Event, From, StateName, StateData) ->
+ Reply = ok,
+ {reply, Reply, StateName, StateData}.
+
+%%----------------------------------------------------------------------
+%% Func: handle_info/3
+%% Returns: {next_state, NextStateName, NextStateData} |
+%% {next_state, NextStateName, NextStateData, Timeout} |
+%% {stop, Reason, NewStateData}
+%%----------------------------------------------------------------------
+handle_info({send_text, Text}, StateName, StateData) ->
+ send_text(StateData#state.socket, Text),
+ {next_state, StateName, StateData}.
+
+%%----------------------------------------------------------------------
+%% Func: terminate/3
+%% Purpose: Shutdown the fsm
+%% Returns: any
+%%----------------------------------------------------------------------
+terminate(Reason, StateName, StateData) ->
+% case StateData#state.user of
+% "" ->
+% ok;
+% _ ->
+% %ejabberd_sm:close_session(StateData#state.user,
+% % StateData#state.resource)
+% end,
+ gen_tcp:close(StateData#state.socket),
+ ok.
+
+%%%----------------------------------------------------------------------
+%%% Internal functions
+%%%----------------------------------------------------------------------
+
+receiver(Socket, C2SPid) ->
+ XMLStreamPid = xml_stream:start(C2SPid),
+ receiver(Socket, C2SPid, XMLStreamPid).
+
+receiver(Socket, C2SPid, XMLStreamPid) ->
+ case gen_tcp:recv(Socket, 0) of
+ {ok, Text} ->
+ xml_stream:send_text(XMLStreamPid, Text),
+ receiver(Socket, C2SPid, XMLStreamPid);
+ {error, closed} ->
+ exit(XMLStreamPid, closed),
+ gen_fsm:send_event(C2SPid, closed),
+ ok
+ end.
+
+send_text(Socket, Text) ->
+ gen_tcp:send(Socket,Text).
+
+send_element(Socket, El) ->
+ send_text(Socket, xml:element_to_string(El)).
+
+new_id() ->
+ lists:flatten(io_lib:format("~p", [random:uniform(65536*65536)])).
+
+
+is_key_packet({xmlelement, Name, Attrs, Els}) when Name == "db:result" ->
+ {key,
+ xml:get_attr_s("to", Attrs),
+ xml:get_attr_s("from", Attrs),
+ xml:get_attr_s("id", Attrs),
+ xml:get_cdata(Els)};
+is_key_packet({xmlelement, Name, Attrs, Els}) when Name == "db:verify" ->
+ {verify,
+ xml:get_attr_s("to", Attrs),
+ xml:get_attr_s("from", Attrs),
+ xml:get_attr_s("id", Attrs),
+ xml:get_cdata(Els)};
+is_key_packet(_) ->
+ false.
+
+get_auth_tags([{xmlelement, Name, Attrs, Els}| L], U, P, D, R) ->
+ CData = xml:get_cdata(Els),
+ case Name of
+ "username" ->
+ get_auth_tags(L, CData, P, D, R);
+ "password" ->
+ get_auth_tags(L, U, CData, D, R);
+ "digest" ->
+ get_auth_tags(L, U, P, CData, R);
+ "resource" ->
+ get_auth_tags(L, U, P, D, CData);
+ _ ->
+ get_auth_tags(L, U, P, D, R)
+ end;
+get_auth_tags([_ | L], U, P, D, R) ->
+ get_auth_tags(L, U, P, D, R);
+get_auth_tags([], U, P, D, R) ->
+ {U, P, D, R}.
+
+
+
+