Add support for AOR hacking for emulators (such as Android or WINCE).

This commit is contained in:
bossiel 2010-05-05 23:25:01 +00:00
parent a25ecc610f
commit 2b0979354d
45 changed files with 3344 additions and 2941 deletions

View File

@ -43,6 +43,7 @@ typedef enum cmd_type_e
cmd_help, /* ++help | ++h */
cmd_large_message, /* ++large-message | ++lm */
cmd_message, /* ++message | ++m*/
cmd_options, /* ++options | ++opt*/
cmd_publish, /* ++publish | ++pub*/
cmd_register, /* ++register | ++reg */
cmd_run, /* ++run | ++r*/

View File

@ -23,6 +23,7 @@
#include "invite.h"
#include "message.h"
#include "options.h"
#include "publish.h"
#include "register.h"
#include "subscribe.h"
@ -82,6 +83,11 @@ int stack_callback(const tsip_event_t *sipevent)
ret = message_handle_event(sipevent);
break;
}
case tsip_event_options:
{ /* OPTIONS */
ret = options_handle_event(sipevent);
break;
}
case tsip_event_publish:
{ /* PUBLISH */
ret = publish_handle_event(sipevent);
@ -444,15 +450,17 @@ const session_t* session_handle_cmd(cmd_type_t cmd, const opts_L_t* opts)
#define TYPE_FROM_CMD(_CMD) \
((_CMD==cmd_audio || _CMD==cmd_video || _CMD==cmd_audiovideo || _CMD==cmd_file || _CMD==cmd_large_message) ? st_invite : \
((_CMD==cmd_message || _CMD==cmd_sms) ? st_message : \
(_CMD==cmd_options ? st_options : \
(_CMD==cmd_publish ? st_publish : \
(_CMD==cmd_register ? st_register : \
(_CMD==cmd_subscribe ? st_subscribe : st_none)))))
(_CMD==cmd_subscribe ? st_subscribe : st_none))))))
/* === Command === */
switch(cmd){
//case cmd_invite:
case cmd_message:
case cmd_sms:
case cmd_options:
case cmd_publish:
case cmd_register:
case cmd_subscribe:
@ -466,7 +474,7 @@ const session_t* session_handle_cmd(cmd_type_t cmd, const opts_L_t* opts)
}
default:
{
TSK_DEBUG_WARN("Registration: Cannot handle this command [%d]", cmd);
TSK_DEBUG_WARN("Session handling: Cannot handle this command [%d]", cmd);
goto bail;
}
} /* switch */

View File

@ -36,6 +36,7 @@ typedef enum session_type_e
st_invite,
st_message,
st_options,
st_publish,
st_register,
st_subscribe,

View File

@ -15,11 +15,11 @@
%%sub-pres-sid
%%pub-sid
# Configure the stack
# Realm, IMPI and IMPU are mandatory
++cst --realm $$(domain) --impi $$(user)@$$(domain) --impu sip:$$(user)@$$(domain) --pwd $$(pwd) \
--pcscf-trans $$(proxy_trans)\
--pcscf-trans $$(proxy_trans)\
--local-ip 10.0.2.15\
--pcscf-ip $$(proxy_ip) --pcscf-port $$(proxy_port) --pcscf-trans $$(proxy_trans)\
--header Privacy=header;id --header Allow=INVITE, ACK, CANCEL, BYE, MESSAGE, OPTIONS, NOTIFY, PRACK, UPDATE, REFER \
--header P-Access-Network-Info=ADSL;utran-cell-id-3gpp=00000000 \
@ -28,6 +28,11 @@
# Run the engine
++r
# OPTIONS to hack AOR
++opt
++sleep --sec 1
# REGISTER
++reg --xp $$(expires) --caps +g.oma.sip-im --caps +g.3gpp.smsip --caps language="en,fr" \
--header Action-Header=Myheader-value @@action\

View File

@ -40,4 +40,8 @@
# pragma warning( disable : 4996 )
#endif
/* use SIP OPTIONS and "rport" to hack the AOR
* usefult on some emulator (such as Android) with non-routable IP addresses */
#define HACK_AOR 0
#endif /* TINYDEMO_CONFIG_H */

View File

@ -12,6 +12,7 @@ OBJS = \
invite.o \
main.o \
message.o \
options.o \
publish.o \
register.o \
subscribe.o

File diff suppressed because it is too large Load Diff

View File

@ -235,6 +235,7 @@ replace:
("help"i | "h"i) %{ cmd->type = cmd_help; } |
("large-message"i | "lm"i) %{ cmd->type = cmd_large_message; } |
("message"i | "m"i) %{ cmd->type = cmd_message; } |
("options"i | "opt"i) %{ cmd->type = cmd_options; } |
("publish"i | "pub"i) %{ cmd->type = cmd_publish; } |
("register"i | "reg"i) %{ cmd->type = cmd_register; } |
("run"i | "r"i) %{ cmd->type = cmd_run; } |

View File

@ -24,6 +24,7 @@
#include "invite.h"
#include "message.h"
#include "options.h"
#include "publish.h"
#include "register.h"
#include "subscribe.h"
@ -182,9 +183,7 @@ parse_buffer:
TSK_DEBUG_INFO("Exit/Quit");
goto bail;
default:
tsk_safeobj_lock(ctx);
ret = execute(cmd);
tsk_safeobj_unlock(ctx);
break;
}
@ -259,6 +258,8 @@ int execute(const cmd_t* cmd)
return -1;
}
tsk_safeobj_lock(ctx);
switch(cmd->type){
case cmd_audio:
{
@ -323,6 +324,18 @@ int execute(const cmd_t* cmd)
}
break;
}
case cmd_options:
{
TSK_DEBUG_INFO("command=options");
if((sid = options_handle_cmd(cmd->type, cmd->opts)) != TSIP_SSESSION_INVALID_ID){
if(cmd->sidparam){
tsk_itoa(sid, &istr);
update_param(cmd->sidparam, istr);
}
}
break;
}
case cmd_publish:
{
TSK_DEBUG_INFO("command=publish");
@ -360,6 +373,9 @@ int execute(const cmd_t* cmd)
{
const opt_t* opt;
double seconds;
tsk_safeobj_unlock(ctx); /* beacuse of callback function */
if((opt = opt_get_by_type(cmd->opts, opt_sec)) && !tsk_strnullORempty(opt->value)){ /* --sec option */
seconds = strtod(opt->value, tsk_null); /* strtod() is better than atof() */
if(seconds<=0){
@ -374,7 +390,7 @@ int execute(const cmd_t* cmd)
else{
TSK_DEBUG_WARN("++sleep need --sec option.");
}
break;
return 0; /* bail: will unlock again */
}
case cmd_sms:
{
@ -417,5 +433,7 @@ int execute(const cmd_t* cmd)
}
bail:
tsk_safeobj_unlock(ctx);
return ret;
}

View File

@ -5,10 +5,10 @@
#++sn --path ./core-colibria.sn
# Ericsson
#++sn --path ./core-ericsson.sn
++sn --path ./core-ericsson.sn
# Inexbee
++sn --path ./core-inexbee.sn
#++sn --path ./core-inexbee.sn
# Micromethod
#++sn --path ./core-micromethod.sn

View File

@ -97,7 +97,7 @@ tsip_ssession_id_t message_handle_cmd(cmd_type_t cmd, const opts_L_t* opts)
tsip_ssession_id_t id = TSIP_SSESSION_INVALID_ID;
if(!(session = session_handle_cmd(cmd, opts))){
return -1;
goto bail;
}
else{
id = tsip_ssession_get_id(session->handle);
@ -200,6 +200,7 @@ done:
break;
}
bail:
return id;
}

114
trunk/tinyDEMO/options.c Normal file
View File

@ -0,0 +1,114 @@
/*
* Copyright (C) 2009 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)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.
*
*/
#include "options.h"
extern ctx_t* ctx;
int options_hack_aor(const tsip_response_t* resp);
int options_handle_event(const tsip_event_t *sipevent)
{
const tsip_options_event_t* opt_event = TSIP_OPTIONS_EVENT(sipevent);
const session_t* session;
tsip_ssession_id_t sid;
/* Find associated session */
sid = tsip_ssession_get_id(sipevent->ss);
if(!(session = session_get_by_sid(ctx->sessions, sid))){
TSK_DEBUG_WARN("Failed to match session event.");
return -1;
}
switch(opt_event->type){
case tsip_i_options: /* incoming OPTIONS */
case tsip_ai_options: /* answer to incoming OPTIONS */
case tsip_o_options: /* outgoing OPTIONS */
break;
case tsip_ao_options: /* answer to outgoing OPTIONS */
#if HACK_AOR
if(TSIP_MESSAGE_IS_RESPONSE(sipevent->sipmessage)){
options_hack_aor(sipevent->sipmessage);
}
#endif
break;
}
return 0;
}
tsip_ssession_id_t options_handle_cmd(cmd_type_t cmd, const opts_L_t* opts)
{
const session_t* session = tsk_null;
tsip_ssession_id_t id = TSIP_SSESSION_INVALID_ID;
if(!(session = session_handle_cmd(cmd, opts))){
goto bail;
}
else{
id = tsip_ssession_get_id(session->handle);
}
/* Execute command */
switch(cmd){
case cmd_options:
{ /* Send SIP OPTIONS */
tsip_action_handle_t* action_config = action_get_config(opts);
tsip_action_OPTIONS(session->handle,
TSIP_ACTION_SET_CONFIG(action_config),
TSIP_ACTION_SET_NULL());
TSK_OBJECT_SAFE_FREE(action_config);
break;
}
default:
/* already handled by session_handle_cmd() */
break;
}
bail:
return id;
}
/* used to hack the AOR. useful for devices behind NATs or emulators (e.g. ANDROID) */
int options_hack_aor(const tsip_response_t* resp)
{
int32_t rport;
if(resp && resp->firstVia){
if(resp->firstVia->rport <=0){
const tsk_param_t* param;
/* Ericsson SDS
==> Via: SIP/2.0/TCP 192.168.0.12:49744;rport;branch=z9hG4bK1273100904048;received_port_ext=49744;received=192.168.0.12 */
if((param = tsk_params_get_param_by_name(TSIP_HEADER_PARAMS(resp->firstVia), "received_port_ext"))){
rport = (int32_t)atoi(param->value);
}
}
else{
rport = resp->firstVia->rport;
}
tsip_stack_set(ctx->stack,
TSIP_STACK_SET_AOR(resp->firstVia->received, rport),
TSIP_STACK_SET_NULL());
return 0;
}
return -1;
}

36
trunk/tinyDEMO/options.h Normal file
View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2009 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)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.
*
*/
#if !defined(TINYDEMO_OPTIONS_H)
#define TINYDEMO_OPTIONS_H
#include "demo_config.h"
#include "common.h"
_BEGIN_DECLS
int options_handle_event(const tsip_event_t *sipevent);
tsip_ssession_id_t options_handle_cmd(cmd_type_t cmd, const opts_L_t* opts);
_END_DECLS
#endif /* TINYDEMO_OPTIONS_H */

View File

@ -91,7 +91,7 @@ tsip_ssession_id_t publish_handle_cmd(cmd_type_t cmd, const opts_L_t* opts)
const opt_t* opt;
if(!(session = session_handle_cmd(cmd, opts))){
return -1;
goto bail;
}
else{
id = tsip_ssession_get_id(session->handle);
@ -120,5 +120,6 @@ tsip_ssession_id_t publish_handle_cmd(cmd_type_t cmd, const opts_L_t* opts)
break;
}
bail:
return id;
}

View File

@ -92,7 +92,7 @@ tsip_ssession_id_t register_handle_cmd(cmd_type_t cmd, const opts_L_t* opts)
const opt_t* opt;
if(!(session = session_handle_cmd(cmd, opts))){
return -1;
goto bail;
}
else{
id = tsip_ssession_get_id(session->handle);
@ -124,5 +124,6 @@ tsip_ssession_id_t register_handle_cmd(cmd_type_t cmd, const opts_L_t* opts)
break;
}
bail:
return id;
}

View File

@ -103,7 +103,7 @@ tsip_ssession_id_t subscribe_handle_cmd(cmd_type_t cmd, const opts_L_t* opts)
const opt_t* opt;
if(!(session = session_handle_cmd(cmd, opts))){
return -1;
goto bail;
}
else{
id = tsip_ssession_get_id(session->handle);
@ -132,5 +132,6 @@ tsip_ssession_id_t subscribe_handle_cmd(cmd_type_t cmd, const opts_L_t* opts)
break;
}
bail:
return id;
}

View File

@ -200,6 +200,10 @@
RelativePath=".\message.c"
>
</File>
<File
RelativePath=".\options.c"
>
</File>
<File
RelativePath=".\publish.c"
>
@ -246,6 +250,10 @@
RelativePath=".\message.h"
>
</File>
<File
RelativePath=".\options.h"
>
</File>
<File
RelativePath=".\publish.h"
>

View File

@ -188,8 +188,7 @@ tnet_dhcp_reply_t* tnet_dhcp_send_request(tnet_dhcp_ctx_t* ctx, tnet_dhcp_reques
/* Receive pending data */
data = tsk_calloc(len, sizeof(uint8_t));
if((ret = tnet_sockfd_recv(localsocket4->fd, data, len, 0))<0)
{
if((ret = tnet_sockfd_recv(localsocket4->fd, data, len, 0))<0){
TSK_FREE(data);
TNET_PRINT_LAST_ERROR("Failed to receive DHCP dgrams.");
@ -197,7 +196,7 @@ tnet_dhcp_reply_t* tnet_dhcp_send_request(tnet_dhcp_ctx_t* ctx, tnet_dhcp_reques
}
/* Parse the incoming response. */
reply = tnet_dhcp_message_deserialize(ctx, data, len);
reply = tnet_dhcp_message_deserialize(ctx, data, (size_t)ret);
TSK_FREE(data);
if(reply)

View File

@ -142,15 +142,13 @@ tnet_dhcp6_reply_t* tnet_dhcp6_send_request(const tnet_dhcp6_ctx_t* ctx, tnet_dh
void* data = 0;
/* Check how how many bytes are pending */
if((ret = tnet_ioctlt(localsocket6->fd, FIONREAD, &len))<0)
{
if((ret = tnet_ioctlt(localsocket6->fd, FIONREAD, &len))<0){
goto next_iface;
}
/* Receive pending data */
data = tsk_calloc(len, sizeof(uint8_t));
if((ret = tnet_sockfd_recv(localsocket6->fd, data, len, 0))<0)
{
if((ret = tnet_sockfd_recv(localsocket6->fd, data, len, 0))<0){
TSK_FREE(data);
TNET_PRINT_LAST_ERROR("Failed to receive DHCP dgrams.");
@ -158,7 +156,7 @@ tnet_dhcp6_reply_t* tnet_dhcp6_send_request(const tnet_dhcp6_ctx_t* ctx, tnet_dh
}
/* Parse the incoming response. */
reply = tnet_dhcp6_message_deserialize(ctx, data, len);
reply = tnet_dhcp6_message_deserialize(ctx, data, (size_t)ret);
TSK_FREE(data);
if(reply)

View File

@ -387,7 +387,7 @@ tnet_dns_response_t *tnet_dns_resolve(tnet_dns_ctx_t* ctx, const char* qname, tn
}
/* Parse the incoming response. */
response = tnet_dns_message_deserialize(data, len);
response = tnet_dns_message_deserialize(data, (size_t)ret);
TSK_FREE(data);
if(response)

View File

@ -199,7 +199,7 @@ tnet_stun_response_t* tnet_stun_send_unreliably(tnet_fd_t localFD, uint16_t RTO,
}
/* Parse the incoming response. */
response = tnet_stun_message_deserialize(data, len);
response = tnet_stun_message_deserialize(data, (size_t)ret);
TSK_FREE(data);
if(response){

View File

@ -516,7 +516,7 @@ void *tnet_transport_mainthread(void *param)
if(active_socket->tlshandle){
int isEncrypted;
size_t tlslen = len;
if(!(ret = tnet_tls_socket_recv(active_socket->tlshandle, &buffer, &tlslen, &isEncrypted))){
if((ret = tnet_tls_socket_recv(active_socket->tlshandle, &buffer, &tlslen, &isEncrypted)) == 0){
if(isEncrypted){
TSK_FREE(buffer);
continue;
@ -524,19 +524,15 @@ void *tnet_transport_mainthread(void *param)
len = tlslen;
}
}
else if((ret = recv(active_socket->fd, buffer, len, 0)) < 0)
{
else if((ret = tnet_sockfd_recv(active_socket->fd, buffer, len, 0)) < 0){
TSK_FREE(buffer);
//if(tnet_geterrno() == TNET_ERROR_WOULDBLOCK)
{
//TSK_DEBUG_INFO("WSAEWOULDBLOCK error for READ SSESSION");
}
//else
{
removeSocket(i, context);
TNET_PRINT_LAST_ERROR("recv have failed.");
continue;
}
removeSocket(i, context);
TNET_PRINT_LAST_ERROR("recv have failed.");
continue;
}
else if(len != (size_t)ret){ /* useless test */
len = (size_t)ret;
}

View File

@ -55,7 +55,7 @@ void test_sockets()
//}
if(!(test = tnet_sockaddr_init("ipv6.google.com", 80, type, &to))){
test = tnet_sockfd_connetto(tcp_socket->fd, (const struct sockaddr_storage *)&to);
test = tnet_sockfd_connectto(tcp_socket->fd, (const struct sockaddr_storage *)&to);
}
TSK_OBJECT_SAFE_FREE(tcp_socket);

View File

@ -474,4 +474,4 @@ _again:
bail:
return sdp_msg;
}
}

View File

@ -15,8 +15,10 @@ OBJS = \
src/tsip_uri.o\
### api
OBJS += src/api/tsip_api_invite.o\
OBJS += src/api/tsip_api_common.o\
src/api/tsip_api_invite.o\
src/api/tsip_api_message.o\
src/api/tsip_api_options.o\
src/api/tsip_api_publish.o\
src/api/tsip_api_register.o\
src/api/tsip_api_subscribe.o
@ -33,6 +35,7 @@ OBJS += src/dialogs/tsip_dialog.o\
src/dialogs/tsip_dialog_invite.server.o\
src/dialogs/tsip_dialog_layer.o\
src/dialogs/tsip_dialog_message.o\
src/dialogs/tsip_dialog_options.o\
src/dialogs/tsip_dialog_publish.client.o\
src/dialogs/tsip_dialog_register.client.o\
src/dialogs/tsip_dialog_register.server.o\

View File

@ -52,6 +52,7 @@
#include "tinysip/api/tsip_api_invite.h"
#include "tinysip/api/tsip_api_message.h"
#include "tinysip/api/tsip_api_options.h"
#include "tinysip/api/tsip_api_publish.h"
#include "tinysip/api/tsip_api_register.h"
#include "tinysip/api/tsip_api_subscribe.h"

View File

@ -47,10 +47,12 @@ typedef enum tsip_options_event_type_e
}
tsip_options_event_type_t;
/**< Event from SIP OPTIONS dialog */
typedef struct tsip_options_event_e
{
TSIP_DECLARE_EVENT;
//! the type of the event
tsip_options_event_type_t type;
}
tsip_options_event_t;

View File

@ -37,6 +37,7 @@ TSIP_BEGIN_DECLS
#define TSIP_DIALOG_REGISTER(self) ((tsip_dialog_register_t*)(self))
/**< SIP REGISTER dialog */
typedef struct tsip_dialog_register
{
TSIP_DECLARE_DIALOG;

View File

@ -176,12 +176,12 @@ TINYSIP_API const char *tsip_header_get_nameex(const tsip_header_t *self);
TINYSIP_API char tsip_header_get_param_separator(const tsip_header_t *self);
TINYSIP_API int tsip_header_tostring(const tsip_header_t *self, tsk_buffer_t *output);
#define TSIP_HEADER_HAVE_PARAM(self, name) tsk_params_have_param(self ? TSIP_HEADER(self)->params : 0, name)
#define TSIP_HEADER_ADD_PARAM(self, name, value) tsk_params_add_param(self ? &TSIP_HEADER(self)->params : 0, name, value)
#define TSIP_HEADER_REMOVE_PARAM(self, name) tsk_params_remove_param(self ? TSIP_HEADER(self)->params : 0, name)
#define TSIP_HEADER_GET_PARAM_BY_NAME(self, name) tsk_params_get_param_by_name(self ? TSIP_HEADER(self)->params : 0, name)
#define TSIP_HEADER_GET_PARAM_VALUE(self, name) tsk_params_get_param_value(self ? TSIP_HEADER(self)->params : 0, name)
#define TSIP_HEADER_GET_PARAM_VALUE_AS_INT(self, name) tsk_params_get_param_value_as_int(self ? TSIP_HEADER(self)->params : 0, name)
#define TSIP_HEADER_HAVE_PARAM(self, name) tsk_params_have_param(self ? TSIP_HEADER(self)->params : tsk_null, name)
#define TSIP_HEADER_ADD_PARAM(self, name, value) tsk_params_add_param(self ? &TSIP_HEADER(self)->params : tsk_null, name, value)
#define TSIP_HEADER_REMOVE_PARAM(self, name) tsk_params_remove_param(self ? TSIP_HEADER(self)->params : tsk_null, name)
#define TSIP_HEADER_GET_PARAM_BY_NAME(self, name) tsk_params_get_param_by_name(self ? TSIP_HEADER(self)->params : tsk_null, name)
#define TSIP_HEADER_GET_PARAM_VALUE(self, name) tsk_params_get_param_value(self ? TSIP_HEADER(self)->params : tsk_null, name)
#define TSIP_HEADER_GET_PARAM_VALUE_AS_INT(self, name) tsk_params_get_param_value_as_int(self ? TSIP_HEADER(self)->params : tsk_null, name)
TSIP_END_DECLS

View File

@ -230,7 +230,7 @@ typedef struct tsip_message_s
/*== */
tnet_fd_t sockfd;
unsigned update:1;
tsk_bool_t update;
}
tsip_message_t;

View File

@ -71,6 +71,7 @@ typedef enum tsip_stack_param_type_e
pname_realm,
pname_local_ip,
pname_local_port,
pname_aor,
pname_discovery_naptr,
pname_discovery_dhcp,
pname_proxy_cscf,
@ -175,7 +176,7 @@ tsip_stack_param_type_t;
* TSIP_STACK_SET_NULL());
* @endcode
*
* @sa @ref TSIP_STACK_SET_LOCAL_PORT()
* @sa @ref TSIP_STACK_SET_LOCAL_PORT()<br>@ref TSIP_STACK_SET_AOR()
*/
/**@ingroup tsip_stack_group
* @def TSIP_STACK_SET_LOCAL_PORT
@ -187,8 +188,24 @@ tsip_stack_param_type_t;
* TSIP_STACK_SET_NULL());
* @endcode
*
* @sa @ref TSIP_STACK_SET_LOCAL_IP()
* @sa @ref TSIP_STACK_SET_LOCAL_IP()<br>@ref TSIP_STACK_SET_AOR()
*/
/**@ingroup tsip_stack_group
* @def TSIP_STACK_SET_AOR
* Sets the SIP AOR to use for all outgoing requests.
* @param IP_STR The IP address. Should be numeric IP string. e.g. 192.168.0.16.
* Will be ignored if null or empty.
* @param PORT_UINT Port number. Should be between 0x0400 and 0xFFFF.
* Will be ignored if equals to zero.
* @code
* int ret = tsip_stack_set(stack,
* TSIP_STACK_SET_AOR("fe80::", 1234),
* TSIP_STACK_SET_NULL());
* @endcode
*
* @sa @ref TSIP_STACK_SET_LOCAL_IP()<br>@ref TSIP_STACK_SET_LOCAL_PORT()
*/
/**@ingroup tsip_stack_group
* @def TSIP_STACK_SET_DISCOVERY_NAPTR
* Whether to use DNS NAPTR for Proxy-CSCF discovery. Default is false. However, if the Proxy-CSCF IP address
@ -234,6 +251,7 @@ tsip_stack_param_type_t;
#define TSIP_STACK_SET_REALM(URI_STR) pname_realm, (const char*)URI_STR
#define TSIP_STACK_SET_LOCAL_IP(IP_STR) pname_local_ip, (const char*)IP_STR
#define TSIP_STACK_SET_LOCAL_PORT(PORT_UINT) pname_local_port, (unsigned)PORT_UINT
#define TSIP_STACK_SET_AOR(IP_STR, PORT_UINT) pname_aor, (const char*)IP_STR, (unsigned)PORT_UINT
#define TSIP_STACK_SET_DISCOVERY_NAPTR(ENABLED_BOOL) pname_discovery_naptr, (tsk_bool_t)ENABLED_BOOL
#define TSIP_STACK_SET_DISCOVERY_DHCP(ENABLED_BOOL) pname_discovery_dhcp, (tsk_bool_t)ENABLED_BOOL
#define TSIP_STACK_SET_PROXY_CSCF(FQDN_STR, PORT_UINT, TRANSPORT_STR, IP_VERSION_STR) pname_proxy_cscf, (const char*)FQDN_STR, (unsigned)PORT_UINT, (const char*)TRANSPORT_STR, (const char*)IP_VERSION_STR
@ -396,6 +414,12 @@ typedef struct tsip_stack_s
tnet_socket_type_t proxy_cscf_type;
tsip_uri_t *realm;
//! IP adddress and port to use as AOR (user-defined)
struct{
char* ip;
tnet_port_t port;
} aor;
tsk_bool_t discovery_naptr;
tsk_bool_t discovery_dhcp;

View File

@ -35,11 +35,12 @@
#include "tsk_debug.h"
/* Internal functions */
extern tsip_action_t* tsip_action_create_2(tsip_action_type_t type, va_list* app);
extern tsip_action_t* _tsip_action_create(tsip_action_type_t type, va_list* app);
/* Local functions */
int _tsip_action_ANY(const tsip_ssession_handle_t *ss, tsip_action_type_t type, va_list* app);
/* internal function used to execute any user action */
/* internal function used to execute any user action
* can only handle session with dialogs */
int _tsip_action_ANY(const tsip_ssession_handle_t *ss, tsip_action_type_t type, va_list* app)
{
int ret = -1;
@ -59,7 +60,7 @@ int _tsip_action_ANY(const tsip_ssession_handle_t *ss, tsip_action_type_t type,
}
/* execute action */
if((action = tsip_action_create_2(type, app))){
if((action = _tsip_action_create(type, app))){
ret = tsip_ssession_handle(_ss, action);
TSK_OBJECT_SAFE_FREE(action);
}

View File

@ -39,7 +39,7 @@
#define TSIP_MESSAGE_EVENT_CREATE( type) tsk_object_new(tsip_message_event_def_t, type)
extern tsip_action_t* tsip_action_create_2(tsip_action_type_t type, va_list* app);
extern tsip_action_t* _tsip_action_create(tsip_action_type_t type, va_list* app);
int tsip_message_event_signal(tsip_message_event_type_t type, struct tsip_stack_s *stack, tsip_ssession_handle_t* SSESSION, short status_code, const char *phrase, const tsip_message_t* sipmessage)
{
@ -72,7 +72,7 @@ int tsip_action_MESSAGE(const tsip_ssession_handle_t *ss, ...)
/* action */
va_start(ap, ss);
if((action = tsip_action_create_2(atype_message_send, &ap))){
if((action = _tsip_action_create(atype_message_send, &ap))){
if(!(dialog = tsip_dialog_layer_find_by_ss(_ss->stack->layer_dialog, ss))){
dialog = tsip_dialog_layer_new(_ss->stack->layer_dialog, tsip_dialog_MESSAGE, ss);
}

View File

@ -39,7 +39,7 @@
#define TSIP_OPTIONS_EVENT_CREATE( type) tsk_object_new(tsip_options_event_def_t, type)
extern tsip_action_t* tsip_action_create_2(tsip_action_type_t type, va_list* app);
extern tsip_action_t* _tsip_action_create(tsip_action_type_t type, va_list* app);
int tsip_options_event_signal(tsip_options_event_type_t type, struct tsip_stack_s *stack, tsip_ssession_handle_t* SSESSION, short status_code, const char *phrase, const tsip_message_t* sipmessage)
{
@ -71,7 +71,7 @@ int tsip_action_OPTIONS(const tsip_ssession_handle_t *ss, ...)
}
va_start(ap, ss);
if((action = tsip_action_create_2(atype_options_send, &ap))){
if((action = _tsip_action_create(atype_options_send, &ap))){
if(!(dialog = tsip_dialog_layer_find_by_ss(_ss->stack->layer_dialog, ss))){
dialog = tsip_dialog_layer_new(_ss->stack->layer_dialog, tsip_dialog_OPTIONS, ss);
}

View File

@ -39,7 +39,7 @@
#define TSIP_PUBLISH_EVENT_CREATE( type) tsk_object_new(tsip_publish_event_def_t, type)
extern tsip_action_t* tsip_action_create_2(tsip_action_type_t type, va_list* app);
extern tsip_action_t* _tsip_action_create(tsip_action_type_t type, va_list* app);
int tsip_publish_event_signal(tsip_publish_event_type_t type, struct tsip_stack_s *stack, tsip_ssession_handle_t* SSESSION, short status_code, const char *phrase, const tsip_message_t* sipmessage)
{
@ -71,7 +71,7 @@ int tsip_action_PUBLISH(const tsip_ssession_handle_t *ss, ...)
}
va_start(ap, ss);
if((action = tsip_action_create_2(atype_publish, &ap))){
if((action = _tsip_action_create(atype_publish, &ap))){
if(!(dialog = tsip_dialog_layer_find_by_ss(_ss->stack->layer_dialog, ss))){
dialog = tsip_dialog_layer_new(_ss->stack->layer_dialog, tsip_dialog_PUBLISH, ss);
}
@ -104,7 +104,7 @@ int tsip_action_UNPUBLISH(const tsip_ssession_handle_t *ss, ...)
}
va_start(ap, ss);
if((action = tsip_action_create_2(atype_unpublish, &ap))){
if((action = _tsip_action_create(atype_unpublish, &ap))){
ret = tsip_ssession_handle(ss, action);
TSK_OBJECT_SAFE_FREE(action);
}

View File

@ -40,8 +40,11 @@
#define TSIP_REGISTER_EVENT_CREATE( type) tsk_object_new(tsip_register_event_def_t, type)
extern tsip_action_t* tsip_action_create_2(tsip_action_type_t type, va_list* app);
/* Internal functions */
extern tsip_action_t* _tsip_action_create(tsip_action_type_t type, va_list* app);
extern int _tsip_action_ANY(const tsip_ssession_handle_t *ss, tsip_action_type_t type, va_list* app);
/* internal function used to signal evant from REGISTER dialog to user app */
int tsip_register_event_signal(tsip_register_event_type_t type, struct tsip_stack_s *stack, tsip_ssession_t* ss, short status_code, const char *phrase, const tsip_message_t* sipmessage)
{
tsip_register_event_t* sipevent = TSIP_REGISTER_EVENT_CREATE(type);
@ -52,7 +55,15 @@ int tsip_register_event_signal(tsip_register_event_type_t type, struct tsip_stac
return 0;
}
/** Sends SIP REGISTER or reREGISTER request. */
/**@ingroup tsip_action_group
* Sends SIP REGISTER request. If the session is already established, the same dialog will
* be used (refresh).
* @param ss The SIP Session managing the REGISTER dialog.
* @param ... Any TSIP_ACTION_SET_*() macros. e.g. @ref TSIP_ACTION_SET_HEADER().
* MUST always ends with @ref TSIP_ACTION_SET_NULL().
* @retval Zero if succeed and non-zero error code otherwise.
* @sa @ref tsip_action_UNREGISTER
*/
int tsip_action_REGISTER(const tsip_ssession_handle_t *ss, ...)
{
const tsip_ssession_t* _ss;
@ -72,14 +83,15 @@ int tsip_action_REGISTER(const tsip_ssession_handle_t *ss, ...)
return -2;
}
/* performs action */
va_start(ap, ss);
if((action = tsip_action_create_2(atype_register, &ap))){
if((action = _tsip_action_create(atype_register, &ap))){
if(!(dialog = tsip_dialog_layer_find_by_ss(_ss->stack->layer_dialog, _ss))){
dialog = tsip_dialog_layer_new(_ss->stack->layer_dialog, tsip_dialog_REGISTER, _ss);
}
ret = tsip_dialog_fsm_act(dialog, action->type, tsk_null, action);
tsk_object_unref(dialog);
TSK_OBJECT_SAFE_FREE(dialog);
TSK_OBJECT_SAFE_FREE(action);
}
va_end(ap);
@ -87,32 +99,26 @@ int tsip_action_REGISTER(const tsip_ssession_handle_t *ss, ...)
return ret;
}
/**@ingroup tsip_action_group
* Sends SIP unREGISTER request (expires=0). The session should be already established.
* @param ss The SIP Session managing the REGISTER dialog.
* @param ... Any TSIP_ACTION_SET_*() macros. e.g. @ref TSIP_ACTION_SET_HEADER().
* MUST always ends with @ref TSIP_ACTION_SET_NULL().
* @retval Zero if succeed and non-zero error code otherwise.
* @sa @ref tsip_action_REGISTER
*/
int tsip_action_UNREGISTER(const tsip_ssession_handle_t *ss, ...)
{
const tsip_ssession_t* _ss;
va_list ap;
tsip_action_t* action;
int ret = -1;
if(!(_ss = ss) || !_ss->stack){
TSK_DEBUG_ERROR("Invalid parameter.");
return ret;
}
/* Checks if the stack is running */
if(!TSK_RUNNABLE(_ss->stack)->running){
TSK_DEBUG_ERROR("Stack not running.");
return -2;
}
va_start(ap, ss);
if((action = tsip_action_create_2(atype_unregister, &ap))){
ret = tsip_ssession_handle(_ss, action);
TSK_OBJECT_SAFE_FREE(action);
}
va_end(ap);
return 0;
int ret = -1;
va_list ap;
va_start(ap, ss);
if((ret = _tsip_action_ANY(ss, atype_unregister, &ap))){
TSK_DEBUG_ERROR("unREGISTER() failed.");
}
va_end(ap);
return ret;
}

View File

@ -40,7 +40,7 @@
#define TSIP_SUBSCRIBE_EVENT_CREATE( type) tsk_object_new(tsip_subscribe_event_def_t, type)
extern tsip_action_t* tsip_action_create_2(tsip_action_type_t type, va_list* app);
extern tsip_action_t* _tsip_action_create(tsip_action_type_t type, va_list* app);
int tsip_subscribe_event_signal(tsip_subscribe_event_type_t type, struct tsip_stack_s *stack, tsip_ssession_t* ss, short status_code, const char *phrase, const tsip_message_t* sipmessage)
{
@ -72,7 +72,7 @@ int tsip_action_SUBSCRIBE(const tsip_ssession_handle_t *ss, ...)
}
va_start(ap, ss);
if((action = tsip_action_create_2(atype_subscribe, &ap))){
if((action = _tsip_action_create(atype_subscribe, &ap))){
if(!(dialog = tsip_dialog_layer_find_by_ss(_ss->stack->layer_dialog, ss))){
dialog = tsip_dialog_layer_new(_ss->stack->layer_dialog, tsip_dialog_SUBSCRIBE, ss);
}
@ -105,7 +105,7 @@ int tsip_action_UNSUBSCRIBE(const tsip_ssession_handle_t *ss, ...)
}
va_start(ap, ss);
if((action = tsip_action_create_2(atype_unsubscribe, &ap))){
if((action = _tsip_action_create(atype_unsubscribe, &ap))){
ret = tsip_ssession_handle(ss, action);
TSK_OBJECT_SAFE_FREE(action);
}

View File

@ -59,7 +59,7 @@ extern tsip_uri_t* tsip_stack_get_contacturi(const tsip_stack_t *self, const cha
tsip_request_t *tsip_dialog_request_new(const tsip_dialog_t *self, const char* method)
{
tsip_request_t *request = 0;
tsip_request_t *request = tsk_null;
tsip_uri_t *to_uri, *from_uri, *request_uri;
const char *call_id;
int copy_routes_start = -1; /* NONE */
@ -157,7 +157,7 @@ tsip_request_t *tsip_dialog_request_new(const tsip_dialog_t *self, const char* m
request = tsip_request_new(method, request_uri, from_uri, to_uri, call_id, self->cseq_value);
request->To->tag = tsk_strdup(self->tag_remote);
request->From->tag = tsk_strdup(self->tag_local);
request->update = 1; /* No signal that the message should be updated by the transport layer (Contact, SigComp, IPSec, ...) */
request->update = tsk_true; /* No signal that the message should be updated by the transport layer (Contact, SigComp, IPSec, ...) */
/*
@ -185,9 +185,9 @@ tsip_request_t *tsip_dialog_request_new(const tsip_dialog_t *self, const char* m
default:
{
char* contact = 0;
char* contact = tsk_false;
tsip_header_Contacts_L_t *hdr_contacts;
tsk_sprintf(&contact, "m: <%s:%s@%s:%d>;expires=%d\r\n", /*self->issecure*/0?"sips":"sip", from_uri->user_name, "127.0.0.1", 5060, TSK_TIME_MS_2_S(self->expires));
tsk_sprintf(&contact, "m: <%s:%s@%s:%d>;expires=%d\r\n", /*self->issecure*/tsk_false?"sips":"sip", from_uri->user_name, "127.0.0.1", 5060, TSK_TIME_MS_2_S(self->expires));
hdr_contacts = tsip_header_Contact_parse(contact, tsk_strlen(contact));
if(!TSK_LIST_IS_EMPTY(hdr_contacts)){
request->Contact = tsk_object_ref(hdr_contacts->head->data);

View File

@ -31,6 +31,7 @@
#include "tinysip/dialogs/tsip_dialog_invite.h"
#include "tinysip/dialogs/tsip_dialog_message.h"
#include "tinysip/dialogs/tsip_dialog_options.h"
#include "tinysip/dialogs/tsip_dialog_publish.h"
#include "tinysip/dialogs/tsip_dialog_register.h"
#include "tinysip/dialogs/tsip_dialog_subscribe.h"
@ -206,6 +207,10 @@ tsip_dialog_t* tsip_dialog_layer_new(tsip_dialog_layer_t *self, tsip_dialog_type
}
case tsip_dialog_OPTIONS:
{
if((dialog = (tsip_dialog_t*)tsip_dialog_options_create(ss))){
ret = tsk_object_ref(dialog);
tsk_list_push_back_data(self->dialogs, (void**)&dialog);
}
break;
}
case tsip_dialog_PUBLISH:

View File

@ -37,22 +37,25 @@
#include "tsk_buffer.h"
#include "tsk_debug.h"
/* creates new SIP transport */
tsip_transport_t* tsip_transport_create(tsip_stack_t* stack, const char* host, tnet_port_t port, tnet_socket_type_t type, const char* description)
{
return tsk_object_new(tsip_transport_def_t, stack, host, port, type, description);
}
/* add Via header using the transport config */
int tsip_transport_addvia(const tsip_transport_t* self, const char *branch, tsip_message_t *msg)
{
tnet_ip_t ip;
tnet_port_t port;
int ret;
if(tsip_transport_get_ip_n_port(self, &ip, &port)){
return -1;
if((ret = tsip_transport_get_ip_n_port(self, &ip, &port))){
return ret;
}
if(!msg->firstVia)
{
/* is there a Via header? */
if(!msg->firstVia){
/* RFC 3261 - 18.1.1 Sending Requests
Before a request is sent, the client transport MUST insert a value of
the "sent-by" field into the Via header field. This field contains
@ -64,11 +67,13 @@ int tsip_transport_addvia(const tsip_transport_t* self, const char *branch, tsip
*/
msg->firstVia = tsip_header_Via_create(TSIP_HEADER_VIA_PROTO_NAME_DEFAULT, TSIP_HEADER_VIA_PROTO_VERSION_DEFAULT,
self->via_protocol, ip, port);
TSIP_HEADER_ADD_PARAM(TSIP_HEADER(msg->firstVia), "rport", 0);
TSIP_HEADER_ADD_PARAM(TSIP_HEADER(msg->firstVia), "rport", tsk_null);
}
/* updates the branch */
tsk_strupdate(&msg->firstVia->branch, branch);
/* multicast case */
if(tsk_false){
/* RFC 3261 - 18.1.1 Sending Requests (FIXME)
A client that sends a request to a multicast address MUST add the
@ -87,16 +92,19 @@ int tsip_transport_addvia(const tsip_transport_t* self, const char *branch, tsip
return 0;
}
/* update the entire message (AOR, IPSec headers, SigComp, ....) */
int tsip_transport_msg_update(const tsip_transport_t* self, tsip_message_t *msg)
{
tnet_ip_t ip;
tnet_port_t port;
int ret = 0;
/* already updtated (e.g. retrans)? */
if(!msg->update){
return 0;
}
/* retrieves the transport ip address and port */
if(tsip_transport_get_ip_n_port(self, &ip, &port)){
return -1;
}
@ -104,13 +112,23 @@ int tsip_transport_msg_update(const tsip_transport_t* self, tsip_message_t *msg)
/* Host and port */
if(msg->Contact && msg->Contact->uri){
tsk_strupdate(&(msg->Contact->uri->scheme), self->scheme);
tsk_strupdate(&(msg->Contact->uri->host), ip);
msg->Contact->uri->port = port;
msg->Contact->uri->host_type = TNET_SOCKET_TYPE_IS_IPV6(self->type) ? host_ipv6 : host_ipv4;
if(!tsk_strnullORempty(self->stack->network.aor.ip)){ /* user supplied his own IP address? */
tsk_strupdate(&(msg->Contact->uri->host), self->stack->network.aor.ip);
}
else{ /* the ip address from the transport */
tsk_strupdate(&(msg->Contact->uri->host), ip);
}
if(self->stack->network.aor.port){ /* user supplied his own port? */
msg->Contact->uri->port = self->stack->network.aor.port;
}
else{ /* use port from the transport */
msg->Contact->uri->port = port;
}
msg->Contact->uri->host_type = TNET_SOCKET_TYPE_IS_IPV6(self->type) ? host_ipv6 : host_ipv4; /* for serializer ...who know? */
tsk_params_add_param(&msg->Contact->uri->params, "transport", self->protocol);
}
/* IPSec headers */
/* IPSec headers (Security-Client, Security-Verify, Sec-Agree ...) */
if(TNET_SOCKET_TYPE_IS_IPSEC(self->type)){
ret = tsip_transport_ipsec_updateMSG(TSIP_TRANSPORT_IPSEC(self), msg);
}
@ -118,11 +136,12 @@ int tsip_transport_msg_update(const tsip_transport_t* self, tsip_message_t *msg)
/* SigComp */
msg->update = 0; /* To avoid update of retrans. msg */
msg->update = tsk_false; /* To avoid to update retrans. */
return ret;
}
/* sets TLS certificates */
int tsip_transport_set_tlscerts(tsip_transport_t *self, const char* ca, const char* pbk, const char* pvk)
{
tnet_transport_t *transport = self->net_transport;
@ -139,6 +158,7 @@ int tsip_transport_set_tlscerts(tsip_transport_t *self, const char* ca, const ch
return 0;
}
/* sends a request */
size_t tsip_transport_send(const tsip_transport_t* self, const char *branch, tsip_message_t *msg, const char* destIP, int32_t destPort)
{
size_t ret = 0;
@ -146,7 +166,7 @@ size_t tsip_transport_send(const tsip_transport_t* self, const char *branch, tsi
{
tsk_buffer_t *buffer = tsk_null;
/* Add Via */
/* Add Via and update AOR, IPSec headers, SigComp ...*/
if(TSIP_MESSAGE_IS_REQUEST(msg) && !TSIP_REQUEST_IS_CANCEL(msg) && !TSIP_REQUEST_IS_ACK(msg)){
tsip_transport_addvia(self, branch, msg);
tsip_transport_msg_update(self, msg);

View File

@ -151,13 +151,20 @@ int __tsip_stack_set(tsip_stack_t *self, va_list* app)
}
case pname_local_port:
{ /* (unsigned)PORT_UINT */
unsigned PORT_UINT = (tnet_port_t)va_arg(*app, unsigned);
if(PORT_UINT>0x00 && PORT_UINT <=0xFFFF){
self->network.local_port = (tnet_port_t)PORT_UINT;
self->network.local_port = (tnet_port_t)va_arg(*app, unsigned);
break;
}
case pname_aor:
{ /* (const char*)IP_STR, (unsigned)PORT_UINT */
const char* IP_STR = va_arg(*app, const char*);
tnet_port_t PORT_UINT = (tnet_port_t)va_arg(*app, unsigned);
if(!tsk_strnullORempty(IP_STR)){
tsk_strupdate(&self->network.aor.ip, IP_STR);
}
else{
TSK_DEBUG_WARN("%u is invalid for a port number", PORT_UINT);
if(PORT_UINT){
self->network.aor.port = PORT_UINT;
}
break;
}
case pname_discovery_naptr:
@ -762,6 +769,8 @@ static tsk_object_t* tsip_stack_dtor(tsk_object_t * self)
TSK_FREE(stack->network.proxy_cscf);
TSK_OBJECT_SAFE_FREE(stack->paths);
TSK_FREE(stack->network.aor.ip);
TSK_OBJECT_SAFE_FREE(stack->service_routes);
TSK_OBJECT_SAFE_FREE(stack->associated_uris);

View File

@ -32,10 +32,10 @@
#include "tsk_debug.h"
/* Local functions */
tsip_action_t* tsip_action_create_2(tsip_action_type_t type, va_list* app);
int tsip_action_set_2(tsip_action_handle_t* self, va_list* app);
tsip_action_t* _tsip_action_create(tsip_action_type_t type, va_list* app);
int _tsip_action_set(tsip_action_handle_t* self, va_list* app);
/**@defgroup tsip_action_group SIP action (Requests)
/**@defgroup tsip_action_group SIP action (Sending/Receiving Requests)
*/
/**@ingroup tsip_action_group
@ -72,7 +72,7 @@ tsip_action_handle_t* tsip_action_create(tsip_action_type_t type, ...)
tsip_action_t* handle;
va_start(ap, type);
handle = tsip_action_create_2(type, &ap);
handle = _tsip_action_create(type, &ap);
va_end(ap);
return handle;
@ -102,7 +102,7 @@ int tsip_action_set(tsip_action_handle_t* self, ...)
va_list ap;
va_start(ap, self);
ret = tsip_action_set_2(self, &ap);
ret = _tsip_action_set(self, &ap);
va_end(ap);
return ret;
@ -110,7 +110,7 @@ int tsip_action_set(tsip_action_handle_t* self, ...)
/** internal fuction used to config a SIP action */
int tsip_action_set_2(tsip_action_handle_t* self, va_list* app)
int _tsip_action_set(tsip_action_handle_t* self, va_list* app)
{
tsip_action_param_type_t curr;
tsip_action_t* action = self;
@ -171,7 +171,7 @@ int tsip_action_set_2(tsip_action_handle_t* self, va_list* app)
}
/** internal function used to create new SIP action */
tsip_action_t* tsip_action_create_2(tsip_action_type_t type, va_list* app)
tsip_action_t* _tsip_action_create(tsip_action_type_t type, va_list* app)
{
tsip_action_t* action = tsk_null;
@ -185,7 +185,7 @@ tsip_action_t* tsip_action_create_2(tsip_action_type_t type, va_list* app)
}
/* configure the action */
if(tsip_action_set_2(action, app)){
if(_tsip_action_set(action, app)){
TSK_DEBUG_ERROR("Invalid parameter");
TSK_OBJECT_SAFE_FREE(action);
}

View File

@ -846,6 +846,10 @@
RelativePath=".\src\dialogs\tsip_dialog_message.c"
>
</File>
<File
RelativePath=".\src\dialogs\tsip_dialog_options.c"
>
</File>
<File
RelativePath=".\src\dialogs\tsip_dialog_publish.client.c"
>
@ -886,6 +890,10 @@
<Filter
Name="api"
>
<File
RelativePath=".\src\api\tsip_api_common.c"
>
</File>
<File
RelativePath=".\src\api\tsip_api_invite.c"
>
@ -894,6 +902,10 @@
RelativePath=".\src\api\tsip_api_message.c"
>
</File>
<File
RelativePath=".\src\api\tsip_api_options.c"
>
</File>
<File
RelativePath=".\src\api\tsip_api_publish.c"
>
@ -1424,6 +1436,10 @@
RelativePath=".\include\tinysip\dialogs\tsip_dialog_message.h"
>
</File>
<File
RelativePath=".\include\tinysip\dialogs\tsip_dialog_options.h"
>
</File>
<File
RelativePath=".\include\tinysip\dialogs\tsip_dialog_publish.h"
>
@ -1456,6 +1472,10 @@
<Filter
Name="api"
>
<File
RelativePath=".\include\tinysip\api\tsip_api_common.h"
>
</File>
<File
RelativePath=".\include\tinysip\api\tsip_api_invite.h"
>
@ -1464,6 +1484,10 @@
RelativePath=".\include\tinysip\api\tsip_api_message.h"
>
</File>
<File
RelativePath=".\include\tinysip\api\tsip_api_options.h"
>
</File>
<File
RelativePath=".\include\tinysip\api\tsip_api_publish.h"
>