2 The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3 Copyright (C) 2001,2002,2003 Aymeric MOIZARD jack@atosc.org
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.
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.
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
20 #include <osip2/internal.h>
21 #include <osip2/osip.h>
25 osip_statemachine_t *ist_fsm;
36 transition_t *transition;
37 osip_statemachine_t *statemachine = __ist_get_fsm ();
39 while (!osip_list_eol (statemachine->transitions, 0))
42 (transition_t *) osip_list_get (statemachine->transitions, 0);
43 osip_list_remove (statemachine->transitions, 0);
44 osip_free (transition);
46 osip_free (statemachine->transitions);
47 osip_free (statemachine);
54 transition_t *transition;
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
130 ist_create_resp_100 (osip_transaction_t * ist, osip_message_t * request)
133 osip_message_t *resp_100;
135 i = osip_message_init (&resp_100);
139 /* follow instructions from 8.2.6 */
140 i = osip_from_clone (request->from, &(resp_100->from));
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! */
147 i = osip_call_id_clone (request->call_id, &(resp_100->call_id));
150 i = osip_cseq_clone (request->cseq, &(resp_100->cseq));
154 /* Via headers are copied from request */
158 osip_via_t *orig_via;
160 while (!osip_list_eol (ist->orig_request->vias, pos))
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);
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 */
177 osip_message_free (resp_100);
182 ist_handle_transport_error (osip_transaction_t * ist, int err)
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 */
191 ist_rcv_invite (osip_transaction_t * ist, osip_event_t * evt)
194 osip_t *osip = (osip_t *) ist->config;
196 if (ist->state == IST_PRE_PROCEEDING) /* announce new INVITE */
198 /* Here we have ist->orig_request == NULL */
199 ist->orig_request = evt->sip;
201 __osip_message_callback (OSIP_IST_INVITE_RECEIVED, ist, evt->sip);
203 else /* IST_PROCEEDING or IST_COMPLETED */
205 /* delete retransmission */
206 osip_message_free (evt->sip);
208 __osip_message_callback (OSIP_IST_INVITE_RECEIVED_AGAIN, ist,
210 if (ist->last_response != NULL) /* retransmit last response */
214 via = (osip_via_t *) osip_list_get (ist->last_response->vias, 0);
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 */
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;
240 if (rport == NULL || rport->gvalue == NULL)
242 if (via->port != NULL)
243 port = osip_atoi (via->port);
248 port = osip_atoi (rport->gvalue);
250 i = osip->cb_send_message (ist, ist->last_response, host,
251 port, ist->out_socket);
257 ist_handle_transport_error (ist, i);
262 if (MSG_IS_STATUS_1XX (ist->last_response))
263 __osip_message_callback (OSIP_IST_STATUS_1XX_SENT, ist,
265 else if (MSG_IS_STATUS_2XX (ist->last_response))
266 __osip_message_callback (OSIP_IST_STATUS_2XX_SENT_AGAIN, ist,
269 __osip_message_callback (OSIP_IST_STATUS_3456XX_SENT_AGAIN,
270 ist, ist->last_response);
276 /* we come here only if it was the first INVITE received */
277 __osip_transaction_set_state (ist, IST_PROCEEDING);
281 osip_ist_timeout_g_event (osip_transaction_t * ist, osip_event_t * evt)
284 osip_t *osip = (osip_t *) ist->config;
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);
294 /* retransmit RESPONSE */
295 via = (osip_via_t *) osip_list_get (ist->last_response->vias, 0);
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 */
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;
321 if (rport == NULL || rport->gvalue == NULL)
323 if (via->port != NULL)
324 port = osip_atoi (via->port);
329 port = osip_atoi (rport->gvalue);
331 i = osip->cb_send_message (ist, ist->last_response, host,
332 port, ist->out_socket);
338 ist_handle_transport_error (ist, i);
341 __osip_message_callback (OSIP_IST_STATUS_3456XX_SENT_AGAIN, ist,
346 osip_ist_timeout_h_event (osip_transaction_t * ist, osip_event_t * evt)
348 ist->ist_context->timer_h_length = -1;
349 ist->ist_context->timer_h_start.tv_sec = -1;
351 __osip_transaction_set_state (ist, IST_TERMINATED);
352 __osip_kill_transaction_callback (OSIP_IST_KILL_TRANSACTION, ist);
356 osip_ist_timeout_i_event (osip_transaction_t * ist, osip_event_t * evt)
358 ist->ist_context->timer_i_length = -1;
359 ist->ist_context->timer_i_start.tv_sec = -1;
361 __osip_transaction_set_state (ist, IST_TERMINATED);
362 __osip_kill_transaction_callback (OSIP_IST_KILL_TRANSACTION, ist);
366 ist_snd_1xx (osip_transaction_t * ist, osip_event_t * evt)
370 osip_t *osip = (osip_t *) ist->config;
372 if (ist->last_response != NULL)
374 osip_message_free (ist->last_response);
376 ist->last_response = evt->sip;
378 via = (osip_via_t *) osip_list_get (ist->last_response->vias, 0);
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 */
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;
404 if (rport == NULL || rport->gvalue == NULL)
406 if (via->port != NULL)
407 port = osip_atoi (via->port);
412 port = osip_atoi (rport->gvalue);
414 i = osip->cb_send_message (ist, ist->last_response, host,
415 port, ist->out_socket);
421 ist_handle_transport_error (ist, i);
425 __osip_message_callback (OSIP_IST_STATUS_1XX_SENT, ist,
428 /* we are already in the proper state */
433 ist_snd_2xx (osip_transaction_t * ist, osip_event_t * evt)
437 osip_t *osip = (osip_t *) ist->config;
439 if (ist->last_response != NULL)
441 osip_message_free (ist->last_response);
443 ist->last_response = evt->sip;
445 via = (osip_via_t *) osip_list_get (ist->last_response->vias, 0);
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 */
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;
471 if (rport == NULL || rport->gvalue == NULL)
473 if (via->port != NULL)
474 port = osip_atoi (via->port);
479 port = osip_atoi (rport->gvalue);
480 i = osip->cb_send_message (ist, ist->last_response, host,
481 port, ist->out_socket);
487 ist_handle_transport_error (ist, i);
492 __osip_message_callback (OSIP_IST_STATUS_2XX_SENT, ist,
494 __osip_transaction_set_state (ist, IST_TERMINATED);
495 __osip_kill_transaction_callback (OSIP_IST_KILL_TRANSACTION, ist);
501 ist_snd_3456xx (osip_transaction_t * ist, osip_event_t * evt)
505 osip_t *osip = (osip_t *) ist->config;
507 if (ist->last_response != NULL)
509 osip_message_free (ist->last_response);
511 ist->last_response = evt->sip;
513 via = (osip_via_t *) osip_list_get (ist->last_response->vias, 0);
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 */
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;
539 if (rport == NULL || rport->gvalue == NULL)
541 if (via->port != NULL)
542 port = osip_atoi (via->port);
547 port = osip_atoi (rport->gvalue);
548 i = osip->cb_send_message (ist, ist->last_response, host,
549 port, ist->out_socket);
555 ist_handle_transport_error (ist, i);
560 if (MSG_IS_STATUS_3XX (ist->last_response))
561 __osip_message_callback (OSIP_IST_STATUS_3XX_SENT, ist,
563 else if (MSG_IS_STATUS_4XX (ist->last_response))
564 __osip_message_callback (OSIP_IST_STATUS_4XX_SENT, ist,
566 else if (MSG_IS_STATUS_5XX (ist->last_response))
567 __osip_message_callback (OSIP_IST_STATUS_5XX_SENT, ist,
570 __osip_message_callback (OSIP_IST_STATUS_6XX_SENT, ist,
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);
585 ist_rcv_ack (osip_transaction_t * ist, osip_event_t * evt)
587 if (ist->ack != NULL)
589 osip_message_free (ist->ack);
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);