diff options
Diffstat (limited to 'pjnath/include')
-rw-r--r-- | pjnath/include/pjnath.h | 35 | ||||
-rw-r--r-- | pjnath/include/pjnath/config.h | 495 | ||||
-rw-r--r-- | pjnath/include/pjnath/errno.h | 226 | ||||
-rw-r--r-- | pjnath/include/pjnath/ice_session.h | 973 | ||||
-rw-r--r-- | pjnath/include/pjnath/ice_strans.h | 816 | ||||
-rw-r--r-- | pjnath/include/pjnath/nat_detect.h | 208 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_auth.h | 457 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_config.h | 128 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_msg.h | 1820 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_session.h | 762 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_sock.h | 446 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_transaction.h | 276 | ||||
-rw-r--r-- | pjnath/include/pjnath/turn_session.h | 730 | ||||
-rw-r--r-- | pjnath/include/pjnath/turn_sock.h | 397 | ||||
-rw-r--r-- | pjnath/include/pjnath/types.h | 76 |
15 files changed, 7845 insertions, 0 deletions
diff --git a/pjnath/include/pjnath.h b/pjnath/include/pjnath.h new file mode 100644 index 0000000..fc5eebb --- /dev/null +++ b/pjnath/include/pjnath.h @@ -0,0 +1,35 @@ +/* $Id: pjnath.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <pjnath/config.h> +#include <pjnath/errno.h> +#include <pjnath/ice_session.h> +#include <pjnath/ice_strans.h> +#include <pjnath/nat_detect.h> +#include <pjnath/stun_auth.h> +#include <pjnath/stun_config.h> +#include <pjnath/stun_msg.h> +#include <pjnath/stun_session.h> +#include <pjnath/stun_sock.h> +#include <pjnath/stun_transaction.h> +#include <pjnath/turn_session.h> +#include <pjnath/turn_sock.h> +#include <pjnath/types.h> + diff --git a/pjnath/include/pjnath/config.h b/pjnath/include/pjnath/config.h new file mode 100644 index 0000000..06368df --- /dev/null +++ b/pjnath/include/pjnath/config.h @@ -0,0 +1,495 @@ +/* $Id: config.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_CONFIG_H__ +#define __PJNATH_CONFIG_H__ + + +/** + * @file config.h + * @brief Compile time settings + */ + +#include <pj/types.h> + +/** + * @defgroup PJNATH_CONFIG Compile-time configurations + * @brief Various compile time settings + * @ingroup PJNATH_STUN_BASE + * @{ + */ + + +/* ************************************************************************** + * GENERAL + */ + +/** + * The log level for PJNATH error display. + * + * default 1 + */ +#ifndef PJNATH_ERROR_LEVEL +# define PJNATH_ERROR_LEVEL 1 +#endif + + +/* ************************************************************************** + * STUN CONFIGURATION + */ + +/** + * Maximum number of attributes in the STUN packet (for the new STUN + * library). + * + * Default: 16 + */ +#ifndef PJ_STUN_MAX_ATTR +# define PJ_STUN_MAX_ATTR 16 +#endif + +/** + * The default initial STUN round-trip time estimation (the RTO value + * in RFC 3489-bis), in miliseconds. + * This value is used to control the STUN request + * retransmit time. The initial value of retransmission interval + * would be set to this value, and will be doubled after each + * retransmission. + */ +#ifndef PJ_STUN_RTO_VALUE +# define PJ_STUN_RTO_VALUE 100 +#endif + + +/** + * The STUN transaction timeout value, in miliseconds. + * After the last retransmission is sent and if no response is received + * after this time, the STUN transaction will be considered to have failed. + * + * The default value is 16x RTO (as per RFC 3489-bis). + */ +#ifndef PJ_STUN_TIMEOUT_VALUE +# define PJ_STUN_TIMEOUT_VALUE (16 * PJ_STUN_RTO_VALUE) +#endif + + +/** + * Maximum number of STUN transmission count. + * + * Default: 7 (as per RFC 3489-bis) + */ +#ifndef PJ_STUN_MAX_TRANSMIT_COUNT +# define PJ_STUN_MAX_TRANSMIT_COUNT 7 +#endif + + +/** + * Duration to keep response in the cache, in msec. + * + * Default: 10000 (as per RFC 3489-bis) + */ +#ifndef PJ_STUN_RES_CACHE_DURATION +# define PJ_STUN_RES_CACHE_DURATION 10000 +#endif + + +/** + * Maximum size of STUN message. + */ +#ifndef PJ_STUN_MAX_PKT_LEN +# define PJ_STUN_MAX_PKT_LEN 800 +#endif + + +/** + * Default STUN port as defined by RFC 3489. + */ +#define PJ_STUN_PORT 3478 + + +/** + * Padding character for string attributes. + * + * Default: ASCII 0 + */ +#ifndef PJ_STUN_STRING_ATTR_PAD_CHR +# define PJ_STUN_STRING_ATTR_PAD_CHR 0 +#endif + + +/** + * Enable pre-RFC3489bis-07 style of STUN MESSAGE-INTEGRITY and FINGERPRINT + * calculation. By default this should be disabled since the calculation is + * not backward compatible with current STUN specification. + */ +#ifndef PJ_STUN_OLD_STYLE_MI_FINGERPRINT +# define PJ_STUN_OLD_STYLE_MI_FINGERPRINT 0 +#endif + + +/* ************************************************************************** + * STUN TRANSPORT CONFIGURATION + */ + +/** + * The packet buffer size for the STUN transport. + */ +#ifndef PJ_STUN_SOCK_PKT_LEN +# define PJ_STUN_SOCK_PKT_LEN 2000 +#endif + + +/** + * The duration of the STUN keep-alive period, in seconds. + */ +#ifndef PJ_STUN_KEEP_ALIVE_SEC +# define PJ_STUN_KEEP_ALIVE_SEC 15 +#endif + + +/* ************************************************************************** + * TURN CONFIGURATION + */ + +/** + * Maximum DNS SRV entries to be processed in the DNS SRV response + */ +#ifndef PJ_TURN_MAX_DNS_SRV_CNT +# define PJ_TURN_MAX_DNS_SRV_CNT 4 +#endif + + +/** + * Maximum TURN packet size to be supported. + */ +#ifndef PJ_TURN_MAX_PKT_LEN +# define PJ_TURN_MAX_PKT_LEN 3000 +#endif + + +/** + * The TURN permission lifetime setting. This value should be taken from the + * TURN protocol specification. + */ +#ifndef PJ_TURN_PERM_TIMEOUT +# define PJ_TURN_PERM_TIMEOUT 300 +#endif + + +/** + * The TURN channel binding lifetime. This value should be taken from the + * TURN protocol specification. + */ +#ifndef PJ_TURN_CHANNEL_TIMEOUT +# define PJ_TURN_CHANNEL_TIMEOUT 600 +#endif + + +/** + * Number of seconds to refresh the permission/channel binding before the + * permission/channel binding expires. This value should be greater than + * PJ_TURN_PERM_TIMEOUT setting. + */ +#ifndef PJ_TURN_REFRESH_SEC_BEFORE +# define PJ_TURN_REFRESH_SEC_BEFORE 60 +#endif + + +/** + * The TURN session timer heart beat interval. When this timer occurs, the + * TURN session will scan all the permissions/channel bindings to see which + * need to be refreshed. + */ +#ifndef PJ_TURN_KEEP_ALIVE_SEC +# define PJ_TURN_KEEP_ALIVE_SEC 15 +#endif + + +/* ************************************************************************** + * ICE CONFIGURATION + */ + +/** + * Maximum number of ICE candidates. + * + * Default: 16 + */ +#ifndef PJ_ICE_MAX_CAND +# define PJ_ICE_MAX_CAND 16 +#endif + + +/** + * Maximum number of candidates for each ICE stream transport component. + * + * Default: 8 + */ +#ifndef PJ_ICE_ST_MAX_CAND +# define PJ_ICE_ST_MAX_CAND 8 +#endif + + +/** + * The number of bits to represent component IDs. This will affect + * the maximum number of components (PJ_ICE_MAX_COMP) value. + */ +#ifndef PJ_ICE_COMP_BITS +# define PJ_ICE_COMP_BITS 1 +#endif + + +/** + * Maximum number of ICE components. + */ +#define PJ_ICE_MAX_COMP (2<<PJ_ICE_COMP_BITS) + +/** + * Use the priority value according to the ice-draft. + */ +#ifndef PJNATH_ICE_PRIO_STD +# define PJNATH_ICE_PRIO_STD 1 +#endif + + +/** + * The number of bits to represent candidate type preference. + */ +#ifndef PJ_ICE_CAND_TYPE_PREF_BITS +# if PJNATH_ICE_PRIO_STD +# define PJ_ICE_CAND_TYPE_PREF_BITS 8 +# else +# define PJ_ICE_CAND_TYPE_PREF_BITS 2 +# endif +#endif + + +/** + * The number of bits to represent ICE candidate's local preference. The + * local preference is used to specify preference among candidates with + * the same type, and ICE draft suggests 65535 as the default local + * preference, which means we need 16 bits to represent the value. But + * since we don't have the facility to specify local preference, we'll + * just disable this feature and let the preference sorted by the + * type only. + * + * Default: 0 + */ +#ifndef PJ_ICE_LOCAL_PREF_BITS +# define PJ_ICE_LOCAL_PREF_BITS 0 +#endif + + +/** + * Maximum number of ICE checks. + * + * Default: 32 + */ +#ifndef PJ_ICE_MAX_CHECKS +# define PJ_ICE_MAX_CHECKS 32 +#endif + + +/** + * Default timer interval (in miliseconds) for starting ICE periodic checks. + * + * Default: 20 + */ +#ifndef PJ_ICE_TA_VAL +# define PJ_ICE_TA_VAL 20 +#endif + + +/** + * According to ICE Section 8.2. Updating States, if an In-Progress pair in + * the check list is for the same component as a nominated pair, the agent + * SHOULD cease retransmissions for its check if its pair priority is lower + * than the lowest priority nominated pair for that component. + * + * If a higher priority check is In Progress, this rule would cause that + * check to be performed even when it most likely will fail. + * + * The macro here controls if ICE session should cancel all In Progress + * checks for the same component regardless of its priority. + * + * Default: 1 (yes, cancel all) + */ +#ifndef PJ_ICE_CANCEL_ALL +# define PJ_ICE_CANCEL_ALL 1 +#endif + + +/** + * For a controlled agent, specify how long it wants to wait (in milliseconds) + * for the controlling agent to complete sending connectivity check with + * nominated flag set to true for all components after the controlled agent + * has found that all connectivity checks in its checklist have been completed + * and there is at least one successful (but not nominated) check for every + * component. + * + * When selecting the value, bear in mind that the connectivity check from + * controlling agent may be delayed because of delay in receiving SDP answer + * from the controlled agent. + * + * Application may set this value to -1 to disable this timer. + * + * Default: 10000 (milliseconds) + */ +#ifndef ICE_CONTROLLED_AGENT_WAIT_NOMINATION_TIMEOUT +# define ICE_CONTROLLED_AGENT_WAIT_NOMINATION_TIMEOUT 10000 +#endif + + +/** + * For controlling agent if it uses regular nomination, specify the delay to + * perform nominated check (connectivity check with USE-CANDIDATE attribute) + * after all components have a valid pair. + * + * Default: 4*PJ_STUN_RTO_VALUE (milliseconds) + */ +#ifndef PJ_ICE_NOMINATED_CHECK_DELAY +# define PJ_ICE_NOMINATED_CHECK_DELAY (4*PJ_STUN_RTO_VALUE) +#endif + + +/** + * Minimum interval value to be used for sending STUN keep-alive on the ICE + * session, in seconds. This minimum interval, plus a random value + * which maximum is PJ_ICE_SESS_KEEP_ALIVE_MAX_RAND, specify the actual interval + * of the STUN keep-alive. + * + * Default: 15 seconds + * + * @see PJ_ICE_SESS_KEEP_ALIVE_MAX_RAND + */ +#ifndef PJ_ICE_SESS_KEEP_ALIVE_MIN +# define PJ_ICE_SESS_KEEP_ALIVE_MIN 20 +#endif + +/* Warn about deprecated macro */ +#ifdef PJ_ICE_ST_KEEP_ALIVE_MIN +# error PJ_ICE_ST_KEEP_ALIVE_MIN is deprecated +#endif + +/** + * To prevent STUN keep-alives to be sent simultaneously, application should + * add random interval to minimum interval (PJ_ICE_SESS_KEEP_ALIVE_MIN). This + * setting specifies the maximum random value to be added to the minimum + * interval, in seconds. + * + * Default: 5 seconds + * + * @see PJ_ICE_SESS_KEEP_ALIVE_MIN + */ +#ifndef PJ_ICE_SESS_KEEP_ALIVE_MAX_RAND +# define PJ_ICE_SESS_KEEP_ALIVE_MAX_RAND 5 +#endif + +/* Warn about deprecated macro */ +#ifdef PJ_ICE_ST_KEEP_ALIVE_MAX_RAND +# error PJ_ICE_ST_KEEP_ALIVE_MAX_RAND is deprecated +#endif + + +/** + * This constant specifies the length of random string generated for ICE + * ufrag and password. + * + * Default: 8 (characters) + */ +#ifndef PJ_ICE_UFRAG_LEN +# define PJ_ICE_UFRAG_LEN 8 +#endif + + +/** ICE session pool initial size. */ +#ifndef PJNATH_POOL_LEN_ICE_SESS +# define PJNATH_POOL_LEN_ICE_SESS 512 +#endif + +/** ICE session pool increment size */ +#ifndef PJNATH_POOL_INC_ICE_SESS +# define PJNATH_POOL_INC_ICE_SESS 512 +#endif + +/** ICE stream transport pool initial size. */ +#ifndef PJNATH_POOL_LEN_ICE_STRANS +# define PJNATH_POOL_LEN_ICE_STRANS 1000 +#endif + +/** ICE stream transport pool increment size */ +#ifndef PJNATH_POOL_INC_ICE_STRANS +# define PJNATH_POOL_INC_ICE_STRANS 512 +#endif + +/** NAT detect pool initial size */ +#ifndef PJNATH_POOL_LEN_NATCK +# define PJNATH_POOL_LEN_NATCK 512 +#endif + +/** NAT detect pool increment size */ +#ifndef PJNATH_POOL_INC_NATCK +# define PJNATH_POOL_INC_NATCK 512 +#endif + +/** STUN session pool initial size */ +#ifndef PJNATH_POOL_LEN_STUN_SESS +# define PJNATH_POOL_LEN_STUN_SESS 1000 +#endif + +/** STUN session pool increment size */ +#ifndef PJNATH_POOL_INC_STUN_SESS +# define PJNATH_POOL_INC_STUN_SESS 1000 +#endif + +/** STUN session transmit data pool initial size */ +#ifndef PJNATH_POOL_LEN_STUN_TDATA +# define PJNATH_POOL_LEN_STUN_TDATA 1000 +#endif + +/** STUN session transmit data pool increment size */ +#ifndef PJNATH_POOL_INC_STUN_TDATA +# define PJNATH_POOL_INC_STUN_TDATA 1000 +#endif + +/** TURN session initial pool size */ +#ifndef PJNATH_POOL_LEN_TURN_SESS +# define PJNATH_POOL_LEN_TURN_SESS 1000 +#endif + +/** TURN session pool increment size */ +#ifndef PJNATH_POOL_INC_TURN_SESS +# define PJNATH_POOL_INC_TURN_SESS 1000 +#endif + +/** TURN socket initial pool size */ +#ifndef PJNATH_POOL_LEN_TURN_SOCK +# define PJNATH_POOL_LEN_TURN_SOCK 1000 +#endif + +/** TURN socket pool increment size */ +#ifndef PJNATH_POOL_INC_TURN_SOCK +# define PJNATH_POOL_INC_TURN_SOCK 1000 +#endif + +/** + * @} + */ + +#endif /* __PJNATH_CONFIG_H__ */ + diff --git a/pjnath/include/pjnath/errno.h b/pjnath/include/pjnath/errno.h new file mode 100644 index 0000000..054fd1e --- /dev/null +++ b/pjnath/include/pjnath/errno.h @@ -0,0 +1,226 @@ +/* $Id: errno.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_ERRNO_H__ +#define __PJNATH_ERRNO_H__ + +/** + * @file errno.h + * @brief PJNATH specific error codes + */ + +#include <pj/errno.h> + +/** + * @defgroup PJNATH_ERROR NAT Helper Library Error Codes + * @brief PJNATH specific error code constants + * @ingroup PJNATH_STUN_BASE + * @{ + */ + +/** + * Start of error code relative to PJ_ERRNO_START_USER. + * This value is 370000. + */ +#define PJNATH_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*4) + + +/************************************************************ + * STUN MESSAGING ERRORS + ***********************************************************/ + +/** + * Map STUN error code (300-699) into pj_status_t error space. + */ +#define PJ_STATUS_FROM_STUN_CODE(code) (PJNATH_ERRNO_START+code) + +/** + * @hideinitializer + * Invalid STUN message + */ +#define PJNATH_EINSTUNMSG (PJNATH_ERRNO_START+1) /* 370001 */ +/** + * @hideinitializer + * Invalid STUN message length. + */ +#define PJNATH_EINSTUNMSGLEN (PJNATH_ERRNO_START+2) /* 370002 */ +/** + * @hideinitializer + * Invalid or unexpected STUN message type + */ +#define PJNATH_EINSTUNMSGTYPE (PJNATH_ERRNO_START+3) /* 370003 */ +/** + * @hideinitializer + * STUN transaction has timed out + */ +#define PJNATH_ESTUNTIMEDOUT (PJNATH_ERRNO_START+4) /* 370004 */ + + +/** + * @hideinitializer + * Too many STUN attributes. + */ +#define PJNATH_ESTUNTOOMANYATTR (PJNATH_ERRNO_START+21) /* 370021 */ +/** + * @hideinitializer + * Invalid STUN attribute length. + */ +#define PJNATH_ESTUNINATTRLEN (PJNATH_ERRNO_START+22) /* 370022 */ +/** + * @hideinitializer + * Found duplicate STUN attribute. + */ +#define PJNATH_ESTUNDUPATTR (PJNATH_ERRNO_START+23) /* 370023 */ + +/** + * @hideinitializer + * STUN FINGERPRINT verification failed + */ +#define PJNATH_ESTUNFINGERPRINT (PJNATH_ERRNO_START+30) /* 370030 */ +/** + * @hideinitializer + * Invalid STUN attribute after MESSAGE-INTEGRITY. + */ +#define PJNATH_ESTUNMSGINTPOS (PJNATH_ERRNO_START+31) /* 370031 */ +/** + * @hideinitializer + * Invalid STUN attribute after FINGERPRINT. + */ +#define PJNATH_ESTUNFINGERPOS (PJNATH_ERRNO_START+33) /* 370033 */ + + +/** + * @hideinitializer + * STUN (XOR-)MAPPED-ADDRESS attribute not found + */ +#define PJNATH_ESTUNNOMAPPEDADDR (PJNATH_ERRNO_START+40) /* 370040 */ +/** + * @hideinitializer + * STUN IPv6 attribute not supported + */ +#define PJNATH_ESTUNIPV6NOTSUPP (PJNATH_ERRNO_START+41) /* 370041 */ +/** + * @hideinitializer + * Invalid address family value in STUN message. + */ +#define PJNATH_EINVAF (PJNATH_ERRNO_START+42) /* 370042 */ + +/** + * @hideinitializer + * Invalid STUN server or server not configured. + */ +#define PJNATH_ESTUNINSERVER (PJNATH_ERRNO_START+50) /* 370050 */ + + +/************************************************************ + * STUN SESSION/TRANSPORT ERROR CODES + ***********************************************************/ +/** + * @hideinitializer + * STUN object has been destoyed. + */ +#define PJNATH_ESTUNDESTROYED (PJNATH_ERRNO_START+60) /* 370060 */ + + +/************************************************************ + * ICE ERROR CODES + ***********************************************************/ + +/** + * @hideinitializer + * ICE session not available + */ +#define PJNATH_ENOICE (PJNATH_ERRNO_START+80) /* 370080 */ +/** + * @hideinitializer + * ICE check is in progress + */ +#define PJNATH_EICEINPROGRESS (PJNATH_ERRNO_START+81) /* 370081 */ +/** + * @hideinitializer + * This error indicates that ICE connectivity check has failed, because + * there is at least one ICE component that does not have a valid check. + * Normally this happens because the network topology had caused the + * connectivity check to fail (e.g. no route between the two agents), + * however other reasons may include software incompatibility between + * the two agents, or incomplete candidates gathered by the agent(s). + */ +#define PJNATH_EICEFAILED (PJNATH_ERRNO_START+82) /* 370082 */ +/** + * @hideinitializer + * Default destination does not match any ICE candidates + */ +#define PJNATH_EICEMISMATCH (PJNATH_ERRNO_START+83) /* 370083 */ +/** + * @hideinitializer + * Invalid ICE component ID + */ +#define PJNATH_EICEINCOMPID (PJNATH_ERRNO_START+86) /* 370086 */ +/** + * @hideinitializer + * Invalid ICE candidate ID + */ +#define PJNATH_EICEINCANDID (PJNATH_ERRNO_START+87) /* 370087 */ +/** + * @hideinitializer + * Source address mismatch. This error occurs if the source address + * of the response for ICE connectivity check is different than + * the destination address of the request. + */ +#define PJNATH_EICEINSRCADDR (PJNATH_ERRNO_START+88) /* 370088 */ +/** + * @hideinitializer + * Missing ICE SDP attribute + */ +#define PJNATH_EICEMISSINGSDP (PJNATH_ERRNO_START+90) /* 370090 */ +/** + * @hideinitializer + * Invalid SDP "candidate" attribute + */ +#define PJNATH_EICEINCANDSDP (PJNATH_ERRNO_START+91) /* 370091 */ +/** + * @hideinitializer + * No host candidate associated with srflx. This error occurs when + * a server reflexive candidate is added without the matching + * host candidate. + */ +#define PJNATH_EICENOHOSTCAND (PJNATH_ERRNO_START+92) /* 370092 */ +/** + * @hideinitializer + * Controlled agent timed-out in waiting for the controlling agent to + * send nominated check after all connectivity checks have completed. + */ +#define PJNATH_EICENOMTIMEOUT (PJNATH_ERRNO_START+93) /* 370093 */ + +/************************************************************ + * TURN ERROR CODES + ***********************************************************/ +/** + * @hideinitializer + * Invalid or unsupported TURN transport. + */ +#define PJNATH_ETURNINTP (PJNATH_ERRNO_START+120) /* 370120 */ + + + +/** + * @} + */ + +#endif /* __PJNATH_ERRNO_H__ */ diff --git a/pjnath/include/pjnath/ice_session.h b/pjnath/include/pjnath/ice_session.h new file mode 100644 index 0000000..1e65943 --- /dev/null +++ b/pjnath/include/pjnath/ice_session.h @@ -0,0 +1,973 @@ +/* $Id: ice_session.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_ICE_SESSION_H__ +#define __PJNATH_ICE_SESSION_H__ + +/** + * @file ice_session.h + * @brief ICE session management + */ +#include <pjnath/types.h> +#include <pjnath/stun_session.h> +#include <pjnath/errno.h> +#include <pj/sock.h> +#include <pj/timer.h> + +PJ_BEGIN_DECL + + +/** + * @addtogroup PJNATH_ICE_SESSION + * @{ + * + * This module describes #pj_ice_sess, a transport independent ICE session, + * part of PJNATH - the Open Source NAT helper library. + * + * \section pj_ice_sess_sec ICE Session + * + * An ICE session, represented by #pj_ice_sess structure, is the lowest + * abstraction of ICE in PJNATH, and it is used to perform and manage + * connectivity checks of transport address candidates <b>within a + * single media stream</b> (note: this differs from what is described + * in ICE draft, where an ICE session manages the whole media sessions + * rather than just a single stream). + * + * The ICE session described here is independent from any transports, + * meaning that the actual network I/O for this session would have to + * be performed by the application, or higher layer abstraction. + * Using this framework, application would give any incoming packets to + * the ICE session, and it would provide the ICE session with a callback + * to send outgoing message. + * + * For higher abstraction of ICE where transport is included, please + * see \ref PJNATH_ICE_STREAM_TRANSPORT. + * + * \subsection pj_ice_sess_using_sec Using The ICE Session + * + * The steps below describe how to use ICE session. Alternatively application + * can use the higher level ICE API, \ref PJNATH_ICE_STREAM_TRANSPORT, + * which has provided the integration of ICE with socket transport. + * + * The steps to use ICE session is similar for both offerer and + * answerer: + * - create ICE session with #pj_ice_sess_create(). Among other things, + * application needs to specify: + * - STUN configuration (pj_stun_config), containing STUN settings + * such as timeout values and the instances of timer heap and + * ioqueue. + * - Session name, useful for identifying this session in the log. + * - Initial ICE role (#pj_ice_sess_role). The role can be changed + * at later time with #pj_ice_sess_change_role(), and ICE session + * can also change its role automatically when it detects role + * conflict. + * - Number of components in the media session. + * - Callback to receive ICE events (#pj_ice_sess_cb) + * - Optional local ICE username and password. If these arguments + * are NULL, they will be generated randomly. + * - Add local candidates for each component, with #pj_ice_sess_add_cand(). + * A candidate is represented with #pj_ice_sess_cand structure. + * Each component must be provided with at least one candidate, and + * all components must have the same number of candidates. Failing + * to comply with this will cause failure during pairing process. + * - Create offer to describe local ICE candidates. ICE session does not + * provide a function to create such offer, but application should be + * able to create one since it knows about all components and candidates. + * If application uses \ref PJNATH_ICE_STREAM_TRANSPORT, it can + * enumerate local candidates by calling #pj_ice_strans_enum_cands(). + * Application may use #pj_ice_sess_find_default_cand() to let ICE + * session chooses the default transport address to be used in SDP + * c= and m= lines. + * - Send the offer to remote endpoint using signaling such as SIP. + * - Once application has received the answer, it should parse this + * answer, build array of remote candidates, and create check lists by + * calling #pj_ice_sess_create_check_list(). This process is known as + * pairing the candidates, and will result in the creation of check lists. + * - Once checklist has been created, application then can call + * #pj_ice_sess_start_check() to instruct ICE session to start + * performing connectivity checks. The ICE session performs the + * connectivity checks by processing each check in the checklists. + * - Application will be notified about the result of ICE connectivity + * checks via the callback that was given in #pj_ice_sess_create() + * above. + * + * To send data, application calls #pj_ice_sess_send_data(). If ICE + * negotiation has not completed, ICE session would simply drop the data, + * and return error to caller. If ICE negotiation has completed + * successfully, ICE session will in turn call the \a on_tx_pkt + * callback of #pj_ice_sess_cb instance that was previously registered + * in #pj_ice_sess_create() above. + * + * When application receives any packets on the underlying sockets, it + * must call #pj_ice_sess_on_rx_pkt(). The ICE session will inspect the + * packet to decide whether to process it locally (if the packet is a + * STUN message and is part of ICE session) or otherwise pass it back to + * application via \a on_rx_data callback. + */ + +/** + * Forward declaration for checklist. + */ +typedef struct pj_ice_sess_checklist pj_ice_sess_checklist; + +/** + * This enumeration describes the type of an ICE candidate. + */ +typedef enum pj_ice_cand_type +{ + /** + * ICE host candidate. A host candidate represents the actual local + * transport address in the host. + */ + PJ_ICE_CAND_TYPE_HOST, + + /** + * ICE server reflexive candidate, which represents the public mapped + * address of the local address, and is obtained by sending STUN + * Binding request from the host candidate to a STUN server. + */ + PJ_ICE_CAND_TYPE_SRFLX, + + /** + * ICE peer reflexive candidate, which is the address as seen by peer + * agent during connectivity check. + */ + PJ_ICE_CAND_TYPE_PRFLX, + + /** + * ICE relayed candidate, which represents the address allocated in + * TURN server. + */ + PJ_ICE_CAND_TYPE_RELAYED + +} pj_ice_cand_type; + + +/** Forward declaration for pj_ice_sess */ +typedef struct pj_ice_sess pj_ice_sess; + +/** Forward declaration for pj_ice_sess_check */ +typedef struct pj_ice_sess_check pj_ice_sess_check; + + +/** + * This structure describes ICE component. + * A media stream may require multiple components, each of which has + * to work for the media stream as a whole to work. For media streams + * based on RTP, there are two components per media stream - one for RTP, + * and one for RTCP. + */ +typedef struct pj_ice_sess_comp +{ + /** + * Pointer to ICE check with highest priority which connectivity check + * has been successful. The value will be NULL if a no successful check + * has not been found for this component. + */ + pj_ice_sess_check *valid_check; + + /** + * Pointer to ICE check with highest priority which connectivity check + * has been successful and it has been nominated. The value may be NULL + * if there is no such check yet. + */ + pj_ice_sess_check *nominated_check; + + /** + * The STUN session to be used to send and receive STUN messages for this + * component. + */ + pj_stun_session *stun_sess; + +} pj_ice_sess_comp; + + +/** + * Data structure to be attached to internal message processing. + */ +typedef struct pj_ice_msg_data +{ + /** Transport ID for this message */ + unsigned transport_id; + + /** Flag to indicate whether data.req contains data */ + pj_bool_t has_req_data; + + /** The data */ + union data { + /** Request data */ + struct request_data { + pj_ice_sess *ice; /**< ICE session */ + pj_ice_sess_checklist *clist; /**< Checklist */ + unsigned ckid; /**< Check ID */ + } req; + } data; + +} pj_ice_msg_data; + + +/** + * This structure describes an ICE candidate. + * ICE candidate is a transport address that is to be tested by ICE + * procedures in order to determine its suitability for usage for + * receipt of media. Candidates also have properties - their type + * (server reflexive, relayed or host), priority, foundation, and + * base. + */ +typedef struct pj_ice_sess_cand +{ + /** + * The candidate type, as described in #pj_ice_cand_type enumeration. + */ + pj_ice_cand_type type; + + /** + * Status of this candidate. The value will be PJ_SUCCESS if candidate + * address has been resolved successfully, PJ_EPENDING when the address + * resolution process is in progress, or other value when the address + * resolution has completed with failure. + */ + pj_status_t status; + + /** + * The component ID of this candidate. Note that component IDs starts + * with one for RTP and two for RTCP. In other words, it's not zero + * based. + */ + pj_uint8_t comp_id; + + /** + * Transport ID to be used to send packets for this candidate. + */ + pj_uint8_t transport_id; + + /** + * Local preference value, which typically is 65535. + */ + pj_uint16_t local_pref; + + /** + * The foundation string, which is an identifier which value will be + * equivalent for two candidates that are of the same type, share the + * same base, and come from the same STUN server. The foundation is + * used to optimize ICE performance in the Frozen algorithm. + */ + pj_str_t foundation; + + /** + * The candidate's priority, a 32-bit unsigned value which value will be + * calculated by the ICE session when a candidate is registered to the + * ICE session. + */ + pj_uint32_t prio; + + /** + * IP address of this candidate. For host candidates, this represents + * the local address of the socket. For reflexive candidates, the value + * will be the public address allocated in NAT router for the host + * candidate and as reported in MAPPED-ADDRESS or XOR-MAPPED-ADDRESS + * attribute of STUN Binding request. For relayed candidate, the value + * will be the address allocated in the TURN server by STUN Allocate + * request. + */ + pj_sockaddr addr; + + /** + * Base address of this candidate. "Base" refers to the address an agent + * sends from for a particular candidate. For host candidates, the base + * is the same as the host candidate itself. For reflexive candidates, + * the base is the local IP address of the socket. For relayed candidates, + * the base address is the transport address allocated in the TURN server + * for this candidate. + */ + pj_sockaddr base_addr; + + /** + * Related address, which is used for informational only and is not used + * in any way by the ICE session. + */ + pj_sockaddr rel_addr; + +} pj_ice_sess_cand; + + +/** + * This enumeration describes the state of ICE check. + */ +typedef enum pj_ice_sess_check_state +{ + /** + * A check for this pair hasn't been performed, and it can't + * yet be performed until some other check succeeds, allowing this + * pair to unfreeze and move into the Waiting state. + */ + PJ_ICE_SESS_CHECK_STATE_FROZEN, + + /** + * A check has not been performed for this pair, and can be + * performed as soon as it is the highest priority Waiting pair on + * the check list. + */ + PJ_ICE_SESS_CHECK_STATE_WAITING, + + /** + * A check has not been performed for this pair, and can be + * performed as soon as it is the highest priority Waiting pair on + * the check list. + */ + PJ_ICE_SESS_CHECK_STATE_IN_PROGRESS, + + /** + * A check has not been performed for this pair, and can be + * performed as soon as it is the highest priority Waiting pair on + * the check list. + */ + PJ_ICE_SESS_CHECK_STATE_SUCCEEDED, + + /** + * A check for this pair was already done and failed, either + * never producing any response or producing an unrecoverable failure + * response. + */ + PJ_ICE_SESS_CHECK_STATE_FAILED + +} pj_ice_sess_check_state; + + +/** + * This structure describes an ICE connectivity check. An ICE check + * contains a candidate pair, and will involve sending STUN Binding + * Request transaction for the purposes of verifying connectivity. + * A check is sent from the local candidate to the remote candidate + * of a candidate pair. + */ +struct pj_ice_sess_check +{ + /** + * Pointer to local candidate entry of this check. + */ + pj_ice_sess_cand *lcand; + + /** + * Pointer to remote candidate entry of this check. + */ + pj_ice_sess_cand *rcand; + + /** + * Check priority. + */ + pj_timestamp prio; + + /** + * Connectivity check state. + */ + pj_ice_sess_check_state state; + + /** + * STUN transmit data containing STUN Binding request that was sent + * as part of this check. The value will only be set when this check + * has a pending transaction, and is used to cancel the transaction + * when other check has succeeded. + */ + pj_stun_tx_data *tdata; + + /** + * Flag to indicate whether this check is nominated. A nominated check + * contains USE-CANDIDATE attribute in its STUN Binding request. + */ + pj_bool_t nominated; + + /** + * When the check failed, this will contain the failure status of the + * STUN transaction. + */ + pj_status_t err_code; +}; + + +/** + * This enumeration describes ICE checklist state. + */ +typedef enum pj_ice_sess_checklist_state +{ + /** + * The checklist is not yet running. + */ + PJ_ICE_SESS_CHECKLIST_ST_IDLE, + + /** + * In this state, ICE checks are still in progress for this + * media stream. + */ + PJ_ICE_SESS_CHECKLIST_ST_RUNNING, + + /** + * In this state, ICE checks have completed for this media stream, + * either successfully or with failure. + */ + PJ_ICE_SESS_CHECKLIST_ST_COMPLETED + +} pj_ice_sess_checklist_state; + + +/** + * This structure represents ICE check list, that is an ordered set of + * candidate pairs that an agent will use to generate checks. + */ +struct pj_ice_sess_checklist +{ + /** + * The checklist state. + */ + pj_ice_sess_checklist_state state; + + /** + * Number of candidate pairs (checks). + */ + unsigned count; + + /** + * Array of candidate pairs (checks). + */ + pj_ice_sess_check checks[PJ_ICE_MAX_CHECKS]; + + /** + * A timer used to perform periodic check for this checklist. + */ + pj_timer_entry timer; + +}; + + +/** + * This structure contains callbacks that will be called by the ICE + * session. + */ +typedef struct pj_ice_sess_cb +{ + /** + * An optional callback that will be called by the ICE session when + * ICE negotiation has completed, successfully or with failure. + * + * @param ice The ICE session. + * @param status Will contain PJ_SUCCESS if ICE negotiation is + * successful, or some error code. + */ + void (*on_ice_complete)(pj_ice_sess *ice, pj_status_t status); + + /** + * A mandatory callback which will be called by the ICE session when + * it needs to send outgoing STUN packet. + * + * @param ice The ICE session. + * @param comp_id ICE component ID. + * @param transport_id Transport ID. + * @param pkt The STUN packet. + * @param size The size of the packet. + * @param dst_addr Packet destination address. + * @param dst_addr_len Length of destination address. + */ + pj_status_t (*on_tx_pkt)(pj_ice_sess *ice, unsigned comp_id, + unsigned transport_id, + const void *pkt, pj_size_t size, + const pj_sockaddr_t *dst_addr, + unsigned dst_addr_len); + + /** + * A mandatory callback which will be called by the ICE session when + * it receives packet which is not part of ICE negotiation. + * + * @param ice The ICE session. + * @param comp_id ICE component ID. + * @param transport_id Transport ID. + * @param pkt The whole packet. + * @param size Size of the packet. + * @param src_addr Source address where this packet was received + * from. + * @param src_addr_len The length of source address. + */ + void (*on_rx_data)(pj_ice_sess *ice, unsigned comp_id, + unsigned transport_id, + void *pkt, pj_size_t size, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); +} pj_ice_sess_cb; + + +/** + * This enumeration describes the role of the ICE agent. + */ +typedef enum pj_ice_sess_role +{ + /** + * The role is unknown. + */ + PJ_ICE_SESS_ROLE_UNKNOWN, + + /** + * The ICE agent is in controlled role. + */ + PJ_ICE_SESS_ROLE_CONTROLLED, + + /** + * The ICE agent is in controlling role. + */ + PJ_ICE_SESS_ROLE_CONTROLLING + +} pj_ice_sess_role; + + +/** + * This structure represents an incoming check (an incoming Binding + * request message), and is mainly used to keep early checks in the + * list in the ICE session. An early check is a request received + * from remote when we haven't received SDP answer yet, therefore we + * can't perform triggered check. For such cases, keep the incoming + * request in a list, and we'll do triggered checks (simultaneously) + * as soon as we receive answer. + */ +typedef struct pj_ice_rx_check +{ + PJ_DECL_LIST_MEMBER(struct pj_ice_rx_check); /**< Standard list */ + + unsigned comp_id; /**< Component ID. */ + unsigned transport_id; /**< Transport ID. */ + + pj_sockaddr src_addr; /**< Source address of request */ + unsigned src_addr_len; /**< Length of src address. */ + + pj_bool_t use_candidate; /**< USE-CANDIDATE is present? */ + pj_uint32_t priority; /**< PRIORITY value in the req. */ + pj_stun_uint64_attr *role_attr; /**< ICE-CONTROLLING/CONTROLLED */ + +} pj_ice_rx_check; + + +/** + * This structure describes various ICE session options. Application + * configure the ICE session with these options by calling + * #pj_ice_sess_set_options(). + */ +typedef struct pj_ice_sess_options +{ + /** + * Specify whether to use aggressive nomination. + */ + pj_bool_t aggressive; + + /** + * For controlling agent if it uses regular nomination, specify the delay + * to perform nominated check (connectivity check with USE-CANDIDATE + * attribute) after all components have a valid pair. + * + * Default value is PJ_ICE_NOMINATED_CHECK_DELAY. + */ + unsigned nominated_check_delay; + + /** + * For a controlled agent, specify how long it wants to wait (in + * milliseconds) for the controlling agent to complete sending + * connectivity check with nominated flag set to true for all components + * after the controlled agent has found that all connectivity checks in + * its checklist have been completed and there is at least one successful + * (but not nominated) check for every component. + * + * Default value for this option is + * ICE_CONTROLLED_AGENT_WAIT_NOMINATION_TIMEOUT. Specify -1 to disable + * this timer. + */ + int controlled_agent_want_nom_timeout; + +} pj_ice_sess_options; + + +/** + * This structure describes the ICE session. For this version of PJNATH, + * an ICE session corresponds to a single media stream (unlike the ICE + * session described in the ICE standard where an ICE session covers the + * whole media and may consist of multiple media streams). The decision + * to support only a single media session was chosen for simplicity, + * while still allowing application to utilize multiple media streams by + * creating multiple ICE sessions, one for each media stream. + */ +struct pj_ice_sess +{ + char obj_name[PJ_MAX_OBJ_NAME]; /**< Object name. */ + + pj_pool_t *pool; /**< Pool instance. */ + void *user_data; /**< App. data. */ + pj_mutex_t *mutex; /**< Mutex. */ + pj_ice_sess_role role; /**< ICE role. */ + pj_ice_sess_options opt; /**< Options */ + pj_timestamp tie_breaker; /**< Tie breaker value */ + pj_uint8_t *prefs; /**< Type preference. */ + pj_bool_t is_nominating; /**< Nominating stage */ + pj_bool_t is_complete; /**< Complete? */ + pj_status_t ice_status; /**< Error status. */ + pj_timer_entry timer; /**< ICE timer. */ + pj_ice_sess_cb cb; /**< Callback. */ + + pj_stun_config stun_cfg; /**< STUN settings. */ + + /* STUN credentials */ + pj_str_t tx_ufrag; /**< Remote ufrag. */ + pj_str_t tx_uname; /**< Uname for TX. */ + pj_str_t tx_pass; /**< Remote password. */ + pj_str_t rx_ufrag; /**< Local ufrag. */ + pj_str_t rx_uname; /**< Uname for RX */ + pj_str_t rx_pass; /**< Local password. */ + + /* Components */ + unsigned comp_cnt; /**< # of components. */ + pj_ice_sess_comp comp[PJ_ICE_MAX_COMP]; /**< Component array */ + unsigned comp_ka; /**< Next comp for KA */ + + /* Local candidates */ + unsigned lcand_cnt; /**< # of local cand. */ + pj_ice_sess_cand lcand[PJ_ICE_MAX_CAND]; /**< Array of cand. */ + + /* Remote candidates */ + unsigned rcand_cnt; /**< # of remote cand. */ + pj_ice_sess_cand rcand[PJ_ICE_MAX_CAND]; /**< Array of cand. */ + + /** Array of transport datas */ + pj_ice_msg_data tp_data[4]; + + /* List of eearly checks */ + pj_ice_rx_check early_check; /**< Early checks. */ + + /* Checklist */ + pj_ice_sess_checklist clist; /**< Active checklist */ + + /* Valid list */ + pj_ice_sess_checklist valid_list; /**< Valid list. */ + + /** Temporary buffer for misc stuffs to avoid using stack too much */ + union { + char txt[128]; + char errmsg[PJ_ERR_MSG_SIZE]; + } tmp; +}; + + +/** + * This is a utility function to retrieve the string name for the + * particular candidate type. + * + * @param type Candidate type. + * + * @return The string representation of the candidate type. + */ +PJ_DECL(const char*) pj_ice_get_cand_type_name(pj_ice_cand_type type); + + +/** + * This is a utility function to retrieve the string name for the + * particular role type. + * + * @param role Role type. + * + * @return The string representation of the role. + */ +PJ_DECL(const char*) pj_ice_sess_role_name(pj_ice_sess_role role); + + +/** + * This is a utility function to calculate the foundation identification + * for a candidate. + * + * @param pool Pool to allocate the foundation string. + * @param foundation Pointer to receive the foundation string. + * @param type Candidate type. + * @param base_addr Base address of the candidate. + */ +PJ_DECL(void) pj_ice_calc_foundation(pj_pool_t *pool, + pj_str_t *foundation, + pj_ice_cand_type type, + const pj_sockaddr *base_addr); + +/** + * Initialize ICE session options with library default values. + * + * @param opt ICE session options. + */ +PJ_DECL(void) pj_ice_sess_options_default(pj_ice_sess_options *opt); + +/** + * Create ICE session with the specified role and number of components. + * Application would typically need to create an ICE session before + * sending an offer or upon receiving one. After the session is created, + * application can register candidates to the ICE session by calling + * #pj_ice_sess_add_cand() function. + * + * @param stun_cfg The STUN configuration settings, containing among + * other things the timer heap instance to be used + * by the ICE session. + * @param name Optional name to identify this ICE instance in + * the log file. + * @param role ICE role. + * @param comp_cnt Number of components. + * @param cb ICE callback. + * @param local_ufrag Optional string to be used as local username to + * authenticate incoming STUN binding request. If + * the value is NULL, a random string will be + * generated. + * @param local_passwd Optional string to be used as local password. + * @param p_ice Pointer to receive the ICE session instance. + * + * @return PJ_SUCCESS if ICE session is created successfully. + */ +PJ_DECL(pj_status_t) pj_ice_sess_create(pj_stun_config *stun_cfg, + const char *name, + pj_ice_sess_role role, + unsigned comp_cnt, + const pj_ice_sess_cb *cb, + const pj_str_t *local_ufrag, + const pj_str_t *local_passwd, + pj_ice_sess **p_ice); + +/** + * Get the value of various options of the ICE session. + * + * @param ice The ICE session. + * @param opt The options to be initialized with the values + * from the ICE session. + * + * @return PJ_SUCCESS on success, or the appropriate error. + */ +PJ_DECL(pj_status_t) pj_ice_sess_get_options(pj_ice_sess *ice, + pj_ice_sess_options *opt); + +/** + * Specify various options for this ICE session. Application MUST only + * call this function after the ICE session has been created but before + * any connectivity check is started. + * + * Application should call #pj_ice_sess_get_options() to initialize the + * options with their default values. + * + * @param ice The ICE session. + * @param opt Options to be applied to the ICE session. + * + * @return PJ_SUCCESS on success, or the appropriate error. + */ +PJ_DECL(pj_status_t) pj_ice_sess_set_options(pj_ice_sess *ice, + const pj_ice_sess_options *opt); + +/** + * Destroy ICE session. This will cancel any connectivity checks currently + * running, if any, and any other events scheduled by this session, as well + * as all memory resources. + * + * @param ice ICE session instance. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pj_ice_sess_destroy(pj_ice_sess *ice); + + +/** + * Change session role. This happens for example when ICE session was + * created with controlled role when receiving an offer, but it turns out + * that the offer contains "a=ice-lite" attribute when the SDP gets + * inspected. + * + * @param ice The ICE session. + * @param new_role The new role to be set. + * + * @return PJ_SUCCESS on success, or the appropriate error. + */ +PJ_DECL(pj_status_t) pj_ice_sess_change_role(pj_ice_sess *ice, + pj_ice_sess_role new_role); + + +/** + * Assign a custom preference values for ICE candidate types. By assigning + * custom preference value, application can control the order of candidates + * to be checked first. The default preference settings is to use 126 for + * host candidates, 100 for server reflexive candidates, 110 for peer + * reflexive candidates, an 0 for relayed candidates. + * + * Note that this function must be called before any candidates are added + * to the ICE session. + * + * @param ice The ICE session. + * @param prefs Array of candidate preference value. The values are + * put in the array indexed by the candidate type as + * specified in pj_ice_cand_type. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_ice_sess_set_prefs(pj_ice_sess *ice, + const pj_uint8_t prefs[4]); + + + +/** + * Add a candidate to this ICE session. Application must add candidates for + * each components ID before it can start pairing the candidates and + * performing connectivity checks. + * + * @param ice ICE session instance. + * @param comp_id Component ID of this candidate. + * @param transport_id Transport ID to be used to send packets for this + * candidate. + * @param type Candidate type. + * @param local_pref Local preference for this candidate, which + * normally should be set to 65535. + * @param foundation Foundation identification. + * @param addr The candidate address. + * @param base_addr The candidate's base address. + * @param rel_addr Optional related address. + * @param addr_len Length of addresses. + * @param p_cand_id Optional pointer to receive the candidate ID. + * + * @return PJ_SUCCESS if candidate is successfully added. + */ +PJ_DECL(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, + unsigned comp_id, + unsigned transport_id, + pj_ice_cand_type type, + pj_uint16_t local_pref, + const pj_str_t *foundation, + const pj_sockaddr_t *addr, + const pj_sockaddr_t *base_addr, + const pj_sockaddr_t *rel_addr, + int addr_len, + unsigned *p_cand_id); + +/** + * Find default candidate for the specified component ID, using this + * rule: + * - if the component has a successful candidate pair, then the + * local candidate of this pair will be returned. + * - otherwise a relay, reflexive, or host candidate will be selected + * on that specified order. + * + * @param ice The ICE session instance. + * @param comp_id The component ID. + * @param p_cand_id Pointer to receive the candidate ID. + * + * @return PJ_SUCCESS if a candidate has been selected. + */ +PJ_DECL(pj_status_t) pj_ice_sess_find_default_cand(pj_ice_sess *ice, + unsigned comp_id, + int *p_cand_id); + +/** + * Pair the local and remote candidates to create check list. Application + * typically would call this function after receiving SDP containing ICE + * candidates from the remote host (either upon receiving the initial + * offer, for UAS, or upon receiving the answer, for UAC). + * + * Note that ICE connectivity check will not start until application calls + * #pj_ice_sess_start_check(). + * + * @param ice ICE session instance. + * @param rem_ufrag Remote ufrag, as seen in the SDP received from + * the remote agent. + * @param rem_passwd Remote password, as seen in the SDP received from + * the remote agent. + * @param rem_cand_cnt Number of remote candidates. + * @param rem_cand Remote candidate array. Remote candidates are + * gathered from the SDP received from the remote + * agent. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) +pj_ice_sess_create_check_list(pj_ice_sess *ice, + const pj_str_t *rem_ufrag, + const pj_str_t *rem_passwd, + unsigned rem_cand_cnt, + const pj_ice_sess_cand rem_cand[]); + +/** + * Start ICE periodic check. This function will return immediately, and + * application will be notified about the connectivity check status in + * #pj_ice_sess_cb callback. + * + * @param ice The ICE session instance. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_ice_sess_start_check(pj_ice_sess *ice); + + +/** + * Send data using this ICE session. If ICE checks have not produced a + * valid check for the specified component ID, this function will return + * with failure. Otherwise ICE session will send the packet to remote + * destination using the nominated local candidate for the specified + * component. + * + * This function will in turn call \a on_tx_pkt function in + * #pj_ice_sess_cb callback to actually send the packet to the wire. + * + * @param ice The ICE session. + * @param comp_id Component ID. + * @param data The data or packet to be sent. + * @param data_len Size of data or packet, in bytes. + * + * @return PJ_SUCCESS if data is sent successfully. + */ +PJ_DECL(pj_status_t) pj_ice_sess_send_data(pj_ice_sess *ice, + unsigned comp_id, + const void *data, + pj_size_t data_len); + +/** + * Report the arrival of packet to the ICE session. Since ICE session + * itself doesn't have any transports, it relies on application or + * higher layer component to give incoming packets to the ICE session. + * If the packet is not a STUN packet, this packet will be given back + * to application via \a on_rx_data() callback in #pj_ice_sess_cb. + * + * @param ice The ICE session. + * @param comp_id Component ID. + * @param transport_id Number to identify where this packet was received + * from. This parameter will be returned back to + * application in \a on_tx_pkt() callback. + * @param pkt Incoming packet. + * @param pkt_size Size of incoming packet. + * @param src_addr Source address of the packet. + * @param src_addr_len Length of the address. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_ice_sess_on_rx_pkt(pj_ice_sess *ice, + unsigned comp_id, + unsigned transport_id, + void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *src_addr, + int src_addr_len); + + + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJNATH_ICE_SESSION_H__ */ + diff --git a/pjnath/include/pjnath/ice_strans.h b/pjnath/include/pjnath/ice_strans.h new file mode 100644 index 0000000..6e973c4 --- /dev/null +++ b/pjnath/include/pjnath/ice_strans.h @@ -0,0 +1,816 @@ +/* $Id: ice_strans.h 4133 2012-05-21 14:00:17Z bennylp $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_ICE_STRANS_H__ +#define __PJNATH_ICE_STRANS_H__ + + +/** + * @file ice_strans.h + * @brief ICE Stream Transport + */ +#include <pjnath/ice_session.h> +#include <pjnath/stun_sock.h> +#include <pjnath/turn_sock.h> +#include <pjlib-util/resolver.h> +#include <pj/ioqueue.h> +#include <pj/timer.h> + + +PJ_BEGIN_DECL + + +/** + * @addtogroup PJNATH_ICE_STREAM_TRANSPORT + * @{ + * + * This module describes ICE stream transport, as represented by #pj_ice_strans + * structure, and is part of PJNATH - the Open Source NAT traversal helper + * library. + * + * ICE stream transport, as represented by #pj_ice_strans structure, is an ICE + * capable class for transporting media streams within a media session. + * It consists of one or more transport sockets (typically two for RTP + * based communication - one for RTP and one for RTCP), and an + * \ref PJNATH_ICE_SESSION for performing connectivity checks among the. + * various candidates of the transport addresses. + * + * + * \section ice_strans_using_sec Using the ICE stream transport + * + * The steps below describe how to use ICE session: + * + * - initialize a #pj_ice_strans_cfg structure. This contains various + * settings for the ICE stream transport, and among other things contains + * the STUN and TURN settings.\n\n + * - create the instance with #pj_ice_strans_create(). Among other things, + * the function needs the following arguments: + * - the #pj_ice_strans_cfg structure for the main configurations + * - number of components to be supported + * - instance of #pj_ice_strans_cb structure to report callbacks to + * application.\n\n + * - while the #pj_ice_strans_create() call completes immediately, the + * initialization will be running in the background to gather the + * candidates (for example STUN and TURN candidates, if they are enabled + * in the #pj_ice_strans_cfg setting). Application will be notified when + * the initialization completes in the \a on_ice_complete callback of + * the #pj_ice_strans_cb structure (the \a op argument of this callback + * will be PJ_ICE_STRANS_OP_INIT).\n\n + * - when media stream is to be started (for example, a call is to be + * started), create an ICE session by calling #pj_ice_strans_init_ice().\n\n + * - the application now typically will need to communicate local ICE + * information to remote host. It can achieve this by using the following + * functions to query local ICE information: + * - #pj_ice_strans_get_ufrag_pwd() + * - #pj_ice_strans_enum_cands() + * - #pj_ice_strans_get_def_cand()\n + * The application may need to encode the above information as SDP.\n\n + * - when the application receives remote ICE information (for example, from + * the SDP received from remote), it can now start ICE negotiation, by + * calling #pj_ice_strans_start_ice(). This function requires some + * information about remote ICE agent such as remote ICE username fragment + * and password as well as array of remote candidates.\n\n + * - note that the PJNATH library does not work with SDP; application would + * need to encode and parse the SDP itself.\n\n + * - once ICE negotiation has been started, application will be notified + * about the completion in the \a on_ice_complete() callback of the + * #pj_ice_strans_cb.\n\n + * - at any time, application may send or receive data. However the ICE + * stream transport may not be able to send it depending on its current + * state. Before ICE negotiation is started, the data will be sent using + * default candidate of the component. After negotiation is completed, + * data will be sent using the candidate from the successful/nominated + * pair. The ICE stream transport may not be able to send data while + * negotiation is in progress.\n\n + * - application sends data by using #pj_ice_strans_sendto(). Incoming + * data will be reported in \a on_rx_data() callback of the + * #pj_ice_strans_cb.\n\n + * - once the media session has finished (e.g. user hangs up the call), + * destroy the ICE session with #pj_ice_strans_stop_ice().\n\n + * - at this point, application may destroy the ICE stream transport itself, + * or let it run so that it can be reused to create other ICE session. + * The benefit of letting the ICE stream transport alive (without any + * session active) is to avoid delay with the initialization, howerver + * keeping the transport alive means the transport needs to keep the + * STUN binding open by using keep-alive and also TURN allocation alive, + * and this will consume power which is an important issue for mobile + * applications.\n\n + */ + +/** Forward declaration for ICE stream transport. */ +typedef struct pj_ice_strans pj_ice_strans; + +/** Transport operation types to be reported on \a on_status() callback */ +typedef enum pj_ice_strans_op +{ + /** Initialization (candidate gathering) */ + PJ_ICE_STRANS_OP_INIT, + + /** Negotiation */ + PJ_ICE_STRANS_OP_NEGOTIATION, + + /** This operatino is used to report failure in keep-alive operation. + * Currently it is only used to report TURN Refresh failure. + */ + PJ_ICE_STRANS_OP_KEEP_ALIVE + +} pj_ice_strans_op; + +/** + * This structure contains callbacks that will be called by the + * ICE stream transport. + */ +typedef struct pj_ice_strans_cb +{ + /** + * This callback will be called when the ICE transport receives + * incoming packet from the sockets which is not related to ICE + * (for example, normal RTP/RTCP packet destined for application). + * + * @param ice_st The ICE stream transport. + * @param comp_id The component ID. + * @param pkt The packet. + * @param size Size of the packet. + * @param src_addr Source address of the packet. + * @param src_addr_len Length of the source address. + */ + void (*on_rx_data)(pj_ice_strans *ice_st, + unsigned comp_id, + void *pkt, pj_size_t size, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + + /** + * Callback to report status of various ICE operations. + * + * @param ice_st The ICE stream transport. + * @param op The operation which status is being reported. + * @param status Operation status. + */ + void (*on_ice_complete)(pj_ice_strans *ice_st, + pj_ice_strans_op op, + pj_status_t status); + +} pj_ice_strans_cb; + + +/** + * This structure describes ICE stream transport configuration. Application + * should initialize the structure by calling #pj_ice_strans_cfg_default() + * before changing the settings. + */ +typedef struct pj_ice_strans_cfg +{ + /** + * Address family, IPv4 or IPv6. Currently only pj_AF_INET() (IPv4) + * is supported, and this is the default value. + */ + int af; + + /** + * STUN configuration which contains the timer heap and + * ioqueue instance to be used, and STUN retransmission + * settings. This setting is mandatory. + * + * The default value is all zero. Application must initialize + * this setting with #pj_stun_config_init(). + */ + pj_stun_config stun_cfg; + + /** + * DNS resolver to be used to resolve servers. If DNS SRV + * resolution is required, the resolver must be set. + * + * The default value is NULL. + */ + pj_dns_resolver *resolver; + + /** + * This contains various STUN session options. Once the ICE stream + * transport is created, application may also change the options + * with #pj_ice_strans_set_options(). + */ + pj_ice_sess_options opt; + + /** + * STUN and local transport settings. This specifies the + * settings for local UDP socket, which will be resolved + * to get the STUN mapped address. + */ + struct { + /** + * Optional configuration for STUN transport. The default + * value will be initialized with #pj_stun_sock_cfg_default(). + */ + pj_stun_sock_cfg cfg; + + /** + * Maximum number of host candidates to be added. If the + * value is zero, no host candidates will be added. + * + * Default: 64 + */ + unsigned max_host_cands; + + /** + * Include loopback addresses in the host candidates. + * + * Default: PJ_FALSE + */ + pj_bool_t loop_addr; + + /** + * Specify the STUN server domain or hostname or IP address. + * If DNS SRV resolution is required, application must fill + * in this setting with the domain name of the STUN server + * and set the resolver instance in the \a resolver field. + * Otherwise if the \a resolver setting is not set, this + * field will be resolved with hostname resolution and in + * this case the \a port field must be set. + * + * The \a port field should also be set even when DNS SRV + * resolution is used, in case the DNS SRV resolution fails. + * + * When this field is empty, STUN mapped address resolution + * will not be performed. In this case only ICE host candidates + * will be added to the ICE transport, unless if \a no_host_cands + * field is set. In this case, both host and srflx candidates + * are disabled. + * + * The default value is empty. + */ + pj_str_t server; + + /** + * The port number of the STUN server, when \a server + * field specifies a hostname rather than domain name. This + * field should also be set even when the \a server + * specifies a domain name, to allow DNS SRV resolution + * to fallback to DNS A/AAAA resolution when the DNS SRV + * resolution fails. + * + * The default value is PJ_STUN_PORT. + */ + pj_uint16_t port; + + /** + * Ignore STUN resolution error and proceed with just local + * addresses. + * + * The default is PJ_FALSE + */ + pj_bool_t ignore_stun_error; + + } stun; + + /** + * TURN specific settings. + */ + struct { + /** + * Optional TURN socket settings. The default values will be + * initialized by #pj_turn_sock_cfg_default(). This contains + * settings such as QoS. + */ + pj_turn_sock_cfg cfg; + + /** + * Specify the TURN server domain or hostname or IP address. + * If DNS SRV resolution is required, application must fill + * in this setting with the domain name of the TURN server + * and set the resolver instance in the \a resolver field. + * Otherwise if the \a resolver setting is not set, this + * field will be resolved with hostname resolution and in + * this case the \a port field must be set. + * + * The \a port field should also be set even when DNS SRV + * resolution is used, in case the DNS SRV resolution fails. + * + * When this field is empty, relay candidate will not be + * created. + * + * The default value is empty. + */ + pj_str_t server; + + /** + * The port number of the TURN server, when \a server + * field specifies a hostname rather than domain name. This + * field should also be set even when the \a server + * specifies a domain name, to allow DNS SRV resolution + * to fallback to DNS A/AAAA resolution when the DNS SRV + * resolution fails. + * + * Default is zero. + */ + pj_uint16_t port; + + /** + * Type of connection to the TURN server. + * + * Default is PJ_TURN_TP_UDP. + */ + pj_turn_tp_type conn_type; + + /** + * Credential to be used for the TURN session. This setting + * is mandatory. + * + * Default is to have no credential. + */ + pj_stun_auth_cred auth_cred; + + /** + * Optional TURN Allocate parameter. The default value will be + * initialized by #pj_turn_alloc_param_default(). + */ + pj_turn_alloc_param alloc_param; + + } turn; + + /** + * Component specific settings, which will override the settings in + * the STUN and TURN settings above. For example, setting the QoS + * parameters here allows the application to have different QoS + * traffic type for RTP and RTCP component. + */ + struct { + /** + * QoS traffic type to be set on this transport. When application + * wants to apply QoS tagging to the transport, it's preferable to + * set this field rather than \a qos_param fields since this is + * more portable. + * + * Default value is PJ_QOS_TYPE_BEST_EFFORT. + */ + pj_qos_type qos_type; + + /** + * Set the low level QoS parameters to the transport. This is a + * lower level operation than setting the \a qos_type field and + * may not be supported on all platforms. + * + * By default all settings in this structure are disabled. + */ + pj_qos_params qos_params; + + } comp[PJ_ICE_MAX_COMP]; + +} pj_ice_strans_cfg; + + +/** + * ICE stream transport's state. + */ +typedef enum pj_ice_strans_state +{ + /** + * ICE stream transport is not created. + */ + PJ_ICE_STRANS_STATE_NULL, + + /** + * ICE candidate gathering process is in progress. + */ + PJ_ICE_STRANS_STATE_INIT, + + /** + * ICE stream transport initialization/candidate gathering process is + * complete, ICE session may be created on this stream transport. + */ + PJ_ICE_STRANS_STATE_READY, + + /** + * New session has been created and the session is ready. + */ + PJ_ICE_STRANS_STATE_SESS_READY, + + /** + * ICE negotiation is in progress. + */ + PJ_ICE_STRANS_STATE_NEGO, + + /** + * ICE negotiation has completed successfully and media is ready + * to be used. + */ + PJ_ICE_STRANS_STATE_RUNNING, + + /** + * ICE negotiation has completed with failure. + */ + PJ_ICE_STRANS_STATE_FAILED + +} pj_ice_strans_state; + + +/** + * Initialize ICE transport configuration with default values. + * + * @param cfg The configuration to be initialized. + */ +PJ_DECL(void) pj_ice_strans_cfg_default(pj_ice_strans_cfg *cfg); + + +/** + * Copy configuration. + * + * @param pool Pool. + * @param dst Destination. + * @param src Source. + */ +PJ_DECL(void) pj_ice_strans_cfg_copy(pj_pool_t *pool, + pj_ice_strans_cfg *dst, + const pj_ice_strans_cfg *src); + + +/** + * Create and initialize the ICE stream transport with the specified + * parameters. + * + * @param name Optional name for logging identification. + * @param cfg Configuration. + * @param comp_cnt Number of components. + * @param user_data Arbitrary user data to be associated with this + * ICE stream transport. + * @param cb Callback. + * @param p_ice_st Pointer to receive the ICE stream transport + * instance. + * + * @return PJ_SUCCESS if ICE stream transport is created + * successfully. + */ +PJ_DECL(pj_status_t) pj_ice_strans_create(const char *name, + const pj_ice_strans_cfg *cfg, + unsigned comp_cnt, + void *user_data, + const pj_ice_strans_cb *cb, + pj_ice_strans **p_ice_st); + +/** + * Get ICE session state. + * + * @param ice_st The ICE stream transport. + * + * @return ICE session state. + */ +PJ_DECL(pj_ice_strans_state) pj_ice_strans_get_state(pj_ice_strans *ice_st); + + +/** + * Get string representation of ICE state. + * + * @param state ICE stream transport state. + * + * @return String. + */ +PJ_DECL(const char*) pj_ice_strans_state_name(pj_ice_strans_state state); + + +/** + * Destroy the ICE stream transport. This will destroy the ICE session + * inside the ICE stream transport, close all sockets and release all + * other resources. + * + * @param ice_st The ICE stream transport. + * + * @return PJ_SUCCESS, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_ice_strans_destroy(pj_ice_strans *ice_st); + + +/** + * Get the user data associated with the ICE stream transport. + * + * @param ice_st The ICE stream transport. + * + * @return The user data. + */ +PJ_DECL(void*) pj_ice_strans_get_user_data(pj_ice_strans *ice_st); + + +/** + * Get the value of various options of the ICE stream transport. + * + * @param ice_st The ICE stream transport. + * @param opt The options to be initialized with the values + * from the ICE stream transport. + * + * @return PJ_SUCCESS on success, or the appropriate error. + */ +PJ_DECL(pj_status_t) pj_ice_strans_get_options(pj_ice_strans *ice_st, + pj_ice_sess_options *opt); + +/** + * Specify various options for this ICE stream transport. Application + * should call #pj_ice_strans_get_options() to initialize the options + * with their default values. + * + * @param ice_st The ICE stream transport. + * @param opt Options to be applied to this ICE stream transport. + * + * @return PJ_SUCCESS on success, or the appropriate error. + */ +PJ_DECL(pj_status_t) pj_ice_strans_set_options(pj_ice_strans *ice_st, + const pj_ice_sess_options *opt); + + +/** + * Initialize the ICE session in the ICE stream transport. + * When application is about to send an offer containing ICE capability, + * or when it receives an offer containing ICE capability, it must + * call this function to initialize the internal ICE session. This would + * register all transport address aliases for each component to the ICE + * session as candidates. Then application can enumerate all local + * candidates by calling #pj_ice_strans_enum_cands(), and encode these + * candidates in the SDP to be sent to remote agent. + * + * @param ice_st The ICE stream transport. + * @param role ICE role. + * @param local_ufrag Optional local username fragment. + * @param local_passwd Optional local password. + * + * @return PJ_SUCCESS, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_ice_strans_init_ice(pj_ice_strans *ice_st, + pj_ice_sess_role role, + const pj_str_t *local_ufrag, + const pj_str_t *local_passwd); + +/** + * Check if the ICE stream transport has the ICE session created. The + * ICE session is created with #pj_ice_strans_init_ice(). + * + * @param ice_st The ICE stream transport. + * + * @return PJ_TRUE if #pj_ice_strans_init_ice() has been + * called. + */ +PJ_DECL(pj_bool_t) pj_ice_strans_has_sess(pj_ice_strans *ice_st); + + +/** + * Check if ICE negotiation is still running. + * + * @param ice_st The ICE stream transport. + * + * @return PJ_TRUE if ICE session has been created and ICE + * negotiation negotiation is in progress. + */ +PJ_DECL(pj_bool_t) pj_ice_strans_sess_is_running(pj_ice_strans *ice_st); + + +/** + * Check if ICE negotiation has completed. + * + * @param ice_st The ICE stream transport. + * + * @return PJ_TRUE if ICE session has been created and the + * negotiation is complete. + */ +PJ_DECL(pj_bool_t) pj_ice_strans_sess_is_complete(pj_ice_strans *ice_st); + + +/** + * Get the current/running component count. If ICE negotiation has not + * been started, the number of components will be equal to the number + * when the ICE stream transport was created. Once negotiation been + * started, the number of components will be the lowest number of + * component between local and remote agents. + * + * @param ice_st The ICE stream transport. + * + * @return The running number of components. + */ +PJ_DECL(unsigned) pj_ice_strans_get_running_comp_cnt(pj_ice_strans *ice_st); + + +/** + * Get the ICE username fragment and password of the ICE session. The + * local username fragment and password can only be retrieved once ICE + * session has been created with #pj_ice_strans_init_ice(). The remote + * username fragment and password can only be retrieved once ICE session + * has been started with #pj_ice_strans_start_ice(). + * + * Note that the string returned by this function is only valid throughout + * the duration of the ICE session, and the application must not modify + * these strings. Once the ICE session has been stopped with + * #pj_ice_strans_stop_ice(), the pointer in the string will no longer be + * valid. + * + * @param ice_st The ICE stream transport. + * @param loc_ufrag Optional pointer to receive ICE username fragment + * of local endpoint from the ICE session. + * @param loc_pwd Optional pointer to receive ICE password of local + * endpoint from the ICE session. + * @param rem_ufrag Optional pointer to receive ICE username fragment + * of remote endpoint from the ICE session. + * @param rem_pwd Optional pointer to receive ICE password of remote + * endpoint from the ICE session. + * + * @return PJ_SUCCESS if the strings have been retrieved + * successfully. + */ +PJ_DECL(pj_status_t) pj_ice_strans_get_ufrag_pwd(pj_ice_strans *ice_st, + pj_str_t *loc_ufrag, + pj_str_t *loc_pwd, + pj_str_t *rem_ufrag, + pj_str_t *rem_pwd); + + +/** + * Get the number of local candidates for the specified component ID. + * + * @param ice_st The ICE stream transport. + * @param comp_id Component ID. + * + * @return The number of candidates. + */ +PJ_DECL(unsigned) pj_ice_strans_get_cands_count(pj_ice_strans *ice_st, + unsigned comp_id); + +/** + * Enumerate the local candidates for the specified component. + * + * @param ice_st The ICE stream transport. + * @param comp_id Component ID. + * @param count On input, it specifies the maximum number of + * elements. On output, it will be filled with + * the number of candidates copied to the + * array. + * @param cand Array of candidates. + * + * @return PJ_SUCCESS, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_ice_strans_enum_cands(pj_ice_strans *ice_st, + unsigned comp_id, + unsigned *count, + pj_ice_sess_cand cand[]); + +/** + * Get the default candidate for the specified component. When this + * function is called before ICE negotiation completes, the default + * candidate is selected according to local preference criteria. When + * this function is called after ICE negotiation completes, the + * default candidate is the candidate that forms the valid pair. + * + * @param ice_st The ICE stream transport. + * @param comp_id Component ID. + * @param cand Pointer to receive the default candidate + * information. + */ +PJ_DECL(pj_status_t) pj_ice_strans_get_def_cand(pj_ice_strans *ice_st, + unsigned comp_id, + pj_ice_sess_cand *cand); + +/** + * Get the current ICE role. ICE session must have been initialized + * before this function can be called. + * + * @param ice_st The ICE stream transport. + * + * @return Current ICE role. + */ +PJ_DECL(pj_ice_sess_role) pj_ice_strans_get_role(pj_ice_strans *ice_st); + + +/** + * Change session role. This happens for example when ICE session was + * created with controlled role when receiving an offer, but it turns out + * that the offer contains "a=ice-lite" attribute when the SDP gets + * inspected. ICE session must have been initialized before this function + * can be called. + * + * @param ice_st The ICE stream transport. + * @param new_role The new role to be set. + * + * @return PJ_SUCCESS on success, or the appropriate error. + */ +PJ_DECL(pj_status_t) pj_ice_strans_change_role(pj_ice_strans *ice_st, + pj_ice_sess_role new_role); + + +/** + * Start ICE connectivity checks. This function can only be called + * after the ICE session has been created in the ICE stream transport + * with #pj_ice_strans_init_ice(). + * + * This function must be called once application has received remote + * candidate list (typically from the remote SDP). This function pairs + * local candidates with remote candidates, and starts ICE connectivity + * checks. The ICE session/transport will then notify the application + * via the callback when ICE connectivity checks completes, either + * successfully or with failure. + * + * @param ice_st The ICE stream transport. + * @param rem_ufrag Remote ufrag, as seen in the SDP received from + * the remote agent. + * @param rem_passwd Remote password, as seen in the SDP received from + * the remote agent. + * @param rcand_cnt Number of remote candidates in the array. + * @param rcand Remote candidates array. + * + * @return PJ_SUCCESS, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_ice_strans_start_ice(pj_ice_strans *ice_st, + const pj_str_t *rem_ufrag, + const pj_str_t *rem_passwd, + unsigned rcand_cnt, + const pj_ice_sess_cand rcand[]); + +/** + * Retrieve the candidate pair that has been nominated and successfully + * checked for the specified component. If ICE negotiation is still in + * progress or it has failed, this function will return NULL. + * + * @param ice_st The ICE stream transport. + * @param comp_id Component ID. + * + * @return The valid pair as ICE checklist structure if the + * pair exist. + */ +PJ_DECL(const pj_ice_sess_check*) +pj_ice_strans_get_valid_pair(const pj_ice_strans *ice_st, + unsigned comp_id); + +/** + * Stop and destroy the ICE session inside this media transport. Application + * needs to call this function once the media session is over (the call has + * been disconnected). + * + * Application MAY reuse this ICE stream transport for subsequent calls. + * In this case, it must call #pj_ice_strans_stop_ice() when the call is + * disconnected, and reinitialize the ICE stream transport for subsequent + * call with #pj_ice_strans_init_ice()/#pj_ice_strans_start_ice(). In this + * case, the ICE stream transport will maintain the internal sockets and + * continue to send STUN keep-alive packets and TURN Refresh request to + * keep the NAT binding/TURN allocation open and to detect change in STUN + * mapped address. + * + * If application does not want to reuse the ICE stream transport for + * subsequent calls, it must call #pj_ice_strans_destroy() to destroy the + * ICE stream transport altogether. + * + * @param ice_st The ICE stream transport. + * + * @return PJ_SUCCESS, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_ice_strans_stop_ice(pj_ice_strans *ice_st); + + +/** + * Send outgoing packet using this transport. + * Application can send data (normally RTP or RTCP packets) at any time + * by calling this function. This function takes a destination + * address as one of the arguments, and this destination address should + * be taken from the default transport address of the component (that is + * the address in SDP c= and m= lines, or in a=rtcp attribute). + * If ICE negotiation is in progress, this function will send the data + * to the destination address. Otherwise if ICE negotiation has completed + * successfully, this function will send the data to the nominated remote + * address, as negotiated by ICE. + * + * @param ice_st The ICE stream transport. + * @param comp_id Component ID. + * @param data The data or packet to be sent. + * @param data_len Size of data or packet, in bytes. + * @param dst_addr The destination address. + * @param dst_addr_len Length of destination address. + * + * @return PJ_SUCCESS if data is sent successfully. + */ +PJ_DECL(pj_status_t) pj_ice_strans_sendto(pj_ice_strans *ice_st, + unsigned comp_id, + const void *data, + pj_size_t data_len, + const pj_sockaddr_t *dst_addr, + int dst_addr_len); + + +/** + * @} + */ + + +PJ_END_DECL + + + +#endif /* __PJNATH_ICE_STRANS_H__ */ + diff --git a/pjnath/include/pjnath/nat_detect.h b/pjnath/include/pjnath/nat_detect.h new file mode 100644 index 0000000..8d217ce --- /dev/null +++ b/pjnath/include/pjnath/nat_detect.h @@ -0,0 +1,208 @@ +/* $Id: nat_detect.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_NAT_DETECT_H__ +#define __PJNATH_NAT_DETECT_H__ + +/** + * @file ice_session.h + * @brief ICE session management + */ +#include <pjnath/stun_session.h> + + +PJ_BEGIN_DECL + + +/** + * @defgroup PJNATH_NAT_DETECT NAT Classification/Detection Tool + * @brief NAT Classification/Detection Tool + * @ingroup PJNATH + * @{ + * + * This module provides one function to perform NAT classification and + * detection. NAT type detection is performed by calling + * #pj_stun_detect_nat_type() function. + */ + + +/** + * This enumeration describes the NAT types, as specified by RFC 3489 + * Section 5, NAT Variations. + */ +typedef enum pj_stun_nat_type +{ + /** + * NAT type is unknown because the detection has not been performed. + */ + PJ_STUN_NAT_TYPE_UNKNOWN, + + /** + * NAT type is unknown because there is failure in the detection + * process, possibly because server does not support RFC 3489. + */ + PJ_STUN_NAT_TYPE_ERR_UNKNOWN, + + /** + * This specifies that the client has open access to Internet (or + * at least, its behind a firewall that behaves like a full-cone NAT, + * but without the translation) + */ + PJ_STUN_NAT_TYPE_OPEN, + + /** + * This specifies that communication with server has failed, probably + * because UDP packets are blocked. + */ + PJ_STUN_NAT_TYPE_BLOCKED, + + /** + * Firewall that allows UDP out, and responses have to come back to + * the source of the request (like a symmetric NAT, but no + * translation. + */ + PJ_STUN_NAT_TYPE_SYMMETRIC_UDP, + + /** + * A full cone NAT is one where all requests from the same internal + * IP address and port are mapped to the same external IP address and + * port. Furthermore, any external host can send a packet to the + * internal host, by sending a packet to the mapped external address. + */ + PJ_STUN_NAT_TYPE_FULL_CONE, + + /** + * A symmetric NAT is one where all requests from the same internal + * IP address and port, to a specific destination IP address and port, + * are mapped to the same external IP address and port. If the same + * host sends a packet with the same source address and port, but to + * a different destination, a different mapping is used. Furthermore, + * only the external host that receives a packet can send a UDP packet + * back to the internal host. + */ + PJ_STUN_NAT_TYPE_SYMMETRIC, + + /** + * A restricted cone NAT is one where all requests from the same + * internal IP address and port are mapped to the same external IP + * address and port. Unlike a full cone NAT, an external host (with + * IP address X) can send a packet to the internal host only if the + * internal host had previously sent a packet to IP address X. + */ + PJ_STUN_NAT_TYPE_RESTRICTED, + + /** + * A port restricted cone NAT is like a restricted cone NAT, but the + * restriction includes port numbers. Specifically, an external host + * can send a packet, with source IP address X and source port P, + * to the internal host only if the internal host had previously sent + * a packet to IP address X and port P. + */ + PJ_STUN_NAT_TYPE_PORT_RESTRICTED + +} pj_stun_nat_type; + + +/** + * This structure contains the result of NAT classification function. + */ +typedef struct pj_stun_nat_detect_result +{ + /** + * Status of the detection process. If this value is not PJ_SUCCESS, + * the detection has failed and \a nat_type field will contain + * PJ_STUN_NAT_TYPE_UNKNOWN. + */ + pj_status_t status; + + /** + * The text describing the status, if the status is not PJ_SUCCESS. + */ + const char *status_text; + + /** + * This contains the NAT type as detected by the detection procedure. + * This value is only valid when the \a status is PJ_SUCCESS. + */ + pj_stun_nat_type nat_type; + + /** + * Text describing that NAT type. + */ + const char *nat_type_name; + +} pj_stun_nat_detect_result; + + +/** + * Type of callback to be called when the NAT detection function has + * completed. + */ +typedef void pj_stun_nat_detect_cb(void *user_data, + const pj_stun_nat_detect_result *res); + + +/** + * Get the NAT name from the specified NAT type. + * + * @param type NAT type. + * + * @return NAT name. + */ +PJ_DECL(const char*) pj_stun_get_nat_name(pj_stun_nat_type type); + + +/** + * Perform NAT classification function according to the procedures + * specified in RFC 3489. Once this function returns successfully, + * the procedure will run in the "background" and will complete + * asynchronously. Application can register a callback to be notified + * when such detection has completed. + * + * @param server STUN server address. + * @param stun_cfg A structure containing various STUN configurations, + * such as the ioqueue and timer heap instance used + * to receive network I/O and timer events. + * @param user_data Application data, which will be returned back + * in the callback. + * @param cb Callback to be registered to receive notification + * about detection result. + * + * @return If this function returns PJ_SUCCESS, the procedure + * will complete asynchronously and callback will be + * called when it completes. For other return + * values, it means that an error has occured and + * the procedure did not start. + */ +PJ_DECL(pj_status_t) pj_stun_detect_nat_type(const pj_sockaddr_in *server, + pj_stun_config *stun_cfg, + void *user_data, + pj_stun_nat_detect_cb *cb); + + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJNATH_NAT_DETECT_H__ */ + diff --git a/pjnath/include/pjnath/stun_auth.h b/pjnath/include/pjnath/stun_auth.h new file mode 100644 index 0000000..5cf1817 --- /dev/null +++ b/pjnath/include/pjnath/stun_auth.h @@ -0,0 +1,457 @@ +/* $Id: stun_auth.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_STUN_AUTH_H__ +#define __PJNATH_STUN_AUTH_H__ + +/** + * @file stun_auth.h + * @brief STUN authentication. + */ + +#include <pjnath/stun_msg.h> + + +PJ_BEGIN_DECL + + +/* **************************************************************************/ +/** + * @defgroup PJNATH_STUN_AUTH STUN Authentication + * @brief STUN authentication helper + * @ingroup PJNATH_STUN_BASE + * @{ + */ + +/** + * Type of authentication. + */ +typedef enum pj_stun_auth_type +{ + /** + * No authentication. + */ + PJ_STUN_AUTH_NONE = 0, + + /** + * Authentication using short term credential. + */ + PJ_STUN_AUTH_SHORT_TERM = 1, + + /** + * Authentication using long term credential. + */ + PJ_STUN_AUTH_LONG_TERM = 2 + +} pj_stun_auth_type; + + +/** + * Type of authentication data in the credential. + */ +typedef enum pj_stun_auth_cred_type +{ + /** + * The credential data contains a static credential to be matched + * against the credential in the message. A static credential can be + * used as both client side or server side authentication. + */ + PJ_STUN_AUTH_CRED_STATIC, + + /** + * The credential data contains callbacks to be called to verify the + * credential in the message. A dynamic credential is suitable when + * performing server side authentication where server does not know + * in advance the identity of the user requesting authentication. + */ + PJ_STUN_AUTH_CRED_DYNAMIC + +} pj_stun_auth_cred_type; + + +/** + * Type of encoding applied to the password stored in the credential. + */ +typedef enum pj_stun_passwd_type +{ + /** + * Plain text password. + */ + PJ_STUN_PASSWD_PLAIN = 0, + + /** + * Hashed password, valid for long term credential only. The hash value + * of the password is calculated as MD5(USERNAME ":" REALM ":" PASSWD) + * with all quotes removed from the username and realm values. + */ + PJ_STUN_PASSWD_HASHED = 1 + +} pj_stun_passwd_type; + + +/** + * This structure contains the descriptions needed to perform server side + * authentication. Depending on the \a type set in the structure, application + * may specify a static username/password combination, or to have callbacks + * called by the function to authenticate the credential dynamically. + */ +typedef struct pj_stun_auth_cred +{ + /** + * The type of authentication information in this structure. + */ + pj_stun_auth_cred_type type; + + /** + * This union contains the authentication data. + */ + union + { + /** + * This structure contains static data for performing authentication. + * A non-empty realm indicates whether short term or long term + * credential is used. + */ + struct + { + /** + * If not-empty, it indicates that this is a long term credential. + */ + pj_str_t realm; + + /** + * The username of the credential. + */ + pj_str_t username; + + /** + * Data type to indicate the type of password in the \a data field. + */ + pj_stun_passwd_type data_type; + + /** + * The data, which depends depends on the value of \a data_type + * field. When \a data_type is zero, this field will contain the + * plaintext password. + */ + pj_str_t data; + + /** + * Optional NONCE. + */ + pj_str_t nonce; + + } static_cred; + + /** + * This structure contains callback to be called by the framework + * to authenticate the incoming message. + */ + struct + { + /** + * User data which will be passed back to callback functions. + */ + void *user_data; + + /** + * This callback is called by pj_stun_verify_credential() when + * server needs to challenge the request with 401 response. + * + * @param user_data The user data as specified in the credential. + * @param pool Pool to allocate memory. + * @param realm On return, the function should fill in with + * realm if application wants to use long term + * credential. Otherwise application should set + * empty string for the realm. + * @param nonce On return, if application wants to use long + * term credential, it MUST fill in the nonce + * with some value. Otherwise if short term + * credential is wanted, it MAY set this value. + * If short term credential is wanted and the + * application doesn't want to include NONCE, + * then it must set this to empty string. + * + * @return The callback should return PJ_SUCCESS, or + * otherwise response message will not be + * created. + */ + pj_status_t (*get_auth)(void *user_data, + pj_pool_t *pool, + pj_str_t *realm, + pj_str_t *nonce); + + /** + * Get the credential to be put in outgoing request. + * + * @param msg The outgoing message where the credential is + * to be applied. + * @param user_data The user data as specified in the credential. + * @param pool Pool where the callback can allocate memory + * to fill in the credential. + * @param realm On return, the callback may specify the realm + * if long term credential is desired, otherwise + * this string must be set to empty. + * @param username On return, the callback must fill in with the + * username. + * @param nonce On return, the callback may optionally fill in + * this argument with NONCE value if desired, + * otherwise this argument must be set to empty. + * @param data_type On return, the callback must set this argument + * with the type of password in the data argument. + * @param data On return, the callback must set this with + * the password, encoded according to data_type + * argument. + * + * @return The callback must return PJ_SUCCESS, otherwise + * the message transmission will be cancelled. + */ + pj_status_t (*get_cred)(const pj_stun_msg *msg, + void *user_data, + pj_pool_t *pool, + pj_str_t *realm, + pj_str_t *username, + pj_str_t *nonce, + pj_stun_passwd_type *data_type, + pj_str_t *data); + + /** + * Get the password for the specified username. This function + * is also used to check whether the username is valid. + * + * @param msg The STUN message where the password will be + * applied to. + * @param user_data The user data as specified in the credential. + * @param realm The realm as specified in the message. + * @param username The username as specified in the message. + * @param pool Pool to allocate memory when necessary. + * @param data_type On return, application should fill up this + * argument with the type of data (which should + * be zero if data is a plaintext password). + * @param data On return, application should fill up this + * argument with the password according to + * data_type. + * + * @return The callback should return PJ_SUCCESS if + * username has been successfully verified + * and password was obtained. If non-PJ_SUCCESS + * is returned, it is assumed that the + * username is not valid. + */ + pj_status_t (*get_password)(const pj_stun_msg *msg, + void *user_data, + const pj_str_t *realm, + const pj_str_t *username, + pj_pool_t *pool, + pj_stun_passwd_type *data_type, + pj_str_t *data); + + /** + * This callback will be called to verify that the NONCE given + * in the message can be accepted. If this callback returns + * PJ_FALSE, 438 (Stale Nonce) response will be created. + * + * This callback is optional. + * + * @param msg The STUN message where the nonce was received. + * @param user_data The user data as specified in the credential. + * @param realm The realm as specified in the message. + * @param username The username as specified in the message. + * @param nonce The nonce to be verified. + * + * @return The callback MUST return non-zero if the + * NONCE can be accepted. + */ + pj_bool_t (*verify_nonce)(const pj_stun_msg *msg, + void *user_data, + const pj_str_t *realm, + const pj_str_t *username, + const pj_str_t *nonce); + + } dyn_cred; + + } data; + +} pj_stun_auth_cred; + + +/** + * This structure contains the credential information that is found and + * used to authenticate incoming requests. Application may use this + * information when generating authentication for the outgoing response. + */ +typedef struct pj_stun_req_cred_info +{ + /** + * The REALM value found in the incoming request. If short term + * credential is used, the value will be empty. + */ + pj_str_t realm; + + /** + * The USERNAME value found in the incoming request. + */ + pj_str_t username; + + /** + * Optional NONCE. + */ + pj_str_t nonce; + + /** + * Authentication key that was used to authenticate the incoming + * request. This key is created with #pj_stun_create_key(), and + * it can be used to encode the credential of the outgoing + * response. + */ + pj_str_t auth_key; + +} pj_stun_req_cred_info; + + +/** + * Duplicate authentication credential. + * + * @param pool Pool to be used to allocate memory. + * @param dst Destination credential. + * @param src Source credential. + */ +PJ_DECL(void) pj_stun_auth_cred_dup(pj_pool_t *pool, + pj_stun_auth_cred *dst, + const pj_stun_auth_cred *src); + +/** + * Duplicate request credential. + * + * @param pool Pool to be used to allocate memory. + * @param dst Destination credential. + * @param src Source credential. + */ +PJ_DECL(void) pj_stun_req_cred_info_dup(pj_pool_t *pool, + pj_stun_req_cred_info *dst, + const pj_stun_req_cred_info *src); + + +/** + * Create authentication key to be used for encoding the message with + * MESSAGE-INTEGRITY. If short term credential is used (i.e. the realm + * argument is NULL or empty), the key will be copied from the password. + * If long term credential is used, the key will be calculated from the + * MD5 hash of the realm, username, and password. + * + * @param pool Pool to allocate memory for the key. + * @param key String to receive the key. + * @param realm The realm of the credential, if long term credential + * is to be used. If short term credential is wanted, + * application can put NULL or empty string here. + * @param username The username. + * @param data_type Password encoding. + * @param data The password. + */ +PJ_DECL(void) pj_stun_create_key(pj_pool_t *pool, + pj_str_t *key, + const pj_str_t *realm, + const pj_str_t *username, + pj_stun_passwd_type data_type, + const pj_str_t *data); + +/** + * Verify credential in the STUN request. Note that before calling this + * function, application must have checked that the message contains + * PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute by calling pj_stun_msg_find_attr() + * function, because this function will reject the message with 401 error + * if it doesn't contain PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute. + * + * @param pkt The original packet which has been parsed into + * the message. This packet MUST NOT have been modified + * after the parsing. + * @param pkt_len The length of the packet. + * @param msg The parsed message to be verified. + * @param cred Pointer to credential to be used to authenticate + * the message. + * @param pool If response is to be created, then memory will + * be allocated from this pool. + * @param info Optional pointer to receive authentication information + * found in the request and the credential that is used + * to authenticate the request. + * @param p_response Optional pointer to receive the response message + * then the credential in the request fails to + * authenticate. + * + * @return PJ_SUCCESS if credential is verified successfully. + * If the verification fails and \a p_response is not + * NULL, an appropriate response will be returned in + * \a p_response. + */ +PJ_DECL(pj_status_t) pj_stun_authenticate_request(const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + pj_stun_auth_cred *cred, + pj_pool_t *pool, + pj_stun_req_cred_info *info, + pj_stun_msg **p_response); + + +/** + * Determine if STUN message can be authenticated. Some STUN error + * responses cannot be authenticated since they cannot contain STUN + * MESSAGE-INTEGRITY attribute. STUN Indication messages also cannot + * be authenticated. + * + * @param msg The STUN message. + * + * @return Non-zero if the STUN message can be authenticated. + */ +PJ_DECL(pj_bool_t) pj_stun_auth_valid_for_msg(const pj_stun_msg *msg); + + +/** + * Verify credential in the STUN response. Note that before calling this + * function, application must have checked that the message contains + * PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute by calling pj_stun_msg_find_attr() + * function, because otherwise this function will report authentication + * failure. + * + * @param pkt The original packet which has been parsed into + * the message. This packet MUST NOT have been modified + * after the parsing. + * @param pkt_len The length of the packet. + * @param msg The parsed message to be verified. + * @param key Authentication key to calculate MESSAGE-INTEGRITY + * value. Application can create this key by using + * #pj_stun_create_key() function. + * + * @return PJ_SUCCESS if credential is verified successfully. + */ +PJ_DECL(pj_status_t) pj_stun_authenticate_response(const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + const pj_str_t *key); + + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJNATH_STUN_AUTH_H__ */ + diff --git a/pjnath/include/pjnath/stun_config.h b/pjnath/include/pjnath/stun_config.h new file mode 100644 index 0000000..199c452 --- /dev/null +++ b/pjnath/include/pjnath/stun_config.h @@ -0,0 +1,128 @@ +/* $Id: stun_config.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_STUN_CONFIG_H__ +#define __PJNATH_STUN_CONFIG_H__ + +/** + * @file stun_config.h + * @brief STUN endpoint. + */ + +#include <pjnath/stun_msg.h> +#include <pj/assert.h> +#include <pj/errno.h> +#include <pj/string.h> + + +PJ_BEGIN_DECL + + +/* **************************************************************************/ +/** + * @defgroup PJNATH_STUN_CONFIG STUN Config + * @brief STUN config + * @ingroup PJNATH_STUN_BASE + * @{ + */ + +/** + * STUN configuration. + */ +typedef struct pj_stun_config +{ + /** + * Pool factory to be used. + */ + pj_pool_factory *pf; + + /** + * Ioqueue. + */ + pj_ioqueue_t *ioqueue; + + /** + * Timer heap instance. + */ + pj_timer_heap_t *timer_heap; + + /** + * Options. + */ + unsigned options; + + /** + * The default initial STUN round-trip time estimation in msecs. + * The value normally is PJ_STUN_RTO_VALUE. + */ + unsigned rto_msec; + + /** + * The interval to cache outgoing STUN response in the STUN session, + * in miliseconds. + * + * Default 10000 (10 seconds). + */ + unsigned res_cache_msec; + +} pj_stun_config; + + + +/** + * Initialize STUN config. + */ +PJ_INLINE(void) pj_stun_config_init(pj_stun_config *cfg, + pj_pool_factory *factory, + unsigned options, + pj_ioqueue_t *ioqueue, + pj_timer_heap_t *timer_heap) +{ + pj_bzero(cfg, sizeof(*cfg)); + + cfg->pf = factory; + cfg->options = options; + cfg->ioqueue = ioqueue; + cfg->timer_heap = timer_heap; + cfg->rto_msec = PJ_STUN_RTO_VALUE; + cfg->res_cache_msec = PJ_STUN_RES_CACHE_DURATION; +} + + +/** + * Check that STUN config is valid. + */ +PJ_INLINE(pj_status_t) pj_stun_config_check_valid(const pj_stun_config *cfg) +{ + PJ_ASSERT_RETURN(cfg->ioqueue && cfg->pf && cfg->timer_heap && + cfg->rto_msec && cfg->res_cache_msec, PJ_EINVAL); + return PJ_SUCCESS; +} + + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJNATH_STUN_CONFIG_H__ */ + diff --git a/pjnath/include/pjnath/stun_msg.h b/pjnath/include/pjnath/stun_msg.h new file mode 100644 index 0000000..9d3d246 --- /dev/null +++ b/pjnath/include/pjnath/stun_msg.h @@ -0,0 +1,1820 @@ +/* $Id: stun_msg.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_STUN_MSG_H__ +#define __PJNATH_STUN_MSG_H__ + +/** + * @file stun_msg.h + * @brief STUN message components. + */ + +#include <pjnath/types.h> +#include <pj/sock.h> + + +PJ_BEGIN_DECL + + +/* **************************************************************************/ +/** + * @defgroup PJNATH_STUN_MSG STUN Message Representation and Parsing + * @ingroup PJNATH_STUN_BASE + * @brief Low-level representation and parsing of STUN messages. + * @{ + */ + + +/** + * STUN magic cookie. + */ +#define PJ_STUN_MAGIC 0x2112A442 + + +/** + * STUN method constants. + */ +enum pj_stun_method_e +{ + /** + * STUN Binding method as defined by RFC 3489-bis. + */ + PJ_STUN_BINDING_METHOD = 1, + + /** + * STUN Shared Secret method as defined by RFC 3489-bis. + */ + PJ_STUN_SHARED_SECRET_METHOD = 2, + + /** + * STUN/TURN Allocate method as defined by draft-ietf-behave-turn + */ + PJ_STUN_ALLOCATE_METHOD = 3, + + /** + * STUN/TURN Refresh method as defined by draft-ietf-behave-turn + */ + PJ_STUN_REFRESH_METHOD = 4, + + /** + * STUN/TURN Send indication as defined by draft-ietf-behave-turn + */ + PJ_STUN_SEND_METHOD = 6, + + /** + * STUN/TURN Data indication as defined by draft-ietf-behave-turn + */ + PJ_STUN_DATA_METHOD = 7, + + /** + * STUN/TURN CreatePermission method as defined by draft-ietf-behave-turn + */ + PJ_STUN_CREATE_PERM_METHOD = 8, + + /** + * STUN/TURN ChannelBind as defined by draft-ietf-behave-turn + */ + PJ_STUN_CHANNEL_BIND_METHOD = 9, + + /** + * All known methods. + */ + PJ_STUN_METHOD_MAX +}; + + +/** + * Retrieve the STUN method from the message-type field of the STUN + * message. + */ +#define PJ_STUN_GET_METHOD(msg_type) ((msg_type) & 0xFEEF) + + +/** + * STUN message classes constants. + */ +enum pj_stun_msg_class_e +{ + /** + * This specifies that the message type is a STUN request message. + */ + PJ_STUN_REQUEST_CLASS = 0, + + /** + * This specifies that the message type is a STUN indication message. + */ + PJ_STUN_INDICATION_CLASS = 1, + + /** + * This specifies that the message type is a STUN successful response. + */ + PJ_STUN_SUCCESS_CLASS = 2, + + /** + * This specifies that the message type is a STUN error response. + */ + PJ_STUN_ERROR_CLASS = 3 +}; + + +/** + * Determine if the message type is a request. + */ +#define PJ_STUN_IS_REQUEST(msg_type) (((msg_type) & 0x0110) == 0x0000) + + +/** + * Determine if the message type is a successful response. + */ +#define PJ_STUN_IS_SUCCESS_RESPONSE(msg_type) (((msg_type) & 0x0110) == 0x0100) + +/** + * The response bit in the message type. + */ +#define PJ_STUN_SUCCESS_RESPONSE_BIT (0x0100) + + +/** + * Determine if the message type is an error response. + */ +#define PJ_STUN_IS_ERROR_RESPONSE(msg_type) (((msg_type) & 0x0110) == 0x0110) + +/** + * The error response bit in the message type. + */ +#define PJ_STUN_ERROR_RESPONSE_BIT (0x0110) + +/** + * Determine if the message type is a response. + */ +#define PJ_STUN_IS_RESPONSE(msg_type) (((msg_type) & 0x0100) == 0x0100) + + +/** + * Determine if the message type is an indication message. + */ +#define PJ_STUN_IS_INDICATION(msg_type) (((msg_type) & 0x0110) == 0x0010) + +/** + * The error response bit in the message type. + */ +#define PJ_STUN_INDICATION_BIT (0x0010) + + +/** + * This enumeration describes STUN message types. + */ +typedef enum pj_stun_msg_type +{ + /** + * STUN BINDING request. + */ + PJ_STUN_BINDING_REQUEST = 0x0001, + + /** + * Successful response to STUN BINDING-REQUEST. + */ + PJ_STUN_BINDING_RESPONSE = 0x0101, + + /** + * Error response to STUN BINDING-REQUEST. + */ + PJ_STUN_BINDING_ERROR_RESPONSE = 0x0111, + + /** + * Binding Indication (ICE) + */ + PJ_STUN_BINDING_INDICATION = 0x0011, + + /** + * STUN SHARED-SECRET reqeust. + */ + PJ_STUN_SHARED_SECRET_REQUEST = 0x0002, + + /** + * Successful response to STUN SHARED-SECRET reqeust. + */ + PJ_STUN_SHARED_SECRET_RESPONSE = 0x0102, + + /** + * Error response to STUN SHARED-SECRET reqeust. + */ + PJ_STUN_SHARED_SECRET_ERROR_RESPONSE = 0x0112, + + + /** + * STUN/TURN Allocate Request + */ + PJ_STUN_ALLOCATE_REQUEST = 0x0003, + + /** + * Successful response to STUN/TURN Allocate Request + */ + PJ_STUN_ALLOCATE_RESPONSE = 0x0103, + + /** + * Failure response to STUN/TURN Allocate Request + */ + PJ_STUN_ALLOCATE_ERROR_RESPONSE = 0x0113, + + + /** + * STUN/TURN REFRESH Request + */ + PJ_STUN_REFRESH_REQUEST = 0x0004, + + /** + * Successful response to STUN REFRESH request + */ + PJ_STUN_REFRESH_RESPONSE = 0x0104, + + /** + * Error response to STUN REFRESH request. + */ + PJ_STUN_REFRESH_ERROR_RESPONSE = 0x0114, + + + /** + * TURN Send indication + */ + PJ_STUN_SEND_INDICATION = 0x0016, + + + /** + * TURN Data indication + */ + PJ_STUN_DATA_INDICATION = 0x0017, + + + /** + * TURN CreatePermission request + */ + PJ_STUN_CREATE_PERM_REQUEST = 0x0008, + + /** + * TURN CreatePermission successful response. + */ + PJ_STUN_CREATE_PERM_RESPONSE = 0x0108, + + /** + * TURN CreatePermission failure response + */ + PJ_STUN_CREATE_PERM_ERROR_RESPONSE = 0x0118, + + + /** + * STUN/TURN ChannelBind Request + */ + PJ_STUN_CHANNEL_BIND_REQUEST = 0x0009, + + /** + * Successful response to STUN ChannelBind request + */ + PJ_STUN_CHANNEL_BIND_RESPONSE = 0x0109, + + /** + * Error response to STUN ChannelBind request. + */ + PJ_STUN_CHANNEL_BIND_ERROR_RESPONSE = 0x0119 + +} pj_stun_msg_type; + + + +/** + * This enumeration describes STUN attribute types. + */ +typedef enum pj_stun_attr_type +{ + PJ_STUN_ATTR_MAPPED_ADDR = 0x0001,/**< MAPPED-ADDRESS. */ + PJ_STUN_ATTR_RESPONSE_ADDR = 0x0002,/**< RESPONSE-ADDRESS (deprcatd)*/ + PJ_STUN_ATTR_CHANGE_REQUEST = 0x0003,/**< CHANGE-REQUEST (deprecated)*/ + PJ_STUN_ATTR_SOURCE_ADDR = 0x0004,/**< SOURCE-ADDRESS (deprecated)*/ + PJ_STUN_ATTR_CHANGED_ADDR = 0x0005,/**< CHANGED-ADDRESS (deprecatd)*/ + PJ_STUN_ATTR_USERNAME = 0x0006,/**< USERNAME attribute. */ + PJ_STUN_ATTR_PASSWORD = 0x0007,/**< was PASSWORD attribute. */ + PJ_STUN_ATTR_MESSAGE_INTEGRITY = 0x0008,/**< MESSAGE-INTEGRITY. */ + PJ_STUN_ATTR_ERROR_CODE = 0x0009,/**< ERROR-CODE. */ + PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES = 0x000A,/**< UNKNOWN-ATTRIBUTES. */ + PJ_STUN_ATTR_REFLECTED_FROM = 0x000B,/**< REFLECTED-FROM (deprecatd)*/ + PJ_STUN_ATTR_CHANNEL_NUMBER = 0x000C,/**< TURN CHANNEL-NUMBER */ + PJ_STUN_ATTR_LIFETIME = 0x000D,/**< TURN LIFETIME attr. */ + PJ_STUN_ATTR_MAGIC_COOKIE = 0x000F,/**< MAGIC-COOKIE attr (deprec)*/ + PJ_STUN_ATTR_BANDWIDTH = 0x0010,/**< TURN BANDWIDTH (deprec) */ + PJ_STUN_ATTR_XOR_PEER_ADDR = 0x0012,/**< TURN XOR-PEER-ADDRESS */ + PJ_STUN_ATTR_DATA = 0x0013,/**< DATA attribute. */ + PJ_STUN_ATTR_REALM = 0x0014,/**< REALM attribute. */ + PJ_STUN_ATTR_NONCE = 0x0015,/**< NONCE attribute. */ + PJ_STUN_ATTR_XOR_RELAYED_ADDR = 0x0016,/**< TURN XOR-RELAYED-ADDRESS */ + PJ_STUN_ATTR_REQ_ADDR_TYPE = 0x0017,/**< REQUESTED-ADDRESS-TYPE */ + PJ_STUN_ATTR_EVEN_PORT = 0x0018,/**< TURN EVEN-PORT */ + PJ_STUN_ATTR_REQ_TRANSPORT = 0x0019,/**< TURN REQUESTED-TRANSPORT */ + PJ_STUN_ATTR_DONT_FRAGMENT = 0x001A,/**< TURN DONT-FRAGMENT */ + PJ_STUN_ATTR_XOR_MAPPED_ADDR = 0x0020,/**< XOR-MAPPED-ADDRESS */ + PJ_STUN_ATTR_TIMER_VAL = 0x0021,/**< TIMER-VAL attribute. */ + PJ_STUN_ATTR_RESERVATION_TOKEN = 0x0022,/**< TURN RESERVATION-TOKEN */ + PJ_STUN_ATTR_XOR_REFLECTED_FROM = 0x0023,/**< XOR-REFLECTED-FROM */ + PJ_STUN_ATTR_PRIORITY = 0x0024,/**< PRIORITY */ + PJ_STUN_ATTR_USE_CANDIDATE = 0x0025,/**< USE-CANDIDATE */ + PJ_STUN_ATTR_ICMP = 0x0030,/**< ICMP (TURN) */ + + PJ_STUN_ATTR_END_MANDATORY_ATTR, + + PJ_STUN_ATTR_START_EXTENDED_ATTR= 0x8021, + + PJ_STUN_ATTR_SOFTWARE = 0x8022,/**< SOFTWARE attribute. */ + PJ_STUN_ATTR_ALTERNATE_SERVER = 0x8023,/**< ALTERNATE-SERVER. */ + PJ_STUN_ATTR_REFRESH_INTERVAL = 0x8024,/**< REFRESH-INTERVAL. */ + PJ_STUN_ATTR_FINGERPRINT = 0x8028,/**< FINGERPRINT attribute. */ + PJ_STUN_ATTR_ICE_CONTROLLED = 0x8029,/**< ICE-CCONTROLLED attribute.*/ + PJ_STUN_ATTR_ICE_CONTROLLING = 0x802a,/**< ICE-CCONTROLLING attribute*/ + + PJ_STUN_ATTR_END_EXTENDED_ATTR + +} pj_stun_attr_type; + + +/** + * STUN error codes, which goes into STUN ERROR-CODE attribute. + */ +typedef enum pj_stun_status +{ + PJ_STUN_SC_TRY_ALTERNATE = 300, /**< Try Alternate */ + PJ_STUN_SC_BAD_REQUEST = 400, /**< Bad Request */ + PJ_STUN_SC_UNAUTHORIZED = 401, /**< Unauthorized */ + PJ_STUN_SC_FORBIDDEN = 403, /**< Forbidden (TURN) */ + PJ_STUN_SC_UNKNOWN_ATTRIBUTE = 420, /**< Unknown Attribute */ +#if 0 + /* These were obsolete in recent rfc3489bis */ + //PJ_STUN_SC_STALE_CREDENTIALS = 430, /**< Stale Credentials */ + //PJ_STUN_SC_INTEGRITY_CHECK_FAILURE= 431, /**< Integrity Chk Fail */ + //PJ_STUN_SC_MISSING_USERNAME = 432, /**< Missing Username */ + //PJ_STUN_SC_USE_TLS = 433, /**< Use TLS */ + //PJ_STUN_SC_MISSING_REALM = 434, /**< Missing Realm */ + //PJ_STUN_SC_MISSING_NONCE = 435, /**< Missing Nonce */ + //PJ_STUN_SC_UNKNOWN_USERNAME = 436, /**< Unknown Username */ +#endif + PJ_STUN_SC_ALLOCATION_MISMATCH = 437, /**< TURN Alloc Mismatch */ + PJ_STUN_SC_STALE_NONCE = 438, /**< Stale Nonce */ + PJ_STUN_SC_TRANSITIONING = 439, /**< Transitioning. */ + PJ_STUN_SC_WRONG_CREDENTIALS = 441, /**< TURN Wrong Credentials */ + PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO = 442, /**< Unsupported Transport or + Protocol (TURN) */ + PJ_STUN_SC_OPER_TCP_ONLY = 445, /**< Operation for TCP Only */ + PJ_STUN_SC_CONNECTION_FAILURE = 446, /**< Connection Failure */ + PJ_STUN_SC_CONNECTION_TIMEOUT = 447, /**< Connection Timeout */ + PJ_STUN_SC_ALLOCATION_QUOTA_REACHED = 486, /**< Allocation Quota Reached + (TURN) */ + PJ_STUN_SC_ROLE_CONFLICT = 487, /**< Role Conflict */ + PJ_STUN_SC_SERVER_ERROR = 500, /**< Server Error */ + PJ_STUN_SC_INSUFFICIENT_CAPACITY = 508, /**< Insufficient Capacity + (TURN) */ + PJ_STUN_SC_GLOBAL_FAILURE = 600 /**< Global Failure */ +} pj_stun_status; + + +/** + * This structure describes STUN message header. A STUN message has the + * following format: + * + * \verbatim + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |0 0| STUN Message Type | Message Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Magic Cookie | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Transaction ID + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + \endverbatim + */ +typedef struct pj_stun_msg_hdr +{ + /** + * STUN message type, which the first two bits must be zeroes. + */ + pj_uint16_t type; + + /** + * The message length is the size, in bytes, of the message not + * including the 20 byte STUN header. + */ + pj_uint16_t length; + + /** + * The magic cookie is a fixed value, 0x2112A442 (PJ_STUN_MAGIC constant). + * In the previous version of this specification [15] this field was part + * of the transaction ID. + */ + pj_uint32_t magic; + + /** + * The transaction ID is a 96 bit identifier. STUN transactions are + * identified by their unique 96-bit transaction ID. For request/ + * response transactions, the transaction ID is chosen by the STUN + * client and MUST be unique for each new STUN transaction generated by + * that STUN client. The transaction ID MUST be uniformly and randomly + * distributed between 0 and 2**96 - 1. + */ + pj_uint8_t tsx_id[12]; + +} pj_stun_msg_hdr; + + +/** + * This structre describes STUN attribute header. Each attribute is + * TLV encoded, with a 16 bit type, 16 bit length, and variable value. + * Each STUN attribute ends on a 32 bit boundary: + * + * \verbatim + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + \endverbatim + */ +typedef struct pj_stun_attr_hdr +{ + /** + * STUN attribute type. + */ + pj_uint16_t type; + + /** + * The Length refers to the length of the actual useful content of the + * Value portion of the attribute, measured in bytes. The value + * in the Length field refers to the length of the Value part of the + * attribute prior to padding - i.e., the useful content. + */ + pj_uint16_t length; + +} pj_stun_attr_hdr; + + +/** + * This structure describes STUN generic IP address attribute, used for + * example to represent STUN MAPPED-ADDRESS attribute. + * + * The generic IP address attribute indicates the transport address. + * It consists of an eight bit address family, and a sixteen bit port, + * followed by a fixed length value representing the IP address. If the + * address family is IPv4, the address is 32 bits, in network byte + * order. If the address family is IPv6, the address is 128 bits in + * network byte order. + * + * The format of the generic IP address attribute is: + * + * \verbatim + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |x x x x x x x x| Family | Port | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Address (variable) + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + \endverbatim + */ +typedef struct pj_stun_sockaddr_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * Flag to indicate whether this attribute should be sent in XOR-ed + * format, or has been received in XOR-ed format. + */ + pj_bool_t xor_ed; + + /** + * The socket address + */ + pj_sockaddr sockaddr; + +} pj_stun_sockaddr_attr; + + +/** + * This structure represents a generic STUN attributes with no payload, + * and it is used for example by ICE USE-CANDIDATE attribute. + */ +typedef struct pj_stun_empty_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + +} pj_stun_empty_attr; + + +/** + * This structure represents generic STUN string attributes, such as STUN + * USERNAME, PASSWORD, SOFTWARE, REALM, and NONCE attributes. + */ +typedef struct pj_stun_string_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * The string value. + */ + pj_str_t value; + +} pj_stun_string_attr; + + +/** + * This structure represents a generic STUN attributes with 32bit (unsigned) + * integer value, such as STUN FINGERPRINT and REFRESH-INTERVAL attributes. + */ +typedef struct pj_stun_uint_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * The 32bit value, in host byte order. + */ + pj_uint32_t value; + +} pj_stun_uint_attr; + + +/** + * This structure represents a generic STUN attributes with 64bit (unsigned) + * integer value, such as ICE-CONTROLLED and ICE-CONTROLLING attributes. + */ +typedef struct pj_stun_uint64_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * The 64bit value, in host byte order, represented with pj_timestamp. + */ + pj_timestamp value; + +} pj_stun_uint64_attr; + + +/** + * This structure represents generic STUN attributes to hold a raw binary + * data. + */ +typedef struct pj_stun_binary_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * Special signature to indicate that this is a valid attribute even + * though we don't have meta-data to describe this attribute. + */ + pj_uint32_t magic; + + /** + * Length of the data. + */ + unsigned length; + + /** + * The raw data. + */ + pj_uint8_t *data; + +} pj_stun_binary_attr; + + +/** + * This structure describes STUN MESSAGE-INTEGRITY attribute. + * The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [10] of the + * STUN message. The MESSAGE-INTEGRITY attribute can be present in any + * STUN message type. Since it uses the SHA1 hash, the HMAC will be 20 + * bytes. + */ +typedef struct pj_stun_msgint_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * The 20 bytes hmac value. + */ + pj_uint8_t hmac[20]; + +} pj_stun_msgint_attr; + + +/** + * This structure describes STUN FINGERPRINT attribute. The FINGERPRINT + * attribute can be present in all STUN messages. It is computed as + * the CRC-32 of the STUN message up to (but excluding) the FINGERPRINT + * attribute itself, xor-d with the 32 bit value 0x5354554e + */ +typedef struct pj_stun_uint_attr pj_stun_fingerprint_attr; + + +/** + * This structure represents STUN ERROR-CODE attribute. The ERROR-CODE + * attribute is present in the Binding Error Response and Shared Secret + * Error Response. It is a numeric value in the range of 100 to 699 + * plus a textual reason phrase encoded in UTF-8 + * + * \verbatim + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 0 |Class| Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reason Phrase (variable) .. + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + \endverbatim + */ +typedef struct pj_stun_errcode_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * STUN error code. + */ + int err_code; + + /** + * The reason phrase. + */ + pj_str_t reason; + +} pj_stun_errcode_attr; + + +/** + * This describes STUN REALM attribute. + * The REALM attribute is present in requests and responses. It + * contains text which meets the grammar for "realm" as described in RFC + * 3261 [11], and will thus contain a quoted string (including the + * quotes). + */ +typedef struct pj_stun_string_attr pj_stun_realm_attr; + + +/** + * This describes STUN NONCE attribute. + * The NONCE attribute is present in requests and in error responses. + * It contains a sequence of qdtext or quoted-pair, which are defined in + * RFC 3261 [11]. See RFC 2617 [7] for guidance on selection of nonce + * values in a server. + */ +typedef struct pj_stun_string_attr pj_stun_nonce_attr; + + +/** + * This describes STUN UNKNOWN-ATTRIBUTES attribute. + * The UNKNOWN-ATTRIBUTES attribute is present only in an error response + * when the response code in the ERROR-CODE attribute is 420. + * The attribute contains a list of 16 bit values, each of which + * represents an attribute type that was not understood by the server. + * If the number of unknown attributes is an odd number, one of the + * attributes MUST be repeated in the list, so that the total length of + * the list is a multiple of 4 bytes. + */ +typedef struct pj_stun_unknown_attr +{ + /** + * Standard STUN attribute header. + */ + pj_stun_attr_hdr hdr; + + /** + * Number of unknown attributes in the array. + */ + unsigned attr_count; + + /** + * Array of unknown attribute IDs. + */ + pj_uint16_t attrs[PJ_STUN_MAX_ATTR]; + +} pj_stun_unknown_attr; + + +/** + * This structure describes STUN MAPPED-ADDRESS attribute. + * The MAPPED-ADDRESS attribute indicates the mapped transport address. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_mapped_addr_attr; + + +/** + * This describes STUN XOR-MAPPED-ADDRESS attribute (which has the same + * format as STUN MAPPED-ADDRESS attribute). + * The XOR-MAPPED-ADDRESS attribute is present in responses. It + * provides the same information that would present in the MAPPED- + * ADDRESS attribute but because the NAT's public IP address is + * obfuscated through the XOR function, STUN messages are able to pass + * through NATs which would otherwise interfere with STUN. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_xor_mapped_addr_attr; + + +/** + * This describes STUN SOFTWARE attribute. + * The SOFTWARE attribute contains a textual description of the software + * being used by the agent sending the message. It is used by clients + * and servers. Its value SHOULD include manufacturer and version + * number. */ +typedef struct pj_stun_string_attr pj_stun_software_attr; + + +/** + * This describes STUN ALTERNATE-SERVER attribute. + * The alternate server represents an alternate transport address for a + * different STUN server to try. It is encoded in the same way as + * MAPPED-ADDRESS. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_alt_server_attr; + + +/** + * This describes STUN REFRESH-INTERVAL attribute. + * The REFRESH-INTERVAL indicates the number of milliseconds that the + * server suggests the client should use between refreshes of the NAT + * bindings between the client and server. + */ +typedef struct pj_stun_uint_attr pj_stun_refresh_interval_attr; + + +/** + * This structure describes STUN RESPONSE-ADDRESS attribute. + * The RESPONSE-ADDRESS attribute indicates where the response to a + * Binding Request should be sent. Its syntax is identical to MAPPED- + * ADDRESS. + * + * Note that the usage of this attribute has been deprecated by the + * RFC 3489-bis standard. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_response_addr_attr; + + +/** + * This structure describes STUN CHANGED-ADDRESS attribute. + * The CHANGED-ADDRESS attribute indicates the IP address and port where + * responses would have been sent from if the "change IP" and "change + * port" flags had been set in the CHANGE-REQUEST attribute of the + * Binding Request. The attribute is always present in a Binding + * Response, independent of the value of the flags. Its syntax is + * identical to MAPPED-ADDRESS. + * + * Note that the usage of this attribute has been deprecated by the + * RFC 3489-bis standard. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_changed_addr_attr; + + +/** + * This structure describes STUN CHANGE-REQUEST attribute. + * The CHANGE-REQUEST attribute is used by the client to request that + * the server use a different address and/or port when sending the + * response. + * + * Bit 29 of the value is the "change IP" flag. If true, it requests + * the server to send the Binding Response with a different IP address + * than the one the Binding Request was received on. + * + * Bit 30 of the value is the "change port" flag. If true, it requests + * the server to send the Binding Response with a different port than + * the one the Binding Request was received on. + * + * Note that the usage of this attribute has been deprecated by the + * RFC 3489-bis standard. + */ +typedef struct pj_stun_uint_attr pj_stun_change_request_attr; + +/** + * This structure describes STUN SOURCE-ADDRESS attribute. + * The SOURCE-ADDRESS attribute is present in Binding Responses. It + * indicates the source IP address and port that the server is sending + * the response from. Its syntax is identical to that of MAPPED- + * ADDRESS. + * + * Note that the usage of this attribute has been deprecated by the + * RFC 3489-bis standard. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_src_addr_attr; + + +/** + * This describes the STUN REFLECTED-FROM attribute. + * The REFLECTED-FROM attribute is present only in Binding Responses, + * when the Binding Request contained a RESPONSE-ADDRESS attribute. The + * attribute contains the identity (in terms of IP address) of the + * source where the request came from. Its purpose is to provide + * traceability, so that a STUN server cannot be used as a reflector for + * denial-of-service attacks. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_reflected_from_attr; + + +/** + * This describes STUN USERNAME attribute. + * The USERNAME attribute is used for message integrity. It identifies + * the shared secret used in the message integrity check. Consequently, + * the USERNAME MUST be included in any request that contains the + * MESSAGE-INTEGRITY attribute. + */ +typedef struct pj_stun_string_attr pj_stun_username_attr; + + +/** + * This describes STUN PASSWORD attribute. + * If the message type is Shared Secret Response it MUST include the + * PASSWORD attribute. + */ +typedef struct pj_stun_string_attr pj_stun_password_attr; + + +/** + * This describes TURN CHANNEL-NUMBER attribute. In this library, + * this attribute is represented with 32bit integer. Application may + * use #PJ_STUN_GET_CH_NB() and #PJ_STUN_SET_CH_NB() to extract/set + * channel number value from the 32bit integral value. + * + * The CHANNEL-NUMBER attribute contains the number of the channel. + * It is a 16-bit unsigned integer, followed by a two-octet RFFU field + * which MUST be set to 0 on transmission and ignored on reception. + + \verbatim + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Channel Number | RFFU | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + \endverbatim + */ +typedef struct pj_stun_uint_attr pj_stun_channel_number_attr; + +/** + * Get 16bit channel number from 32bit integral value. + * Note that uint32 attributes are always stored in host byte order + * after they have been parsed from the PDU, so no need to do ntohs() + * here. + */ +#define PJ_STUN_GET_CH_NB(u32) ((pj_uint16_t)(u32>>16)) + +/** + * Convert 16bit channel number into 32bit integral value. + * Note that uint32 attributes will be converted to network byte order + * when the attribute is written to packet, so no need to do htons() + * here. + */ +#define PJ_STUN_SET_CH_NB(chnum) (((pj_uint32_t)chnum) << 16) + + +/** + * This describes STUN LIFETIME attribute. + * The lifetime attribute represents the duration for which the server + * will maintain an allocation in the absence of data traffic either + * from or to the client. It is a 32 bit value representing the number + * of seconds remaining until expiration. + */ +typedef struct pj_stun_uint_attr pj_stun_lifetime_attr; + + +/** + * This describes STUN BANDWIDTH attribute. + * The bandwidth attribute represents the peak bandwidth, measured in + * kbits per second, that the client expects to use on the binding. The + * value represents the sum in the receive and send directions. + */ +typedef struct pj_stun_uint_attr pj_stun_bandwidth_attr; + + +/** + * This describes the STUN XOR-PEER-ADDRESS attribute. + * The XOR-PEER-ADDRESS specifies the address and port of the peer as seen + * from the TURN server. It is encoded in the same way as XOR-MAPPED- + * ADDRESS. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_xor_peer_addr_attr; + + +/** + * This describes the STUN DATA attribute. + * The DATA attribute is present in Send Indications and Data + * Indications. It contains raw payload data that is to be sent (in the + * case of a Send Request) or was received (in the case of a Data + * Indication).. + */ +typedef struct pj_stun_binary_attr pj_stun_data_attr; + + +/** + * This describes the STUN XOR-RELAYED-ADDRESS attribute. The + * XOR-RELAYED-ADDRESS is present in Allocate responses. It specifies the + * address and port that the server allocated to the client. It is + * encoded in the same way as XOR-MAPPED-ADDRESS. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_xor_relayed_addr_attr; + + +/** + * This describes the REQUESTED-ADDRESS-TYPE attribute. + * The REQUESTED-ADDRESS-TYPE attribute is used by clients to request + * the allocation of a specific address type from a server. The + * following is the format of the REQUESTED-ADDRESS-TYPE attribute. + + \verbatim + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Family | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + \endverbatim + */ +typedef struct pj_stun_uint_attr pj_stun_req_addr_type_attr; + + +/** + * This describes the TURN REQUESTED-TRANSPORT attribute, encoded in + * STUN generic integer attribute. + * + * This attribute allows the client to request that the port in the + * relayed-transport-address be even, and (optionally) that the server + * reserve the next-higher port number. The attribute is 8 bits long. + * Its format is: + +\verbatim + 0 + 0 1 2 3 4 5 6 7 + +-+-+-+-+-+-+-+-+ + |R| RFFU | + +-+-+-+-+-+-+-+-+ + +\endverbatim + + * The attribute contains a single 1-bit flag: + * + * R: If 1, the server is requested to reserve the next higher port + * number (on the same IP address) for a subsequent allocation. If + * 0, no such reservation is requested. + * + * The other 7 bits of the attribute must be set to zero on transmission + * and ignored on reception. + */ +typedef struct pj_stun_uint_attr pj_stun_even_port_attr; + + +/** + * This describes the TURN REQUESTED-TRANSPORT attribute, encoded in + * STUN generic integer attribute. + * + * This attribute is used by the client to request a specific transport + * protocol for the allocated transport address. It has the following + * format: + + \verbatim + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Protocol | RFFU | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + \endverbatim + + * The Protocol field specifies the desired protocol. The codepoints + * used in this field are taken from those allowed in the Protocol field + * in the IPv4 header and the NextHeader field in the IPv6 header + * [Protocol-Numbers]. This specification only allows the use of + * codepoint 17 (User Datagram Protocol). + * + * The RFFU field is set to zero on transmission and ignored on + * receiption. It is reserved for future uses. + */ +typedef struct pj_stun_uint_attr pj_stun_req_transport_attr; + +/** + * Get protocol value from 32bit TURN REQUESTED-TRANSPORT attribute. + */ +#define PJ_STUN_GET_RT_PROTO(u32) (u32 >> 24) + +/** + * Convert protocol value to be placed in 32bit TURN REQUESTED-TRANSPORT + * attribute. + */ +#define PJ_STUN_SET_RT_PROTO(proto) (((pj_uint32_t)(proto)) << 24) + + +/** + * This describes the TURN DONT-FRAGMENT attribute. + * + * This attribute is used by the client to request that the server set + * the DF (Don't Fragment) bit in the IP header when relaying the + * application data onward to the peer. This attribute has no value + * part and thus the attribute length field is 0. + */ +typedef struct pj_stun_empty_attr pj_stun_dont_fragment_attr; + + +/** + * This describes the TURN RESERVATION-TOKEN attribute. + * The RESERVATION-TOKEN attribute contains a token that uniquely + * identifies a relayed transport address being held in reserve by the + * server. The server includes this attribute in a success response to + * tell the client about the token, and the client includes this + * attribute in a subsequent Allocate request to request the server use + * that relayed transport address for the allocation. + * + * The attribute value is a 64-bit-long field containing the token + * value. + */ +typedef struct pj_stun_uint64_attr pj_stun_res_token_attr; + +/** + * This describes the XOR-REFLECTED-FROM attribute, as described by + * draft-macdonald-behave-nat-behavior-discovery-00. + * The XOR-REFLECTED-FROM attribute is used in place of the REFLECTED- + * FROM attribute. It provides the same information, but because the + * NAT's public address is obfuscated through the XOR function, It can + * pass through a NAT that would otherwise attempt to translate it to + * the private network address. XOR-REFLECTED-FROM has identical syntax + * to XOR-MAPPED-ADDRESS. + */ +typedef struct pj_stun_sockaddr_attr pj_stun_xor_reflected_from_attr; + +/** + * This describes the PRIORITY attribute from draft-ietf-mmusic-ice-13. + * The PRIORITY attribute indicates the priority that is to be + * associated with a peer reflexive candidate, should one be discovered + * by this check. It is a 32 bit unsigned integer, and has an attribute + * type of 0x0024. + */ +typedef struct pj_stun_uint_attr pj_stun_priority_attr; + +/** + * This describes the USE-CANDIDATE attribute from draft-ietf-mmusic-ice-13. + * The USE-CANDIDATE attribute indicates that the candidate pair + * resulting from this check should be used for transmission of media. + * The attribute has no content (the Length field of the attribute is + * zero); it serves as a flag. + */ +typedef struct pj_stun_empty_attr pj_stun_use_candidate_attr; + +/** + * This describes the STUN TIMER-VAL attribute. + * The TIMER-VAL attribute is used only in conjunction with the Set + * Active Destination response. It conveys from the server, to the + * client, the value of the timer used in the server state machine. + */ +typedef struct pj_stun_uint_attr pj_stun_timer_val_attr; + +/** + * This describes ICE-CONTROLLING attribute. + */ +typedef struct pj_stun_uint64_attr pj_stun_ice_controlling_attr; + +/** + * This describes ICE-CONTROLLED attribute. + */ +typedef struct pj_stun_uint64_attr pj_stun_ice_controlled_attr; + +/** + * This describes TURN ICMP attribute + */ +typedef struct pj_stun_uint_attr pj_stun_icmp_attr; + +/** + * This structure describes a parsed STUN message. All integral fields + * in this structure (including IP addresses) will be in the host + * byte order. + */ +typedef struct pj_stun_msg +{ + /** + * STUN message header. + */ + pj_stun_msg_hdr hdr; + + /** + * Number of attributes in the STUN message. + */ + unsigned attr_count; + + /** + * Array of STUN attributes. + */ + pj_stun_attr_hdr *attr[PJ_STUN_MAX_ATTR]; + +} pj_stun_msg; + + +/** STUN decoding options */ +enum pj_stun_decode_options +{ + /** + * Tell the decoder that the message was received from datagram + * oriented transport (such as UDP). + */ + PJ_STUN_IS_DATAGRAM = 1, + + /** + * Tell pj_stun_msg_decode() to check the validity of the STUN + * message by calling pj_stun_msg_check() before starting to + * decode the packet. + */ + PJ_STUN_CHECK_PACKET = 2, + + /** + * This option current is only valid for #pj_stun_session_on_rx_pkt(). + * When specified, it tells the session NOT to authenticate the + * message. + */ + PJ_STUN_NO_AUTHENTICATE = 4, + + /** + * Disable FINGERPRINT verification. This option can be used when calling + * #pj_stun_msg_check() and #pj_stun_msg_decode() to disable the + * verification of FINGERPRINT, for example when the STUN usage says when + * FINGERPRINT mechanism shall not be used. + */ + PJ_STUN_NO_FINGERPRINT_CHECK = 8 +}; + + +/** + * Get STUN message method name. + * + * @param msg_type The STUN message type (in host byte order) + * + * @return The STUN message method name string. + */ +PJ_DECL(const char*) pj_stun_get_method_name(unsigned msg_type); + + +/** + * Get STUN message class name. + * + * @param msg_type The STUN message type (in host byte order) + * + * @return The STUN message class name string. + */ +PJ_DECL(const char*) pj_stun_get_class_name(unsigned msg_type); + + +/** + * Get STUN attribute name. + * + * @return attr_type The STUN attribute type (in host byte order). + * + * @return The STUN attribute type name string. + */ +PJ_DECL(const char*) pj_stun_get_attr_name(unsigned attr_type); + + +/** + * Get STUN standard reason phrase for the specified error code. + * + * @param err_code The STUN error code. + * + * @return The STUN error reason phrase. + */ +PJ_DECL(pj_str_t) pj_stun_get_err_reason(int err_code); + + +/** + * Internal: set the padding character for string attribute. + * The default padding character is PJ_STUN_STRING_ATTR_PAD_CHR. + * + * @return The previous padding character. + */ +PJ_DECL(int) pj_stun_set_padding_char(int chr); + + +/** + * Initialize a generic STUN message. + * + * @param msg The message structure to be initialized. + * @param msg_type The 14bit message type (see pj_stun_msg_type + * constants). + * @param magic Magic value to be put to the mesage; for requests, + * the value normally should be PJ_STUN_MAGIC. + * @param tsx_id Optional transaction ID, or NULL to let the + * function generates a random transaction ID. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pj_stun_msg_init(pj_stun_msg *msg, + unsigned msg_type, + pj_uint32_t magic, + const pj_uint8_t tsx_id[12]); + +/** + * Create a generic STUN message. + * + * @param pool Pool to create the STUN message. + * @param msg_type The 14bit message type. + * @param magic Magic value to be put to the mesage; for requests, + * the value should be PJ_STUN_MAGIC. + * @param tsx_id Optional transaction ID, or NULL to let the + * function generates a random transaction ID. + * @param p_msg Pointer to receive the message. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pj_stun_msg_create(pj_pool_t *pool, + unsigned msg_type, + pj_uint32_t magic, + const pj_uint8_t tsx_id[12], + pj_stun_msg **p_msg); + +/** + * Clone a STUN message with all of its attributes. + * + * @param pool Pool to allocate memory for the new message. + * @param msg The message to be cloned. + * + * @return The duplicate message. + */ +PJ_DECL(pj_stun_msg*) pj_stun_msg_clone(pj_pool_t *pool, + const pj_stun_msg *msg); + +/** + * Create STUN response message. + * + * @param pool Pool to create the mesage. + * @param req_msg The request message. + * @param err_code STUN error code. If this value is not zero, + * then error response will be created, otherwise + * successful response will be created. + * @param err_msg Optional error message to explain err_code. + * If this value is NULL and err_code is not zero, + * the error string will be taken from the default + * STUN error message. + * @param p_response Pointer to receive the response. + * + * @return PJ_SUCCESS on success, or the appropriate error. + */ +PJ_DECL(pj_status_t) pj_stun_msg_create_response(pj_pool_t *pool, + const pj_stun_msg *req_msg, + unsigned err_code, + const pj_str_t *err_msg, + pj_stun_msg **p_response); + + +/** + * Add STUN attribute to STUN message. + * + * @param msg The STUN message. + * @param attr The STUN attribute to be added to the message. + * + * @return PJ_SUCCESS on success, or PJ_ETOOMANY if there are + * already too many attributes in the message. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_attr(pj_stun_msg *msg, + pj_stun_attr_hdr *attr); + + +/** + * Print the STUN message structure to a packet buffer, ready to be + * sent to remote destination. This function will take care about + * calculating the MESSAGE-INTEGRITY digest as well as FINGERPRINT + * value, if these attributes are present in the message. + * + * If application wants to apply credential to the message, it MUST + * include a blank MESSAGE-INTEGRITY attribute in the message as the + * last attribute or the attribute before FINGERPRINT. This function will + * calculate the HMAC digest from the message using the supplied key in + * the parameter. The key should be set to the password if short term + * credential is used, or calculated from the MD5 hash of the realm, + * username, and password using #pj_stun_create_key() if long term + * credential is used. + * + * If FINGERPRINT attribute is present, this function will calculate + * the FINGERPRINT CRC attribute for the message. The FINGERPRINT MUST + * be added as the last attribute of the message. + * + * @param msg The STUN message to be printed. Upon return, + * some fields in the header (such as message + * length) will be updated. + * @param pkt_buf The buffer to be filled with the packet. + * @param buf_size Size of the buffer. + * @param options Options, which currently must be zero. + * @param key Authentication key to calculate MESSAGE-INTEGRITY + * value. Application can create this key by using + * #pj_stun_create_key() function. + * @param p_msg_len Upon return, it will be filed with the size of + * the packet in bytes, or negative value on error. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_encode(pj_stun_msg *msg, + pj_uint8_t *pkt_buf, + pj_size_t buf_size, + unsigned options, + const pj_str_t *key, + pj_size_t *p_msg_len); + +/** + * Check that the PDU is potentially a valid STUN message. This function + * is useful when application needs to multiplex STUN packets with other + * application traffic. When this function returns PJ_SUCCESS, there is a + * big chance that the packet is a STUN packet. + * + * Note that we cannot be sure that the PDU is a really valid STUN message + * until we actually parse the PDU. + * + * @param pdu The packet buffer. + * @param pdu_len The length of the packet buffer. + * @param options Additional options to be applied in the checking, + * which can be taken from pj_stun_decode_options. One + * of the useful option is PJ_STUN_IS_DATAGRAM which + * means that the pdu represents a whole STUN packet. + * + * @return PJ_SUCCESS if the PDU is a potentially valid STUN + * message. + */ +PJ_DECL(pj_status_t) pj_stun_msg_check(const pj_uint8_t *pdu, + pj_size_t pdu_len, unsigned options); + + +/** + * Decode incoming packet into STUN message. + * + * @param pool Pool to allocate the message. + * @param pdu The incoming packet to be parsed. + * @param pdu_len The length of the incoming packet. + * @param options Parsing flags, according to pj_stun_decode_options. + * @param p_msg Pointer to receive the parsed message. + * @param p_parsed_len Optional pointer to receive how many bytes have + * been parsed for the STUN message. This is useful + * when the packet is received over stream oriented + * transport. + * @param p_response Optional pointer to receive an instance of response + * message, if one can be created. If the packet being + * decoded is a request message, and it contains error, + * and a response can be created, then the STUN + * response message will be returned on this argument. + * + * @return PJ_SUCCESS if a STUN message has been successfully + * decoded. + */ +PJ_DECL(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool, + const pj_uint8_t *pdu, + pj_size_t pdu_len, + unsigned options, + pj_stun_msg **p_msg, + pj_size_t *p_parsed_len, + pj_stun_msg **p_response); + +/** + * Dump STUN message to a printable string output. + * + * @param msg The STUN message + * @param buffer Buffer where the printable string output will + * be printed on. + * @param length Specify the maximum length of the buffer. + * @param printed_len Optional pointer, which on output will be filled + * up with the actual length of the output string. + * + * @return The message string output. + */ +#if PJ_LOG_MAX_LEVEL > 0 +PJ_DECL(char*) pj_stun_msg_dump(const pj_stun_msg *msg, + char *buffer, + unsigned length, + unsigned *printed_len); +#else +# define pj_stun_msg_dump(msg, buf, length, printed_len) "" +#endif + + +/** + * Find STUN attribute in the STUN message, starting from the specified + * index. + * + * @param msg The STUN message. + * @param attr_type The attribute type to be found, from pj_stun_attr_type. + * @param start_index The start index of the attribute in the message. + * Specify zero to start searching from the first + * attribute. + * + * @return The attribute instance, or NULL if it cannot be + * found. + */ +PJ_DECL(pj_stun_attr_hdr*) pj_stun_msg_find_attr(const pj_stun_msg *msg, + int attr_type, + unsigned start_index); + + +/** + * Clone a STUN attribute. + * + * @param pool Pool to allocate memory. + * @param attr Attribute to clone. + * + * @return Duplicate attribute. + */ +PJ_DECL(pj_stun_attr_hdr*) pj_stun_attr_clone(pj_pool_t *pool, + const pj_stun_attr_hdr *attr); + + +/** + * Initialize generic STUN IP address attribute. The \a addr_len and + * \a addr parameters specify whether the address is IPv4 or IPv4 + * address. + * + * @param attr The socket address attribute to initialize. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param xor_ed If non-zero, the port and address will be XOR-ed + * with magic, to make the XOR-MAPPED-ADDRESS attribute. + * @param addr A pj_sockaddr_in or pj_sockaddr_in6 structure. + * @param addr_len Length of \a addr parameter. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_sockaddr_attr_init(pj_stun_sockaddr_attr *attr, + int attr_type, + pj_bool_t xor_ed, + const pj_sockaddr_t *addr, + unsigned addr_len); + +/** + * Create a generic STUN IP address attribute. The \a addr_len and + * \a addr parameters specify whether the address is IPv4 or IPv4 + * address. + * + * @param pool The pool to allocate memory from. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param xor_ed If non-zero, the port and address will be XOR-ed + * with magic, to make the XOR-MAPPED-ADDRESS attribute. + * @param addr A pj_sockaddr_in or pj_sockaddr_in6 structure. + * @param addr_len Length of \a addr parameter. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_sockaddr_attr_create(pj_pool_t *pool, + int attr_type, + pj_bool_t xor_ed, + const pj_sockaddr_t *addr, + unsigned addr_len, + pj_stun_sockaddr_attr **p_attr); + + +/** + * Create and add generic STUN IP address attribute to a STUN message. + * The \a addr_len and \a addr parameters specify whether the address is + * IPv4 or IPv4 address. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param xor_ed If non-zero, the port and address will be XOR-ed + * with magic, to make the XOR-MAPPED-ADDRESS attribute. + * @param addr A pj_sockaddr_in or pj_sockaddr_in6 structure. + * @param addr_len Length of \a addr parameter. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_sockaddr_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + pj_bool_t xor_ed, + const pj_sockaddr_t *addr, + unsigned addr_len); + +/** + * Initialize a STUN generic string attribute. + * + * @param attr The string attribute to be initialized. + * @param pool Pool to duplicate the value into the attribute, + * if value is not NULL or empty. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param value The string value to be assigned to the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_string_attr_init(pj_stun_string_attr *attr, + pj_pool_t *pool, + int attr_type, + const pj_str_t *value); + +/** + * Create a STUN generic string attribute. + * + * @param pool The pool to allocate memory from. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param value The string value to be assigned to the attribute. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_string_attr_create(pj_pool_t *pool, + int attr_type, + const pj_str_t *value, + pj_stun_string_attr **p_attr); + +/** + * Create and add STUN generic string attribute to the message. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param value The string value to be assigned to the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_string_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + const pj_str_t *value); + +/** + * Create a STUN generic 32bit value attribute. + * + * @param pool The pool to allocate memory from. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param value The 32bit value to be assigned to the attribute. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_uint_attr_create(pj_pool_t *pool, + int attr_type, + pj_uint32_t value, + pj_stun_uint_attr **p_attr); + +/** + * Create and add STUN generic 32bit value attribute to the message. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param value The 32bit value to be assigned to the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_uint_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + pj_uint32_t value); + + +/** + * Create a STUN generic 64bit value attribute. + * + * @param pool Pool to allocate memory from. + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param value Optional value to be assigned. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_uint64_attr_create(pj_pool_t *pool, + int attr_type, + const pj_timestamp *value, + pj_stun_uint64_attr **p_attr); + + +/** + * Create and add STUN generic 64bit value attribute to the message. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message + * @param attr_type Attribute type, from #pj_stun_attr_type. + * @param value The 64bit value to be assigned to the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_uint64_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + const pj_timestamp *value); + +/** + * Create a STUN MESSAGE-INTEGRITY attribute. + * + * @param pool The pool to allocate memory from. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msgint_attr_create(pj_pool_t *pool, + pj_stun_msgint_attr **p_attr); + +/** + * Create and add STUN MESSAGE-INTEGRITY attribute. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_msgint_attr(pj_pool_t *pool, + pj_stun_msg *msg); + +/** + * Create a STUN ERROR-CODE attribute. + * + * @param pool The pool to allocate memory from. + * @param err_code STUN error code. + * @param err_reason Optional STUN error reason. If NULL is given, the + * standard error reason will be given. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_errcode_attr_create(pj_pool_t *pool, + int err_code, + const pj_str_t *err_reason, + pj_stun_errcode_attr **p_attr); + + +/** + * Create and add STUN ERROR-CODE attribute to the message. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN mesage. + * @param err_code STUN error code. + * @param err_reason Optional STUN error reason. If NULL is given, the + * standard error reason will be given. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_errcode_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int err_code, + const pj_str_t *err_reason); + +/** + * Create instance of STUN UNKNOWN-ATTRIBUTES attribute and copy the + * unknown attribute array to the attribute. + * + * @param pool The pool to allocate memory from. + * @param attr_cnt Number of attributes in the array (can be zero). + * @param attr Optional array of attributes. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_unknown_attr_create(pj_pool_t *pool, + unsigned attr_cnt, + const pj_uint16_t attr[], + pj_stun_unknown_attr **p_attr); + +/** + * Create and add STUN UNKNOWN-ATTRIBUTES attribute to the message. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message. + * @param attr_cnt Number of attributes in the array (can be zero). + * @param attr Optional array of attribute types. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_unknown_attr(pj_pool_t *pool, + pj_stun_msg *msg, + unsigned attr_cnt, + const pj_uint16_t attr[]); + +/** + * Initialize STUN binary attribute. + * + * @param attr The attribute to be initialized. + * @param pool Pool to copy data, if the data and length are set. + * @param attr_type The attribute type, from #pj_stun_attr_type. + * @param data Data to be coped to the attribute, or NULL + * if no data to be copied now. + * @param length Length of data, or zero if no data is to be + * copied now. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_binary_attr_init(pj_stun_binary_attr *attr, + pj_pool_t *pool, + int attr_type, + const pj_uint8_t *data, + unsigned length); + +/** + * Create STUN binary attribute. + * + * @param pool The pool to allocate memory from. + * @param attr_type The attribute type, from #pj_stun_attr_type. + * @param data Data to be coped to the attribute, or NULL + * if no data to be copied now. + * @param length Length of data, or zero if no data is to be + * copied now. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_binary_attr_create(pj_pool_t *pool, + int attr_type, + const pj_uint8_t *data, + unsigned length, + pj_stun_binary_attr **p_attr); + +/** + * Create STUN binary attribute and add the attribute to the message. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message. + * @param attr_type The attribute type, from #pj_stun_attr_type. + * @param data Data to be coped to the attribute, or NULL + * if no data to be copied now. + * @param length Length of data, or zero if no data is to be + * copied now. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_binary_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type, + const pj_uint8_t *data, + unsigned length); + +/** + * Create STUN empty attribute. + * + * @param pool The pool to allocate memory from. + * @param attr_type The attribute type, from #pj_stun_attr_type. + * @param p_attr Pointer to receive the attribute. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_empty_attr_create(pj_pool_t *pool, + int attr_type, + pj_stun_empty_attr **p_attr); + +/** + * Create STUN empty attribute and add the attribute to the message. + * + * @param pool The pool to allocate memory from. + * @param msg The STUN message. + * @param attr_type The attribute type, from #pj_stun_attr_type. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_msg_add_empty_attr(pj_pool_t *pool, + pj_stun_msg *msg, + int attr_type); + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJNATH_STUN_MSG_H__ */ + diff --git a/pjnath/include/pjnath/stun_session.h b/pjnath/include/pjnath/stun_session.h new file mode 100644 index 0000000..29efe1a --- /dev/null +++ b/pjnath/include/pjnath/stun_session.h @@ -0,0 +1,762 @@ +/* $Id: stun_session.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_STUN_SESSION_H__ +#define __PJNATH_STUN_SESSION_H__ + +/** + * @file stun_session.h + * @brief STUN session management for client/server. + */ + +#include <pjnath/stun_msg.h> +#include <pjnath/stun_auth.h> +#include <pjnath/stun_config.h> +#include <pjnath/stun_transaction.h> +#include <pj/list.h> +#include <pj/timer.h> + +PJ_BEGIN_DECL + + +/* **************************************************************************/ +/** + * @addtogroup PJNATH_STUN_SESSION + * @{ + * + * This is is a transport-independent object to manage a client or server + * STUN session. It has the following features: + * + * - <b>transport independent</b>:\n + * the object does not have it's own socket, but rather it provides + * functions and callbacks to send and receive packets. This way the + * object can be used by different transport types (e.g. UDP, TCP, + * TLS, etc.) as well as better integration to application which + * already has its own means to send and receive packets. + * + * - <b>authentication management</b>:\n + * the object manages STUN authentication throughout the lifetime of + * the session. For client sessions, once it's given a credential to + * authenticate itself with the server, the object will automatically + * add authentication info (the MESSAGE-INTEGRITY) to the request as + * well as authenticate the response. It will also handle long-term + * authentication challenges, including handling of nonce expiration, + * and retry the request automatically. For server sessions, it can + * be configured to authenticate incoming requests automatically. + * + * - <b>static or dynamic credential</b>:\n + * application may specify static or dynamic credential to be used by + * the STUN session. Static credential means a static combination of + * username and password (and these cannot change during the session + * duration), while dynamic credential provides callback to ask the + * application about which username/password to use everytime + * authentication is about to be performed. + * + * - <b>client transaction management</b>:\n + * outgoing requests may be sent with a STUN transaction for reliability, + * and the object will manage the transaction internally (including + * performing retransmissions). Application will be notified about the + * result of the request when the response arrives (or the transaction + * times out). When the request is challenged with authentication, the + * object will retry the request with new authentication info, and + * application will be notified about the final result of this request. + * + * - <b>server transaction management</b>:\n + * application may ask response to incoming requests to be cached by + * the object, and in this case the object will check for cached + * response everytime request is received. The cached response will be + * deleted once a timer expires. + * + * \section using_stun_sess_sec Using the STUN session + * + * The following steps describes how to use the STUN session: + * + * - <b>create the object configuration</b>:\n + * The #pj_stun_config contains the configuration to create the STUN + * session, such as the timer heap to register internal timers and + * various STUN timeout values. You can initialize this structure by + * calling #pj_stun_config_init() + * + * - <b>create the STUN session</b>:\n + * by calling #pj_stun_session_create(). Among other things, this + * function requires the instance of #pj_stun_config and also + * #pj_stun_session_cb structure which stores callbacks to send + * outgoing packets as well as to notify application about incoming + * STUN requests, responses, and indicates and other events. + * + * - <b>configure credential:</b>\n + * if authentication is required for the session, configure the + * credential with #pj_stun_session_set_credential() + * + * - <b>configuring other settings:</b>\n + * several APIs are provided to configure the behavior of the STUN + * session (for example, to set the SOFTWARE attribute value, controls + * the logging behavior, fine tune the mutex locking, etc.). Please see + * the API reference for more info. + * + * - <b>creating outgoing STUN requests or indications:</b>\n + * create the STUN message by using #pj_stun_session_create_req() or + * #pj_stun_session_create_ind(). This will create a transmit data + * buffer containing a blank STUN request or indication. You will then + * typically need to add STUN attributes that are relevant to the + * request or indication, but note that some default attributes will + * be added by the session later when the message is sent (such as + * SOFTWARE attribute and attributes related to authentication). + * The message is now ready to be sent. + * + * - <b>sending outgoing message:</b>\n + * use #pj_stun_session_send_msg() to send outgoing STUN messages (this + * includes STUN requests, indications, and responses). The function has + * options whether to retransmit the request (for non reliable transports) + * or to cache the response if we're sending response. This function in + * turn will call the \a on_send_msg() callback of #pj_stun_session_cb + * to request the application to send the packet. + * + * - <b>handling incoming packet:</b>\n + * call #pj_stun_session_on_rx_pkt() everytime the application receives + * a STUN packet. This function will decode the packet and process the + * packet according to the message, and normally this will cause one + * of the callback in the #pj_stun_session_cb to be called to notify + * the application about the event. + * + * - <b>handling incoming requests:</b>\n + * incoming requests are notified to application in the \a on_rx_request + * callback of the #pj_stun_session_cb. If authentication is enabled in + * the session, the application will only receive this callback after + * the incoming request has been authenticated (if the authentication + * fails, the session would respond automatically with 401 error and + * the callback will not be called). Application now must create and + * send response for this request. + * + * - <b>creating and sending response:</b>\n + * create the STUN response with #pj_stun_session_create_res(). This will + * create a transmit data buffer containing a blank STUN response. You + * will then typically need to add STUN attributes that are relevant to + * the response, but note that some default attributes will + * be added by the session later when the message is sent (such as + * SOFTWARE attribute and attributes related to authentication). + * The message is now ready to be sent. Use #pj_stun_session_send_msg() + * (as explained above) to send the response. + * + * - <b>convenient way to send response:</b>\n + * the #pj_stun_session_respond() is provided as a convenient way to + * create and send simple STUN responses, such as error responses. + * + * - <b>destroying the session:</b>\n + * once the session is done, use #pj_stun_session_destroy() to destroy + * the session. + */ + + +/** Forward declaration for pj_stun_tx_data */ +typedef struct pj_stun_tx_data pj_stun_tx_data; + +/** Forward declaration for pj_stun_rx_data */ +typedef struct pj_stun_rx_data pj_stun_rx_data; + +/** Forward declaration for pj_stun_session */ +typedef struct pj_stun_session pj_stun_session; + + +/** + * This is the callback to be registered to pj_stun_session, to send + * outgoing message and to receive various notifications from the STUN + * session. + */ +typedef struct pj_stun_session_cb +{ + /** + * Callback to be called by the STUN session to send outgoing message. + * + * @param sess The STUN session. + * @param token The token associated with this outgoing message + * and was set by the application. This token was + * set by application in pj_stun_session_send_msg() + * for outgoing messages that are initiated by the + * application, or in pj_stun_session_on_rx_pkt() + * if this message is a response that was internally + * generated by the STUN session (for example, an + * 401/Unauthorized response). Application may use + * this facility for any purposes. + * @param pkt Packet to be sent. + * @param pkt_size Size of the packet to be sent. + * @param dst_addr The destination address. + * @param addr_len Length of destination address. + * + * @return The callback should return the status of the + * packet sending. + */ + pj_status_t (*on_send_msg)(pj_stun_session *sess, + void *token, + const void *pkt, + pj_size_t pkt_size, + const pj_sockaddr_t *dst_addr, + unsigned addr_len); + + /** + * Callback to be called on incoming STUN request message. This function + * is called when application calls pj_stun_session_on_rx_pkt() and when + * the STUN session has detected that the incoming STUN message is a + * STUN request message. In the + * callback processing, application MUST create a response by calling + * pj_stun_session_create_response() function and send the response + * with pj_stun_session_send_msg() function, before returning from + * the callback. + * + * @param sess The STUN session. + * @param pkt Pointer to the original STUN packet. + * @param pkt_len Length of the STUN packet. + * @param rdata Data containing incoming request message. + * @param token The token that was set by the application when + * calling pj_stun_session_on_rx_pkt() function. + * @param src_addr Source address of the packet. + * @param src_addr_len Length of the source address. + * + * @return The return value of this callback will be + * returned back to pj_stun_session_on_rx_pkt() + * function. + */ + pj_status_t (*on_rx_request)(pj_stun_session *sess, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_rx_data *rdata, + void *token, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + + /** + * Callback to be called when response is received or the transaction + * has timed out. This callback is called either when application calls + * pj_stun_session_on_rx_pkt() with the packet containing a STUN + * response for the client transaction, or when the internal timer of + * the STUN client transaction has timed-out before a STUN response is + * received. + * + * @param sess The STUN session. + * @param status Status of the request. If the value if not + * PJ_SUCCESS, the transaction has timed-out + * or other error has occurred, and the response + * argument may be NULL. + * Note that when the status is not success, the + * response may contain non-NULL value if the + * response contains STUN ERROR-CODE attribute. + * @param token The token that was set by the application when + * calling pj_stun_session_send_msg() function. + * Please not that this token IS NOT the token + * that was given in pj_stun_session_on_rx_pkt(). + * @param tdata The original STUN request. + * @param response The response message, on successful transaction, + * or otherwise MAY BE NULL if status is not success. + * Note that when the status is not success, this + * argument may contain non-NULL value if the + * response contains STUN ERROR-CODE attribute. + * @param src_addr The source address where the response was + * received, or NULL if the response is NULL. + * @param src_addr_len The length of the source address. + */ + void (*on_request_complete)(pj_stun_session *sess, + pj_status_t status, + void *token, + pj_stun_tx_data *tdata, + const pj_stun_msg *response, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + + + /** + * Callback to be called on incoming STUN request message. This function + * is called when application calls pj_stun_session_on_rx_pkt() and when + * the STUN session has detected that the incoming STUN message is a + * STUN indication message. + * + * @param sess The STUN session. + * @param pkt Pointer to the original STUN packet. + * @param pkt_len Length of the STUN packet. + * @param msg The parsed STUN indication. + * @param token The token that was set by the application when + * calling pj_stun_session_on_rx_pkt() function. + * @param src_addr Source address of the packet. + * @param src_addr_len Length of the source address. + * + * @return The return value of this callback will be + * returned back to pj_stun_session_on_rx_pkt() + * function. + */ + pj_status_t (*on_rx_indication)(pj_stun_session *sess, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_stun_msg *msg, + void *token, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + +} pj_stun_session_cb; + + +/** + * This structure describes incoming request message. + */ +struct pj_stun_rx_data +{ + /** + * The parsed request message. + */ + pj_stun_msg *msg; + + /** + * Credential information that is found and used to authenticate + * incoming request. Application may use this information when + * generating authentication for the outgoing response. + */ + pj_stun_req_cred_info info; +}; + + +/** + * This structure describe the outgoing STUN transmit data to carry the + * message to be sent. + */ +struct pj_stun_tx_data +{ + /** PJLIB list interface */ + PJ_DECL_LIST_MEMBER(struct pj_stun_tx_data); + + pj_pool_t *pool; /**< Pool. */ + pj_stun_session *sess; /**< The STUN session. */ + pj_stun_msg *msg; /**< The STUN message. */ + + void *token; /**< The token. */ + + pj_stun_client_tsx *client_tsx; /**< Client STUN transaction. */ + pj_bool_t retransmit; /**< Retransmit request? */ + pj_uint32_t msg_magic; /**< Message magic. */ + pj_uint8_t msg_key[12]; /**< Message/transaction key. */ + + pj_stun_req_cred_info auth_info; /**< Credential info */ + + void *pkt; /**< The STUN packet. */ + unsigned max_len; /**< Length of packet buffer. */ + pj_size_t pkt_size; /**< The actual length of STUN pkt. */ + + unsigned addr_len; /**< Length of destination address. */ + const pj_sockaddr_t *dst_addr; /**< Destination address. */ + + pj_timer_entry res_timer; /**< Response cache timer. */ +}; + + +/** + * These are the flags to control the message logging in the STUN session. + */ +typedef enum pj_stun_sess_msg_log_flag +{ + PJ_STUN_SESS_LOG_TX_REQ=1, /**< Log outgoing STUN requests. */ + PJ_STUN_SESS_LOG_TX_RES=2, /**< Log outgoing STUN responses. */ + PJ_STUN_SESS_LOG_TX_IND=4, /**< Log outgoing STUN indications. */ + + PJ_STUN_SESS_LOG_RX_REQ=8, /**< Log incoming STUN requests. */ + PJ_STUN_SESS_LOG_RX_RES=16, /**< Log incoming STUN responses */ + PJ_STUN_SESS_LOG_RX_IND=32 /**< Log incoming STUN indications */ +} pj_stun_sess_msg_log_flag; + + +/** + * Create a STUN session. + * + * @param cfg The STUN endpoint, to be used to register timers etc. + * @param name Optional name to be associated with this instance. The + * name will be used for example for logging purpose. + * @param cb Session callback. + * @param fingerprint Enable message fingerprint for outgoing messages. + * @param p_sess Pointer to receive STUN session instance. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_create(pj_stun_config *cfg, + const char *name, + const pj_stun_session_cb *cb, + pj_bool_t fingerprint, + pj_stun_session **p_sess); + +/** + * Destroy the STUN session and all objects created in the context of + * this session. + * + * @param sess The STUN session instance. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + * This function will return PJ_EPENDING if the operation + * cannot be performed immediately because callbacks are + * being called; in this case the session will be destroyed + * as soon as the last callback returns. + */ +PJ_DECL(pj_status_t) pj_stun_session_destroy(pj_stun_session *sess); + +/** + * Associated an arbitrary data with this STUN session. The user data may + * be retrieved later with pj_stun_session_get_user_data() function. + * + * @param sess The STUN session instance. + * @param user_data The user data. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_set_user_data(pj_stun_session *sess, + void *user_data); + +/** + * Retrieve the user data previously associated to this STUN session with + * pj_stun_session_set_user_data(). + * + * @param sess The STUN session instance. + * + * @return The user data associated with this STUN session. + */ +PJ_DECL(void*) pj_stun_session_get_user_data(pj_stun_session *sess); + +/** + * Change the lock object used by the STUN session. By default, the STUN + * session uses a mutex to protect its internal data. If application already + * protects access to STUN session with higher layer lock, it may disable + * the mutex protection in the STUN session by changing the STUN session + * lock to a NULL mutex. + * + * @param sess The STUN session instance. + * @param lock New lock instance to be used by the STUN session. + * @param auto_del Specify whether STUN session should destroy this + * lock instance when it's destroyed. + */ +PJ_DECL(pj_status_t) pj_stun_session_set_lock(pj_stun_session *sess, + pj_lock_t *lock, + pj_bool_t auto_del); + +/** + * Set SOFTWARE name to be included in all requests and responses. + * + * @param sess The STUN session instance. + * @param sw Software name string. If this argument is NULL or + * empty, the session will not include SOFTWARE attribute + * in STUN requests and responses. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_set_software_name(pj_stun_session *sess, + const pj_str_t *sw); + +/** + * Set credential to be used by this session. Once credential is set, all + * outgoing messages will include MESSAGE-INTEGRITY, and all incoming + * message will be authenticated against this credential. + * + * To disable authentication after it has been set, call this function + * again with NULL as the argument. + * + * @param sess The STUN session instance. + * @param auth_type Type of authentication. + * @param cred The credential to be used by this session. If NULL + * is specified, authentication will be disabled. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_set_credential(pj_stun_session *sess, + pj_stun_auth_type auth_type, + const pj_stun_auth_cred *cred); +/** + * Configure message logging. By default all flags are enabled. + * + * @param sess The STUN session instance. + * @param flags Bitmask combination of #pj_stun_sess_msg_log_flag + */ +PJ_DECL(void) pj_stun_session_set_log(pj_stun_session *sess, + unsigned flags); +/** + * Configure whether the STUN session should utilize FINGERPRINT in + * outgoing messages. + * + * @param sess The STUN session instance. + * @param use Boolean for the setting. + * + * @return The previous configured value of FINGERPRINT + * utilization of the sessoin. + */ +PJ_DECL(pj_bool_t) pj_stun_session_use_fingerprint(pj_stun_session *sess, + pj_bool_t use); + +/** + * Create a STUN request message. After the message has been successfully + * created, application can send the message by calling + * pj_stun_session_send_msg(). + * + * @param sess The STUN session instance. + * @param msg_type The STUN request message type, from pj_stun_method_e or + * from pj_stun_msg_type. + * @param magic STUN magic, use PJ_STUN_MAGIC. + * @param tsx_id Optional transaction ID. + * @param p_tdata Pointer to receive STUN transmit data instance containing + * the request. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, + int msg_type, + pj_uint32_t magic, + const pj_uint8_t tsx_id[12], + pj_stun_tx_data **p_tdata); + +/** + * Create a STUN Indication message. After the message has been successfully + * created, application can send the message by calling + * pj_stun_session_send_msg(). + * + * @param sess The STUN session instance. + * @param msg_type The STUN request message type, from pj_stun_method_e or + * from pj_stun_msg_type. This function will add the + * indication bit as necessary. + * @param p_tdata Pointer to receive STUN transmit data instance containing + * the message. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_create_ind(pj_stun_session *sess, + int msg_type, + pj_stun_tx_data **p_tdata); + +/** + * Create a STUN response message. After the message has been + * successfully created, application can send the message by calling + * pj_stun_session_send_msg(). Alternatively application may use + * pj_stun_session_respond() to create and send response in one function + * call. + * + * @param sess The STUN session instance. + * @param rdata The STUN request where the response is to be created. + * @param err_code Error code to be set in the response, if error response + * is to be created, according to pj_stun_status enumeration. + * This argument MUST be zero if successful response is + * to be created. + * @param err_msg Optional pointer for the error message string, when + * creating error response. If the value is NULL and the + * \a err_code is non-zero, then default error message will + * be used. + * @param p_tdata Pointer to receive the response message created. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_session_create_res(pj_stun_session *sess, + const pj_stun_rx_data *rdata, + unsigned err_code, + const pj_str_t *err_msg, + pj_stun_tx_data **p_tdata); + +/** + * Send STUN message to the specified destination. This function will encode + * the pj_stun_msg instance to a packet buffer, and add credential or + * fingerprint if necessary. If the message is a request, the session will + * also create and manage a STUN client transaction to be used to manage the + * retransmission of the request. After the message has been encoded and + * transaction is setup, the \a on_send_msg() callback of pj_stun_session_cb + * (which is registered when the STUN session is created) will be called + * to actually send the message to the wire. + * + * @param sess The STUN session instance. + * @param token Optional token which will be given back to application in + * \a on_send_msg() callback and \a on_request_complete() + * callback, if the message is a STUN request message. + * Internally this function will put the token in the + * \a token field of pj_stun_tx_data, hence it will + * overwrite any value that the application puts there. + * @param cache_res If the message is a response message for an incoming + * request, specify PJ_TRUE to instruct the STUN session + * to cache this response for subsequent incoming request + * retransmission. Otherwise this parameter will be ignored + * for non-response message. + * @param retransmit If the message is a request message, specify whether the + * request should be retransmitted. Normally application will + * specify TRUE if the underlying transport is UDP and FALSE + * if the underlying transport is TCP or TLS. + * @param dst_addr The destination socket address. + * @param addr_len Length of destination address. + * @param tdata The STUN transmit data containing the STUN message to + * be sent. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + * This function will return PJNATH_ESTUNDESTROYED if + * application has destroyed the session in + * \a on_send_msg() callback. + */ +PJ_DECL(pj_status_t) pj_stun_session_send_msg(pj_stun_session *sess, + void *token, + pj_bool_t cache_res, + pj_bool_t retransmit, + const pj_sockaddr_t *dst_addr, + unsigned addr_len, + pj_stun_tx_data *tdata); + +/** + * This is a utility function to create and send response for an incoming + * STUN request. Internally this function calls pj_stun_session_create_res() + * and pj_stun_session_send_msg(). It is provided here as a matter of + * convenience. + * + * @param sess The STUN session instance. + * @param rdata The STUN request message to be responded. + * @param code Error code to be set in the response, if error response + * is to be created, according to pj_stun_status enumeration. + * This argument MUST be zero if successful response is + * to be created. + * @param err_msg Optional pointer for the error message string, when + * creating error response. If the value is NULL and the + * \a err_code is non-zero, then default error message will + * be used. + * @param token Optional token which will be given back to application in + * \a on_send_msg() callback and \a on_request_complete() + * callback, if the message is a STUN request message. + * Internally this function will put the token in the + * \a token field of pj_stun_tx_data, hence it will + * overwrite any value that the application puts there. + * @param cache Specify whether session should cache this response for + * future request retransmission. If TRUE, subsequent request + * retransmission will be handled by the session and it + * will not call request callback. + * @param dst_addr Destination address of the response (or equal to the + * source address of the original request). + * @param addr_len Address length. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + * This function will return PJNATH_ESTUNDESTROYED if + * application has destroyed the session in + * \a on_send_msg() callback. + */ +PJ_DECL(pj_status_t) pj_stun_session_respond(pj_stun_session *sess, + const pj_stun_rx_data *rdata, + unsigned code, + const char *err_msg, + void *token, + pj_bool_t cache, + const pj_sockaddr_t *dst_addr, + unsigned addr_len); + +/** + * Cancel outgoing STUN transaction. This operation is only valid for outgoing + * STUN request, to cease retransmission of the request and destroy the + * STUN client transaction that is used to send the request. + * + * @param sess The STUN session instance. + * @param tdata The request message previously sent. + * @param notify Specify whether \a on_request_complete() callback should + * be called. + * @param status If \a on_request_complete() callback is to be called, + * specify the error status to be given when calling the + * callback. This error status MUST NOT be PJ_SUCCESS. + * + * @return PJ_SUCCESS if transaction is successfully cancelled. + * This function will return PJNATH_ESTUNDESTROYED if + * application has destroyed the session in + * \a on_request_complete() callback. + */ +PJ_DECL(pj_status_t) pj_stun_session_cancel_req(pj_stun_session *sess, + pj_stun_tx_data *tdata, + pj_bool_t notify, + pj_status_t status); + +/** + * Explicitly request retransmission of the request. Normally application + * doesn't need to do this, but this functionality is needed by ICE to + * speed up connectivity check completion. + * + * @param sess The STUN session instance. + * @param tdata The request message previously sent. + * + * @return PJ_SUCCESS on success, or the appropriate error. + * This function will return PJNATH_ESTUNDESTROYED if + * application has destroyed the session in \a on_send_msg() + * callback. + */ +PJ_DECL(pj_status_t) pj_stun_session_retransmit_req(pj_stun_session *sess, + pj_stun_tx_data *tdata); + + +/** + * Application must call this function to notify the STUN session about + * the arrival of STUN packet. The STUN packet MUST have been checked + * first with #pj_stun_msg_check() to verify that this is indeed a valid + * STUN packet. + * + * The STUN session will decode the packet into pj_stun_msg, and process + * the message accordingly. If the message is a response, it will search + * through the outstanding STUN client transactions for a matching + * transaction ID and hand over the response to the transaction. + * + * On successful message processing, application will be notified about + * the message via one of the pj_stun_session_cb callback. + * + * @param sess The STUN session instance. + * @param packet The packet containing STUN message. + * @param pkt_size Size of the packet. + * @param options Options, from #pj_stun_decode_options. + * @param parsed_len Optional pointer to receive the size of the parsed + * STUN message (useful if packet is received via a + * stream oriented protocol). + * @param token Optional token which will be given back to application + * in the \a on_rx_request(), \a on_rx_indication() and + * \a on_send_msg() callbacks. The token can be used to + * associate processing or incoming request or indication + * with some context. + * @param src_addr The source address of the packet, which will also + * be given back to application callbacks, along with + * source address length. + * @param src_addr_len Length of the source address. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + * This function will return PJNATH_ESTUNDESTROYED if + * application has destroyed the session in one of the + * callback. + */ +PJ_DECL(pj_status_t) pj_stun_session_on_rx_pkt(pj_stun_session *sess, + const void *packet, + pj_size_t pkt_size, + unsigned options, + void *token, + pj_size_t *parsed_len, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + +/** + * Destroy the transmit data. Call this function only when tdata has been + * created but application doesn't want to send the message (perhaps + * because of other error). + * + * @param sess The STUN session. + * @param tdata The transmit data. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(void) pj_stun_msg_destroy_tdata(pj_stun_session *sess, + pj_stun_tx_data *tdata); + + +/** + * @} + */ + + +PJ_END_DECL + +#endif /* __PJNATH_STUN_SESSION_H__ */ + diff --git a/pjnath/include/pjnath/stun_sock.h b/pjnath/include/pjnath/stun_sock.h new file mode 100644 index 0000000..decba9a --- /dev/null +++ b/pjnath/include/pjnath/stun_sock.h @@ -0,0 +1,446 @@ +/* $Id: stun_sock.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_STUN_SOCK_H__ +#define __PJNATH_STUN_SOCK_H__ + +/** + * @file stun_sock.h + * @brief STUN aware socket transport + */ +#include <pjnath/stun_config.h> +#include <pjlib-util/resolver.h> +#include <pj/ioqueue.h> +#include <pj/sock.h> +#include <pj/sock_qos.h> + + +PJ_BEGIN_DECL + + +/** + * @addtogroup PJNATH_STUN_SOCK + * @{ + * + * The STUN transport provides asynchronous UDP like socket transport + * with the additional STUN capability. It has the following features: + * + * - API to send and receive UDP packets + * + * - multiplex STUN and non-STUN incoming packets and distinguish between + * STUN responses that belong to internal requests with application data + * (the application data may be STUN packets as well) + * + * - DNS SRV resolution to the STUN server (if wanted), along with fallback + * to DNS A resolution if SRV record is not found. + * + * - STUN keep-alive maintenance, and handle changes to the mapped address + * (when the NAT binding changes) + * + */ + +/** + * Opaque type to represent a STUN transport. + */ +typedef struct pj_stun_sock pj_stun_sock; + +/** + * Types of operation being reported in \a on_status() callback of + * pj_stun_sock_cb. Application may retrieve the string representation + * of these constants with pj_stun_sock_op_name(). + */ +typedef enum pj_stun_sock_op +{ + /** + * Asynchronous DNS resolution. + */ + PJ_STUN_SOCK_DNS_OP = 1, + + /** + * Initial STUN Binding request. + */ + PJ_STUN_SOCK_BINDING_OP, + + /** + * Subsequent STUN Binding request for keeping the binding + * alive. + */ + PJ_STUN_SOCK_KEEP_ALIVE_OP, + + /** + * IP address change notification from the keep-alive operation. + */ + PJ_STUN_SOCK_MAPPED_ADDR_CHANGE + + +} pj_stun_sock_op; + + +/** + * This structure contains callbacks that will be called by the STUN + * transport to notify application about various events. + */ +typedef struct pj_stun_sock_cb +{ + /** + * Notification when incoming packet has been received. + * + * @param stun_sock The STUN transport. + * @param data The packet. + * @param data_len Length of the packet. + * @param src_addr The source address of the packet. + * @param addr_len The length of the source address. + * + * @return Application should normally return PJ_TRUE to let + * the STUN transport continue its operation. However + * it must return PJ_FALSE if it has destroyed the + * STUN transport in this callback. + */ + pj_bool_t (*on_rx_data)(pj_stun_sock *stun_sock, + void *pkt, + unsigned pkt_len, + const pj_sockaddr_t *src_addr, + unsigned addr_len); + + /** + * Notifification when asynchronous send operation has completed. + * + * @param stun_sock The STUN transport. + * @param send_key The send operation key that was given in + * #pj_stun_sock_sendto(). + * @param sent If value is positive non-zero it indicates the + * number of data sent. When the value is negative, + * it contains the error code which can be retrieved + * by negating the value (i.e. status=-sent). + * + * @return Application should normally return PJ_TRUE to let + * the STUN transport continue its operation. However + * it must return PJ_FALSE if it has destroyed the + * STUN transport in this callback. + */ + pj_bool_t (*on_data_sent)(pj_stun_sock *stun_sock, + pj_ioqueue_op_key_t *send_key, + pj_ssize_t sent); + + /** + * Notification when the status of the STUN transport has changed. This + * callback may be called for the following conditions: + * - the first time the publicly mapped address has been resolved from + * the STUN server, this callback will be called with \a op argument + * set to PJ_STUN_SOCK_BINDING_OP \a status argument set to + * PJ_SUCCESS. + * - anytime when the transport has detected that the publicly mapped + * address has changed, this callback will be called with \a op + * argument set to PJ_STUN_SOCK_KEEP_ALIVE_OP and \a status + * argument set to PJ_SUCCESS. On this case and the case above, + * application will get the resolved public address in the + * #pj_stun_sock_info structure. + * - for any terminal error (such as STUN time-out, DNS resolution + * failure, or keep-alive failure), this callback will be called + * with the \a status argument set to non-PJ_SUCCESS. + * + * @param stun_sock The STUN transport. + * @param op The operation that triggers the callback. + * @param status The status. + * + * @return Must return PJ_FALSE if it has destroyed the + * STUN transport in this callback. Application should + * normally destroy the socket and return PJ_FALSE + * upon encountering terminal error, otherwise it + * should return PJ_TRUE to let the STUN socket operation + * continues. + */ + pj_bool_t (*on_status)(pj_stun_sock *stun_sock, + pj_stun_sock_op op, + pj_status_t status); + +} pj_stun_sock_cb; + + +/** + * This structure contains information about the STUN transport. Application + * may query this information by calling #pj_stun_sock_get_info(). + */ +typedef struct pj_stun_sock_info +{ + /** + * The bound address of the socket. + */ + pj_sockaddr bound_addr; + + /** + * IP address of the STUN server. + */ + pj_sockaddr srv_addr; + + /** + * The publicly mapped address. It may contain zero address when the + * mapped address has not been resolved. Application may query whether + * this field contains valid address with pj_sockaddr_has_addr(). + */ + pj_sockaddr mapped_addr; + + /** + * Number of interface address aliases. The interface address aliases + * are list of all interface addresses in this host. + */ + unsigned alias_cnt; + + /** + * Array of interface address aliases. + */ + pj_sockaddr aliases[PJ_ICE_ST_MAX_CAND]; + +} pj_stun_sock_info; + + +/** + * This describe the settings to be given to the STUN transport during its + * creation. Application should initialize this structure by calling + * #pj_stun_sock_cfg_default(). + */ +typedef struct pj_stun_sock_cfg +{ + /** + * Packet buffer size. Default value is PJ_STUN_SOCK_PKT_LEN. + */ + unsigned max_pkt_size; + + /** + * Specify the number of simultaneous asynchronous read operations to + * be invoked to the ioqueue. Having more than one read operations will + * increase performance on multiprocessor systems since the application + * will be able to process more than one incoming packets simultaneously. + * Default value is 1. + */ + unsigned async_cnt; + + /** + * Specify the interface where the socket should be bound to. If the + * address is zero, socket will be bound to INADDR_ANY. If the address + * is non-zero, socket will be bound to this address only, and the + * transport will have only one address alias (the \a alias_cnt field + * in #pj_stun_sock_info structure. + */ + pj_sockaddr bound_addr; + + /** + * Specify the STUN keep-alive duration, in seconds. The STUN transport + * does keep-alive by sending STUN Binding request to the STUN server. + * If this value is zero, the PJ_STUN_KEEP_ALIVE_SEC value will be used. + * If the value is negative, it will disable STUN keep-alive. + */ + int ka_interval; + + /** + * QoS traffic type to be set on this transport. When application wants + * to apply QoS tagging to the transport, it's preferable to set this + * field rather than \a qos_param fields since this is more portable. + * + * Default value is PJ_QOS_TYPE_BEST_EFFORT. + */ + pj_qos_type qos_type; + + /** + * Set the low level QoS parameters to the transport. This is a lower + * level operation than setting the \a qos_type field and may not be + * supported on all platforms. + * + * By default all settings in this structure are disabled. + */ + pj_qos_params qos_params; + + /** + * Specify if STUN socket should ignore any errors when setting the QoS + * traffic type/parameters. + * + * Default: PJ_TRUE + */ + pj_bool_t qos_ignore_error; + +} pj_stun_sock_cfg; + + + +/** + * Retrieve the name representing the specified operation. + */ +PJ_DECL(const char*) pj_stun_sock_op_name(pj_stun_sock_op op); + + +/** + * Initialize the STUN transport setting with its default values. + * + * @param cfg The STUN transport config. + */ +PJ_DECL(void) pj_stun_sock_cfg_default(pj_stun_sock_cfg *cfg); + + +/** + * Create the STUN transport using the specified configuration. Once + * the STUN transport has been create, application should call + * #pj_stun_sock_start() to start the transport. + * + * @param stun_cfg The STUN configuration which contains among other + * things the ioqueue and timer heap instance for + * the operation of this transport. + * @param af Address family of socket. Currently pj_AF_INET() + * and pj_AF_INET6() are supported. + * @param name Optional name to be given to this transport to + * assist debugging. + * @param cb Callback to receive events/data from the transport. + * @param cfg Optional transport settings. + * @param user_data Arbitrary application data to be associated with + * this transport. + * @param p_sock Pointer to receive the created transport instance. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_stun_sock_create(pj_stun_config *stun_cfg, + const char *name, + int af, + const pj_stun_sock_cb *cb, + const pj_stun_sock_cfg *cfg, + void *user_data, + pj_stun_sock **p_sock); + + +/** + * Start the STUN transport. This will start the DNS SRV resolution for + * the STUN server (if desired), and once the server is resolved, STUN + * Binding request will be sent to resolve the publicly mapped address. + * Once the initial STUN Binding response is received, the keep-alive + * timer will be started. + * + * @param stun_sock The STUN transport instance. + * @param domain The domain, hostname, or IP address of the TURN + * server. When this parameter contains domain name, + * the \a resolver parameter must be set to activate + * DNS SRV resolution. + * @param default_port The default STUN port number to use when DNS SRV + * resolution is not used. If DNS SRV resolution is + * used, the server port number will be set from the + * DNS SRV records. The recommended value for this + * parameter is PJ_STUN_PORT. + * @param resolver If this parameter is not NULL, then the \a domain + * parameter will be first resolved with DNS SRV and + * then fallback to using DNS A/AAAA resolution when + * DNS SRV resolution fails. If this parameter is + * NULL, the \a domain parameter will be resolved as + * hostname. + * + * @return PJ_SUCCESS if the operation has been successfully + * queued, or the appropriate error code on failure. + * When this function returns PJ_SUCCESS, the final + * result of the allocation process will be notified + * to application in \a on_state() callback. + */ +PJ_DECL(pj_status_t) pj_stun_sock_start(pj_stun_sock *stun_sock, + const pj_str_t *domain, + pj_uint16_t default_port, + pj_dns_resolver *resolver); + +/** + * Destroy the STUN transport. + * + * @param sock The STUN transport socket. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_stun_sock_destroy(pj_stun_sock *sock); + + +/** + * Associate a user data with this STUN transport. The user data may then + * be retrieved later with #pj_stun_sock_get_user_data(). + * + * @param stun_sock The STUN transport instance. + * @param user_data Arbitrary data. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_stun_sock_set_user_data(pj_stun_sock *stun_sock, + void *user_data); + +/** + * Retrieve the previously assigned user data associated with this STUN + * transport. + * + * @param stun_sock The STUN transport instance. + * + * @return The user/application data. + */ +PJ_DECL(void*) pj_stun_sock_get_user_data(pj_stun_sock *stun_sock); + + +/** + * Get the STUN transport info. The transport info contains, among other + * things, the allocated relay address. + * + * @param stun_sock The STUN transport instance. + * @param info Pointer to be filled with STUN transport info. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_stun_sock_get_info(pj_stun_sock *stun_sock, + pj_stun_sock_info *info); + + +/** + * Send a data to the specified address. This function may complete + * asynchronously and in this case \a on_data_sent() will be called. + * + * @param stun_sock The STUN transport instance. + * @param send_key Optional send key for sending the packet down to + * the ioqueue. This value will be given back to + * \a on_data_sent() callback + * @param pkt The data/packet to be sent to peer. + * @param pkt_len Length of the data. + * @param flag pj_ioqueue_sendto() flag. + * @param dst_addr The remote address. + * @param addr_len Length of the address. + * + * @return PJ_SUCCESS if data has been sent immediately, or + * PJ_EPENDING if data cannot be sent immediately. In + * this case the \a on_data_sent() callback will be + * called when data is actually sent. Any other return + * value indicates error condition. + */ +PJ_DECL(pj_status_t) pj_stun_sock_sendto(pj_stun_sock *stun_sock, + pj_ioqueue_op_key_t *send_key, + const void *pkt, + unsigned pkt_len, + unsigned flag, + const pj_sockaddr_t *dst_addr, + unsigned addr_len); + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJNATH_STUN_SOCK_H__ */ + diff --git a/pjnath/include/pjnath/stun_transaction.h b/pjnath/include/pjnath/stun_transaction.h new file mode 100644 index 0000000..526186f --- /dev/null +++ b/pjnath/include/pjnath/stun_transaction.h @@ -0,0 +1,276 @@ +/* $Id: stun_transaction.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_STUN_TRANSACTION_H__ +#define __PJNATH_STUN_TRANSACTION_H__ + +/** + * @file stun_transaction.h + * @brief STUN transaction + */ + +#include <pjnath/stun_msg.h> +#include <pjnath/stun_config.h> + + +PJ_BEGIN_DECL + + +/* **************************************************************************/ +/** + * @defgroup PJNATH_STUN_TRANSACTION STUN Client Transaction + * @brief STUN client transaction + * @ingroup PJNATH_STUN_BASE + * @{ + * + The @ref PJNATH_STUN_TRANSACTION is used to manage outgoing STUN request, + for example to retransmit the request and to notify application about the + completion of the request. + + The @ref PJNATH_STUN_TRANSACTION does not use any networking operations, + but instead application must supply the transaction with a callback to + be used by the transaction to send outgoing requests. This way the STUN + transaction is made more generic and can work with different types of + networking codes in application. + + + */ + +/** + * Opaque declaration of STUN client transaction. + */ +typedef struct pj_stun_client_tsx pj_stun_client_tsx; + +/** + * STUN client transaction callback. + */ +typedef struct pj_stun_tsx_cb +{ + /** + * This callback is called when the STUN transaction completed. + * + * @param tsx The STUN transaction. + * @param status Status of the transaction. Status PJ_SUCCESS + * means that the request has received a successful + * response. + * @param response The STUN response, which value may be NULL if + * \a status is not PJ_SUCCESS. + * @param src_addr The source address of the response, if response + * is not NULL. + * @param src_addr_len The length of the source address. + */ + void (*on_complete)(pj_stun_client_tsx *tsx, + pj_status_t status, + const pj_stun_msg *response, + const pj_sockaddr_t *src_addr, + unsigned src_addr_len); + + /** + * This callback is called by the STUN transaction when it wants to send + * outgoing message. + * + * @param tsx The STUN transaction instance. + * @param stun_pkt The STUN packet to be sent. + * @param pkt_size Size of the STUN packet. + * + * @return If return value of the callback is not PJ_SUCCESS, + * the transaction will fail. Application MUST return + * PJNATH_ESTUNDESTROYED if it has destroyed the + * transaction in this callback. + */ + pj_status_t (*on_send_msg)(pj_stun_client_tsx *tsx, + const void *stun_pkt, + pj_size_t pkt_size); + + /** + * This callback is called after the timer that was scheduled by + * #pj_stun_client_tsx_schedule_destroy() has elapsed. Application + * should call #pj_stun_client_tsx_destroy() upon receiving this + * callback. + * + * This callback is optional if application will not call + * #pj_stun_client_tsx_schedule_destroy(). + * + * @param tsx The STUN transaction instance. + */ + void (*on_destroy)(pj_stun_client_tsx *tsx); + +} pj_stun_tsx_cb; + + + +/** + * Create an instance of STUN client transaction. The STUN client + * transaction is used to transmit outgoing STUN request and to + * ensure the reliability of the request by periodically retransmitting + * the request, if necessary. + * + * @param cfg The STUN endpoint, which will be used to retrieve + * various settings for the transaction. + * @param pool Pool to be used to allocate memory from. + * @param cb Callback structure, to be used by the transaction + * to send message and to notify the application about + * the completion of the transaction. + * @param p_tsx Pointer to receive the transaction instance. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_client_tsx_create( pj_stun_config *cfg, + pj_pool_t *pool, + const pj_stun_tsx_cb *cb, + pj_stun_client_tsx **p_tsx); + +/** + * Schedule timer to destroy the transaction after the transaction is + * complete. Application normally calls this function in the on_complete() + * callback. When this timer elapsed, the on_destroy() callback will be + * called. + * + * This is convenient to let the STUN transaction absorbs any response + * for the previous request retransmissions. If application doesn't want + * this, it can destroy the transaction immediately by calling + * #pj_stun_client_tsx_destroy(). + * + * @param tsx The STUN transaction. + * @param delay The delay interval before on_destroy() callback + * is called. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) +pj_stun_client_tsx_schedule_destroy(pj_stun_client_tsx *tsx, + const pj_time_val *delay); + + +/** + * Destroy a STUN client transaction immediately. This function can be + * called at any time to stop the transaction and destroy it. + * + * @param tsx The STUN transaction. + * + * @return PJ_SUCCESS on success or PJ_EINVAL if the parameter + * is NULL. + */ +PJ_DECL(pj_status_t) pj_stun_client_tsx_destroy(pj_stun_client_tsx *tsx); + + +/** + * Check if transaction has completed. + * + * @param tsx The STUN transaction. + * + * @return Non-zero if transaction has completed. + */ +PJ_DECL(pj_bool_t) pj_stun_client_tsx_is_complete(pj_stun_client_tsx *tsx); + + +/** + * Associate an arbitrary data with the STUN transaction. This data + * can be then retrieved later from the transaction, by using + * pj_stun_client_tsx_get_data() function. + * + * @param tsx The STUN client transaction. + * @param data Application data to be associated with the + * STUN transaction. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pj_stun_client_tsx_set_data(pj_stun_client_tsx *tsx, + void *data); + + +/** + * Get the user data that was previously associated with the STUN + * transaction. + * + * @param tsx The STUN client transaction. + * + * @return The user data. + */ +PJ_DECL(void*) pj_stun_client_tsx_get_data(pj_stun_client_tsx *tsx); + + +/** + * Start the STUN client transaction by sending STUN request using + * this transaction. If reliable transport such as TCP or TLS is used, + * the retransmit flag should be set to PJ_FALSE because reliablity + * will be assured by the transport layer. + * + * @param tsx The STUN client transaction. + * @param retransmit Should this message be retransmitted by the + * STUN transaction. + * @param pkt The STUN packet to send. + * @param pkt_len Length of STUN packet. + * + * @return PJ_SUCCESS on success, or PJNATH_ESTUNDESTROYED + * when the user has destroyed the transaction in + * \a on_send_msg() callback, or any other error code + * as returned by \a on_send_msg() callback. + */ +PJ_DECL(pj_status_t) pj_stun_client_tsx_send_msg(pj_stun_client_tsx *tsx, + pj_bool_t retransmit, + void *pkt, + unsigned pkt_len); + +/** + * Request to retransmit the request. Normally application should not need + * to call this function since retransmission would be handled internally, + * but this functionality is needed by ICE. + * + * @param tsx The STUN client transaction instance. + * + * @return PJ_SUCCESS on success, or PJNATH_ESTUNDESTROYED + * when the user has destroyed the transaction in + * \a on_send_msg() callback, or any other error code + * as returned by \a on_send_msg() callback. + */ +PJ_DECL(pj_status_t) pj_stun_client_tsx_retransmit(pj_stun_client_tsx *tsx); + + +/** + * Notify the STUN transaction about the arrival of STUN response. + * If the STUN response contains a final error (300 and greater), the + * transaction will be terminated and callback will be called. If the + * STUN response contains response code 100-299, retransmission + * will cease, but application must still call this function again + * with a final response later to allow the transaction to complete. + * + * @param tsx The STUN client transaction instance. + * @param msg The incoming STUN message. + * @param src_addr The source address of the packet. + * @param src_addr_len The length of the source address. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_stun_client_tsx_on_rx_msg(pj_stun_client_tsx *tsx, + const pj_stun_msg *msg, + const pj_sockaddr_t*src_addr, + unsigned src_addr_len); + + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJNATH_STUN_TRANSACTION_H__ */ + diff --git a/pjnath/include/pjnath/turn_session.h b/pjnath/include/pjnath/turn_session.h new file mode 100644 index 0000000..0eeb6e3 --- /dev/null +++ b/pjnath/include/pjnath/turn_session.h @@ -0,0 +1,730 @@ +/* $Id: turn_session.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_TURN_SESSION_H__ +#define __PJNATH_TURN_SESSION_H__ + +/** + * @file turn_session.h + * @brief Transport independent TURN client session. + */ +#include <pjnath/stun_session.h> +#include <pjlib-util/resolver.h> + + +PJ_BEGIN_DECL + + +/* **************************************************************************/ +/** +@addtogroup PJNATH_TURN_SESSION +@{ + +The \ref PJNATH_TURN_SESSION is a transport-independent object to +manage a client TURN session. It contains the core logic for manage +the TURN client session as listed in \ref turn_op_sec, but +in transport-independent manner (i.e. it doesn't have a socket), so +that developer can integrate TURN client functionality into existing +framework that already has its own means to send and receive data, +or to support new transport types to TURN, such as TLS. + + +\section turn_sess_using_sec Using the TURN session + +These steps describes how to use the TURN session: + + - <b>Creating the session</b>:\n + use #pj_turn_session_create() to create the session. + + - <b>Configuring credential</b>:\n + all TURN operations requires the use of authentication (it uses STUN + long term autentication method). Use #pj_turn_session_set_credential() + to configure the TURN credential to be used by the session. + + - <b>Configuring server</b>:\n + application must call #pj_turn_session_set_server() before it can send + Allocate request (with pj_turn_session_alloc()). This function will + resolve the TURN server using DNS SRV resolution if the \a resolver + is set. The server resolution process will complete asynchronously, + and application will be notified in \a on_state() callback of the + #pj_turn_session_cb structurewith the session state set to + PJ_TURN_STATE_RESOLVED. + + - <b>Creating allocation</b>:\n + create one "relay port" (or called <b>relayed-transport-address</b> + in TURN terminology) in the TURN server by using #pj_turn_session_alloc(). + This will send Allocate request to the server. This function will complete + immediately, and application will be notified about the allocation + result in the \a on_state() callback of the #pj_turn_session_cb structure. + + - <b>Getting the allocation result</b>:\n + if allocation is successful, the session state will progress to + \a PJ_TURN_STATE_READY, otherwise the state will be + \a PJ_TURN_STATE_DEALLOCATED or higher. Session state progression is + reported in the \a on_state() callback of the #pj_turn_session_cb + structure. On successful allocation, application may retrieve the + allocation info by calling #pj_turn_session_get_info(). + + - <b>Sending data through the relay</b>.\n + Once allocation has been created, client may send data to any remote + endpoints (called peers in TURN terminology) via the "relay port". It does + so by calling #pj_turn_session_sendto(), giving the peer address + in the function argument. But note that at this point peers are not allowed + to send data towards the client (via the "relay port") before permission is + installed for that peer. + + - <b>Creating permissions</b>.\n + Permission needs to be created in the TURN server so that a peer can send + data to the client via the relay port (a peer in this case is identified by + its IP address). Without this, when the TURN server receives data from the + peer in the "relay port", it will drop this data. Create the permission by + calling #pj_turn_session_set_perm(), specifying the peer IP address in the + argument (the port part of the address is ignored). More than one IP + addresses may be specified. + + - <b>Receiving data from peers</b>.\n + Once permission has been installed for the peer, any data received by the + TURN server (from that peer) in the "relay port" will be relayed back to + client by the server, and application will be notified via \a on_rx_data + callback of the #pj_turn_session_cb. + + - <b>Using ChannelData</b>.\n + TURN provides optimized framing to the data by using ChannelData + packetization. The client activates this format for the specified peer by + calling #pj_turn_session_bind_channel(). Data sent or received to/for + this peer will then use ChannelData format instead of Send or Data + Indications. + + - <b>Refreshing the allocation, permissions, and channel bindings</b>.\n + Allocations, permissions, and channel bindings will be refreshed by the + session automatically when they about to expire. + + - <b>Destroying the allocation</b>.\n + Once the "relay port" is no longer needed, client destroys the allocation + by calling #pj_turn_session_shutdown(). This function will return + immediately, and application will be notified about the deallocation + result in the \a on_state() callback of the #pj_turn_session_cb structure. + Once the state has reached PJ_TURN_STATE_DESTROYING, application must + assume that the session will be destroyed shortly after. + + */ + +/** + * Opaque declaration for TURN client session. + */ +typedef struct pj_turn_session pj_turn_session; + + +/** + * TURN transport types, which will be used both to specify the connection + * type for reaching TURN server and the type of allocation transport to be + * requested to server (the REQUESTED-TRANSPORT attribute). + */ +typedef enum pj_turn_tp_type +{ + /** + * UDP transport, which value corresponds to IANA protocol number. + */ + PJ_TURN_TP_UDP = 17, + + /** + * TCP transport, which value corresponds to IANA protocol number. + */ + PJ_TURN_TP_TCP = 6, + + /** + * TLS transport. The TLS transport will only be used as the connection + * type to reach the server and never as the allocation transport type. + */ + PJ_TURN_TP_TLS = 255 + +} pj_turn_tp_type; + + +/** TURN session state */ +typedef enum pj_turn_state_t +{ + /** + * TURN session has just been created. + */ + PJ_TURN_STATE_NULL, + + /** + * TURN server has been configured and now is being resolved via + * DNS SRV resolution. + */ + PJ_TURN_STATE_RESOLVING, + + /** + * TURN server has been resolved. If there is pending allocation to + * be done, it will be invoked immediately. + */ + PJ_TURN_STATE_RESOLVED, + + /** + * TURN session has issued ALLOCATE request and is waiting for response + * from the TURN server. + */ + PJ_TURN_STATE_ALLOCATING, + + /** + * TURN session has successfully allocated relay resoruce and now is + * ready to be used. + */ + PJ_TURN_STATE_READY, + + /** + * TURN session has issued deallocate request and is waiting for a + * response from the TURN server. + */ + PJ_TURN_STATE_DEALLOCATING, + + /** + * Deallocate response has been received. Normally the session will + * proceed to DESTROYING state immediately. + */ + PJ_TURN_STATE_DEALLOCATED, + + /** + * TURN session is being destroyed. + */ + PJ_TURN_STATE_DESTROYING + +} pj_turn_state_t; + + +#pragma pack(1) + +/** + * This structure ChannelData header. All the fields are in network byte + * order when it's on the wire. + */ +typedef struct pj_turn_channel_data +{ + pj_uint16_t ch_number; /**< Channel number. */ + pj_uint16_t length; /**< Payload length. */ +} pj_turn_channel_data; + + +#pragma pack() + + +/** + * Callback to receive events from TURN session. + */ +typedef struct pj_turn_session_cb +{ + /** + * This callback will be called by the TURN session whenever it + * needs to send outgoing message. Since the TURN session doesn't + * have a socket on its own, this callback must be implemented. + * + * @param sess The TURN session. + * @param pkt The packet/data to be sent. + * @param pkt_len Length of the packet/data. + * @param dst_addr Destination address of the packet. + * @param addr_len Length of the destination address. + * + * @return The callback should return the status of the + * send operation. + */ + pj_status_t (*on_send_pkt)(pj_turn_session *sess, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_sockaddr_t *dst_addr, + unsigned addr_len); + + /** + * Notification when peer address has been bound successfully to + * a channel number. + * + * This callback is optional since the nature of this callback is + * for information only. + * + * @param sess The TURN session. + * @param peer_addr The peer address. + * @param addr_len Length of the peer address. + * @param ch_num The channel number associated with this peer address. + */ + void (*on_channel_bound)(pj_turn_session *sess, + const pj_sockaddr_t *peer_addr, + unsigned addr_len, + unsigned ch_num); + + /** + * Notification when incoming data has been received, either through + * Data indication or ChannelData message from the TURN server. + * + * @param sess The TURN session. + * @param pkt The data/payload of the Data Indication or ChannelData + * packet. + * @param pkt_len Length of the data/payload. + * @param peer_addr Peer address where this payload was received by + * the TURN server. + * @param addr_len Length of the peer address. + */ + void (*on_rx_data)(pj_turn_session *sess, + void *pkt, + unsigned pkt_len, + const pj_sockaddr_t *peer_addr, + unsigned addr_len); + + /** + * Notification when TURN session state has changed. Application should + * implement this callback at least to know that the TURN session is + * going to be destroyed. + * + * @param sess The TURN session. + * @param old_state The previous state of the session. + * @param new_state The current state of the session. + */ + void (*on_state)(pj_turn_session *sess, + pj_turn_state_t old_state, + pj_turn_state_t new_state); + +} pj_turn_session_cb; + + +/** + * Allocation parameter, which can be given when application calls + * pj_turn_session_alloc() to allocate relay address in the TURN server. + * Application should call pj_turn_alloc_param_default() to initialize + * this structure with the default values. + */ +typedef struct pj_turn_alloc_param +{ + /** + * The requested BANDWIDTH. Default is zero to not request any + * specific bandwidth. Note that this attribute has been deprecated + * after TURN-08 draft, hence application should only use this + * attribute when talking to TURN-07 or older version. + */ + int bandwidth; + + /** + * The requested LIFETIME. Default is zero to not request any + * explicit allocation lifetime. + */ + int lifetime; + + /** + * If set to non-zero, the TURN session will periodically send blank + * Send Indication every PJ_TURN_KEEP_ALIVE_SEC to refresh local + * NAT bindings. Default is zero. + */ + int ka_interval; + +} pj_turn_alloc_param; + + +/** + * This structure describes TURN session info. + */ +typedef struct pj_turn_session_info +{ + /** + * Session state. + */ + pj_turn_state_t state; + + /** + * Last error (if session was terminated because of error) + */ + pj_status_t last_status; + + /** + * Type of connection to the TURN server. + */ + pj_turn_tp_type conn_type; + + /** + * The selected TURN server address. + */ + pj_sockaddr server; + + /** + * Mapped address, as reported by the TURN server. + */ + pj_sockaddr mapped_addr; + + /** + * The relay address + */ + pj_sockaddr relay_addr; + + /** + * Current seconds before allocation expires. + */ + int lifetime; + +} pj_turn_session_info; + + +/** + * Initialize pj_turn_alloc_param with the default values. + * + * @param prm The TURN allocation parameter to be initialized. + */ +PJ_DECL(void) pj_turn_alloc_param_default(pj_turn_alloc_param *prm); + + +/** + * Duplicate pj_turn_alloc_param. + * + * @param pool Pool to allocate memory (currently not used) + * @param dst Destination parameter. + * @param src Source parameter. + */ +PJ_DECL(void) pj_turn_alloc_param_copy(pj_pool_t *pool, + pj_turn_alloc_param *dst, + const pj_turn_alloc_param *src); + +/** + * Get string representation for the given TURN state. + * + * @param state The TURN session state. + * + * @return The state name as NULL terminated string. + */ +PJ_DECL(const char*) pj_turn_state_name(pj_turn_state_t state); + + +/** + * Create a TURN session instance with the specified address family and + * connection type. Once TURN session instance is created, application + * must call pj_turn_session_alloc() to allocate a relay address in the TURN + * server. + * + * @param cfg The STUN configuration which contains among other + * things the ioqueue and timer heap instance for + * the operation of this session. + * @param name Optional name to identify this session in the log. + * @param af Address family of the client connection. Currently + * pj_AF_INET() and pj_AF_INET6() are supported. + * @param conn_type Connection type to the TURN server. + * @param cb Callback to receive events from the TURN session. + * @param options Option flags, currently this value must be zero. + * @param user_data Arbitrary application data to be associated with + * this transport. + * @param p_sess Pointer to receive the created instance of the + * TURN session. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_session_create(const pj_stun_config *cfg, + const char *name, + int af, + pj_turn_tp_type conn_type, + const pj_turn_session_cb *cb, + unsigned options, + void *user_data, + pj_turn_session **p_sess); + +/** + * Shutdown TURN client session. This will gracefully deallocate and + * destroy the client session. + * + * @param sess The TURN client session. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_session_shutdown(pj_turn_session *sess); + + +/** + * Forcefully destroy the TURN session. This will destroy the session + * immediately. If there is an active allocation, the server will not + * be notified about the client destruction. + * + * @param sess The TURN client session. + * @param last_err Optional error code to be set to the session, + * which would be returned back in the \a info + * parameter of #pj_turn_session_get_info(). If + * this argument value is PJ_SUCCESS, the error + * code will not be set. If the session already + * has an error code set, this function will not + * overwrite that error code either. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_session_destroy(pj_turn_session *sess, + pj_status_t last_err); + + +/** + * Get the information about this TURN session and the allocation, if + * any. + * + * @param sess The TURN client session. + * @param info The structure to be initialized with the TURN + * session info. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_session_get_info(pj_turn_session *sess, + pj_turn_session_info *info); + +/** + * Associate a user data with this TURN session. The user data may then + * be retrieved later with pj_turn_session_get_user_data(). + * + * @param sess The TURN client session. + * @param user_data Arbitrary data. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_session_set_user_data(pj_turn_session *sess, + void *user_data); + +/** + * Retrieve the previously assigned user data associated with this TURN + * session. + * + * @param sess The TURN client session. + * + * @return The user/application data. + */ +PJ_DECL(void*) pj_turn_session_get_user_data(pj_turn_session *sess); + + +/** + * Configure message logging. By default all flags are enabled. + * + * @param sess The TURN client session. + * @param flags Bitmask combination of #pj_stun_sess_msg_log_flag + */ +PJ_DECL(void) pj_turn_session_set_log(pj_turn_session *sess, + unsigned flags); + + +/** + * Configure the SOFTWARE name to be sent in all STUN requests by the + * TURN session. + * + * @param sess The TURN client session. + * @param sw Software name string. If this argument is NULL or + * empty, the session will not include SOFTWARE attribute + * in STUN requests and responses. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_turn_session_set_software_name(pj_turn_session *sess, + const pj_str_t *sw); + + +/** + * Set the server or domain name of the server. Before the application + * can send Allocate request (with pj_turn_session_alloc()), it must first + * resolve the server address(es) using this function. This function will + * resolve the TURN server using DNS SRV resolution if the \a resolver + * is set. The server resolution process will complete asynchronously, + * and application will be notified in \a on_state() callback with the + * session state set to PJ_TURN_STATE_RESOLVED. + * + * Application may call with pj_turn_session_alloc() before the server + * resolution completes. In this case, the operation will be queued by + * the session, and it will be sent once the server resolution completes. + * + * @param sess The TURN client session. + * @param domain The domain, hostname, or IP address of the TURN + * server. When this parameter contains domain name, + * the \a resolver parameter must be set to activate + * DNS SRV resolution. + * @param default_port The default TURN port number to use when DNS SRV + * resolution is not used. If DNS SRV resolution is + * used, the server port number will be set from the + * DNS SRV records. + * @param resolver If this parameter is not NULL, then the \a domain + * parameter will be first resolved with DNS SRV and + * then fallback to using DNS A/AAAA resolution when + * DNS SRV resolution fails. If this parameter is + * NULL, the \a domain parameter will be resolved as + * hostname. + * + * @return PJ_SUCCESS if the operation has been successfully + * queued, or the appropriate error code on failure. + * When this function returns PJ_SUCCESS, the final + * result of the resolution process will be notified + * to application in \a on_state() callback. + */ +PJ_DECL(pj_status_t) pj_turn_session_set_server(pj_turn_session *sess, + const pj_str_t *domain, + int default_port, + pj_dns_resolver *resolver); + + +/** + * Set credential to be used to authenticate against TURN server. + * Application must call this function before sending Allocate request + * with pj_turn_session_alloc(). + * + * @param sess The TURN client session + * @param cred STUN credential to be used. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_session_set_credential(pj_turn_session *sess, + const pj_stun_auth_cred *cred); + + +/** + * Allocate a relay address/resource in the TURN server by sending TURN + * Allocate request. Application must first initiate the server resolution + * process with pj_turn_session_set_server() and set the credential to be + * used with pj_turn_session_set_credential() before calling this function. + * + * This function will complete asynchronously, and the application will be + * notified about the allocation result in \a on_state() callback. The + * TURN session state will move to PJ_TURN_STATE_READY if allocation is + * successful, and PJ_TURN_STATE_DEALLOCATING or greater state if allocation + * has failed. + * + * Once allocation has been successful, the TURN session will keep this + * allocation alive until the session is destroyed, by sending periodic + * allocation refresh to the TURN server. + * + * @param sess The TURN client session. + * @param param Optional TURN allocation parameter. + * + * @return PJ_SUCCESS if the operation has been successfully + * initiated or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_session_alloc(pj_turn_session *sess, + const pj_turn_alloc_param *param); + + +/** + * Create or renew permission in the TURN server for the specified peer IP + * addresses. Application must install permission for a particular (peer) + * IP address before it sends any data to that IP address, or otherwise + * the TURN server will drop the data. + * + * @param sess The TURN client session. + * @param addr_cnt Number of IP addresses. + * @param addr Array of peer IP addresses. Only the address family + * and IP address portion of the socket address matter. + * @param options Specify 1 to let the TURN client session automatically + * renew the permission later when they are about to + * expire. + * + * @return PJ_SUCCESS if the operation has been successfully + * issued, or the appropriate error code. Note that + * the operation itself will complete asynchronously. + */ +PJ_DECL(pj_status_t) pj_turn_session_set_perm(pj_turn_session *sess, + unsigned addr_cnt, + const pj_sockaddr addr[], + unsigned options); + + +/** + * Send a data to the specified peer address via the TURN relay. This + * function will encapsulate the data as STUN Send Indication or TURN + * ChannelData packet and send the message to the TURN server. The TURN + * server then will send the data to the peer. + * + * The allocation (pj_turn_session_alloc()) must have been successfully + * created before application can relay any data. + * + * Since TURN session is transport independent, this function will + * ultimately call \a on_send_pkt() callback to request the application + * to actually send the packet containing the data to the TURN server. + * + * @param sess The TURN client session. + * @param pkt The data/packet to be sent to peer. + * @param pkt_len Length of the data. + * @param peer_addr The remote peer address (the ultimate destination + * of the data, and not the TURN server address). + * @param addr_len Length of the address. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_session_sendto(pj_turn_session *sess, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_sockaddr_t *peer_addr, + unsigned addr_len); + +/** + * Optionally establish channel binding for the specified a peer address. + * This function will assign a unique channel number for the peer address + * and request channel binding to the TURN server for this address. When + * a channel has been bound to a peer, the TURN client and TURN server + * will exchange data using ChannelData encapsulation format, which has + * lower bandwidth overhead than Send Indication (the default format used + * when peer address is not bound to a channel). + * + * This function will complete asynchronously, and application will be + * notified about the result in \a on_channel_bound() callback. + * + * @param sess The TURN client session. + * @param peer The remote peer address. + * @param addr_len Length of the address. + * + * @return PJ_SUCCESS if the operation has been successfully + * initiated, or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_session_bind_channel(pj_turn_session *sess, + const pj_sockaddr_t *peer, + unsigned addr_len); + +/** + * Notify TURN client session upon receiving a packet from server. Since + * the TURN session is transport independent, it does not read packet from + * any sockets, and rather relies on application giving it packets that + * are received from the TURN server. The session then processes this packet + * and decides whether it is part of TURN protocol exchange or if it is a + * data to be reported back to user, which in this case it will call the + * \a on_rx_data() callback. + * + * @param sess The TURN client session. + * @param pkt The packet as received from the TURN server. This + * should contain either STUN encapsulated message or + * a ChannelData packet. + * @param pkt_len The length of the packet. + * @param parsed_len Optional argument to receive the number of parsed + * or processed data from the packet. + * + * @return The function may return non-PJ_SUCCESS if it receives + * non-STUN and non-ChannelData packet, or if the + * \a on_rx_data() returns non-PJ_SUCCESS; + */ +PJ_DECL(pj_status_t) pj_turn_session_on_rx_pkt(pj_turn_session *sess, + void *pkt, + pj_size_t pkt_len, + pj_size_t *parsed_len); + + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJNATH_TURN_SESSION_H__ */ + diff --git a/pjnath/include/pjnath/turn_sock.h b/pjnath/include/pjnath/turn_sock.h new file mode 100644 index 0000000..1a75a64 --- /dev/null +++ b/pjnath/include/pjnath/turn_sock.h @@ -0,0 +1,397 @@ +/* $Id: turn_sock.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_TURN_SOCK_H__ +#define __PJNATH_TURN_SOCK_H__ + +/** + * @file turn_sock.h + * @brief TURN relay using UDP client as transport protocol + */ +#include <pjnath/turn_session.h> +#include <pj/sock_qos.h> + + +PJ_BEGIN_DECL + + +/* **************************************************************************/ +/** +@addtogroup PJNATH_TURN_SOCK +@{ + +This is a ready to use object for relaying application data via a TURN server, +by managing all the operations in \ref turn_op_sec. + +\section turnsock_using_sec Using TURN transport + +This object provides a thin wrapper to the \ref PJNATH_TURN_SESSION, hence the +API is very much the same (apart from the obvious difference in the names). +Please see \ref PJNATH_TURN_SESSION for the documentation on how to use the +session. + +\section turnsock_samples_sec Samples + +The \ref turn_client_sample is a sample application to use the +\ref PJNATH_TURN_SOCK. + +Also see <b>\ref samples_page</b> for other samples. + + */ + + +/** + * Opaque declaration for TURN client. + */ +typedef struct pj_turn_sock pj_turn_sock; + +/** + * This structure contains callbacks that will be called by the TURN + * transport. + */ +typedef struct pj_turn_sock_cb +{ + /** + * Notification when incoming data has been received from the remote + * peer via the TURN server. The data reported in this callback will + * be the exact data as sent by the peer (e.g. the TURN encapsulation + * such as Data Indication or ChannelData will be removed before this + * function is called). + * + * @param turn_sock The TURN client transport. + * @param data The data as received from the peer. + * @param data_len Length of the data. + * @param peer_addr The peer address. + * @param addr_len The length of the peer address. + */ + void (*on_rx_data)(pj_turn_sock *turn_sock, + void *pkt, + unsigned pkt_len, + const pj_sockaddr_t *peer_addr, + unsigned addr_len); + + /** + * Notification when TURN session state has changed. Application should + * implement this callback to monitor the progress of the TURN session. + * + * @param turn_sock The TURN client transport. + * @param old_state Previous state. + * @param new_state Current state. + */ + void (*on_state)(pj_turn_sock *turn_sock, + pj_turn_state_t old_state, + pj_turn_state_t new_state); + +} pj_turn_sock_cb; + + +/** + * This structure describes options that can be specified when creating + * the TURN socket. Application should call #pj_turn_sock_cfg_default() + * to initialize this structure with its default values before using it. + */ +typedef struct pj_turn_sock_cfg +{ + /** + * QoS traffic type to be set on this transport. When application wants + * to apply QoS tagging to the transport, it's preferable to set this + * field rather than \a qos_param fields since this is more portable. + * + * Default value is PJ_QOS_TYPE_BEST_EFFORT. + */ + pj_qos_type qos_type; + + /** + * Set the low level QoS parameters to the transport. This is a lower + * level operation than setting the \a qos_type field and may not be + * supported on all platforms. + * + * By default all settings in this structure are not set. + */ + pj_qos_params qos_params; + + /** + * Specify if STUN socket should ignore any errors when setting the QoS + * traffic type/parameters. + * + * Default: PJ_TRUE + */ + pj_bool_t qos_ignore_error; + +} pj_turn_sock_cfg; + + +/** + * Initialize pj_turn_sock_cfg structure with default values. + */ +PJ_DECL(void) pj_turn_sock_cfg_default(pj_turn_sock_cfg *cfg); + + +/** + * Create a TURN transport instance with the specified address family and + * connection type. Once TURN transport instance is created, application + * must call pj_turn_sock_alloc() to allocate a relay address in the TURN + * server. + * + * @param cfg The STUN configuration which contains among other + * things the ioqueue and timer heap instance for + * the operation of this transport. + * @param af Address family of the client connection. Currently + * pj_AF_INET() and pj_AF_INET6() are supported. + * @param conn_type Connection type to the TURN server. Both TCP and + * UDP are supported. + * @param cb Callback to receive events from the TURN transport. + * @param setting Optional settings to be specified to the transport. + * If this parameter is NULL, default values will be + * used. + * @param user_data Arbitrary application data to be associated with + * this transport. + * @param p_turn_sock Pointer to receive the created instance of the + * TURN transport. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_sock_create(pj_stun_config *cfg, + int af, + pj_turn_tp_type conn_type, + const pj_turn_sock_cb *cb, + const pj_turn_sock_cfg *setting, + void *user_data, + pj_turn_sock **p_turn_sock); + +/** + * Destroy the TURN transport instance. This will gracefully close the + * connection between the client and the TURN server. Although this + * function will return immediately, the TURN socket deletion may continue + * in the background and the application may still get state changes + * notifications from this transport. + * + * @param turn_sock The TURN transport instance. + */ +PJ_DECL(void) pj_turn_sock_destroy(pj_turn_sock *turn_sock); + + +/** + * Associate a user data with this TURN transport. The user data may then + * be retrieved later with #pj_turn_sock_get_user_data(). + * + * @param turn_sock The TURN transport instance. + * @param user_data Arbitrary data. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_sock_set_user_data(pj_turn_sock *turn_sock, + void *user_data); + +/** + * Retrieve the previously assigned user data associated with this TURN + * transport. + * + * @param turn_sock The TURN transport instance. + * + * @return The user/application data. + */ +PJ_DECL(void*) pj_turn_sock_get_user_data(pj_turn_sock *turn_sock); + + +/** + * Get the TURN transport info. The transport info contains, among other + * things, the allocated relay address. + * + * @param turn_sock The TURN transport instance. + * @param info Pointer to be filled with TURN transport info. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_sock_get_info(pj_turn_sock *turn_sock, + pj_turn_session_info *info); + +/** + * Acquire the internal mutex of the TURN transport. Application may need + * to call this function to synchronize access to other objects alongside + * the TURN transport, to avoid deadlock. + * + * @param turn_sock The TURN transport instance. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_sock_lock(pj_turn_sock *turn_sock); + + +/** + * Release the internal mutex previously held with pj_turn_sock_lock(). + * + * @param turn_sock The TURN transport instance. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_sock_unlock(pj_turn_sock *turn_sock); + + +/** + * Set STUN message logging for this TURN session. + * See #pj_stun_session_set_log(). + * + * @param turn_sock The TURN transport instance. + * @param flags Bitmask combination of #pj_stun_sess_msg_log_flag + */ +PJ_DECL(void) pj_turn_sock_set_log(pj_turn_sock *turn_sock, + unsigned flags); + +/** + * Configure the SOFTWARE name to be sent in all STUN requests by the + * TURN session. + * + * @param turn_sock The TURN transport instance. + * @param sw Software name string. If this argument is NULL or + * empty, the session will not include SOFTWARE attribute + * in STUN requests and responses. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_turn_sock_set_software_name(pj_turn_sock *turn_sock, + const pj_str_t *sw); + + +/** + * Allocate a relay address/resource in the TURN server. This function + * will resolve the TURN server using DNS SRV (if desired) and send TURN + * \a Allocate request using the specified credential to allocate a relay + * address in the server. This function completes asynchronously, and + * application will be notified when the allocation process has been + * successful in the \a on_state() callback when the state is set to + * PJ_TURN_STATE_READY. If the allocation fails, the state will be set + * to PJ_TURN_STATE_DEALLOCATING or greater. + * + * @param turn_sock The TURN transport instance. + * @param domain The domain, hostname, or IP address of the TURN + * server. When this parameter contains domain name, + * the \a resolver parameter must be set to activate + * DNS SRV resolution. + * @param default_port The default TURN port number to use when DNS SRV + * resolution is not used. If DNS SRV resolution is + * used, the server port number will be set from the + * DNS SRV records. + * @param resolver If this parameter is not NULL, then the \a domain + * parameter will be first resolved with DNS SRV and + * then fallback to using DNS A/AAAA resolution when + * DNS SRV resolution fails. If this parameter is + * NULL, the \a domain parameter will be resolved as + * hostname. + * @param cred The STUN credential to be used for the TURN server. + * @param param Optional TURN allocation parameter. + * + * @return PJ_SUCCESS if the operation has been successfully + * queued, or the appropriate error code on failure. + * When this function returns PJ_SUCCESS, the final + * result of the allocation process will be notified + * to application in \a on_state() callback. + * + */ +PJ_DECL(pj_status_t) pj_turn_sock_alloc(pj_turn_sock *turn_sock, + const pj_str_t *domain, + int default_port, + pj_dns_resolver *resolver, + const pj_stun_auth_cred *cred, + const pj_turn_alloc_param *param); + +/** + * Create or renew permission in the TURN server for the specified peer IP + * addresses. Application must install permission for a particular (peer) + * IP address before it sends any data to that IP address, or otherwise + * the TURN server will drop the data. + * + * @param turn_sock The TURN transport instance. + * @param addr_cnt Number of IP addresses. + * @param addr Array of peer IP addresses. Only the address family + * and IP address portion of the socket address matter. + * @param options Specify 1 to let the TURN client session automatically + * renew the permission later when they are about to + * expire. + * + * @return PJ_SUCCESS if the operation has been successfully + * issued, or the appropriate error code. Note that + * the operation itself will complete asynchronously. + */ +PJ_DECL(pj_status_t) pj_turn_sock_set_perm(pj_turn_sock *turn_sock, + unsigned addr_cnt, + const pj_sockaddr addr[], + unsigned options); + +/** + * Send a data to the specified peer address via the TURN relay. This + * function will encapsulate the data as STUN Send Indication or TURN + * ChannelData packet and send the message to the TURN server. The TURN + * server then will send the data to the peer. + * + * The allocation (pj_turn_sock_alloc()) must have been successfully + * created before application can relay any data. + * + * @param turn_sock The TURN transport instance. + * @param pkt The data/packet to be sent to peer. + * @param pkt_len Length of the data. + * @param peer_addr The remote peer address (the ultimate destination + * of the data, and not the TURN server address). + * @param addr_len Length of the address. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_sock_sendto(pj_turn_sock *turn_sock, + const pj_uint8_t *pkt, + unsigned pkt_len, + const pj_sockaddr_t *peer_addr, + unsigned addr_len); + +/** + * Optionally establish channel binding for the specified a peer address. + * This function will assign a unique channel number for the peer address + * and request channel binding to the TURN server for this address. When + * a channel has been bound to a peer, the TURN transport and TURN server + * will exchange data using ChannelData encapsulation format, which has + * lower bandwidth overhead than Send Indication (the default format used + * when peer address is not bound to a channel). + * + * @param turn_sock The TURN transport instance. + * @param peer The remote peer address. + * @param addr_len Length of the address. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_turn_sock_bind_channel(pj_turn_sock *turn_sock, + const pj_sockaddr_t *peer, + unsigned addr_len); + + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJNATH_TURN_SOCK_H__ */ + diff --git a/pjnath/include/pjnath/types.h b/pjnath/include/pjnath/types.h new file mode 100644 index 0000000..a845b04 --- /dev/null +++ b/pjnath/include/pjnath/types.h @@ -0,0 +1,76 @@ +/* $Id: types.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* + * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_TYPES_H__ +#define __PJNATH_TYPES_H__ + +/** + * @file types.h + * @brief PJNATH types. + */ + +#include <pj/types.h> +#include <pjnath/config.h> + +/** + * @defgroup PJNATH NAT Traversal Helper Library + * @{ + */ + +PJ_BEGIN_DECL + +/** + * This constant describes a number to be used to identify an invalid TURN + * channel number. + */ +#define PJ_TURN_INVALID_CHANNEL 0xFFFF + + +/** + * Initialize pjnath library. + * + * @return Initialization status. + */ +PJ_DECL(pj_status_t) pjnath_init(void); + + +/** + * Display error to the log. + * + * @param sender The sender name. + * @param title Title message. + * @param status The error status. + */ +#if PJNATH_ERROR_LEVEL <= PJ_LOG_MAX_LEVEL +PJ_DECL(void) pjnath_perror(const char *sender, const char *title, + pj_status_t status); +#else +# define pjnath_perror(sender, title, status) +#endif + + + +PJ_END_DECL + +/** + * @} + */ + +#endif /* __PJNATH_TYPES_H__ */ + |