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>
26 static int __osip_transaction_set_topvia (osip_transaction_t * transaction,
28 static int __osip_transaction_set_from (osip_transaction_t * transaction,
30 static int __osip_transaction_set_to (osip_transaction_t * transaction,
32 static int __osip_transaction_set_call_id (osip_transaction_t * transaction,
33 osip_call_id_t * call_id);
34 static int __osip_transaction_set_cseq (osip_transaction_t * transaction,
38 __osip_transaction_set_topvia (osip_transaction_t * transaction,
43 if (transaction == NULL)
45 i = osip_via_clone (topvia, &(transaction->topvia));
48 transaction->topvia = NULL;
53 __osip_transaction_set_from (osip_transaction_t * transaction,
58 if (transaction == NULL)
60 i = osip_from_clone (from, &(transaction->from));
63 transaction->from = NULL;
68 __osip_transaction_set_to (osip_transaction_t * transaction, osip_to_t * to)
72 if (transaction == NULL)
74 i = osip_to_clone (to, &(transaction->to));
77 transaction->to = NULL;
82 __osip_transaction_set_call_id (osip_transaction_t * transaction,
83 osip_call_id_t * call_id)
87 if (transaction == NULL)
89 i = osip_call_id_clone (call_id, &(transaction->callid));
92 transaction->callid = NULL;
97 __osip_transaction_set_cseq (osip_transaction_t * transaction,
102 if (transaction == NULL)
104 i = osip_cseq_clone (cseq, &(transaction->cseq));
107 transaction->cseq = NULL;
112 osip_transaction_init (osip_transaction_t ** transaction,
113 osip_fsm_type_t ctx_type, osip_t * osip,
114 osip_message_t * request)
116 static int transactionid = 1;
122 if (request==NULL) return -1;
123 if (request->call_id==NULL) return -1;
124 if (request->call_id->number==NULL) return -1;
126 OSIP_TRACE (osip_trace
127 (__FILE__, __LINE__, OSIP_INFO2, NULL,
128 "allocating transaction ressource %i %s\n", transactionid,
129 request->call_id->number));
132 (osip_transaction_t *) osip_malloc (sizeof (osip_transaction_t));
133 if (*transaction == NULL)
138 memset (*transaction, 0, sizeof (osip_transaction_t));
140 (*transaction)->birth_time = now;
141 (*transaction)->transactionid = transactionid;
144 topvia = osip_list_get (request->vias, 0);
148 i = __osip_transaction_set_topvia (*transaction, topvia);
152 /* In some situation, some of those informtions might
153 be useless. Mostly, I prefer to keep them in all case
154 for backward compatibility. */
155 i = __osip_transaction_set_from (*transaction, request->from);
158 i = __osip_transaction_set_to (*transaction, request->to);
161 i = __osip_transaction_set_call_id (*transaction, request->call_id);
164 i = __osip_transaction_set_cseq (*transaction, request->cseq);
167 /* RACE conditions can happen for server transactions */
168 /* (*transaction)->orig_request = request; */
169 (*transaction)->orig_request = NULL;
171 (*transaction)->config = osip;
173 (*transaction)->transactionff =
174 (osip_fifo_t *) osip_malloc (sizeof (osip_fifo_t));
175 if ((*transaction)->transactionff == NULL)
177 osip_fifo_init ((*transaction)->transactionff);
179 (*transaction)->ctx_type = ctx_type;
180 (*transaction)->ict_context = NULL;
181 (*transaction)->ist_context = NULL;
182 (*transaction)->nict_context = NULL;
183 (*transaction)->nist_context = NULL;
186 (*transaction)->state = ICT_PRE_CALLING;
187 i = __osip_ict_init (&((*transaction)->ict_context), osip, request);
190 __osip_add_ict (osip, *transaction);
192 else if (ctx_type == IST)
194 (*transaction)->state = IST_PRE_PROCEEDING;
195 i = __osip_ist_init (&((*transaction)->ist_context), osip, request);
198 __osip_add_ist (osip, *transaction);
200 else if (ctx_type == NICT)
202 (*transaction)->state = NICT_PRE_TRYING;
203 i = __osip_nict_init (&((*transaction)->nict_context), osip, request);
206 __osip_add_nict (osip, *transaction);
210 (*transaction)->state = NIST_PRE_TRYING;
211 i = __osip_nist_init (&((*transaction)->nist_context), osip, request);
214 __osip_add_nist (osip, *transaction);
220 osip_fifo_free ((*transaction)->transactionff);
222 osip_cseq_free ((*transaction)->cseq);
224 osip_call_id_free ((*transaction)->callid);
226 osip_to_free ((*transaction)->to);
228 osip_from_free ((*transaction)->from);
230 osip_via_free ((*transaction)->topvia);
232 osip_free (*transaction);
236 /* This method automaticly remove the transaction context from
237 the osip stack. This task is required for proper operation
238 when a transaction goes in the TERMINATED STATE.
239 However the user might want to just take the context out of
240 the SIP stack andf keep it for future use without freeing
241 all ressource.... This way the transaction context can be
242 kept without being used by the oSIP stack.
244 new methods that replace this one:
245 osip_remove_transaction
247 osip_transaction_free2();
251 osip_transaction_free (osip_transaction_t * transaction)
255 if (transaction == NULL)
257 i = osip_remove_transaction (transaction->config, transaction);
259 if (i != 0) /* yet removed ??? */
261 OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_BUG, NULL,
262 "transaction already removed from list %i!\n",
263 transaction->transactionid));
266 return osip_transaction_free2 (transaction);
269 /* same as osip_transaction_free() but assume the transaction is
270 already removed from the list of transaction in the osip stack */
272 osip_transaction_free2 (osip_transaction_t * transaction)
276 if (transaction == NULL)
278 if (transaction->orig_request != NULL
279 &&transaction->orig_request->call_id!=NULL
280 &&transaction->orig_request->call_id->number!=NULL)
282 OSIP_TRACE (osip_trace
283 (__FILE__, __LINE__, OSIP_INFO2, NULL,
284 "free transaction ressource %i %s\n",
285 transaction->transactionid,
286 transaction->orig_request->call_id->number));
288 if (transaction->ctx_type == ICT)
290 __osip_ict_free (transaction->ict_context);
292 else if (transaction->ctx_type == IST)
294 __osip_ist_free (transaction->ist_context);
296 else if (transaction->ctx_type == NICT)
298 __osip_nict_free (transaction->nict_context);
302 __osip_nist_free (transaction->nist_context);
306 evt = osip_fifo_tryget (transaction->transactionff);
309 osip_message_free (evt->sip);
311 evt = osip_fifo_tryget (transaction->transactionff);
313 osip_fifo_free (transaction->transactionff);
315 osip_message_free (transaction->orig_request);
316 osip_message_free (transaction->last_response);
317 osip_message_free (transaction->ack);
319 osip_via_free (transaction->topvia);
320 osip_from_free (transaction->from);
321 osip_to_free (transaction->to);
322 osip_call_id_free (transaction->callid);
323 osip_cseq_free (transaction->cseq);
325 osip_free (transaction);
330 osip_transaction_add_event (osip_transaction_t * transaction,
335 if (transaction == NULL)
337 evt->transactionid = transaction->transactionid;
338 osip_fifo_add (transaction->transactionff, evt);
343 osip_transaction_execute (osip_transaction_t * transaction,
346 osip_statemachine_t *statemachine;
348 /* to kill the process, simply send this type of event. */
349 if (EVT_IS_KILL_TRANSACTION (evt))
352 TRANSACTION MUST NOW BE RELEASED BY END-USER:
353 So Any usefull data can be save and re-used */
354 /* osip_transaction_free(transaction);
355 osip_free(transaction); */
360 OSIP_TRACE (osip_trace
361 (__FILE__, __LINE__, OSIP_INFO4, NULL,
362 "sipevent tr->transactionid: %i\n",
363 transaction->transactionid));
364 OSIP_TRACE (osip_trace
365 (__FILE__, __LINE__, OSIP_INFO4, NULL,
366 "sipevent tr->state: %i\n", transaction->state));
367 OSIP_TRACE (osip_trace
368 (__FILE__, __LINE__, OSIP_INFO4, NULL,
369 "sipevent evt->type: %i\n", evt->type));
370 OSIP_TRACE (osip_trace
371 (__FILE__, __LINE__, OSIP_INFO4, NULL,
372 "sipevent evt->sip: %x\n", evt->sip));
374 if (transaction->ctx_type == ICT)
375 statemachine = __ict_get_fsm ();
376 else if (transaction->ctx_type == IST)
377 statemachine = __ist_get_fsm ();
378 else if (transaction->ctx_type == NICT)
379 statemachine = __nict_get_fsm ();
381 statemachine = __nist_get_fsm ();
384 if (-1 == fsm_callmethod (evt->type,
385 transaction->state, statemachine, evt,
388 OSIP_TRACE (osip_trace
389 (__FILE__, __LINE__, OSIP_INFO3, NULL, "USELESS event!\n"));
390 /* message is useless. */
391 if (EVT_IS_MSG (evt))
393 if (evt->sip != NULL)
395 osip_message_free (evt->sip);
401 OSIP_TRACE (osip_trace
402 (__FILE__, __LINE__, OSIP_INFO4, NULL,
403 "sipevent evt: method called!\n"));
405 osip_free (evt); /* this is the ONLY place for freeing event!! */
410 osip_transaction_get_destination (osip_transaction_t * transaction, char **ip,
415 if (transaction == NULL)
417 if (transaction->ict_context != NULL)
419 *ip = transaction->ict_context->destination;
420 *port = transaction->ict_context->port;
423 else if (transaction->nict_context != NULL)
425 *ip = transaction->nict_context->destination;
426 *port = transaction->nict_context->port;
433 osip_transaction_set_your_instance (osip_transaction_t * transaction,
436 if (transaction == NULL)
438 transaction->your_instance = instance;
443 osip_transaction_get_your_instance (osip_transaction_t * transaction)
445 if (transaction == NULL)
447 return transaction->your_instance;
451 __osip_transaction_set_state (osip_transaction_t * transaction, state_t state)
453 if (transaction == NULL)
455 transaction->state = state;
460 osip_transaction_set_in_socket (osip_transaction_t * transaction, int sock)
462 if (transaction == NULL)
464 transaction->in_socket = sock;
469 osip_transaction_set_out_socket (osip_transaction_t * transaction, int sock)
471 if (transaction == NULL)
473 transaction->out_socket = sock;
478 __osip_transaction_matching_response_osip_to_xict_17_1_3 (osip_transaction_t *
483 osip_generic_param_t *b_request;
484 osip_generic_param_t *b_response;
485 osip_via_t *topvia_response;
487 /* some checks to avoid crashing on bad requests */
488 if (tr == NULL || (tr->ict_context == NULL && tr->nict_context == NULL) ||
489 /* only ict and nict can match a response */
490 response == NULL || response->cseq == NULL
491 || response->cseq->method == NULL)
494 topvia_response = osip_list_get (response->vias, 0);
495 if (topvia_response == NULL)
497 OSIP_TRACE (osip_trace
498 (__FILE__, __LINE__, OSIP_ERROR, NULL,
499 "Remote UA is not compliant: missing a Via header!\n"));
502 osip_via_param_get_byname (tr->topvia, "branch", &b_request);
503 if (b_request == NULL)
505 OSIP_TRACE (osip_trace
506 (__FILE__, __LINE__, OSIP_BUG, NULL,
507 "You created a transaction without any branch! THIS IS NOT ALLOWED\n"));
510 osip_via_param_get_byname (topvia_response, "branch", &b_response);
511 if (b_response == NULL)
514 /* the from tag (unique) */
515 if (from_tag_match (tr->from, response->from) != 0)
518 if (cseq_match (tr->cseq, response->cseq) != 0)
521 if (response->to->url->username == NULL
522 && tr->from->url->username != NULL)
524 if (response->to->url->username != NULL
525 && tr->from->url->username == NULL)
527 if (response->to->url->username != NULL
528 && tr->from->url->username != NULL)
530 if (strcmp (response->to->url->host, tr->from->url->host) ||
531 strcmp (response->to->url->username, tr->from->url->username))
536 if (strcmp (response->to->url->host, tr->from->url->host))
540 /* the Call-ID field */
541 if (call_id_match (tr->callid, response->call_id) != 0)
545 OSIP_TRACE (osip_trace
546 (__FILE__, __LINE__, OSIP_BUG, NULL,
547 "Remote UA is not compliant: missing a branch parameter in Via header!\n"));
553 A response matches a client transaction under two
556 1. If the response has the same value of the branch parameter
557 in the top Via header field as the branch parameter in the
558 top Via header field of the request that created the
561 if (0 != strcmp (b_request->gvalue, b_response->gvalue))
564 2. If the method parameter in the CSeq header field matches
565 the method of the request that created the transaction. The
566 method is needed since a CANCEL request constitutes a
567 different transaction, but shares the same value of the
569 AMD NOTE: cseq->method is ALWAYS the same than the METHOD of the request.
571 if (0 == strcmp (response->cseq->method, tr->cseq->method)) /* general case */
577 __osip_transaction_matching_request_osip_to_xist_17_2_3 (osip_transaction_t *
582 osip_generic_param_t *b_origrequest;
583 osip_generic_param_t *b_request;
584 osip_via_t *topvia_request;
588 /* some checks to avoid crashing on bad requests */
589 if (tr == NULL || (tr->ist_context == NULL && tr->nist_context == NULL) ||
590 /* only ist and nist can match a request */
591 request == NULL || request->cseq == NULL
592 || request->cseq->method == NULL)
595 topvia_request = osip_list_get (request->vias, 0);
596 if (topvia_request == NULL)
598 OSIP_TRACE (osip_trace
599 (__FILE__, __LINE__, OSIP_ERROR, NULL,
600 "Remote UA is not compliant: missing a Via header!\n"));
603 osip_via_param_get_byname (topvia_request, "branch", &b_request);
604 osip_via_param_get_byname (tr->topvia, "branch", &b_origrequest);
606 if ((b_origrequest == NULL && b_request != NULL) ||
607 (b_origrequest != NULL && b_request == NULL))
608 return -1; /* one request is compliant, the other one is not... */
610 /* Section 17.2.3 Matching Requests to Server Transactions:
611 "The branch parameter in the topmost Via header field of the request
612 is examined. If it is present and begins with the magic cookie
613 "z9hG4bK", the request was generated by a client transaction
614 compliant to this specification."
617 if (b_origrequest != NULL && b_request != NULL)
618 /* case where both request contains a branch */
620 length_br = strlen (b_origrequest->gvalue);
621 length_br2 = strlen (b_request->gvalue);
622 if (length_br != length_br2)
623 return -1; /* can't be the same */
624 if (0 == strncmp (b_origrequest->gvalue, "z9hG4bK", 7)
625 && 0 == strncmp (b_request->gvalue, "z9hG4bK", 7))
627 /* both request comes from a compliant UA */
628 /* The request matches a transaction if the branch parameter
629 in the request is equal to the one in the top Via header
630 field of the request that created the transaction, the
631 sent-by value in the top Via of the request is equal to
632 the one in the request that created the transaction, and in
633 the case of a CANCEL request, the method of the request
634 that created the transaction was also CANCEL.
636 if (0 != strcmp (b_origrequest->gvalue, b_request->gvalue))
637 return -1; /* branch param does not match */
639 /* check the sent-by values */
640 char *b_port = via_get_port (topvia_request);
641 char *b_origport = via_get_port (tr->topvia);
642 char *b_host = via_get_host (topvia_request);
643 char *b_orighost = via_get_host (tr->topvia);
644 if ((b_host == NULL || b_orighost == NULL))
646 if (0 != strcmp (b_orighost, b_host))
649 if (b_port != NULL && b_origport == NULL
650 && 0 != strcmp (b_port, "5060"))
652 else if (b_origport != NULL && b_port == NULL
653 && 0 != strcmp (b_origport, "5060"))
655 else if (b_origport != NULL && b_port != NULL
656 && 0 != strcmp (b_origport, b_port))
660 /* audiocodes bug (MP108-fxs-SIP-4-0-282-380) */
661 if (0 != osip_from_tag_match (tr->from, request->from))
664 if ( /* MSG_IS_CANCEL(request)&& <<-- BUG from the spec?
665 I always check the CSeq */
666 (!(0 == strcmp (tr->cseq->method, "INVITE") &&
667 0 == strcmp (request->cseq->method, "ACK")))
668 && 0 != strcmp (tr->cseq->method, request->cseq->method))
674 /* Back to the old backward compatibilty mechanism for matching requests */
675 if (0 != osip_call_id_match (tr->callid, request->call_id))
677 if (MSG_IS_ACK (request))
679 osip_generic_param_t *tag_from1;
680 osip_generic_param_t *tag_from2;
682 osip_from_param_get_byname (tr->to, "tag", &tag_from1);
683 osip_from_param_get_byname (request->to, "tag", &tag_from2);
684 if (tag_from1 == NULL && tag_from2 != NULL)
685 { /* do not check it as it can be a new tag when the final
686 answer has a tag while an INVITE doesn't have one */
688 else if (tag_from1 != NULL && tag_from2 == NULL)
694 if (0 != osip_to_tag_match (tr->to, request->to))
700 if (0 != osip_to_tag_match (tr->to, request->to))
703 if (0 != osip_from_tag_match (tr->from, request->from))
705 if (0 != osip_cseq_match (tr->cseq, request->cseq))
707 if (0 != osip_via_match (tr->topvia, topvia_request))
715 callleg_match (osip_to_t * to1, osip_from_t * from1, osip_to_t * to2,
718 if (to1 == NULL || to2 == NULL)
720 if (from1 == NULL || from2 == NULL)
723 if (0 == osip_from_compare ((osip_from_t *) to1, (osip_from_t *) to2)
724 && 0 == osip_from_compare (from1, from2))