reSIProcate介绍(英文)

 


 

reSIProcate SIP stack overview

 

reSIProcate is a high performance, object-oriented, C++ sip stack that is compliant with RFC 3261. It includes support for a wide variety of operating systems, including Windows and Linux. It has full support for UDP, TCP, and TLS transports on both IPv4 and IPv6. It also implements the full set of specifications for DNS usage in SIP, including NAPTR and SRV lookups (RFCs: 3263, 2915, 2782) using an asynchronous DNS library (ares).  One major difference found between Vovida stack and reSIProcate stack is that Vovida stack’s state machine doesn’t clearly differentiate between SIP UAC and UAS, when reSIProcate does. Refer to following figure for a high level architecture of reSIProcate.

 

 

<!--[if !vml]-->

 
 


Transport and Transaction Layer:

reSIProcate has been architected in a layered model. The bottom most layer being the transport layer. Transport layer supports TCP, UDP and TLS transport, each having its own FIFO for outgoing SIP messages (to be sent off the wire). Any incoming messages from the wire gets processed by one of there transports depending upon the configuration and a Transaction message (made out of incoming SIP message) gets added to the Transaction Layer’s FIFO. For outgoing SIP messages coming from the application, Transport Selector is used in selecting the right transport. Transaction layer is the next layer on top of Transport and it handles all SIP transactions with a state machine on its own.  It has a FIFO and Timer Queue associated with it. It has 6 simple state machines (ClientNonInvite, ClientInvite, ServerNonInvite,  ServerInvite, ClientStale, ServerStale, Stateless)  handling Client and Server, Invite and non-Invite transactions. Depending on the state of the transaction (Calling, Trying, Proceeding, Completed,  Confirmed,  Terminated,  Bogus) SIP message gets processed.  Following is the code which does the main processing in Transaction layer.

 

 

TransactionController::process(FdSet& fdset) {

/*Processes mesg. in TxFifo in the transport layer sending them off the wire. And rxes any SIP messages  coming off the wire and adds to the Transaction Controller FIFO */

mTransportSelector.process(fdset);

 

/* Processes Timers associated with Transactions */

            mTimers.process();       

 

/* Processes messages in its FIFO.  May contain, sip messages (requests and responses), timers (used by state machines),  asynchronous dns responses, transport errors from the underlying  transport, etc. */

       while (mStateMacFifo.messageAvailable())   //

      {

         TransactionState::process(*this);      

      }

}

 

In TransactionState::process, for incoming SIP messages from the wire,  Transaction layer adds the message to SipStack’s FIFO depending on the message. For example, if there is a SIP INVITE coming from the wire, a new ServerInvite state Machine will be created at “Trying” state and the INVITE message will be added to the SipStack’s FIFO. For a SIP INVITE coming from the application (like DUM), a new ClientInvite state machine will be created at “Calling” state and the INVITE will be sent out by calling TransactionState::sendToWire() which uses the Transport Selector to select the right transport to fire the message off the wire.  Transaction layer adds a timer message in its timer queue depending upon the message. For example, if there is an invite sent by the DUM to the wire, Transaction layer adds a TimerB message in its Timer Queue, which will timeout at (64*T1) where T1 is 500msec (Refer RFC 3261). If TimerB timeouts before getting any response for the SIP request sent out, Transaction layer takes appropriate action.

 

SipStack:

Tranaction layer is wrapped up in the SIP stack which has its own queue and a timer queue. Though the picture shows that it shares a timer queue with Transaction layer, in the code, it shows that it has its own queue. Timer associated with the SipStack is used for Application timer messages. Following is the code which does main processing in SipStack.

 

void SipStack::process(FdSet& fdset)

{

 if(!mShuttingDown && mStatisticsManagerEnabled)

 {

      mStatsManager.process();

 }

/* Things done on Transaction controller’s process are discussed above */

mTransactionController.process(fdset);

 

 /* (TU) Transaction User selector is used in selecting the right TU when there are more than one TU connected to the stack. It has a FIFO, which is used by TUs to inform shutdown and remove a TU. FIFO is called shutdown FIFO and the messages in that are processed here */

mTuSelector.process();

mDnsStub->process(fdset);

 

Lock lock(mAppTimerMutex);

 

/* processes  Application Timer messages added by the application */

mAppTimers.process();

}

 

Transaction User (TU):

       Refer to RFC 3261 for definition of TU. In reSIProcate, TU object comes with an Fifo on its own. TU can register and unregister  with SipStack by calling SipStack::registerTransactionUser() and SipStack::unregisterTransactionUser. If done, Transaction controller will add messages into TU’s queue instead of SipStack’s FIFO, by choosing the right TU through TUSelector. If not, messages will be added to SipStack’s queue by Transaction Controller.

 

Dialog Usage Manager (DUM):

 

(From www.resiprocate.org) The DialogUsageManager (or DUM) class sits on top of the transaction layer of the SIP stack. It keeps track of all of the Dialog-related data structures in multiple DialogSets. Each DialogSet contains all the Dialogs created by an initial request, which share the same SIP Call-Id and From tag. Inside a specific DialogSet on the UAC side, a BaseCreator can represent the intial request that generated the dialog. The DialogSet also contains several objects derived from BaseUsage that are using this particular dialog. There are several Usages available to a dialog: one InviteSession, one Registration, one Publication, multiple Subscriptions and multiple OutOfDialogRequests. Note: OutOfDialogRequests resemble a dialog, but are actually transactions that do not fit of the other categories. Requests that result in OutOfDialogRequests are MESSAGE and OPTIONS.  An initial SIP request is created by calling the makeX interfaces on the DUM. It is then sent using the send7 interface on the DUM. When a response is returned for the request, a callback from one of the Handler classes notifies the application. This will pass up some type of client or server usages class that can be used to send additional messages and responses in the context of this particular usage of the dialog. The Dialog Usage Manager makes writing user agents easy by hiding complex SIP specifics. DUM provides user agent functionality (both UAC and UAS), including the handling of INVITE and SUBSCRIBE/NOTIFY dialogs, registration, and instant messaging. A dum application creates a dum object, typically a single dum object for the entire application. This single dum object can manage multiple user agents. By default, the construction of the dum object creates a SipStack. DUM provides the following benefits:

  • Manages refreshes for you:
    • Just set up registration binding and keep it active
    • Set up a subscription and keep it active. DUM will let you know when new updates come in via ** NOTIFY requests
    • Keep an INVITE session active
    • Handles forking for you
    • Merged requests
    • GRUU
  • Implements Offer/Answer (rfc 3264)
  • Manages profile information such as authorization
  • Manages AppDialogSetFactory, which enables DUM to create your derived AppDialogSet object instead of the default one. An AppDialogSet is equivalent to a call. It is created when a call starts.
  • Manages and stores Handlers, which are a way of referencing usages: DialogSetHandler, InviteSessionHandler, ClientRegistrationHandler, ServerRegistrationHandler, ClientSubscriptionHandler, ServerSubscriptionHandler, ClientPublicationHandler, ServerPublicationHandler, OutOfDialogHandler, ClientPagerMessageHandler, ServerPagerMessageHandler, RegistrationPersistenceManager
  • Manages redirections (RedirectManager)
  • Manages client authentication (ClientAuthManager)
  • Manages server authentication (ServerAuthManager)
  • Interface to add new Transports
  • Manages handles to Usages (HandleManager)
  • Provides interfaces to create new sessions as a UAC (invite, subscription, publication, registration, pager, others)
  • Provides interfaces to find particular usages based on a DialogId

On the code side, Dum is inherited of HandleManager and Transaction User(TU) objects. HandleManager creates ids for all the handles created (for example, ClientInviteSession is a handle) and hold a hashmap of all handles. And Dum has a map of DialogSets keyed by DialogSetIds and it is also a place to hold handlers for InviteSession, ClientRegistration, ServerRegistration, Redirect, DialogSet, OutOfDialog, ClientSubscription, ServerSubscription, ClientPublication, ServerPublication, ClientPagerMessage, ServerPagerMessage and ExternalMessage. Applications has to set handles with Dum depending upon the features they wish to use. A client and server invite session handles are enough for a simple SIP call. Following code does the main processing in Dum.

 

// return true if there is more to do

bool DialogUsageManager::process(resip::RWMutex* mutex)

{

 

               // Checks messages in TU’s FIFO and processes it

   if (mFifo.messageAvailable())

   {

      if (mutex)

      {

         resip::Lock lock(*mutex);

         internalProcess(std::auto_ptr<Message>(mFifo.getNext()));

      }

      else

      {

         internalProcess(std::auto_ptr<Message>(mFifo.getNext()));

      }

   }

   return mFifo.messageAvailable();

}

TU’s FIFO can hold messages of various types – TransactionUserMessage (messages like TransactionUserRemoved, coming from TuSelector in response to a remove TU command), DestroyUsage (to delete a DialogSet),  DumTimeout, KeepAliveTimeout, ConnectionTerminated, DumCommand, ExternalMessage , incoming SipMessages.

Call Flow for an INVITE message sent by the application to outside world

Imagine an application is sending an SIP INVITE to outside world. From a high-level perspective, this is what happens. Applications should first register  handlers for InviteSessionHandler and other handler in Dialog Usage Manager based on what they are trying to do. By registering (using setInviteSessionHandler in DialogUsageManager), applications are trying to set callbacks to get notifications from the concerned sessions. In this case, Client and Server Invite Session objects  handle Client and Server Invite related messages. They have their own State Machine and states. Refer to https://www.resiprocate.org/DUM_Invite_Session_State_Diagrams for State diagrams. When a message gets processed by these sessions, they will make state transitions as per the State diagram and also call the call backs registered by the application through DialogUsageManager::setInviteSessionHandler(). Consider  SIP INVITE coming from an application look at the following code in dum/test/BasicCall.cxx.

TestUac uac;

dumUac->setInviteSessionHandler(&uac);

……

dumUac->send(dumUac->makeInviteSession(uasAor, uac.sdp, new testAppDialogSet(*dumUac, "UAC(INVITE)")));

By registering TestUac with Dum through setInviteSessionHandler, application is setting call backs for Invite related functions like onNewSession, onProvisional,  onConnected (refer to InviteSessionHandler) etc. In ClientInviteSession and ServerInviteSession objects, it can be seen that the callbacks set by the application is called depending on the state they are in. In our case, when the INVITE sent out by the application, ClientInviteSession is not created. A dialogset and a diolog object are created. When there is a response from the other side  for the INVITE,  Dialog::dispatch() gets the response and creates a new ClientInviteSession by calling makeClientInviteSession() and dispatches the response to the newly created session. When response come to this new Client Invite Session which is at UAC_Start state, it processes the response depending on its response code (like 100/180/200) and changes its state accordingly. Also it calls the call backs set by the application through,

 

InviteSessionHandler* handler = mDum.mInviteSessionHandler;

handler->onNewSession(getHandle(), InviteSession::None, msg);  /*called for 1xx response */

 

Applications can take appropriate actions in onNewSession(). In BasicCall.cxx, it can be seen that there is no action taken if it is a ClientInviteSession. But for a ServerInviteSession (INVITE received by the application from outside world), application goes back to the ServerInviteSession (using the handle sent to it as a parameter in onNewSession) and sends a 180 response by calling provisional(). This makes the ServerInviteSession changes its state as well as send the 180 response back on the wire.  ClientInvite and ServerInvite Sessions are State Machines fed by messages from the application(messages sent off the wire) as well as from Sipstack (messages coming off the wire). Interaction to the application is handled by registering respective handlers in Dum. It can be seen that SIP messages coming from the applications are directly fed into Transaction Controller’s FIFO while the messages coming from the wire goes through Transaction Controller FIFO and  SipStack/TU FIFO to Dum.

 

 

Message Flow in reSIProcate using Dum

v/:* {behavior:url(#default#VML);} o/:* {behavior:url(#default#VML);} w/:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} <!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} span.GramE {mso-style-name:""; mso-gram-e:yes;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:595.3pt 841.9pt; margin:177.95pt 81.65pt 177.95pt 81.65pt; mso-header-margin:42.55pt; mso-footer-margin:49.6pt; mso-paper-source:0; layout-grid:15.6pt;} div.Section1 {page:Section1;} -->

Transport  TxFifo

                            Transaction Controller FIFO

SIP mesg. coming from wire

 Sent over the network

SIP Mesg. coming from Appln.

SIP STACK FIFO or TU FIFO

Dum and Application

SIP mesg. coming from wire

SIP mesg. coming from wire

SIP Mesg. coming from Appln.

<!--[if !vml]--><!--[endif]-->

 

Transport  TxFifo

                            Transaction Controller FIFO

SIP mesg. coming from wire

 Sent over the network

SIP Mesg. coming from Appln.

SIP STACK FIFO or TU FIFO

Dum and Application

SIP mesg. coming from wire

SIP mesg. coming from wire

SIP Mesg. coming from Appln.

 

 

From:http://blog.chinaunix.net/u3/108006/showart.php?id=2128783

 

你可能感兴趣的:(timer,application,dialog,asynchronous,layer,transactions)