initial commit

This commit is contained in:
Dan Bastone committed 2021-10-29 14:41:03 -04:00
commit 636959b37b
2474 files changed
+1343178

No files matched your search

+44
View File
@@ -0,0 +1,44 @@
/* $Id$ */
/*
* 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_H__
#define __PJNATH_H__
/**
* @file pjnath.h
* @brief PJNATH main header file.
*/
#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>
#endif
@@ -0,0 +1,581 @@
/* $Id$ */
/*
* 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
/**
* Maximum number of TCP data connection to peer(s) that a TURN client can
* open/accept for each TURN allocation (or TURN control connection).
*/
#ifndef PJ_TURN_MAX_TCP_CONN_CNT
# define PJ_TURN_MAX_TCP_CONN_CNT 8
#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
/**
* Maximum number of STUN transports for each ICE stream transport component.
* Valid values are 1 - 64.
*
* Default: 2
*/
#ifndef PJ_ICE_MAX_STUN
# define PJ_ICE_MAX_STUN 2
#endif
/**
* Maximum number of TURN transports for each ICE stream transport component.
* Valid values are 1 - 64.
*
* Default: 2
*/
#ifndef PJ_ICE_MAX_TURN
# define PJ_ICE_MAX_TURN 3
#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 (1<<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.
*
* Default: 8 (characters)
*/
#ifndef PJ_ICE_UFRAG_LEN
# define PJ_ICE_UFRAG_LEN 8
#endif
/**
* This constant specifies the length of random string generated for ICE
* password.
*
* Default: 24 (characters)
*/
#ifndef PJ_ICE_PWD_LEN
# define PJ_ICE_PWD_LEN 24
#endif
/**
* This constant specifies whether ICE stream transport should allow TURN
* client session to automatically renew permission for all remote candidates.
*
* Default: PJ_FALSE
*/
#ifndef PJ_ICE_ST_USE_TURN_PERMANENT_PERM
# define PJ_ICE_ST_USE_TURN_PERMANENT_PERM PJ_FALSE
#endif
/**
* For trickle ICE, this macro specifies the maximum time of waiting for
* end-of-candidates indication from remote once ICE connectivity checks
* is started, in seconds. When the timer expires, ICE will assume that
* end-of-candidates indication is received so any further remote candidate
* update will be ignored.
*
* Note that without remote end-of-candidates indication, ICE will not be
* able to conclude that the ICE negotiation has failed when all pair checks
* are completed but there is no valid pair (on the other hand, the ICE
* negotiation may be completed as successful before the end-of-candidates
* indication is received when valid pairs are found very quickly).
*
* Also note that the ICE connectivity checks should only be started after
* both agents have started trickling ICE candidates (e.g: both have sent
* their SDPs, either via normal SDP offer/answer or SIP INFO).
*
* Default: 40 seconds.
*/
#ifndef PJ_TRICKLE_ICE_END_OF_CAND_TIMEOUT
# define PJ_TRICKLE_ICE_END_OF_CAND_TIMEOUT 40
#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
/** Default STUN software name */
#ifndef PJNATH_STUN_SOFTWARE_NAME
# define PJNATH_MAKE_SW_NAME(a,b,c,d) "pjnath-" #a "." #b "." #c d
# define PJNATH_MAKE_SW_NAME2(a,b,c,d) PJNATH_MAKE_SW_NAME(a,b,c,d)
# define PJNATH_STUN_SOFTWARE_NAME PJNATH_MAKE_SW_NAME2( \
PJ_VERSION_NUM_MAJOR, \
PJ_VERSION_NUM_MINOR, \
PJ_VERSION_NUM_REV, \
PJ_VERSION_NUM_EXTRA)
#endif
/**
* @}
*/
#endif /* __PJNATH_CONFIG_H__ */
@@ -0,0 +1,226 @@
/* $Id$ */
/*
* 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__ */
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,234 @@
/* $Id$ */
/*
* 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.
*
* See also #pj_stun_detect_nat_type2() which supports IPv6.
*
* @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);
/**
* Variant of #pj_stun_detect_nat_type() that supports IPv6.
*
* @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_type2(const pj_sockaddr *server,
pj_stun_config *stun_cfg,
void *user_data,
pj_stun_nat_detect_cb *cb);
/**
* @}
*/
PJ_END_DECL
#endif /* __PJNATH_NAT_DETECT_H__ */
@@ -0,0 +1,457 @@
/* $Id$ */
/*
* 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__ */
@@ -0,0 +1,136 @@
/* $Id$ */
/*
* 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;
/**
* Software name to be included in all STUN requests and responses.
*
* Default: PJNATH_STUN_SOFTWARE_NAME.
*/
pj_str_t software_name;
} 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;
cfg->software_name = pj_str((char*)PJNATH_STUN_SOFTWARE_NAME);
}
/**
* 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__ */
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,764 @@
/* $Id$ */
/*
* 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/lock.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_grp_lock_t *grp_lock; /**< Group lock (for resp cache). */
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 grp_lock Optional group lock to be used by this session.
* If NULL, the session will create one itself.
* @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_grp_lock_t *grp_lock,
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);
/**
* Get the group lock for this STUN session.
*
* @param sess The STUN session instance.
*
* @return The group lock.
*/
PJ_DECL(pj_grp_lock_t *) pj_stun_session_get_grp_lock(pj_stun_session *sess);
/**
* 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.
* @param mod_count Boolean flag to indicate whether transmission count
* needs to be incremented.
*
* @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,
pj_bool_t mod_count);
/**
* 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__ */
@@ -0,0 +1,497 @@
/* $Id$ */
/*
* 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/lock.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
{
/**
* The group lock to be used by the STUN socket. If NULL, the STUN socket
* will create one internally.
*
* Default: NULL
*/
pj_grp_lock_t *grp_lock;
/**
* 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. If the port is set to zero, the
* socket will bind at any port (chosen by the OS).
*/
pj_sockaddr bound_addr;
/**
* Specify the port range for STUN socket binding, relative to the start
* port number specified in \a bound_addr. Note that this setting is only
* applicable when the start port number is non zero.
*
* Default value is zero.
*/
pj_uint16_t port_range;
/**
* 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;
/**
* Specify target value for socket receive buffer size. It will be
* applied using setsockopt(). When it fails to set the specified size,
* it will try with lower value until the highest possible is
* successfully set.
*
* Default: 0 (OS default)
*/
unsigned so_rcvbuf_size;
/**
* Specify target value for socket send buffer size. It will be
* applied using setsockopt(). When it fails to set the specified size,
* it will try with lower value until the highest possible is
* successfully set.
*
* Default: 0 (OS default)
*/
unsigned so_sndbuf_size;
} 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 STUN
* 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_status() 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 group lock for this STUN transport.
*
* @param stun_sock The STUN transport instance.
*
* @return The group lock.
*/
PJ_DECL(pj_grp_lock_t *) pj_stun_sock_get_grp_lock(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__ */
@@ -0,0 +1,292 @@
/* $Id$ */
/*
* 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>
#include <pj/lock.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 grp_lock Group lock to synchronize.
* @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,
pj_grp_lock_t *grp_lock,
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 the STUN transaction immediately after the transaction is complete.
* Application normally calls this function in the on_complete() callback.
*
* @param tsx The STUN transaction.
*
* @return PJ_SUCCESS on success, or the appropriate error code.
*/
PJ_DECL(pj_status_t) pj_stun_client_tsx_destroy(pj_stun_client_tsx *tsx);
/**
* Stop the client transaction.
*
* @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_stop(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.
* @param mod_count Boolean flag to indicate whether transmission count
* needs to be incremented.
*
* @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,
pj_bool_t mod_count);
/**
* 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__ */
@@ -0,0 +1,910 @@
/* $Id$ */
/*
* 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.
* The value corresponds to IANA protocol number.
*/
PJ_TURN_TP_TLS = 56
} 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 data or outgoing messages. Since the TURN session
* doesn't have a socket on its own, this callback must be implemented.
*
* If the callback \a on_stun_send_pkt() is implemented, outgoing
* messages will use that callback instead.
*
* @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);
/**
* This callback will be called by the TURN session whenever it
* needs to send outgoing STUN requests/messages for TURN signalling
* purposes (data sending will not invoke this callback). If this
* callback is not implemented, the callback \a on_send_pkt()
* will be called instead.
*
* @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_stun_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);
/**
* Notification when TURN client received a ConnectionAttempt Indication
* from the TURN server, which indicates that peer initiates a TCP
* connection to allocated slot in the TURN server. Application must
* implement this callback if it uses RFC 6062 (TURN TCP allocations).
*
* After receiving this callback, application should establish a new TCP
* connection to the TURN server and send ConnectionBind request (using
* pj_turn_session_connection_bind()). After the connection binding
* succeeds, this new connection will become a data only connection.
*
* @param sess The TURN session.
* @param conn_id The connection ID assigned by TURN server.
* @param peer_addr Peer address that tried to connect to the TURN server.
* @param addr_len Length of the peer address.
*/
void (*on_connection_attempt)(pj_turn_session *sess,
pj_uint32_t conn_id,
const pj_sockaddr_t *peer_addr,
unsigned addr_len);
/**
* Notification for ConnectionBind request sent using
* pj_turn_session_connection_bind().
*
* @param sess The TURN session.
* @param status The status code.
* @param conn_id The connection ID.
* @param peer_addr Peer address.
* @param addr_len Length of the peer address.
*/
void (*on_connection_bind_status)(pj_turn_session *sess,
pj_status_t status,
pj_uint32_t conn_id,
const pj_sockaddr_t *peer_addr,
unsigned addr_len);
} 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;
/**
* The requested ADDRESS-FAMILY. Default is zero to request relay with
* address family matched to the one specified in TURN session creation.
* Valid values are zero, pj_AF_INET(), and pj_AF_INET6().
*
* Default value is zero.
*/
int af;
/**
* Type of connection to from TURN server to peer. Supported values are
* PJ_TURN_TP_UDP (RFC 5766) and PJ_TURN_TP_TCP (RFC 6062)
*
* Default is PJ_TURN_TP_UDP.
*/
pj_turn_tp_type peer_conn_type;
} 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;
/**
* Parameters for function pj_turn_session_on_rx_pkt2().
*/
typedef struct pj_turn_session_on_rx_pkt_param
{
/**
* The packet as received from the TURN server. This should contain
* either STUN encapsulated message or a ChannelData packet.
*/
void *pkt;
/**
* The length of the packet.
*/
pj_size_t pkt_len;
/**
* The number of parsed or processed data from the packet.
*/
pj_size_t parsed_len;
/**
* Source address where the packet is received from.
*/
const pj_sockaddr_t *src_addr;
/**
* Length of the source address.
*/
unsigned src_addr_len;
} pj_turn_session_on_rx_pkt_param;
/**
* 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 grp_lock Optional group lock object to be used by this session.
* If this value is NULL, the session will create
* a group lock internally.
* @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,
pj_grp_lock_t *grp_lock,
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);
/**
* Get the group lock for this TURN session.
*
* @param sess The TURN client session.
*
* @return The group lock.
*/
PJ_DECL(pj_grp_lock_t *) pj_turn_session_get_grp_lock(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 If the callback \a on_send_pkt() is called, this
* will contain the return value of the callback.
* Otherwise, it will indicate failure with
* the appropriate error code.
*/
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);
/**
* 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.
*
* This function is variant of pj_turn_session_on_rx_pkt() with additional
* parameters such as source address. Source address will allow STUN/TURN
* session to resend the request (e.g: with updated authentication) to the
* provided source address which may be different to the initial connection,
* for example in RFC 6062 scenario that there can be some data connection
* and a control connection.
*
* @param sess The TURN client session.
* @param prm The function parameters, e.g: packet, source address.
*
* @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_pkt2(
pj_turn_session *sess,
pj_turn_session_on_rx_pkt_param *prm);
/**
* Initiate connection binding to the specified peer using ConnectionBind
* request. Application must call this function when it uses RFC 6062
* (TURN TCP allocations) to establish a data connection with peer after
* opening/accepting connection to/from peer. The connection binding status
* will be notified via on_connection_bind_status callback.
*
* @param sess The TURN session.
* @param pool The memory pool.
* @param conn_id The connection ID assigned by TURN server.
* @param peer_addr Peer address.
* @param addr_len Length of the peer address.
*
* @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_connection_bind(
pj_turn_session *sess,
pj_pool_t *pool,
pj_uint32_t conn_id,
const pj_sockaddr_t *peer_addr,
unsigned addr_len);
/**
* @}
*/
PJ_END_DECL
#endif /* __PJNATH_TURN_SESSION_H__ */
@@ -0,0 +1,636 @@
/* $Id$ */
/*
* 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>
#include <pj/ssl_sock.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);
/**
* Notifification when asynchronous send operation has completed.
*
* @param turn_sock The TURN transport.
* @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 TURN transport continue its operation. However
* it must return PJ_FALSE if it has destroyed the
* TURN transport in this callback.
*/
pj_bool_t (*on_data_sent)(pj_turn_sock *sock,
pj_ssize_t sent);
/**
* 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);
/**
* Notification when TURN client received a ConnectionAttempt Indication
* from the TURN server, which indicates that peer initiates a TCP
* connection to allocated slot in the TURN server. Application should
* implement this callback if it uses RFC 6062 (TURN TCP allocations),
* otherwise TURN client will automatically accept it.
*
* If application accepts the peer connection attempt (i.e: by returning
* PJ_SUCCESS or not implementing this callback), the TURN socket will
* initiate a new connection to the TURN server and send ConnectionBind
* request, and eventually will notify application via
* on_connection_status callback, if implemented.
*
* @param turn_sock The TURN client transport.
* @param conn_id The connection ID assigned by TURN server.
* @param peer_addr Peer address that tried to connect to the
* TURN server.
* @param addr_len Length of the peer address.
*
* @return The callback must return PJ_SUCCESS to accept
* the connection attempt.
*/
pj_status_t (*on_connection_attempt)(pj_turn_sock *turn_sock,
pj_uint32_t conn_id,
const pj_sockaddr_t *peer_addr,
unsigned addr_len);
/**
* Notification for initiated TCP data connection to peer (RFC 6062),
* for example after peer connection attempt is accepted.
*
* @param turn_sock The TURN client transport.
* @param status The status code.
* @param conn_id The connection ID.
* @param peer_addr Peer address.
* @param addr_len Length of the peer address.
*/
void (*on_connection_status)(pj_turn_sock *turn_sock,
pj_status_t status,
pj_uint32_t conn_id,
const pj_sockaddr_t *peer_addr,
unsigned addr_len);
} pj_turn_sock_cb;
/**
* The default enabled SSL proto to be used.
* Default is all protocol above TLSv1 (TLSv1 & TLS v1.1 & TLS v1.2).
*/
#ifndef PJ_TURN_TLS_DEFAULT_PROTO
# define PJ_TURN_TLS_DEFAULT_PROTO (PJ_SSL_SOCK_PROTO_TLS1 | \
PJ_SSL_SOCK_PROTO_TLS1_1 | \
PJ_SSL_SOCK_PROTO_TLS1_2)
#endif
/**
* TLS transport settings.
*/
typedef struct pj_turn_sock_tls_cfg
{
/**
* Certificate of Authority (CA) list file.
*/
pj_str_t ca_list_file;
/**
* Certificate of Authority (CA) list directory path.
*/
pj_str_t ca_list_path;
/**
* Public endpoint certificate file, which will be used as client-
* side certificate for outgoing TLS connection.
*/
pj_str_t cert_file;
/**
* Optional private key of the endpoint certificate to be used.
*/
pj_str_t privkey_file;
/**
* Certificate of Authority (CA) buffer. If ca_list_file, ca_list_path,
* cert_file or privkey_file are set, this setting will be ignored.
*/
pj_ssl_cert_buffer ca_buf;
/**
* Public endpoint certificate buffer, which will be used as client-
* side certificate for outgoing TLS connection, and server-side
* certificate for incoming TLS connection. If ca_list_file, ca_list_path,
* cert_file or privkey_file are set, this setting will be ignored.
*/
pj_ssl_cert_buffer cert_buf;
/**
* Optional private key buffer of the endpoint certificate to be used.
* If ca_list_file, ca_list_path, cert_file or privkey_file are set,
* this setting will be ignored.
*/
pj_ssl_cert_buffer privkey_buf;
/**
* Password to open private key.
*/
pj_str_t password;
/**
* The ssl socket parameter.
* These fields are used by TURN TLS:
* - proto
* - ciphers_num
* - ciphers
* - curves_num
* - curves
* - sigalgs
* - entropy_type
* - entropy_path
* - timeout
* - sockopt_params
* - sockopt_ignore_error
*/
pj_ssl_sock_param ssock_param;
} pj_turn_sock_tls_cfg;
/**
* Initialize TLS setting with default values.
*
* @param tls_cfg The TLS setting to be initialized.
*/
PJ_DECL(void) pj_turn_sock_tls_cfg_default(pj_turn_sock_tls_cfg *tls_cfg);
/**
* Duplicate TLS setting.
*
* @param pool The pool to duplicate strings etc.
* @param dst Destination structure.
* @param src Source structure.
*/
PJ_DECL(void) pj_turn_sock_tls_cfg_dup(pj_pool_t *pool,
pj_turn_sock_tls_cfg *dst,
const pj_turn_sock_tls_cfg *src);
/**
* Wipe out certificates and keys in the TLS setting.
*
* @param tls_cfg The TLS setting.
*/
PJ_DECL(void) pj_turn_sock_tls_cfg_wipe_keys(pj_turn_sock_tls_cfg *tls_cfg);
/**
* 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
{
/**
* The group lock to be used by the STUN socket. If NULL, the STUN socket
* will create one internally.
*
* Default: NULL
*/
pj_grp_lock_t *grp_lock;
/**
* Packet buffer size.
*
* Default value is PJ_TURN_MAX_PKT_LEN.
*/
unsigned max_pkt_size;
/**
* 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;
/**
* 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. If the port is
* set to zero, the socket will bind at any port (chosen by the OS).
*/
pj_sockaddr bound_addr;
/**
* Specify the port range for TURN socket binding, relative to the start
* port number specified in \a bound_addr. Note that this setting is only
* applicable when the start port number is non zero.
*
* Default value is zero.
*/
pj_uint16_t port_range;
/**
* Specify target value for socket receive buffer size. It will be
* applied using setsockopt(). When it fails to set the specified size,
* it will try with lower value until the highest possible has been
* successfully set.
*
* Default: 0 (OS default)
*/
unsigned so_rcvbuf_size;
/**
* Specify target value for socket send buffer size. It will be
* applied using setsockopt(). When it fails to set the specified size,
* it will try with lower value until the highest possible has been
* successfully set.
*
* Default: 0 (OS default)
*/
unsigned so_sndbuf_size;
/**
* This specifies TLS settings for TLS transport. It is only be used
* when this TLS is used to connect to the TURN server.
*/
pj_turn_sock_tls_cfg tls_cfg;
} 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 group lock for this TURN transport.
*
* @param turn_sock The TURN transport instance.
*
* @return The group lock.
*/
PJ_DECL(pj_grp_lock_t *) pj_turn_sock_get_grp_lock(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 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_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__ */
@@ -0,0 +1,76 @@
/* $Id$ */
/*
* 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__ */