/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002,2003,2004,2005,2006,2007 Aymeric MOIZARD - jack@atosc.org
eXosip is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
eXosip 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ENABLE_MPATROL
#include <mpatrol.h>
#endif
#include "eXosip2.h"
#include <eXosip2/eXosip.h>
#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef __APPLE_CC__
#include <unistd.h>
#endif
#else
#include <windows.h>
#endif
extern eXosip_t eXosip;
extern int ipv6_enable;
/* Private functions */
static void eXosip_send_default_answer (eXosip_dialog_t * jd,
osip_transaction_t * transaction,
osip_event_t * evt,
int status,
char *reason_phrase,
char *warning, int line);
static void eXosip_process_bye (eXosip_call_t * jc, eXosip_dialog_t * jd,
osip_transaction_t * transaction,
osip_event_t * evt);
static void eXosip_process_ack (eXosip_call_t * jc, eXosip_dialog_t * jd,
osip_event_t * evt);
static void eXosip_process_prack (eXosip_call_t * jc, eXosip_dialog_t * jd,
osip_transaction_t * transaction,
osip_event_t * evt);
static int cancel_match_invite (osip_transaction_t * invite,
osip_message_t * cancel);
static void eXosip_process_cancel (osip_transaction_t * transaction,
osip_event_t * evt);
static void eXosip_process_reinvite (eXosip_call_t * jc,
eXosip_dialog_t * jd,
osip_transaction_t *
transaction, osip_event_t * evt);
static void eXosip_process_new_invite (osip_transaction_t * transaction,
osip_event_t * evt);
#ifndef MINISIZE
static void eXosip_process_new_subscribe (osip_transaction_t * transaction,
osip_event_t * evt);
static void eXosip_process_subscribe_within_call (eXosip_notify_t * jn,
eXosip_dialog_t * jd,
osip_transaction_t *
transaction, osip_event_t * evt);
static void eXosip_process_notify_within_dialog (eXosip_subscribe_t * js,
eXosip_dialog_t * jd,
osip_transaction_t *
transaction, osip_event_t * evt);
static int eXosip_match_notify_for_subscribe (eXosip_subscribe_t * js,
osip_message_t * notify);
#endif
static void eXosip_process_message_within_dialog (eXosip_call_t * jc,
eXosip_dialog_t * jd,
osip_transaction_t *
transaction, osip_event_t * evt);
static void eXosip_process_newrequest (osip_event_t * evt, int socket);
static void eXosip_process_response_out_of_transaction (osip_event_t * evt);
static int eXosip_pendingosip_transaction_exist (eXosip_call_t * jc,
eXosip_dialog_t * jd);
static int eXosip_release_finished_calls (eXosip_call_t * jc,
eXosip_dialog_t * jd);
static int eXosip_release_aborted_calls (eXosip_call_t * jc, eXosip_dialog_t * jd);
static int eXosip_release_finished_transactions (eXosip_call_t *jc, eXosip_dialog_t * jd);
#ifndef MINISIZE
static int eXosip_release_finished_transactions_for_subscription (eXosip_dialog_t *jd);
#endif
static void
eXosip_send_default_answer (eXosip_dialog_t * jd,
osip_transaction_t * transaction,
osip_event_t * evt,
int status,
char *reason_phrase, char *warning, int line)
{
osip_event_t *evt_answer;
osip_message_t *answer;
int i;
/* osip_list_add(eXosip.j_transactions, transaction, 0); */
osip_transaction_set_your_instance (transaction, NULL);
/* THIS METHOD DOES NOT ACCEPT STATUS CODE BETWEEN 101 and 299 */
if (status > 100 && status < 299 && MSG_IS_INVITE (evt->sip))
return;
if (jd != NULL)
i = _eXosip_build_response_default (&answer, jd->d_dialog, status, evt->sip);
else
i = _eXosip_build_response_default (&answer, NULL, status, evt->sip);
if (i != 0 || answer == NULL)
{
return;
}
if (reason_phrase != NULL)
{
char *_reason;
_reason = osip_message_get_reason_phrase (answer);
if (_reason != NULL)
osip_free (_reason);
_reason = osip_strdup (reason_phrase);
osip_message_set_reason_phrase (answer, _reason);
}
osip_message_set_content_length (answer, "0");
if (status == 500)
osip_message_set_retry_after (answer, "10");
evt_answer = osip_new_outgoing_sipmessage (answer);
evt_answer->transactionid = transaction->transactionid;
osip_transaction_add_event (transaction, evt_answer);
__eXosip_wakeup ();
}
static void
eXosip_process_bye (eXosip_call_t * jc, eXosip_dialog_t * jd,
osip_transaction_t * transaction, osip_event_t * evt)
{
osip_event_t *evt_answer;
osip_message_t *answer;
int i;
#ifndef MINISIZE
osip_transaction_set_your_instance (transaction,
__eXosip_new_jinfo (jc, NULL /*jd */ ,
NULL, NULL));
#else
osip_transaction_set_your_instance (transaction,
__eXosip_new_jinfo (jc, NULL /*jd */));
#endif
i = _eXosip_build_response_default (&answer, jd->d_dialog, 200, evt->sip);
if (i != 0)
{
osip_list_add (eXosip.j_transactions, transaction, 0);
return;
}
osip_message_set_content_length (answer, "0");
evt_answer = osip_new_outgoing_sipmessage (answer);
evt_answer->transactionid = transaction->transactionid;
osip_list_add (jd->d_inc_trs, transaction, 0);
/* Release the eXosip_dialog */
osip_dialog_free (jd->d_dialog);
jd->d_dialog = NULL;
osip_transaction_add_event (transaction, evt_answer);
osip_nist_execute (eXosip.j_osip);
report_call_event (EXOSIP_CALL_MESSAGE_NEW, jc, jd, transaction);
report_call_event (EXOSIP_CALL_CLOSED, jc, jd, transaction);
eXosip_update (); /* AMD 30/09/05 */
__eXosip_wakeup ();
}
static void
eXosip_process_ack (eXosip_call_t * jc, eXosip_dialog_t * jd, osip_event_t * evt)
{
/* TODO: We should find the matching transaction for this ACK
and also add the ACK in the event. */
eXosip_event_t *je;
int i;
je = eXosip_event_init_for_call (EXOSIP_CALL_ACK, jc, jd, NULL);
if (je != NULL)
{
osip_transaction_t *tr;
tr= eXosip_find_last_inc_invite(jc, jd);
if (tr!=NULL)
{
je->tid = tr->transactionid;
/* fill request and answer */
if (tr->orig_request != NULL)
{
i = osip_message_clone (tr->orig_request, &je->request);
if (i != 0)
{
OSIP_TRACE (osip_trace (__FILE__, __
评论0