http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / userapps / opensource / libosip2 / src / osip2 / ist_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 *ist_fsm;
26
27 osip_statemachine_t *
28 __ist_get_fsm ()
29 {
30   return ist_fsm;
31 }
32
33 void
34 __ist_unload_fsm ()
35 {
36   transition_t *transition;
37   osip_statemachine_t *statemachine = __ist_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 __ist_load_fsm ()
53 {
54   transition_t *transition;
55
56   ist_fsm =
57     (osip_statemachine_t *) osip_malloc (sizeof (osip_statemachine_t));
58   ist_fsm->transitions = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
59   osip_list_init (ist_fsm->transitions);
60
61   transition = (transition_t *) osip_malloc (sizeof (transition_t));
62   transition->state = IST_PRE_PROCEEDING;
63   transition->type = RCV_REQINVITE;
64   transition->method = (void (*)(void *, void *)) &ist_rcv_invite;
65   osip_list_add (ist_fsm->transitions, transition, -1);
66
67   transition = (transition_t *) osip_malloc (sizeof (transition_t));
68   transition->state = IST_PROCEEDING;
69   transition->type = RCV_REQINVITE;
70   transition->method = (void (*)(void *, void *)) &ist_rcv_invite;
71   osip_list_add (ist_fsm->transitions, transition, -1);
72
73   transition = (transition_t *) osip_malloc (sizeof (transition_t));
74   transition->state = IST_COMPLETED;
75   transition->type = RCV_REQINVITE;
76   transition->method = (void (*)(void *, void *)) &ist_rcv_invite;
77   osip_list_add (ist_fsm->transitions, transition, -1);
78
79   transition = (transition_t *) osip_malloc (sizeof (transition_t));
80   transition->state = IST_COMPLETED;
81   transition->type = TIMEOUT_G;
82   transition->method = (void (*)(void *, void *)) &osip_ist_timeout_g_event;
83   osip_list_add (ist_fsm->transitions, transition, -1);
84
85   transition = (transition_t *) osip_malloc (sizeof (transition_t));
86   transition->state = IST_COMPLETED;
87   transition->type = TIMEOUT_H;
88   transition->method = (void (*)(void *, void *)) &osip_ist_timeout_h_event;
89   osip_list_add (ist_fsm->transitions, transition, -1);
90
91   transition = (transition_t *) osip_malloc (sizeof (transition_t));
92   transition->state = IST_PROCEEDING;
93   transition->type = SND_STATUS_1XX;
94   transition->method = (void (*)(void *, void *)) &ist_snd_1xx;
95   osip_list_add (ist_fsm->transitions, transition, -1);
96
97   transition = (transition_t *) osip_malloc (sizeof (transition_t));
98   transition->state = IST_PROCEEDING;
99   transition->type = SND_STATUS_2XX;
100   transition->method = (void (*)(void *, void *)) &ist_snd_2xx;
101   osip_list_add (ist_fsm->transitions, transition, -1);
102
103   transition = (transition_t *) osip_malloc (sizeof (transition_t));
104   transition->state = IST_PROCEEDING;
105   transition->type = SND_STATUS_3456XX;
106   transition->method = (void (*)(void *, void *)) &ist_snd_3456xx;
107   osip_list_add (ist_fsm->transitions, transition, -1);
108
109   transition = (transition_t *) osip_malloc (sizeof (transition_t));
110   transition->state = IST_COMPLETED;
111   transition->type = RCV_REQACK;
112   transition->method = (void (*)(void *, void *)) &ist_rcv_ack;
113   osip_list_add (ist_fsm->transitions, transition, -1);
114
115   transition = (transition_t *) osip_malloc (sizeof (transition_t));
116   transition->state = IST_CONFIRMED;
117   transition->type = RCV_REQACK;
118   transition->method = (void (*)(void *, void *)) &ist_rcv_ack;
119   osip_list_add (ist_fsm->transitions, transition, -1);
120
121   transition = (transition_t *) osip_malloc (sizeof (transition_t));
122   transition->state = IST_CONFIRMED;
123   transition->type = TIMEOUT_I;
124   transition->method = (void (*)(void *, void *)) &osip_ist_timeout_i_event;
125   osip_list_add (ist_fsm->transitions, transition, -1);
126
127 }
128
129 osip_message_t *
130 ist_create_resp_100 (osip_transaction_t * ist, osip_message_t * request)
131 {
132   int i;
133   osip_message_t *resp_100;
134
135   i = osip_message_init (&resp_100);
136   if (i != 0)
137     return NULL;
138
139   /* follow instructions from 8.2.6 */
140   i = osip_from_clone (request->from, &(resp_100->from));
141   if (i != 0)
142     goto icr_error;
143   /* 17.2.1 says: should NOT add a tag */
144   i = osip_to_clone (request->to, &(resp_100->to));     /* DOES NOT include any tag! */
145   if (i != 0)
146     goto icr_error;
147   i = osip_call_id_clone (request->call_id, &(resp_100->call_id));
148   if (i != 0)
149     goto icr_error;
150   i = osip_cseq_clone (request->cseq, &(resp_100->cseq));
151   if (i != 0)
152     goto icr_error;
153
154   /* Via headers are copied from request */
155   {
156     int pos = 0;
157     osip_via_t *via;
158     osip_via_t *orig_via;
159
160     while (!osip_list_eol (ist->orig_request->vias, pos))
161       {
162         orig_via =
163           (osip_via_t *) osip_list_get (ist->orig_request->vias, pos);
164         osip_via_clone (orig_via, &via);
165         osip_list_add (resp_100->vias, via, -1);
166         pos++;
167       }
168   }
169
170   /* TODO: */
171   /* MUST copy the "Timestamp" header here (+ add a delay if necessary!)        */
172   /* a delay should not be necessary for 100 as it is sent in less than one sec */
173
174
175   return resp_100;
176 icr_error:
177   osip_message_free (resp_100);
178   return NULL;
179 }
180
181 static void
182 ist_handle_transport_error (osip_transaction_t * ist, int err)
183 {
184   __osip_transport_error_callback (OSIP_IST_TRANSPORT_ERROR, ist, err);
185   __osip_transaction_set_state (ist, IST_TERMINATED);
186   __osip_kill_transaction_callback (OSIP_IST_KILL_TRANSACTION, ist);
187   /* TODO: MUST BE DELETED NOW */
188 }
189
190 void
191 ist_rcv_invite (osip_transaction_t * ist, osip_event_t * evt)
192 {
193   int i;
194   osip_t *osip = (osip_t *) ist->config;
195
196   if (ist->state == IST_PRE_PROCEEDING) /* announce new INVITE */
197     {
198       /* Here we have ist->orig_request == NULL */
199       ist->orig_request = evt->sip;
200
201       __osip_message_callback (OSIP_IST_INVITE_RECEIVED, ist, evt->sip);
202     }
203   else                          /* IST_PROCEEDING or IST_COMPLETED */
204     {
205       /* delete retransmission */
206       osip_message_free (evt->sip);
207
208       __osip_message_callback (OSIP_IST_INVITE_RECEIVED_AGAIN, ist,
209                                ist->orig_request);
210       if (ist->last_response != NULL)   /* retransmit last response */
211         {
212           osip_via_t *via;
213
214           via = (osip_via_t *) osip_list_get (ist->last_response->vias, 0);
215           if (via)
216             {
217               char *host;
218               int port;
219               osip_generic_param_t *maddr;
220               osip_generic_param_t *received;
221               osip_generic_param_t *rport;
222               osip_via_param_get_byname (via, "maddr", &maddr);
223               osip_via_param_get_byname (via, "received", &received);
224               osip_via_param_get_byname (via, "rport", &rport);
225               /* 1: user should not use the provided information
226                  (host and port) if they are using a reliable
227                  transport. Instead, they should use the already
228                  open socket attached to this transaction. */
229               /* 2: check maddr and multicast usage */
230               if (maddr != NULL)
231                 host = maddr->gvalue;
232               /* we should check if this is a multicast address and use
233                  set the "ttl" in this case. (this must be done in the
234                  UDP message (not at the SIP layer) */
235               else if (received != NULL)
236                 host = received->gvalue;
237               else
238                 host = via->host;
239
240               if (rport == NULL || rport->gvalue == NULL)
241                 {
242                   if (via->port != NULL)
243                     port = osip_atoi (via->port);
244                   else
245                     port = 5060;
246                 }
247               else
248                 port = osip_atoi (rport->gvalue);
249
250               i = osip->cb_send_message (ist, ist->last_response, host,
251                                          port, ist->out_socket);
252             }
253           else
254             i = -1;
255           if (i != 0)
256             {
257               ist_handle_transport_error (ist, i);
258               return;
259             }
260           else
261             {
262               if (MSG_IS_STATUS_1XX (ist->last_response))
263                 __osip_message_callback (OSIP_IST_STATUS_1XX_SENT, ist,
264                                          ist->last_response);
265               else if (MSG_IS_STATUS_2XX (ist->last_response))
266                 __osip_message_callback (OSIP_IST_STATUS_2XX_SENT_AGAIN, ist,
267                                          ist->last_response);
268               else
269                 __osip_message_callback (OSIP_IST_STATUS_3456XX_SENT_AGAIN,
270                                          ist, ist->last_response);
271             }
272         }
273       return;
274     }
275
276   /* we come here only if it was the first INVITE received */
277   __osip_transaction_set_state (ist, IST_PROCEEDING);
278 }
279
280 void
281 osip_ist_timeout_g_event (osip_transaction_t * ist, osip_event_t * evt)
282 {
283   osip_via_t *via;
284   osip_t *osip = (osip_t *) ist->config;
285   int i;
286
287   ist->ist_context->timer_g_length = ist->ist_context->timer_g_length * 2;
288   if (ist->ist_context->timer_g_length > 4000)
289     ist->ist_context->timer_g_length = 4000;
290   gettimeofday (&ist->ist_context->timer_g_start, NULL);
291   add_gettimeofday (&ist->ist_context->timer_g_start,
292                     ist->ist_context->timer_g_length);
293
294   /* retransmit RESPONSE */
295   via = (osip_via_t *) osip_list_get (ist->last_response->vias, 0);
296   if (via)
297     {
298       char *host;
299       int port;
300       osip_generic_param_t *maddr;
301       osip_generic_param_t *received;
302       osip_generic_param_t *rport;
303       osip_via_param_get_byname (via, "maddr", &maddr);
304       osip_via_param_get_byname (via, "received", &received);
305       osip_via_param_get_byname (via, "rport", &rport);
306       /* 1: user should not use the provided information
307          (host and port) if they are using a reliable
308          transport. Instead, they should use the already
309          open socket attached to this transaction. */
310       /* 2: check maddr and multicast usage */
311       if (maddr != NULL)
312         host = maddr->gvalue;
313       /* we should check if this is a multicast address and use
314          set the "ttl" in this case. (this must be done in the
315          UDP message (not at the SIP layer) */
316       else if (received != NULL)
317         host = received->gvalue;
318       else
319         host = via->host;
320
321       if (rport == NULL || rport->gvalue == NULL)
322         {
323           if (via->port != NULL)
324             port = osip_atoi (via->port);
325           else
326             port = 5060;
327         }
328       else
329         port = osip_atoi (rport->gvalue);
330
331       i = osip->cb_send_message (ist, ist->last_response, host,
332                                  port, ist->out_socket);
333     }
334   else
335     i = -1;
336   if (i != 0)
337     {
338       ist_handle_transport_error (ist, i);
339       return;
340     }
341   __osip_message_callback (OSIP_IST_STATUS_3456XX_SENT_AGAIN, ist,
342                            ist->last_response);
343 }
344
345 void
346 osip_ist_timeout_h_event (osip_transaction_t * ist, osip_event_t * evt)
347 {
348   ist->ist_context->timer_h_length = -1;
349   ist->ist_context->timer_h_start.tv_sec = -1;
350
351   __osip_transaction_set_state (ist, IST_TERMINATED);
352   __osip_kill_transaction_callback (OSIP_IST_KILL_TRANSACTION, ist);
353 }
354
355 void
356 osip_ist_timeout_i_event (osip_transaction_t * ist, osip_event_t * evt)
357 {
358   ist->ist_context->timer_i_length = -1;
359   ist->ist_context->timer_i_start.tv_sec = -1;
360
361   __osip_transaction_set_state (ist, IST_TERMINATED);
362   __osip_kill_transaction_callback (OSIP_IST_KILL_TRANSACTION, ist);
363 }
364
365 void
366 ist_snd_1xx (osip_transaction_t * ist, osip_event_t * evt)
367 {
368   int i;
369   osip_via_t *via;
370   osip_t *osip = (osip_t *) ist->config;
371
372   if (ist->last_response != NULL)
373     {
374       osip_message_free (ist->last_response);
375     }
376   ist->last_response = evt->sip;
377
378   via = (osip_via_t *) osip_list_get (ist->last_response->vias, 0);
379   if (via)
380     {
381       char *host;
382       int port;
383       osip_generic_param_t *maddr;
384       osip_generic_param_t *received;
385       osip_generic_param_t *rport;
386       osip_via_param_get_byname (via, "maddr", &maddr);
387       osip_via_param_get_byname (via, "received", &received);
388       osip_via_param_get_byname (via, "rport", &rport);
389       /* 1: user should not use the provided information
390          (host and port) if they are using a reliable
391          transport. Instead, they should use the already
392          open socket attached to this transaction. */
393       /* 2: check maddr and multicast usage */
394       if (maddr != NULL)
395         host = maddr->gvalue;
396       /* we should check if this is a multicast address and use
397          set the "ttl" in this case. (this must be done in the
398          UDP message (not at the SIP layer) */
399       else if (received != NULL)
400         host = received->gvalue;
401       else
402         host = via->host;
403
404       if (rport == NULL || rport->gvalue == NULL)
405         {
406           if (via->port != NULL)
407             port = osip_atoi (via->port);
408           else
409             port = 5060;
410         }
411       else
412         port = osip_atoi (rport->gvalue);
413
414       i = osip->cb_send_message (ist, ist->last_response, host,
415                                  port, ist->out_socket);
416     }
417   else
418     i = -1;
419   if (i != 0)
420     {
421       ist_handle_transport_error (ist, i);
422       return;
423     }
424   else
425     __osip_message_callback (OSIP_IST_STATUS_1XX_SENT, ist,
426                              ist->last_response);
427
428   /* we are already in the proper state */
429   return;
430 }
431
432 void
433 ist_snd_2xx (osip_transaction_t * ist, osip_event_t * evt)
434 {
435   int i;
436   osip_via_t *via;
437   osip_t *osip = (osip_t *) ist->config;
438
439   if (ist->last_response != NULL)
440     {
441       osip_message_free (ist->last_response);
442     }
443   ist->last_response = evt->sip;
444
445   via = (osip_via_t *) osip_list_get (ist->last_response->vias, 0);
446   if (via)
447     {
448       char *host;
449       int port;
450       osip_generic_param_t *maddr;
451       osip_generic_param_t *received;
452       osip_generic_param_t *rport;
453       osip_via_param_get_byname (via, "maddr", &maddr);
454       osip_via_param_get_byname (via, "received", &received);
455       osip_via_param_get_byname (via, "rport", &rport);
456       /* 1: user should not use the provided information
457          (host and port) if they are using a reliable
458          transport. Instead, they should use the already
459          open socket attached to this transaction. */
460       /* 2: check maddr and multicast usage */
461       if (maddr != NULL)
462         host = maddr->gvalue;
463       /* we should check if this is a multicast address and use
464          set the "ttl" in this case. (this must be done in the
465          UDP message (not at the SIP layer) */
466       else if (received != NULL)
467         host = received->gvalue;
468       else
469         host = via->host;
470
471       if (rport == NULL || rport->gvalue == NULL)
472         {
473           if (via->port != NULL)
474             port = osip_atoi (via->port);
475           else
476             port = 5060;
477         }
478       else
479         port = osip_atoi (rport->gvalue);
480       i = osip->cb_send_message (ist, ist->last_response, host,
481                                  port, ist->out_socket);
482     }
483   else
484     i = -1;
485   if (i != 0)
486     {
487       ist_handle_transport_error (ist, i);
488       return;
489     }
490   else
491     {
492       __osip_message_callback (OSIP_IST_STATUS_2XX_SENT, ist,
493                                ist->last_response);
494       __osip_transaction_set_state (ist, IST_TERMINATED);
495       __osip_kill_transaction_callback (OSIP_IST_KILL_TRANSACTION, ist);
496     }
497   return;
498 }
499
500 void
501 ist_snd_3456xx (osip_transaction_t * ist, osip_event_t * evt)
502 {
503   int i;
504   osip_via_t *via;
505   osip_t *osip = (osip_t *) ist->config;
506
507   if (ist->last_response != NULL)
508     {
509       osip_message_free (ist->last_response);
510     }
511   ist->last_response = evt->sip;
512
513   via = (osip_via_t *) osip_list_get (ist->last_response->vias, 0);
514   if (via)
515     {
516       char *host;
517       int port;
518       osip_generic_param_t *maddr;
519       osip_generic_param_t *received;
520       osip_generic_param_t *rport;
521       osip_via_param_get_byname (via, "maddr", &maddr);
522       osip_via_param_get_byname (via, "received", &received);
523       osip_via_param_get_byname (via, "rport", &rport);
524       /* 1: user should not use the provided information
525          (host and port) if they are using a reliable
526          transport. Instead, they should use the already
527          open socket attached to this transaction. */
528       /* 2: check maddr and multicast usage */
529       if (maddr != NULL)
530         host = maddr->gvalue;
531       /* we should check if this is a multicast address and use
532          set the "ttl" in this case. (this must be done in the
533          UDP message (not at the SIP layer) */
534       else if (received != NULL)
535         host = received->gvalue;
536       else
537         host = via->host;
538
539       if (rport == NULL || rport->gvalue == NULL)
540         {
541           if (via->port != NULL)
542             port = osip_atoi (via->port);
543           else
544             port = 5060;
545         }
546       else
547         port = osip_atoi (rport->gvalue);
548       i = osip->cb_send_message (ist, ist->last_response, host,
549                                  port, ist->out_socket);
550     }
551   else
552     i = -1;
553   if (i != 0)
554     {
555       ist_handle_transport_error (ist, i);
556       return;
557     }
558   else
559     {
560       if (MSG_IS_STATUS_3XX (ist->last_response))
561         __osip_message_callback (OSIP_IST_STATUS_3XX_SENT, ist,
562                                  ist->last_response);
563       else if (MSG_IS_STATUS_4XX (ist->last_response))
564         __osip_message_callback (OSIP_IST_STATUS_4XX_SENT, ist,
565                                  ist->last_response);
566       else if (MSG_IS_STATUS_5XX (ist->last_response))
567         __osip_message_callback (OSIP_IST_STATUS_5XX_SENT, ist,
568                                  ist->last_response);
569       else
570         __osip_message_callback (OSIP_IST_STATUS_6XX_SENT, ist,
571                                  ist->last_response);
572     }
573
574   gettimeofday (&ist->ist_context->timer_g_start, NULL);
575   add_gettimeofday (&ist->ist_context->timer_g_start,
576                     ist->ist_context->timer_g_length);
577   gettimeofday (&ist->ist_context->timer_h_start, NULL);
578   add_gettimeofday (&ist->ist_context->timer_h_start,
579                     ist->ist_context->timer_h_length);
580   __osip_transaction_set_state (ist, IST_COMPLETED);
581   return;
582 }
583
584 void
585 ist_rcv_ack (osip_transaction_t * ist, osip_event_t * evt)
586 {
587   if (ist->ack != NULL)
588     {
589       osip_message_free (ist->ack);
590     }
591
592   ist->ack = evt->sip;
593
594   if (ist->state == IST_COMPLETED)
595     __osip_message_callback (OSIP_IST_ACK_RECEIVED, ist, ist->ack);
596   else                          /* IST_CONFIRMED */
597     __osip_message_callback (OSIP_IST_ACK_RECEIVED_AGAIN, ist, ist->ack);
598   /* set the timer to 0 for reliable, and T4 for unreliable (already set) */
599   gettimeofday (&ist->ist_context->timer_i_start, NULL);
600   add_gettimeofday (&ist->ist_context->timer_i_start,
601                     ist->ist_context->timer_i_length);
602   __osip_transaction_set_state (ist, IST_CONFIRMED);
603 }