http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / userapps / opensource / libosip2 / src / osip2 / nist_fsm.c
1 /*
2   The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3   Copyright (C) 2001,2002,2003  Aymeric MOIZARD jack@atosc.org
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10   This library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14   
15   You should have received a copy of the GNU Lesser General Public
16   License along with this library; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #include <osip2/internal.h>
21 #include <osip2/osip.h>
22
23 #include "fsm.h"
24
25 osip_statemachine_t *nist_fsm;
26
27 osip_statemachine_t *
28 __nist_get_fsm ()
29 {
30   return nist_fsm;
31 }
32
33 void
34 __nist_unload_fsm ()
35 {
36   transition_t *transition;
37   osip_statemachine_t *statemachine = __nist_get_fsm ();
38
39   while (!osip_list_eol (statemachine->transitions, 0))
40     {
41       transition =
42         (transition_t *) osip_list_get (statemachine->transitions, 0);
43       osip_list_remove (statemachine->transitions, 0);
44       osip_free (transition);
45     }
46   osip_free (statemachine->transitions);
47   osip_free (statemachine);
48 }
49
50
51 void
52 __nist_load_fsm ()
53 {
54   transition_t *transition;
55
56   nist_fsm =
57     (osip_statemachine_t *) osip_malloc (sizeof (osip_statemachine_t));
58   nist_fsm->transitions = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
59   osip_list_init (nist_fsm->transitions);
60
61   transition = (transition_t *) osip_malloc (sizeof (transition_t));
62   transition->state = NIST_PRE_TRYING;
63   transition->type = RCV_REQUEST;
64   transition->method = (void (*)(void *, void *)) &nist_rcv_request;
65   osip_list_add (nist_fsm->transitions, transition, -1);
66
67   /* This can be used to announce request but is useless, as
68      the transaction cannot send any response yet!
69      transition         = (transition_t *) osip_malloc(sizeof(transition_t));
70      transition->state  = NIST_TRYING;
71      transition->type   = RCV_REQUEST;
72      transition->method = (void(*)(void *,void *))&nist_rcv_request;
73      osip_list_add(nist_fsm->transitions,transition,-1);
74    */
75
76   transition = (transition_t *) osip_malloc (sizeof (transition_t));
77   transition->state = NIST_TRYING;
78   transition->type = SND_STATUS_1XX;
79   transition->method = (void (*)(void *, void *)) &nist_snd_1xx;
80   osip_list_add (nist_fsm->transitions, transition, -1);
81
82   transition = (transition_t *) osip_malloc (sizeof (transition_t));
83   transition->state = NIST_TRYING;
84   transition->type = SND_STATUS_2XX;
85   transition->method = (void (*)(void *, void *)) &nist_snd_23456xx;
86   osip_list_add (nist_fsm->transitions, transition, -1);
87
88   transition = (transition_t *) osip_malloc (sizeof (transition_t));
89   transition->state = NIST_TRYING;
90   transition->type = SND_STATUS_3456XX;
91   transition->method = (void (*)(void *, void *)) &nist_snd_23456xx;
92   osip_list_add (nist_fsm->transitions, transition, -1);
93
94   transition = (transition_t *) osip_malloc (sizeof (transition_t));
95   transition->state = NIST_PROCEEDING;
96   transition->type = SND_STATUS_1XX;
97   transition->method = (void (*)(void *, void *)) &nist_snd_1xx;
98   osip_list_add (nist_fsm->transitions, transition, -1);
99
100   transition = (transition_t *) osip_malloc (sizeof (transition_t));
101   transition->state = NIST_PROCEEDING;
102   transition->type = SND_STATUS_2XX;
103   transition->method = (void (*)(void *, void *)) &nist_snd_23456xx;
104   osip_list_add (nist_fsm->transitions, transition, -1);
105
106   transition = (transition_t *) osip_malloc (sizeof (transition_t));
107   transition->state = NIST_PROCEEDING;
108   transition->type = SND_STATUS_3456XX;
109   transition->method = (void (*)(void *, void *)) &nist_snd_23456xx;
110   osip_list_add (nist_fsm->transitions, transition, -1);
111
112   transition = (transition_t *) osip_malloc (sizeof (transition_t));
113   transition->state = NIST_PROCEEDING;
114   transition->type = RCV_REQUEST;
115   transition->method = (void (*)(void *, void *)) &nist_rcv_request;
116   osip_list_add (nist_fsm->transitions, transition, -1);
117
118   transition = (transition_t *) osip_malloc (sizeof (transition_t));
119   transition->state = NIST_COMPLETED;
120   transition->type = TIMEOUT_J;
121   transition->method = (void (*)(void *, void *)) &osip_nist_timeout_j_event;
122   osip_list_add (nist_fsm->transitions, transition, -1);
123
124   transition = (transition_t *) osip_malloc (sizeof (transition_t));
125   transition->state = NIST_COMPLETED;
126   transition->type = RCV_REQUEST;
127   transition->method = (void (*)(void *, void *)) &nist_rcv_request;
128   osip_list_add (nist_fsm->transitions, transition, -1);
129
130 }
131
132 static void
133 nist_handle_transport_error (osip_transaction_t * nist, int err)
134 {
135   __osip_transport_error_callback (OSIP_NIST_TRANSPORT_ERROR, nist, err);
136   __osip_transaction_set_state (nist, NIST_TERMINATED);
137   __osip_kill_transaction_callback (OSIP_NIST_KILL_TRANSACTION, nist);
138   /* TODO: MUST BE DELETED NOW */
139 }
140
141 void
142 nist_rcv_request (osip_transaction_t * nist, osip_event_t * evt)
143 {
144   int i;
145   osip_t *osip = (osip_t *) nist->config;
146
147   if (nist->state == NIST_PRE_TRYING)   /* announce new REQUEST */
148     {
149       /* Here we have ist->orig_request == NULL */
150       nist->orig_request = evt->sip;
151
152       if (MSG_IS_REGISTER (evt->sip))
153         __osip_message_callback (OSIP_NIST_REGISTER_RECEIVED, nist,
154                                  nist->orig_request);
155       else if (MSG_IS_BYE (evt->sip))
156         __osip_message_callback (OSIP_NIST_BYE_RECEIVED, nist,
157                                  nist->orig_request);
158       else if (MSG_IS_OPTIONS (evt->sip))
159         __osip_message_callback (OSIP_NIST_OPTIONS_RECEIVED, nist,
160                                  nist->orig_request);
161       else if (MSG_IS_INFO (evt->sip))
162         __osip_message_callback (OSIP_NIST_INFO_RECEIVED, nist,
163                                  nist->orig_request);
164       else if (MSG_IS_CANCEL (evt->sip))
165         __osip_message_callback (OSIP_NIST_CANCEL_RECEIVED, nist,
166                                  nist->orig_request);
167       else if (MSG_IS_NOTIFY (evt->sip))
168         __osip_message_callback (OSIP_NIST_NOTIFY_RECEIVED, nist,
169                                  nist->orig_request);
170       else if (MSG_IS_SUBSCRIBE (evt->sip))
171         __osip_message_callback (OSIP_NIST_SUBSCRIBE_RECEIVED, nist,
172                                  nist->orig_request);
173       else
174         __osip_message_callback (OSIP_NIST_UNKNOWN_REQUEST_RECEIVED, nist,
175                                  nist->orig_request);
176     }
177   else                          /* NIST_PROCEEDING or NIST_COMPLETED */
178     {
179       /* delete retransmission */
180       osip_message_free (evt->sip);
181
182       __osip_message_callback (OSIP_NIST_REQUEST_RECEIVED_AGAIN, nist,
183                                nist->orig_request);
184       if (nist->last_response != NULL)  /* retransmit last response */
185         {
186           osip_via_t *via;
187
188           via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0);
189           if (via)
190             {
191               char *host;
192               int port;
193               osip_generic_param_t *maddr;
194               osip_generic_param_t *received;
195               osip_generic_param_t *rport;
196               osip_via_param_get_byname (via, "maddr", &maddr);
197               osip_via_param_get_byname (via, "received", &received);
198               osip_via_param_get_byname (via, "rport", &rport);
199               /* 1: user should not use the provided information
200                  (host and port) if they are using a reliable
201                  transport. Instead, they should use the already
202                  open socket attached to this transaction. */
203               /* 2: check maddr and multicast usage */
204               if (maddr != NULL)
205                 host = maddr->gvalue;
206               /* we should check if this is a multicast address and use
207                  set the "ttl" in this case. (this must be done in the
208                  UDP message (not at the SIP layer) */
209               else if (received != NULL)
210                 host = received->gvalue;
211               else
212                 host = via->host;
213
214               if (rport == NULL || rport->gvalue == NULL)
215                 {
216                   if (via->port != NULL)
217                     port = osip_atoi (via->port);
218                   else
219                     port = 5060;
220                 }
221               else
222                 port = osip_atoi (rport->gvalue);
223
224               i = osip->cb_send_message (nist, nist->last_response, host,
225                                          port, nist->out_socket);
226             }
227           else
228             i = -1;
229           if (i != 0)
230             {
231               nist_handle_transport_error (nist, i);
232               return;
233             }
234           else
235             {
236               if (MSG_IS_STATUS_1XX (nist->last_response))
237                 __osip_message_callback (OSIP_NIST_STATUS_1XX_SENT, nist,
238                                          nist->last_response);
239               else if (MSG_IS_STATUS_2XX (nist->last_response))
240                 __osip_message_callback (OSIP_NIST_STATUS_2XX_SENT_AGAIN,
241                                          nist, nist->last_response);
242               else
243                 __osip_message_callback (OSIP_NIST_STATUS_3456XX_SENT_AGAIN,
244                                          nist, nist->last_response);
245               return;
246             }
247         }
248       /* we are already in the proper state */
249       return;
250     }
251
252   /* we come here only if it was the first REQUEST received */
253   __osip_transaction_set_state (nist, NIST_TRYING);
254 }
255
256 void
257 nist_snd_1xx (osip_transaction_t * nist, osip_event_t * evt)
258 {
259   int i;
260   osip_via_t *via;
261   osip_t *osip = (osip_t *) nist->config;
262
263   if (nist->last_response != NULL)
264     {
265       osip_message_free (nist->last_response);
266     }
267   nist->last_response = evt->sip;
268
269   via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0);
270   if (via)
271     {
272       char *host;
273       int port;
274       osip_generic_param_t *maddr;
275       osip_generic_param_t *received;
276       osip_generic_param_t *rport;
277       osip_via_param_get_byname (via, "maddr", &maddr);
278       osip_via_param_get_byname (via, "received", &received);
279       osip_via_param_get_byname (via, "rport", &rport);
280       /* 1: user should not use the provided information
281          (host and port) if they are using a reliable
282          transport. Instead, they should use the already
283          open socket attached to this transaction. */
284       /* 2: check maddr and multicast usage */
285       if (maddr != NULL)
286         host = maddr->gvalue;
287       /* we should check if this is a multicast address and use
288          set the "ttl" in this case. (this must be done in the
289          UDP message (not at the SIP layer) */
290       else if (received != NULL)
291         host = received->gvalue;
292       else
293         host = via->host;
294
295       if (rport == NULL || rport->gvalue == NULL)
296         {
297           if (via->port != NULL)
298             port = osip_atoi (via->port);
299           else
300             port = 5060;
301         }
302       else
303         port = osip_atoi (rport->gvalue);
304       i = osip->cb_send_message (nist, nist->last_response, host,
305                                  port, nist->out_socket);
306     }
307   else
308     i = -1;
309   if (i != 0)
310     {
311       nist_handle_transport_error (nist, i);
312       return;
313     }
314   else
315     __osip_message_callback (OSIP_NIST_STATUS_1XX_SENT, nist,
316                              nist->last_response);
317
318   __osip_transaction_set_state (nist, NIST_PROCEEDING);
319 }
320
321 void
322 nist_snd_23456xx (osip_transaction_t * nist, osip_event_t * evt)
323 {
324   int i;
325   osip_via_t *via;
326   osip_t *osip = (osip_t *) nist->config;
327
328   if (nist->last_response != NULL)
329     {
330       osip_message_free (nist->last_response);
331     }
332   nist->last_response = evt->sip;
333
334   via = (osip_via_t *) osip_list_get (nist->last_response->vias, 0);
335   if (via)
336     {
337       char *host;
338       int port;
339       osip_generic_param_t *maddr;
340       osip_generic_param_t *received;
341       osip_generic_param_t *rport;
342       osip_via_param_get_byname (via, "maddr", &maddr);
343       osip_via_param_get_byname (via, "received", &received);
344       osip_via_param_get_byname (via, "rport", &rport);
345       /* 1: user should not use the provided information
346          (host and port) if they are using a reliable
347          transport. Instead, they should use the already
348          open socket attached to this transaction. */
349       /* 2: check maddr and multicast usage */
350       if (maddr != NULL)
351         host = maddr->gvalue;
352       /* we should check if this is a multicast address and use
353          set the "ttl" in this case. (this must be done in the
354          UDP message (not at the SIP layer) */
355       else if (received != NULL)
356         host = received->gvalue;
357       else
358         host = via->host;
359
360       if (rport == NULL || rport->gvalue == NULL)
361         {
362           if (via->port != NULL)
363             port = osip_atoi (via->port);
364           else
365             port = 5060;
366         }
367       else
368         port = osip_atoi (rport->gvalue);
369       i = osip->cb_send_message (nist, nist->last_response, host,
370                                  port, nist->out_socket);
371     }
372   else
373     i = -1;
374   if (i != 0)
375     {
376       nist_handle_transport_error (nist, i);
377       return;
378     }
379   else
380     {
381       if (EVT_IS_SND_STATUS_2XX (evt))
382         __osip_message_callback (OSIP_NIST_STATUS_2XX_SENT, nist,
383                                  nist->last_response);
384       else if (MSG_IS_STATUS_3XX (nist->last_response))
385         __osip_message_callback (OSIP_NIST_STATUS_3XX_SENT, nist,
386                                  nist->last_response);
387       else if (MSG_IS_STATUS_4XX (nist->last_response))
388         __osip_message_callback (OSIP_NIST_STATUS_4XX_SENT, nist,
389                                  nist->last_response);
390       else if (MSG_IS_STATUS_5XX (nist->last_response))
391         __osip_message_callback (OSIP_NIST_STATUS_5XX_SENT, nist,
392                                  nist->last_response);
393       else
394         __osip_message_callback (OSIP_NIST_STATUS_6XX_SENT, nist,
395                                  nist->last_response);
396     }
397
398   if (nist->state != NIST_COMPLETED)    /* start J timer */
399     {
400       gettimeofday (&nist->nist_context->timer_j_start, NULL);
401       add_gettimeofday (&nist->nist_context->timer_j_start,
402                         nist->nist_context->timer_j_length);
403     }
404
405   __osip_transaction_set_state (nist, NIST_COMPLETED);
406 }
407
408
409 void
410 osip_nist_timeout_j_event (osip_transaction_t * nist, osip_event_t * evt)
411 {
412   nist->nist_context->timer_j_length = -1;
413   nist->nist_context->timer_j_start.tv_sec = -1;
414
415   __osip_transaction_set_state (nist, NIST_TERMINATED);
416   __osip_kill_transaction_callback (OSIP_NIST_KILL_TRANSACTION, nist);
417 }