diff options
Diffstat (limited to 'tinySIP/src/tsip.c')
-rwxr-xr-x | tinySIP/src/tsip.c | 1107 |
1 files changed, 563 insertions, 544 deletions
diff --git a/tinySIP/src/tsip.c b/tinySIP/src/tsip.c index 9a377d4..1db31d3 100755 --- a/tinySIP/src/tsip.c +++ b/tinySIP/src/tsip.c @@ -70,7 +70,7 @@ TSK_RUNNABLE_ENQUEUE_OBJECT(TSK_RUNNABLE(self), e); \ static int __tsip_stack_get_transport_idx_by_name(tsip_stack_t *self, const char* name) { - if(tsk_strnullORempty(name) && TSIP_STACK_MODE_IS_CLIENT(self)){ + if(tsk_strnullORempty(name) && TSIP_STACK_MODE_IS_CLIENT(self)) { return self->network.transport_idx_default; // for backward compatibility } return tsip_transport_get_idx_by_name(name); @@ -80,384 +80,399 @@ static int __tsip_stack_get_transport_idx_by_name(tsip_stack_t *self, const char static int __tsip_stack_set(tsip_stack_t *self, va_list* app) { tsip_stack_param_type_t curr; - - while((curr = va_arg(*app, tsip_stack_param_type_t)) != tsip_pname_null){ - switch(curr){ - - /* === Identity === */ - case tsip_pname_display_name: - { /* (const char*)NAME_STR */ - const char* NAME_STR = va_arg(*app, const char*); - tsk_strupdate(&self->identity.display_name, NAME_STR); - break; - } - case tsip_pname_impu: - case tsip_pname_preferred_id: - { /* (const char*)URI_STR */ - const char* URI_STR = va_arg(*app, const char*); - if(!tsk_strnullORempty(URI_STR)){ - tsip_uri_t *uri = tsip_uri_parse(URI_STR, tsk_strlen(URI_STR)); - if(uri){ - if(curr == tsip_pname_impu){ - TSK_OBJECT_SAFE_FREE(self->identity.impu); - self->identity.impu = uri; - } - else{ - TSK_OBJECT_SAFE_FREE(self->identity.preferred); - self->identity.preferred = uri; - } + + while((curr = va_arg(*app, tsip_stack_param_type_t)) != tsip_pname_null) { + switch(curr) { + + /* === Identity === */ + case tsip_pname_display_name: { + /* (const char*)NAME_STR */ + const char* NAME_STR = va_arg(*app, const char*); + tsk_strupdate(&self->identity.display_name, NAME_STR); + break; + } + case tsip_pname_impu: + case tsip_pname_preferred_id: { + /* (const char*)URI_STR */ + const char* URI_STR = va_arg(*app, const char*); + if(!tsk_strnullORempty(URI_STR)) { + tsip_uri_t *uri = tsip_uri_parse(URI_STR, tsk_strlen(URI_STR)); + if(uri) { + if(curr == tsip_pname_impu) { + TSK_OBJECT_SAFE_FREE(self->identity.impu); + self->identity.impu = uri; } - else{ - TSK_DEBUG_ERROR("'%s' is an invalid SIP/TEL URI", URI_STR); - if(curr == tsip_pname_impu){ - return -1; /* IMPU is mandatory but P-Preferred-Identity isn't. */ - } + else { + TSK_OBJECT_SAFE_FREE(self->identity.preferred); + self->identity.preferred = uri; } } - else if(curr == tsip_pname_impu){ - TSK_DEBUG_ERROR("IMPU (IMS Public Identity) is mandatory."); - return -1; + else { + TSK_DEBUG_ERROR("'%s' is an invalid SIP/TEL URI", URI_STR); + if(curr == tsip_pname_impu) { + return -1; /* IMPU is mandatory but P-Preferred-Identity isn't. */ + } } - break; } - case tsip_pname_impi: - { /* (const char*)IMPI_STR */ - const char* IMPI_STR = va_arg(*app, const char*); - if(tsk_strnullORempty(IMPI_STR)){ - TSK_DEBUG_ERROR("IMPI (IMS Private Identity) is mandatory."); - return -1; /* mandatory */ - } - tsk_strupdate(&self->identity.impi, IMPI_STR); - break; + else if(curr == tsip_pname_impu) { + TSK_DEBUG_ERROR("IMPU (IMS Public Identity) is mandatory."); + return -1; } - case tsip_pname_password: - { /* (const char*)PASSORD_STR */ - const char* PASSORD_STR = va_arg(*app, const char*); - tsk_strupdate(&self->identity.password, PASSORD_STR); - break; + break; + } + case tsip_pname_impi: { + /* (const char*)IMPI_STR */ + const char* IMPI_STR = va_arg(*app, const char*); + if(tsk_strnullORempty(IMPI_STR)) { + TSK_DEBUG_ERROR("IMPI (IMS Private Identity) is mandatory."); + return -1; /* mandatory */ } - - /* === SigComp === */ - case tsip_pname_sigcomp: - { /* (unsigned)DMS_UINT, (unsigned)SMS_UINT, (unsigned)CPB_UINT, (tsk_bool_t)PRES_DICT_BOOL */ - self->sigcomp.dms = va_arg(*app, unsigned); - self->sigcomp.sms = va_arg(*app, unsigned); - self->sigcomp.cpb = va_arg(*app, unsigned); - self->sigcomp.pres_dict = va_arg(*app, tsk_bool_t); - break; + tsk_strupdate(&self->identity.impi, IMPI_STR); + break; + } + case tsip_pname_password: { + /* (const char*)PASSORD_STR */ + const char* PASSORD_STR = va_arg(*app, const char*); + tsk_strupdate(&self->identity.password, PASSORD_STR); + break; + } + + /* === SigComp === */ + case tsip_pname_sigcomp: { + /* (unsigned)DMS_UINT, (unsigned)SMS_UINT, (unsigned)CPB_UINT, (tsk_bool_t)PRES_DICT_BOOL */ + self->sigcomp.dms = va_arg(*app, unsigned); + self->sigcomp.sms = va_arg(*app, unsigned); + self->sigcomp.cpb = va_arg(*app, unsigned); + self->sigcomp.pres_dict = va_arg(*app, tsk_bool_t); + break; + } + case tsip_pname_sigcomp_add_compartment: { + /* (const char*)COMPARTMENT_ID_STR */ + if(!self->sigcomp.handle) { + self->sigcomp.handle = tsip_sigcomp_handler_create(self->sigcomp.cpb, self->sigcomp.dms, self->sigcomp.sms); + tsip_sigcomp_handler_set_dicts(self->sigcomp.handle, self->sigcomp.sip_dict, self->sigcomp.pres_dict); } - case tsip_pname_sigcomp_add_compartment: - { /* (const char*)COMPARTMENT_ID_STR */ - if(!self->sigcomp.handle){ - self->sigcomp.handle = tsip_sigcomp_handler_create(self->sigcomp.cpb, self->sigcomp.dms, self->sigcomp.sms); - tsip_sigcomp_handler_set_dicts(self->sigcomp.handle, self->sigcomp.sip_dict, self->sigcomp.pres_dict); - } - tsip_sigcomp_handler_add_compartment(self->sigcomp.handle, va_arg(*app, const char*)); - break; + tsip_sigcomp_handler_add_compartment(self->sigcomp.handle, va_arg(*app, const char*)); + break; + } + case tsip_pname_sigcomp_remove_compartment: { + /* (const char*)COMPARTMENT_ID_STR */ + if(self->sigcomp.handle) { + tsip_sigcomp_handler_remove_compartment(self->sigcomp.handle, va_arg(*app, const char*)); } - case tsip_pname_sigcomp_remove_compartment: - { /* (const char*)COMPARTMENT_ID_STR */ - if(self->sigcomp.handle){ - tsip_sigcomp_handler_remove_compartment(self->sigcomp.handle, va_arg(*app, const char*)); + break; + } + + /* === Network === */ + case tsip_pname_realm: { + /* (const char*)URI_STR */ + const char* URI_STR = va_arg(*app, const char*); + tsip_uri_t *uri; + if(!tsk_strnullORempty(URI_STR) && (uri = tsip_uri_parse(URI_STR, tsk_strlen(URI_STR)))) { + if(uri->type == uri_unknown) { /* scheme is missing or unsupported? */ + tsk_strupdate(&uri->scheme, "sip"); + uri->type = uri_sip; } - break; + TSK_OBJECT_SAFE_FREE(self->network.realm); /* delete old */ + self->network.realm = uri; } - - /* === Network === */ - case tsip_pname_realm: - { /* (const char*)URI_STR */ - const char* URI_STR = va_arg(*app, const char*); - tsip_uri_t *uri; - if(!tsk_strnullORempty(URI_STR) && (uri = tsip_uri_parse(URI_STR, tsk_strlen(URI_STR)))){ - if(uri->type == uri_unknown){ /* scheme is missing or unsupported? */ - tsk_strupdate(&uri->scheme, "sip"); - uri->type = uri_sip; - } - TSK_OBJECT_SAFE_FREE(self->network.realm); /* delete old */ - self->network.realm = uri; - } - else{ - TSK_DEBUG_ERROR("'%s' is an invalid SIP/TEL URI", URI_STR); - return -1; /* mandatory */ - } - break; + else { + TSK_DEBUG_ERROR("'%s' is an invalid SIP/TEL URI", URI_STR); + return -1; /* mandatory */ } - case tsip_pname_local_ip: - { /* (const char*)TRANSPORT_STR, (const char*)IP_STR */ - const char* TRANSPORT_STR = va_arg(*app, const char*); - const char* IP_STR = va_arg(*app, const char*); - int t_idx = __tsip_stack_get_transport_idx_by_name(self, TRANSPORT_STR); - 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); - } - break; + break; + } + case tsip_pname_local_ip: { + /* (const char*)TRANSPORT_STR, (const char*)IP_STR */ + const char* TRANSPORT_STR = va_arg(*app, const char*); + const char* IP_STR = va_arg(*app, const char*); + int t_idx = __tsip_stack_get_transport_idx_by_name(self, TRANSPORT_STR); + if(t_idx < 0) { + TSK_DEBUG_ERROR("%s not valid as transport or you're probably using deprecated function", TRANSPORT_STR); + return -1; } - case tsip_pname_local_port: - { /* (const char*)TRANSPORT_STR, (unsigned)PORT_UINT */ - const char* TRANSPORT_STR = va_arg(*app, const char*); - unsigned PORT_UINT = va_arg(*app, unsigned); - int t_idx = __tsip_stack_get_transport_idx_by_name(self, TRANSPORT_STR); - if(t_idx < 0) { TSK_DEBUG_ERROR("%s not valid as transport or you're probably using deprecated function", TRANSPORT_STR); return -1; } - - self->network.local_port[t_idx] = PORT_UINT; - 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); - } - break; + + 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); } - case tsip_pname_aor: - { /* (const char*)TRANSPORT_STR, (const char*)IP_STR, (unsigned)PORT_UINT */ - const char* TRANSPORT_STR = va_arg(*app, const char*); - const char* IP_STR = va_arg(*app, const char*); - tnet_port_t PORT_UINT = (tnet_port_t)va_arg(*app, unsigned); - int t_idx = __tsip_stack_get_transport_idx_by_name(self, TRANSPORT_STR); - if(t_idx < 0) { TSK_DEBUG_ERROR("%s not valid as transport or you're probably using deprecated function", TRANSPORT_STR); return -1; } - - if(!tsk_strnullORempty(IP_STR)){ - tsk_strupdate(&self->network.aor.ip[t_idx], IP_STR); - } - if(PORT_UINT){ - self->network.aor.port[t_idx] = PORT_UINT; - } - break; + break; + } + case tsip_pname_local_port: { + /* (const char*)TRANSPORT_STR, (unsigned)PORT_UINT */ + const char* TRANSPORT_STR = va_arg(*app, const char*); + unsigned PORT_UINT = va_arg(*app, unsigned); + int t_idx = __tsip_stack_get_transport_idx_by_name(self, TRANSPORT_STR); + if(t_idx < 0) { + TSK_DEBUG_ERROR("%s not valid as transport or you're probably using deprecated function", TRANSPORT_STR); + return -1; } - case tsip_pname_discovery_naptr: - { /* (tsk_bool_t)ENABLED_BOOL */ - self->network.discovery_naptr = va_arg(*app, tsk_bool_t); - break; + + self->network.local_port[t_idx] = PORT_UINT; + 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); } - case tsip_pname_discovery_dhcp: - { /* (tsk_bool_t)ENABLED_BOOL */ - self->network.discovery_dhcp = va_arg(*app, tsk_bool_t); - break; + break; + } + case tsip_pname_aor: { + /* (const char*)TRANSPORT_STR, (const char*)IP_STR, (unsigned)PORT_UINT */ + const char* TRANSPORT_STR = va_arg(*app, const char*); + const char* IP_STR = va_arg(*app, const char*); + tnet_port_t PORT_UINT = (tnet_port_t)va_arg(*app, unsigned); + int t_idx = __tsip_stack_get_transport_idx_by_name(self, TRANSPORT_STR); + if(t_idx < 0) { + TSK_DEBUG_ERROR("%s not valid as transport or you're probably using deprecated function", TRANSPORT_STR); + return -1; } - case tsip_pname_proxy_cscf: - { /* (const char*)FQDN_STR, (unsigned)PORT_UINT, (const char*)TRANSPORT_STR, (const char*)IP_VERSION_STR */ - const char* FQDN_STR = va_arg(*app, const char*); - tnet_port_t PORT_UINT = va_arg(*app, unsigned); - const char* TRANSPORT_STR = va_arg(*app, const char*); - const char* IP_VERSION_STR = va_arg(*app, const char*); - int t_idx = __tsip_stack_get_transport_idx_by_name(self, TRANSPORT_STR); - if(t_idx < 0) { TSK_DEBUG_ERROR("%s not valid as transport or you're probably using deprecated function", TRANSPORT_STR); return -1; } - - if(TSIP_STACK_MODE_IS_CLIENT(self)){ - // "client" mode support a unique proxy_cscf -> reset previous transports - int k; - for(k = 0; k < sizeof(self->network.proxy_cscf_type)/sizeof(self->network.proxy_cscf_type[0]); ++k) { - self->network.proxy_cscf_type[k] = tnet_socket_type_invalid; - } - } - - /* IP Address */ - tsk_strupdate(&self->network.proxy_cscf[t_idx], FQDN_STR); - - /* Port */ - if(PORT_UINT){ - self->network.proxy_cscf_port[t_idx] = PORT_UINT; - } - - /* Transport */ - if(tsk_strnullORempty(TRANSPORT_STR) || tsk_striequals(TRANSPORT_STR, "UDP")){ - TNET_SOCKET_TYPE_SET_UDP(self->network.proxy_cscf_type[t_idx]); - } - else if(tsk_striequals(TRANSPORT_STR, "DTLS")){ - TNET_SOCKET_TYPE_SET_DTLS(self->network.proxy_cscf_type[t_idx]); - } - else if(tsk_striequals(TRANSPORT_STR, "TCP")){ - TNET_SOCKET_TYPE_SET_TCP(self->network.proxy_cscf_type[t_idx]); - } - else if(tsk_striequals(TRANSPORT_STR, "TLS")){ - TNET_SOCKET_TYPE_SET_TLS(self->network.proxy_cscf_type[t_idx]); - } - else if(tsk_striequals(TRANSPORT_STR, "SCTP")){ - TNET_SOCKET_TYPE_SET_SCTP(self->network.proxy_cscf_type[t_idx]); - } - else if(tsk_striequals(TRANSPORT_STR, "WS")){ - TNET_SOCKET_TYPE_SET_WS(self->network.proxy_cscf_type[t_idx]); - } - else if(tsk_striequals(TRANSPORT_STR, "WSS")){ - TNET_SOCKET_TYPE_SET_WSS(self->network.proxy_cscf_type[t_idx]); - } - TNET_SOCKET_TYPE_SET_IPV4(self->network.proxy_cscf_type[t_idx]); // IPv4 is the default version - /* whether to use ipv6 or not */ - if(!tsk_strnullORempty(IP_VERSION_STR)){ - if(tsk_strcontains(IP_VERSION_STR, tsk_strlen(IP_VERSION_STR), "6")){ - TNET_SOCKET_TYPE_SET_IPV6Only(self->network.proxy_cscf_type[t_idx]); // "only" to clear IPv4 flag - } - if(tsk_strcontains(IP_VERSION_STR, tsk_strlen(IP_VERSION_STR), "4")){ - TNET_SOCKET_TYPE_SET_IPV4(self->network.proxy_cscf_type[t_idx]); /* Not IPV4only ==> '46'/'64' */ - } - } - /* use same transport type as the proxy-cscf */ - self->network.transport_types[t_idx] = self->network.proxy_cscf_type[t_idx]; - /* set default transport */ - self->network.transport_idx_default = t_idx; - break; + + if(!tsk_strnullORempty(IP_STR)) { + tsk_strupdate(&self->network.aor.ip[t_idx], IP_STR); + } + if(PORT_UINT) { + self->network.aor.port[t_idx] = PORT_UINT; } - case tsip_pname_dnsserver: - { /* (const char*)IP_STR */ - const char* IP_STR = va_arg(*app, const char*); - if(tnet_dns_add_server(self->dns_ctx, IP_STR)){ - TSK_DEBUG_ERROR("Failed to add [%s] as DNS server", IP_STR); + break; + } + case tsip_pname_discovery_naptr: { + /* (tsk_bool_t)ENABLED_BOOL */ + self->network.discovery_naptr = va_arg(*app, tsk_bool_t); + break; + } + case tsip_pname_discovery_dhcp: { + /* (tsk_bool_t)ENABLED_BOOL */ + self->network.discovery_dhcp = va_arg(*app, tsk_bool_t); + break; + } + case tsip_pname_proxy_cscf: { + /* (const char*)FQDN_STR, (unsigned)PORT_UINT, (const char*)TRANSPORT_STR, (const char*)IP_VERSION_STR */ + const char* FQDN_STR = va_arg(*app, const char*); + tnet_port_t PORT_UINT = va_arg(*app, unsigned); + const char* TRANSPORT_STR = va_arg(*app, const char*); + const char* IP_VERSION_STR = va_arg(*app, const char*); + int t_idx = __tsip_stack_get_transport_idx_by_name(self, TRANSPORT_STR); + if(t_idx < 0) { + TSK_DEBUG_ERROR("%s not valid as transport or you're probably using deprecated function", TRANSPORT_STR); + return -1; + } + + if(TSIP_STACK_MODE_IS_CLIENT(self)) { + // "client" mode support a unique proxy_cscf -> reset previous transports + int k; + for(k = 0; k < sizeof(self->network.proxy_cscf_type)/sizeof(self->network.proxy_cscf_type[0]); ++k) { + self->network.proxy_cscf_type[k] = tnet_socket_type_invalid; } - break; } - case tsip_pname_max_fds: - { /* (unsigned)MAX_FDS_UINT */ - self->network.max_fds = va_arg(*app, unsigned); - break; + + /* IP Address */ + tsk_strupdate(&self->network.proxy_cscf[t_idx], FQDN_STR); + + /* Port */ + if(PORT_UINT) { + self->network.proxy_cscf_port[t_idx] = PORT_UINT; + } + + /* Transport */ + if(tsk_strnullORempty(TRANSPORT_STR) || tsk_striequals(TRANSPORT_STR, "UDP")) { + TNET_SOCKET_TYPE_SET_UDP(self->network.proxy_cscf_type[t_idx]); } - case tsip_pname_mode: - { /* (tsip_stack_mode_t)MODE_ENUM */ - self->network.mode = va_arg(*app, tsip_stack_mode_t); - break; + else if(tsk_striequals(TRANSPORT_STR, "DTLS")) { + TNET_SOCKET_TYPE_SET_DTLS(self->network.proxy_cscf_type[t_idx]); } - - - - /* === Security === */ - case tsip_pname_early_ims: - { /* (tsk_bool_t)ENABLED_BOOL */ - self->security.earlyIMS = va_arg(*app, tsk_bool_t); - break; + else if(tsk_striequals(TRANSPORT_STR, "TCP")) { + TNET_SOCKET_TYPE_SET_TCP(self->network.proxy_cscf_type[t_idx]); } - case tsip_pname_secagree_ipsec: - { /* (const char*)TRANSPORT_STR, (tsk_bool_t)ENABLED_BOOL */ - const char* TRANSPORT_STR = va_arg(*app, const char*); - tsk_bool_t ENABLED_BOOL = va_arg(*app, tsk_bool_t); - int t_idx = __tsip_stack_get_transport_idx_by_name(self, TRANSPORT_STR); - if(t_idx < 0) { TSK_DEBUG_ERROR("%s not valid as transport or you're probably using deprecated function", TRANSPORT_STR); return -1; } - if(ENABLED_BOOL){ - tsk_strupdate(&self->security.secagree_mech, "ipsec-3gpp"); - TNET_SOCKET_TYPE_SET_IPSEC(self->network.proxy_cscf_type[t_idx]); - } - else{ - TNET_SOCKET_TYPE_UNSET(self->network.proxy_cscf_type[t_idx], IPSEC); - } - break; + else if(tsk_striequals(TRANSPORT_STR, "TLS")) { + TNET_SOCKET_TYPE_SET_TLS(self->network.proxy_cscf_type[t_idx]); } - case tsip_pname_secagree_tls: - { /* (tsk_bool_t)ENABLED_BOOL */ - if((self->security.enable_secagree_tls = va_arg(*app, tsk_bool_t))){ - tsk_strupdate(&self->security.secagree_mech, "tls"); - } - break; + else if(tsk_striequals(TRANSPORT_STR, "SCTP")) { + TNET_SOCKET_TYPE_SET_SCTP(self->network.proxy_cscf_type[t_idx]); } - case tsip_pname_amf: - { /* (uint16_t)AMF_UINT16 */ - unsigned amf = va_arg(*app, unsigned); - self->security.amf[0] = (amf >> 8); - self->security.amf[1] = (amf & 0xFF); - break; + else if(tsk_striequals(TRANSPORT_STR, "WS")) { + TNET_SOCKET_TYPE_SET_WS(self->network.proxy_cscf_type[t_idx]); } - case tsip_pname_operator_id: - { /* (const char*)OPID_HEX_STR */ - const char* hexstr = va_arg(*app, const char*); - tsk_size_t len = tsk_strlen(hexstr); - if(len && !(len & 0x01)){ - tsk_size_t i, j; - if(tsk_strindexOf(hexstr, tsk_strlen(hexstr), "0x") == 0){ - hexstr += 2; - len -= 2; - } - /* reset old value */ - memset(self->security.operator_id, 0, sizeof(self->security.operator_id)); - - /* set new value */ - if(len){ /* perhaps there were only 2 chars*/ - for(i = 0, j = 0; (i<(sizeof(operator_id_t) * 2) && i<len); i+=2, j++){ -#if 0 /* Could cause SIGBUS error (if memory misaligned) */ - sscanf(&hexstr[i], "%2x", &self->security.operator_id[j]); -#else - static unsigned _1bytes; /* do not use neither int8_t nor uint8_t */ - sscanf(&hexstr[i], "%2x", &_1bytes); - self->security.operator_id[j] = (_1bytes & 0xFF); -#endif - } - } + else if(tsk_striequals(TRANSPORT_STR, "WSS")) { + TNET_SOCKET_TYPE_SET_WSS(self->network.proxy_cscf_type[t_idx]); + } + TNET_SOCKET_TYPE_SET_IPV4(self->network.proxy_cscf_type[t_idx]); // IPv4 is the default version + /* whether to use ipv6 or not */ + if(!tsk_strnullORempty(IP_VERSION_STR)) { + if(tsk_strcontains(IP_VERSION_STR, tsk_strlen(IP_VERSION_STR), "6")) { + TNET_SOCKET_TYPE_SET_IPV6Only(self->network.proxy_cscf_type[t_idx]); // "only" to clear IPv4 flag } - else{ - TSK_DEBUG_ERROR("%s is invalid for an Operator Id value.", hexstr); + if(tsk_strcontains(IP_VERSION_STR, tsk_strlen(IP_VERSION_STR), "4")) { + TNET_SOCKET_TYPE_SET_IPV4(self->network.proxy_cscf_type[t_idx]); /* Not IPV4only ==> '46'/'64' */ } - break; } - case tsip_pname_ipsec_params: - { /* (const char*)ALG_STR, (const char*)EALG_STR, (const char*)MODE_STR, (const char*)PROTOCOL_STR*/ - tsk_strupdate(&self->security.ipsec.alg, va_arg(*app, const char*)); - tsk_strupdate(&self->security.ipsec.ealg, va_arg(*app, const char*)); - tsk_strupdate(&self->security.ipsec.mode, va_arg(*app, const char*)); - tsk_strupdate(&self->security.ipsec.protocol, va_arg(*app, const char*)); - break; + /* use same transport type as the proxy-cscf */ + self->network.transport_types[t_idx] = self->network.proxy_cscf_type[t_idx]; + /* set default transport */ + self->network.transport_idx_default = t_idx; + break; + } + case tsip_pname_dnsserver: { + /* (const char*)IP_STR */ + const char* IP_STR = va_arg(*app, const char*); + if(tnet_dns_add_server(self->dns_ctx, IP_STR)) { + TSK_DEBUG_ERROR("Failed to add [%s] as DNS server", IP_STR); } - case tsip_pname_tls_certs: - { /* (const char*)CA_FILE_STR, (const char*)PUB_FILE_STR, (const char*)PRIV_FILE_STR, (tsk_bool_t)VERIF_BOOL */ - tsk_strupdate(&self->security.tls.ca, va_arg(*app, const char*)); - tsk_strupdate(&self->security.tls.pbk, va_arg(*app, const char*)); - tsk_strupdate(&self->security.tls.pvk, va_arg(*app, const char*)); - self->security.tls.verify = va_arg(*app, tsk_bool_t); - break; + break; + } + case tsip_pname_max_fds: { + /* (unsigned)MAX_FDS_UINT */ + self->network.max_fds = va_arg(*app, unsigned); + break; + } + case tsip_pname_mode: { + /* (tsip_stack_mode_t)MODE_ENUM */ + self->network.mode = va_arg(*app, tsip_stack_mode_t); + break; + } + + + + /* === Security === */ + case tsip_pname_early_ims: { + /* (tsk_bool_t)ENABLED_BOOL */ + self->security.earlyIMS = va_arg(*app, tsk_bool_t); + break; + } + case tsip_pname_secagree_ipsec: { + /* (const char*)TRANSPORT_STR, (tsk_bool_t)ENABLED_BOOL */ + const char* TRANSPORT_STR = va_arg(*app, const char*); + tsk_bool_t ENABLED_BOOL = va_arg(*app, tsk_bool_t); + int t_idx = __tsip_stack_get_transport_idx_by_name(self, TRANSPORT_STR); + if(t_idx < 0) { + TSK_DEBUG_ERROR("%s not valid as transport or you're probably using deprecated function", TRANSPORT_STR); + return -1; } - - - /* === Dummy Headers === */ - case tsip_pname_header: - { /* (const char*)NAME_STR, (const char*)VALUE_STR */ - const char* NAME_STR = va_arg(*app, const char*); - const char* VALUE_STR = va_arg(*app, const char*); - if(VALUE_STR == ((const char*)-1)){ /* UNSET */ - tsk_params_remove_param(self->headers, NAME_STR); - } - else{ /* SET */ - tsk_params_add_param(&self->headers, NAME_STR, VALUE_STR); - } - break; + if(ENABLED_BOOL) { + tsk_strupdate(&self->security.secagree_mech, "ipsec-3gpp"); + TNET_SOCKET_TYPE_SET_IPSEC(self->network.proxy_cscf_type[t_idx]); } - - - /* === Nat Traversal === */ - case tsip_pname_stun_server: - { /* (const char*)IP_STR, (unsigned)PORT_UINT */ - const char* IP_STR = va_arg(*app, const char*); - unsigned PORT_UINT = va_arg(*app, unsigned); - /* do not check, Null==> disable STUN */ - tsk_strupdate(&self->natt.stun.ip, IP_STR); - self->natt.stun.port = PORT_UINT; - break; + else { + TNET_SOCKET_TYPE_UNSET(self->network.proxy_cscf_type[t_idx], IPSEC); } - case tsip_pname_stun_cred: - { /* (const char*)USR_STR, (const char*)PASSORD_STR */ - const char* USR_STR = va_arg(*app, const char*); - const char* PASSORD_STR = va_arg(*app, const char*); - tsk_strupdate(&self->natt.stun.login, USR_STR); - tsk_strupdate(&self->natt.stun.pwd, PASSORD_STR); - break; + break; + } + case tsip_pname_secagree_tls: { + /* (tsk_bool_t)ENABLED_BOOL */ + if((self->security.enable_secagree_tls = va_arg(*app, tsk_bool_t))) { + tsk_strupdate(&self->security.secagree_mech, "tls"); } - case tsip_pname_stun_enabled: - { /* (tsk_bool_t)ENABLED_BOOL */ - self->natt.stun.enabled = va_arg(*app, tsk_bool_t); - break; + break; + } + case tsip_pname_amf: { + /* (uint16_t)AMF_UINT16 */ + unsigned amf = va_arg(*app, unsigned); + self->security.amf[0] = (amf >> 8); + self->security.amf[1] = (amf & 0xFF); + break; + } + case tsip_pname_operator_id: { + /* (const char*)OPID_HEX_STR */ + const char* hexstr = va_arg(*app, const char*); + tsk_size_t len = tsk_strlen(hexstr); + if(len && !(len & 0x01)) { + tsk_size_t i, j; + if(tsk_strindexOf(hexstr, tsk_strlen(hexstr), "0x") == 0) { + hexstr += 2; + len -= 2; + } + /* reset old value */ + memset(self->security.operator_id, 0, sizeof(self->security.operator_id)); + + /* set new value */ + if(len) { /* perhaps there were only 2 chars*/ + for(i = 0, j = 0; (i<(sizeof(operator_id_t) * 2) && i<len); i+=2, j++) { +#if 0 /* Could cause SIGBUS error (if memory misaligned) */ + sscanf(&hexstr[i], "%2x", &self->security.operator_id[j]); +#else + static unsigned _1bytes; /* do not use neither int8_t nor uint8_t */ + sscanf(&hexstr[i], "%2x", &_1bytes); + self->security.operator_id[j] = (_1bytes & 0xFF); +#endif + } + } } - /* === User Data === */ - case tsip_pname_userdata: - { /* (const void*)DATA_PTR */ - self->userdata = va_arg(*app, const void*); - break; + else { + TSK_DEBUG_ERROR("%s is invalid for an Operator Id value.", hexstr); } - - - - default: - { /* va_list will be unsafe ==> must exit */ - TSK_DEBUG_WARN("Found unknown pname."); - goto bail; + break; + } + case tsip_pname_ipsec_params: { + /* (const char*)ALG_STR, (const char*)EALG_STR, (const char*)MODE_STR, (const char*)PROTOCOL_STR*/ + tsk_strupdate(&self->security.ipsec.alg, va_arg(*app, const char*)); + tsk_strupdate(&self->security.ipsec.ealg, va_arg(*app, const char*)); + tsk_strupdate(&self->security.ipsec.mode, va_arg(*app, const char*)); + tsk_strupdate(&self->security.ipsec.protocol, va_arg(*app, const char*)); + break; + } + case tsip_pname_tls_certs: { + /* (const char*)CA_FILE_STR, (const char*)PUB_FILE_STR, (const char*)PRIV_FILE_STR, (tsk_bool_t)VERIF_BOOL */ + tsk_strupdate(&self->security.tls.ca, va_arg(*app, const char*)); + tsk_strupdate(&self->security.tls.pbk, va_arg(*app, const char*)); + tsk_strupdate(&self->security.tls.pvk, va_arg(*app, const char*)); + self->security.tls.verify = va_arg(*app, tsk_bool_t); + break; + } + + + /* === Dummy Headers === */ + case tsip_pname_header: { + /* (const char*)NAME_STR, (const char*)VALUE_STR */ + const char* NAME_STR = va_arg(*app, const char*); + const char* VALUE_STR = va_arg(*app, const char*); + if(VALUE_STR == ((const char*)-1)) { /* UNSET */ + tsk_params_remove_param(self->headers, NAME_STR); + } + else { /* SET */ + tsk_params_add_param(&self->headers, NAME_STR, VALUE_STR); } + break; + } + + + /* === Nat Traversal === */ + case tsip_pname_stun_server: { + /* (const char*)IP_STR, (unsigned)PORT_UINT */ + const char* IP_STR = va_arg(*app, const char*); + unsigned PORT_UINT = va_arg(*app, unsigned); + /* do not check, Null==> disable STUN */ + tsk_strupdate(&self->natt.stun.ip, IP_STR); + self->natt.stun.port = PORT_UINT; + break; + } + case tsip_pname_stun_cred: { + /* (const char*)USR_STR, (const char*)PASSORD_STR */ + const char* USR_STR = va_arg(*app, const char*); + const char* PASSORD_STR = va_arg(*app, const char*); + tsk_strupdate(&self->natt.stun.login, USR_STR); + tsk_strupdate(&self->natt.stun.pwd, PASSORD_STR); + break; + } + case tsip_pname_stun_enabled: { + /* (tsk_bool_t)ENABLED_BOOL */ + self->natt.stun.enabled = va_arg(*app, tsk_bool_t); + break; + } + /* === User Data === */ + case tsip_pname_userdata: { + /* (const void*)DATA_PTR */ + self->userdata = va_arg(*app, const void*); + break; + } + + + + default: { + /* va_list will be unsafe ==> must exit */ + TSK_DEBUG_WARN("Found unknown pname."); + goto bail; + } }/* switch */ }/* while */ - + bail: return 0; } @@ -478,18 +493,18 @@ bail: * * @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"; - + 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()); - + // ...whatever - + TSK_OBJECT_SAFE_FREE(stack); * @endcode * @sa @ref tsip_stack_set()<br>@ref tsip_stack_start() @@ -499,41 +514,47 @@ tsip_stack_handle_t* tsip_stack_create(tsip_stack_callback_f callback, const cha tsip_stack_t* stack = tsk_null; va_list ap; int i; - + /* === check values === */ - if(!realm_uri || !impi_uri || !impu_uri){ + if(!realm_uri || !impi_uri || !impu_uri) { TSK_DEBUG_ERROR("Invalid parameter."); goto bail; } - + /* === create the stack === */ - if(!(stack = tsk_object_new(tsip_stack_def_t))){ /* should never happen */ + if(!(stack = tsk_object_new(tsip_stack_def_t))) { /* should never happen */ TSK_DEBUG_ERROR("Failed to create the stack."); goto bail; } - + /* === Set mandatory values (realm, IMPI and IMPU) === */ if(tsip_stack_set(stack, TSIP_STACK_SET_REALM(realm_uri), TSIP_STACK_SET_IMPI(impi_uri), TSIP_STACK_SET_IMPU(impu_uri), - - TSIP_STACK_SET_NULL())){ + + TSIP_STACK_SET_NULL())) { TSK_DEBUG_ERROR("Invalid parameter."); TSK_OBJECT_SAFE_FREE(stack); goto bail; } - + /* === Default values (Network) === */ stack->network.mode = tsip_stack_mode_ua; - for(i = 0; i < sizeof(stack->network.local_port)/sizeof(stack->network.local_port[0]); ++i) { stack->network.local_port[i] = TNET_SOCKET_PORT_ANY; } - for(i = 0; i < sizeof(stack->network.proxy_cscf_port)/sizeof(stack->network.proxy_cscf_port[0]); ++i) { stack->network.proxy_cscf_port[i] = 5060; } - for(i = 0; i < sizeof(stack->network.proxy_cscf_type)/sizeof(stack->network.proxy_cscf_type[0]); ++i) { stack->network.proxy_cscf_type[i] = tnet_socket_type_invalid; } + for(i = 0; i < sizeof(stack->network.local_port)/sizeof(stack->network.local_port[0]); ++i) { + stack->network.local_port[i] = TNET_SOCKET_PORT_ANY; + } + for(i = 0; i < sizeof(stack->network.proxy_cscf_port)/sizeof(stack->network.proxy_cscf_port[0]); ++i) { + stack->network.proxy_cscf_port[i] = 5060; + } + for(i = 0; i < sizeof(stack->network.proxy_cscf_type)/sizeof(stack->network.proxy_cscf_type[0]); ++i) { + stack->network.proxy_cscf_type[i] = tnet_socket_type_invalid; + } stack->network.max_fds = tmedia_defaults_get_max_fds(); - + // all events should be delivered to the user before the stack stop tsk_runnable_set_important(TSK_RUNNABLE(stack), tsk_true); - + /* === SigComp === */ // only create the handler on-demand: when compartment is added stack->sigcomp.dms = TSIP_SIGCOMP_DMS; @@ -541,65 +562,65 @@ tsip_stack_handle_t* tsip_stack_create(tsip_stack_callback_f callback, const cha stack->sigcomp.cpb = TSIP_SIGCOMP_CPB; stack->sigcomp.sip_dict = TSIP_SIGCOMP_SIP_DICT; stack->sigcomp.pres_dict = TSIP_SIGCOMP_PRES_DICT; - + /* === DNS context === * Because of TSIP_STACK_SET_DNS_SERVER(), ctx should be created before calling __tsip_stack_set() */ stack->dns_ctx = tnet_dns_ctx_create(); - + /* === DHCP context === */ - + /* === NAT Traversal === */ { const char *server_ip, *usr_name, *usr_pwd; uint16_t server_port; stack->natt.stun.enabled = tmedia_defaults_get_stun_enabled(); - if(tmedia_defaults_get_stun_server(&server_ip, &server_port) == 0){ + if(tmedia_defaults_get_stun_server(&server_ip, &server_port) == 0) { tsk_strupdate(&stack->natt.stun.ip, server_ip); stack->natt.stun.port = server_port; } - if(tmedia_defaults_get_stun_cred(&usr_name, &usr_pwd) == 0){ + if(tmedia_defaults_get_stun_cred(&usr_name, &usr_pwd) == 0) { tsk_strupdate(&stack->natt.stun.login, usr_name); tsk_strupdate(&stack->natt.stun.pwd, usr_pwd); } } - + /* === Set user supplied parameters === */ va_start(ap, impu_uri); - if(__tsip_stack_set(stack, &ap)){ + if(__tsip_stack_set(stack, &ap)) { TSK_DEBUG_ERROR("Invalid parameter."); TSK_OBJECT_SAFE_FREE(stack); va_end(ap); goto bail; } va_end(ap); - + /* === Internals === */ stack->callback = callback; - if(!stack->ssessions){ + if(!stack->ssessions) { stack->ssessions = tsk_list_create(); } - if(!stack->headers){ /* could be created by tsk_params_add_param() */ + if(!stack->headers) { /* could be created by tsk_params_add_param() */ stack->headers = tsk_list_create(); } - + /* === Layers === */ - if(!(stack->layer_dialog = tsip_dialog_layer_create(stack))){ + if(!(stack->layer_dialog = tsip_dialog_layer_create(stack))) { TSK_DEBUG_ERROR("Failed to create Dialog layer"); TSK_OBJECT_SAFE_FREE(stack); goto bail; } - if(!(stack->layer_transac = tsip_transac_layer_create(stack))){ + if(!(stack->layer_transac = tsip_transac_layer_create(stack))) { TSK_DEBUG_ERROR("Failed to create Transac layer"); TSK_OBJECT_SAFE_FREE(stack); goto bail; } - if(!(stack->layer_transport = tsip_transport_layer_create(stack))){ + if(!(stack->layer_transport = tsip_transport_layer_create(stack))) { TSK_DEBUG_ERROR("Failed to create Transport layer"); TSK_OBJECT_SAFE_FREE(stack); goto bail; } - + bail: return stack; } @@ -616,44 +637,44 @@ int tsip_stack_start(tsip_stack_handle_t *self) tsip_stack_t *stack = self; tnet_socket_type_t* tx_values; const char* stack_error_desc = "Failed to start the stack"; - - if(!stack){ + + if(!stack) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - - if(stack->started){ + + if(stack->started) { TSK_DEBUG_INFO("Stack Already started"); return 0; } - + tsk_safeobj_lock(stack); - + // transports - if(TSIP_STACK_MODE_IS_SERVER(stack)){ + if(TSIP_STACK_MODE_IS_SERVER(stack)) { TSK_DEBUG_INFO("Stack running in SERVER mode"); tx_values = &stack->network.transport_types[0]; tx_count = sizeof(stack->network.transport_types) / sizeof(stack->network.transport_types[0]); } - else{ + else { TSK_DEBUG_INFO("Stack running in CLIENT mode"); tx_values = &stack->network.proxy_cscf_type[0]; tx_count = sizeof(stack->network.proxy_cscf_type) / sizeof(stack->network.proxy_cscf_type[0]); } - + /* === Timer manager === */ - if(!stack->timer_mgr_global){ + if(!stack->timer_mgr_global) { stack->timer_mgr_global = tsk_timer_mgr_global_ref(); } - if((ret = tsk_timer_manager_start(stack->timer_mgr_global))){ + if((ret = tsk_timer_manager_start(stack->timer_mgr_global))) { goto bail; } - + /* === Set P-Preferred-Identity === */ - if(!stack->identity.preferred && stack->identity.impu){ + if(!stack->identity.preferred && stack->identity.impu) { stack->identity.preferred = tsk_object_ref((void*)stack->identity.impu); } - + /* === Set Max FDs === */ if (stack->network.max_fds > 0 && stack->network.max_fds < 0xFFFF) { TSK_DEBUG_INFO("Setting max FDs to %u", (unsigned)stack->network.max_fds); @@ -663,10 +684,10 @@ int tsip_stack_start(tsip_stack_handle_t *self) /* goto bail; */ // Not fatal error } } - + /* === Transport type === */ - if(!tsk_strnullORempty(stack->security.secagree_mech)){ - if(tsk_striequals(stack->security.secagree_mech, "ipsec-3gpp") && stack->security.enable_secagree_ipsec){ + if(!tsk_strnullORempty(stack->security.secagree_mech)) { + if(tsk_striequals(stack->security.secagree_mech, "ipsec-3gpp") && stack->security.enable_secagree_ipsec) { #if 0 TNET_SOCKET_TYPE_SET_IPSEC(stack->network.proxy_cscf_type); #endif @@ -674,59 +695,58 @@ int tsip_stack_start(tsip_stack_handle_t *self) } //else if if(tsk_striquals(stack->security.secagree_mech, "ipsec-ike")) } - - for(t_idx = 0; t_idx < tx_count; ++t_idx){ - if(!TNET_SOCKET_TYPE_IS_VALID(tx_values[t_idx])){ + + for(t_idx = 0; t_idx < tx_count; ++t_idx) { + if(!TNET_SOCKET_TYPE_IS_VALID(tx_values[t_idx])) { continue; } /* === Use DNS NAPTR+SRV for the P-CSCF discovery if we are in client mode === */ - if(TSIP_STACK_MODE_IS_CLIENT(stack)){ - if(tsk_strnullORempty(stack->network.proxy_cscf[t_idx]) || (stack->network.discovery_dhcp || stack->network.discovery_naptr)){ - if(stack->network.discovery_dhcp){ /* DHCP v4/v6 */ + if(TSIP_STACK_MODE_IS_CLIENT(stack)) { + if(tsk_strnullORempty(stack->network.proxy_cscf[t_idx]) || (stack->network.discovery_dhcp || stack->network.discovery_naptr)) { + if(stack->network.discovery_dhcp) { /* DHCP v4/v6 */ /* FIXME: */ TSK_DEBUG_ERROR("Unexpected code called"); ret = -2; } /* DHCP */ - else{ /* DNS NAPTR + SRV*/ + else { /* DNS NAPTR + SRV*/ char* hostname = tsk_null; tnet_port_t port = 0; const char* service = TNET_SOCKET_TYPE_IS_DGRAM(tx_values[t_idx]) ? "SIP+D2U" : (TNET_SOCKET_TYPE_IS_TLS(tx_values[t_idx]) ? "SIPS+D2T" : "SIP+D2T"); - if((ret = tnet_dns_query_naptr_srv(stack->dns_ctx, stack->network.realm->host, service, &hostname, &port)) == 0){ + if((ret = tnet_dns_query_naptr_srv(stack->dns_ctx, stack->network.realm->host, service, &hostname, &port)) == 0) { TSK_DEBUG_INFO("DNS SRV(NAPTR(%s, %s) = [%s / %d]", stack->network.realm->host, service, hostname, port); tsk_strupdate(&stack->network.proxy_cscf[t_idx], hostname); - if(!stack->network.proxy_cscf_port[t_idx] || stack->network.proxy_cscf_port[t_idx]==5060){ /* Only if the Proxy-CSCF port is missing or default */ + if(!stack->network.proxy_cscf_port[t_idx] || stack->network.proxy_cscf_port[t_idx]==5060) { /* Only if the Proxy-CSCF port is missing or default */ stack->network.proxy_cscf_port[t_idx] = port; } } - else{ + else { TSK_DEBUG_ERROR("P-CSCF discovery using DNS NAPTR failed. The stack will use the user supplied address and port."); } - + TSK_FREE(hostname); } /* NAPTR */ } - + /* Check Proxy-CSCF IP address */ - if(!tsk_strnullORempty(stack->network.proxy_cscf[t_idx])){ + if(!tsk_strnullORempty(stack->network.proxy_cscf[t_idx])) { TSK_DEBUG_INFO("Proxy-CSCF=[%s]:%d", stack->network.proxy_cscf[t_idx], stack->network.proxy_cscf_port[t_idx]); } - else{ + else { TSK_DEBUG_ERROR("Proxy-CSCF IP address is Null."); ret = -1983; goto bail; } }// !Server mode - + /* === Get Best source address === */ // 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", - stack->network.proxy_cscf_port[t_idx] ? stack->network.proxy_cscf_port[t_idx] : 5060, - tx_values[t_idx], - &bestsource))) - { + 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); /* do not exit ==> will use default IP address */ } @@ -739,98 +759,98 @@ int tsip_stack_start(tsip_stack_handle_t *self) 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 === */ TSK_RUNNABLE(stack)->run = run; - if((ret = tsk_runnable_start(TSK_RUNNABLE(stack), tsip_event_def_t))){ + if((ret = tsk_runnable_start(TSK_RUNNABLE(stack), tsip_event_def_t))) { stack_error_desc = "Failed to start runnable"; TSK_DEBUG_ERROR("%s", stack_error_desc); goto bail; } - + // must be here because the runnable object is only valid after start() TSIP_STACK_SIGNAL(self, tsip_event_code_stack_starting, "Stack starting"); - + /* === Nat Traversal === */ // delete previous context TSK_OBJECT_SAFE_FREE(stack->natt.ctx); - if(stack->natt.stun.enabled && !tsk_strnullORempty(stack->natt.stun.ip)){ - if(stack->natt.stun.port == 0){ + if(stack->natt.stun.enabled && !tsk_strnullORempty(stack->natt.stun.ip)) { + if(stack->natt.stun.port == 0) { /* FIXME: for now only UDP(IPv4/IPv6) is supported */ stack->natt.stun.port = kStunPortDefaultTcpUdp; } TSK_DEBUG_INFO("STUN server = %s:%u", stack->natt.stun.ip, stack->natt.stun.port); stack->natt.ctx = tnet_nat_context_create(TNET_SOCKET_TYPE_IS_IPV6(tx_values[stack->network.transport_idx_default])? tnet_socket_type_udp_ipv6: tnet_socket_type_udp_ipv4, - stack->natt.stun.login, stack->natt.stun.pwd); + stack->natt.stun.login, stack->natt.stun.pwd); ret = tnet_nat_set_server(stack->natt.ctx, stack->natt.stun.ip, stack->natt.stun.port); } - + /* === Transport Layer === */ - for(t_idx = 0; t_idx < tx_count; ++t_idx){ - if(!TNET_SOCKET_TYPE_IS_VALID(tx_values[t_idx])){ + for(t_idx = 0; t_idx < tx_count; ++t_idx) { + if(!TNET_SOCKET_TYPE_IS_VALID(tx_values[t_idx])) { continue; } - if((ret = tsip_transport_layer_add(stack->layer_transport, stack->network.local_ip[t_idx], stack->network.local_port[t_idx], tx_values[t_idx], "SIP transport"))){ + if((ret = tsip_transport_layer_add(stack->layer_transport, stack->network.local_ip[t_idx], stack->network.local_port[t_idx], tx_values[t_idx], "SIP transport"))) { stack_error_desc = "Failed to add new transport"; TSK_DEBUG_ERROR("%s", stack_error_desc); goto bail; } } /* Starts the transport Layer */ - if((ret = tsip_transport_layer_start(stack->layer_transport))){ + if((ret = tsip_transport_layer_start(stack->layer_transport))) { stack_error_desc = "Failed to start sip transport"; TSK_DEBUG_ERROR("%s", stack_error_desc); goto bail; } - + /* Update the local_ip */ - for(t_idx = 0; t_idx < tx_count; ++t_idx){ - if(!TNET_SOCKET_TYPE_IS_VALID(tx_values[t_idx])){ + for(t_idx = 0; t_idx < tx_count; ++t_idx) { + if(!TNET_SOCKET_TYPE_IS_VALID(tx_values[t_idx])) { continue; } - if(tsk_strnullORempty(stack->network.local_ip[t_idx])){ + if(tsk_strnullORempty(stack->network.local_ip[t_idx])) { const tsip_transport_t* transport = tsip_transport_layer_find_by_type(stack->layer_transport, tx_values[t_idx]); - - if(transport){ + + if(transport) { tnet_ip_t ip; - if(!tnet_transport_get_ip_n_port_2(transport->net_transport, &ip, tsk_null)){ + if(!tnet_transport_get_ip_n_port_2(transport->net_transport, &ip, tsk_null)) { tsk_strupdate(&stack->network.local_ip[t_idx], ip); } - else{ + else { TSK_DEBUG_WARN("Failed to get local_ip for transport type = %d", tx_values[t_idx]); /* Do not exit */ } } } } - - + + /* === ALL IS OK === */ - + stack->started = tsk_true; - + /* Signal to the end-user that the stack has been started */ TSIP_STACK_SIGNAL(self, tsip_event_code_stack_started, "Stack started"); - + TSK_DEBUG_INFO("SIP STACK -- START"); - + tsk_safeobj_unlock(stack); - + return 0; - - + + bail: TSIP_STACK_SIGNAL(self, tsip_event_code_stack_failed_to_start, stack_error_desc); /* stop all running instances */ - if(stack->layer_transport){ + if(stack->layer_transport) { tsip_transport_layer_shutdown(stack->layer_transport); } - if(TSK_RUNNABLE(stack)->running){ + if(TSK_RUNNABLE(stack)->running) { tsk_runnable_stop(TSK_RUNNABLE(stack)); } - + tsk_safeobj_unlock(stack); - + return ret; } @@ -850,17 +870,17 @@ bail: */ int tsip_stack_set(tsip_stack_handle_t *self, ...) { - if(self){ + if(self) { int ret; tsip_stack_t *stack = self; - + va_list ap; va_start(ap, self); ret = __tsip_stack_set(stack, &ap); va_end(ap); return ret; } - else{ + else { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -872,10 +892,10 @@ int tsip_stack_set(tsip_stack_handle_t *self, ...) */ const void* tsip_stack_get_userdata(const tsip_stack_handle_t *self) { - if(self){ + if(self) { return ((const tsip_stack_t *)self)->userdata; } - else{ + else { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } @@ -885,10 +905,10 @@ const void* tsip_stack_get_userdata(const tsip_stack_handle_t *self) */ tnet_dns_ctx_t* tsip_stack_get_dnsctx(tsip_stack_handle_t *self) { - if(self){ + if(self) { return (tnet_dns_ctx_t*)tsk_object_ref(((tsip_stack_t *)self)->dns_ctx); } - else{ + else { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } @@ -898,10 +918,10 @@ tnet_dns_ctx_t* tsip_stack_get_dnsctx(tsip_stack_handle_t *self) */ tsip_uri_t* tsip_stack_get_preferred_id(tsip_stack_handle_t *self) { - if(self){ + if(self) { return (tsip_uri_t*)tsk_object_ref(((tsip_stack_t *)self)->identity.preferred); } - else{ + else { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } @@ -912,25 +932,25 @@ tsip_uri_t* tsip_stack_get_preferred_id(tsip_stack_handle_t *self) 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; - - if(!stack || !port || !ip){ + + if(!stack || !port || !ip) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - - if(stack){ + + if(stack) { tsk_list_item_t *item; - tsk_list_foreach(item, stack->layer_transport->transports){ + tsk_list_foreach(item, stack->layer_transport->transports) { tsip_transport_t *transport = item->data; - - if(transport){ - if(tsk_striequals(transport->protocol, protocol)){ + + if(transport) { + if(tsk_striequals(transport->protocol, protocol)) { return tnet_transport_get_public_ip_n_port(transport->net_transport,transport->connectedFD, ip, port); } } } } - + TSK_DEBUG_ERROR("No transport with such protocol (%s) could be found", protocol); return -2; } @@ -946,97 +966,97 @@ int tsip_stack_get_local_ip_n_port(const tsip_stack_handle_t *self, const char* int tsip_stack_stop(tsip_stack_handle_t *self) { tsip_stack_t *stack = self; - - if(stack){ + + if(stack) { tsk_bool_t one_failed = tsk_false; int ret = 0; - + tsk_safeobj_lock(stack); - - if(!stack->started){ + + if(!stack->started) { TSK_DEBUG_INFO("Stack already stopped"); goto bail; } - + TSIP_STACK_SIGNAL(self, tsip_event_code_stack_stopping, "Stack stopping"); - + /* Hangup all dialogs starting by REGISTER */ - if((ret = tsip_dialog_layer_shutdownAll(stack->layer_dialog))){ + if((ret = tsip_dialog_layer_shutdownAll(stack->layer_dialog))) { TSK_DEBUG_WARN("Failed to hang-up all dialogs"); one_failed = tsk_true; } - + /* do not try to clean up transactions ==> each dialog will cancel its transactions. * see tsip_dialog_deinit() which call tsip_transac_layer_cancel_by_dialog() */ - + /* Stop the timer manager */ // not done as it's global (shared). Will be done when all instance are destoyed - + /* Stop the transport layer */ - if((ret = tsip_transport_layer_shutdown(stack->layer_transport))){ + if((ret = tsip_transport_layer_shutdown(stack->layer_transport))) { TSK_DEBUG_WARN("Failed to stop the transport layer"); one_failed = tsk_true; } - - /* Signal to the end-user that the stack has been stopped + + /* Signal to the end-user that the stack has been stopped * should be done before tsk_runnable_stop() which will stop the thread * responsible for the callbacks. The enqueued data have been marked as "important". * As both the timer manager and the transport layer have been stoped there is no * chance to got additional events */ - if(one_failed){ + if(one_failed) { TSIP_STACK_SIGNAL(self, tsip_event_code_stack_failed_to_stop, "Stack failed to stop"); } - else{ + else { TSIP_STACK_SIGNAL(self, tsip_event_code_stack_stopped, "Stack stopped"); } - + /* Stop runnable (run() thread) */ - if((ret = tsk_runnable_stop(TSK_RUNNABLE(stack)))){ + if((ret = tsk_runnable_stop(TSK_RUNNABLE(stack)))) { TSK_DEBUG_WARN("Failed to stop the stack"); one_failed = tsk_true; } - + /* Close all SigComp Compartments (do not remove them) */ - if(stack->sigcomp.handle){ + if(stack->sigcomp.handle) { tsip_sigcomp_close_all(stack->sigcomp.handle); } - + /* reset AoR */ TSK_FREE_TABLE(stack->network.aor.ip); memset(stack->network.aor.port, 0, sizeof(stack->network.aor.port)); - + /* stops timer manager */ - if(stack->timer_mgr_global){ + if(stack->timer_mgr_global) { tsk_timer_mgr_global_unref(&stack->timer_mgr_global); } - - if(!one_failed){ + + if(!one_failed) { stack->started = tsk_false; } - + TSK_DEBUG_INFO("SIP STACK -- STOP"); - - bail: + +bail: tsk_safeobj_unlock(stack); - + return ret; } - + return -1; } /* internal function used to construct a valid contact URI */ tsip_uri_t* tsip_stack_get_contacturi(const tsip_stack_t *stack, const char* protocol) { - if(stack){ + if(stack) { tsk_list_item_t *item; - tsk_list_foreach(item, stack->layer_transport->transports){ + tsk_list_foreach(item, stack->layer_transport->transports) { tsip_transport_t *transport = item->data; - - if(transport){ - if(tsk_striequals(transport->protocol, protocol)){ + + if(transport) { + if(tsk_striequals(transport->protocol, protocol)) { tsip_uri_t* uri = tsk_null; - if((uri = tsip_transport_get_uri(transport, tsk_false))){ + if((uri = tsip_transport_get_uri(transport, tsk_false))) { tsk_strupdate(&uri->user_name, stack->identity.impu->user_name); return uri; } @@ -1050,20 +1070,20 @@ tsip_uri_t* tsip_stack_get_contacturi(const tsip_stack_t *stack, const char* pro /* internal function used to construct a valid Proxy-CSCF URI used as the default first route */ tsip_uri_t* tsip_stack_get_pcscf_uri(const tsip_stack_t *stack, tnet_socket_type_t type, tsk_bool_t lr) { - if(stack){ + if(stack) { const tsip_transport_t *transport = tsk_null; - if(!TNET_SOCKET_TYPE_IS_VALID(type) && !TSK_LIST_IS_EMPTY(stack->layer_transport->transports)){ + if(!TNET_SOCKET_TYPE_IS_VALID(type) && !TSK_LIST_IS_EMPTY(stack->layer_transport->transports)) { transport = stack->layer_transport->transports->head->data; } - else{ + else { transport = tsip_transport_layer_find_by_type(stack->layer_transport, type); } - - if(transport){ + + if(transport) { tsip_uri_t* uri = tsk_null; tsk_bool_t ipv6 = TNET_SOCKET_TYPE_IS_IPV6(transport->type); tsk_bool_t quote_ip = (ipv6 && tsk_strcontains(stack->network.proxy_cscf[transport->idx], tsk_strlen(stack->network.proxy_cscf[transport->idx]), ":")) /* IPv6 IP string?*/; - + char* uristring = tsk_null; tsk_sprintf(&uristring, "%s:%s%s%s:%d;%s;transport=%s", transport->scheme, @@ -1073,16 +1093,16 @@ tsip_uri_t* tsip_stack_get_pcscf_uri(const tsip_stack_t *stack, tnet_socket_type stack->network.proxy_cscf_port[transport->idx], lr ? "lr" : "", transport->protocol); - if(uristring){ - if((uri = tsip_uri_parse(uristring, tsk_strlen(uristring)))){ + if(uristring) { + if((uri = tsip_uri_parse(uristring, tsk_strlen(uristring)))) { //uri->host_type = ipv6 ? thttp_host_ipv6 : thttp_host_ipv4; } TSK_FREE(uristring); } - + return uri; } - + } return tsk_null; } @@ -1100,22 +1120,22 @@ static void* TSK_STDCALL run(void* self) { tsk_list_item_t *curr; tsip_stack_t *stack = self; - + TSK_DEBUG_INFO("SIP STACK::run -- START"); - + TSK_RUNNABLE_RUN_BEGIN(stack); - - if((curr = TSK_RUNNABLE_POP_FIRST(stack))){ + + if((curr = TSK_RUNNABLE_POP_FIRST(stack))) { tsip_event_t *sipevent = (tsip_event_t*)curr->data; - if(stack->callback){ + if(stack->callback) { sipevent->userdata = stack->userdata; // needed by sessionless events stack->callback(sipevent); - } + } tsk_object_unref(curr); } - + TSK_RUNNABLE_RUN_END(self); - + TSK_DEBUG_INFO("SIP STACK::run -- STOP"); return 0; } @@ -1135,36 +1155,36 @@ static void* TSK_STDCALL run(void* self) static tsk_object_t* tsip_stack_ctor(tsk_object_t * self, va_list * app) { tsip_stack_t *stack = self; - if(stack){ + if(stack) { tsk_safeobj_init(stack); } return self; } static tsk_object_t* tsip_stack_dtor(tsk_object_t * self) -{ +{ tsip_stack_t *stack = self; - if(stack){ - + if(stack) { + /* /!\ Order in which objects are destroyed is very important */ - - /* Stop + + /* Stop * Will try to hangup all dialogs */ - if(stack->started){ + if(stack->started) { tsip_stack_stop(stack); } - - /* Layers(1/1): Transacs and dialogs use timer_mgr when destroyed + + /* Layers(1/1): Transacs and dialogs use timer_mgr when destroyed * Dialogs =>(use)=> transacs =>(use)=> transport. */ TSK_OBJECT_SAFE_FREE(stack->layer_dialog); TSK_OBJECT_SAFE_FREE(stack->layer_transac); TSK_OBJECT_SAFE_FREE(stack->layer_transport); - + /* Internals(1/2) */ - if(stack->timer_mgr_global){ + if(stack->timer_mgr_global) { tsk_timer_mgr_global_unref(&stack->timer_mgr_global); } - + /* Identity */ TSK_FREE(stack->identity.display_name); TSK_OBJECT_SAFE_FREE(stack->identity.impu); @@ -1172,64 +1192,63 @@ static tsk_object_t* tsip_stack_dtor(tsk_object_t * self) //TSK_OBJECT_SAFE_FREE(stack->associated_identity); TSK_FREE(stack->identity.impi); TSK_FREE(stack->identity.password); - + /* Network(1/1) */ TSK_FREE_TABLE(stack->network.local_ip); TSK_OBJECT_SAFE_FREE(stack->network.realm); TSK_FREE_TABLE(stack->network.proxy_cscf); TSK_OBJECT_SAFE_FREE(stack->paths); - + TSK_FREE_TABLE(stack->network.aor.ip); - + TSK_OBJECT_SAFE_FREE(stack->service_routes); TSK_OBJECT_SAFE_FREE(stack->associated_uris); - + /* SigComp (MUST be done after transports) */ TSK_OBJECT_SAFE_FREE(stack->sigcomp.handle); - + /* Security(1/1) */ TSK_FREE(stack->security.secagree_mech); TSK_FREE(stack->security.ipsec.alg); TSK_FREE(stack->security.ipsec.ealg); TSK_FREE(stack->security.ipsec.mode); TSK_FREE(stack->security.ipsec.protocol); - + TSK_FREE(stack->security.tls.ca); TSK_FREE(stack->security.tls.pbk); TSK_FREE(stack->security.tls.pvk); - - + + /* DNS */ TSK_OBJECT_SAFE_FREE(stack->dns_ctx); - + /* NAT Traversal context */ TSK_FREE(stack->natt.stun.ip); TSK_FREE(stack->natt.stun.login); TSK_FREE(stack->natt.stun.pwd); TSK_OBJECT_SAFE_FREE(stack->natt.ctx); - + /* DHCP */ - + /* features */ - + /* QoS */ - + /* Internals (2/2) */ TSK_OBJECT_SAFE_FREE(stack->ssessions); TSK_OBJECT_SAFE_FREE(stack->headers); - + tsk_safeobj_deinit(stack); - + TSK_DEBUG_INFO("*** SIP Stack destroyed ***"); } return self; } -static const tsk_object_def_t tsip_stack_def_s = -{ +static const tsk_object_def_t tsip_stack_def_s = { sizeof(tsip_stack_t), - tsip_stack_ctor, + tsip_stack_ctor, tsip_stack_dtor, - tsk_null, + tsk_null, }; const tsk_object_def_t *tsip_stack_def_t = &tsip_stack_def_s; |