+++ /dev/null
-/*
- The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
- Copyright (C) 2001,2002,2003 Aymeric MOIZARD jack@atosc.org
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-#include <osip2/internal.h>
-#include <osip2/osip.h>
-
-#include "fsm.h"
-#include "xixt.h"
-
-#ifdef OSIP_MT
-static struct osip_mutex *ict_fastmutex;
-static struct osip_mutex *ist_fastmutex;
-static struct osip_mutex *nict_fastmutex;
-static struct osip_mutex *nist_fastmutex;
-#endif
-
-#ifdef OSIP_RETRANSMIT_2XX
-
-#include <osip2/osip_dialog.h>
-#ifdef OSIP_MT
-static struct osip_mutex *ixt_fastmutex;
-#endif
-
-#endif
-
-static int __osip_global_init (void);
-static void __osip_global_free (void);
-static int increase_ref_count (void);
-static void decrease_ref_count (void);
-
-static int
-__osip_global_init ()
-{
- /* load the fsm configuration */
- __ict_load_fsm ();
- __ist_load_fsm ();
- __nict_load_fsm ();
- __nist_load_fsm ();
-
- /* load the parser configuration */
- parser_init ();
-
-#ifdef OSIP_MT
- ict_fastmutex = osip_mutex_init ();
- ist_fastmutex = osip_mutex_init ();
- nict_fastmutex = osip_mutex_init ();
- nist_fastmutex = osip_mutex_init ();
-
-#ifdef OSIP_RETRANSMIT_2XX
- ixt_fastmutex = osip_mutex_init ();
-#endif
-
-#endif
- return 0;
-}
-
-static void
-__osip_global_free ()
-{
- __ict_unload_fsm ();
- __ist_unload_fsm ();
- __nict_unload_fsm ();
- __nist_unload_fsm ();
-
-#ifdef OSIP_MT
- osip_mutex_destroy (ict_fastmutex);
- osip_mutex_destroy (ist_fastmutex);
- osip_mutex_destroy (nict_fastmutex);
- osip_mutex_destroy (nist_fastmutex);
-
-#ifdef OSIP_RETRANSMIT_2XX
- osip_mutex_destroy (ixt_fastmutex);
-#endif
-#endif
-}
-
-#ifdef OSIP_RETRANSMIT_2XX
-
-int
-osip_ixt_lock (osip_t * osip)
-{
-#ifdef OSIP_MT
- return osip_mutex_lock (ixt_fastmutex);
-#else
- return 0;
-#endif
-}
-
-int
-osip_ixt_unlock (osip_t * osip)
-{
-#ifdef OSIP_MT
- return osip_mutex_unlock (ixt_fastmutex);
-#else
- return 0;
-#endif
-}
-
-/* these are for transactions that would need retransmission not handled by state machines */
-void
-osip_add_ixt (osip_t * osip, ixt_t * ixt)
-{
- /* ajout dans la liste de osip_t->ixt */
- osip_ixt_lock (osip);
- osip_list_add (osip->ixt_retransmissions, (void *) ixt, 0);
- osip_ixt_unlock (osip);
-}
-
-void
-osip_remove_ixt (osip_t * osip, ixt_t * ixt)
-{
- int i;
- int found = 0;
- ixt_t *tmp;
- /* ajout dans la liste de osip_t->ixt */
- osip_ixt_lock (osip);
- for (i = 0; !osip_list_eol (osip->ixt_retransmissions, i); i++)
- {
- tmp = (ixt_t *) osip_list_get (osip->ixt_retransmissions, i);
- if (tmp == ixt)
- {
- osip_list_remove (osip->ixt_retransmissions, i);
- found = 1;
- break;
- }
- }
- osip_ixt_unlock (osip);
-}
-
-
-void
-response_get_destination (osip_message_t * response, char **address,
- int *portnum)
-{
- osip_via_t *via;
- char *host = NULL;
- int port = 0;
-
- via = (osip_via_t *) osip_list_get (response->vias, 0);
- if (via)
- {
- osip_generic_param_t *maddr;
- osip_generic_param_t *received;
- osip_generic_param_t *rport;
- osip_via_param_get_byname (via, "maddr", &maddr);
- osip_via_param_get_byname (via, "received", &received);
- osip_via_param_get_byname (via, "rport", &rport);
- /* 1: user should not use the provided information
- (host and port) if they are using a reliable
- transport. Instead, they should use the already
- open socket attached to this transaction. */
- /* 2: check maddr and multicast usage */
- if (maddr != NULL)
- host = maddr->gvalue;
- /* we should check if this is a multicast address and use
- set the "ttl" in this case. (this must be done in the
- UDP message (not at the SIP layer) */
- else if (received != NULL)
- host = received->gvalue;
- else
- host = via->host;
-
- if (rport == NULL || rport->gvalue == NULL)
- {
- if (via->port != NULL)
- port = osip_atoi (via->port);
- else
- port = 5060;
- }
- else
- port = osip_atoi (rport->gvalue);
- }
- *portnum = port;
- if (host != NULL)
- *address = osip_strdup (host);
- else
- *address = NULL;
-}
-
-
-int
-ixt_init (ixt_t ** ixt)
-{
- ixt_t *pixt;
- *ixt = pixt = (ixt_t *) osip_malloc (sizeof (ixt_t));
- if (pixt==NULL) return -1;
- pixt->dialog = NULL;
- pixt->msg2xx = NULL;
- pixt->ack = NULL;
- pixt->start = time (NULL);
- pixt->interval = 500;
- pixt->counter = 7;
- pixt->dest = NULL;
- pixt->port = 5060;
- pixt->sock = -1;
- return 0;
-}
-
-void
-ixt_free (ixt_t * ixt)
-{
- osip_message_free (ixt->ack);
- osip_message_free (ixt->msg2xx);
- osip_free (ixt->dest);
- osip_free (ixt);
-}
-
-/* usefull for UAs */
-void
-osip_start_200ok_retransmissions (osip_t * osip, osip_dialog_t * dialog,
- osip_message_t * msg200ok, int sock)
-{
- ixt_t *ixt;
- ixt_init (&ixt);
- ixt->dialog = dialog;
- osip_message_clone (msg200ok, &ixt->msg2xx);
- ixt->sock = sock;
- response_get_destination (msg200ok, &ixt->dest, &ixt->port);
- osip_add_ixt (osip, ixt);
-}
-
-void
-osip_start_ack_retransmissions (osip_t * osip, osip_dialog_t * dialog,
- osip_message_t * ack, char *dest, int port,
- int sock)
-{
- int i;
- ixt_t *ixt;
- i = ixt_init (&ixt);
- if (i != 0)
- return;
- ixt->dialog = dialog;
- osip_message_clone (ack, &ixt->ack);
- ixt->dest = osip_strdup (dest);
- ixt->port = port;
- ixt->sock = sock;
- osip_add_ixt (osip, ixt);
-}
-
-/* we stop the 200ok when receiving the corresponding ack */
-void
-osip_stop_200ok_retransmissions (osip_t * osip, osip_message_t * ack)
-{
- int i;
- ixt_t *ixt;
- osip_ixt_lock (osip);
- for (i = 0; !osip_list_eol (osip->ixt_retransmissions, i); i++)
- {
- ixt = (ixt_t *) osip_list_get (osip->ixt_retransmissions, i);
- if (osip_dialog_match_as_uas (ixt->dialog, ack) == 0)
- {
- osip_list_remove (osip->ixt_retransmissions, i);
- ixt_free (ixt);
- break;
- }
- }
- osip_ixt_unlock (osip);
-}
-
-/* when a dialog is destroyed by the application,
- it is safer to remove all ixt that are related to it */
-void
-osip_stop_retransmissions_from_dialog (osip_t * osip, osip_dialog_t * dialog)
-{
- int i;
- ixt_t *ixt;
- osip_ixt_lock (osip);
- for (i = 0; !osip_list_eol (osip->ixt_retransmissions, i); i++)
- {
- ixt = (ixt_t *) osip_list_get (osip->ixt_retransmissions, i);
- if (ixt->dialog == dialog)
- {
- osip_list_remove (osip->ixt_retransmissions, i);
- ixt_free (ixt);
- i--;
- }
- }
- osip_ixt_unlock (osip);
-}
-
-void
-ixt_retransmit (osip_t * osip, ixt_t * ixt, time_t current)
-{
- if ((current - ixt->start) * 1000 > ixt->interval)
- {
- ixt->interval = ixt->interval * 2;
- ixt->start = current;
- if (ixt->ack != NULL)
- osip->cb_send_message (NULL, ixt->ack,
- ixt->dest, ixt->port, ixt->sock);
- else if (ixt->msg2xx != NULL)
- osip->cb_send_message (NULL, ixt->msg2xx,
- ixt->dest, ixt->port, ixt->sock);
- ixt->counter--;
- }
-}
-
-void
-osip_retransmissions_execute (osip_t * osip)
-{
- int i;
- time_t current;
- ixt_t *ixt;
- current = time (NULL);
- osip_ixt_lock (osip);
- for (i = 0; !osip_list_eol (osip->ixt_retransmissions, i); i++)
- {
- ixt = (ixt_t *) osip_list_get (osip->ixt_retransmissions, i);
- ixt_retransmit (osip, ixt, current);
- if (ixt->counter == 0)
- {
- /* remove it */
- osip_list_remove (osip->ixt_retransmissions, i);
- ixt_free (ixt);
- i--;
- }
- }
- osip_ixt_unlock (osip);
-}
-
-#endif
-
-int
-osip_ict_lock (osip_t * osip)
-{
-#ifdef OSIP_MT
- return osip_mutex_lock (ict_fastmutex);
-#else
- return 0;
-#endif
-}
-
-int
-osip_ict_unlock (osip_t * osip)
-{
-#ifdef OSIP_MT
- return osip_mutex_unlock (ict_fastmutex);
-#else
- return 0;
-#endif
-}
-
-int
-osip_ist_lock (osip_t * osip)
-{
-#ifdef OSIP_MT
- return osip_mutex_lock (ist_fastmutex);
-#else
- return 0;
-#endif
-}
-
-int
-osip_ist_unlock (osip_t * osip)
-{
-#ifdef OSIP_MT
- return osip_mutex_unlock (ist_fastmutex);
-#else
- return 0;
-#endif
-}
-
-int
-osip_nict_lock (osip_t * osip)
-{
-#ifdef OSIP_MT
- return osip_mutex_lock (nict_fastmutex);
-#else
- return 0;
-#endif
-}
-
-int
-osip_nict_unlock (osip_t * osip)
-{
-#ifdef OSIP_MT
- return osip_mutex_unlock (nict_fastmutex);
-#else
- return 0;
-#endif
-}
-
-int
-osip_nist_lock (osip_t * osip)
-{
-#ifdef OSIP_MT
- return osip_mutex_lock (nist_fastmutex);
-#else
- return 0;
-#endif
-}
-
-int
-osip_nist_unlock (osip_t * osip)
-{
-#ifdef OSIP_MT
- return osip_mutex_unlock (nist_fastmutex);
-#else
- return 0;
-#endif
-}
-
-int
-__osip_add_ict (osip_t * osip, osip_transaction_t * ict)
-{
-#ifdef OSIP_MT
- osip_mutex_lock (ict_fastmutex);
-#endif
- osip_list_add (osip->osip_ict_transactions, ict, -1);
-#ifdef OSIP_MT
- osip_mutex_unlock (ict_fastmutex);
-#endif
- return 0;
-}
-
-int
-__osip_add_ist (osip_t * osip, osip_transaction_t * ist)
-{
-#ifdef OSIP_MT
- osip_mutex_lock (ist_fastmutex);
-#endif
- osip_list_add (osip->osip_ist_transactions, ist, -1);
-#ifdef OSIP_MT
- osip_mutex_unlock (ist_fastmutex);
-#endif
- return 0;
-}
-
-int
-__osip_add_nict (osip_t * osip, osip_transaction_t * nict)
-{
-#ifdef OSIP_MT
- osip_mutex_lock (nict_fastmutex);
-#endif
- osip_list_add (osip->osip_nict_transactions, nict, -1);
-#ifdef OSIP_MT
- osip_mutex_unlock (nict_fastmutex);
-#endif
- return 0;
-}
-
-int
-__osip_add_nist (osip_t * osip, osip_transaction_t * nist)
-{
-#ifdef OSIP_MT
- osip_mutex_lock (nist_fastmutex);
-#endif
- osip_list_add (osip->osip_nist_transactions, nist, -1);
-#ifdef OSIP_MT
- osip_mutex_unlock (nist_fastmutex);
-#endif
- return 0;
-}
-
-int
-osip_remove_transaction (osip_t * osip, osip_transaction_t * tr)
-{
- int i = -1;
- if (tr == NULL)
- return -1;
- if (tr->ctx_type == ICT)
- i = __osip_remove_ict_transaction (osip, tr);
- else if (tr->ctx_type == IST)
- i = __osip_remove_ist_transaction (osip, tr);
- else if (tr->ctx_type == NICT)
- i = __osip_remove_nict_transaction (osip, tr);
- else if (tr->ctx_type == NIST)
- i = __osip_remove_nist_transaction (osip, tr);
- else
- return -1;
- return i;
-}
-
-int
-__osip_remove_ict_transaction (osip_t * osip, osip_transaction_t * ict)
-{
- int pos = 0;
- osip_transaction_t *tmp;
-
-#ifdef OSIP_MT
- osip_mutex_lock (ict_fastmutex);
-#endif
- while (!osip_list_eol (osip->osip_ict_transactions, pos))
- {
- tmp = osip_list_get (osip->osip_ict_transactions, pos);
- if (tmp->transactionid == ict->transactionid)
- {
- osip_list_remove (osip->osip_ict_transactions, pos);
-#ifdef OSIP_MT
- osip_mutex_unlock (ict_fastmutex);
-#endif
- return 0;
- }
- pos++;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (ict_fastmutex);
-#endif
- return -1;
-}
-
-int
-__osip_remove_ist_transaction (osip_t * osip, osip_transaction_t * ist)
-{
- int pos = 0;
- osip_transaction_t *tmp;
-
-#ifdef OSIP_MT
- osip_mutex_lock (ist_fastmutex);
-#endif
- while (!osip_list_eol (osip->osip_ist_transactions, pos))
- {
- tmp = osip_list_get (osip->osip_ist_transactions, pos);
- if (tmp->transactionid == ist->transactionid)
- {
- osip_list_remove (osip->osip_ist_transactions, pos);
-#ifdef OSIP_MT
- osip_mutex_unlock (ist_fastmutex);
-#endif
- return 0;
- }
- pos++;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (ist_fastmutex);
-#endif
- return -1;
-}
-
-int
-__osip_remove_nict_transaction (osip_t * osip, osip_transaction_t * nict)
-{
- int pos = 0;
- osip_transaction_t *tmp;
-
-#ifdef OSIP_MT
- osip_mutex_lock (nict_fastmutex);
-#endif
- while (!osip_list_eol (osip->osip_nict_transactions, pos))
- {
- tmp = osip_list_get (osip->osip_nict_transactions, pos);
- if (tmp->transactionid == nict->transactionid)
- {
- osip_list_remove (osip->osip_nict_transactions, pos);
-#ifdef OSIP_MT
- osip_mutex_unlock (nict_fastmutex);
-#endif
- return 0;
- }
- pos++;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (nict_fastmutex);
-#endif
- return -1;
-}
-
-int
-__osip_remove_nist_transaction (osip_t * osip, osip_transaction_t * nist)
-{
- int pos = 0;
- osip_transaction_t *tmp;
-
-#ifdef OSIP_MT
- osip_mutex_lock (nist_fastmutex);
-#endif
- while (!osip_list_eol (osip->osip_nist_transactions, pos))
- {
- tmp = osip_list_get (osip->osip_nist_transactions, pos);
- if (tmp->transactionid == nist->transactionid)
- {
- osip_list_remove (osip->osip_nist_transactions, pos);
-#ifdef OSIP_MT
- osip_mutex_unlock (nist_fastmutex);
-#endif
- return 0;
- }
- pos++;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (nist_fastmutex);
-#endif
- return -1;
-}
-
-#if 0
-/* this method is made obsolete because it contains bugs and is also
- too much limited.
- any call to this method should be replace this way:
-
- //osip_distribute(osip, evt);
- osip_transaction_t *transaction = osip_find_transaction_and_add_event(osip, evt);
-
- if (i!=0) // in case it's a new request
- {
- if (evt is an ACK)
- evt could be an ACK for INVITE (not handled by oSIP)
- else if ( evt is a 200 for INVITE)
- evt could be a retransmission of a 200 for INVITE (not handled by oSIP)
- else if (evt is a new request) == not a ACK and not a response
- {
- transaction = osip_create_transaction(osip, evt);
- if (transaction==NULL)
- printf("failed to create a transaction\");
- }
- }
- else
- {
- // here, the message as been taken by the stack.
- }
-*/
-
-
-/* finds the transaction context and add the sipevent in its fifo. */
-/* USED ONLY BY THE TRANSPORT LAYER. */
-/* INPUT : osip_t *osip | osip. contains the list of tr. context*/
-/* INPUT : osip_event_t* sipevent | event to dispatch. */
-osip_transaction_t *
-osip_distribute_event (osip_t * osip, osip_event_t * evt)
-{
- osip_transaction_t *transaction = NULL;
- int i;
- osip_fsm_type_t ctx_type;
-
- if (EVT_IS_INCOMINGMSG (evt))
- {
- /* event is for ict */
- if (MSG_IS_REQUEST (evt->sip))
- {
- if (0 == strcmp (evt->sip->cseq->method, "INVITE")
- || 0 == strcmp (evt->sip->cseq->method, "ACK"))
- {
-#ifdef OSIP_MT
- osip_mutex_lock (ist_fastmutex);
-#endif
- transaction =
- osip_transaction_find (osip->osip_ist_transactions, evt);
-#ifdef OSIP_MT
- osip_mutex_unlock (ist_fastmutex);
-#endif
- }
- else
- {
-#ifdef OSIP_MT
- osip_mutex_lock (nist_fastmutex);
-#endif
- transaction =
- osip_transaction_find (osip->osip_nist_transactions, evt);
-#ifdef OSIP_MT
- osip_mutex_unlock (nist_fastmutex);
-#endif
- }
- }
- else
- {
- if (0 == strcmp (evt->sip->cseq->method, "INVITE")
- || 0 == strcmp (evt->sip->cseq->method, "ACK"))
- {
-#ifdef OSIP_MT
- osip_mutex_lock (ict_fastmutex);
-#endif
- transaction =
- osip_transaction_find (osip->osip_ict_transactions, evt);
-#ifdef OSIP_MT
- osip_mutex_unlock (ict_fastmutex);
-#endif
- }
- else
- {
-#ifdef OSIP_MT
- osip_mutex_lock (nict_fastmutex);
-#endif
- transaction =
- osip_transaction_find (osip->osip_nict_transactions, evt);
-#ifdef OSIP_MT
- osip_mutex_unlock (nict_fastmutex);
-#endif
- }
- }
- if (transaction == NULL)
- {
- if (EVT_IS_RCV_STATUS_1XX (evt)
- || EVT_IS_RCV_STATUS_2XX (evt)
- || EVT_IS_RCV_STATUS_3456XX (evt) || EVT_IS_RCV_ACK (evt))
- { /* event MUST be ignored! */
- /* EXCEPT FOR 2XX THAT MUST BE GIVEN TO THE CORE LAYER!!! */
-
- /* TODO */
-
- OSIP_TRACE (osip_trace
- (__FILE__, __LINE__, OSIP_WARNING, NULL,
- "transaction does not yet exist... %x callid:%s\n",
- evt, evt->sip->call_id->number));
- osip_message_free (evt->sip);
- osip_free (evt); /* transaction thread will not delete it */
- return NULL;
- }
-
- /* we create a new context for this incoming request */
- if (0 == strcmp (evt->sip->cseq->method, "INVITE"))
- ctx_type = IST;
- else
- ctx_type = NIST;
-
- i = osip_transaction_init (&transaction, ctx_type, osip, evt->sip);
- if (i == -1)
- {
- osip_message_free (evt->sip);
- osip_free (evt); /* transaction thread will not delete it */
- return NULL;
- }
- }
- evt->transactionid = transaction->transactionid;
-
- evt->transactionid = transaction->transactionid;
- osip_fifo_add (transaction->transactionff, evt);
- return transaction;
- }
- else
- {
- OSIP_TRACE (osip_trace
- (__FILE__, __LINE__, OSIP_BUG, NULL,
- "wrong event type %x\n", evt));
- return NULL;
- }
-}
-#endif
-
-int
-osip_find_transaction_and_add_event (osip_t * osip, osip_event_t * evt)
-{
- osip_transaction_t *transaction = __osip_find_transaction (osip, evt, 1);
-
- if (transaction == NULL)
- return -1;
- return 0;
-}
-
-#ifndef OSIP_MT
-osip_transaction_t *
-osip_find_transaction (osip_t * osip, osip_event_t * evt)
-{
- return __osip_find_transaction (osip, evt, 0);
-}
-#endif
-
-osip_transaction_t *
-__osip_find_transaction (osip_t * osip, osip_event_t * evt, int consume)
-{
- osip_transaction_t *transaction = NULL;
- osip_list_t *transactions = NULL;
-
-#ifdef OSIP_MT
- struct osip_mutex *mut = NULL;
-#endif
-
- if (evt == NULL || evt->sip == NULL || evt->sip->cseq == NULL)
- return NULL;
-
- if (EVT_IS_INCOMINGMSG (evt))
- {
- if (MSG_IS_REQUEST (evt->sip))
- {
- if (0 == strcmp (evt->sip->cseq->method, "INVITE")
- || 0 == strcmp (evt->sip->cseq->method, "ACK"))
- {
- transactions = osip->osip_ist_transactions;
-#ifdef OSIP_MT
- mut = ist_fastmutex;
-#endif
- }
- else
- {
- transactions = osip->osip_nist_transactions;
-#ifdef OSIP_MT
- mut = nist_fastmutex;
-#endif
- }
- }
- else
- {
- if (0 == strcmp (evt->sip->cseq->method, "INVITE")
- || 0 == strcmp (evt->sip->cseq->method, "ACK"))
- {
- transactions = osip->osip_ict_transactions;
-#ifdef OSIP_MT
- mut = ict_fastmutex;
-#endif
- }
- else
- {
- transactions = osip->osip_nict_transactions;
-#ifdef OSIP_MT
- mut = nict_fastmutex;
-#endif
- }
- }
- }
- else if (EVT_IS_OUTGOINGMSG (evt))
- {
- if (MSG_IS_RESPONSE (evt->sip))
- {
- if (0 == strcmp (evt->sip->cseq->method, "INVITE")
- || 0 == strcmp (evt->sip->cseq->method, "ACK"))
- {
- transactions = osip->osip_ist_transactions;
-#ifdef OSIP_MT
- mut = ist_fastmutex;
-#endif
- }
- else
- {
- transactions = osip->osip_nist_transactions;
-#ifdef OSIP_MT
- mut = nist_fastmutex;
-#endif
- }
- }
- else
- {
- if (0 == strcmp (evt->sip->cseq->method, "INVITE")
- || 0 == strcmp (evt->sip->cseq->method, "ACK"))
- {
- transactions = osip->osip_ict_transactions;
-#ifdef OSIP_MT
- mut = ict_fastmutex;
-#endif
- }
- else
- {
- transactions = osip->osip_nict_transactions;
-#ifdef OSIP_MT
- mut = nict_fastmutex;
-#endif
- }
- }
- }
- if (transactions == NULL)
- return NULL; /* not a message??? */
-
-#ifdef OSIP_MT
- osip_mutex_lock (mut);
-#endif
- transaction = osip_transaction_find (transactions, evt);
- if (consume == 1)
- { /* we add the event before releasing the mutex!! */
- if (transaction != NULL)
- {
- osip_transaction_add_event (transaction, evt);
-#ifdef OSIP_MT
- osip_mutex_unlock (mut);
-#endif
- return transaction;
- }
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (mut);
-#endif
-
- return transaction;
-}
-
-osip_transaction_t *
-osip_create_transaction (osip_t * osip, osip_event_t * evt)
-{
- osip_transaction_t *transaction;
- int i;
- osip_fsm_type_t ctx_type;
-
- if (evt == NULL)
- return NULL;
- if (evt->sip == NULL)
- return NULL;
-
- /* make sure the request's method reflect the cseq value. */
- if (MSG_IS_REQUEST (evt->sip))
- {
- /* delete request where cseq method does not match
- the method in request-line */
- if (evt->sip->cseq == NULL
- || evt->sip->cseq->method == NULL || evt->sip->sip_method == NULL)
- {
- return NULL;
- }
- if (0 != strcmp (evt->sip->cseq->method, evt->sip->sip_method))
- {
- OSIP_TRACE (osip_trace
- (__FILE__, __LINE__, OSIP_WARNING, NULL,
- "core module: Discard invalid message with method!=cseq!\n"));
- return NULL;
- }
- }
-
- if (MSG_IS_ACK (evt->sip)) /* ACK never create transactions */
- return NULL;
-
- if (EVT_IS_INCOMINGREQ (evt))
- {
- /* we create a new context for this incoming request */
- if (0 == strcmp (evt->sip->cseq->method, "INVITE"))
- ctx_type = IST;
- else
- ctx_type = NIST;
- }
- else if (EVT_IS_OUTGOINGREQ (evt))
- {
- if (0 == strcmp (evt->sip->cseq->method, "INVITE"))
- ctx_type = ICT;
- else
- ctx_type = NICT;
- }
- else
- {
- OSIP_TRACE (osip_trace
- (__FILE__, __LINE__, OSIP_ERROR, NULL,
- "Cannot build a transction for this message!\n"));
- return NULL;
- }
-
- i = osip_transaction_init (&transaction, ctx_type, osip, evt->sip);
- if (i == -1)
- {
- return NULL;
- }
- evt->transactionid = transaction->transactionid;
- return transaction;
-}
-
-osip_transaction_t *
-osip_transaction_find (osip_list_t * transactions, osip_event_t * evt)
-{
- int pos = 0;
- osip_transaction_t *transaction;
-
- if (EVT_IS_INCOMINGREQ (evt))
- {
- while (!osip_list_eol (transactions, pos))
- {
- transaction =
- (osip_transaction_t *) osip_list_get (transactions, pos);
- if (0 ==
- __osip_transaction_matching_request_osip_to_xist_17_2_3
- (transaction, evt->sip))
- return transaction;
- pos++;
- }
- }
- else if (EVT_IS_INCOMINGRESP (evt))
- {
- while (!osip_list_eol (transactions, pos))
- {
- transaction =
- (osip_transaction_t *) osip_list_get (transactions, pos);
- if (0 ==
- __osip_transaction_matching_response_osip_to_xict_17_1_3
- (transaction, evt->sip))
- return transaction;
- pos++;
- }
- }
- else /* handle OUTGOING message */
- { /* THE TRANSACTION ID MUST BE SET */
- while (!osip_list_eol (transactions, pos))
- {
- transaction =
- (osip_transaction_t *) osip_list_get (transactions, pos);
- if (transaction->transactionid == evt->transactionid)
- return transaction;
- pos++;
- }
- }
- return NULL;
-}
-
-static int ref_count = 0;
-#ifdef OSIP_MT
-static struct osip_mutex *ref_mutex = NULL;
-#endif
-
-static int
-increase_ref_count (void)
-{
-#ifdef OSIP_MT
- if (ref_count == 0)
- ref_mutex = osip_mutex_init ();
- /* Here we should assert() that the mutex was really generated. */
- osip_mutex_lock (ref_mutex);
-#endif
- if (ref_count == 0)
- __osip_global_init ();
- ref_count++;
-#ifdef OSIP_MT
- osip_mutex_unlock (ref_mutex);
-#endif
-
- return 0;
-}
-
-static void
-decrease_ref_count (void)
-{
-#ifdef OSIP_MT
- osip_mutex_lock (ref_mutex);
-#endif
- /* assert (ref_count > 0); */
- ref_count--;
- if (ref_count == 0)
- {
-#ifdef OSIP_MT
- osip_mutex_unlock (ref_mutex);
- osip_mutex_destroy (ref_mutex);
-#endif
- __osip_global_free ();
- return;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (ref_mutex);
-#endif
-}
-
-int
-osip_init (osip_t ** osip)
-{
- if (increase_ref_count () != 0)
- return -1;
-
- *osip = (osip_t *) osip_malloc (sizeof (osip_t));
- if (*osip == NULL)
- return -1; /* allocation failed */
-
- memset (*osip, 0, sizeof (osip_t));
-
- (*osip)->osip_ict_transactions =
- (osip_list_t *) osip_malloc (sizeof (osip_list_t));
- osip_list_init ((*osip)->osip_ict_transactions);
- (*osip)->osip_ist_transactions =
- (osip_list_t *) osip_malloc (sizeof (osip_list_t));
- osip_list_init ((*osip)->osip_ist_transactions);
- (*osip)->osip_nict_transactions =
- (osip_list_t *) osip_malloc (sizeof (osip_list_t));
- osip_list_init ((*osip)->osip_nict_transactions);
- (*osip)->osip_nist_transactions =
- (osip_list_t *) osip_malloc (sizeof (osip_list_t));
- osip_list_init ((*osip)->osip_nist_transactions);
-
-#ifdef OSIP_RETRANSMIT_2XX
- (*osip)->ixt_retransmissions =
- (osip_list_t *) osip_malloc (sizeof (osip_list_t));
- osip_list_init ((*osip)->ixt_retransmissions);
-#else
- (*osip)->ixt_retransmissions = NULL;
-#endif
-
- return 0;
-}
-
-void
-osip_release (osip_t * osip)
-{
- osip_free (osip->osip_ict_transactions);
- osip_free (osip->osip_ist_transactions);
- osip_free (osip->osip_nict_transactions);
- osip_free (osip->osip_nist_transactions);
-
-#ifdef OSIP_RETRANSMIT_2XX
- osip_free (osip->ixt_retransmissions);
-#endif
-
- osip_free (osip);
- decrease_ref_count ();
-}
-
-
-void
-osip_set_application_context (osip_t * osip, void *pointer)
-{
- osip->application_context = pointer;
-}
-
-void *
-osip_get_application_context (osip_t * osip)
-{
- if (osip == NULL)
- return NULL;
- return osip->application_context;
-}
-
-int
-osip_ict_execute (osip_t * osip)
-{
- osip_transaction_t *transaction;
- osip_event_t *se;
- int more_event;
- int tr;
-
- tr = 0;
- while (!osip_list_eol (osip->osip_ict_transactions, tr))
- {
- transaction = osip_list_get (osip->osip_ict_transactions, tr);
- tr++;
- more_event = 1;
- do
- {
- se = (osip_event_t *) osip_fifo_tryget (transaction->transactionff);
- if (se == NULL) /* no more event for this transaction */
- more_event = 0;
- else
- osip_transaction_execute (transaction, se);
- }
- while (more_event == 1);
- }
- return 0;
-}
-
-int
-osip_ist_execute (osip_t * osip)
-{
- osip_transaction_t *transaction;
- osip_event_t *se;
- int more_event;
- int tr;
-
- tr = 0;
- while (!osip_list_eol (osip->osip_ist_transactions, tr))
- {
- transaction = osip_list_get (osip->osip_ist_transactions, tr);
- tr++;
- more_event = 1;
- do
- {
- se = (osip_event_t *) osip_fifo_tryget (transaction->transactionff);
- if (se == NULL) /* no more event for this transaction */
- more_event = 0;
- else
- osip_transaction_execute (transaction, se);
- }
- while (more_event == 1);
- }
- return 0;
-}
-
-int
-osip_nict_execute (osip_t * osip)
-{
- osip_transaction_t *transaction;
- osip_event_t *se;
- int more_event;
- int tr;
-
- tr = 0;
- while (!osip_list_eol (osip->osip_nict_transactions, tr))
- {
- transaction = osip_list_get (osip->osip_nict_transactions, tr);
- tr++;
- more_event = 1;
- do
- {
- se = (osip_event_t *) osip_fifo_tryget (transaction->transactionff);
- if (se == NULL) /* no more event for this transaction */
- more_event = 0;
- else
- osip_transaction_execute (transaction, se);
- }
- while (more_event == 1);
- }
- return 0;
-}
-
-int
-osip_nist_execute (osip_t * osip)
-{
- osip_transaction_t *transaction;
- osip_event_t *se;
- int more_event;
- int tr;
-
- tr = 0;
- while (!osip_list_eol (osip->osip_nist_transactions, tr))
- {
- transaction = osip_list_get (osip->osip_nist_transactions, tr);
- tr++;
- more_event = 1;
- do
- {
- se = (osip_event_t *) osip_fifo_tryget (transaction->transactionff);
- if (se == NULL) /* no more event for this transaction */
- more_event = 0;
- else
- osip_transaction_execute (transaction, se);
- }
- while (more_event == 1);
- }
- return 0;
-}
-
-void
-osip_timers_gettimeout (osip_t * osip, struct timeval *lower_tv)
-{
- struct timeval now;
- osip_transaction_t *tr;
- int pos = 0;
-
- gettimeofday (&now, NULL);
- lower_tv->tv_sec = now.tv_sec + 3600 * 24 * 265; /* wake up evry year :-) */
- lower_tv->tv_usec = now.tv_usec;
-
-#ifdef OSIP_MT
- osip_mutex_lock (ict_fastmutex);
-#endif
- /* handle ict timers */
- while (!osip_list_eol (osip->osip_ict_transactions, pos))
- {
- tr =
- (osip_transaction_t *) osip_list_get (osip->osip_ict_transactions,
- pos);
-
- if (1 <= osip_fifo_size (tr->transactionff))
- {
- OSIP_TRACE (osip_trace
- (__FILE__, __LINE__, OSIP_INFO4, NULL,
- "1 Pending event already in transaction !\n"));
- lower_tv->tv_sec = 0;
- lower_tv->tv_usec = 0;
-#ifdef OSIP_MT
- osip_mutex_unlock (ict_fastmutex);
-#endif
- return;
- }
- else
- {
- if (tr->state == ICT_CALLING)
- min_timercmp (lower_tv, &tr->ict_context->timer_b_start);
- if (tr->state == ICT_CALLING)
- min_timercmp (lower_tv, &tr->ict_context->timer_a_start);
- if (tr->state == ICT_COMPLETED)
- min_timercmp (lower_tv, &tr->ict_context->timer_d_start);
- if (timercmp (&now, lower_tv, >))
- {
- lower_tv->tv_sec = 0;
- lower_tv->tv_usec = 0;
-#ifdef OSIP_MT
- osip_mutex_unlock (ict_fastmutex);
-#endif
- return;
- }
- }
- pos++;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (ict_fastmutex);
-#endif
-
-#ifdef OSIP_MT
- osip_mutex_lock (ist_fastmutex);
-#endif
- /* handle ist timers */
- while (!osip_list_eol (osip->osip_ist_transactions, pos))
- {
- tr =
- (osip_transaction_t *) osip_list_get (osip->osip_ist_transactions,
- pos);
-
- if (tr->state == IST_CONFIRMED)
- min_timercmp (lower_tv, &tr->ist_context->timer_i_start);
- if (tr->state == IST_COMPLETED)
- min_timercmp (lower_tv, &tr->ist_context->timer_h_start);
- if (tr->state == IST_COMPLETED)
- min_timercmp (lower_tv, &tr->ist_context->timer_g_start);
- if (timercmp (&now, lower_tv, >))
- {
- lower_tv->tv_sec = 0;
- lower_tv->tv_usec = 0;
-#ifdef OSIP_MT
- osip_mutex_unlock (ist_fastmutex);
-#endif
- return;
- }
- pos++;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (ist_fastmutex);
-#endif
-
-#ifdef OSIP_MT
- osip_mutex_lock (nict_fastmutex);
-#endif
- /* handle nict timers */
- while (!osip_list_eol (osip->osip_nict_transactions, pos))
- {
- tr =
- (osip_transaction_t *) osip_list_get (osip->osip_nict_transactions,
- pos);
-
- if (tr->state == NICT_COMPLETED)
- min_timercmp (lower_tv, &tr->nict_context->timer_k_start);
- if (tr->state == NICT_PROCEEDING || tr->state == NICT_TRYING)
- min_timercmp (lower_tv, &tr->nict_context->timer_f_start);
- if (tr->state == NICT_PROCEEDING || tr->state == NICT_TRYING)
- min_timercmp (lower_tv, &tr->nict_context->timer_e_start);
- if (timercmp (&now, lower_tv, >))
- {
- lower_tv->tv_sec = 0;
- lower_tv->tv_usec = 0;
-#ifdef OSIP_MT
- osip_mutex_unlock (nict_fastmutex);
-#endif
- return;
- }
- pos++;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (nict_fastmutex);
-#endif
-
-#ifdef OSIP_MT
- osip_mutex_lock (nist_fastmutex);
-#endif
- /* handle nist timers */
- while (!osip_list_eol (osip->osip_nist_transactions, pos))
- {
- tr =
- (osip_transaction_t *) osip_list_get (osip->osip_nist_transactions,
- pos);
-
- if (tr->state == NIST_COMPLETED)
- min_timercmp (lower_tv, &tr->nist_context->timer_j_start);
- if (timercmp (&now, lower_tv, >))
- {
- lower_tv->tv_sec = 0;
- lower_tv->tv_usec = 0;
-#ifdef OSIP_MT
- osip_mutex_unlock (nist_fastmutex);
-#endif
- return;
- }
- pos++;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (nist_fastmutex);
-#endif
-
- lower_tv->tv_sec = lower_tv->tv_sec - now.tv_sec;
- lower_tv->tv_usec = lower_tv->tv_usec - now.tv_usec;
-
- /* just make sure the value is correct! */
- if (lower_tv->tv_usec < 0)
- {
- lower_tv->tv_usec = lower_tv->tv_usec + 1000000;
- lower_tv->tv_sec--;
- }
- if (lower_tv->tv_sec < 0)
- {
- lower_tv->tv_sec = 0;
- lower_tv->tv_usec = 0;
- }
- if (lower_tv->tv_usec > 1000000)
- {
- lower_tv->tv_usec = lower_tv->tv_usec - 1000000;
- lower_tv->tv_sec++;
- }
- return;
-}
-
-void
-osip_timers_ict_execute (osip_t * osip)
-{
- osip_transaction_t *tr;
- int pos = 0;
-
-#ifdef OSIP_MT
- osip_mutex_lock (ict_fastmutex);
-#endif
- /* handle ict timers */
- while (!osip_list_eol (osip->osip_ict_transactions, pos))
- {
- osip_event_t *evt;
-
- tr =
- (osip_transaction_t *) osip_list_get (osip->osip_ict_transactions,
- pos);
-
- if (1 <= osip_fifo_size (tr->transactionff))
- {
- OSIP_TRACE (osip_trace
- (__FILE__, __LINE__, OSIP_INFO4, NULL,
- "1 Pending event already in transaction !\n"));
- }
- else
- {
- evt = __osip_ict_need_timer_b_event (tr->ict_context, tr->state,
- tr->transactionid);
- if (evt != NULL)
- osip_fifo_add (tr->transactionff, evt);
- else
- {
- evt = __osip_ict_need_timer_a_event (tr->ict_context, tr->state,
- tr->transactionid);
- if (evt != NULL)
- osip_fifo_add (tr->transactionff, evt);
- else
- {
- evt =
- __osip_ict_need_timer_d_event (tr->ict_context, tr->state,
- tr->transactionid);
- if (evt != NULL)
- osip_fifo_add (tr->transactionff, evt);
- }
- }
- }
- pos++;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (ict_fastmutex);
-#endif
-}
-
-void
-osip_timers_ist_execute (osip_t * osip)
-{
- osip_transaction_t *tr;
- int pos = 0;
-
-#ifdef OSIP_MT
- osip_mutex_lock (ist_fastmutex);
-#endif
- /* handle ist timers */
- while (!osip_list_eol (osip->osip_ist_transactions, pos))
- {
- osip_event_t *evt;
-
- tr =
- (osip_transaction_t *) osip_list_get (osip->osip_ist_transactions,
- pos);
-
- evt = __osip_ist_need_timer_i_event (tr->ist_context, tr->state,
- tr->transactionid);
- if (evt != NULL)
- osip_fifo_add (tr->transactionff, evt);
- else
- {
- evt = __osip_ist_need_timer_h_event (tr->ist_context, tr->state,
- tr->transactionid);
- if (evt != NULL)
- osip_fifo_add (tr->transactionff, evt);
- else
- {
- evt = __osip_ist_need_timer_g_event (tr->ist_context, tr->state,
- tr->transactionid);
- if (evt != NULL)
- osip_fifo_add (tr->transactionff, evt);
- }
- }
- pos++;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (ist_fastmutex);
-#endif
-}
-
-void
-osip_timers_nict_execute (osip_t * osip)
-{
- osip_transaction_t *tr;
- int pos = 0;
-
-#ifdef OSIP_MT
- osip_mutex_lock (nict_fastmutex);
-#endif
- /* handle nict timers */
- while (!osip_list_eol (osip->osip_nict_transactions, pos))
- {
- osip_event_t *evt;
-
- tr =
- (osip_transaction_t *) osip_list_get (osip->osip_nict_transactions,
- pos);
-
- evt = __osip_nict_need_timer_k_event (tr->nict_context, tr->state,
- tr->transactionid);
- if (evt != NULL)
- osip_fifo_add (tr->transactionff, evt);
- else
- {
- evt = __osip_nict_need_timer_f_event (tr->nict_context, tr->state,
- tr->transactionid);
- if (evt != NULL)
- osip_fifo_add (tr->transactionff, evt);
- else
- {
- evt =
- __osip_nict_need_timer_e_event (tr->nict_context, tr->state,
- tr->transactionid);
- if (evt != NULL)
- osip_fifo_add (tr->transactionff, evt);
- }
- }
- pos++;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (nict_fastmutex);
-#endif
-}
-
-
-void
-osip_timers_nist_execute (osip_t * osip)
-{
- osip_transaction_t *tr;
- int pos = 0;
-
-#ifdef OSIP_MT
- osip_mutex_lock (nist_fastmutex);
-#endif
- /* handle nist timers */
- while (!osip_list_eol (osip->osip_nist_transactions, pos))
- {
- osip_event_t *evt;
-
- tr =
- (osip_transaction_t *) osip_list_get (osip->osip_nist_transactions,
- pos);
-
- evt = __osip_nist_need_timer_j_event (tr->nist_context, tr->state,
- tr->transactionid);
- if (evt != NULL)
- osip_fifo_add (tr->transactionff, evt);
- pos++;
- }
-#ifdef OSIP_MT
- osip_mutex_unlock (nist_fastmutex);
-#endif
-}
-
-void
-osip_set_cb_send_message (osip_t * cf,
- int (*cb) (osip_transaction_t *, osip_message_t *,
- char *, int, int))
-{
- cf->cb_send_message = cb;
-}
-
-void
-__osip_message_callback (int type, osip_transaction_t * tr,
- osip_message_t * msg)
-{
- osip_t *config = tr->config;
-
- if (type >= OSIP_MESSAGE_CALLBACK_COUNT)
- {
- OSIP_TRACE (osip_trace
- (__FILE__, __LINE__, OSIP_BUG, NULL,
- "invalid callback type %d\n", type));
- return;
- }
- if (config->msg_callbacks[type] == NULL)
- return;
- config->msg_callbacks[type] (type, tr, msg);
-}
-
-void
-__osip_kill_transaction_callback (int type, osip_transaction_t * tr)
-{
- osip_t *config = tr->config;
-
- if (type >= OSIP_KILL_CALLBACK_COUNT)
- {
- OSIP_TRACE (osip_trace
- (__FILE__, __LINE__, OSIP_BUG, NULL,
- "invalid callback type %d\n", type));
- return;
- }
- if (config->kill_callbacks[type] == NULL)
- return;
- config->kill_callbacks[type] (type, tr);
-}
-
-void
-__osip_transport_error_callback (int type, osip_transaction_t * tr, int error)
-{
- osip_t *config = tr->config;
-
- if (type >= OSIP_TRANSPORT_ERROR_CALLBACK_COUNT)
- {
- OSIP_TRACE (osip_trace
- (__FILE__, __LINE__, OSIP_BUG, NULL,
- "invalid callback type %d\n", type));
- return;
- }
- if (config->tp_error_callbacks[type] == NULL)
- return;
- config->tp_error_callbacks[type] (type, tr, error);
-}
-
-
-int
-osip_set_message_callback (osip_t * config, int type, osip_message_cb_t cb)
-{
- if (type >= OSIP_MESSAGE_CALLBACK_COUNT)
- {
- OSIP_TRACE (osip_trace
- (__FILE__, __LINE__, OSIP_ERROR, NULL,
- "invalid callback type %d\n", type));
- return -1;
- }
- config->msg_callbacks[type] = cb;
-
- return 0;
-}
-
-int
-osip_set_kill_transaction_callback (osip_t * config, int type,
- osip_kill_transaction_cb_t cb)
-{
- if (type >= OSIP_KILL_CALLBACK_COUNT)
- {
- OSIP_TRACE (osip_trace
- (__FILE__, __LINE__, OSIP_ERROR, NULL,
- "invalid callback type %d\n", type));
- return -1;
- }
- config->kill_callbacks[type] = cb;
- return 0;
-}
-
-int
-osip_set_transport_error_callback (osip_t * config, int type,
- osip_transport_error_cb_t cb)
-{
- if (type >= OSIP_TRANSPORT_ERROR_CALLBACK_COUNT)
- {
- OSIP_TRACE (osip_trace
- (__FILE__, __LINE__, OSIP_ERROR, NULL,
- "invalid callback type %d\n", type));
- return -1;
- }
- config->tp_error_callbacks[type] = cb;
- return 0;
-}