ht3-fsm.dox 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /**
  2. * @ingroup libosip2 The GNU oSIP stack
  3. * @defgroup howto_transaction How-To manage transactions.
  4. * @section howto_transaction1 Description.
  5. The interesting and somewhat complex feature implemented
  6. by osip is the 4 states machines that applied to the different
  7. transactions defined by the SIP rfc.
  8. SIP defines the following 4 state machines, abreviations
  9. used in osip are provided below:
  10. + **ICT** : Invite Client Transaction (Section 17.1.1)
  11. + **NICT**: Non Invite Client Transaction (Section 17.1.2)
  12. + **IST** : Invite Server Transaction (Section 17.2.1)
  13. + **NIST**: Non Invite Server Transaction (Section 17.2.2)
  14. As you can notice if you have read the rfc (do it!), those
  15. 4 state machines are provided as drawings within the SIP
  16. rfc3261.txt (section 17.1 and 17.2)
  17. As an exemple of what you'll find in the rfc3261, here is the
  18. drawing that apply to the "Invite Client Transaction" (page 127)
  19. <PRE>
  20. |INVITE from TU
  21. Timer A fires |INVITE sent
  22. Reset A, V Timer B fires
  23. INVITE sent +-----------+ or Transport Err.
  24. +---------| |---------------+inform TU
  25. | | Calling | |
  26. +-------->| |-------------->|
  27. +-----------+ 2xx |
  28. | | 2xx to TU |
  29. | |1xx |
  30. 300-699 +---------------+ |1xx to TU |
  31. ACK sent | | |
  32. resp. to TU | 1xx V |
  33. | 1xx to TU -----------+ |
  34. | +---------| | |
  35. | | |Proceeding |-------------->|
  36. | +-------->| | 2xx |
  37. | +-----------+ 2xx to TU |
  38. | 300-699 | |
  39. | ACK sent, | |
  40. | resp. to TU| |
  41. | | | NOTE:
  42. | 300-699 V |
  43. | ACK sent +-----------+Transport Err. | transitions
  44. | +---------| |Inform TU | labeled with
  45. | | | Completed |-------------->| the event
  46. | +-------->| | | over the action
  47. | +-----------+ | to take
  48. | ^ | |
  49. | | | Timer D fires |
  50. +--------------+ | - |
  51. | |
  52. V |
  53. +-----------+ |
  54. | | |
  55. | Terminated|<--------------+
  56. | |
  57. +-----------+
  58. Figure 5: INVITE client transaction
  59. </PRE>
  60. As you can expect, with osip an Invite Client Transaction may be
  61. in the CALLING, PROCEEDING, COMPLETED or TERMINATED state. To
  62. "execute" the state machine, you will build events, provide them
  63. to the correct transaction context and the the state of the
  64. transaction will be updated if the event is allowed in the current
  65. state.
  66. Events are divided in three categories:
  67. + **SIP messages**
  68. + **Timers**
  69. + **Transport Errors**
  70. * @section howto_transaction2 Managing a new transaction.
  71. Let's assume you want to implement a User Agent and you want to
  72. start a REGISTER transaction. Using the parser library, you will first
  73. have to build a SIP compliant message. (oSIP, as a low layer library
  74. provides an interface to build SIP messages, but it's up to you to
  75. correctly fill all the required fields.)
  76. As soon as you have build the SIP message, you are ready to start a new
  77. transaction. Here is the code:
  78. ~~~~~~~{.c}
  79. osip_t *osip = your_global_osip_context;
  80. osip_transaction_t *transaction;
  81. osip_message_t *sip_register_message;
  82. osip_event_t *sipevent;
  83. application_build_register(&sip_register_message);
  84. osip_transaction_init(&transaction,
  85. NICT, //a REGISTER is a Non-Invite-Client-Transaction
  86. osip,
  87. sip_register_message);
  88. // If you have a special context that you want to associate to that
  89. // transaction, you can use a special method that associate your context
  90. // to the transaction context.
  91. osip_transaction_set_your_instance(transaction, any_pointer);
  92. // at this point, the transaction context exists in oSIP but you still have
  93. // to give the SIP message to the finite state machine.
  94. sipevent = osip_new_outgoing_sipmessage (msg);
  95. sipevent->transactionid = transaction->transactionid;
  96. osip_transaction_add_event (transaction, sipevent);
  97. // at this point, the event will be handled by oSIP. (The memory resource will
  98. // also be handled by oSIP). Note that no action is taken there.
  99. ~~~~~~~
  100. Adding new events in the fsm is made with similar code.
  101. * @section howto_transaction3 Consuming events.
  102. The previous step show how to create a transaction and one possible way
  103. to add a new event. (Note, that some events -the TIMEOUT_* ones- will be
  104. added by oSIP not by the application). In this step, we describe how the
  105. oSIP stack will consume events. In fact, this is very simple, but you
  106. should be aware that it's not always allowed to consume an event at any time!
  107. The fsm MUST consume events sequentially within a transaction. This means
  108. that when your are calling osip_transaction_execute(), it is forbidden to call
  109. this method again with the same transaction context until the first call
  110. has returned. In a multi threaded application, if one thread handles one
  111. transaction, the code will be the following:
  112. ~~~~~~~{.c}
  113. while (1)
  114. {
  115. se = (osip_event_t *) osip_fifo_get (transaction->transactionff);
  116. if (se==NULL)
  117. osip_thread_exit ();
  118. if ( osip_transaction_execute (transaction,se)<1) // deletion asked
  119. osip_thread_exit ();
  120. }
  121. ~~~~~~~
  122. * @section howto_transaction4 Announcing events to the application layer.
  123. Looking at the case of a usual outgoing REGISTER transaction, this behaviour
  124. is expected.
  125. When an event is seen as useful for the fsm, it means that a transition
  126. from one state to another has to be done on the transaction context. If the
  127. event is SND_REQUEST (this is the case for an outgoing REGISTER), the
  128. callback previously registered to announce this action will be called. This
  129. callback is useless for the application as no action has to be taken at this
  130. step. A more interesting announcement will be made when consuming the
  131. first final response received. If the callbacks associated to 2xx message
  132. is called, then the transaction has succeeded. Inside this callback, you
  133. will probably inform the user of the success of the registration if you want
  134. to do so...
  135. If the final response is not a 2xx, or the network callback is called, you'll
  136. probably want to take some actions. For example, if you receive a 302, you'll
  137. probably want to retry a registration at the new location. All that decision
  138. is up to you.
  139. When the transaction reach the TERMINATED state (when the *kill* callback
  140. is called, you must remove it from the list of known transactions with
  141. ~~~~~~~{.c}
  142. static void cb_ict_kill_transaction(int type, osip_transaction_t *tr)
  143. {
  144. int i;
  145. fprintf(stdout, "testosip: transaction is over\n");
  146. i = osip_remove_transaction (_osip, tr);
  147. if (i!=0) fprintf(stderr, "testosip: cannot remove transaction\n");
  148. }
  149. ~~~~~~~
  150. */