Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/processone/ejabberd.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristophe Romain <christophe.romain@process-one.net>2008-07-03 13:56:31 +0400
committerChristophe Romain <christophe.romain@process-one.net>2008-07-03 13:56:31 +0400
commit35d25d3420c267b52c33b6d46956c8e05920b17e (patch)
treece69b2d9b5bf5e62a2462fd5133cd9fad4481144 /src
parent2ccf410a7574bdb76402f75849841425322a6887 (diff)
PubSub improvements, and solves (EJAB-453) (EJAB-608)
SVN Revision: 1408
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_c2s.erl3
-rw-r--r--src/ejabberd_local.erl7
-rw-r--r--src/ejabberd_receiver.erl6
-rw-r--r--src/ejabberd_sm.erl15
-rw-r--r--src/mod_caps.erl12
-rw-r--r--src/mod_pubsub/gen_pubsub_node.erl2
-rw-r--r--src/mod_pubsub/mod_pubsub.erl102
-rw-r--r--src/mod_pubsub/node.template9
-rw-r--r--src/mod_pubsub/node_buddy.erl8
-rw-r--r--src/mod_pubsub/node_club.erl9
-rw-r--r--src/mod_pubsub/node_default.erl116
-rw-r--r--src/mod_pubsub/node_dispatch.erl9
-rw-r--r--src/mod_pubsub/node_pep.erl11
-rw-r--r--src/mod_pubsub/node_private.erl9
-rw-r--r--src/mod_pubsub/node_public.erl9
-rw-r--r--src/mod_pubsub/node_zoo.erl177
-rw-r--r--src/web/ejabberd_http.erl14
-rw-r--r--src/web/ejabberd_http_poll.erl40
18 files changed, 484 insertions, 74 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 358b1fe32..5afd6cc53 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -1267,6 +1267,9 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
handle_info({'DOWN', Monitor, _Type, _Object, _Info}, _StateName, StateData)
when Monitor == StateData#state.socket_monitor ->
{stop, normal, StateData};
+handle_info({peername, IP}, StateName, StateData) ->
+ ejabberd_sm:set_session_ip(StateData#state.sid, IP),
+ fsm_next_state(StateName, StateData#state{ip = IP});
handle_info(Info, StateName, StateData) ->
?ERROR_MSG("Unexpected info: ~p", [Info]),
fsm_next_state(StateName, StateData).
diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl
index b54173581..67f5b9636 100644
--- a/src/ejabberd_local.erl
+++ b/src/ejabberd_local.erl
@@ -37,6 +37,7 @@
register_iq_handler/5,
register_iq_response_handler/4,
unregister_iq_handler/2,
+ unregister_iq_response_handler/2,
refresh_iq_handlers/0,
bounce_resource_packet/3
]).
@@ -138,6 +139,9 @@ register_iq_handler(Host, XMLNS, Module, Fun) ->
register_iq_handler(Host, XMLNS, Module, Fun, Opts) ->
ejabberd_local ! {register_iq_handler, Host, XMLNS, Module, Fun, Opts}.
+unregister_iq_response_handler(Host, ID) ->
+ ejabberd_local ! {unregister_iq_response_handler, Host, ID}.
+
unregister_iq_handler(Host, XMLNS) ->
ejabberd_local ! {unregister_iq_handler, Host, XMLNS}.
@@ -214,6 +218,9 @@ handle_info({route, From, To, Packet}, State) ->
handle_info({register_iq_response_handler, _Host, ID, Module, Function}, State) ->
mnesia:dirty_write(#iq_response{id = ID, module = Module, function = Function}),
{noreply, State};
+handle_info({unregister_iq_response_handler, _Host, ID}, State) ->
+ mnesia:dirty_delete({iq_response, ID}),
+ {noreply, State};
handle_info({register_iq_handler, Host, XMLNS, Module, Function}, State) ->
ets:insert(?IQTABLE, {{XMLNS, Host}, Module, Function}),
catch mod_disco:register_feature(Host, XMLNS),
diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl
index 72b3608d6..c178df62a 100644
--- a/src/ejabberd_receiver.erl
+++ b/src/ejabberd_receiver.erl
@@ -269,7 +269,8 @@ code_change(_OldVsn, State, _Extra) ->
%%--------------------------------------------------------------------
activate_socket(#state{socket = Socket,
- sock_mod = SockMod}) ->
+ sock_mod = SockMod,
+ c2s_pid = C2SPid}) ->
PeerName =
case SockMod of
gen_tcp ->
@@ -282,7 +283,8 @@ activate_socket(#state{socket = Socket,
case PeerName of
{error, _Reason} ->
self() ! {tcp_closed, Socket};
- {ok, _} ->
+ {ok, IP} ->
+ C2SPid ! {peername, IP},
ok
end.
diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl
index 2d4b7c5b9..bb543707f 100644
--- a/src/ejabberd_sm.erl
+++ b/src/ejabberd_sm.erl
@@ -49,7 +49,8 @@
ctl_process/2,
get_session_pid/3,
get_user_info/3,
- get_user_ip/3
+ get_user_ip/3,
+ set_session_ip/2
]).
%% gen_server callbacks
@@ -164,6 +165,18 @@ get_user_info(User, Server, Resource) ->
[{node, Node}, {conn, Conn}, {ip, IP}]
end.
+set_session_ip(SID, IP) ->
+ case mnesia:dirty_read(session, SID) of
+ [#session{info = Info} = Session] ->
+ NewInfo = case lists:keymember(ip, 1, Info) of
+ true -> lists:keyreplace(ip, 1, Info, {ip, IP});
+ false -> [{ip, IP}|Info]
+ end,
+ mnesia:dirty_write(Session#session{info = NewInfo});
+ _ ->
+ ok
+ end.
+
set_presence(SID, User, Server, Resource, Priority, Presence, Info) ->
set_session(SID, User, Server, Resource, Priority, Info),
ejabberd_hooks:run(set_presence_hook, jlib:nameprep(Server),
diff --git a/src/mod_caps.erl b/src/mod_caps.erl
index 2be0fac66..3240aa6e2 100644
--- a/src/mod_caps.erl
+++ b/src/mod_caps.erl
@@ -53,6 +53,7 @@
-define(PROCNAME, ejabberd_mod_caps).
-define(DICT, dict).
+-define(CAPS_QUERY_TIMEOUT, 60000). % 1mn without answer, consider client never answer
-record(caps, {node, version, exts}).
-record(caps_features, {node_pair, features}).
@@ -220,6 +221,7 @@ handle_cast({note_caps, From,
ejabberd_local:register_iq_response_handler
(Host, ID, ?MODULE, handle_disco_response),
ejabberd_router:route(jlib:make_jid("", Host, ""), From, Stanza),
+ timer:send_after(?CAPS_QUERY_TIMEOUT, self(), {disco_timeout, ID}),
?DICT:store(ID, {Node, SubNode}, Dict)
end, Requests, Missing),
{noreply, State#state{disco_requests = NewRequests}};
@@ -274,6 +276,16 @@ handle_cast({disco_response, From, _To,
end,
NewRequests = ?DICT:erase(ID, Requests),
{noreply, State#state{disco_requests = NewRequests}};
+handle_cast({disco_timeout, ID}, #state{host = Host, disco_requests = Requests} = State) ->
+ %% do not wait a response anymore for this IQ, client certainly will never answer
+ NewRequests = case ?DICT:is_key(ID, Requests) of
+ true ->
+ ejabberd_local:unregister_iq_response_handler(Host, ID),
+ ?DICT:erase(ID, Requests);
+ false ->
+ Requests
+ end,
+ {noreply, State#state{disco_requests = NewRequests}};
handle_cast(visit_feature_queries, #state{feature_queries = FeatureQueries} = State) ->
Timestamp = timestamp(),
NewFeatureQueries =
diff --git a/src/mod_pubsub/gen_pubsub_node.erl b/src/mod_pubsub/gen_pubsub_node.erl
index 195ed3934..bbbb5c409 100644
--- a/src/mod_pubsub/gen_pubsub_node.erl
+++ b/src/mod_pubsub/gen_pubsub_node.erl
@@ -62,7 +62,9 @@ behaviour_info(callbacks) ->
{get_states, 2},
{get_state, 3},
{set_state, 1},
+ {get_items, 7},
{get_items, 2},
+ {get_item, 8},
{get_item, 3},
{set_item, 1},
{get_item_name, 3}
diff --git a/src/mod_pubsub/mod_pubsub.erl b/src/mod_pubsub/mod_pubsub.erl
index 349c7ad4f..92f5cf959 100644
--- a/src/mod_pubsub/mod_pubsub.erl
+++ b/src/mod_pubsub/mod_pubsub.erl
@@ -30,16 +30,17 @@
%%%
%%% @reference See <a href="http://www.xmpp.org/extensions/xep-0060.html">XEP-0060: Pubsub</a> for
%%% the latest version of the PubSub specification.
-%%% This module uses version 1.10 of the specification as a base.
+%%% This module uses version 1.11 of the specification as a base.
%%% Most of the specification is implemented.
-%%% Code is derivated from the original pubsub v1.7, functions concerning config may be rewritten.
-%%% Code also inspired from the original PEP patch by Magnus Henoch (mangeATfreemail.hu)
+%%% Functions concerning configuration should be rewritten.
+%%% Code is derivated from the original pubsub v1.7, by Alexey Shchepin <alexey@process-one.net>
%%% TODO
%%% plugin: generate Reply (do not use broadcast atom anymore)
-module(mod_pubsub).
--version('1.10-01').
+-author('christophe.romain@process-one.net').
+-version('1.11-01').
-behaviour(gen_server).
-behaviour(gen_mod).
@@ -912,7 +913,17 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, _Lang, Access, Plugins) ->
unsubscribe_node(Host, Node, From, JID, SubId);
{get, "items"} ->
MaxItems = xml:get_attr_s("max_items", Attrs),
- get_items(Host, Node, From, MaxItems);
+ SubId = xml:get_attr_s("subid", Attrs),
+ ItemIDs = lists:foldl(fun
+ ({xmlelement, "item", ItemAttrs, _}, Acc) ->
+ case xml:get_attr_s("id", ItemAttrs) of
+ "" -> Acc;
+ ItemID -> ItemID
+ end;
+ (_, Acc) ->
+ Acc
+ end, [], xml:remove_cdata(Els)),
+ get_items(Host, Node, From, SubId, MaxItems, ItemIDs);
{get, "subscriptions"} ->
get_subscriptions(Host, From, Plugins);
{get, "affiliations"} ->
@@ -1436,7 +1447,7 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) ->
Action = fun(#pubsub_node{options = Options, type = Type}) ->
Features = features(Type),
PublishFeature = lists:member("publish", Features),
- Model = get_option(Options, publish_model),
+ PublishModel = get_option(Options, publish_model),
MaxItems = max_items(Options),
PayloadSize = size(term_to_binary(Payload)),
PayloadMaxSize = get_option(Options, max_payload_size),
@@ -1459,7 +1470,7 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) ->
%% % Publisher attempts to publish to transient notification node with item
%% {error, extended_error(?ERR_BAD_REQUEST, "item-forbidden")};
true ->
- node_call(Type, publish_item, [Host, Node, Publisher, Model, MaxItems, ItemId, Payload])
+ node_call(Type, publish_item, [Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload])
end
end,
%%ejabberd_hooks:run(pubsub_publish_item, Host, [Host, Node, JID, service_jid(Host), ItemId, Payload]),
@@ -1622,7 +1633,7 @@ purge_node(Host, Node, Owner) ->
%% <p>The permission are not checked in this function.</p>
%% @todo We probably need to check that the user doing the query has the right
%% to read the items.
-get_items(Host, Node, _JID, SMaxItems) ->
+get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) ->
MaxItems =
if
SMaxItems == "" -> ?MAXITEMS;
@@ -1636,24 +1647,60 @@ get_items(Host, Node, _JID, SMaxItems) ->
{error, Error} ->
{error, Error};
_ ->
- case get_items(Host, Node) of
- [] ->
- {error, ?ERR_ITEM_NOT_FOUND};
- Items ->
+ Action = fun(#pubsub_node{options = Options, type = Type}) ->
+ Features = features(Type),
+ RetreiveFeature = lists:member("retrieve-items", Features),
+ PersistentFeature = lists:member("persistent-items", Features),
+ AccessModel = get_option(Options, access_model),
+ AllowedGroups = get_option(Options, roster_groups_allowed),
+ {PresenceSubscription, RosterGroup} =
+ case Host of
+ {OUser, OServer, _} ->
+ get_roster_info(OUser, OServer,
+ jlib:jid_tolower(From), AllowedGroups);
+ _ ->
+ {true, true}
+ end,
+ if
+ not RetreiveFeature ->
+ %% Item Retrieval Not Supported
+ {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "retrieve-items")};
+ not PersistentFeature ->
+ %% Persistent Items Not Supported
+ {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "persistent-items")};
+ true ->
+ node_call(Type, get_items,
+ [Host, Node, From,
+ AccessModel, PresenceSubscription, RosterGroup,
+ SubId])
+ end
+ end,
+ case transaction(Host, Node, Action, sync_dirty) of
+ {error, Reason} ->
+ {error, Reason};
+ {result, Items} ->
+ SendItems = case ItemIDs of
+ [] ->
+ Items;
+ _ ->
+ lists:filter(fun(Item) ->
+ lists:member(Item, ItemIDs)
+ end, Items)
+ end,
%% Generate the XML response (Item list), limiting the
%% number of items sent to MaxItems:
ItemsEls = lists:map(
- fun(#pubsub_item{itemid = {ItemId, _},
- payload = Payload}) ->
- ItemAttrs = case ItemId of
- "" -> [];
- _ -> [{"id", ItemId}]
- end,
- {xmlelement, "item", ItemAttrs, Payload}
- end, lists:sublist(Items, MaxItems)),
+ fun(#pubsub_item{itemid = {ItemId, _},
+ payload = Payload}) ->
+ ItemAttrs = case ItemId of
+ "" -> [];
+ _ -> [{"id", ItemId}]
+ end,
+ {xmlelement, "item", ItemAttrs, Payload}
+ end, lists:sublist(SendItems, MaxItems)),
{result, [{xmlelement, "pubsub", [{"xmlns", ?NS_PUBSUB}],
- [{xmlelement, "items", [{"node", node_to_string(Node)}],
- ItemsEls}]}]}
+ [{xmlelement, "items", [{"node", node_to_string(Node)}],
+ ItemsEls}]}]}
end
end.
@@ -1809,7 +1856,7 @@ set_affiliations(Host, Node, From, EntitiesEls) ->
end, Entities),
{result, []};
_ ->
- {error, ?ERR_NOT_ALLOWED}
+ {error, ?ERR_FORBIDDEN}
end
end,
transaction(Host, Node, Action, sync_dirty)
@@ -1870,7 +1917,7 @@ get_subscriptions(Host, Node, JID) ->
%% Service does not support manage subscriptions
{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, "manage-affiliations")};
Affiliation /= {result, owner} ->
- % Entity is not an owner
+ %% Entity is not an owner
{error, ?ERR_FORBIDDEN};
true ->
node_call(Type, get_node_subscriptions, [Host, Node])
@@ -1938,7 +1985,7 @@ set_subscriptions(Host, Node, From, EntitiesEls) ->
end, Entities),
{result, []};
_ ->
- {error, ?ERR_NOT_ALLOWED}
+ {error, ?ERR_FORBIDDEN}
end
end,
transaction(Host, Node, Action, sync_dirty)
@@ -2438,6 +2485,7 @@ get_configure_xfields(_Type, Options, Lang, _Owners) ->
?BOOL_CONFIG_FIELD("Notify subscribers when the node is deleted", notify_delete),
?BOOL_CONFIG_FIELD("Notify subscribers when items are removed from the node", notify_retract),
?BOOL_CONFIG_FIELD("Persist items to storage", persist_items),
+ ?STRING_CONFIG_FIELD("A friendly name for the node", title),
?INTEGER_CONFIG_FIELD("Max # of items to persist", max_items),
?BOOL_CONFIG_FIELD("Whether to allow subscriptions", subscribe),
?ALIST_CONFIG_FIELD("Specify the access model", access_model,
@@ -2605,7 +2653,7 @@ features() ->
[
%"access-authorize", % OPTIONAL
"access-open", % OPTIONAL this relates to access_model option in node_default
- %"access-presence", % OPTIONAL
+ "access-presence", % OPTIONAL this relates to access_model option in node_pep
%"access-roster", % OPTIONAL
%"access-whitelist", % OPTIONAL
% see plugin "auto-create", % OPTIONAL
@@ -2619,7 +2667,7 @@ features() ->
% see plugin "filtered-notifications", % RECOMMENDED
%TODO "get-pending", % OPTIONAL
% see plugin "instant-nodes", % RECOMMENDED
- %TODO "item-ids", % RECOMMENDED
+ "item-ids", % RECOMMENDED
"last-published", % RECOMMENDED
%TODO "cache-last-item",
%TODO "leased-subscription", % OPTIONAL
diff --git a/src/mod_pubsub/node.template b/src/mod_pubsub/node.template
index 850a38ec9..973aa38a4 100644
--- a/src/mod_pubsub/node.template
+++ b/src/mod_pubsub/node.template
@@ -61,7 +61,9 @@
get_states/2,
get_state/3,
set_state/1,
+ get_items/7,
get_items/2,
+ get_item/8,
get_item/3,
set_item/1
]).
@@ -94,7 +96,6 @@ features() ->
["create-nodes",
"delete-nodes",
"instant-nodes",
- "item-ids",
"outcast-affiliation",
"persistent-items",
"publish",
@@ -170,8 +171,14 @@ set_state(State) ->
get_items(Host, Node) ->
node_default:get_items(Host, Node).
+get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId)
+ node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
get_item(Host, Node, ItemId) ->
node_default:get_item(Host, Node, ItemId).
+get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
set_item(Item) ->
node_default:set_item(Item).
diff --git a/src/mod_pubsub/node_buddy.erl b/src/mod_pubsub/node_buddy.erl
index cdf3a696f..cd051b66f 100644
--- a/src/mod_pubsub/node_buddy.erl
+++ b/src/mod_pubsub/node_buddy.erl
@@ -62,7 +62,9 @@
get_states/2,
get_state/3,
set_state/1,
+ get_items/7,
get_items/2,
+ get_item/8,
get_item/3,
set_item/1,
get_item_name/3
@@ -172,9 +174,15 @@ set_state(State) ->
get_items(Host, Node) ->
node_default:get_items(Host, Node).
+get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
get_item(Host, Node, ItemId) ->
node_default:get_item(Host, Node, ItemId).
+get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
set_item(Item) ->
node_default:set_item(Item).
diff --git a/src/mod_pubsub/node_club.erl b/src/mod_pubsub/node_club.erl
index d927053fb..155edc10a 100644
--- a/src/mod_pubsub/node_club.erl
+++ b/src/mod_pubsub/node_club.erl
@@ -62,7 +62,9 @@
get_states/2,
get_state/3,
set_state/1,
+ get_items/7,
get_items/2,
+ get_item/8,
get_item/3,
set_item/1,
get_item_name/3
@@ -96,7 +98,6 @@ features() ->
["create-nodes",
"delete-nodes",
"instant-nodes",
- "item-ids",
"outcast-affiliation",
"persistent-items",
"publish",
@@ -172,9 +173,15 @@ set_state(State) ->
get_items(Host, Node) ->
node_default:get_items(Host, Node).
+get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
get_item(Host, Node, ItemId) ->
node_default:get_item(Host, Node, ItemId).
+get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
set_item(Item) ->
node_default:set_item(Item).
diff --git a/src/mod_pubsub/node_default.erl b/src/mod_pubsub/node_default.erl
index fc4194c32..491676269 100644
--- a/src/mod_pubsub/node_default.erl
+++ b/src/mod_pubsub/node_default.erl
@@ -69,7 +69,9 @@
get_states/2,
get_state/3,
set_state/1,
+ get_items/7,
get_items/2,
+ get_item/8,
get_item/3,
set_item/1,
get_item_name/3
@@ -158,7 +160,6 @@ features() ->
"auto-create",
"delete-nodes",
"instant-nodes",
- "item-ids",
"manage-subscriptions",
"modify-affiliations",
"outcast-affiliation",
@@ -192,18 +193,14 @@ features() ->
%% module by implementing this function like this:
%% ```check_create_user_permission(Host, Node, Owner, Access) ->
%% node_default:check_create_user_permission(Host, Node, Owner, Access).'''</p>
-create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) ->
+create_node_permission(_Host, ServerHost, Node, _ParentNode, Owner, Access) ->
LOwner = jlib:jid_tolower(Owner),
{User, Server, _Resource} = LOwner,
Allowed = case acl:match_rule(ServerHost, Access, LOwner) of
allow ->
- if Server == Host -> %% Server == ServerHost ??
- true;
- true ->
- case Node of
- ["home", Server, User | _] -> true;
- _ -> false
- end
+ case Node of
+ ["home", Server, User | _] -> true;
+ _ -> false
end;
_ ->
case Owner of
@@ -211,8 +208,7 @@ create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) ->
_ -> false
end
end,
- ChildOK = true, %% TODO test with ParentNode
- {result, Allowed and ChildOK}.
+ {result, Allowed}.
%% @spec (Host, Node, Owner) ->
%% {result, Result} | exit
@@ -297,12 +293,12 @@ subscribe_node(Host, Node, Sender, Subscriber, AccessModel,
not Authorized ->
%% JIDs do not match
{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "invalid-jid")};
- Subscription == pending ->
- %% Requesting entity has pending subscription
- {error, ?ERR_EXTENDED(?ERR_NOT_AUTHORIZED, "pending-subscription")};
Affiliation == outcast ->
%% Requesting entity is blocked
{error, ?ERR_FORBIDDEN};
+ Subscription == pending ->
+ %% Requesting entity has pending subscription
+ {error, ?ERR_EXTENDED(?ERR_NOT_AUTHORIZED, "pending-subscription")};
(AccessModel == presence) and (not PresenceSubscription) ->
%% Entity is not authorized to create a subscription (presence subscription required)
{error, ?ERR_EXTENDED(?ERR_NOT_AUTHORIZED, "presence-subscription-required")};
@@ -446,6 +442,7 @@ publish_item(Host, Node, Publisher, PublishModel, MaxItems, ItemId, Payload) ->
{error, ?ERR_FORBIDDEN};
true ->
PubId = {PublisherKey, now()},
+ %% TODO: check creation, presence, roster (EJAB-663)
Item = case get_item(Host, Node, ItemId) of
{error, ?ERR_ITEM_NOT_FOUND} ->
#pubsub_item{itemid = {ItemId, {Host, Node}},
@@ -501,7 +498,7 @@ remove_extra_items(Host, Node, MaxItems, ItemIds) ->
%% ItemId = string()
%% @doc <p>Triggers item deletion.</p>
%% <p>Default plugin: The user performing the deletion must be the node owner
-%% or a node publisher e item publisher.</p>
+%% or a publisher.</p>
delete_item(Host, Node, Publisher, ItemId) ->
PublisherKey = jlib:jid_tolower(jlib:jid_remove_resource(Publisher)),
State = case get_state(Host, Node, PublisherKey) of
@@ -542,17 +539,16 @@ delete_item(Host, Node, Publisher, ItemId) ->
purge_node(Host, Node, Owner) ->
OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
case get_state(Host, Node, OwnerKey) of
- {error, ?ERR_ITEM_NOT_FOUND} ->
- %% This should not append (case node does not exists)
- {error, ?ERR_ITEM_NOT_FOUND};
{result, #pubsub_state{items = Items, affiliation = owner}} ->
lists:foreach(fun(ItemId) ->
mnesia:delete({pubsub_item, {ItemId, {Host, Node}}})
end, Items),
{result, {default, broadcast}};
+ {result, _} ->
+ %% Entity is not owner
+ {error, ?ERR_FORBIDDEN};
_ ->
- %% Entity is not an owner
- {error, ?ERR_FORBIDDEN}
+ {error, ?ERR_ITEM_NOT_FOUND}
end.
%% @spec (Host, JID) -> [{Node,Affiliation}]
@@ -588,7 +584,7 @@ get_affiliation(Host, Node, Owner) ->
OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
Affiliation = case get_state(Host, Node, OwnerKey) of
{result, #pubsub_state{affiliation = A}} -> A;
- _ -> unknown
+ _ -> none
end,
{result, Affiliation}.
@@ -638,7 +634,7 @@ get_subscription(Host, Node, Owner) ->
OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
Subscription = case get_state(Host, Node, OwnerKey) of
{result, #pubsub_state{subscription = S}} -> S;
- _ -> unknown
+ _ -> none
end,
{result, Subscription}.
@@ -713,6 +709,44 @@ get_items(Host, Node) ->
Items = mnesia:match_object(
#pubsub_item{itemid = {'_', {Host, Node}}, _ = '_'}),
{result, Items}.
+get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) ->
+ {Affiliation, Subscription} =
+ case get_state(Host, Node, jlib:jid_tolower(jlib:jid_remove_resource(JID))) of
+ {result, #pubsub_state{affiliation = A, subscription = S}} -> {A, S};
+ _ -> {none, none}
+ end,
+ Subscribed = not ((Subscription == none) or (Subscription == pending)),
+ if
+ %%SubID == "", ?? ->
+ %% Entity has multiple subscriptions to the node but does not specify a subscription ID
+ %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
+ %%InvalidSubID ->
+ %% Entity is subscribed but specifies an invalid subscription ID
+ %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
+ Affiliation == outcast ->
+ %% Requesting entity is blocked
+ {error, ?ERR_FORBIDDEN};
+ (AccessModel == open) and (not Subscribed) ->
+ %% Entity is not subscribed
+ {error, ?ERR_EXTENDED(?ERR_NOT_AUTHORIZED, "not-subscribed")};
+ (AccessModel == presence) and (not PresenceSubscription) ->
+ %% Entity is not authorized to create a subscription (presence subscription required)
+ {error, ?ERR_EXTENDED(?ERR_NOT_AUTHORIZED, "presence-subscription-required")};
+ (AccessModel == roster) and (not RosterGroup) ->
+ %% Entity is not authorized to create a subscription (not in roster group)
+ {error, ?ERR_EXTENDED(?ERR_NOT_AUTHORIZED, "not-in-roster-group")};
+ (AccessModel == whitelist) -> % TODO: to be done
+ %% Node has whitelist access model
+ {error, ?ERR_EXTENDED(?ERR_NOT_ALLOWED, "closed-node")};
+ (AccessModel == authorize) -> % TODO: to be done
+ %% Node has authorize access model
+ {error, ?ERR_FORBIDDEN};
+ %%MustPay ->
+ %% % Payment is required for a subscription
+ %% {error, ?ERR_PAYMENT_REQUIRED};
+ true ->
+ get_items(Host, Node)
+ end.
%% @spec (Host, Node, ItemId) -> [Item] | []
%% Host = mod_pubsub:host()
@@ -727,6 +761,44 @@ get_item(Host, Node, ItemId) ->
_ ->
{error, ?ERR_ITEM_NOT_FOUND}
end.
+get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) ->
+ {Affiliation, Subscription} =
+ case get_state(Host, Node, jlib:jid_tolower(jlib:jid_remove_resource(JID))) of
+ {result, #pubsub_state{affiliation = A, subscription = S}} -> {A, S};
+ _ -> {none, none}
+ end,
+ Subscribed = not ((Subscription == none) or (Subscription == pending)),
+ if
+ %%SubID == "", ?? ->
+ %% Entity has multiple subscriptions to the node but does not specify a subscription ID
+ %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")};
+ %%InvalidSubID ->
+ %% Entity is subscribed but specifies an invalid subscription ID
+ %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")};
+ Affiliation == outcast ->
+ %% Requesting entity is blocked
+ {error, ?ERR_FORBIDDEN};
+ (AccessModel == open) and (not Subscribed) ->
+ %% Entity is not subscribed
+ {error, ?ERR_EXTENDED(?ERR_NOT_AUTHORIZED, "not-subscribed")};
+ (AccessModel == presence) and (not PresenceSubscription) ->
+ %% Entity is not authorized to create a subscription (presence subscription required)
+ {error, ?ERR_EXTENDED(?ERR_NOT_AUTHORIZED, "presence-subscription-required")};
+ (AccessModel == roster) and (not RosterGroup) ->
+ %% Entity is not authorized to create a subscription (not in roster group)
+ {error, ?ERR_EXTENDED(?ERR_NOT_AUTHORIZED, "not-in-roster-group")};
+ (AccessModel == whitelist) -> % TODO: to be done
+ %% Node has whitelist access model
+ {error, ?ERR_EXTENDED(?ERR_NOT_ALLOWED, "closed-node")};
+ (AccessModel == authorize) -> % TODO: to be done
+ %% Node has authorize access model
+ {error, ?ERR_FORBIDDEN};
+ %%MustPay ->
+ %% % Payment is required for a subscription
+ %% {error, ?ERR_PAYMENT_REQUIRED};
+ true ->
+ get_item(Host, Node, ItemId)
+ end.
%% @spec (Item) -> ok | {error, Reason::stanzaError()}
%% Item = mod_pubsub:pubsubItems()
diff --git a/src/mod_pubsub/node_dispatch.erl b/src/mod_pubsub/node_dispatch.erl
index 3b4418c3e..0532826d2 100644
--- a/src/mod_pubsub/node_dispatch.erl
+++ b/src/mod_pubsub/node_dispatch.erl
@@ -60,7 +60,9 @@
get_states/2,
get_state/3,
set_state/1,
+ get_items/7,
get_items/2,
+ get_item/8,
get_item/3,
set_item/1,
get_item_name/3
@@ -94,7 +96,6 @@ features() ->
["create-nodes",
"delete-nodes",
"instant-nodes",
- "item-ids",
"outcast-affiliation",
"persistent-items",
"publish",
@@ -175,9 +176,15 @@ set_state(State) ->
get_items(Host, Node) ->
node_default:get_items(Host, Node).
+get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
get_item(Host, Node, ItemId) ->
node_default:get_item(Host, Node, ItemId).
+get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
set_item(Item) ->
node_default:set_item(Item).
diff --git a/src/mod_pubsub/node_pep.erl b/src/mod_pubsub/node_pep.erl
index 2fceb03ed..2c648148d 100644
--- a/src/mod_pubsub/node_pep.erl
+++ b/src/mod_pubsub/node_pep.erl
@@ -58,7 +58,9 @@
get_states/2,
get_state/3,
set_state/1,
+ get_items/7,
get_items/2,
+ get_item/8,
get_item/3,
set_item/1,
get_item_name/3
@@ -96,7 +98,6 @@ features() ->
"auto-subscribe", %*
"delete-nodes", %*
"filtered-notifications", %*
- "item-ids",
"modify-affiliations",
"outcast-affiliation",
"persistent-items",
@@ -185,7 +186,7 @@ get_node_subscriptions(_Host, _Node) ->
{result, []}.
get_subscription(_Host, _Node, _Owner) ->
- {result, unknown}.
+ {result, none}.
set_subscription(_Host, _Node, _Owner, _Subscription) ->
ok.
@@ -202,9 +203,15 @@ set_state(State) ->
get_items(Host, Node) ->
node_default:get_items(Host, Node).
+get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
get_item(Host, Node, ItemId) ->
node_default:get_item(Host, Node, ItemId).
+get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
set_item(Item) ->
node_default:set_item(Item).
diff --git a/src/mod_pubsub/node_private.erl b/src/mod_pubsub/node_private.erl
index 35f63c925..00e952392 100644
--- a/src/mod_pubsub/node_private.erl
+++ b/src/mod_pubsub/node_private.erl
@@ -62,7 +62,9 @@
get_states/2,
get_state/3,
set_state/1,
+ get_items/7,
get_items/2,
+ get_item/8,
get_item/3,
set_item/1,
get_item_name/3
@@ -96,7 +98,6 @@ features() ->
["create-nodes",
"delete-nodes",
"instant-nodes",
- "item-ids",
"outcast-affiliation",
"persistent-items",
"publish",
@@ -175,9 +176,15 @@ set_state(State) ->
get_items(Host, Node) ->
node_default:get_items(Host, Node).
+get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
get_item(Host, Node, ItemId) ->
node_default:get_item(Host, Node, ItemId).
+get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
set_item(Item) ->
node_default:set_item(Item).
diff --git a/src/mod_pubsub/node_public.erl b/src/mod_pubsub/node_public.erl
index 1586abe86..ab4107a76 100644
--- a/src/mod_pubsub/node_public.erl
+++ b/src/mod_pubsub/node_public.erl
@@ -62,7 +62,9 @@
get_states/2,
get_state/3,
set_state/1,
+ get_items/7,
get_items/2,
+ get_item/8,
get_item/3,
set_item/1,
get_item_name/3
@@ -96,7 +98,6 @@ features() ->
["create-nodes",
"delete-nodes",
"instant-nodes",
- "item-ids",
"outcast-affiliation",
"persistent-items",
"publish",
@@ -172,9 +173,15 @@ set_state(State) ->
get_items(Host, Node) ->
node_default:get_items(Host, Node).
+get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
get_item(Host, Node, ItemId) ->
node_default:get_item(Host, Node, ItemId).
+get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
set_item(Item) ->
node_default:set_item(Item).
diff --git a/src/mod_pubsub/node_zoo.erl b/src/mod_pubsub/node_zoo.erl
new file mode 100644
index 000000000..1cb8a73cb
--- /dev/null
+++ b/src/mod_pubsub/node_zoo.erl
@@ -0,0 +1,177 @@
+%%% ====================================================================
+%%% ``The contents of this file are subject to the Erlang Public License,
+%%% Version 1.1, (the "License"); you may not use this file except in
+%%% compliance with the License. You should have received a copy of the
+%%% Erlang Public License along with this software. If not, it can be
+%%% retrieved via the world wide web at http://www.erlang.org/.
+%%%
+%%% Software distributed under the License is distributed on an "AS IS"
+%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%%% the License for the specific language governing rights and limitations
+%%% under the License.
+%%%
+%%% The Initial Developer of the Original Code is Process-one.
+%%% Portions created by Process-one are Copyright 2006-2008, Process-one
+%%% All Rights Reserved.''
+%%% This software is copyright 2006-2008, Process-one.
+%%%
+%%% @copyright 2006-2008 Process-one
+%%% @author Christophe romain <christophe.romain@process-one.net>
+%%% [http://www.process-one.net/]
+%%% @version {@vsn}, {@date} {@time}
+%%% @end
+%%% ====================================================================
+
+-module(node_zoo).
+-author('christophe.romain@process-one.net').
+
+-include("pubsub.hrl").
+-include("jlib.hrl").
+
+-behaviour(gen_pubsub_node).
+
+%% API definition
+-export([init/3, terminate/2,
+ options/0, features/0,
+ create_node_permission/6,
+ create_node/3,
+ delete_node/2,
+ purge_node/3,
+ subscribe_node/8,
+ unsubscribe_node/5,
+ publish_item/7,
+ delete_item/4,
+ remove_extra_items/4,
+ get_entity_affiliations/2,
+ get_node_affiliations/2,
+ get_affiliation/3,
+ set_affiliation/4,
+ get_entity_subscriptions/2,
+ get_node_subscriptions/2,
+ get_subscription/3,
+ set_subscription/4,
+ get_states/2,
+ get_state/3,
+ set_state/1,
+ get_items/7,
+ get_items/2,
+ get_item/8,
+ get_item/3,
+ set_item/1
+ ]).
+
+
+init(Host, ServerHost, Opts) ->
+ node_default:init(Host, ServerHost, Opts).
+
+terminate(Host, ServerHost) ->
+ node_default:terminate(Host, ServerHost).
+
+options() ->
+ [{node_type, zoo},
+ {deliver_payloads, true},
+ {notify_config, false},
+ {notify_delete, false},
+ {notify_retract, true},
+ {persist_items, true},
+ {max_items, ?MAXITEMS div 2},
+ {subscribe, true},
+ {access_model, open},
+ {roster_groups_allowed, []},
+ {publish_model, publishers},
+ {max_payload_size, ?MAX_PAYLOAD_SIZE},
+ {send_last_published_item, never},
+ {deliver_notifications, true},
+ {presence_based_delivery, false}].
+
+features() ->
+ node_default:features().
+
+%% use same code as node_default, but do not limite node to
+%% the home/localhost/user/... hierarchy
+%% any node is allowed
+create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) ->
+ LOwner = jlib:jid_tolower(Owner),
+ {User, Server, _Resource} = LOwner,
+ Allowed = case acl:match_rule(ServerHost, Access, LOwner) of
+ allow ->
+ true;
+ _ ->
+ case Owner of
+ {jid, "", _, "", "", _, ""} -> true;
+ _ -> false
+ end
+ end,
+ {result, Allowed}.
+
+create_node(Host, Node, Owner) ->
+ node_default:create_node(Host, Node, Owner).
+
+delete_node(Host, Removed) ->
+ node_default:delete_node(Host, Removed).
+
+subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup) ->
+ node_default:subscribe_node(Host, Node, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup).
+
+unsubscribe_node(Host, Node, Sender, Subscriber, SubID) ->
+ node_default:unsubscribe_node(Host, Node, Sender, Subscriber, SubID).
+
+publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload) ->
+ node_default:publish_item(Host, Node, Publisher, Model, MaxItems, ItemId, Payload).
+
+remove_extra_items(Host, Node, MaxItems, ItemIds) ->
+ node_default:remove_extra_items(Host, Node, MaxItems, ItemIds).
+
+delete_item(Host, Node, JID, ItemId) ->
+ node_default:delete_item(Host, Node, JID, ItemId).
+
+purge_node(Host, Node, Owner) ->
+ node_default:purge_node(Host, Node, Owner).
+
+get_entity_affiliations(Host, Owner) ->
+ node_default:get_entity_affiliations(Host, Owner).
+
+get_node_affiliations(Host, Node) ->
+ node_default:get_node_affiliations(Host, Node).
+
+get_affiliation(Host, Node, Owner) ->
+ node_default:get_affiliation(Host, Node, Owner).
+
+set_affiliation(Host, Node, Owner, Affiliation) ->
+ node_default:set_affiliation(Host, Node, Owner, Affiliation).
+
+get_entity_subscriptions(Host, Owner) ->
+ node_default:get_entity_subscriptions(Host, Owner).
+
+get_node_subscriptions(Host, Node) ->
+ node_default:get_node_subscriptions(Host, Node).
+
+get_subscription(Host, Node, Owner) ->
+ node_default:get_subscription(Host, Node, Owner).
+
+set_subscription(Host, Node, Owner, Subscription) ->
+ node_default:set_subscription(Host, Node, Owner, Subscription).
+
+get_states(Host, Node) ->
+ node_default:get_states(Host, Node).
+
+get_state(Host, Node, JID) ->
+ node_default:get_state(Host, Node, JID).
+
+set_state(State) ->
+ node_default:set_state(State).
+
+get_items(Host, Node) ->
+ node_default:get_items(Host, Node).
+
+get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_items(Host, Node, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
+get_item(Host, Node, ItemId) ->
+ node_default:get_item(Host, Node, ItemId).
+
+get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) ->
+ node_default:get_item(Host, Node, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId).
+
+set_item(Item) ->
+ node_default:set_item(Item).
diff --git a/src/web/ejabberd_http.erl b/src/web/ejabberd_http.erl
index 51384a216..34eeef739 100644
--- a/src/web/ejabberd_http.erl
+++ b/src/web/ejabberd_http.erl
@@ -290,7 +290,7 @@ process_request(#state{request_method = Method,
LQ
end,
LPath = string:tokens(NPath, "/"),
- {ok, {IP, _Port}} =
+ {ok, IP} =
case SockMod of
gen_tcp ->
inet:peername(Socket);
@@ -302,7 +302,7 @@ process_request(#state{request_method = Method,
q = LQuery,
auth = Auth,
lang = Lang,
- ip=IP},
+ ip = IP},
%% XXX bard: This previously passed control to
%% ejabberd_web:process_get, now passes it to a local
%% procedure (process) that handles dispatching based on
@@ -348,12 +348,20 @@ process_request(#state{request_method = Method,
LQ ->
LQ
end,
+ {ok, IP} =
+ case SockMod of
+ gen_tcp ->
+ inet:peername(Socket);
+ _ ->
+ SockMod:peername(Socket)
+ end,
Request = #request{method = Method,
path = LPath,
q = LQuery,
auth = Auth,
data = Data,
- lang = Lang},
+ lang = Lang,
+ ip = IP},
case process(RequestHandlers, Request) of
El when element(1, El) == xmlelement ->
make_xhtml_output(State, 200, [], El);
diff --git a/src/web/ejabberd_http_poll.erl b/src/web/ejabberd_http_poll.erl
index f5b419275..d93bec791 100644
--- a/src/web/ejabberd_http_poll.erl
+++ b/src/web/ejabberd_http_poll.erl
@@ -50,13 +50,16 @@
-record(http_poll, {id, pid}).
+-define(NULL_PEER, {{0, 0, 0, 0}, 0}).
+
-record(state, {id,
key,
output = "",
input = "",
waiting_input = false, %% {ReceiverPid, Tag}
last_receiver,
- timer}).
+ timer,
+ ip = ?NULL_PEER }).
%-define(DBGFSM, true).
@@ -94,11 +97,18 @@ setopts({http_poll, FsmRef}, Opts) ->
ok
end.
-sockname(_Socket) ->
- {ok, {{0, 0, 0, 0}, 0}}.
+sockname(_) ->
+ {ok, ?NULL_PEER}.
-peername(_Socket) ->
- {ok, {{0, 0, 0, 0}, 0}}.
+peername({http_poll, FsmRef}) ->
+ gen_fsm:send_all_state_event(FsmRef, {peername, self()}),
+ %% XXX should improve that, but sync call seems not possible
+ receive
+ {peername, PeerName} -> {ok, PeerName}
+ after 1000 -> {ok, ?NULL_PEER}
+ end;
+peername(_) ->
+ {ok, ?NULL_PEER}.
controlling_process(_Socket, _Pid) ->
ok.
@@ -107,7 +117,7 @@ close({http_poll, FsmRef}) ->
catch gen_fsm:sync_send_all_state_event(FsmRef, close).
-process([], #request{data = Data} = _Request) ->
+process([], #request{data = Data, ip = IP} = _Request) ->
case catch parse_request(Data) of
{ok, ID1, Key, NewKey, Packet} ->
ID = if
@@ -123,7 +133,7 @@ process([], #request{data = Data} = _Request) ->
true ->
ID1
end,
- case http_put(ID, Key, NewKey, Packet) of
+ case http_put(ID, Key, NewKey, Packet, IP) of
{error, not_exists} ->
{200, ?BAD_REQUEST, ""};
{error, bad_key} ->
@@ -228,6 +238,10 @@ handle_event({activate, From}, StateName, StateData) ->
}}
end;
+handle_event({peername, From}, StateName, StateData) ->
+ From ! {peername, StateData#state.ip},
+ {next_state, StateName, StateData};
+
handle_event(_Event, StateName, StateData) ->
{next_state, StateName, StateData}.
@@ -249,7 +263,7 @@ handle_sync_event(stop, _From, _StateName, StateData) ->
Reply = ok,
{stop, normal, Reply, StateData};
-handle_sync_event({http_put, Key, NewKey, Packet},
+handle_sync_event({http_put, Key, NewKey, Packet, IP},
_From, StateName, StateData) ->
Allow = case StateData#state.key of
"" ->
@@ -271,7 +285,8 @@ handle_sync_event({http_put, Key, NewKey, Packet},
Input = [StateData#state.input|Packet],
Reply = ok,
{reply, Reply, StateName, StateData#state{input = Input,
- key = NewKey}};
+ key = NewKey,
+ ip = IP}};
{Receiver, _Tag} ->
Receiver ! {tcp, {http_poll, self()},
list_to_binary(Packet)},
@@ -282,7 +297,8 @@ handle_sync_event({http_put, Key, NewKey, Packet},
StateData#state{waiting_input = false,
last_receiver = Receiver,
key = NewKey,
- timer = Timer}}
+ timer = Timer,
+ ip = IP}}
end;
true ->
Reply = {error, bad_key},
@@ -343,13 +359,13 @@ terminate(_Reason, _StateName, StateData) ->
%%% Internal functions
%%%----------------------------------------------------------------------
-http_put(ID, Key, NewKey, Packet) ->
+http_put(ID, Key, NewKey, Packet, IP) ->
case mnesia:dirty_read({http_poll, ID}) of
[] ->
{error, not_exists};
[#http_poll{pid = FsmRef}] ->
gen_fsm:sync_send_all_state_event(
- FsmRef, {http_put, Key, NewKey, Packet})
+ FsmRef, {http_put, Key, NewKey, Packet, IP})
end.
http_get(ID) ->