我正在编写一个ejabberd模块来过滤数据包。我需要使用gen_mod:get_module_opt()
获取主机名来提取一些配置。
我有4个重要的功能:
start(Host, _Opt)
:这是一个加载我的模块的ejabberd函数。我在这里得到Host
原子filter_packet({From, To, XML})
:这是我的数据包过滤器挂钩。我无法将自定义参数传递给此函数,因为它是ejabberd中的一个钩子。get_translation(XmlData)
:filter_packet()
在循环中调用get_translation()
fetch_translation(XmlData)
:从get_translation()
递归调用。这是我呼叫gen_mod:get_module_opt()
的地方,因此需要Host
。我的问题是,如何从Host
获取start()
并将其放入全局变量中,以便fetch_translation
可以访问它?
答案 0 :(得分:9)
“最简单的方法”是创建一个命名的ets表,并将其放在那里。
start(Host, _Opt) ->
ets:new(my_table, [named_table, protected, set, {keypos, 1}]),
ets:insert(my_table, {host, Host}),
...
fetch_translation(XmlData) ->
[{_, Host}] = ets:lookup(my_table, host),
...
请注意,这是一种“通用”解决方案。 Ejabberd可能会提供你想要的设施,但我无法帮助你。
答案 1 :(得分:9)
听起来有点矫枉过正,但您可以考虑实施一个非常基本的gen_server。它包含一个可用于其回调的状态,并且数据可以保存在那里。对于您的情况,您可以编写与此类似的模块:
-module(your_module_name).
-behaviour(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([start/2, filter_loop/1]).
start(Host, Opt) ->
%% start the named gen server
gen_server:start({local, ?MODULE}, ?MODULE, Host, []).
filter_packet({From, To, XML}) ->
%% do your thing
gen_server:call(?MODULE, {fetch_translation, XmlData}).
%% this will be called by gen_server:start - just pass the Host
init(Host) ->
{ok, Host}.
handle_call({fetch_translation, XmlData}, _From, Host) ->
%% do your thing
{reply, ok, Host}.
%% you can ignore the rest - they are needed to be present
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
答案 2 :(得分:1)
您可以启动新的邮件过滤流程并使用erlang:register/2
进行注册,然后通过它路由所有filter_packet/1
个请求(潜在的瓶颈)。
-define(?SERVER, msg_filter).
start(Host, Opt) ->
{ok, Pid} = spawn(?MODULE, filter_loop, [Host, Opt]),
register(?SERVER, Pid).
filter_loop(Host, Opt) ->
receive
{Pid, filter_packet, {_From, _To, XML}} ->
Trans = get_translation(XML, Host),
Pid ! {?SERVER, translation, Trans},
filter_loop(Host, Opt)
end.
filter_packet(Pack) ->
?SERVER ! {self(), filter_packet, Pack}
receive
{?SERVER, translation, Trans} ->
% wrap translation
UpdatedPacket
end.
答案 3 :(得分:1)
假设您正在过滤传入的数据包,那么#jid.lserver可能是您的主机。
答案 4 :(得分:1)
猜测您的描述而不是单域ejabberd部署(无虚拟主机),
你可以使用?MYNAME宏获取本地XMPP域(有关定义,请参阅ejabberd.hrl)。
答案 5 :(得分:1)
您可以在模块顶部定义全局变量...如下所示
-define (Your Variable, "your host name here").
例如
-define (RelayHost, "smtp.gmail.com").
您可以在模块中的所有方法中使用此Global变量。
io:fwrite("Global Value ~p", [?RelayHost]).
-AjAy
答案 6 :(得分:0)
您不能创建全局变量,但您可以在函数之外定义一条记录,并使用属性创建该记录的实例,然后将其传递给您调用的方法。因此,您只能通过方法参数共享一条记录。
答案 7 :(得分:0)
尝试使用persistent_term:
1> persistent_term:put(hello, <<"world">>).
ok
2> persistent_term:get(hello).
<<"world">>
3> persistent_term:erase(hello).
true
4> persistent_term:get(hello).
** exception error: bad argument
in function persistent_term:get/1
called as persistent_term:get(hello)