-define(SETS, gb_sets).
--record(state, {socket, receiver, streamid,
+-record(state, {socket, receiver,
+ sockmod,
+ streamid,
sasl_state,
access,
shaper,
_ -> none
end,
{ok, wait_for_stream, #state{socket = Socket,
+ sockmod = SockMod,
receiver = ReceiverPid,
streamid = new_id(),
access = Access,
[StateData#state.streamid,
?MYNAME,
" version='1.0'"]),
- send_text(StateData#state.socket, Header),
+ send_text(StateData, Header),
SASLState = cyrsasl:server_new("jabber", ?MYNAME, "", []),
Mechs = lists:map(fun(S) ->
{xmlelement, "mechanism", [],
[{xmlcdata, S}]}
end, cyrsasl:listmech()),
- send_element(StateData#state.socket,
+ send_element(StateData,
{xmlelement, "stream:features", [],
[{xmlelement, "mechanisms",
[{"xmlns", ?NS_SASL_MECHANISMS}],
Header = io_lib:format(
?STREAM_HEADER,
[StateData#state.streamid, ?MYNAME, ""]),
- send_text(StateData#state.socket, Header),
+ send_text(StateData, Header),
{next_state, wait_for_auth, StateData}
end;
_ ->
Header = io_lib:format(
?STREAM_HEADER,
[StateData#state.streamid, ?MYNAME, ""]),
- send_text(StateData#state.socket,
+ send_text(StateData,
Header ++ ?INVALID_NS_ERR ++ ?STREAM_TRAILER),
{stop, normal, StateData}
end;
wait_for_stream({xmlstreamerror, _}, StateData) ->
Header = io_lib:format(?STREAM_HEADER,
["none", ?MYNAME, " version='1.0'"]),
- send_text(StateData#state.socket,
+ send_text(StateData,
Header ++ ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
{stop, normal, StateData};
case is_auth_packet(El) of
{auth, ID, get, {"", _, _, _}} ->
Err = jlib:make_error_reply(El, "406", "Not Acceptable"),
- send_element(StateData#state.socket, Err),
+ send_element(StateData, Err),
{next_state, wait_for_auth, StateData};
{auth, ID, get, {U, _, _, _}} ->
{xmlelement, Name, Attrs, Els} = jlib:make_result_iq_reply(El),
{xmlelement, "digest", [], []},
{xmlelement, "resource", [], []}
]}]},
- send_element(StateData#state.socket, Res),
+ send_element(StateData, Res),
{next_state, wait_for_auth, StateData};
{auth, ID, set, {U, P, D, ""}} ->
Err = jlib:make_error_reply(El, ?ERR_AUTH_NO_RESOURCE_PROVIDED),
- send_element(StateData#state.socket, Err),
+ send_element(StateData, Err),
{next_state, wait_for_auth, StateData};
{auth, ID, set, {U, P, D, R}} ->
io:format("AUTH: ~p~n", [{U, P, D, R}]),
true ->
ejabberd_sm:open_session(U, R),
Res = jlib:make_result_iq_reply(El),
- send_element(StateData#state.socket, Res),
+ send_element(StateData, Res),
change_shaper(StateData, JID),
{Fs, Ts} = mod_roster:get_subscription_lists(U),
{next_state, session_established,
_ ->
Err = jlib:make_error_reply(
El, ?ERR_FORBIDDEN),
- send_element(StateData#state.socket, Err),
+ send_element(StateData, Err),
{next_state, wait_for_auth, StateData}
end;
_ ->
Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED),
- send_element(StateData#state.socket, Err),
+ send_element(StateData, Err),
{next_state, wait_for_auth, StateData}
end;
_ ->
{"", "", ""},
jlib:iq_to_xml(ResIQ)),
Res = jlib:remove_attr("to", Res1),
- send_element(StateData#state.socket, Res),
+ send_element(StateData, Res),
{next_state, wait_for_auth, StateData};
_ ->
{next_state, wait_for_auth, StateData}
end;
wait_for_auth({xmlstreamend, Name}, StateData) ->
- send_text(StateData#state.socket, ?STREAM_TRAILER),
+ send_text(StateData, ?STREAM_TRAILER),
{stop, normal, StateData};
wait_for_auth({xmlstreamerror, _}, StateData) ->
- send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
+ send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
{stop, normal, StateData};
wait_for_auth(closed, StateData) ->
Mech,
ClientIn) of
{ok, Props} ->
- send_element(StateData#state.socket,
+ send_element(StateData,
{xmlelement, "success",
[{"xmlns", ?NS_SASL_MECHANISMS}], []}),
{next_state, wait_for_resource_auth,
StateData#state{user = xml:get_attr_s(username, Props)}};
{continue, ServerOut, NewSASLState} ->
- send_element(StateData#state.socket,
+ send_element(StateData,
{xmlelement, "challenge",
[{"xmlns", ?NS_SASL_MECHANISMS}],
[{xmlcdata,
{next_state, wait_for_sasl_response,
StateData#state{sasl_state = NewSASLState}};
{error, Code} ->
- send_element(StateData#state.socket,
+ send_element(StateData,
{xmlelement, "failure",
[{"xmlns", ?NS_SASL_MECHANISMS},
{"code", Code}],
{"", "", ""},
jlib:iq_to_xml(ResIQ)),
Res = jlib:remove_attr("to", Res1),
- send_element(StateData#state.socket, Res),
+ send_element(StateData, Res),
{next_state, wait_for_sasl_auth, StateData};
_ ->
{next_state, wait_for_sasl_auth, StateData}
end;
wait_for_sasl_auth({xmlstreamend, Name}, StateData) ->
- send_text(StateData#state.socket, ?STREAM_TRAILER),
+ send_text(StateData, ?STREAM_TRAILER),
{stop, normal, StateData};
wait_for_sasl_auth({xmlstreamerror, _}, StateData) ->
- send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
+ send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
{stop, normal, StateData};
wait_for_sasl_auth(closed, StateData) ->
case is_auth_packet(El) of
{auth, ID, get, {"", _, _, _}} ->
Err = jlib:make_error_reply(El, "406", "Not Acceptable"),
- send_element(StateData#state.socket, Err),
+ send_element(StateData, Err),
{next_state, wait_for_resource_auth, StateData};
{auth, ID, get, {U, _, _, _}} ->
{xmlelement, Name, Attrs, Els} = jlib:make_result_iq_reply(El),
[{xmlcdata, StateData#state.user}]},
{xmlelement, "resource", [], []}
]}]},
- send_element(StateData#state.socket, Res),
+ send_element(StateData, Res),
{next_state, wait_for_resource_auth, StateData};
{auth, ID, set, {U, _, _, ""}} ->
Err = jlib:make_error_reply(El, ?ERR_AUTH_NO_RESOURCE_PROVIDED),
- send_element(StateData#state.socket, Err),
+ send_element(StateData, Err),
{next_state, wait_for_resource_auth, StateData};
{auth, ID, set, {U, _, _, R}} ->
case StateData#state.user of
allow ->
ejabberd_sm:open_session(U, R),
Res = jlib:make_result_iq_reply(El),
- send_element(StateData#state.socket, Res),
+ send_element(StateData, Res),
change_shaper(StateData, JID),
{Fs, Ts} = mod_roster:get_subscription_lists(U),
{next_state, session_established,
pres_t = ?SETS:from_list(Ts)}};
_ ->
Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED),
- send_element(StateData#state.socket, Err),
+ send_element(StateData, Err),
{next_state, wait_for_resource_auth, StateData}
end;
_ ->
Err = jlib:make_error_reply(El, "406", "Not Acceptable"),
- send_element(StateData#state.socket, Err),
+ send_element(StateData, Err),
{next_state, wait_for_resource_auth, StateData}
end;
_ ->
{"", "", ""},
jlib:iq_to_xml(ResIQ)),
Res = jlib:remove_attr("to", Res1),
- send_element(StateData#state.socket, Res),
+ send_element(StateData, Res),
{next_state, wait_for_resource_auth, StateData};
_ ->
{next_state, wait_for_resource_auth, StateData}
end;
wait_for_resource_auth({xmlstreamend, Name}, StateData) ->
- send_text(StateData#state.socket, ?STREAM_TRAILER),
+ send_text(StateData, ?STREAM_TRAILER),
{stop, normal, StateData};
wait_for_resource_auth({xmlstreamerror, _}, StateData) ->
- send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
+ send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
{stop, normal, StateData};
wait_for_resource_auth(closed, StateData) ->
case cyrsasl:server_step(StateData#state.sasl_state,
ClientIn) of
{ok, Props} ->
- send_element(StateData#state.socket,
+ send_element(StateData,
{xmlelement, "success",
[{"xmlns", ?NS_SASL_MECHANISMS}], []}),
{next_state, wait_for_resource_auth,
StateData#state{user = xml:get_attr_s(username, Props)}};
{continue, ServerOut, NewSASLState} ->
- send_element(StateData#state.socket,
+ send_element(StateData,
{xmlelement, "challenge",
[{"xmlns", ?NS_SASL_MECHANISMS}],
[{xmlcdata,
{next_state, wait_for_sasl_response,
StateData#state{sasl_state = NewSASLState}};
{error, Code} ->
- send_element(StateData#state.socket,
+ send_element(StateData,
{xmlelement, "failure",
[{"xmlns", ?NS_SASL_MECHANISMS},
{"code", Code}],
{"", "", ""},
jlib:iq_to_xml(ResIQ)),
Res = jlib:remove_attr("to", Res1),
- send_element(StateData#state.socket, Res),
+ send_element(StateData, Res),
{next_state, wait_for_sasl_auth, StateData};
_ ->
{next_state, wait_for_sasl_auth, StateData}
end;
wait_for_sasl_response({xmlstreamend, Name}, StateData) ->
- send_text(StateData#state.socket, ?STREAM_TRAILER),
+ send_text(StateData, ?STREAM_TRAILER),
{stop, normal, StateData};
wait_for_sasl_response({xmlstreamerror, _}, StateData) ->
- send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
+ send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
{stop, normal, StateData};
wait_for_sasl_response(closed, StateData) ->
{next_state, session_established, NewState};
session_established({xmlstreamend, Name}, StateData) ->
- send_text(StateData#state.socket, ?STREAM_TRAILER),
+ send_text(StateData, ?STREAM_TRAILER),
{stop, normal, StateData};
session_established({xmlstreamerror, _}, StateData) ->
- send_text(StateData#state.socket, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
+ send_text(StateData, ?INVALID_XML_ERR ++ ?STREAM_TRAILER),
{stop, normal, StateData};
session_established(closed, StateData) ->
%% {stop, Reason, NewStateData}
%%----------------------------------------------------------------------
handle_info({send_text, Text}, StateName, StateData) ->
- send_text(StateData#state.socket, Text),
+ send_text(StateData, Text),
{next_state, StateName, StateData};
handle_info(replaced, StateName, StateData) ->
% TODO
jlib:jid_to_string(To),
NewAttrs),
Text = xml:element_to_string({xmlelement, Name, Attrs2, Els}),
- send_text(StateData#state.socket, Text),
+ send_text(StateData, Text),
{next_state, StateName, NewState};
true ->
{next_state, StateName, NewState}
presence_broadcast(From, StateData#state.pres_a, Packet),
presence_broadcast(From, StateData#state.pres_i, Packet)
end,
- gen_tcp:close(StateData#state.socket),
+ (StateData#state.sockmod):close(StateData#state.socket),
ok.
%%%----------------------------------------------------------------------
Shaper = acl:match_rule(StateData#state.shaper, JID),
StateData#state.receiver ! {change_shaper, Shaper}.
-send_text(Socket, Text) ->
- gen_tcp:send(Socket,Text).
+send_text(StateData, Text) ->
+ (StateData#state.sockmod):send(StateData#state.socket, Text).
-send_element(Socket, El) ->
- send_text(Socket, xml:element_to_string(El)).
+send_element(StateData, El) ->
+ send_text(StateData, xml:element_to_string(El)).
new_id() ->