[reSIProcate] process incoming calls design question - UML seqdiagram attached

Jay Hogg jay at 2imagineit.net
Sun Jan 23 18:06:10 CST 2005


I'll take a crack at this...  I'm not part of the Resip development team 
but I've been working with the code for quite a while, learned a lot of 
hard lessons and am doing some of the same work you are describing.  
What I say may not be part of the design goals but it is what I have 
found to work.

If you guys take another crack at relationships 
AppDialog/AppDialogSet/Dialogs/etc please post an invitation for 
comments. While I like most of what was done some things could be easier 
and I have some requests!  The biggest thing I want to do is divorce the 
Stack/DUM/Dialogs from the Application side but some of the knowledge 
needed on the application side is too embedded right now.

The basics of what I am doing (and understand that you are trying to do):
- Resip/Stack/DUM all run within a thread
- The "application" runs asynchronously in other thread(s)
- "events" are generated from DUM callbacks for the "application" to 
deal with later
- The application makes DUM requests as it sees fit during a "call" 
lifecycle.
- We're only talking about INVITE sessions here - no 
Publish/Subscribe/NIS stuff (I haven't dove into that yet).

1) You need a "forward" reference from DUM to your application data.  I 
build a string from DialogId() (is->getAppDialog()->getDialogId()) and 
store it in a map with a refrence to my object.

2) The "reverse" reference for your application must be the 
InviteSessionHandle (it casts so Client/Server) in order to get requests 
back to DUM.  I found no other option.

These 2 issues make it a "loose" coupling between DUM and the 
application.  My biggest issue with DUM right now and storing info in 
AppDialog/AppDialogSet is it goes away at a very wrong time for me - DUM 
may be done with it but my application wasn't.  Making this "loose" 
creates another issue - either the application or the DUM could make 
objects go away at really bad times.  I handled this with locks.  I 
haven't had a need to use an AppDialog for anything - an AppDialogSet is 
mandatory to "marry" up an outbound invite because it is the only way to 
get the DialogSetId() back.

3) The Resip/DUM processing runs as its own thread but NOT the thread 
dum::process() they have defined.  There must be a mutex that is owned 
by the Resip thread when dum::process(fdset) is executing or by an 
application thread when it is referencing an InviteSession handle.  
Watch the case of DUM executing a callback that your application 
immediately calls into DUM to respond - deadlock if not handled correctly.

4) ALWAYS (after aquiring the lock) to an invitesessionhandle.isValid() 
to make sure DUM hasn't destroyed the object - if it is valid it will 
stay valid through the duration of the lock (if you get locking right).

5) ALWAYS send() messages that relate to a session via 
invitesessionhandle->send() and NOT dum->send(). The send() on session 
handles is overloaded to special-case state handling based on current 
state and response. Failure to do this creates strange problems in state 
transitions in dialogs.

6) WATCH OUT for recurisve loops (this is how I also found #5).  
OnNewSession() calling app code calling send(reject()) results in DUM 
(within the context of OnNewSession!!!) calling onTerminated() calling 
application code. It got deeper than I expected and posed problems with 
locking/events. Example:

dum->process()
   handler->onNewSession(server)
      application->handleNewSession()
         is->send(is->reject(486))
            handler->onTerminated()
               application->handleTerminated()

At that point my MyAppDialog() instance went away with me 2 levels deep 
in calls...  just a lesson.

7) I have not found ANY circumstances where you MUST call send() or 
provide information in the context of the executing callback - 
everything I have tried has worked fine from delayed application 
handling as long as I used the invitesession->send().  DEVELOPERS:  Can 
you confirm this??

8) The way DUM implements Handled:: is MUCH cleaner than what I am doing 
and I didn't understand it initially so I avoided it.  Now I'm going to 
review my code an do something similar with 2 additions:
   - the ability to lock() a handle so the object can't be destroyed yet 
to pacify some of the interlock issues by scoping a lock to a call 
instance instead of the entire DUM execution or application execution.
   - an external "reference" so I don't have to keep the handle. In this 
case DialogId as a string.

I have code doing this at the moment dealing with the multiple threads, 
handling events, handling inbound calls and basic handling in place for 
outbound calls. By no means is it an application at this time. The goal 
of this is a "Media Server Application Framework" that supports SIP/MGCP 
on one side and Media Servers (small imbedded, Snowshore for basic, 
conference, VXML, Convedia if I can get my hands on one) via an 
abstracted interface that can be event based or a per-thread procedural 
method which makes building quick applications very easy.

The goal is open source but non-GPL non-Commercial use at this time...  
that said, if anybody wants it to take a look at how some things are 
structure just drop me a line (Linux 2.6 w/NPTL and TLS, autoconf - 
probably won't run on windows today).  Remember - it is ROUGH at this 
time and I'm proving out some interfaces but the interlocking is there.

Jay


Scott Godin wrote:

>You may want to have a look at the AppDialog and AppDialogSet objects.  A
>quick sample of their use is in BasicCall.cxx.  You can override with your
>own derived class and store pointers to these objects in your app.
>
>-----Original Message-----
>From: resiprocate-devel-bounces at list.sipfoundry.org
>[mailto:resiprocate-devel-bounces at list.sipfoundry.org] On Behalf Of Justin
>Matthews
>Sent: Saturday, January 22, 2005 3:10 PM
>To: resiprocate-devel at list.sipfoundry.org
>Subject: [reSIProcate] process incoming calls design question - UML
>seqdiagram attached
>
>Hello,
>
>I have a question on how to use the dum.  After handling the callbacks with
>my InviteSessionHandler derived class, I would like to store a minimal
>amount of information so that I can get the appropriate InviteSession for a
>call at a later time.  For example, when onNewSession is called I need to
>asynchronously pass the information about the new call to my apps internal
>system which will eventually call InviteSession::provisional and then
>InviteSession::send.  How would my internal system get the appropriate
>InviteSession?  What is the best way to do this?  Simply store the
>ServerInviteSessionHandle passed into my InviteSessionHandler?  Ideally I
>would not like to keep track of dum data objects such as the handle.  Is
>there a way to get a reference to the correct InviteSessionHandle using
>parts of the message (callid, to, from)?  
>
>Also, I will be doing at least a few more UML diagrams such as the one
>attached.  Please let me know if it is incorrect.  Being a newbie to the
>system I find this is the best way for me to jump on the learning curve.
>Are similar docs being developed right now for the dum?  I am willing to
>continue to post my docs to this thread and/or be educated on the current
>documentation plan to help in generating similar docs for the project.  
>
>Thanks,
>
>-Justin 
>
>
>_______________________________________________
>resiprocate-devel mailing list
>resiprocate-devel at list.sipfoundry.org
>https://list.sipfoundry.org/mailman/listinfo/resiprocate-devel
>  
>



More information about the resiprocate-devel mailing list