views:

647

answers:

4

Hi,

I am writing an ejabberd module to filter packets. I need to get the hostname to pull some configs using gen_mod:get_module_opt() .

I have 4 important functions :

  1. start(Host, _Opt) : This is an ejabberd function to load my module. I get the 'Host' atom here
  2. filter_packet({From, To, XML}) : This is my packet filter hook. I cannot pass custom params to this function, as it is a hook in ejabberd.
  3. get_translation(XmlData) : 'filter_packet()' calls 'get_translation()' in a loop
  4. fetch_translation( XmlData ) : called recursively from 'get_translation()'. This is where i am calling 'gen_mod:get_module_opt()', and hence need the 'Host'.

My question is, how can i take 'Host' from 'start()' and put it in a global variable, so that 'fetch_translation' can access it.

PS: I'm a newbie at erlang

Thanks, Adil

+2  A: 

The "easiest way" is to create a named ets table, and put it in there.

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),
  ...

Note that this is a "general" solution. Ejabberd might provide facilities for what you want, but I cannot help you with that.

Zed
Thx zed.The module compiles ok but gives a 'badarg' error for 'ets:new(my_table, [named_table, protected, set, {keypos, 1}]),'
Adil
If table 'my_table' exists, you will get a badarg. You either need to check if the table already exists, or wrap it in a try-catch block
Zed
I'm not creating 'my_table' anywhere, except as given above.
Adil
A: 

You could start a new message filtering process and register it using erlang:register/2, then route all filter_packet/1 requests through it (a potential bottleneck).

-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.
Felix Lange
A: 

Say you are filtering incoming packets, then To#jid.lserver might be your host.

Hi andi5. Can you explain what "To#jid.lserver" means. How can i set / get it?
Adil
This is only best guess, but I suppose that To is a variable bound to a record of type jid (see the record definition in src/jlib.hrl, at the bottom). To#jid.lserver means that you want to access the lserver field of the record, where lserver is the lower-cased version of the jid's domain. If you have problems in the shell, run rd(jid, {user,[...]}).
+1  A: 

Hi, guessing for your description than you are in a single-domain ejabberd deployment (no virtual hosts),

yo can get the local XMPP domain using the ?MYNAME macro (see ejabberd.hrl for the definition).

ppolv