Fix issue 454

This commit is contained in:
bossiel 2015-07-13 23:20:07 +00:00
parent 4c0f326ff0
commit 616569765e
2 changed files with 1079 additions and 1071 deletions

View File

@ -576,6 +576,7 @@ typedef struct tsip_stack_s
char *local_ip[TSIP_TRANSPORT_IDX_MAX];
tnet_port_t local_port[TSIP_TRANSPORT_IDX_MAX];
tsk_bool_t local_ip_is_set_by_user[TSIP_TRANSPORT_IDX_MAX]; // whether the address (ip and port) is set by the user or retrieved
char *proxy_cscf[TSIP_TRANSPORT_IDX_MAX];
tnet_port_t proxy_cscf_port[TSIP_TRANSPORT_IDX_MAX];

View File

@ -1,23 +1,23 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
* Copyright (C) 2012 Doubango Telecom <http://doubango.org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO 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 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO 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 DOUBANGO.
*
*/
* Copyright (C) 2010-2011 Mamadou Diop.
* Copyright (C) 2012 Doubango Telecom <http://doubango.org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO 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 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO 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 DOUBANGO.
*
*/
/**@file tsip.c
* @brief SIP (RFC 3261) and 3GPP IMS/LTE (TS 24.229) implementation.
@ -50,23 +50,23 @@
static void* TSK_STDCALL run(void* self);
/* For tests:
* http://www.voip-info.org/wiki/view/PROTOS+Test-Suite
* http://tools.ietf.org/html/rfc4475
* http://portal.etsi.org/docbox/EC_Files/EC_Files/ts_10202702v030101p.pdf
*/
* http://www.voip-info.org/wiki/view/PROTOS+Test-Suite
* http://tools.ietf.org/html/rfc4475
* http://portal.etsi.org/docbox/EC_Files/EC_Files/ts_10202702v030101p.pdf
*/
/**@defgroup tsip_stack_group 3GPP IMS/LTE Stack
*/
*/
extern tsip_event_t* tsip_event_create(tsip_ssession_t* ss, short code, const char* phrase, const tsip_message_t* sipmessage, tsip_event_type_t type);
#define TSIP_STACK_SIGNAL(self, code, phrase) \
{ \
tsip_event_t* e; \
if((e = tsip_event_create(tsk_null, code, phrase, tsk_null, tsip_event_stack))){ \
TSK_RUNNABLE_ENQUEUE_OBJECT(TSK_RUNNABLE(self), e); \
} \
}
{ \
tsip_event_t* e; \
if((e = tsip_event_create(tsk_null, code, phrase, tsk_null, tsip_event_stack))){ \
TSK_RUNNABLE_ENQUEUE_OBJECT(TSK_RUNNABLE(self), e); \
} \
}
static int __tsip_stack_get_transport_idx_by_name(tsip_stack_t *self, const char* name)
{
@ -190,6 +190,7 @@ static int __tsip_stack_set(tsip_stack_t *self, va_list* app)
if(t_idx < 0) { TSK_DEBUG_ERROR("%s not valid as transport or you're probably using deprecated function", TRANSPORT_STR); return -1; }
tsk_strupdate(&self->network.local_ip[t_idx], IP_STR);
self->network.local_ip_is_set_by_user[t_idx] = tsk_true; // do not query best source when stack is re-started
if(TSIP_STACK_MODE_IS_SERVER(self) && !tsk_strnullORempty(TRANSPORT_STR)){
self->network.transport_types[t_idx] = tsip_transport_get_type_by_name(TRANSPORT_STR);
}
@ -462,27 +463,27 @@ bail:
}
/**@ingroup tsip_stack_group
* Creates new 3GPP IMS/LTE stack handle.
* As the 3GPP IMS/LTE stack depends on the network library (tinyNET), you MUST call <a href="http://doubango.org/API/tinyNET/tnet_8c.html#affba6c2710347476f615b0135777c640"> tnet_startup()</a> before using any SIP function (tsip_*).
* <a href="http://doubango.org/API/tinyNET/tnet_8c.html#ac42b22a7ac5831f04326aee9de033c84"> tnet_cleanup()</a> is used to terminate use of network functions.
* @param callback Callback function to call to alert the application for new SIP or media events.
* @param realm_uri The realm is the name of the domain name to authenticate to. It should be a valid SIP URI (e.g. sip:open-ims.test).
* @param impi_uri The IMPI is a unique identifier assigned to a user (or UE) by the home network.
* It could be either a SIP URI (e.g. sip:bob@open-ims.test), a tel URI (e.g. tel:+33100000) or any alphanumeric string (e.g. bob@open-ims.test or bob).
* It is used to authenticate the UE (username field in SIP Authorization/Proxy-Authorization header).
* @param impu_uri As its name says, its you public visible identifier where you are willing to receive calls or any demands.
* An IMPU could be either a SIP or tel URI (e.g. tel:+33100000 or sip:bob@open-ims.test). In IMS world, a user can have multiple IMPUs associated to its unique IMPI.
* @param ... Any TSIP_STACK_SET_*() macros.
* @retval A valid handle if succeed and Null-handle otherwise. As a stack is a well-defined object, you should use @a TSK_OBJECT_SAFE_FREE() to safely destroy the handle.
*
* @code
int app_callback(const tsip_event_t *sipevent);
* Creates new 3GPP IMS/LTE stack handle.
* As the 3GPP IMS/LTE stack depends on the network library (tinyNET), you MUST call <a href="http://doubango.org/API/tinyNET/tnet_8c.html#affba6c2710347476f615b0135777c640"> tnet_startup()</a> before using any SIP function (tsip_*).
* <a href="http://doubango.org/API/tinyNET/tnet_8c.html#ac42b22a7ac5831f04326aee9de033c84"> tnet_cleanup()</a> is used to terminate use of network functions.
* @param callback Callback function to call to alert the application for new SIP or media events.
* @param realm_uri The realm is the name of the domain name to authenticate to. It should be a valid SIP URI (e.g. sip:open-ims.test).
* @param impi_uri The IMPI is a unique identifier assigned to a user (or UE) by the home network.
* It could be either a SIP URI (e.g. sip:bob@open-ims.test), a tel URI (e.g. tel:+33100000) or any alphanumeric string (e.g. bob@open-ims.test or bob).
* It is used to authenticate the UE (username field in SIP Authorization/Proxy-Authorization header).
* @param impu_uri As its name says, its you public visible identifier where you are willing to receive calls or any demands.
* An IMPU could be either a SIP or tel URI (e.g. tel:+33100000 or sip:bob@open-ims.test). In IMS world, a user can have multiple IMPUs associated to its unique IMPI.
* @param ... Any TSIP_STACK_SET_*() macros.
* @retval A valid handle if succeed and Null-handle otherwise. As a stack is a well-defined object, you should use @a TSK_OBJECT_SAFE_FREE() to safely destroy the handle.
*
* @code
int app_callback(const tsip_event_t *sipevent);
const char* realm_uri = "sip:open-ims.test";
const char* impi_uri = "bob@open-ims.test";
const char* impu_uri = "sip:bob@open-ims.test";
const char* realm_uri = "sip:open-ims.test";
const char* impi_uri = "bob@open-ims.test";
const char* impu_uri = "sip:bob@open-ims.test";
tsip_stack_handle_t* stack = tsip_stack_create(app_callback, realm_uri, impi_uri, impu_uri,
tsip_stack_handle_t* stack = tsip_stack_create(app_callback, realm_uri, impi_uri, impu_uri,
TSIP_STACK_SET_PASSWORD("mysecret"),
// ...other macros...
TSIP_STACK_SET_NULL());
@ -490,9 +491,9 @@ tsip_stack_handle_t* stack = tsip_stack_create(app_callback, realm_uri, impi_uri
// ...whatever
TSK_OBJECT_SAFE_FREE(stack);
* @endcode
* @sa @ref tsip_stack_set()<br>@ref tsip_stack_start()
*/
* @endcode
* @sa @ref tsip_stack_set()<br>@ref tsip_stack_start()
*/
tsip_stack_handle_t* tsip_stack_create(tsip_stack_callback_f callback, const char* realm_uri, const char* impi_uri, const char* impu_uri, ...)
{
tsip_stack_t* stack = tsk_null;
@ -605,10 +606,10 @@ bail:
/**@ingroup tsip_stack_group
* Starts a 3GPP IMS/LTE stack. This function MUST be called before you start calling any SIP function (@a tsip_*).
* @param self The 3GPP IMS/LTE stack to start. This handle should be created using @ref tsip_stack_create().
* @retval Zero if succeed and non-zero error code otherwise.
*/
* Starts a 3GPP IMS/LTE stack. This function MUST be called before you start calling any SIP function (@a tsip_*).
* @param self The 3GPP IMS/LTE stack to start. This handle should be created using @ref tsip_stack_create().
* @retval Zero if succeed and non-zero error code otherwise.
*/
int tsip_stack_start(tsip_stack_handle_t *self)
{
int ret = -1, t_idx, tx_count;
@ -655,10 +656,10 @@ int tsip_stack_start(tsip_stack_handle_t *self)
/* === Set Max FDs === */
if (stack->network.max_fds > 0 && stack->network.max_fds < 0xFFFF) {
TSK_DEBUG_INFO("Setting max FDs to %u", stack->network.max_fds);
TSK_DEBUG_INFO("Setting max FDs to %u", (unsigned)stack->network.max_fds);
ret = tnet_set_fd_max_allowed(stack->network.max_fds);
if (ret) {
TSK_DEBUG_ERROR("Failed to set max FDs to %u", stack->network.max_fds);
TSK_DEBUG_ERROR("Failed to set max FDs to %u", (unsigned)stack->network.max_fds);
/* goto bail; */ // Not fatal error
}
}
@ -717,20 +718,26 @@ int tsip_stack_start(tsip_stack_handle_t *self)
}// !Server mode
/* === Get Best source address === */
if(tsk_strnullORempty(stack->network.local_ip[t_idx]) || tsk_striequals(stack->network.local_ip[t_idx], "127.0.0.1")){ /* loacal-ip is missing? */
// Best local address must be updated if not defined or none is set by the user.
// The local address could be no-null if the stack is re-starting: https://code.google.com/p/doubango/issues/detail?id=454 and https://code.google.com/p/idoubs/issues/detail?id=195
if (!stack->network.local_ip_is_set_by_user[t_idx] || tsk_strnullORempty(stack->network.local_ip[t_idx]) || tsk_striequals(stack->network.local_ip[t_idx], "127.0.0.1")) { /* loacal-ip is missing? */
tnet_ip_t bestsource;
if((ret = tnet_getbestsource(stack->network.proxy_cscf[t_idx] ? stack->network.proxy_cscf[t_idx] : "google.com",
if ((ret = tnet_getbestsource(stack->network.proxy_cscf[t_idx] ? stack->network.proxy_cscf[t_idx] : "google.com",
stack->network.proxy_cscf_port[t_idx] ? stack->network.proxy_cscf_port[t_idx] : 5060,
tx_values[t_idx],
&bestsource)))
{
TSK_DEBUG_ERROR("Failed to get best source [%d].", ret);
TSK_DEBUG_ERROR("Failed to get best source [%d]", ret);
/* do not exit ==> will use default IP address */
}
else{
else {
tsk_strupdate(&stack->network.local_ip[t_idx], bestsource);
TSK_DEBUG_INFO("Best source at %d: %s", t_idx, bestsource);
}
}
else {
TSK_DEBUG_INFO("Do not query for best source address at %d, local_ip_is_set_by_user=%d, local_ip=%s", t_idx, stack->network.local_ip_is_set_by_user[t_idx], stack->network.local_ip[t_idx]);
}
} /* for (t_idx...) */
/* === Runnable === */
@ -828,19 +835,19 @@ bail:
}
/**@ingroup tsip_stack_group
* Configures the stack.
* @param self The 3GPP IMS/LTE stack to configure. This handle should be created using @ref tsip_stack_create().
* @param ... Any TSIP_STACK_SET_*() or TSIP_STACK_UNSET_*() macros.
* @retval Zero if succeed and non-zero error code otherwise.
*
* @code
int ret = tsip_stack_set(stack,
* Configures the stack.
* @param self The 3GPP IMS/LTE stack to configure. This handle should be created using @ref tsip_stack_create().
* @param ... Any TSIP_STACK_SET_*() or TSIP_STACK_UNSET_*() macros.
* @retval Zero if succeed and non-zero error code otherwise.
*
* @code
int ret = tsip_stack_set(stack,
TSIP_STACK_SET_HEADER("User-Agent", "IM-client/OMA1.0 doubango/v1.0.0"),
TSIP_STACK_SET_NULL());
* @endcode
*
* @sa @ref tsip_stack_create()
*/
* @endcode
*
* @sa @ref tsip_stack_create()
*/
int tsip_stack_set(tsip_stack_handle_t *self, ...)
{
if(self){
@ -860,9 +867,9 @@ int tsip_stack_set(tsip_stack_handle_t *self, ...)
}
/**@ingroup tsip_stack_group
* Gets user's data, previously set using @ref TSIP_STACK_SET_USERDATA() macro.
* @param self Stack from which to get the user's data.
*/
* Gets user's data, previously set using @ref TSIP_STACK_SET_USERDATA() macro.
* @param self Stack from which to get the user's data.
*/
const void* tsip_stack_get_userdata(const tsip_stack_handle_t *self)
{
if(self){
@ -875,7 +882,7 @@ const void* tsip_stack_get_userdata(const tsip_stack_handle_t *self)
}
/**@ingroup tsip_stack_group
*/
*/
tnet_dns_ctx_t* tsip_stack_get_dnsctx(tsip_stack_handle_t *self)
{
if(self){
@ -888,7 +895,7 @@ tnet_dns_ctx_t* tsip_stack_get_dnsctx(tsip_stack_handle_t *self)
}
/**@ingroup tsip_stack_group
*/
*/
tsip_uri_t* tsip_stack_get_preferred_id(tsip_stack_handle_t *self)
{
if(self){
@ -901,7 +908,7 @@ tsip_uri_t* tsip_stack_get_preferred_id(tsip_stack_handle_t *self)
}
/**@ingroup tsip_stack_group
*/
*/
int tsip_stack_get_local_ip_n_port(const tsip_stack_handle_t *self, const char* protocol, tnet_port_t *port, tnet_ip_t *ip)
{
const tsip_stack_t *stack = self;
@ -929,13 +936,13 @@ int tsip_stack_get_local_ip_n_port(const tsip_stack_handle_t *self, const char*
}
/**@ingroup tsip_stack_group
* Stops the stack.
* @param self The 3GPP IMS/LTE stack to stop. This handle should be created using @ref tsip_stack_create() and started using tsip_stack_start().
* This function is also called by the garbage collector when the stack is destroyed but you should call it yourself before destroying the stack.<br>
* Before stopping, the stack will hangup all SIP dialogs (starting with non-register dialogs) and destroy all sessions. This is called shutdown phase.
* At the end of this phase, all the SIP sessions will be destroyed.
* @sa @ref tsip_stack_create()<br>@ref tsip_stack_start()
*/
* Stops the stack.
* @param self The 3GPP IMS/LTE stack to stop. This handle should be created using @ref tsip_stack_create() and started using tsip_stack_start().
* This function is also called by the garbage collector when the stack is destroyed but you should call it yourself before destroying the stack.<br>
* Before stopping, the stack will hangup all SIP dialogs (starting with non-register dialogs) and destroy all sessions. This is called shutdown phase.
* At the end of this phase, all the SIP sessions will be destroyed.
* @sa @ref tsip_stack_create()<br>@ref tsip_stack_start()
*/
int tsip_stack_stop(tsip_stack_handle_t *self)
{
tsip_stack_t *stack = self;
@ -1009,7 +1016,7 @@ int tsip_stack_stop(tsip_stack_handle_t *self)
TSK_DEBUG_INFO("SIP STACK -- STOP");
bail:
bail:
tsk_safeobj_unlock(stack);
return ret;