[Freeswitch-dev] mod_radius_cdr behavior and questions [first patch created]

Apostolos Pantsiopoulos regs at kinetix.gr
Tue Feb 10 08:34:43 PST 2009


Hi,

    I have finished coding  the first version of my patch for 
mod_radius_cdr.
The patch allows the module to behave differently than the current
implementation. Instead of blocking the call until the radius packet
is send, my implementation allows the call to continue its execution steps.
The task of sending the radius packet is now relayed to another thread.
The same configuration about timeouts and retries is used. The key 
difference
in my implementation is that the call does not fail nor does it block in 
case
the radius server is down or slow in responding.

    I implemented the whole thing - following Anthony's algorithm and
guidelines - with a queue and some radius processing threads. Both the
queue size and the number of threads is hard coded for now (at least until
I get the consensus for the general idea).

    I noticed while tweaking the module that there might be a memory leak
problem. I monitored the freeswitch process using the simple top linux 
program
and the sipp call generator. When the radius module is activated then FS 
starts
consuming more memory in a linear manner. I used a 10 calls / sec rate with
sipp (zero call length) and the memory  reached 200 MB in just a few 
minutes.
At first I suspected my additions to the module to be the problem, but I 
found
out that the same thing happened using the module in its current svn state
(i.e. without my patch).

    I followed the wiki's guidelines for creating a patch, but I don't 
know how the
whole patch submitting "protocol" works. Should I create an account on 
jira? Should
I post the patch here first until it is in an "acceptable" state? Should 
I send the patch
to a code maintainer and let him decide what to do?

    I am attaching the patch along with the whole file I changed (in 
case someone
wants to just browse the code) until I get some feedback from the 
maintainers
regarding the above questions.

P.S. If someone is eager to work with me in solving the possible memory 
leak
please contact me directly or through the list. I am not a very good c 
coder and
debugging c is somewhat new to me. So, any help would be welcomed.

Anthony Minessale wrote:
> the same one that is already in there now the my_on_routing will now 
> get called for both legs.
>
>
> On Tue, Feb 3, 2009 at 3:33 PM, Apostolos Pantsiopoulos 
> <regs at kinetix.gr <mailto:regs at kinetix.gr>> wrote:
>
>     Cheers!
>
>     One clarification though :
>
>     Would that be a state handler? Or an event handler?
>     And what is its name?
>
>
>     Anthony Minessale wrote:
>>     yes,
>>
>>     you will *now* get the event handler on both legs.
>>
>>
>>     On Tue, Feb 3, 2009 at 3:13 PM, Apostolos Pantsiopoulos
>>     <regs at kinetix.gr <mailto:regs at kinetix.gr>> wrote:
>>
>>         "you will not get that event handler"
>>
>>         please tell me that this "not" meant to be a "now"
>>
>>
>>         Anthony Minessale wrote:
>>>         I updated the core today in a way that you will not get that
>>>         event handler on both inbound and outbound legs.
>>>
>>>
>>>         On Tue, Feb 3, 2009 at 8:41 AM, Apostolos Pantsiopoulos
>>>         <regs at kinetix.gr <mailto:regs at kinetix.gr>> wrote:
>>>
>>>             Even if my intention was not to send the acct start in a
>>>             separate thread
>>>             we are still missing an acct start at the setup of the
>>>             b-leg of a bridge.
>>>             The on_routing handler cannot do that (it is called only
>>>             for the a-leg).
>>>             I tried on_init (which I thought was called at the setup
>>>             of a channel) but
>>>             it didn't invoke my handler even for the a-leg. An event
>>>             on the other hand
>>>             (create_channel) which is triggered correctly does not
>>>             carry all the info
>>>             needed for an acct start packet to be filled (not even
>>>             at a min level). The
>>>             event originate_channel is also called only once during
>>>             a bridge, so it cannot
>>>             be used either.
>>>
>>>             So it is not only a matter of thread vs non threaded (or
>>>             multiple threads vs one thread).
>>>             It is also a matter of when and how many times (2 for a
>>>             simple bridge) to call an
>>>             acct start routine.
>>>
>>>             So we either need to create one more state handler that
>>>             gets called in such a
>>>             manner that can be used for b-legs too. Or an event of
>>>             the same kind that carries all the info
>>>             needed by radius acct start.
>>>             Both ways (adding a state-handler or adding a new event)
>>>             I think require
>>>             changes to the FS core architecture. I must admit,
>>>             however, that my
>>>             understanding of the FS source code is still on a newbie
>>>             level so the above
>>>             conclusions might be wrong.
>>>
>>>
>>>
>>>             Anthony Minessale wrote:
>>>>             or everything is already in the right place the way it
>>>>             already is.....?
>>>>
>>>>             If all you want to do is background the start packet,
>>>>             then just take the info in the place where the existing
>>>>             code gets it (routing state change) and create your own
>>>>             switch_event or private struct, add the data to it and
>>>>             launch a thread to run the radius in it's own thread.
>>>>
>>>>             I still think making the radius not be down or have
>>>>             short timeouts across a list of servers is a better
>>>>             place to fix it than making FS launch a bonus thread
>>>>             per established call to run the radius start packets in
>>>>             the bg.
>>>>
>>>>             I also still think that if you insist on not listing to
>>>>             my previous point, pushing all the packets to a fifo
>>>>             queue is better than launching a new thread per call
>>>>             because if the server is down and timing out why would
>>>>             you want to have 250 threads up at once all blocking on
>>>>             the dead radius instead of a queue of them that could
>>>>             withstand a bit of downtime by stacking up the start
>>>>             packet requests and unloading them in order when it
>>>>             returned.
>>>>
>>>>
>>>>
>>>>             On Tue, Feb 3, 2009 at 4:59 AM, Apostolos Pantsiopoulos
>>>>             <regs at kinetix.gr <mailto:regs at kinetix.gr>> wrote:
>>>>
>>>>                 I came to the following conclusions :
>>>>
>>>>                 In the case of the acct start I cannot use the
>>>>                 CHANNEL_ORIGINATE event since
>>>>                 it is fired only once (I want to send one acct
>>>>                 start for each leg)
>>>>
>>>>                 If I use the CHANNEL_CREATE event for the acct
>>>>                 start I am a little sort on info
>>>>                 since the event does not contain much. So I need to
>>>>                 get the info from the session.
>>>>
>>>>                 On the acct stop it is better to use the info from
>>>>                 the event (lots of info - easy to duplicate).
>>>>
>>>>                 I was hoping to implement a uniform way to get data
>>>>                 for both start and stop but it seems
>>>>                 that this is not the case.
>>>>
>>>>
>>>>
>>>>                 Apostolos Pantsiopoulos wrote:
>>>>>                 You are right about the stop packet.
>>>>>                 But what about the acct start packet?
>>>>>                 If I put that on the session's thread that holds
>>>>>                 the call from continuing.
>>>>>                 Maybe a mixed solution (the acct start uses an
>>>>>                 event handler
>>>>>                 and the acct stop uses a state handler) will be my
>>>>>                 last resort.
>>>>>
>>>>>                 Anthony Minessale wrote:
>>>>>>                 What other flow of the call are you waiting for?
>>>>>>                 The hangup state handler is close to the last
>>>>>>                 thing executed by the session thread before it's
>>>>>>                 destroyed.
>>>>>>                 The session thread has nothing better to do while
>>>>>>                 it's waiting for the reply.
>>>>>>
>>>>>>
>>>>>>                 On Mon, Feb 2, 2009 at 4:49 PM, regs at kinetix.gr
>>>>>>                 <mailto:regs at kinetix.gr> <regs at kinetix.gr
>>>>>>                 <mailto:regs at kinetix.gr>> wrote:
>>>>>>
>>>>>>                     If the session thread makes the radius
>>>>>>                     connection (and waits for it to complete)
>>>>>>                     the flow of the call will be interrupted
>>>>>>                     until the the radius code finishes (current
>>>>>>                     implementation).
>>>>>>                     this is why I figured that I need another
>>>>>>                     thread in order to let the session continue
>>>>>>                     whatever steps it needs until the completion
>>>>>>                     of the call. this parallel thread (radius thread)
>>>>>>                     could continue trying to send the radius
>>>>>>                     packet even after the end of the call/session
>>>>>>                     (desired
>>>>>>                     implementation).
>>>>>>
>>>>>>                     I undesrtand now that the session_locate
>>>>>>                     function stands in the way of I am trying to
>>>>>>                     accomplish
>>>>>>                     but I am afraid that using the session's
>>>>>>                     thread (instead of a parallel one) would not
>>>>>>                     meet my needs.
>>>>>>                     I examined the code of the function and saw
>>>>>>                     that it locks the session and that I need to
>>>>>>                     unlock it myself.
>>>>>>                     Although it works on the creation of a
>>>>>>                     channel it does not work on the hangup (I get
>>>>>>                     a core dump).
>>>>>>                     I'll continue with it tomorrow.
>>>>>>
>>>>>>                     The state event handler is not suitable
>>>>>>                     because I need to get an acct start on both
>>>>>>                     call legs of a bridge
>>>>>>                     and none of the state handlers in the state
>>>>>>                     handler table does that for the b-leg.
>>>>>>                      
>>>>>>
>>>>>>                     Anthony Minessale wrote:
>>>>>>>                     The session runs in it's own thread when you
>>>>>>>                     use session_locate to find a pointer to the
>>>>>>>                     session you stop that session from exiting
>>>>>>>                     until you release it from the same thread
>>>>>>>                     you called session_locate from.
>>>>>>>
>>>>>>>                     So the session could have just done the
>>>>>>>                     radius connection itself in it's perfectly
>>>>>>>                     good existing thread.
>>>>>>>                     now you are detaining the session and
>>>>>>>                     creating a new thread thus wasting the
>>>>>>>                     session thread.
>>>>>>>
>>>>>>>                     instead of an event handler you may want to
>>>>>>>                     use a state handler so you can run the stuff
>>>>>>>                     in the session thread.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                     On Mon, Feb 2, 2009 at 11:18 AM,
>>>>>>>                     regs at kinetix.gr <mailto:regs at kinetix.gr>
>>>>>>>                     <regs at kinetix.gr <mailto:regs at kinetix.gr>>
>>>>>>>                     wrote:
>>>>>>>
>>>>>>>                         Correct me if I am wrong, but wouldn't a
>>>>>>>                         fifo queue (along with its processing
>>>>>>>                         thread)
>>>>>>>                         process the radius packets to be sent in
>>>>>>>                         a sequential manner? And If a packet
>>>>>>>                         submission
>>>>>>>                         got stuck for retries*timeout secs
>>>>>>>                         wouldn't that affect the packets that
>>>>>>>                         wait in the queue?
>>>>>>>                         What I am trying to implement is
>>>>>>>                         different. I want the transmission of
>>>>>>>                         the radius packets
>>>>>>>                         to be independent of any sequence or
>>>>>>>                         order... That's why I am creating a new
>>>>>>>                         thread
>>>>>>>                         for each one, then detaching the thread,
>>>>>>>                         stalling the session with a lock until I
>>>>>>>                         get all the
>>>>>>>                         info I want from it and in the end
>>>>>>>                         notifying the calling function that it
>>>>>>>                         is free to continue (even to destroy the
>>>>>>>                         session).
>>>>>>>                         Also, does the event message contain all
>>>>>>>                         the possible info for a
>>>>>>>                         session/channel/profile of a
>>>>>>>                         call leg?
>>>>>>>
>>>>>>>                         Anthony Minessale wrote:
>>>>>>>>                         when you call session =
>>>>>>>>                         switch_core_session_locate(uuid);
>>>>>>>>
>>>>>>>>                         if session is not NULL you MUST
>>>>>>>>                         switch_core_session_rwunlock(session)
>>>>>>>>                         before you exit your function.
>>>>>>>>
>>>>>>>>                         I have already pointed out 2 times now
>>>>>>>>                         that you should not try to
>>>>>>>>                         session_locate the session, you should
>>>>>>>>                         be using the data for the event for
>>>>>>>>                         this, and dup the event and hand the
>>>>>>>>                         info to a backend thread over a fifo queue?
>>>>>>>>
>>>>>>>>                         On Mon, Feb 2, 2009 at 6:02 AM,
>>>>>>>>                         Apostolos Pantsiopoulos
>>>>>>>>                         <regs at kinetix.gr
>>>>>>>>                         <mailto:regs at kinetix.gr>> wrote:
>>>>>>>>
>>>>>>>>                             Anthony,
>>>>>>>>
>>>>>>>>                                 I need your help in clarifying
>>>>>>>>                             something.
>>>>>>>>
>>>>>>>>                             I my module load function I am
>>>>>>>>                             using this to bind a handler to a
>>>>>>>>                             specific event (channel create) :
>>>>>>>>
>>>>>>>>                             if (switch_event_bind(modname, 
>>>>>>>>                             SWITCH_EVENT_CHANNEL_CREATE,
>>>>>>>>                             SWITCH_EVENT_SUBCLASS_ANY,
>>>>>>>>                             my_on_create_handler, NULL) !=
>>>>>>>>                             SWITCH_STATUS_SUCCESS) {
>>>>>>>>                                            
>>>>>>>>                             switch_log_printf(SWITCH_CHANNEL_LOG,
>>>>>>>>                             SWITCH_LOG_ERROR, "Couldn't bind!\n");
>>>>>>>>                                             return
>>>>>>>>                             SWITCH_STATUS_GENERR;
>>>>>>>>                                     }
>>>>>>>>
>>>>>>>>                             Then in my my_on_create_handler
>>>>>>>>                             routine  I have :
>>>>>>>>
>>>>>>>>                             static void
>>>>>>>>                             my_on_create_handler(switch_event_t
>>>>>>>>                             *event) {
>>>>>>>>
>>>>>>>>                                     char* uuid =
>>>>>>>>                             switch_event_get_header(event,
>>>>>>>>                             "Unique-ID");
>>>>>>>>
>>>>>>>>                                     switch_core_session_t *session;
>>>>>>>>
>>>>>>>>                                     session =
>>>>>>>>                             switch_core_session_locate(uuid);
>>>>>>>>                             }
>>>>>>>>
>>>>>>>>                             this is only for test purposes. My
>>>>>>>>                             handler does nothing else than
>>>>>>>>                             creating a pointer to the session that
>>>>>>>>                             triggered the event. Everything
>>>>>>>>                             compiles just fine. When I am
>>>>>>>>                             running freeswitch everything goes
>>>>>>>>                             as expected (my handling routine is
>>>>>>>>                             called and a session is indeed
>>>>>>>>                             returned on my local session variable)
>>>>>>>>                             except from one thing : I can see
>>>>>>>>                             doing a "ps -eLf" that the session
>>>>>>>>                             threads of my call get stuck and
>>>>>>>>                             never get terminated.
>>>>>>>>
>>>>>>>>                             I can also tell that they are stuck
>>>>>>>>                             by that error message in my console :
>>>>>>>>
>>>>>>>>                             switch_core_session_hupall() Giving
>>>>>>>>                             up with 42 sessions remaining
>>>>>>>>
>>>>>>>>                             which makes sense since I initiated
>>>>>>>>                             21 bridged calls.
>>>>>>>>
>>>>>>>>                             Is the reference (pointer) to the
>>>>>>>>                             session the cause of all these?
>>>>>>>>                             Does FS considers that
>>>>>>>>                             since there are still references to
>>>>>>>>                             a session the session should not be
>>>>>>>>                             terminated? If yes,
>>>>>>>>                             how can I destroy this reference
>>>>>>>>                             (after I have used it)?
>>>>>>>>
>>>>>>>>
>>>>>>>>                             Anthony Minessale wrote:
>>>>>>>>>                             No problem, I have the advantage
>>>>>>>>>                             That I have implemented this
>>>>>>>>>                             technique all over the place ;)
>>>>>>>>>                             Your event handler is the
>>>>>>>>>                             recipient end of that same algorithm.
>>>>>>>>>
>>>>>>>>>                             In fact the events are a very good
>>>>>>>>>                             thing to pass into queues.
>>>>>>>>>
>>>>>>>>>                             You could clone the event and
>>>>>>>>>                             insert the clone into the queue
>>>>>>>>>                             and when you pop it from the
>>>>>>>>>                             backend thread you can just
>>>>>>>>>                             destroy it there then.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>                             On Fri, Jan 30, 2009 at 8:27 AM,
>>>>>>>>>                             Apostolos Pantsiopoulos
>>>>>>>>>                             <regs at kinetix.gr
>>>>>>>>>                             <mailto:regs at kinetix.gr>> wrote:
>>>>>>>>>
>>>>>>>>>                                 Wow. I didn't expect so much
>>>>>>>>>                                 detailing :)
>>>>>>>>>
>>>>>>>>>                                 Thanks for the idea.
>>>>>>>>>
>>>>>>>>>                                 My implementation is different
>>>>>>>>>                                 though, but yours seems to be
>>>>>>>>>                                 better.
>>>>>>>>>
>>>>>>>>>                                 I will conclude what I started
>>>>>>>>>                                 doing now and get back to you
>>>>>>>>>                                 with the results.
>>>>>>>>>
>>>>>>>>>                                 If something is wrong against
>>>>>>>>>                                 my implementation I will try
>>>>>>>>>                                 doing it your way.
>>>>>>>>>
>>>>>>>>>                                 Thanks again!
>>>>>>>>>
>>>>>>>>>                                 Anthony Minessale wrote:
>>>>>>>>>>                                 use a queue object to send
>>>>>>>>>>                                 the data in a dynamic struct
>>>>>>>>>>                                 to the other thread.
>>>>>>>>>>
>>>>>>>>>>                                 1) create a global queue.
>>>>>>>>>>                                 2) create a struct with all
>>>>>>>>>>                                 the info you need to send.
>>>>>>>>>>
>>>>>>>>>>                                 on the event handler.
>>>>>>>>>>
>>>>>>>>>>                                 1) malloc a new struct of
>>>>>>>>>>                                 that type.
>>>>>>>>>>                                 2) memset it to all 0.
>>>>>>>>>>                                 3) populate the struct.
>>>>>>>>>>                                 4) write the data into the queue.
>>>>>>>>>>
>>>>>>>>>>                                 launch a thread at startup
>>>>>>>>>>                                 that does a blocking wait on
>>>>>>>>>>                                 the same queue
>>>>>>>>>>
>>>>>>>>>>                                 1) pop the void pointer off
>>>>>>>>>>                                 the queue.
>>>>>>>>>>                                 2) cast it into your struct.
>>>>>>>>>>                                 3) extract the data from the
>>>>>>>>>>                                 struct and send it over radius.
>>>>>>>>>>                                 4) destroy the struct with
>>>>>>>>>>                                 free and loop.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>                                 On Fri, Jan 30, 2009 at 5:14
>>>>>>>>>>                                 AM, Apostolos Pantsiopoulos
>>>>>>>>>>                                 <regs at kinetix.gr
>>>>>>>>>>                                 <mailto:regs at kinetix.gr>> wrote:
>>>>>>>>>>
>>>>>>>>>>                                     Hi,
>>>>>>>>>>
>>>>>>>>>>                                        I am tweaking the
>>>>>>>>>>                                     mod_radius_cdr module to
>>>>>>>>>>                                     archive the behavior
>>>>>>>>>>                                     that most NASes have
>>>>>>>>>>                                     (i.e. accounting packets
>>>>>>>>>>                                     are sent in a separate
>>>>>>>>>>                                     thread so that the
>>>>>>>>>>                                     submission does not
>>>>>>>>>>                                     interfere with the
>>>>>>>>>>                                     execution of
>>>>>>>>>>                                     the call). While doing
>>>>>>>>>>                                     that, however, I bumped
>>>>>>>>>>                                     into another behavior of
>>>>>>>>>>                                     the module that I think
>>>>>>>>>>                                     is not desirable (at
>>>>>>>>>>                                     least by me) :
>>>>>>>>>>
>>>>>>>>>>                                        While on a bridge, the
>>>>>>>>>>                                     module sends one acct
>>>>>>>>>>                                     start packet at the
>>>>>>>>>>                                     beginning of the originating
>>>>>>>>>>                                     leg (on_routing event
>>>>>>>>>>                                     handler) and two acct
>>>>>>>>>>                                     stop packets at the end of
>>>>>>>>>>                                     each leg
>>>>>>>>>>                                     (inbound and outbound).
>>>>>>>>>>                                     My opinion is that it
>>>>>>>>>>                                     should send one accounting
>>>>>>>>>>                                     start
>>>>>>>>>>                                     packet at the beginning
>>>>>>>>>>                                     of each call leg
>>>>>>>>>>                                     (inbound, outbound) resulting
>>>>>>>>>>                                     to a total
>>>>>>>>>>                                     number of two acct start
>>>>>>>>>>                                     packets. It is generally
>>>>>>>>>>                                     accepted that acct
>>>>>>>>>>                                     start/stop packets
>>>>>>>>>>                                     come in pairs so that
>>>>>>>>>>                                     billing applications can
>>>>>>>>>>                                     handle them accordingly.
>>>>>>>>>>
>>>>>>>>>>                                        Some NAS's radius
>>>>>>>>>>                                     radius implementations
>>>>>>>>>>                                     have some other
>>>>>>>>>>                                     configuration modes
>>>>>>>>>>                                     like the Cisco's RADIUS
>>>>>>>>>>                                     Packet Suppression. When
>>>>>>>>>>                                     in this mode the Cisco NAS
>>>>>>>>>>                                     sends only an accounting
>>>>>>>>>>                                     start/stop pair at the
>>>>>>>>>>                                     end of a final dialpeer
>>>>>>>>>>                                     attempt (and suppresses
>>>>>>>>>>                                     all the previous failed
>>>>>>>>>>                                     dialpeer attempts) thus
>>>>>>>>>>                                     resulting to less
>>>>>>>>>>                                     network traffic. Other
>>>>>>>>>>                                     NASes (such as MERA MVTS)
>>>>>>>>>>                                     can send a start/stop
>>>>>>>>>>                                     pair for each leg OR a
>>>>>>>>>>                                     start/stop
>>>>>>>>>>                                     pair for each end to end
>>>>>>>>>>                                     call, depending on the
>>>>>>>>>>                                     configuration. Opensips
>>>>>>>>>>                                     follows
>>>>>>>>>>                                     the star/stop pair by
>>>>>>>>>>                                     call leg paradigm. No
>>>>>>>>>>                                     matter what the
>>>>>>>>>>                                     implementation, all of them
>>>>>>>>>>                                     always send a acct
>>>>>>>>>>                                     start/stop pair. This is
>>>>>>>>>>                                     a common thing. And all the
>>>>>>>>>>                                     billing platforms
>>>>>>>>>>                                     can deal only with paired
>>>>>>>>>>                                     start/stops.
>>>>>>>>>>
>>>>>>>>>>                                        The current module
>>>>>>>>>>                                     behavior (one start two
>>>>>>>>>>                                     stops) can complicate
>>>>>>>>>>                                     things since the
>>>>>>>>>>                                     radius server would not
>>>>>>>>>>                                     know how to match the
>>>>>>>>>>                                     second stop packet with
>>>>>>>>>>                                     its equivalent start.
>>>>>>>>>>
>>>>>>>>>>                                        Before I get the
>>>>>>>>>>                                     infamous answer "pathes
>>>>>>>>>>                                     welcomed" I would like to
>>>>>>>>>>                                     state that I am
>>>>>>>>>>                                     already involved in
>>>>>>>>>>                                     changing this behavior
>>>>>>>>>>                                     (through a patch). So my real
>>>>>>>>>>                                     question is this :
>>>>>>>>>>
>>>>>>>>>>                                     I noticed that the module
>>>>>>>>>>                                     uses the
>>>>>>>>>>                                     switch_core_add_state_handler
>>>>>>>>>>                                     function to register
>>>>>>>>>>                                     its handler table :
>>>>>>>>>>
>>>>>>>>>>                                     switch_core_add_state_handler(&state_handlers);
>>>>>>>>>>
>>>>>>>>>>                                     So the on_routing ( or
>>>>>>>>>>                                     the on_execute) event
>>>>>>>>>>                                     happens only when the
>>>>>>>>>>                                     inbound call is started.
>>>>>>>>>>                                     When the outbound call is
>>>>>>>>>>                                     initiated no handler is
>>>>>>>>>>                                     available to hook up a
>>>>>>>>>>                                     function and
>>>>>>>>>>                                     send the proper acct
>>>>>>>>>>                                     start packet.
>>>>>>>>>>
>>>>>>>>>>                                        Should the module
>>>>>>>>>>                                     register its handlers
>>>>>>>>>>                                     using the
>>>>>>>>>>                                     switch_channel_add_state_handler()
>>>>>>>>>>                                     function instead?
>>>>>>>>>>                                     And if yes, how could the
>>>>>>>>>>                                     module pass the channel
>>>>>>>>>>                                     as a parameter to the
>>>>>>>>>>                                     function since channels
>>>>>>>>>>                                     are created and destroyed
>>>>>>>>>>                                     dynamically (and the
>>>>>>>>>>                                     module when initialized
>>>>>>>>>>                                     does not have that info).
>>>>>>>>>>
>>>>>>>>>>                                        I would greatly
>>>>>>>>>>                                     appreciate your help in
>>>>>>>>>>                                     pinpointing a proper way to
>>>>>>>>>>                                     call my event handling
>>>>>>>>>>                                     routines on a per call
>>>>>>>>>>                                     leg basis.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>                                     --
>>>>>>>>>>                                     -------------------------------------------
>>>>>>>>>>                                     Apostolos Pantsiopoulos
>>>>>>>>>>                                     Kinetix Tele.com R & D
>>>>>>>>>>                                     email: regs at kinetix.gr
>>>>>>>>>>                                     <mailto:regs at kinetix.gr>
>>>>>>>>>>                                     -------------------------------------------
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>                                     _______________________________________________
>>>>>>>>>>                                     Freeswitch-dev mailing list
>>>>>>>>>>                                     Freeswitch-dev at lists.freeswitch.org
>>>>>>>>>>                                     <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>>>>>>>                                     http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>>>>>>>                                     UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>>>>>>>                                     http://www.freeswitch.org
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>                                 -- 
>>>>>>>>>>                                 Anthony Minessale II
>>>>>>>>>>
>>>>>>>>>>                                 FreeSWITCH
>>>>>>>>>>                                 http://www.freeswitch.org/
>>>>>>>>>>                                 ClueCon http://www.cluecon.com/
>>>>>>>>>>
>>>>>>>>>>                                 AIM: anthm
>>>>>>>>>>                                 MSN:anthony_minessale at hotmail.com
>>>>>>>>>>                                 <mailto:MSN%3Aanthony_minessale at hotmail.com>
>>>>>>>>>>                                 GTALK/JABBER/PAYPAL:anthony.minessale at gmail.com
>>>>>>>>>>                                 <mailto:PAYPAL%3Aanthony.minessale at gmail.com>
>>>>>>>>>>                                 IRC: irc.freenode.net
>>>>>>>>>>                                 <http://irc.freenode.net>
>>>>>>>>>>                                 #freeswitch
>>>>>>>>>>
>>>>>>>>>>                                 FreeSWITCH Developer Conference
>>>>>>>>>>                                 sip:888 at conference.freeswitch.org
>>>>>>>>>>                                 <mailto:sip%3A888 at conference.freeswitch.org>
>>>>>>>>>>                                 iax:guest at conference.freeswitch.org/888
>>>>>>>>>>                                 <http://iax:guest@conference.freeswitch.org/888>
>>>>>>>>>>                                 googletalk:conf+888 at conference.freeswitch.org
>>>>>>>>>>                                 <mailto:googletalk%3Aconf%2B888 at conference.freeswitch.org>
>>>>>>>>>>                                 pstn:213-799-1400
>>>>>>>>>>                                 ------------------------------------------------------------------------
>>>>>>>>>>                                 _______________________________________________
>>>>>>>>>>                                 Freeswitch-dev mailing list
>>>>>>>>>>                                 Freeswitch-dev at lists.freeswitch.org
>>>>>>>>>>                                 <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>>>>>>>                                 http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>>>>>>>                                 UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>>>>>>>                                 http://www.freeswitch.org
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>                                 -- 
>>>>>>>>>                                 -------------------------------------------
>>>>>>>>>                                 Apostolos Pantsiopoulos
>>>>>>>>>                                 Kinetix Tele.com R & D
>>>>>>>>>                                 email: regs at kinetix.gr <mailto:regs at kinetix.gr>
>>>>>>>>>                                 ------------------------------------------- 
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>                                 _______________________________________________
>>>>>>>>>                                 Freeswitch-dev mailing list
>>>>>>>>>                                 Freeswitch-dev at lists.freeswitch.org
>>>>>>>>>                                 <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>>>>>>                                 http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>>>>>>                                 UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>>>>>>                                 http://www.freeswitch.org
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>                             -- 
>>>>>>>>>                             Anthony Minessale II
>>>>>>>>>
>>>>>>>>>                             FreeSWITCH http://www.freeswitch.org/
>>>>>>>>>                             ClueCon http://www.cluecon.com/
>>>>>>>>>
>>>>>>>>>                             AIM: anthm
>>>>>>>>>                             MSN:anthony_minessale at hotmail.com
>>>>>>>>>                             <mailto:MSN%3Aanthony_minessale at hotmail.com>
>>>>>>>>>                             GTALK/JABBER/PAYPAL:anthony.minessale at gmail.com
>>>>>>>>>                             <mailto:PAYPAL%3Aanthony.minessale at gmail.com>
>>>>>>>>>                             IRC: irc.freenode.net
>>>>>>>>>                             <http://irc.freenode.net> #freeswitch
>>>>>>>>>
>>>>>>>>>                             FreeSWITCH Developer Conference
>>>>>>>>>                             sip:888 at conference.freeswitch.org
>>>>>>>>>                             <mailto:sip%3A888 at conference.freeswitch.org>
>>>>>>>>>                             iax:guest at conference.freeswitch.org/888
>>>>>>>>>                             <http://iax:guest@conference.freeswitch.org/888>
>>>>>>>>>                             googletalk:conf+888 at conference.freeswitch.org
>>>>>>>>>                             <mailto:googletalk%3Aconf%2B888 at conference.freeswitch.org>
>>>>>>>>>                             pstn:213-799-1400
>>>>>>>>>                             ------------------------------------------------------------------------
>>>>>>>>>
>>>>>>>>>                             _______________________________________________
>>>>>>>>>                             Freeswitch-dev mailing list
>>>>>>>>>                             Freeswitch-dev at lists.freeswitch.org <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>>>>>>                             http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>>>>>>                             UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>>>>>>                             http://www.freeswitch.org
>>>>>>>>>                               
>>>>>>>>
>>>>>>>>
>>>>>>>>                             -- 
>>>>>>>>                             -------------------------------------------
>>>>>>>>                             Apostolos Pantsiopoulos
>>>>>>>>                             Kinetix Tele.com R & D
>>>>>>>>                             email: regs at kinetix.gr <mailto:regs at kinetix.gr>
>>>>>>>>                             ------------------------------------------- 
>>>>>>>>
>>>>>>>>
>>>>>>>>                             _______________________________________________
>>>>>>>>                             Freeswitch-dev mailing list
>>>>>>>>                             Freeswitch-dev at lists.freeswitch.org
>>>>>>>>                             <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>>>>>                             http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>>>>>                             UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>>>>>                             http://www.freeswitch.org
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>                         -- 
>>>>>>>>                         Anthony Minessale II
>>>>>>>>
>>>>>>>>                         FreeSWITCH http://www.freeswitch.org/
>>>>>>>>                         ClueCon http://www.cluecon.com/
>>>>>>>>
>>>>>>>>                         AIM: anthm
>>>>>>>>                         MSN:anthony_minessale at hotmail.com
>>>>>>>>                         <mailto:MSN%3Aanthony_minessale at hotmail.com>
>>>>>>>>                         GTALK/JABBER/PAYPAL:anthony.minessale at gmail.com
>>>>>>>>                         <mailto:PAYPAL%3Aanthony.minessale at gmail.com>
>>>>>>>>                         IRC: irc.freenode.net
>>>>>>>>                         <http://irc.freenode.net> #freeswitch
>>>>>>>>
>>>>>>>>                         FreeSWITCH Developer Conference
>>>>>>>>                         sip:888 at conference.freeswitch.org
>>>>>>>>                         <mailto:sip%3A888 at conference.freeswitch.org>
>>>>>>>>                         iax:guest at conference.freeswitch.org/888
>>>>>>>>                         <http://iax:guest@conference.freeswitch.org/888>
>>>>>>>>                         googletalk:conf+888 at conference.freeswitch.org
>>>>>>>>                         <mailto:googletalk%3Aconf%2B888 at conference.freeswitch.org>
>>>>>>>>                         pstn:213-799-1400
>>>>>>>>                         ------------------------------------------------------------------------
>>>>>>>>
>>>>>>>>                         _______________________________________________
>>>>>>>>                         Freeswitch-dev mailing list
>>>>>>>>                         Freeswitch-dev at lists.freeswitch.org <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>>>>>                         http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>>>>>                         UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>>>>>                         http://www.freeswitch.org
>>>>>>>>                           
>>>>>>>
>>>>>>>
>>>>>>>                         _______________________________________________
>>>>>>>                         Freeswitch-dev mailing list
>>>>>>>                         Freeswitch-dev at lists.freeswitch.org
>>>>>>>                         <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>>>>                         http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>>>>                         UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>>>>                         http://www.freeswitch.org
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                     -- 
>>>>>>>                     Anthony Minessale II
>>>>>>>
>>>>>>>                     FreeSWITCH http://www.freeswitch.org/
>>>>>>>                     ClueCon http://www.cluecon.com/
>>>>>>>
>>>>>>>                     AIM: anthm
>>>>>>>                     MSN:anthony_minessale at hotmail.com
>>>>>>>                     <mailto:MSN%3Aanthony_minessale at hotmail.com>
>>>>>>>                     GTALK/JABBER/PAYPAL:anthony.minessale at gmail.com
>>>>>>>                     <mailto:PAYPAL%3Aanthony.minessale at gmail.com>
>>>>>>>                     IRC: irc.freenode.net
>>>>>>>                     <http://irc.freenode.net> #freeswitch
>>>>>>>
>>>>>>>                     FreeSWITCH Developer Conference
>>>>>>>                     sip:888 at conference.freeswitch.org
>>>>>>>                     <mailto:sip%3A888 at conference.freeswitch.org>
>>>>>>>                     iax:guest at conference.freeswitch.org/888
>>>>>>>                     <http://iax:guest@conference.freeswitch.org/888>
>>>>>>>                     googletalk:conf+888 at conference.freeswitch.org
>>>>>>>                     <mailto:googletalk%3Aconf%2B888 at conference.freeswitch.org>
>>>>>>>                     pstn:213-799-1400
>>>>>>>                     ------------------------------------------------------------------------
>>>>>>>                     _______________________________________________
>>>>>>>                     Freeswitch-dev mailing list
>>>>>>>                     Freeswitch-dev at lists.freeswitch.org
>>>>>>>                     <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>>>>                     http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>>>>                     UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>>>>                     http://www.freeswitch.org
>>>>>>
>>>>>>
>>>>>>                     _______________________________________________
>>>>>>                     Freeswitch-dev mailing list
>>>>>>                     Freeswitch-dev at lists.freeswitch.org
>>>>>>                     <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>>>                     http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>>>                     UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>>>                     http://www.freeswitch.org
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>                 -- 
>>>>>>                 Anthony Minessale II
>>>>>>
>>>>>>                 FreeSWITCH http://www.freeswitch.org/
>>>>>>                 ClueCon http://www.cluecon.com/
>>>>>>
>>>>>>                 AIM: anthm
>>>>>>                 MSN:anthony_minessale at hotmail.com
>>>>>>                 <mailto:MSN%3Aanthony_minessale at hotmail.com>
>>>>>>                 GTALK/JABBER/PAYPAL:anthony.minessale at gmail.com
>>>>>>                 <mailto:PAYPAL%3Aanthony.minessale at gmail.com>
>>>>>>                 IRC: irc.freenode.net <http://irc.freenode.net>
>>>>>>                 #freeswitch
>>>>>>
>>>>>>                 FreeSWITCH Developer Conference
>>>>>>                 sip:888 at conference.freeswitch.org
>>>>>>                 <mailto:sip%3A888 at conference.freeswitch.org>
>>>>>>                 iax:guest at conference.freeswitch.org/888
>>>>>>                 <http://iax:guest@conference.freeswitch.org/888>
>>>>>>                 googletalk:conf+888 at conference.freeswitch.org
>>>>>>                 <mailto:googletalk%3Aconf%2B888 at conference.freeswitch.org>
>>>>>>                 pstn:213-799-1400
>>>>>>                 ------------------------------------------------------------------------
>>>>>>
>>>>>>                 _______________________________________________
>>>>>>                 Freeswitch-dev mailing list
>>>>>>                 Freeswitch-dev at lists.freeswitch.org <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>>>                 http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>>>                 UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>>>                 http://www.freeswitch.org
>>>>>>                   
>>>>>
>>>>>
>>>>>                 -- 
>>>>>                 -------------------------------------------
>>>>>                 Apostolos Pantsiopoulos
>>>>>                 Kinetix Tele.com R & D
>>>>>                 email: regs at kinetix.gr <mailto:regs at kinetix.gr>
>>>>>                 ------------------------------------------- 
>>>>>                 ------------------------------------------------------------------------
>>>>>
>>>>>                 _______________________________________________
>>>>>                 Freeswitch-dev mailing list
>>>>>                 Freeswitch-dev at lists.freeswitch.org <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>>                 http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>>                 UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>>                 http://www.freeswitch.org
>>>>>                   
>>>>
>>>>
>>>>                 -- 
>>>>                 -------------------------------------------
>>>>                 Apostolos Pantsiopoulos
>>>>                 Kinetix Tele.com R & D
>>>>                 email: regs at kinetix.gr <mailto:regs at kinetix.gr>
>>>>                 ------------------------------------------- 
>>>>
>>>>
>>>>                 _______________________________________________
>>>>                 Freeswitch-dev mailing list
>>>>                 Freeswitch-dev at lists.freeswitch.org
>>>>                 <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>                 http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>                 UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>                 http://www.freeswitch.org
>>>>
>>>>
>>>>
>>>>
>>>>             -- 
>>>>             Anthony Minessale II
>>>>
>>>>             FreeSWITCH http://www.freeswitch.org/
>>>>             ClueCon http://www.cluecon.com/
>>>>
>>>>             AIM: anthm
>>>>             MSN:anthony_minessale at hotmail.com
>>>>             <mailto:MSN%3Aanthony_minessale at hotmail.com>
>>>>             GTALK/JABBER/PAYPAL:anthony.minessale at gmail.com
>>>>             <mailto:PAYPAL%3Aanthony.minessale at gmail.com>
>>>>             IRC: irc.freenode.net <http://irc.freenode.net> #freeswitch
>>>>
>>>>             FreeSWITCH Developer Conference
>>>>             sip:888 at conference.freeswitch.org
>>>>             <mailto:sip%3A888 at conference.freeswitch.org>
>>>>             iax:guest at conference.freeswitch.org/888
>>>>             <http://iax:guest@conference.freeswitch.org/888>
>>>>             googletalk:conf+888 at conference.freeswitch.org
>>>>             <mailto:googletalk%3Aconf%2B888 at conference.freeswitch.org>
>>>>             pstn:213-799-1400
>>>>             ------------------------------------------------------------------------
>>>>
>>>>             _______________________________________________
>>>>             Freeswitch-dev mailing list
>>>>             Freeswitch-dev at lists.freeswitch.org <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>>             http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>>             UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>>             http://www.freeswitch.org
>>>>               
>>>
>>>
>>>             -- 
>>>             -------------------------------------------
>>>             Apostolos Pantsiopoulos
>>>             Kinetix Tele.com R & D
>>>             email: regs at kinetix.gr <mailto:regs at kinetix.gr>
>>>             ------------------------------------------- 
>>>
>>>
>>>             _______________________________________________
>>>             Freeswitch-dev mailing list
>>>             Freeswitch-dev at lists.freeswitch.org
>>>             <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>             http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>             UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>             http://www.freeswitch.org
>>>
>>>
>>>
>>>
>>>         -- 
>>>         Anthony Minessale II
>>>
>>>         FreeSWITCH http://www.freeswitch.org/
>>>         ClueCon http://www.cluecon.com/
>>>
>>>         AIM: anthm
>>>         MSN:anthony_minessale at hotmail.com
>>>         <mailto:MSN%3Aanthony_minessale at hotmail.com>
>>>         GTALK/JABBER/PAYPAL:anthony.minessale at gmail.com
>>>         <mailto:PAYPAL%3Aanthony.minessale at gmail.com>
>>>         IRC: irc.freenode.net <http://irc.freenode.net> #freeswitch
>>>
>>>         FreeSWITCH Developer Conference
>>>         sip:888 at conference.freeswitch.org
>>>         <mailto:sip%3A888 at conference.freeswitch.org>
>>>         iax:guest at conference.freeswitch.org/888
>>>         <http://iax:guest@conference.freeswitch.org/888>
>>>         googletalk:conf+888 at conference.freeswitch.org
>>>         <mailto:googletalk%3Aconf%2B888 at conference.freeswitch.org>
>>>         pstn:213-799-1400
>>>         ------------------------------------------------------------------------
>>>
>>>         _______________________________________________
>>>         Freeswitch-dev mailing list
>>>         Freeswitch-dev at lists.freeswitch.org <mailto:Freeswitch-dev at lists.freeswitch.org>
>>>         http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>>         UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>>         http://www.freeswitch.org
>>>           
>>
>>
>>         -- 
>>         -------------------------------------------
>>         Apostolos Pantsiopoulos
>>         Kinetix Tele.com R & D
>>         email: regs at kinetix.gr <mailto:regs at kinetix.gr>
>>         ------------------------------------------- 
>>
>>
>>         _______________________________________________
>>         Freeswitch-dev mailing list
>>         Freeswitch-dev at lists.freeswitch.org
>>         <mailto:Freeswitch-dev at lists.freeswitch.org>
>>         http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>         UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>         http://www.freeswitch.org
>>
>>
>>
>>
>>     -- 
>>     Anthony Minessale II
>>
>>     FreeSWITCH http://www.freeswitch.org/
>>     ClueCon http://www.cluecon.com/
>>
>>     AIM: anthm
>>     MSN:anthony_minessale at hotmail.com
>>     <mailto:MSN%3Aanthony_minessale at hotmail.com>
>>     GTALK/JABBER/PAYPAL:anthony.minessale at gmail.com
>>     <mailto:PAYPAL%3Aanthony.minessale at gmail.com>
>>     IRC: irc.freenode.net <http://irc.freenode.net> #freeswitch
>>
>>     FreeSWITCH Developer Conference
>>     sip:888 at conference.freeswitch.org
>>     <mailto:sip%3A888 at conference.freeswitch.org>
>>     iax:guest at conference.freeswitch.org/888
>>     <http://iax:guest@conference.freeswitch.org/888>
>>     googletalk:conf+888 at conference.freeswitch.org
>>     <mailto:googletalk%3Aconf%2B888 at conference.freeswitch.org>
>>     pstn:213-799-1400
>>     ------------------------------------------------------------------------
>>
>>     _______________________________________________
>>     Freeswitch-dev mailing list
>>     Freeswitch-dev at lists.freeswitch.org <mailto:Freeswitch-dev at lists.freeswitch.org>
>>     http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>>     UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>>     http://www.freeswitch.org
>>       
>
>
>     -- 
>     -------------------------------------------
>     Apostolos Pantsiopoulos
>     Kinetix Tele.com R & D
>     email: regs at kinetix.gr <mailto:regs at kinetix.gr>
>     ------------------------------------------- 
>
>
>     _______________________________________________
>     Freeswitch-dev mailing list
>     Freeswitch-dev at lists.freeswitch.org
>     <mailto:Freeswitch-dev at lists.freeswitch.org>
>     http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
>     UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
>     http://www.freeswitch.org
>
>
>
>
> -- 
> Anthony Minessale II
>
> FreeSWITCH http://www.freeswitch.org/
> ClueCon http://www.cluecon.com/
>
> AIM: anthm
> MSN:anthony_minessale at hotmail.com 
> <mailto:MSN%3Aanthony_minessale at hotmail.com>
> GTALK/JABBER/PAYPAL:anthony.minessale at gmail.com 
> <mailto:PAYPAL%3Aanthony.minessale at gmail.com>
> IRC: irc.freenode.net <http://irc.freenode.net> #freeswitch
>
> FreeSWITCH Developer Conference
> sip:888 at conference.freeswitch.org 
> <mailto:sip%3A888 at conference.freeswitch.org>
> iax:guest at conference.freeswitch.org/888 
> <http://iax:guest@conference.freeswitch.org/888>
> googletalk:conf+888 at conference.freeswitch.org 
> <mailto:googletalk%3Aconf%2B888 at conference.freeswitch.org>
> pstn:213-799-1400
> ------------------------------------------------------------------------
>
> _______________________________________________
> Freeswitch-dev mailing list
> Freeswitch-dev at lists.freeswitch.org
> http://lists.freeswitch.org/mailman/listinfo/freeswitch-dev
> UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-dev
> http://www.freeswitch.org
>   


-- 
-------------------------------------------
Apostolos Pantsiopoulos
Kinetix Tele.com R & D
email: regs at kinetix.gr
------------------------------------------- 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.freeswitch.org/pipermail/freeswitch-dev/attachments/20090210/59bd0ddd/attachment-0001.html 
-------------- next part --------------
/* 
 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
 * Copyright (C) 2005/2006, Anthony Minessale II <anthmct at yahoo.com>
 *
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * 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 Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
 *
 * The Initial Developer of the Original Code is
 * Anthony Minessale II <anthmct at yahoo.com>
 * Portions created by the Initial Developer are Copyright (C)
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 * 
 * Chris Parker <cparker at segv.org>
 *
 *
 * mod_radius_cdr.c -- RADIUS CDR Module
 *
 */

#include <switch.h>
#include <sys/stat.h>
#include <freeradius-client.h>
#include "mod_radius_cdr.h"

SWITCH_MODULE_LOAD_FUNCTION(mod_radius_cdr_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_radius_cdr_shutdown);
SWITCH_MODULE_DEFINITION(mod_radius_cdr, mod_radius_cdr_load, mod_radius_cdr_shutdown, NULL);

switch_memory_pool_t *module_pool = NULL;
switch_queue_t *rad_queue = NULL;

static struct {
	int shutdown;
	switch_thread_rwlock_t *rwlock;
} globals = { 0 };

static char cf[] = "mod_radius_cdr.conf";
static char my_dictionary[PATH_MAX];
static char my_seqfile[PATH_MAX];
static char *my_deadtime;		/* 0 */
static char *my_timeout;		/* 5 */
static char *my_retries;		/* 3 */
static char my_servers[SERVER_MAX][255];

struct acct_packet {

	rc_handle *rad_config;
	VALUE_PAIR *data;

};

static void *SWITCH_THREAD_FUNC process_packets(switch_thread_t *thread, void *ptr){

	void *pop = NULL;

	while(1){

		if(switch_queue_pop(rad_queue,&pop) != SWITCH_STATUS_SUCCESS || !pop){

			switch_yield(1000);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[mod_radius_cdr] nothing to do thread is sleeping\n");		

		} else {

		        struct acct_packet *tmp = (struct acct_packet *) pop;

		        if (rc_acct(tmp->rad_config, 0, tmp->data) == OK_RC) {
		                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[mod_radius_cdr] RADIUS Accounting Packet OK\n");
	        	} else {
        	        	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[mod_radius_cdr] RADIUS Accounting Packet FAILED\n");
	        	}


			switch_safe_free(tmp->data);
			switch_safe_free(tmp->rad_config);
			switch_safe_free(tmp);

		}

	}

	return 0;

}

static rc_handle *my_radius_init(void)
{
	int i = 0;
	rc_handle *rad_config;

	rad_config = rc_new();

	if (rad_config == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[mod_radius_cdr] Error initializing rc_handle!\n");
		return NULL;
	}

	rad_config = rc_config_init(rad_config);

	if (rad_config == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error initializing radius config!\n");
		rc_destroy(rad_config);
		return NULL;
	}

	/* Some hardcoded ( for now ) defaults needed to initialize radius */
	if (rc_add_config(rad_config, "auth_order", "radius", "mod_radius_cdr.c", 0) != 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setting auth_order = radius failed\n");
		rc_destroy(rad_config);
		return NULL;
	}

	if (rc_add_config(rad_config, "seqfile", my_seqfile, "mod_radius_cdr.c", 0) != 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setting seqfile = %s failed\n", my_seqfile);
		rc_destroy(rad_config);
		return NULL;
	}


	/* Add the module configs to initialize rad_config */

	for (i = 0; i < SERVER_MAX && my_servers[i][0] != '\0'; i++) {
		if (rc_add_config(rad_config, "acctserver", my_servers[i], cf, 0) != 0) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setting acctserver = %s failed\n", my_servers[i]);
			rc_destroy(rad_config);
			return NULL;
		}
	}

	if (rc_add_config(rad_config, "dictionary", my_dictionary, cf, 0) != 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed setting dictionary = %s failed\n", my_dictionary);
		rc_destroy(rad_config);
		return NULL;
	}

	if (rc_add_config(rad_config, "radius_deadtime", my_deadtime, cf, 0) != 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setting radius_deadtime = %s failed\n", my_deadtime);
		rc_destroy(rad_config);
		return NULL;
	}

	if (rc_add_config(rad_config, "radius_timeout", my_timeout, cf, 0) != 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setting radius_timeout = %s failed\n", my_timeout);
		rc_destroy(rad_config);
		return NULL;
	}

	if (rc_add_config(rad_config, "radius_retries", my_retries, cf, 0) != 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "setting radius_retries = %s failed\n", my_retries);
		rc_destroy(rad_config);
		return NULL;
	}

	/* Read the dictionary file(s) */
	if (rc_read_dictionary(rad_config, rc_conf_str(rad_config, "dictionary")) != 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "reading dictionary file(s): %s\n", my_dictionary);
		rc_destroy(rad_config);
		return NULL;
	}

	return rad_config;
}

static switch_status_t my_on_routing(switch_core_session_t *session)
{
	switch_xml_t cdr;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	rc_handle *rad_config;
	VALUE_PAIR *send = NULL;
	//uint32_t client_port = 0;
	uint32_t status_type = PW_STATUS_START;
	switch_time_t callstartdate = 0;
	switch_time_t callanswerdate = 0;
	switch_time_t callenddate = 0;
	switch_time_t calltransferdate = 0;

	char *uuid_str;

	switch_time_exp_t tm;
	char buffer[32];

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[mod_radius_cdr] Entering my_on_routing\n");

	if (globals.shutdown) {
		return SWITCH_STATUS_SUCCESS;
	}

	if(channel) {
		const char *disable_flag = switch_channel_get_variable(channel, "disable_radius_start");
		if(switch_true(disable_flag)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[mod_radius_cdr] Not Sending RADIUS Start\n");
			return SWITCH_STATUS_SUCCESS;
		}
	}

	switch_thread_rwlock_rdlock(globals.rwlock);

	rad_config = my_radius_init();

	if (rad_config == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[mod_radius_cdr] Error initializing radius, Start packet not logged.\n");
		goto end;
	}

	if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) {
		uuid_str = switch_core_session_get_uuid(session);
	} else {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[mod_radius_cdr] Error Generating Data!\n");
		goto end;
	}

	/* Create the radius packet */

	/* Set Status Type */
	if (rc_avpair_add(rad_config, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[mod_radius_cdr] Failed setting Acct-Status-Type: Start\n");
		rc_destroy(rad_config);
		goto end;
	}

	if (rc_avpair_add(rad_config, &send, PW_ACCT_SESSION_ID, uuid_str, -1, 0) == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[mod_radius_cdr] Failed adding Acct-Session-ID: %s\n", uuid_str);
		rc_destroy(rad_config);
		goto end;
	}

	/* Add VSAs */

	if (channel) {
		/*switch_call_cause_t   cause; */
		switch_caller_profile_t *profile;

		/*
		   cause = switch_channel_get_cause(channel);
		   if (rc_avpair_add(rad_config, &send, PW_FS_HANGUPCAUSE, &cause, -1, PW_FS_PEC) == NULL) {
		   switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Hangupcause: %d\n", cause);
		   rc_destroy(rad_config);
		   return SWITCH_STATUS_TERM;
		   }
		 */

		profile = switch_channel_get_caller_profile(channel);

		if (profile) {

			callstartdate = profile->times->created;
			callanswerdate = profile->times->answered;
			calltransferdate = profile->times->transferred;
			callenddate = profile->times->hungup;

			if (profile->username) {
				if (rc_avpair_add(rad_config, &send, PW_USER_NAME, (void *) profile->username, -1, 0) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding User-Name: %s\n", profile->username);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->caller_id_number) {
				if (rc_avpair_add(rad_config, &send, PW_FS_SRC, (void *) profile->caller_id_number, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Src: %s\n", profile->caller_id_number);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->caller_id_name) {
				if (rc_avpair_add(rad_config, &send, PW_FS_CLID, (void *) profile->caller_id_name, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-CLID: %s\n", profile->caller_id_name);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->destination_number) {
				if (rc_avpair_add(rad_config, &send, PW_FS_DST, (void *) profile->destination_number, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Dst: %s\n", profile->destination_number);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->dialplan) {
				if (rc_avpair_add(rad_config, &send, PW_FS_DIALPLAN, (void *) profile->dialplan, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Dialplan: %s\n", profile->dialplan);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->network_addr) {
				if (rc_avpair_add(rad_config, &send, PW_FRAMED_IP_ADDRESS, (void *) profile->network_addr, -1, 0) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Framed-IP-Address: %s\n", profile->network_addr);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->rdnis) {
				if (rc_avpair_add(rad_config, &send, PW_FS_RDNIS, (void *) profile->rdnis, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-RDNIS: %s\n", profile->rdnis);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->context) {
				if (rc_avpair_add(rad_config, &send, PW_FS_CONTEXT, (void *) profile->context, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Context: %s\n", profile->context);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->ani) {
				if (rc_avpair_add(rad_config, &send, PW_FS_ANI, (void *) profile->ani, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-ANI: %s\n", profile->ani);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->aniii) {
				if (rc_avpair_add(rad_config, &send, PW_FS_ANIII, (void *) profile->aniii, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-ANIII: %s\n", profile->aniii);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->source) {
				if (rc_avpair_add(rad_config, &send, PW_FS_SOURCE, (void *) profile->source, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Source: %s\n", profile->source);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (callstartdate > 0) {
				switch_time_exp_lt(&tm, callstartdate);
				switch_snprintf(buffer, sizeof(buffer), "%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
								tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
								tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
				if (rc_avpair_add(rad_config, &send, PW_FS_CALLSTARTDATE, &buffer, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Callstartdate: %s\n", buffer);
					rc_destroy(rad_config);
					goto end;
				}
			}

			if (callanswerdate > 0) {
				switch_time_exp_lt(&tm, callanswerdate);
				switch_snprintf(buffer, sizeof(buffer), "%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
								tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
								tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
				if (rc_avpair_add(rad_config, &send, PW_FS_CALLANSWERDATE, &buffer, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Callanswerdate: %s\n", buffer);
					rc_destroy(rad_config);
					goto end;
				}
			}

			if (calltransferdate > 0) {
				switch_time_exp_lt(&tm, calltransferdate);
				switch_snprintf(buffer, sizeof(buffer), "%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
								tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
								tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
				if (rc_avpair_add(rad_config, &send, PW_FS_CALLTRANSFERDATE, &buffer, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Calltransferdate: %s\n", buffer);
					rc_destroy(rad_config);
					goto end;
				}
			}

			if (callenddate > 0) {
				switch_time_exp_lt(&tm, callenddate);
				switch_snprintf(buffer, sizeof(buffer), "%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
								tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
								tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
				if (rc_avpair_add(rad_config, &send, PW_FS_CALLENDDATE, &buffer, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Callenddate: %s\n", buffer);
					rc_destroy(rad_config);
					goto end;
				}
			}

			if (profile->caller_extension && 
				profile->caller_extension->last_application && 
				profile->caller_extension->last_application->application_name) {
				if (rc_avpair_add(rad_config, &send, PW_FS_LASTAPP,
								  (void *) profile->caller_extension->last_application->application_name, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Lastapp: %s\n", profile->source);
					rc_destroy(rad_config);
					goto end;
				}
			}
		} else {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "profile == NULL\n");
		}
	}

	struct acct_packet *acct_start = NULL;

	acct_start = malloc(sizeof(&acct_start));
	
	memset(acct_start, 0, sizeof(&acct_start));

	acct_start->rad_config = rad_config;
	acct_start->data = send;

	switch_queue_push(rad_queue,acct_start);

 end:
	switch_thread_rwlock_unlock(globals.rwlock);
	return (SWITCH_STATUS_SUCCESS);
}

static switch_status_t my_on_hangup(switch_core_session_t *session)
{
	switch_xml_t cdr;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	rc_handle *rad_config;
	VALUE_PAIR *send = NULL;
	uint32_t status_type = PW_STATUS_STOP;
	switch_time_t callstartdate = 0;
	switch_time_t callanswerdate = 0;
	switch_time_t callenddate = 0;
	switch_time_t calltransferdate = 0;
	switch_time_t billusec = 0;
	uint32_t billsec = 0;
	char *uuid_str;

	switch_time_exp_t tm;
	char buffer[32] = "";

	if (globals.shutdown) {
		return SWITCH_STATUS_FALSE;
	}


	if(channel) {
		const char *disable_flag = switch_channel_get_variable(channel, "disable_radius_stop");
		if(switch_true(disable_flag)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[mod_radius_cdr] Not Sending RADIUS Stop\n");
			return SWITCH_STATUS_SUCCESS;
		}
	}

	switch_thread_rwlock_rdlock(globals.rwlock);

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[mod_radius_cdr] Entering my_on_hangup\n");

	rad_config = my_radius_init();

	if (rad_config == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[mod_radius_cdr] Error initializing radius, session not logged.\n");
		goto end;
	}

	if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) {
		uuid_str = switch_core_session_get_uuid(session);
	} else {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[mod_radius_cdr] Error Generating Data!\n");
		goto end;
	}

	/* Create the radius packet */

	/* Set Status Type */
	if (rc_avpair_add(rad_config, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Acct-Session-ID: %s\n", uuid_str);
		rc_destroy(rad_config);
		goto end;
	}

	if (rc_avpair_add(rad_config, &send, PW_ACCT_SESSION_ID, uuid_str, -1, 0) == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Acct-Session-ID: %s\n", uuid_str);
		rc_destroy(rad_config);
		goto end;
	}

	/* Add VSAs */

	if (channel) {
		switch_call_cause_t cause;
		switch_caller_profile_t *profile;

		cause = switch_channel_get_cause(channel);
		if (rc_avpair_add(rad_config, &send, PW_FS_HANGUPCAUSE, &cause, -1, PW_FS_PEC) == NULL) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Hangupcause: %d\n", cause);
			rc_destroy(rad_config);
			goto end;
		}

		profile = switch_channel_get_caller_profile(channel);

		if (profile) {

			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[mod_radius_cdr] Calculating billable time\n");

			/* calculate billable time */
			callstartdate = profile->times->created;
			callanswerdate = profile->times->answered;
			calltransferdate = profile->times->transferred;
			callenddate = profile->times->hungup;

			if (switch_channel_test_flag(channel, CF_ANSWERED)) {
				if (callstartdate && callanswerdate) {
					if (callenddate)
						billusec = callenddate - callanswerdate;
					else if (calltransferdate)
						billusec = calltransferdate - callanswerdate;
				}
			} else if (switch_channel_test_flag(channel, CF_TRANSFER)) {
				if (callanswerdate && calltransferdate)
					billusec = calltransferdate - callanswerdate;
			}
			billsec = (billusec / 1000000);

			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[mod_radius_cdr] Finished calculating billable time\n");

			if (profile->username) {
				if (rc_avpair_add(rad_config, &send, PW_USER_NAME, (void *) profile->username, -1, 0) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding User-Name: %s\n", profile->username);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->caller_id_number) {
				if (rc_avpair_add(rad_config, &send, PW_FS_SRC, (void *) profile->caller_id_number, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Src: %s\n", profile->caller_id_number);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->caller_id_name) {
				if (rc_avpair_add(rad_config, &send, PW_FS_CLID, (void *) profile->caller_id_name, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-CLID: %s\n", profile->caller_id_name);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->destination_number) {
				if (rc_avpair_add(rad_config, &send, PW_FS_DST, (void *) profile->destination_number, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Dst: %s\n", profile->destination_number);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->dialplan) {
				if (rc_avpair_add(rad_config, &send, PW_FS_DIALPLAN, (void *) profile->dialplan, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Dialplan: %s\n", profile->dialplan);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->network_addr) {
				if (rc_avpair_add(rad_config, &send, PW_FRAMED_IP_ADDRESS, (void *) profile->network_addr, -1, 0) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Framed-IP-Address: %s\n", profile->network_addr);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->rdnis) {
				if (rc_avpair_add(rad_config, &send, PW_FS_RDNIS, (void *) profile->rdnis, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-RDNIS: %s\n", profile->rdnis);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->context) {
				if (rc_avpair_add(rad_config, &send, PW_FS_CONTEXT, (void *) profile->context, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Context: %s\n", profile->context);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->ani) {
				if (rc_avpair_add(rad_config, &send, PW_FS_ANI, (void *) profile->ani, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-ANI: %s\n", profile->ani);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->aniii) {
				if (rc_avpair_add(rad_config, &send, PW_FS_ANIII, (void *) profile->aniii, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-ANIII: %s\n", profile->aniii);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->source) {
				if (rc_avpair_add(rad_config, &send, PW_FS_SOURCE, (void *) profile->source, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Source: %s\n", profile->source);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (profile->caller_extension && profile->caller_extension->last_application && 
			    profile->caller_extension->last_application->application_name) {
				if (rc_avpair_add(rad_config, &send, PW_FS_LASTAPP,
								  (void *) profile->caller_extension->last_application->application_name, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Lastapp: %s\n", profile->source);
					rc_destroy(rad_config);
					goto end;
				}
			}
			if (rc_avpair_add(rad_config, &send, PW_FS_BILLUSEC, &billusec, -1, PW_FS_PEC) == NULL) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Billusec: %u\n", (uint32_t) billusec);
				rc_destroy(rad_config);
				goto end;
			}

			if (callstartdate > 0) {
				switch_time_exp_lt(&tm, callstartdate);
				switch_snprintf(buffer, sizeof(buffer), "%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
								tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
								tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
				if (rc_avpair_add(rad_config, &send, PW_FS_CALLSTARTDATE, &buffer, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Callstartdate: %s\n", buffer);
					rc_destroy(rad_config);
					goto end;
				}
			}

			if (callanswerdate > 0) {
				switch_time_exp_lt(&tm, callanswerdate);
				switch_snprintf(buffer, sizeof(buffer), "%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
								tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
								tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
				if (rc_avpair_add(rad_config, &send, PW_FS_CALLANSWERDATE, &buffer, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Callanswerdate: %s\n", buffer);
					rc_destroy(rad_config);
					goto end;
				}
			}

			if (calltransferdate > 0) {
				switch_time_exp_lt(&tm, calltransferdate);
				switch_snprintf(buffer, sizeof(buffer), "%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
								tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
								tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
				if (rc_avpair_add(rad_config, &send, PW_FS_CALLTRANSFERDATE, &buffer, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Calltransferdate: %s\n", buffer);
					rc_destroy(rad_config);
					goto end;
				}
			}

			if (callenddate > 0) {
				switch_time_exp_lt(&tm, callenddate);
				switch_snprintf(buffer, sizeof(buffer), "%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d",
								tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
								tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
				if (rc_avpair_add(rad_config, &send, PW_FS_CALLENDDATE, &buffer, -1, PW_FS_PEC) == NULL) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Freeswitch-Callenddate: %s\n", buffer);
					rc_destroy(rad_config);
					goto end;
				}
			}

			if (rc_avpair_add(rad_config, &send, PW_ACCT_SESSION_TIME, &billsec, -1, 0) == NULL) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed adding Acct-Session-Time: %u\n", billsec);
				rc_destroy(rad_config);
				goto end;
			}
		} else {				/* no profile, can't create data to send */
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "profile == NULL\n");
		}
	}

	struct acct_packet *acct_stop = NULL;

	acct_stop = malloc(sizeof(&acct_stop));

        memset(acct_stop, 0, sizeof(&acct_stop));

        acct_stop->rad_config = rad_config;
        acct_stop->data = send;

        switch_queue_push(rad_queue,acct_stop);

 end:
	switch_thread_rwlock_unlock(globals.rwlock);
	return (SWITCH_STATUS_SUCCESS);
}

static switch_status_t load_config(void)
{
	switch_xml_t cfg, xml, settings, param;

	int num_servers = 0;
	int i = 0;

	my_timeout = "5";
	my_retries = "3";
	my_deadtime = "0";
	strncpy(my_seqfile, "/var/run/radius.seq", PATH_MAX - 1);
	strncpy(my_dictionary, "/usr/local/freeswitch/conf/radius/dictionary", PATH_MAX - 1);

	for (i = 0; i < SERVER_MAX; i++) {
		my_servers[i][0] = '\0';
	}

	if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
		return SWITCH_STATUS_TERM;
	}

	if ((settings = switch_xml_child(cfg, "settings"))) {
		for (param = switch_xml_child(settings, "param"); param; param = param->next) {
			char *var = (char *) switch_xml_attr_soft(param, "name");
			char *val = (char *) switch_xml_attr_soft(param, "value");

			if (!strcmp(var, "acctserver")) {
				if (num_servers < SERVER_MAX) {
					strncpy(my_servers[num_servers], val, 255 - 1);
					num_servers++;
				} else {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
									  "you can only specify %d radius servers, ignoring excess server entry\n", SERVER_MAX);
				}
			} else if (!strcmp(var, "dictionary")) {
				strncpy(my_dictionary, val, PATH_MAX - 1);
			} else if (!strcmp(var, "seqfile")) {
				strncpy(my_seqfile, val, PATH_MAX - 1);
			} else if (!strcmp(var, "radius_timeout")) {
				my_timeout = strdup(val);
			} else if (!strcmp(var, "radius_retries")) {
				my_retries = strdup(val);
			} else if (!strcmp(var, "radius_deadtime")) {
				my_deadtime = strdup(val);
			}
		}
	}

	switch_xml_free(xml);

	if (num_servers < 1) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "you must specify at least 1 radius server\n");
		return SWITCH_STATUS_TERM;
	}

	/* If we made it this far, we succeeded */
	return SWITCH_STATUS_SUCCESS;
}

static const switch_state_handler_table_t state_handlers = {
	/*.on_init */ NULL,
	/*.on_routing */ my_on_routing,
	/*.on_execute */ NULL,
	/*.on_hangup */ my_on_hangup,
	/*.on_exchange_media */ NULL,
	/*.on_soft_execute */ NULL
};

SWITCH_MODULE_LOAD_FUNCTION(mod_radius_cdr_load)
{

	switch_thread_rwlock_create(&globals.rwlock, pool);

	if (load_config() != SWITCH_STATUS_SUCCESS) {
		return SWITCH_STATUS_TERM;
	}

	if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not create pool for module\n");
                return SWITCH_STATUS_TERM;
        }

	// the queue limit could be configurable but we leave it hardcoded for now

        switch_queue_create(&rad_queue, 10000, module_pool);

	/* test global state handlers */
        switch_core_add_state_handler(&state_handlers);

	// the queue processing threads number could be configurable but we leave it hardcoded for now

	switch_thread_t *thread[10];
	switch_threadattr_t *thd_attr = NULL;

        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initializing radius threads\n");

        switch_threadattr_create(&thd_attr, pool);
        switch_threadattr_detach_set(thd_attr, 1);
	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);

	for(int i=0;i<10;i++){

	        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Creating radius thread\n");

	        switch_thread_create(&thread[i], thd_attr, process_packets, &i, pool);

	}

	*module_interface = switch_loadable_module_create_module_interface(pool, modname);

	/* indicate that the module should continue to be loaded */
	return SWITCH_STATUS_SUCCESS;
}


SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_radius_cdr_shutdown)
{

	globals.shutdown = 1;
	switch_core_remove_state_handler(&state_handlers);
	switch_thread_rwlock_wrlock(globals.rwlock);
	switch_thread_rwlock_unlock(globals.rwlock);

	return SWITCH_STATUS_SUCCESS;
}

/* For Emacs:
 * Local Variables:
 * mode:c
 * indent-tabs-mode:t
 * tab-width:4
 * c-basic-offset:4
 * End:
 * For VIM:
 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
 */
-------------- next part --------------
Index: src/mod/event_handlers/mod_radius_cdr/mod_radius_cdr.c
===================================================================
--- src/mod/event_handlers/mod_radius_cdr/mod_radius_cdr.c	(revision 11727)
+++ src/mod/event_handlers/mod_radius_cdr/mod_radius_cdr.c	(working copy)
@@ -1,6 +1,6 @@
 /* 
  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
- * Copyright (C) 2005/2006, Anthony Minessale II <anthm at freeswitch.org>
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct at yahoo.com>
  *
  * Version: MPL 1.1
  *
@@ -17,7 +17,7 @@
  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
  *
  * The Initial Developer of the Original Code is
- * Anthony Minessale II <anthm at freeswitch.org>
+ * Anthony Minessale II <anthmct at yahoo.com>
  * Portions created by the Initial Developer are Copyright (C)
  * the Initial Developer. All Rights Reserved.
  *
@@ -39,6 +39,9 @@
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_radius_cdr_shutdown);
 SWITCH_MODULE_DEFINITION(mod_radius_cdr, mod_radius_cdr_load, mod_radius_cdr_shutdown, NULL);
 
+switch_memory_pool_t *module_pool = NULL;
+switch_queue_t *rad_queue = NULL;
+
 static struct {
 	int shutdown;
 	switch_thread_rwlock_t *rwlock;
@@ -52,6 +55,47 @@
 static char *my_retries;		/* 3 */
 static char my_servers[SERVER_MAX][255];
 
+struct acct_packet {
+
+	rc_handle *rad_config;
+	VALUE_PAIR *data;
+
+};
+
+static void *SWITCH_THREAD_FUNC process_packets(switch_thread_t *thread, void *ptr){
+
+	void *pop = NULL;
+
+	while(1){
+
+		if(switch_queue_pop(rad_queue,&pop) != SWITCH_STATUS_SUCCESS || !pop){
+
+			switch_yield(1000);
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[mod_radius_cdr] nothing to do thread is sleeping\n");		
+
+		} else {
+
+		        struct acct_packet *tmp = (struct acct_packet *) pop;
+
+		        if (rc_acct(tmp->rad_config, 0, tmp->data) == OK_RC) {
+		                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[mod_radius_cdr] RADIUS Accounting Packet OK\n");
+	        	} else {
+        	        	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[mod_radius_cdr] RADIUS Accounting Packet FAILED\n");
+	        	}
+
+
+			switch_safe_free(tmp->data);
+			switch_safe_free(tmp->rad_config);
+			switch_safe_free(tmp);
+
+		}
+
+	}
+
+	return 0;
+
+}
+
 static rc_handle *my_radius_init(void)
 {
 	int i = 0;
@@ -135,9 +179,8 @@
 	switch_xml_t cdr;
 	switch_channel_t *channel = switch_core_session_get_channel(session);
 	rc_handle *rad_config;
-	switch_status_t retval = SWITCH_STATUS_TERM;
 	VALUE_PAIR *send = NULL;
-	uint32_t client_port = 0;
+	//uint32_t client_port = 0;
 	uint32_t status_type = PW_STATUS_START;
 	switch_time_t callstartdate = 0;
 	switch_time_t callanswerdate = 0;
@@ -152,7 +195,7 @@
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[mod_radius_cdr] Entering my_on_routing\n");
 
 	if (globals.shutdown) {
-		return SWITCH_STATUS_FALSE;
+		return SWITCH_STATUS_SUCCESS;
 	}
 
 	if(channel) {
@@ -358,17 +401,20 @@
 		}
 	}
 
-	if (rc_acct(rad_config, client_port, send) == OK_RC) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[mod_radius_cdr] RADIUS Accounting OK\n");
-		retval = SWITCH_STATUS_SUCCESS;
-	} else {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[mod_radius_cdr] RADIUS Accounting Failed\n");
-		retval = SWITCH_STATUS_TERM;
-	}
-	rc_avpair_free(send);
+	struct acct_packet *acct_start = NULL;
+
+	acct_start = malloc(sizeof(&acct_start));
+	
+	memset(acct_start, 0, sizeof(&acct_start));
+
+	acct_start->rad_config = rad_config;
+	acct_start->data = send;
+
+	switch_queue_push(rad_queue,acct_start);
+
  end:
 	switch_thread_rwlock_unlock(globals.rwlock);
-	return (retval);
+	return (SWITCH_STATUS_SUCCESS);
 }
 
 static switch_status_t my_on_hangup(switch_core_session_t *session)
@@ -376,9 +422,7 @@
 	switch_xml_t cdr;
 	switch_channel_t *channel = switch_core_session_get_channel(session);
 	rc_handle *rad_config;
-	switch_status_t retval = SWITCH_STATUS_TERM;
 	VALUE_PAIR *send = NULL;
-	uint32_t client_port = 0;
 	uint32_t status_type = PW_STATUS_STOP;
 	switch_time_t callstartdate = 0;
 	switch_time_t callanswerdate = 0;
@@ -627,18 +671,20 @@
 		}
 	}
 
-	if (rc_acct(rad_config, client_port, send) == OK_RC) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RADIUS Accounting OK\n");
-		retval = SWITCH_STATUS_SUCCESS;
-	} else {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RADIUS Accounting Failed\n");
-		retval = SWITCH_STATUS_TERM;
-	}
-	rc_avpair_free(send);
+	struct acct_packet *acct_stop = NULL;
 
+	acct_stop = malloc(sizeof(&acct_stop));
+
+        memset(acct_stop, 0, sizeof(&acct_stop));
+
+        acct_stop->rad_config = rad_config;
+        acct_stop->data = send;
+
+        switch_queue_push(rad_queue,acct_stop);
+
  end:
 	switch_thread_rwlock_unlock(globals.rwlock);
-	return (retval);
+	return (SWITCH_STATUS_SUCCESS);
 }
 
 static switch_status_t load_config(void)
@@ -719,9 +765,37 @@
 		return SWITCH_STATUS_TERM;
 	}
 
+	if (switch_core_new_memory_pool(&module_pool) != SWITCH_STATUS_SUCCESS) {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not create pool for module\n");
+                return SWITCH_STATUS_TERM;
+        }
+
+	// the queue limit could be configurable but we leave it hardcoded for now
+
+        switch_queue_create(&rad_queue, 10000, module_pool);
+
 	/* test global state handlers */
-	switch_core_add_state_handler(&state_handlers);
+        switch_core_add_state_handler(&state_handlers);
 
+	// the queue processing threads number could be configurable but we leave it hardcoded for now
+
+	switch_thread_t *thread[10];
+	switch_threadattr_t *thd_attr = NULL;
+
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initializing radius threads\n");
+
+        switch_threadattr_create(&thd_attr, pool);
+        switch_threadattr_detach_set(thd_attr, 1);
+	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+
+	for(int i=0;i<10;i++){
+
+	        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Creating radius thread\n");
+
+	        switch_thread_create(&thread[i], thd_attr, process_packets, &i, pool);
+
+	}
+
 	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
 
 	/* indicate that the module should continue to be loaded */


More information about the Freeswitch-dev mailing list