wait_for_stream/2,
wait_for_auth/2,
wait_for_sasl_auth/2,
+ wait_for_bind/2,
wait_for_session/2,
wait_for_sasl_response/2,
session_established/2,
{next_state, wait_for_sasl_auth,
StateData#state{sasl_state = SASLState}};
_ ->
- send_element(
- StateData,
- {xmlelement, "stream:features", [], []}),
- {next_state, wait_for_session, StateData}
+ case StateData#state.resource of
+ "" ->
+ send_element(
+ StateData,
+ {xmlelement, "stream:features", [],
+ [{xmlelement, "bind",
+ [{"xmlns", ?NS_SASL}], []}]}),
+ {next_state, wait_for_bind, StateData};
+ _ ->
+ send_element(
+ StateData,
+ {xmlelement, "stream:features", [], []}),
+ {next_state, wait_for_session, StateData}
+ end
end;
_ ->
Header = io_lib:format(
send_element(StateData,
{xmlelement, "success",
[{"xmlns", ?NS_SASL}], []}),
- JID = #jid{user = U, resource = R} =
- jlib:string_to_jid(
- xml:get_attr_s(authzid, Props)),
+ U = xml:get_attr_s(username, Props),
?INFO_MSG("(~w) Accepted authentification for ~s",
- [StateData#state.socket,
- jlib:jid_to_string(JID)]),
+ [StateData#state.socket, U]),
{next_state, wait_for_stream,
StateData#state{authentificated = true,
- user = U,
- resource = R,
- jid = JID
+ user = U
}};
{continue, ServerOut, NewSASLState} ->
send_element(StateData,
send_element(StateData,
{xmlelement, "success",
[{"xmlns", ?NS_SASL}], []}),
- JID = #jid{user = U, resource = R} =
- jlib:string_to_jid(xml:get_attr_s(authzid, Props)),
+ U = xml:get_attr_s(username, Props),
?INFO_MSG("(~w) Accepted authentification for ~s",
- [StateData#state.socket,
- jlib:jid_to_string(JID)]),
+ [StateData#state.socket, U]),
{next_state, wait_for_stream,
StateData#state{authentificated = true,
- user = U,
- resource = R,
- jid = JID
+ user = U
}};
{continue, ServerOut, NewSASLState} ->
send_element(StateData,
+wait_for_bind({xmlstreamelement, El}, StateData) ->
+ case jlib:iq_query_info(El) of
+ {iq, ID, set, ?NS_BIND, SubEl} ->
+ U = StateData#state.user,
+ R1 = xml:get_path_s(SubEl, [{elem, "resource"}, cdata]),
+ R = case jlib:resourceprep(R1) of
+ error -> error;
+ "" ->
+ lists:concat(
+ [randoms:get_string() | tuple_to_list(now())]);
+ Resource -> Resource
+ end,
+ case R of
+ error ->
+ Err = jlib:make_error_reply(El, ?ERR_BAD_REQUEST),
+ send_element(StateData, Err),
+ {next_state, wait_for_bind, StateData};
+ _ ->
+ JID = jlib:make_jid(U, StateData#state.server, R),
+ Res = {iq, ID, result, ?NS_BIND,
+ [{xmlelement, "bind",
+ [{"xmlns", ?NS_BIND}],
+ [{xmlelement, "jid", [],
+ [{xmlcdata, jlib:jid_to_string(JID)}]}]}]},
+ send_element(StateData, jlib:iq_to_xml(Res)),
+ {next_state, wait_for_session,
+ StateData#state{resource = R, jid = JID}}
+ end;
+ _ ->
+ {next_state, wait_for_bind, StateData}
+ end;
+
+wait_for_bind({xmlstreamend, Name}, StateData) ->
+ send_text(StateData, ?STREAM_TRAILER),
+ {stop, normal, StateData};
+
+wait_for_bind({xmlstreamerror, _}, StateData) ->
+ send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
+ {stop, normal, StateData};
+
+wait_for_bind(closed, StateData) ->
+ {stop, normal, StateData}.
+
+
+
wait_for_session({xmlstreamelement, El}, StateData) ->
case jlib:iq_query_info(El) of
{iq, ID, set, ?NS_SESSION, SubEl} ->
%% Returns: any
%%----------------------------------------------------------------------
terminate(Reason, StateName, StateData) ->
- case StateData#state.user of
- "" ->
- ok;
- _ ->
+ case StateName of
+ session_established ->
?INFO_MSG("(~w) Close session for ~s",
[StateData#state.socket,
jlib:jid_to_string(StateData#state.jid)]),
ejabberd_sm:unset_presence(StateData#state.user,
StateData#state.resource),
presence_broadcast(StateData, From, StateData#state.pres_a, Packet),
- presence_broadcast(StateData, From, StateData#state.pres_i, Packet)
+ presence_broadcast(StateData, From, StateData#state.pres_i, Packet);
+ _ ->
+ ok
end,
(StateData#state.sockmod):close(StateData#state.socket),
ok.
register_connection(User, Resource, Pid) ->
LUser = jlib:nodeprep(User),
- UR = {LUser, Resource},
+ LResource = jlib:nodeprep(Resource),
+ UR = {LUser, LResource},
F = fun() ->
Ss = mnesia:wread({session, UR}),
Ls = mnesia:wread({local_session, UR}),
replace_my_connection(User, Resource) ->
LUser = jlib:nodeprep(User),
+ LResource = jlib:nodeprep(Resource),
+ UR = {LUser, LResource},
F = fun() ->
- UR = {LUser, Resource},
Es = mnesia:read({local_session, UR}),
mnesia:delete({local_session, UR}),
Es
remove_connection(User, Resource) ->
LUser = jlib:nodeprep(User),
+ LResource = jlib:nodeprep(Resource),
F = fun() ->
- UR = {LUser, Resource},
+ UR = {LUser, LResource},
mnesia:delete({local_session, UR}),
mnesia:delete({session, UR})
end,
do_route(From, To, Packet) ->
?DEBUG("session manager~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n",
[From, To, Packet, 8]),
- #jid{user = User, resource = Resource,
+ #jid{user = User,
luser = LUser, lserver = LServer, lresource = LResource} = To,
{xmlelement, Name, Attrs, _Els} = Packet,
- case Resource of
+ case LResource of
"" ->
case Name of
"presence" ->