]> granicus.if.org Git - ejabberd/commitdiff
*** empty log message ***
authorAlexey Shchepin <alexey@process-one.net>
Sun, 24 Nov 2002 20:36:57 +0000 (20:36 +0000)
committerAlexey Shchepin <alexey@process-one.net>
Sun, 24 Nov 2002 20:36:57 +0000 (20:36 +0000)
SVN Revision: 6

src/ejabberd.erl
src/ejabberd_c2s.erl
src/ejabberd_sm.erl [new file with mode: 0644]
src/xml.erl

index 40d0bc448fbb773728a88b7ce94dc038af43e93e..4036e92e844a2390b57ffeda06f263f2b3881c0b 100644 (file)
@@ -23,6 +23,7 @@ init() ->
     Port = open_port({spawn, expat_erl}, [binary]),
     db_init(),
     ejabberd_auth:start(),
+    ejabberd_sm:start(),
     ejabberd_listener:start(),
     loop(Port).
 
@@ -35,4 +36,5 @@ loop(Port) ->
 
 db_init() ->
     mnesia:create_schema([node()]),
-    mnesia:start().
+    mnesia:start(),
+    mnesia:wait_for_tables(mnesia:system_info(tables), infinity).
index 518f5a4883580790477f8355627b3825bef3e58c..6cce2f261c490b03a1c70e8b0b9b26df25995391 100644 (file)
@@ -103,14 +103,10 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
            io:format("AUTH: ~p~n", [{U, P, D, R}]),
            case ejabberd_auth:check_password(U, P) of
                true ->
+                   % TODO
                    {next_state, session_established, StateData};
                _ ->
-                   {xmlelement, _, _, SubTags} = El,
-                   Err = {xmlelement, "iq",
-                          [{"id", "0"}, {"type", "error"}],
-                          SubTags ++ [{xmlelement, "error",
-                                       [{"code", "404"}],
-                                       [{xmlcdata, "Unauthorized"}]}]},
+                   Err = xml:make_error_iq_reply(El, "404", "Unauthorized"),
                    send_element(StateData#state.sender, Err),
                    {next_state, wait_for_auth, StateData}
            end;
@@ -238,7 +234,6 @@ is_auth_packet({xmlelement, Name, Attrs, Els}) when Name == "iq" ->
        true ->
            false
     end;
-
 is_auth_packet(_) ->
     false.
 
diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl
new file mode 100644 (file)
index 0000000..1650594
--- /dev/null
@@ -0,0 +1,171 @@
+%%%----------------------------------------------------------------------
+%%% File    : ejabberd_sm.erl
+%%% Author  : Alexey Shchepin <alexey@sevcom.net>
+%%% Purpose : 
+%%% Created : 24 Nov 2002 by Alexey Shchepin <alexey@sevcom.net>
+%%% Id      : $Id$
+%%%----------------------------------------------------------------------
+
+-module(ejabberd_sm).
+-author('alexey@sevcom.net').
+
+-export([start/0, init/0, open_session/2]).
+
+-include_lib("mnemosyne/include/mnemosyne.hrl").
+
+-record(user_resource, {id, user, resource}).
+-record(user_resource_id_seq, {name = value, id}).
+-record(session, {id, node}).
+-record(mysession, {id, info}).
+
+-record(mysession_info, {pid}).
+
+
+start() ->
+    spawn(ejabberd_sm, init, []).
+
+init() ->
+    register(ejabberd_sm, self()),
+    mnesia:create_table(user_resource_id_seq,
+                       [{ram_copies, [node()]},
+                        {attributes,
+                         record_info(fields, user_resource_id_seq)}]),
+    init_seq(),
+    mnesia:create_table(user_resource,[{ram_copies, [node()]},
+                                      {attributes,
+                                       record_info(fields, user_resource)}]),
+    mnesia:add_table_index(user_resource, user),
+    mnesia:create_table(session,[{ram_copies, [node()]},
+                                {attributes, record_info(fields, session)}]),
+    mnesia:add_table_index(session, node),
+    mnesia:create_table(mysession,
+                       [{ram_copies, [node()]},
+                        {local_content, true},
+                        {attributes, record_info(fields, mysession)}]),
+    mnesia:subscribe(system),
+    loop().
+
+loop() ->
+    receive
+       {open_session, User, Resource, From} ->
+           replace_and_register_my_connection(User, Resource, From),
+           replace_alien_connection(User, Resource),
+           loop();
+       {replace, User, Resource} ->
+           replace_my_connection(User, Resource),
+           loop();
+       {mnesia_system_event, {mnesia_down, Node}} ->
+           clean_table_from_bad_node(Node),
+           loop();
+       _ ->
+           loop()
+    end.
+
+
+open_session(User, Resource) ->
+    ejabberd_sm ! {open_session, User, Resource, self()}.
+
+replace_alien_connection(User, Resource) ->
+    F = fun() ->
+               [ID] = mnemosyne:eval(query [X.id || X <- table(user_resource),
+                                                    X.user = User,
+                                                    X.resource = Resource]
+                                     end),
+               Es = mnesia:read({session, ID}),
+               mnesia:write(#session{id = ID, node = node()}),
+               Es
+        end,
+    case mnesia:transaction(F) of
+       {atomic, Rs} ->
+           lists:foreach(
+             fun(R) ->
+                     if R#session.node /= node() ->
+                             {ejabberd_sm, R#session.node} !
+                                 {replace, User, Resource};
+                        true ->
+                             ok
+                     end
+             end, Rs);
+       _ ->
+           false
+    end.
+
+
+replace_my_connection(User, Resource) ->
+    F = fun() ->
+               [ID] = mnemosyne:eval(query [X.id || X <- table(user_resource),
+                                                    X.user = User,
+                                                    X.resource = Resource]
+                                     end),
+
+               Es = mnesia:read({mysession, ID}),
+               mnesia:delete({mysession, ID}),
+               Es
+        end,
+    case mnesia:transaction(F) of
+       {atomic, Rs} ->
+           lists:foreach(
+             fun(R) ->
+                     (R#mysession.info)#mysession_info.pid ! replaced
+             end, Rs);
+       _ ->
+           false
+    end.
+
+replace_and_register_my_connection(User, Resource, Pid) ->
+    F = fun() ->
+               IDs = mnemosyne:eval(query [X.id || X <- table(user_resource),
+                                                   X.user = User,
+                                                   X.resource = Resource]
+                                    end),
+
+               ID = case IDs of
+                        [Id] -> Id;
+                        [] ->
+                            [CurID] = 
+                                mnemosyne:eval(
+                                  query [X.id ||
+                                            X <- table(user_resource_id_seq)]
+                                    end),
+                            mnesia:write(
+                              #user_resource_id_seq{id = CurID + 1}),
+                            mnesia:write(
+                              #user_resource{id = CurID,
+                                             user = User,
+                                             resource = Resource}),
+                            CurID
+                    end,
+               Es = mnesia:read({mysession, ID}),
+               mnesia:write(#mysession{id = ID,
+                                       info = #mysession_info{pid = Pid}}),
+               Es
+        end,
+    case mnesia:transaction(F) of
+       {atomic, Rs} ->
+           lists:foreach(
+             fun(R) ->
+                     (R#mysession.info)#mysession_info.pid ! replaced
+             end, Rs);
+       _ ->
+           false
+    end.
+
+
+clean_table_from_bad_node(Node) ->
+    F = fun() ->
+               Es = mnesia:index_read(session, Node, #session.node),
+               lists:foreach(fun(E) ->
+                                     mnesia:delete_object(session, E, write),
+                                     mnesia:delete(
+                                       {user_resource, E#session.id})
+                             end, Es)
+        end,
+    mnesia:transaction(F).
+
+init_seq() ->
+    F = fun() ->
+               [] = mnesia:read({user_resource_id_seq, value}),
+               mnesia:write(#user_resource_id_seq{id = 0})
+        end,
+    mnesia:transaction(F).
+
index e1ae3b1bafeb2b54e5a09cef3018da268a87d5a1..5ae3cb593af9fd1b6a1ed8f64ad4c1c294abe528 100644 (file)
@@ -11,7 +11,7 @@
 -vsn('$Revision$ ').
 
 -export([element_to_string/1, crypt/1, remove_cdata/1, get_cdata/1,
-        get_attr/2, get_attr_s/2]).
+        get_attr/2, get_attr_s/2, make_error_iq_reply/3]).
 
 element_to_string(El) ->
     case El of
@@ -90,3 +90,31 @@ get_attr_s(AttrName, Attrs) ->
            ""
     end.
 
+
+make_error_iq_reply({xmlelement, Name, Attrs, SubTags}, Code, Desc)
+  when Name == "iq" ->
+    NewAttrs = make_error_iq_reply_attrs(Attrs),
+    {xmlelement, Name, NewAttrs, SubTags ++ [{xmlelement, "error",
+                                             [{"code", Code}],
+                                             [{xmlcdata, Desc}]}]}.
+
+make_error_iq_reply_attrs(Attrs) ->
+    To = get_attr("to", Attrs),
+    From = get_attr("from", Attrs),
+    Attrs1 = lists:keydelete("to", 1, Attrs),
+    Attrs2 = lists:keydelete("from", 1, Attrs1),
+    Attrs3 = case To of
+                {value, ToVal} ->
+                     [{"from", ToVal} | Attrs2];
+                _ ->
+                    Attrs2
+            end,
+    Attrs4 = case From of
+                {value, FromVal} ->
+                     [{"to", FromVal} | Attrs3];
+                _ ->
+                    Attrs3
+            end,
+    Attrs5 = lists:keydelete("type", 1, Attrs4),
+    Attrs6 = [{"type", "error"} | Attrs5],
+    Attrs6.