Blame view

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