doubango/tinySIP/include/tsip.h
c732d49e
 /*
74ca6d11
 * Copyright (C) 2020, University of the Basque Country (UPV/EHU)
c732d49e
 * Contact for licensing options: <licensing-mcpttclient(at)mcopenplatform(dot)com>
 *
 * The original file was part of Open Source Doubango Framework
 * 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.h
  * @brief SIP (RFC 3261) and 3GPP IMS/LTE (TS 24.229) implementation.
  *
  * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
  *
 
  */
 #ifndef TINYSIP_TSIP_H
 #define TINYSIP_TSIP_H
 
 #include "tinysip_config.h"
 
 #include "tinysip/tsip_ssession.h"
 #include "tinysip/tsip_timers.h"
 #include "tinysip/tsip_event.h"
 #include "tinysip/transports/tsip_transport.h"
 
 #include "tinysip/tsip_uri.h"
 
 #include "tinysip/sigcomp/tsip_sigcomp.h"
 
 #include "tinynet.h"
 
 #include "tsk_runnable.h"
 
 TSIP_BEGIN_DECLS
 
 #define TSIP_IARI_GSMAIS				"urn%3Aurn-7%3A3gpp-application.ims.iari.gsma-is"
 #define TSIP_IARI_QUOTED_GSMAIS			"\"" TSIP_IARI_GSMAIS "\""
 #define TSIP_ICSI_MMTEL_PSVOICE			"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel"
 #define TSIP_ICSI_QUOTED_MMTEL_PSVOICE	"\"" TSIP_ICSI_MMTEL_PSVOICE "\""
 
 #define TSIP_STACK(self)		((tsip_stack_t*)(self))
 
 typedef uint8_t amf_t[2];
 typedef uint8_t operator_id_t[16];
 
 // @tinyWRAP
 typedef enum tsip_stack_mode_e
 {
 	tsip_stack_mode_ua,
 	tsip_stack_mode_p2p,
 	tsip_stack_mode_webrtc2sip,
 	tsip_stack_mode_mcu
 }
 tsip_stack_mode_t;
 #define TSIP_STACK_MODE_IS_SERVER(stack) ((stack)->network.mode == tsip_stack_mode_webrtc2sip || (stack)->network.mode == tsip_stack_mode_mcu)
 #define TSIP_STACK_MODE_IS_CLIENT(stack) (!TSIP_STACK_MODE_IS_SERVER((stack)))
 
 typedef enum tsip_stack_param_type_e
 {
 	tsip_pname_null = 0,
 	
 	/* === Identity === */
 	tsip_pname_display_name,
 	tsip_pname_impu,
 	tsip_pname_preferred_id,
 	tsip_pname_impi,
 	tsip_pname_password,
 
 	/* === SigComp === */
 	tsip_pname_sigcomp,
 	tsip_pname_sigcomp_add_compartment,
 	tsip_pname_sigcomp_remove_compartment,
 
 	/* === Network === */
 	tsip_pname_realm,
 	tsip_pname_local_ip,
 	tsip_pname_local_port,
 	tsip_pname_aor,
 	tsip_pname_discovery_naptr,
 	tsip_pname_discovery_dhcp,
 	tsip_pname_proxy_cscf,
 	tsip_pname_dnsserver,
 	tsip_pname_max_fds,
 	tsip_pname_mode,
 
 	
 	/* === Security === */
 	tsip_pname_early_ims,
 	tsip_pname_secagree_ipsec,
 	tsip_pname_secagree_tls,
 	tsip_pname_amf,
 	tsip_pname_operator_id,
 	tsip_pname_tls_certs,
 	tsip_pname_ipsec_params,
 
 	/* === Dummy Headers === */
 	tsip_pname_header,
 
 	/* Nat Traversal */
 	tsip_pname_stun_enabled,
 	tsip_pname_stun_server,
 	tsip_pname_stun_cred,
 
 	/* === User Data === */
 	tsip_pname_userdata,
 
 	/* === PTT MCPTT === */
 	tsip_pname_mcptt_psi_private,
 	tsip_pname_mcptt_psi_group,
 	tsip_pname_mcptt_psi_preestablished,
175b478c
 	tsip_pname_mcptt_psi_cms,
 	tsip_pname_mcptt_psi_gms,
 	tsip_pname_mcptt_client_id,
c732d49e
 	tsip_pname_mcptt_id,
175b478c
 	tsip_pname_client_id,
c732d49e
 	tsip_pname_mcptt_access_token,
 	tsip_pname_mcptt_priority,
 	tsip_pname_mcptt_implicit,
 	tsip_pname_mcptt_granted,
 	tsip_pname_mcptt_answer_mode,
 	tsip_pname_mcptt_priv_answer_mode,
 	tsip_pname_mcptt_namespace,
 	tsip_pname_mcptt_insert_x_Framed_IP,
 	tsip_pname_mcptt_timer_T100,
 	tsip_pname_mcptt_timer_T101,
 	tsip_pname_mcptt_timer_T103,
 	tsip_pname_mcptt_timer_T104,
 	tsip_pname_mcptt_timer_T132,
 	//MCPTT LOCATION
 	tsip_location_p_asserted_identity,
 	//MCPTT MBMS
 	tsip_mbms_p_asserted_identity,
 	//MCPTT MBMS
 	tsip_mbms_port_manager,
 	//MCPTT MBMS
 	tsip_mbms_addr_manager,
 	//MCPTT MBMS
 	tsip_mbms_is_rtcp_mux,
 	
 	//MCPTT AFFILIATION
 	tsip_pname_mcptt_psi_affiliation,
 	tsip_pname_mcptt_affiliation_is_enable,
 	tsip_pname_mcptt_affiliation_groups_default,
175b478c
 	//MCPTT AUTHENTICATION
 	tsip_pname_mcptt_psi_authentcation,
c732d49e
 }
 tsip_stack_param_type_t;
 
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_NULL
 * Ends the stack parameters. Mandatory and should be the last one.
 */
 #define TSIP_STACK_SET_NULL()							tsip_pname_null
 
 /* === Identity === */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_DISPLAY_NAME
 * Sets the user's display name. Used in SIP 'From' and 'To' headers.
 * @param NAME_STR The user's display name.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_DISPLAY_NAME("john doe"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_IMPU
 * Sets the user's IMPU (IMS Public Identity).
 * @param URI_STR A valid SIP/SIPS/tel URI string.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_IMPU("sip:johndoe@open-ims.test"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_PREFERRED_IDENTITY
 * Sets the user's Preferred Identity. Used to populate the P-Preferred-Identity header.
 * @param URI_STR A valid SIP/SIPS/tel URI string.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_PREFERRED_IDENTITY("sip:johndoe@open-ims.test"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_IMPI
 * Sets the user's IMPI (IMS Private Identity).
 * @param IMPI_STR Any string.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_IMPI("johndoe@open-ims.test"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_PASSWORD
 * Sets the user's password.
 * @param PASSORD_STR Any string.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_PASSWORD("mysecret"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 */
 #define TSIP_STACK_SET_DISPLAY_NAME(NAME_STR)			tsip_pname_display_name, (const char*)NAME_STR
 #define TSIP_STACK_SET_IMPU(URI_STR)					tsip_pname_impu, (const char*)URI_STR
 #define TSIP_STACK_SET_PREFERRED_IDENTITY(URI_STR)		tsip_pname_preferred_id, (const char*)URI_STR
 #define TSIP_STACK_SET_IMPI(IMPI_STR)					tsip_pname_impi, (const char*)IMPI_STR
 #define TSIP_STACK_SET_PASSWORD(PASSORD_STR)			tsip_pname_password, (const char*)PASSORD_STR
 
 
 /* === SigComp === */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_SIGCOMP
 * Sets the SigComp parameters. It's not mandatory to call this function in order to use SigComp.
 * It should be called to change default parameters. As these parameters will be shared by all compartments,
 * you should call this function before adding any compartment.
 * @param DMS_UINT Decompression Memory Size. Default value is 8192.
 * @param SMS_UINT State Memory Size. Default value is 8192.
 * @param CPB_UINT Cycles Per Bit. Default value is 64.
 * @param PRES_DICT_BOOL Indicates whether to enable Presence dictionary (RFC 5112) or not. Default value is @a tsk_false.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_SIGCOMP(8192, 8192, 64, tsk_true),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_SIGCOMP_NEW_COMPARTMENT
 * Add New unique compartment identifier to the stack. This compartment will be closed (not removed) when the stack is stopped.
 * A any time, you can remove this compartment by using @ref TSIP_STACK_UNSET_SIGCOMP_COMPARTMENT().
 * @param COMPARTMENT_ID_STR The id of the compartment to add. Should be unique.
 * The identifier will be used to in the sip headers (as per RFC 5049) "AS IS".<br>
 * @sa @ref TSIP_STACK_UNSET_SIGCOMP_COMPARTMENT()
 *
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_NEW_SIGCOMP_COMPARTMENT("urn:uuid:0C67446E-F1A1-11D9-94D3-000A95A0E128"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_UNSET_SIGCOMP_COMPARTMENT
 * Removes a SigComp compartment. This will close the compartment and release all its states.
 * You should only close a compartment if there is no outgoing session using it. In all cases, all compartments
 * will be closed when the stack is destroyed or stopped.
 * @param COMPARTMENT_ID_STR The id of the compartment to close.
 * @sa @ref TSIP_STACK_SET_SIGCOMP_NEW_COMPARTMENT()
 *
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_UNSET_SIGCOMP_COMPARTMENT("urn:uuid:0C67446E-F1A1-11D9-94D3-000A95A0E128"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 */
 #define TSIP_STACK_SET_SIGCOMP(DMS_UINT, SMS_UINT, CPB_UINT, PRES_DICT_BOOL) tsip_pname_sigcomp, (unsigned)DMS_UINT, (unsigned)SMS_UINT, (unsigned)CPB_UINT, (tsk_bool_t)PRES_DICT_BOOL
 #define TSIP_STACK_SET_SIGCOMP_NEW_COMPARTMENT(COMPARTMENT_ID_STR)			tsip_pname_sigcomp_add_compartment, (const char*)COMPARTMENT_ID_STR
 #define TSIP_STACK_UNSET_SIGCOMP_COMPARTMENT(COMPARTMENT_ID_STR)			tsip_pname_sigcomp_remove_compartment, (const char*)COMPARTMENT_ID_STR
 
 /* === Network === */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_REALM
 * Sets the domain name.
 * @param URI_STR A valid SIP/SIPS URI string.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_REALM("sip:open-ims.test"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_LOCAL_IP
 * Sets the user's local IP address.
 * @param IP_STR IPv4/IPv6 IP address or FQDN.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_LOCAL_IP("fe80::"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref  TSIP_STACK_SET_LOCAL_PORT()<br>@ref TSIP_STACK_SET_AOR()
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_LOCAL_PORT
 * Sets the user's local Port to bind to.
 * @param PORT_UINT Port number. Should be between 0x0400 and 0xFFFF.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_LOCAL_PORT(5060),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @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
 * is missing, then this option will be enabled by default.
 * @param ENABLED_BOOL @a tsk_true (1) or @a tsk_false (0).
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_DISCOVERY_NAPTR(tsk_true),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_SET_DISCOVERY_DHCP()
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_DISCOVERY_DHCP
 * Whether to use DHCPv4/v6 for Proxy-CSCF discovery. Default is false. The IP version (v4/v6) of the DHCP protocol
 * to use will depend on the Proxy-CSCF address type.
 * @param ENABLED_BOOL @a tsk_true (1) or @a tsk_false (0).
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_DISCOVERY_DHCP(tsk_false),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_SET_DISCOVERY_NAPTR()
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_PROXY_CSCF
 * Configures the Proxy-CSCF. 
 * @param FQDN_STR The IP address (v4/v6) or FQDN of the Proxy-CSCF.
 * @param PORT_UINT The port.
 * @param TRANSPORT_STR The transport type. Should be: @a "udp" or @a "tcp" or @a "tls" or @a "sctp". Default is @a "udp".
 * @param IP_VERSION_STR The IP version to use. Should be:  @a "ipv4" or @a "ipv6" or @a "ipv46". This parameter is useful when 
 * @a FQDN_STR parameter is a domain name. default is @a "ipv4".
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_PROXY_CSCF("pcscf-doubango.org", 4060, "tcp", "ipv6"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_SET_DISCOVERY_DHCP()<br>@ref TSIP_STACK_SET_DISCOVERY_NAPTR()
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_DNS_SERVER
 * Adds a DNS server.
 * @param IP_STR The IP address or FQDN of the DNS server to add.
 * @code
  // Add two new DNS servers (IPv6 and IPv4)
 int ret = tsip_stack_set(stack, 
               TSIP_STACK_SET_DNS_SERVER("192.16.16.9"),
 			  TSIP_STACK_SET_DNS_SERVER("fe::"),
               TSIP_STACK_SET_NULL());
 * @endcode
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_MODE_SERVER
 * Configure the stack to be used as server. Cannot be changed later.
 * @code
 int ret = tsip_stack_set(stack, 
               TSIP_STACK_SET_MODE_SERVER(),
               TSIP_STACK_SET_NULL());
 * @endcode
 */
 #define TSIP_STACK_SET_REALM(URI_STR)															tsip_pname_realm, (const char*)URI_STR
 #define TSIP_STACK_SET_LOCAL_IP_2(TRANSPORT_STR, IP_STR)										tsip_pname_local_ip, (const char*)TRANSPORT_STR, (const char*)IP_STR
 #define TSIP_STACK_SET_LOCAL_PORT_2(TRANSPORT_STR, PORT_UINT)									tsip_pname_local_port, (const char*)TRANSPORT_STR, (unsigned)PORT_UINT
 #define TSIP_STACK_SET_LOCAL_IP(IP_STR)															TSIP_STACK_SET_LOCAL_IP_2(tsk_null, IP_STR)// @deprecated
 #define TSIP_STACK_SET_LOCAL_PORT(PORT_UINT)													TSIP_STACK_SET_LOCAL_PORT_2(tsk_null, PORT_UINT)// @deprecated
 #define TSIP_STACK_SET_AOR_2(TRANSPORT_STR, IP_STR, PORT_UINT)									tsip_pname_aor, (const char*)TRANSPORT_STR, (const char*)IP_STR, (unsigned)PORT_UINT
 #define TSIP_STACK_SET_AOR(IP_STR, PORT_UINT)													TSIP_STACK_SET_AOR_2(tsk_null, IP_STR, PORT_UINT)// @deprecated
 #define TSIP_STACK_SET_DISCOVERY_NAPTR(ENABLED_BOOL)											tsip_pname_discovery_naptr, (tsk_bool_t)ENABLED_BOOL
 #define TSIP_STACK_SET_DISCOVERY_DHCP(ENABLED_BOOL)												tsip_pname_discovery_dhcp, (tsk_bool_t)ENABLED_BOOL
 #define TSIP_STACK_SET_PROXY_CSCF(FQDN_STR, PORT_UINT, TRANSPORT_STR, IP_VERSION_STR)			tsip_pname_proxy_cscf, (const char*)FQDN_STR, (unsigned)PORT_UINT, (const char*)TRANSPORT_STR, (const char*)IP_VERSION_STR
 #define TSIP_STACK_SET_DNS_SERVER(IP_STR)														tsip_pname_dnsserver, (const char*)IP_STR
 #define TSIP_STACK_SET_MAX_FDS(MAX_FDS_UINT)													tsip_pname_max_fds, (unsigned)MAX_FDS_UINT
 #define TSIP_STACK_SET_MODE(MODE_ENUM)															tsip_pname_mode, (tsip_stack_mode_t)MODE_ENUM
 
 /* === Security === */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_EARLY_IMS
 * Whether to enable 3GPP Early-IMS Security as per 3GPP TS 33.978. 
 * @param ENABLED_BOOL @a tsk_true (1) or @a tsk_false (0).
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_EARLY_IMS(tsk_false),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_SECAGREE_IPSEC
 * Whether to enable IPSec security agreement as per IETF RFC 3329. 
 * @param ENABLED_BOOL @a tsk_true (1) or @a tsk_false (0).
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_SECAGREE_IPSEC(tsk_true),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_SET_IPSEC_PARAMS()
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_SECAGREE_TLS
 * Whether to enable TLS security agreement as per IETF RFC 3329. 
 * @param ENABLED_BOOL @a tsk_true (1) or @a tsk_false (0).
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_SECAGREE_TLS(tsk_true),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_SET_IPSEC_PARAMS()
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_IMS_AKA_AMF
 * Sets AMF (Authentication Management Field) value to use for IMS-AKA authentication.
 * @param AMF_UINT16 16-bit value.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_IMS_AKA_AMF(0x3FB6),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_SET_IMS_AKA_OPERATOR_ID()
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_IMS_AKA_OPERATOR_ID
 * Sets the operator identifier value to use for IMS-AKA authentication.
 * @param OPID_HEX_STR 128-bit value as hex-string. If the length of the value supplied by the user is less than 128 bits,
 * then it will be padded with zeros.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_IMS_AKA_OPERATOR_ID("0x5FABC9"), // Will be padded with zeros
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_SET_IMS_AKA_AMF()
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_IPSEC_PARAMS
 * Sets the IPSec parameters. To enable IPSec security agreement you should use @ref TSIP_STACK_SET_SECAGREE_IPSEC(tsk_true).
 * @param ALG_STR Algorithm. Should be: @a "hmac-sha-1-96" or @a "hmac-md5-96". Default is @a "hmac-md5-96".
 * @param EALG_STR Encryption Algorithm. Should be: @a "des-ede3-cbc" or @a "aes" or @a "null". Default is @a "null".
 * @param MODE_STR Mode. Should be: @a "tun" or @a "trans". Default is @a "trans".
 * @param PROTOCOL_STR Protocol. Should be @a "ah" or @a "esp" or @a "ah/esp". Default is @a "esp".
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_SECAGREE_IPSEC(tsk_true),
                TSIP_STACK_SET_IPSEC_PARAMS("hmac-md5-96", "des-ede3-cbc", "trans", "esp"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_SET_TLS_CERTS()
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_TLS_CERTS
 * Sets TLS certificate files. To enable TLS security agreement you should use @ref TSIP_STACK_SET_SECAGREE_TLS(tsk_true).
 * @param CA_FILE_STR CA file.
 * @param PUB_FILE_STR Public cert. file.
 * @param PRIV_FILE_STR Private cert. file.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_TLS_CERTS("C:\\tls\\ca.pki-crt.pem", "C:\\tls\\pub-crt.pem", "C:\\tls\\priv-key.pem"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_SET_IPSEC_PARAMS()
 */
 #define TSIP_STACK_SET_EARLY_IMS(ENABLED_BOOL)												tsip_pname_early_ims, (tsk_bool_t)ENABLED_BOOL
 #define TSIP_STACK_SET_SECAGREE_IPSEC_2(TRANSPORT_STR, ENABLED_BOOL)						tsip_pname_secagree_ipsec, (const char*)TRANSPORT_STR, (tsk_bool_t)ENABLED_BOOL
 #define TSIP_STACK_SET_SECAGREE_IPSEC(ENABLED_BOOL)											TSIP_STACK_SET_SECAGREE_IPSEC_2(tsk_null, ENABLED_BOOL) // @deprecated
 #define TSIP_STACK_SET_SECAGREE_TLS(ENABLED_BOOL)											tsip_pname_secagree_tls, (tsk_bool_t)ENABLED_BOOL
 #define TSIP_STACK_SET_IMS_AKA_AMF(AMF_UINT16)												tsip_pname_amf, (uint16_t)AMF_UINT16
 #define TSIP_STACK_SET_IMS_AKA_OPERATOR_ID(OPID_HEX_STR)									tsip_pname_operator_id, (const char*)OPID_HEX_STR
 #define TSIP_STACK_SET_IPSEC_PARAMS(ALG_STR, EALG_STR, MODE_STR, PROTOCOL_STR)				tsip_pname_ipsec_params, (const char*)ALG_STR, (const char*)EALG_STR, (const char*)MODE_STR, (const char*)PROTOCOL_STR
 #define TSIP_STACK_SET_TLS_CERTS(CA_FILE_STR, PUB_FILE_STR, PRIV_FILE_STR)					TSIP_STACK_SET_TLS_CERTS_2(CA_FILE_STR, PUB_FILE_STR, PRIV_FILE_STR, tsk_false)
 #define TSIP_STACK_SET_TLS_CERTS_2(CA_FILE_STR, PUB_FILE_STR, PRIV_FILE_STR, VERIF_BOOL)	tsip_pname_tls_certs, (const char*)CA_FILE_STR, (const char*)PUB_FILE_STR, (const char*)PRIV_FILE_STR, (tsk_bool_t)VERIF_BOOL
 
 /* === Headers === */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_HEADER
 * Adds or updates a stack-level header.
 * @param NAME_STR The name of the header to add or update.
 * @param VALUE_STR The value of the header to add or update.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_HEADER("User-Agent", "IM-client/OMA1.0 doubango/v1.0.0"),
 *              TSIP_STACK_SET_HEADER("Allow", "INVITE, ACK, CANCEL, BYE, MESSAGE, OPTIONS, NOTIFY, PRACK, UPDATE, REFER"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_UNSET_HEADER()
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_HEADER
 * Removes a stack-level header.
 * @param NAME_STR The name of the header to remove.
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_UNSET_HEADER("User-Agent"),
 *              TSIP_STACK_UNSET_HEADER("Allow"),
 *              TSIP_STACK_UNSET_HEADER("My_Header"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_SET_HEADER()
 */
 #define TSIP_STACK_SET_HEADER(NAME_STR, VALUE_STR)		tsip_pname_header, (const char*)NAME_STR, (const char*)VALUE_STR
 #define TSIP_STACK_UNSET_HEADER(NAME_STR)				TSIP_STACK_SET_HEADER(NAME_STR, ((const char*)-1))
 
 /* === NAT Traversal === */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_STUN_SERVER
 * Sets the IP address and port of the STUN2 server. Also used for TURN.
 * @param IP_STR The IPv4/IPv6 address for FQDN of the STUN2/TURN address.
 * @param PORT_UINT The server port (default is 3478 for both TCP and UDP, and 5349 for TLS)
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_STUN_SERVER("numb.viagenie.ca", 3478),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_SET_STUN_CRED()
 */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_STUN_CRED
 * Sets STUN/TURN credentials.
 * @param USR_STR The login.
 * @param PASSORD_STR The password
 * @code
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_STUN_CRED("bob@open-ims.test", "mysecret"),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 *
 * @sa @ref TSIP_STACK_SET_STUN_SERVER()
 */
 #define TSIP_STACK_SET_STUN_SERVER(IP_STR, PORT_UINT)	tsip_pname_stun_server, (const char*)IP_STR, (unsigned)PORT_UINT
 #define TSIP_STACK_SET_STUN_CRED(USR_STR, PASSORD_STR)	tsip_pname_stun_cred, (const char*)USR_STR, (const char*)PASSORD_STR
 #define TSIP_STACK_SET_STUN_ENABLED(ENABLED_BOOL)		tsip_pname_stun_enabled, (tsk_bool_t)ENABLED_BOOL
 
 /* === User Data === */
 /**@ingroup tsip_stack_group
 * @def TSIP_STACK_SET_USERDATA
 * Sets opaque user's data returned in each callback. Could be used to store the context.
 * @param DATA_PTR Pointer to the user data.
 * @code
 * const void* context;
 * int ret = tsip_stack_set(stack, 
 *              TSIP_STACK_SET_USERDATA(context),
 *              TSIP_STACK_SET_NULL());
 * @endcode
 */
 #define TSIP_STACK_SET_USERDATA(DATA_PTR)		tsip_pname_userdata, (const void*)DATA_PTR
 
 /* === MCPTT === */
 #define TSIP_STACK_SET_MCPTT_PSI_PRIVATE(PSI_PRIVATE)		tsip_pname_mcptt_psi_private, (const char*)PSI_PRIVATE
 #define TSIP_STACK_SET_MCPTT_PSI_GROUP(PSI_GROUP)		tsip_pname_mcptt_psi_group, (const char*)PSI_GROUP
 #define TSIP_STACK_SET_MCPTT_PSI_PREESTABLISHED(PSI_PREESTABLISHED)		tsip_pname_mcptt_psi_preestablished, (const char*)PSI_PREESTABLISHED
175b478c
 
 #define TSIP_STACK_SET_MCPTT_PSI_CMS(PSI_CMS)		tsip_pname_mcptt_psi_cms, (const char*)PSI_CMS
 
 #define TSIP_STACK_SET_MCPTT_PSI_GMS(PSI_GMS)		tsip_pname_mcptt_psi_gms, (const char*)PSI_GMS
 
c732d49e
 #define TSIP_STACK_SET_MCPTT_ID(MCPTT_ID)		tsip_pname_mcptt_id, (const char*)MCPTT_ID
175b478c
 #define TSIP_STACK_SET_MCPTT_CLIENT_ID(MCPTT_CLIENT_ID)		tsip_pname_mcptt_client_id, (const char*)MCPTT_CLIENT_ID
 #define TSIP_STACK_SET_CLIENT_ID(CLIENT_ID)		tsip_pname_client_id, (const char*)CLIENT_ID
c732d49e
 #define TSIP_STACK_SET_MCPTT_PRIORITY(MCPTT_PRIORITY)		tsip_pname_mcptt_priority, (const int)MCPTT_PRIORITY
 #define TSIP_STACK_SET_MCPTT_IMPLICIT(MCPTT_IMPLICIT)		tsip_pname_mcptt_implicit, (const tsk_bool_t)MCPTT_IMPLICIT
 #define TSIP_STACK_SET_MCPTT_GRANTED(MCPTT_GRANTED)		tsip_pname_mcptt_granted, (const tsk_bool_t)MCPTT_GRANTED
 
 
 #define TSIP_STACK_SET_MCPTT_ANSWER_MODE(MCPTT_ANSWER_MODE)		tsip_pname_mcptt_answer_mode, (const tsk_bool_t)MCPTT_ANSWER_MODE
 #define TSIP_STACK_SET_MCPTT_PRIV_ANSWER_MODE(MCPTT_PRIV_ANSWER_MODE)		tsip_pname_mcptt_priv_answer_mode, (const tsk_bool_t)MCPTT_PRIV_ANSWER_MODE
 #define TSIP_STACK_SET_MCPTT_NAMESPACE(MCPTT_NAMESPACE)		tsip_pname_mcptt_namespace, (const tsk_bool_t)MCPTT_NAMESPACE
 #define TSIP_STACK_SET_MCPTT_INSERT_X_FRAMED_IP(MCPTT_INSERT_X_FRAMED_IP)		tsip_pname_mcptt_insert_x_Framed_IP, (const tsk_bool_t)MCPTT_INSERT_X_FRAMED_IP
 
 
175b478c
 //Timers received from CMS
c732d49e
 #define TSIP_STACK_SET_MCPTT_TIMER_T100(MCPTT_TIMER_T100)		tsip_pname_mcptt_timer_T100, (const int)MCPTT_TIMER_T100
 #define TSIP_STACK_SET_MCPTT_TIMER_T101(MCPTT_TIMER_T101)		tsip_pname_mcptt_timer_T101, (const int)MCPTT_TIMER_T101
 #define TSIP_STACK_SET_MCPTT_TIMER_T103(MCPTT_TIMER_T103)		tsip_pname_mcptt_timer_T103, (const int)MCPTT_TIMER_T103
 #define TSIP_STACK_SET_MCPTT_TIMER_T104(MCPTT_TIMER_T104)		tsip_pname_mcptt_timer_T104, (const int)MCPTT_TIMER_T104
 #define TSIP_STACK_SET_MCPTT_TIMER_T132(MCPTT_TIMER_T132)		tsip_pname_mcptt_timer_T132, (const int)MCPTT_TIMER_T132
 
 
 //MCPTT LOCATION
 #define TSIP_STACK_SET_LOCATION_P_ASSERTED_IDENTITY(P_ASSERTED_IDENTITY)		tsip_location_p_asserted_identity, (const char*)P_ASSERTED_IDENTITY
 //MCPTT MBMS
 #define TSIP_STACK_SET_MBMS_P_ASSERTED_IDENTITY(P_ASSERTED_IDENTITY_MBMS)		tsip_mbms_p_asserted_identity, (const char*)P_ASSERTED_IDENTITY_MBMS
 //MCPTT MBMS
 #define TSIP_STACK_SET_MBMS_PORT_MANAGER(PORT_MANAGER_MBMS)		tsip_mbms_port_manager, (const int)PORT_MANAGER_MBMS
 //MCPTT MBMS
 #define TSIP_STACK_SET_MBMS_ADDR_MANAGER(ADDR_MANAGER_MBMS)		tsip_mbms_addr_manager, (const char*)ADDR_MANAGER_MBMS
 //MCPTT MBMS
 #define TSIP_STACK_SET_MBMS_IS_RTCP_MUX(IS_RTCP_MUX_MBMS)		tsip_mbms_is_rtcp_mux, (const tsk_bool_t)IS_RTCP_MUX_MBMS
 
175b478c
 
 
 
 
c732d49e
 //MCPTT AFFILIATION
 #define TSIP_STACK_SET_MCPTT_PSI_AFFILIATION(PSI_AFFILIATION)		tsip_pname_mcptt_psi_affiliation, (const char*)PSI_AFFILIATION
 #define TSIP_STACK_SET_MCPTT_AFFILIATION_IS_ENABLE(IS_ENABLE)		tsip_pname_mcptt_affiliation_is_enable, (const tsk_bool_t)IS_ENABLE
 #define TSIP_STACK_SET_MCPTT_AFFILIATION_GROUPS_DEFAULT(GROUPS_DEFAULT)		tsip_pname_mcptt_affiliation_groups_default, (const tsip_uris_L_t*)GROUPS_DEFAULT
175b478c
 //MCPTT AUTHENTICATION
 #define TSIP_STACK_SET_MCPTT_PSI_AUTHENTICATION(PSI_AUTHENTICATION)		tsip_pname_mcptt_psi_authentcation, (const char*)PSI_AUTHENTICATION
c732d49e
 /* 3GPP IMS/LTE stack (for internal use). only tsip_stack_handle_t should be visible. */
 typedef struct tsip_stack_s
 {
 	TSK_DECLARE_RUNNABLE;
 	TSK_DECLARE_SAFEOBJ;
 	
 	tsk_timer_manager_handle_t* timer_mgr_global;
 	tsk_bool_t started;
 	tsip_stack_callback_f callback;
 
 	/* === Identity === */
 	struct{
 		char* display_name;
 		tsip_uri_t *impu;
 		tsip_uri_t *preferred;
 		char *impi;
 		char *password;
 	} identity;
 
 	/* === SigComp === */
 	struct{
 		tsip_sigcomp_handle_t* handle;
 
 		unsigned dms;
 		unsigned sms;
 		unsigned cpb;
 		tsk_bool_t sip_dict;
 		tsk_bool_t pres_dict;
 	} sigcomp;
 
 	/* === Network === */
 	struct{
 		tsip_stack_mode_t mode;
 
 		char *local_ip[TSIP_TRANSPORT_IDX_MAX];
 		tnet_port_t local_port[TSIP_TRANSPORT_IDX_MAX];
 
 		char *proxy_cscf[TSIP_TRANSPORT_IDX_MAX];
 		tnet_port_t proxy_cscf_port[TSIP_TRANSPORT_IDX_MAX];
 		tnet_socket_type_t proxy_cscf_type[TSIP_TRANSPORT_IDX_MAX];
 		tnet_socket_type_t transport_types[TSIP_TRANSPORT_IDX_MAX];
 		int32_t transport_idx_default;
 		
 		tsip_uri_t *realm;
 		
 		//! IP adddress and port to use as AOR (user-defined)
 		struct{
 			char* ip[TSIP_TRANSPORT_IDX_MAX];
 			tnet_port_t port[TSIP_TRANSPORT_IDX_MAX];
 		} aor;
 		
 		tsk_bool_t discovery_naptr;
 		tsk_bool_t discovery_dhcp;
 
 		tsk_size_t max_fds;
 	} network;
 
 	/* === Security === */
 	struct{
 		char* secagree_mech;
 		tsk_bool_t earlyIMS;
 		operator_id_t operator_id;
 		amf_t amf;
 		
 		/* IPSec */
 		struct{
 			char* alg;
 			char* ealg;
 			char* mode;
 			char* protocol;
 		} ipsec;
 		tsk_bool_t enable_secagree_ipsec;
 		
 		/* TLS */
 		struct {
 			char* ca;
 			char* pbk;
 			char* pvk;
 			tsk_bool_t verify;
 		}tls;
 		tsk_bool_t enable_secagree_tls;
 	} security;
 	
 	tsip_uris_L_t* paths;
 	tsip_uris_L_t* service_routes;
 	tsip_uris_L_t* associated_uris;
 
 	/* DNS context */
 	tnet_dns_ctx_t *dns_ctx;
 
 	/* NAT Traversal context */
 	struct {
 		// STUN
 		struct{
 			char* ip;
 			tnet_port_t port;
 			char* login;
 			char* pwd;
 			tsk_bool_t enabled;
 		} stun;
 		struct tnet_nat_ctx_s* ctx;
 	} natt;
 
 	/* MCPTT context */
 	struct {
 		tsip_uri_t* psi_private;
 		tsip_uri_t* psi_group;
 		tsip_uri_t* psi_preestablished;
175b478c
 
 		tsip_uri_t* psi_cms;
 
 		tsip_uri_t* psi_gms;
 		tsk_buffer_t* mcptt_client_id;
c732d49e
 		tsip_uri_t* mcptt_id;
175b478c
 		tsip_uri_t* client_id;
c732d49e
 		int mcptt_priority;
 		tsk_bool_t mcptt_implicit;
 		tsk_bool_t mcptt_granted;
 		tsk_bool_t mcptt_answer_mode;
 		tsk_bool_t mcptt_priv_answer_mode;
 		tsk_bool_t mcptt_namespace;
 		tsk_bool_t mcptt_insert_x_Framed_IP;
 		struct{
175b478c
 			//This times are in seconds.
c732d49e
 			uint32_t timer_t100;
 			uint32_t timer_t101;
 			uint32_t timer_t103;
 			uint32_t timer_t104;
 			uint32_t timer_t132;
175b478c
 		}timer_s; //
c732d49e
 		
 		
 		
 	} pttMCPTT;
 
 	/* MCPTT AFFILIATION context */
 	struct {
 		//MCPTT AFFILIATION
 	tsip_uri_t* psi_affiliation;
 	tsk_bool_t mcptt_affiliation_is_enable;
 	tsip_uris_L_t* mcptt_affiliation_groups_default;
 	} pttMCPTTAffiliation;
175b478c
 	/* MCPTT AUTHENTICATION context */
 	struct {
 		//MCPTT AUTHENTICATION
 	tsip_uri_t* psi_authentication;
 	} pttMCPTTAuthentication;
c732d49e
 	//=======
 	//  MCPTT LOCATION
 	//=======
 	struct{
 		tsip_uri_t* p_asserted_identity_location;
 	}sessionLocation;
 	//=======
 	//  MCPTT MBMS
 	//=======
 	struct{
 		tsip_uri_t* p_asserted_identity_mbms;
 		//Internal process
 		uint32_t port_manager;
 		char* addr_multicast;
 		tsk_bool_t is_rtcp_mux;
 		tsdp_message_t* sdp_ro;
 	}pttMCPTTMbms;
 
175b478c
 
 
c732d49e
 	/* DHCP context */	
 
 	/* QoS */
 
 	/* Internals. */
 	//tsk_timer_manager_handle_t* timer_mgr;
 	tsip_timers_t timers;
 	tsip_ssessions_L_t *ssessions;
 	tsk_params_L_t *headers;
 	const void* userdata;
 
 	/* Layers */
 	struct tsip_dialog_layer_s *layer_dialog;
 	struct tsip_transac_layer_s *layer_transac;
 	struct tsip_transport_layer_s *layer_transport;
 }
 tsip_stack_t;
 
 
 
 
 TINYSIP_API tsip_stack_handle_t *tsip_stack_create(tsip_stack_callback_f callback, const char* realm_uri, const char* impi_uri, const char* impu_uri, ...);
 TINYSIP_API int tsip_stack_start(tsip_stack_handle_t *self);
 TINYSIP_API int tsip_stack_set(tsip_stack_handle_t *self, ...);
 TINYSIP_API const void* tsip_stack_get_userdata(const tsip_stack_handle_t *self);
 TINYSIP_API tnet_dns_ctx_t* tsip_stack_get_dnsctx(tsip_stack_handle_t *self);
 TINYSIP_API tsip_uri_t* tsip_stack_get_preferred_id(tsip_stack_handle_t *self);
 TINYSIP_API 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);
 TINYSIP_API int tsip_stack_stop(tsip_stack_handle_t *self);
 
 #define TSIP_STACK_EVENT_RAISE(stack, status_code, reason_phrase, incoming, type) \
 	TSK_RUNNABLE_ENQUEUE(TSK_RUNNABLE(stack), (const tsip_stack_handle_t*)stack, (short)status_code, (const char*)reason_phrase, (unsigned)incoming, (tsip_event_type_t)type);
 
 
 TINYSIP_GEXTERN const tsk_object_def_t *tsip_stack_def_t;
 
 TSIP_END_DECLS
 
 #endif /* TINYSIP_TSIP_H */