/*
eXosip - This is the eXtended osip library.
Copyright (C) 2002,2003,2004,2005 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"
extern eXosip_t eXosip;
static int _eXosip_register_build_register (eXosip_reg_t * jr,
osip_message_t ** _reg);
static eXosip_reg_t *
eXosip_reg_find (int rid)
{
eXosip_reg_t *jr;
for (jr = eXosip.j_reg; jr != NULL; jr = jr->next)
{
if (jr->r_id == rid)
{
return jr;
}
}
return NULL;
}
int eXosip_register_remove (int rid)
{
eXosip_reg_t *jr;
jr = eXosip_reg_find (rid);
if (jr == NULL)
{
/* fprintf(stderr, "eXosip: no registration info saved!\n"); */
return -1;
}
jr->r_reg_period = 0;
return 0;
}
static int
_eXosip_register_build_register (eXosip_reg_t * jr, osip_message_t ** _reg)
{
osip_message_t *reg = NULL;
struct eXosip_net *net;
int i;
reg = NULL;
*_reg = NULL;
if (jr->r_last_tr != NULL)
{
if (jr->r_last_tr->state != NICT_TERMINATED
&& jr->r_last_tr->state != NICT_COMPLETED)
return -1;
else
{
osip_message_t *last_response = NULL;
osip_transaction_t *tr;
osip_message_clone (jr->r_last_tr->orig_request, ®);
if (reg == NULL)
return -1;
/* reg = jr->r_last_tr->orig_request; */
if (jr->r_last_tr->last_response != NULL)
{
osip_message_clone (jr->r_last_tr->last_response, &last_response);
if (last_response == NULL)
{
osip_message_free (reg);
return -1;
}
}
__eXosip_delete_jinfo (jr->r_last_tr);
tr = jr->r_last_tr;
jr->r_last_tr = NULL;
osip_list_add (eXosip.j_transactions, tr, 0);
/* modify the REGISTER request */
{
int osip_cseq_num = osip_atoi (reg->cseq->number);
int length = strlen (reg->cseq->number);
osip_authorization_t *aut;
osip_proxy_authorization_t *proxy_aut;
aut = (osip_authorization_t *) osip_list_get (®->authorizations, 0);
while (aut != NULL)
{
osip_list_remove (®->authorizations, 0);
osip_authorization_free (aut);
aut =
(osip_authorization_t *) osip_list_get (®->authorizations, 0);
}
proxy_aut =
(osip_proxy_authorization_t *) osip_list_get (®->
proxy_authorizations,
0);
while (proxy_aut != NULL)
{
osip_list_remove (®->proxy_authorizations, 0);
osip_proxy_authorization_free (proxy_aut);
proxy_aut =
(osip_proxy_authorization_t *) osip_list_get (®->
proxy_authorizations,
0);
}
if (0 == osip_strcasecmp (jr->transport, "udp"))
net = &eXosip.net_interfaces[0];
else if (0 == osip_strcasecmp (jr->transport, "tcp"))
net = &eXosip.net_interfaces[1];
else
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"eXosip: unsupported protocol '%s' (default to UDP)\n",
jr->transport));
net = &eXosip.net_interfaces[0];
}
/*
modify the port number when masquerading is ON.
*/
if (net->net_firewall_ip[0] != '\0')
{
int pos = 0;
while (!osip_list_eol (®->contacts, pos))
{
osip_contact_t *co;
co = (osip_contact_t *) osip_list_get (®->contacts, pos);
pos++;
if (co != NULL && co->url != NULL && co->url->host != NULL
&& 0 == osip_strcasecmp (co->url->host,
net->net_firewall_ip))
{
if (co->url->port == NULL &&
0 != osip_strcasecmp (net->net_port, "5060"))
{
co->url->port = osip_strdup (net->net_port);
} else if (co->url->port != NULL &&
0 != osip_strcasecmp (net->net_port,
co->url->port))
{
osip_free (co->url->port);
co->url->port = osip_strdup (net->net_port);
}
}
}
}
if (-1 == eXosip_update_top_via (reg))
{
osip_message_free (reg);
if (last_response != NULL)
osip_message_free (last_response);
return -1;
}
osip_cseq_num++;
osip_free (reg->cseq->number);
reg->cseq->number = (char *) osip_malloc (length + 2); /* +2 like for 9 to 10 */
sprintf (reg->cseq->number, "%i", osip_cseq_num);
{
osip_header_t *exp;
osip_message_header_get_byname (reg, "expires", 0, &exp);
osip_free (exp->hvalue);
exp->hvalue = (char *) osip_malloc (10);
snprintf (exp->hvalue, 9, "%i", jr->r_reg_period);
}
osip_message_force_update (reg);
}
if (last_response != NULL)
{
if (MSG_IS_STATUS_4XX (last_response))
{
eXosip_add_authentication_information (reg, last_response);
}
osip_message_free (last_response);
}
}
}
if (reg == NULL)
{
i = generating_register (®, jr->transport,
jr->r_aor, jr->r_registrar, jr->r_contact,
jr->r_reg_period);
if (i != 0)
{
return -2;
}
}
*_reg = reg;
return 0;
}
int
eXosip_register_build_initial_register (const char *from, const char *proxy,
const char *contact, int expires,
osip_message_t ** reg)
{
eXosip_reg_t *jr = NULL;
int i;
*reg = NULL;
if (eXosip.net_interfaces[0].net_socket <= 0
&& eXosip.net_interfaces[1].net_socket <= 0
&& eXosip.net_interfaces[2].net_socket <= 0)
return -1;
/* Avoid adding the same registration info twice to prevent mem leaks */
for (jr = eXosip.j_reg; jr != NULL; jr = jr->next)
{
if (strcmp (jr->r_aor, from) == 0 && strcmp (jr->r_registrar, proxy) == 0)
{
break;
}
}
if (jr == NULL)
{
/* Add new registration info */
i = eXosip_reg_init (&jr, from, proxy, contact);
if (i != 0)
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"eXosip: cannot register! "));
return i;
}
ADD_ELEMENT (eXosip.j_reg, jr);
}
/* Guess transport from existing connections */
if (eXosip.net_interfaces[0].net_socket > 0)
osip_strncpy (jr->transport, "UDP", sizeof (jr->transport) - 1);
else if (eXosip.net_interfaces[1].net_socket > 0)
osip_strncpy (jr->transport, "TCP", sizeof (jr->transport) - 1);
else if (eXosip.net_interfaces[2].net_socket > 0)
osip_strncpy (jr->transport, "TLS", sizeof (jr->transport) - 1);
/* build register */
jr->r_reg_period = expires;
i = _eXosip_register_build_register (jr, reg);
if (i != 0)
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"eXosip: cannot build REGISTER!\n"));
*reg = NULL;
return i;
}
return jr->r_id;
}
int
eXosip_register_build_register (int rid, int expires, osip_message_t ** reg)
{
eXosip_reg_t *jr;
int i;
*reg = NULL;
jr = eXosip_reg_find (rid);
if (jr == NULL)
{
/* fprintf(stderr, "eXosip: no registration info saved!\n"); */
return -1;
}
jr->r_reg_period = expires;
if (jr->r_reg_period == 0)
{
} /* unregistration */
else if (jr->r_reg_period > 3600)
jr->r_reg_period = 3600;
else if (jr->r_reg_period < 200) /* too low */
jr->r_reg_period = 200;
if (jr->r_last_tr != NULL)
{
if (jr->r_last_tr->state != NICT_TERMINATED
&& jr->r_last_tr->state != NICT_COMPLETED)
{
/* fprintf(stderr, "eXosip: a registration is already pending!\n"); */
return -1;
}
}
i = _eXosip_register_build_register (jr, reg);
if (i != 0)
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"eXosip: cannot build REGISTER!"));
*reg = NULL;
return i;
}
return 0;
}
int
eXosip_register_send_register (int rid, osip_message_t * reg)
{
osip_transaction_t *transaction;
osip_event_t *sipevent;
eXosip_reg_t *jr;
char *transport;
int i;
jr = eXosip_reg_find (rid);
if (jr == NULL)
{
osip_message_free (reg);
return -1;
}
if (jr->r_last_tr != NULL)
{
if (jr->r_last_tr->state != NICT_TERMINATED
&& jr->r_last_tr->state != NICT_COMPLETED)
{
osip_message_free (reg);
return -1;
}
}
if (reg == NULL)
{
i = _eXosip_register_build_register (jr, ®);
if (i != 0)
{
OSIP_TRACE (osip_trace
(__FILE__, __LINE__, OSIP_ERROR, NULL,
"eXosip: cannot build REGISTER!"));
return i;
}
}
transport = _eXosip_transport_protocol (reg);
osip_strncpy (jr->transport, transport, sizeof (jr->transport) - 1);
i = _eXosip_transaction_init (&transaction, NICT, eXosip.j_osip, reg);
if (i != 0)
{
/* TODO: release the j_call.. */
osip_message_free (reg);
return -2;
}
jr->r_last_tr = transaction;
/* send REGISTER */
sipevent = osip_new_outgoing_sipmessage (reg);
sipevent->transactionid = transaction->transactionid;
osip_message_force_update (reg);
osip_transaction_add_event (transaction, sipevent);
__eXosip_wakeup ();
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1