diff options
author | Benny Prijono <bennylp@teluu.com> | 2008-06-06 14:47:10 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2008-06-06 14:47:10 +0000 |
commit | 8ec5bd6b3d5bafb1d3ab11236a3adc45ac5f04d8 (patch) | |
tree | 75c82cf12d34d58e3ccf64e6eb08e8628e8f94cf /pjnath/include | |
parent | 77825e4c00356383e69f3fc4c63eccd0a3aa103f (diff) |
Major major modifications related to ticket #485 (support for TURN-07):
- Added STUN socket transport pj_stun_sock
- Integration of TURN-07 to ICE
- Major refactoring in ICE stream transport to make it simpler
- Major modification (i.e. API change) in almost everywhere else
- Much more elaborate STUN, TURN, and ICE tests in pjnath-test
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1988 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjnath/include')
-rw-r--r-- | pjnath/include/pjnath.h | 1 | ||||
-rw-r--r-- | pjnath/include/pjnath/config.h | 78 | ||||
-rw-r--r-- | pjnath/include/pjnath/errno.h | 9 | ||||
-rw-r--r-- | pjnath/include/pjnath/ice_session.h | 77 | ||||
-rw-r--r-- | pjnath/include/pjnath/ice_strans.h | 695 | ||||
-rw-r--r-- | pjnath/include/pjnath/nat_detect.h | 1 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_config.h | 13 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_msg.h | 21 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_session.h | 50 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_sock.h | 403 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_transaction.h | 17 | ||||
-rw-r--r-- | pjnath/include/pjnath/turn_session.h | 346 | ||||
-rw-r--r-- | pjnath/include/pjnath/turn_sock.h | 230 | ||||
-rw-r--r-- | pjnath/include/pjnath/types.h | 378 |
14 files changed, 1637 insertions, 682 deletions
diff --git a/pjnath/include/pjnath.h b/pjnath/include/pjnath.h index 962aeba0..84096beb 100644 --- a/pjnath/include/pjnath.h +++ b/pjnath/include/pjnath.h @@ -26,6 +26,7 @@ #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> diff --git a/pjnath/include/pjnath/config.h b/pjnath/include/pjnath/config.h index c84fe18c..e002a105 100644 --- a/pjnath/include/pjnath/config.h +++ b/pjnath/include/pjnath/config.h @@ -142,6 +142,84 @@ /* ************************************************************************** + * STUN TRANSPORT CONFIGURATION + */ + +/** + * The packet buffer size for the STUN transport. + */ +#ifndef PJ_STUN_SOCK_PKT_LEN +# define PJ_STUN_SOCK_PKT_LEN 2000 +#endif + + +/** + * The duration of the STUN keep-alive period, in seconds. + */ +#ifndef PJ_STUN_KEEP_ALIVE_SEC +# define PJ_STUN_KEEP_ALIVE_SEC 15 +#endif + + +/* ************************************************************************** + * TURN CONFIGURATION + */ + +/** + * Maximum DNS SRV entries to be processed in the DNS SRV response + */ +#ifndef PJ_TURN_MAX_DNS_SRV_CNT +# define PJ_TURN_MAX_DNS_SRV_CNT 4 +#endif + + +/** + * Maximum TURN packet size to be supported. + */ +#ifndef PJ_TURN_MAX_PKT_LEN +# define PJ_TURN_MAX_PKT_LEN 3000 +#endif + + +/** + * The TURN permission lifetime setting. This value should be taken from the + * TURN protocol specification. + */ +#ifndef PJ_TURN_PERM_TIMEOUT +# define PJ_TURN_PERM_TIMEOUT 300 +#endif + + +/** + * The TURN channel binding lifetime. This value should be taken from the + * TURN protocol specification. + */ +#ifndef PJ_TURN_CHANNEL_TIMEOUT +# define PJ_TURN_CHANNEL_TIMEOUT 600 +#endif + + +/** + * Number of seconds to refresh the permission/channel binding before the + * permission/channel binding expires. This value should be greater than + * PJ_TURN_PERM_TIMEOUT setting. + */ +#ifndef PJ_TURN_REFRESH_SEC_BEFORE +# define PJ_TURN_REFRESH_SEC_BEFORE 60 +#endif + + +/** + * The TURN session timer heart beat interval. When this timer occurs, the + * TURN session will scan all the permissions/channel bindings to see which + * need to be refreshed. + */ +#ifndef PJ_TURN_KEEP_ALIVE_SEC +# define PJ_TURN_KEEP_ALIVE_SEC 15 +#endif + + +/* ************************************************************************** * ICE CONFIGURATION */ diff --git a/pjnath/include/pjnath/errno.h b/pjnath/include/pjnath/errno.h index 56763916..3cd3320a 100644 --- a/pjnath/include/pjnath/errno.h +++ b/pjnath/include/pjnath/errno.h @@ -121,6 +121,15 @@ #define PJNATH_ESTUNINSERVER (PJNATH_ERRNO_START+42) /* 370042 */ +/************************************************************ + * STUN SESSION/TRANSPORT ERROR CODES + ***********************************************************/ +/** + * @hideinitializer + * STUN object has been destoyed. + */ +#define PJNATH_ESTUNDESTROYED (PJNATH_ERRNO_START+60) /* 370060 */ + /************************************************************ * ICE ERROR CODES diff --git a/pjnath/include/pjnath/ice_session.h b/pjnath/include/pjnath/ice_session.h index 2af223f3..87b723af 100644 --- a/pjnath/include/pjnath/ice_session.h +++ b/pjnath/include/pjnath/ice_session.h @@ -129,6 +129,11 @@ PJ_BEGIN_DECL */ /** + * Forward declaration for checklist. + */ +typedef struct pj_ice_sess_checklist pj_ice_sess_checklist; + +/** * This enumeration describes the type of an ICE candidate. */ typedef enum pj_ice_cand_type @@ -194,6 +199,24 @@ typedef struct pj_ice_sess_comp /** + * Data structure to be attached to internal message processing. + */ +typedef struct pj_ice_msg_data +{ + unsigned transport_id; + pj_bool_t has_req_data; + + union data { + struct request_data { + pj_ice_sess *ice; + pj_ice_sess_checklist *clist; + unsigned ckid; + } req; + } data; +} pj_ice_msg_data; + + +/** * This structure describes an ICE candidate. * ICE candidate is a transport address that is to be tested by ICE * procedures in order to determine its suitability for usage for @@ -204,16 +227,34 @@ typedef struct pj_ice_sess_comp typedef struct pj_ice_sess_cand { /** + * The candidate type, as described in #pj_ice_cand_type enumeration. + */ + pj_ice_cand_type type; + + /** + * Status of this candidate. The value will be PJ_SUCCESS if candidate + * address has been resolved successfully, PJ_EPENDING when the address + * resolution process is in progress, or other value when the address + * resolution has completed with failure. + */ + pj_status_t status; + + /** * The component ID of this candidate. Note that component IDs starts * with one for RTP and two for RTCP. In other words, it's not zero * based. */ - pj_uint32_t comp_id; + pj_uint8_t comp_id; /** - * The candidate type, as described in #pj_ice_cand_type enumeration. + * Transport ID to be used to send packets for this candidate. */ - pj_ice_cand_type type; + pj_uint8_t transport_id; + + /** + * Local preference value, which typically is 65535. + */ + pj_uint16_t local_pref; /** * The foundation string, which is an identifier which value will be @@ -383,7 +424,7 @@ typedef enum pj_ice_sess_checklist_state * This structure represents ICE check list, that is an ordered set of * candidate pairs that an agent will use to generate checks. */ -typedef struct pj_ice_sess_checklist +struct pj_ice_sess_checklist { /** * The checklist state. @@ -405,7 +446,7 @@ typedef struct pj_ice_sess_checklist */ pj_timer_entry timer; -} pj_ice_sess_checklist; +}; /** @@ -430,12 +471,14 @@ typedef struct pj_ice_sess_cb * * @param ice The ICE session. * @param comp_id ICE component ID. + * @param transport_id Transport ID. * @param pkt The STUN packet. * @param size The size of the packet. * @param dst_addr Packet destination address. * @param dst_addr_len Length of destination address. */ pj_status_t (*on_tx_pkt)(pj_ice_sess *ice, unsigned comp_id, + unsigned transport_id, const void *pkt, pj_size_t size, const pj_sockaddr_t *dst_addr, unsigned dst_addr_len); @@ -446,6 +489,7 @@ typedef struct pj_ice_sess_cb * * @param ice The ICE session. * @param comp_id ICE component ID. + * @param transport_id Transport ID. * @param pkt The whole packet. * @param size Size of the packet. * @param src_addr Source address where this packet was received @@ -453,6 +497,7 @@ typedef struct pj_ice_sess_cb * @param src_addr_len The length of source address. */ void (*on_rx_data)(pj_ice_sess *ice, unsigned comp_id, + unsigned transport_id, void *pkt, pj_size_t size, const pj_sockaddr_t *src_addr, unsigned src_addr_len); @@ -496,6 +541,7 @@ typedef struct pj_ice_rx_check PJ_DECL_LIST_MEMBER(struct pj_ice_rx_check); unsigned comp_id; /**< Component ID. */ + unsigned transport_id; /**< Transport ID. */ pj_sockaddr src_addr; /**< Source address of request */ unsigned src_addr_len; /**< Length of src address. */ @@ -553,6 +599,9 @@ struct pj_ice_sess unsigned rcand_cnt; /**< # of remote cand. */ pj_ice_sess_cand rcand[PJ_ICE_MAX_CAND]; /**< Array of cand. */ + /* Array of transport datas */ + pj_ice_msg_data tp_data[4]; + /* List of eearly checks */ pj_ice_rx_check early_check; /**< Early checks. */ @@ -582,6 +631,17 @@ PJ_DECL(const char*) pj_ice_get_cand_type_name(pj_ice_cand_type type); /** + * This is a utility function to retrieve the string name for the + * particular role type. + * + * @param role Role type. + * + * @return The string representation of the role. + */ +PJ_DECL(const char*) pj_ice_sess_role_name(pj_ice_sess_role role); + + +/** * This is a utility function to calculate the foundation identification * for a candidate. * @@ -685,6 +745,8 @@ PJ_DECL(pj_status_t) pj_ice_sess_set_prefs(pj_ice_sess *ice, * * @param ice ICE session instance. * @param comp_id Component ID of this candidate. + * @param transport_id Transport ID to be used to send packets for this + * candidate. * @param type Candidate type. * @param local_pref Local preference for this candidate, which * normally should be set to 65535. @@ -699,6 +761,7 @@ PJ_DECL(pj_status_t) pj_ice_sess_set_prefs(pj_ice_sess *ice, */ PJ_DECL(pj_status_t) pj_ice_sess_add_cand(pj_ice_sess *ice, unsigned comp_id, + unsigned transport_id, pj_ice_cand_type type, pj_uint16_t local_pref, const pj_str_t *foundation, @@ -797,6 +860,9 @@ PJ_DECL(pj_status_t) pj_ice_sess_send_data(pj_ice_sess *ice, * * @param ice The ICE session. * @param comp_id Component ID. + * @param transport_id Number to identify where this packet was received + * from. This parameter will be returned back to + * application in \a on_tx_pkt() callback. * @param pkt Incoming packet. * @param pkt_size Size of incoming packet. * @param src_addr Source address of the packet. @@ -806,6 +872,7 @@ PJ_DECL(pj_status_t) pj_ice_sess_send_data(pj_ice_sess *ice, */ PJ_DECL(pj_status_t) pj_ice_sess_on_rx_pkt(pj_ice_sess *ice, unsigned comp_id, + unsigned transport_id, void *pkt, pj_size_t pkt_size, const pj_sockaddr_t *src_addr, diff --git a/pjnath/include/pjnath/ice_strans.h b/pjnath/include/pjnath/ice_strans.h index 09fedbad..8097b382 100644 --- a/pjnath/include/pjnath/ice_strans.h +++ b/pjnath/include/pjnath/ice_strans.h @@ -25,6 +25,8 @@ * @brief ICE Stream Transport */ #include <pjnath/ice_session.h> +#include <pjnath/stun_sock.h> +#include <pjnath/turn_sock.h> #include <pjlib-util/resolver.h> #include <pj/ioqueue.h> #include <pj/timer.h> @@ -44,137 +46,28 @@ PJ_BEGIN_DECL * library. * * ICE stream transport, as represented by #pj_ice_strans structure, is an ICE - * capable component for transporting media streams within a media session. + * capable class for transporting media streams within a media session. * It consists of one or more transport sockets (typically two for RTP * based communication - one for RTP and one for RTCP), and an * \ref PJNATH_ICE_SESSION for performing connectivity checks among the. * various candidates of the transport addresses. * - * \section PJNATH_ICE_STREAM_TRANSPORT_USING Using the ICE Stream Transport - * - * Application may use the ICE stream transport in two ways: - * - it can create the ICE stream transports once during application - * initialization and keep them alive throughout application lifetime, or - * - it can create and destroy the ICE stream transport as needed everytime - * a call is made and destroyed. - * - * Keeping the ICE stream transport alive throughout - * application's lifetime is normally preferable, as initializing the - * ICE stream transport may incur delay because the ICE stream transport - * would need to communicate with the STUN/TURN server to get the - * server reflexive and relayed candidates for the transports. - * - * Regardless of which usage scenario is being used, the ICE stream - * transport is capable for restarting the ICE session being used and to - * send STUN keep-alives for its STUN server reflexive and relayed - * candidates. When ICE stream transport detects that the STUN mapped - * address has changed in the keep-alive response, it will automatically - * update its address to the new address, and notify the application via - * \a on_addr_change() function of the #pj_ice_strans_cb callback. - * - * \subsection PJNATH_ICE_ST_TRA_INIT Initialization - * - * Application creates the ICE stream transport by calling - * #pj_ice_strans_create() function. Among other things, application needs - * to specify: - * - STUN configuration (pj_stun_config), containing STUN settings - * such as timeout values and the instances of timer heap and - * ioqueue. - * - Session name, useful for identifying this session in the log. - * - Number of ICE components. - * - Arbitrary user data, useful when associating the ICE session - * with some application's data structure. - * - A callback (#pj_ice_strans_cb) to receive events from the ICE - * stream transport. Two of the most important fields in this - * callback structure are \a on_rx_data() to notify application - * about incoming data (perhaps RTP or RTCP packet), and - * \a on_ice_complete() to notify application that ICE negotiation - * has completed, either successfully or with failure. - * - * After the ICE stream transport is created, application may set up the - * STUN servers to be used to obtain STUN server reflexive and relayed - * candidate, by calling #pj_ice_strans_set_stun_domain() or - * #pj_ice_strans_set_stun_srv(). - * - * Application then creates each component by calling - * #pj_ice_strans_create_comp(); this would create an actual socket - * which listens to the specified local address, and it would also - * perform lookup to find various transport address candidates for this - * socket. - * - * Adding component may involve contacting STUN and TURN servers to get - * STUN mapped address and allocate TURN relay channel, and this process - * may take some time to complete. Once application has added all - * components, it can check whether server reflexive and relayed - * candidates have been acquired, by calling #pj_ice_strans_get_comps_status(). - * - * \subsection PJNATH_ICE_ST_TRA_INIT_ICE Starting ICE Session - * - * When application is about to send an offer containing ICE capability, - * or when it receives an offer containing ICE capability, it would - * create the ICE session by calling #pj_ice_strans_init_ice(). This would - * register all transport address aliases for each component to the ICE - * session as candidates. After this application can enumerate all local - * candidates by calling #pj_ice_strans_enum_cands(), and encode these - * candidates in the SDP to be sent to remote agent. - * - * \subsection PJNATH_ICE_ST_TRA_START Starting Connectivity Checks - * - * Once application receives the SDP from remote, it pairs local candidates - * with remote candidates, and can start ICE connectivity checks. This is - * done by calling #pj_ice_strans_start_ice(), specifying - * the remote candidate list, and remote username and password. If the - * pairing process is successful, ICE connectivity checks will begin - * immediately. The ICE session/transport will then notify the application - * via the callback when ICE connectivity checks completes, either - * successfully or with failure. - * - * \subsection PJNATH_ICE_ST_TRA_SEND_RECV Sending and Receiving Data - * - * Application can send data (normally RTP or RTCP packets) at any time - * by calling #pj_ice_strans_sendto(). This function takes a destination - * address as one of the arguments, and this destination address should - * be taken from the default transport address of the component (that is - * the address in SDP c= and m= lines, or in a=rtcp attribute). - * If ICE negotiation is in progress, this function will send the data - * to the destination address. Otherwise if ICE negotiation has completed - * successfully, this function will send the data to the nominated remote - * address, as negotiated by ICE. - * - * Upon receiving incoming data (that is a non-STUN message), the ICE - * stream transport will notify the application by calling \a on_rx_data() - * of the #pj_ice_strans_cb callback. - * - * \subsection PJNATH_ICE_ST_TRA_STOP Stopping ICE Session - * - * Once the call is terminated, application no longer needs to keep the - * ICE session, so it should call #pj_ice_strans_stop_ice() to destroy the - * ICE session within this ICE stream transport. Note that this WILL NOT - * destroy the sockets/transports, it only destroys the ICE session - * within this ICE stream transport. It is recommended that application - * retains the ICE stream transport to speed up the process of setting up - * the next call. The ICE stream transport will continue to send STUN - * keep-alive packets to keep the NAT binding open and to detect change - * in STUN mapped address. - * - * \subsection PJNATH_ICE_ST_TRA_RESTART Restarting ICE Session - * - * When a new call is made, application can repeat the above - * #pj_ice_strans_init_ice() to #pj_ice_strans_stop_ice() cycle for - * the new call, using this same ICE stream transport. - * - * \subsection PJNATH_ICE_ST_TRA_DESTROY Destroying ICE Stream Transport - * - * Finally, when the ICE stream transport itself is no longer needed, - * for example when the application quits, application should call - * #pj_ice_strans_destroy() to release back all resources allocated by this - * ICE stream transport. - * */ /** Forward declaration for ICE stream transport. */ typedef struct pj_ice_strans pj_ice_strans; +/** Transport operation types to be reported on \a on_status() callback */ +typedef enum pj_ice_strans_op +{ + /** Initialization (candidate gathering) */ + PJ_ICE_STRANS_OP_INIT, + + /** Negotiation */ + PJ_ICE_STRANS_OP_NEGOTIATION + +} pj_ice_strans_op; + /** * This structure contains callbacks that will be called by the * ICE stream transport. @@ -200,195 +93,200 @@ typedef struct pj_ice_strans_cb unsigned src_addr_len); /** - * This callback will be called when ICE checks have completed. - * This callback is optional. + * Callback to report status. * * @param ice_st The ICE stream transport. - * @param status The ICE connectivity check status. + * @param op The operation + * @param status Operation status. */ void (*on_ice_complete)(pj_ice_strans *ice_st, + pj_ice_strans_op op, pj_status_t status); - /** - * This callback will be called when ICE transport has detected that - * the STUN mapped address of a candidate has changed. - * - * @param ice_st The ICE stream transport. - * @param comp_id Component ID. - * @param cand_id Candidate ID. - */ - void (*on_addr_change)(pj_ice_strans *ice_st, - unsigned comp_id, - unsigned cand_id); - } pj_ice_strans_cb; /** - * Various flags that can be specified when creating a component with - * #pj_ice_strans_create_comp(). These options may be combined together - * with bitmask operation. + * This structure describes ICE stream transport configuration. Application + * should initialize the structure by calling #pj_ice_strans_cfg_default() + * before changing the settings. */ -enum pj_ice_strans_option +typedef struct pj_ice_strans_cfg { /** - * If this option is specified, only a listening socket will be - * created for the component, and no candidate will be added to - * the component. Application must add the component manually - * by inspecting the socket and transport address of the component. + * Address family, IPv4 or IPv6. Currently only pj_AF_INET() (IPv4) + * is supported, and this is the default value. */ - PJ_ICE_ST_OPT_DONT_ADD_CAND = 1, + int af; /** - * If this option is specified, then no STUN reflexive candidate - * will be added to the component. - */ - PJ_ICE_ST_OPT_DISABLE_STUN = 2, - - /** - * If this option is specified, then no STUN relay candidate - * will be added to the component. - */ - PJ_ICE_ST_OPT_DISABLE_RELAY = 4, - - /** - * If this option is specified, then when the function fails to - * bind the socket to the specified port, it WILL NOT try to - * bind the socket to the next available port. + * STUN configuration which contains the timer heap and + * ioqueue instance to be used, and STUN retransmission + * settings. This setting is mandatory. * - * If this option is NOT specified, then the function will try to - * bind the socket to next port+2, repetitively until the socket - * is bound successfully. + * The default value is all zero. Application must initialize + * this setting with #pj_stun_config_init(). */ - PJ_ICE_ST_OPT_NO_PORT_RETRY = 8, -}; + pj_stun_config stun_cfg; - -/** - * This structure describes ICE stream transport candidate. A "candidate" - * in ICE stream transport can be viewed as alias transport address - * for the socket. - */ -typedef struct pj_ice_strans_cand -{ /** - * Candidate type. - */ - pj_ice_cand_type type; - - /** - * Status of this candidate. This status is useful for ICE reflexive - * and relay candidate, where the address needs to be resolved - * asynchronously by sending STUN request to STUN server. + * DNS resolver to be used to resolve servers. If DNS SRV + * resolution is required, the resolver must be set. * - * The value will be PJ_SUCCESS if candidate address has been resolved - * successfully, PJ_EPENDING when the address resolution process is - * in progress, or other value when the address resolution has - * completed with failure. + * The default value is NULL. */ - pj_status_t status; + pj_dns_resolver *resolver; /** - * The candidate transport address. + * STUN and local transport settings. This specifies the + * settings for local UDP socket, which will be resolved + * to get the STUN mapped address. */ - pj_sockaddr addr; + struct { + /** + * Optional configuration for STUN transport. The default + * value will be initialized with #pj_stun_sock_cfg_default(). + */ + pj_stun_sock_cfg cfg; + + /** + * Disable host candidates. When this option is set, no + * host candidates will be added. + * + * Default: PJ_FALSE + */ + pj_bool_t no_host_cands; + + /** + * Include loopback addresses in the host candidates. + * + * Default: PJ_FALSE + */ + pj_bool_t loop_addr; + + /** + * Specify the STUN server domain or hostname or IP address. + * If DNS SRV resolution is required, application must fill + * in this setting with the domain name of the STUN server + * and set the resolver instance in the \a resolver field. + * Otherwise if the \a resolver setting is not set, this + * field will be resolved with hostname resolution and in + * this case the \a port field must be set. + * + * The \a port field should also be set even when DNS SRV + * resolution is used, in case the DNS SRV resolution fails. + * + * When this field is empty, STUN mapped address resolution + * will not be performed. In this case only ICE host candidates + * will be added to the ICE transport, unless if \a no_host_cands + * field is set. In this case, both host and srflx candidates + * are disabled. + * + * The default value is empty. + */ + pj_str_t server; + + /** + * The port number of the STUN server, when \a server + * field specifies a hostname rather than domain name. This + * field should also be set even when the \a server + * specifies a domain name, to allow DNS SRV resolution + * to fallback to DNS A/AAAA resolution when the DNS SRV + * resolution fails. + * + * The default value is PJ_STUN_PORT. + */ + pj_uint16_t port; + + } stun; /** - * The ICE session candidate ID after this candidate has been registered - * to an ICE session. Before ICE session is created, or after ICE - * session has been destroyed, the value will be -1. + * TURN specific settings. */ - int ice_cand_id; + struct { + /** + * Specify the TURN server domain or hostname or IP address. + * If DNS SRV resolution is required, application must fill + * in this setting with the domain name of the TURN server + * and set the resolver instance in the \a resolver field. + * Otherwise if the \a resolver setting is not set, this + * field will be resolved with hostname resolution and in + * this case the \a port field must be set. + * + * The \a port field should also be set even when DNS SRV + * resolution is used, in case the DNS SRV resolution fails. + * + * When this field is empty, relay candidate will not be + * created. + * + * The default value is empty. + */ + pj_str_t server; + + /** + * The port number of the TURN server, when \a server + * field specifies a hostname rather than domain name. This + * field should also be set even when the \a server + * specifies a domain name, to allow DNS SRV resolution + * to fallback to DNS A/AAAA resolution when the DNS SRV + * resolution fails. + * + * Default is zero. + */ + pj_uint16_t port; + + /** + * Type of connection to the TURN server. + * + * Default is PJ_TURN_TP_UDP. + */ + pj_turn_tp_type conn_type; + + /** + * Credential to be used for the TURN session. This setting + * is mandatory. + * + * Default is to have no credential. + */ + pj_stun_auth_cred auth_cred; + + /** + * Optional TURN Allocate parameter. The default value will be + * initialized by #pj_turn_alloc_param_default(). + */ + pj_turn_alloc_param alloc_param; + + } turn; + +} pj_ice_strans_cfg; - /** - * Local preference value, which typically is 65535. - */ - pj_uint16_t local_pref; - - /** - * Foundation associated with this candidate, which value normally will be - * calculated by the function. - */ - pj_str_t foundation; -} pj_ice_strans_cand; - - -/** - * This structure describes an ICE stream transport component. A component - * in ICE stream transport typically corresponds to a single socket created - * for this component, and bound to a specific transport address. This - * component may have multiple alias addresses, for example one alias - * address for each interfaces in multi-homed host, another for server - * reflexive alias, and another for relayed alias. For each transport - * address alias, an ICE stream transport candidate (#pj_ice_strans_cand) will - * be created, and these candidates will eventually registered to the ICE - * session. +/** + * Initialize ICE transport configuration with default values. + * + * @param cfg The configuration to be initialized. */ -typedef struct pj_ice_strans_comp -{ - pj_ice_strans *ice_st; /**< ICE stream transport. */ - unsigned comp_id; /**< Component ID. */ - pj_uint32_t options; /**< Option flags. */ - pj_sock_t sock; /**< Socket descriptor. */ - - pj_stun_session *stun_sess; /**< STUN session. */ - pj_uint8_t ka_tsx_id[12]; /**< ID for keep STUN alives */ - - pj_sockaddr local_addr; /**< Local/base address. */ - - unsigned pending_cnt; /**< Pending resolution cnt. */ - pj_status_t last_status; /**< Last status. */ - - unsigned cand_cnt; /**< # of candidates/aliaes. */ - pj_ice_strans_cand cand_list[PJ_ICE_ST_MAX_CAND]; /**< Cand array */ - int default_cand; /**< Default candidate selected */ - - pj_ioqueue_key_t *key; /**< ioqueue key. */ - pj_uint8_t pkt[1500]; /**< Incoming packet buffer. */ - pj_ioqueue_op_key_t read_op; /**< ioqueue read operation key */ - pj_ioqueue_op_key_t write_op; /**< ioqueue write op. key */ - pj_sockaddr src_addr; /**< source packet address buf. */ - int src_addr_len; /**< length of src addr. buf. */ - -} pj_ice_strans_comp; +PJ_DECL(void) pj_ice_strans_cfg_default(pj_ice_strans_cfg *cfg); /** - * This structure represents the ICE stream transport. + * Copy configuration. + * + * @param pool Pool. + * @param dst Destination. + * @param src Source. */ -struct pj_ice_strans -{ - char obj_name[PJ_MAX_OBJ_NAME]; /**< Log ID. */ - - pj_pool_t *pool; /**< Pool used by this object. */ - void *user_data; /**< Application data. */ - pj_stun_config stun_cfg; /**< STUN settings. */ - pj_ice_strans_cb cb; /**< Application callback. */ - - pj_ice_sess *ice; /**< ICE session. */ - - unsigned comp_cnt; /**< Number of components. */ - pj_ice_strans_comp **comp; /**< Components array. */ - - pj_dns_resolver *resolver; /**< The resolver instance. */ - pj_bool_t has_rjob; /**< Has pending resolve? */ - pj_sockaddr_in stun_srv; /**< STUN server address. */ - pj_sockaddr_in turn_srv; /**< TURN server address. */ - - pj_timer_entry ka_timer; /**< STUN keep-alive timer. */ -}; +PJ_DECL(void) pj_ice_strans_cfg_copy(pj_pool_t *pool, + pj_ice_strans_cfg *dst, + const pj_ice_strans_cfg *src); /** - * Create the ICE stream transport containing the specified number of - * components. After the ICE stream transport is created, application - * may initialize the STUN server settings, and after that it has to - * initialize each components by calling #pj_ice_strans_create_comp() - * function. + * Create and initialize the ICE stream transport with the specified + * parameters. * - * @param stun_cfg The STUN settings. * @param name Optional name for logging identification. + * @param cfg Configuration. * @param comp_cnt Number of components. * @param user_data Arbitrary user data to be associated with this * ICE stream transport. @@ -399,8 +297,8 @@ struct pj_ice_strans * @return PJ_SUCCESS if ICE stream transport is created * successfully. */ -PJ_DECL(pj_status_t) pj_ice_strans_create(pj_stun_config *stun_cfg, - const char *name, +PJ_DECL(pj_status_t) pj_ice_strans_create(const char *name, + const pj_ice_strans_cfg *cfg, unsigned comp_cnt, void *user_data, const pj_ice_strans_cb *cb, @@ -419,133 +317,24 @@ PJ_DECL(pj_status_t) pj_ice_strans_destroy(pj_ice_strans *ice_st); /** - * Set the domain to be used when resolving the STUN servers. If application - * wants to utillize STUN, then STUN server must be specified, either by - * calling this function or by calling #pj_ice_strans_set_stun_srv(). - * - * If application calls this function, then the STUN/TURN servers will - * be resolved by querying DNS SRV records for the specified domain. - * - * @param ice_st The ICE stream transport. - * @param resolver The resolver instance that will be used to - * resolve the STUN/TURN servers. - * @param domain The target domain. - * - * @return PJ_SUCCESS if DNS SRV resolution job can be - * started. The resolution process itself will - * complete asynchronously. - */ -PJ_DECL(pj_status_t) pj_ice_strans_set_stun_domain(pj_ice_strans *ice_st, - pj_dns_resolver *resolver, - const pj_str_t *domain); - -/** - * Set the STUN and TURN server addresses. If application - * wants to utillize STUN, then STUN server must be specified, either by - * calling this function or by calling #pj_ice_strans_set_stun_domain(). - * - * With this function, the STUN and TURN server addresses will be - * assigned immediately, that is no DNS resolution will need to be - * performed. + * Get the user data associated with the ICE stream transport. * * @param ice_st The ICE stream transport. - * @param stun_srv The STUN server address, or NULL if STUN - * reflexive candidate is not to be used. - * @param turn_srv The TURN server address, or NULL if STUN - * relay candidate is not to be used. * - * @return PJ_SUCCESS, or the appropriate error code. + * @return The user data. */ -PJ_DECL(pj_status_t) -pj_ice_strans_set_stun_srv( pj_ice_strans *ice_st, - const pj_sockaddr_in *stun_srv, - const pj_sockaddr_in *turn_srv); +PJ_DECL(void*) pj_ice_strans_get_user_data(pj_ice_strans *ice_st); -/** - * Create and initialize the specified component. This function will - * instantiate the socket descriptor for this component, optionally - * bind the socket to the specified address (or bind to any address/port - * if the \a addr parameter is NULL), and start finding all alias - * addresses for this socket. For each alias addresses that if finds, - * it will add an ICE stream transport candidate for this component. - * - * After all components have been initialized, application should poll - * the #pj_ice_strans_get_comps_status() peridically to check if STUN - * server reflexive and relayed candidates have been obtained - * successfully. - * - * @param ice_st The ICE stream transport. - * @param comp_id The component ID, which value must be greater than - * zero and less than or equal to the number of - * components in this ICE stream transport. - * @param options Options, see #pj_ice_strans_option. - * @param addr Local address where socket will be bound to. This - * address will be used as follows: - * - if the value is NULL, then socket will be bound - * to any available port. - * - if the value is not NULL, then if the port number - * is not zero, it will used as the starting port - * where the socket will be bound to. If bind() to - * this port fails, this function will try to bind - * to port+2, repeatedly until it succeeded. - * If application doesn't want this function to - * retry binding the socket to other port, it can - * specify PJ_ICE_ST_OPT_NO_PORT_RETRY option. - * - if the value is not NULL, then if the address - * is not INADDR_ANY, this function will bind the - * socket to this particular interface only, and - * no other host candidates will be added for this - * socket. - * - * - * @return PJ_SUCCESS, or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_ice_strans_create_comp(pj_ice_strans *ice_st, - unsigned comp_id, - pj_uint32_t options, - const pj_sockaddr_in *addr); - -/** - * Manually add a candidate (transport address alias) for the specified - * component. Normally application shouldn't need to use this function, - * as candidates will be added automatically when component is created - * with #pj_ice_strans_create_comp(). - * - * @param ice_st ICE stream transport. - * @param comp_id The component ID. - * @param type The candidate type. - * @param local_pref The local preference for this candidate - * (typically the value is 65535). - * @param addr The candidate address. - * @param set_default Set to non-zero to make this candidate the - * default candidate for this component. - * - * @return PJ_SUCCESS, or the appropriate error code. - */ -PJ_DECL(pj_status_t) pj_ice_strans_add_cand(pj_ice_strans *ice_st, - unsigned comp_id, - pj_ice_cand_type type, - pj_uint16_t local_pref, - const pj_sockaddr_in *addr, - pj_bool_t set_default); - -/** - * Get the status of components in the ICE stream transports. Since - * some IP address candidates have to be obtained asynchronously (for - * example, the STUN reflexive or relay candidate), application can - * use this function to know whether the address resolution has - * completed. - * - * @param ice_st The ICE stream transport. - * - * @return PJ_SUCCESS if all candidates have been resolved - * successfully, PJ_EPENDING if transport resolution - * is still in progress, or other status on failure. - */ -PJ_DECL(pj_status_t) pj_ice_strans_get_comps_status(pj_ice_strans *ice_st); /** * Initialize the ICE session in the ICE stream transport. + * When application is about to send an offer containing ICE capability, + * or when it receives an offer containing ICE capability, it must + * call this function to initialize the internal ICE session. This would + * register all transport address aliases for each component to the ICE + * session as candidates. Then application can enumerate all local + * candidates by calling #pj_ice_strans_enum_cands(), and encode these + * candidates in the SDP to be sent to remote agent. * * @param ice_st The ICE stream transport. * @param role ICE role. @@ -560,10 +349,10 @@ PJ_DECL(pj_status_t) pj_ice_strans_init_ice(pj_ice_strans *ice_st, const pj_str_t *local_passwd); /** - * Enumerate the local candidates. This function can only be called - * after the ICE session has been created in the ICE stream transport. + * Enumerate the local candidates for the specified component. * * @param ice_st The ICE stream transport. + * @param comp_id Component ID. * @param count On input, it specifies the maximum number of * elements. On output, it will be filled with * the number of candidates copied to the @@ -573,38 +362,113 @@ PJ_DECL(pj_status_t) pj_ice_strans_init_ice(pj_ice_strans *ice_st, * @return PJ_SUCCESS, or the appropriate error code. */ PJ_DECL(pj_status_t) pj_ice_strans_enum_cands(pj_ice_strans *ice_st, + unsigned comp_id, unsigned *count, pj_ice_sess_cand cand[]); /** + * Get the default candidate for the specified component. When this + * function is called before ICE negotiation completes, the default + * candidate is selected according to local preference criteria. When + * this function is called after ICE negotiation completes, the + * default candidate is the candidate that forms the valid pair. + * + * @param ice_st The ICE stream transport. + * @param comp_id Component ID. + * @param cand Pointer to receive the default candidate + * information. + */ +PJ_DECL(pj_status_t) pj_ice_strans_get_def_cand(pj_ice_strans *ice_st, + unsigned comp_id, + pj_ice_sess_cand *cand); + +/** + * Get the current ICE role. ICE session must have been initialized + * before this function can be called. + * + * @param ice_st The ICE stream transport. + * + * @return Current ICE role. + */ +PJ_DECL(pj_ice_sess_role) pj_ice_strans_get_role(pj_ice_strans *ice_st); + + +/** + * Change session role. This happens for example when ICE session was + * created with controlled role when receiving an offer, but it turns out + * that the offer contains "a=ice-lite" attribute when the SDP gets + * inspected. ICE session must have been initialized before this function + * can be called. + * + * @param ice_st The ICE stream transport. + * @param new_role The new role to be set. + * + * @return PJ_SUCCESS on success, or the appropriate error. + */ +PJ_DECL(pj_status_t) pj_ice_strans_change_role(pj_ice_strans *ice_st, + pj_ice_sess_role new_role); + + +/** * Start ICE connectivity checks. This function can only be called - * after the ICE session has been created in the ICE stream transport. + * after the ICE session has been created in the ICE stream transport + * with #pj_ice_strans_init_ice(). * - * This function will pair the local and remote candidates to create - * check list. Once the check list is created and sorted based on the - * priority, ICE periodic checks will be started. This function will - * return immediately, and application will be notified about the - * connectivity check status in the callback. + * This function must be called once application has received remote + * candidate list (typically from the remote SDP). This function pairs + * local candidates with remote candidates, and starts ICE connectivity + * checks. The ICE session/transport will then notify the application + * via the callback when ICE connectivity checks completes, either + * successfully or with failure. * * @param ice_st The ICE stream transport. * @param rem_ufrag Remote ufrag, as seen in the SDP received from * the remote agent. * @param rem_passwd Remote password, as seen in the SDP received from * the remote agent. - * @param rem_cand_cnt Number of remote candidates. - * @param rem_cand Remote candidate array. + * @param rcand_cnt Number of remote candidates in the array. + * @param rcand Remote candidates array. * * @return PJ_SUCCESS, or the appropriate error code. */ -PJ_DECL(pj_status_t) -pj_ice_strans_start_ice( pj_ice_strans *ice_st, - const pj_str_t *rem_ufrag, - const pj_str_t *rem_passwd, - unsigned rem_cand_cnt, - const pj_ice_sess_cand rem_cand[]); +PJ_DECL(pj_status_t) pj_ice_strans_start_ice(pj_ice_strans *ice_st, + const pj_str_t *rem_ufrag, + const pj_str_t *rem_passwd, + unsigned rcand_cnt, + const pj_ice_sess_cand rcand[]); + +/** + * Retrieve the candidate pair that has been nominated and successfully + * checked for the specified component. If ICE negotiation is still in + * progress or it has failed, this function will return NULL. + * + * @param ice_st The ICE stream transport. + * @param comp_id Component ID. + * + * @return The valid pair as ICE checklist structure if the + * pair exist. + */ +PJ_DECL(const pj_ice_sess_check*) +pj_ice_strans_get_valid_pair(const pj_ice_strans *ice_st, + unsigned comp_id); /** - * Stop and destroy the ICE session inside this media transport. + * Stop and destroy the ICE session inside this media transport. Application + * needs to call this function once the media session is over (the call has + * been disconnected). + * + * Application MAY reuse this ICE stream transport for subsequent calls. + * In this case, it must call #pj_ice_strans_stop_ice() when the call is + * disconnected, and reinitialize the ICE stream transport for subsequent + * call with #pj_ice_strans_init_ice()/#pj_ice_strans_start_ice(). In this + * case, the ICE stream transport will maintain the internal sockets and + * continue to send STUN keep-alive packets and TURN Refresh request to + * keep the NAT binding/TURN allocation open and to detect change in STUN + * mapped address. + * + * If application does not want to reuse the ICE stream transport for + * subsequent calls, it must call #pj_ice_strans_destroy() to destroy the + * ICE stream transport altogether. * * @param ice_st The ICE stream transport. * @@ -614,11 +478,16 @@ PJ_DECL(pj_status_t) pj_ice_strans_stop_ice(pj_ice_strans *ice_st); /** - * Send outgoing packet using this transport. If ICE checks have not - * produced a valid check for the specified component ID, this function - * send to the destination address. Otherwise it will send the packet to - * remote destination using the nominated local candidate as have been checked - * previously. + * Send outgoing packet using this transport. + * Application can send data (normally RTP or RTCP packets) at any time + * by calling this function. This function takes a destination + * address as one of the arguments, and this destination address should + * be taken from the default transport address of the component (that is + * the address in SDP c= and m= lines, or in a=rtcp attribute). + * If ICE negotiation is in progress, this function will send the data + * to the destination address. Otherwise if ICE negotiation has completed + * successfully, this function will send the data to the nominated remote + * address, as negotiated by ICE. * * @param ice_st The ICE stream transport. * @param comp_id Component ID. diff --git a/pjnath/include/pjnath/nat_detect.h b/pjnath/include/pjnath/nat_detect.h index a4bc5fec..53fcceec 100644 --- a/pjnath/include/pjnath/nat_detect.h +++ b/pjnath/include/pjnath/nat_detect.h @@ -32,7 +32,6 @@ PJ_BEGIN_DECL /** * @defgroup PJNATH_NAT_DETECT NAT Classification/Detection Tool * @brief NAT Classification/Detection Tool - * @ingroup PJNATH_ICE * @{ * * This module provides one function to perform NAT classification and diff --git a/pjnath/include/pjnath/stun_config.h b/pjnath/include/pjnath/stun_config.h index d724ed9c..eba1fce0 100644 --- a/pjnath/include/pjnath/stun_config.h +++ b/pjnath/include/pjnath/stun_config.h @@ -25,6 +25,8 @@ */ #include <pjnath/stun_msg.h> +#include <pj/assert.h> +#include <pj/errno.h> #include <pj/string.h> @@ -103,6 +105,17 @@ PJ_INLINE(void) pj_stun_config_init(pj_stun_config *cfg, /** + * 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; +} + + +/** * @} */ diff --git a/pjnath/include/pjnath/stun_msg.h b/pjnath/include/pjnath/stun_msg.h index 7c3805ea..e293f6fe 100644 --- a/pjnath/include/pjnath/stun_msg.h +++ b/pjnath/include/pjnath/stun_msg.h @@ -34,8 +34,8 @@ PJ_BEGIN_DECL /* **************************************************************************/ /** * @defgroup PJNATH_STUN_MSG STUN Message Representation and Parsing - * @brief Low-level representation and parsing of STUN messages. * @ingroup PJNATH_STUN + * @brief Low-level representation and parsing of STUN messages. * @{ */ @@ -955,9 +955,8 @@ typedef struct pj_stun_uint_attr pj_stun_req_addr_type; /** * This describes the TURN REQUESTED-PROPS attribute, encoded as * STUN 32bit integer attribute. Few macros are provided to manipulate - * the values in this attribute: #PJ_STUN_GET_RPP_BITS(), - * #PJ_STUN_SET_RPP_BITS(), #PJ_STUN_GET_RPP_PORT(), and - * #PJ_STUN_SET_RPP_PORT(). + * the values in this attribute: #PJ_STUN_GET_PROP_TYPE(), and + * #PJ_STUN_SET_PROP_TYPE(). * * This attribute allows the client to request certain properties for * the relayed transport address that is allocated by the server. The @@ -1164,7 +1163,7 @@ enum pj_stun_decode_options * Disable FINGERPRINT verification. This option can be used when calling * #pj_stun_msg_check() and #pj_stun_msg_decode() to disable the * verification of FINGERPRINT, for example when the STUN usage says when - * FINGERPRINT mechanism shall not * be used. + * FINGERPRINT mechanism shall not be used. */ PJ_STUN_NO_FINGERPRINT_CHECK = 8 }; @@ -1292,7 +1291,7 @@ PJ_DECL(pj_status_t) pj_stun_msg_add_attr(pj_stun_msg *msg, * value, if these attributes are present in the message. * * If application wants to apply credential to the message, it MUST - * include a blank MESSAGE-INTEGRITY attribute in the message, as the + * include a blank MESSAGE-INTEGRITY attribute in the message as the * last attribute or the attribute before FINGERPRINT. This function will * calculate the HMAC digest from the message using the supplied key in * the parameter. The key should be set to the password if short term @@ -1320,10 +1319,10 @@ PJ_DECL(pj_status_t) pj_stun_msg_add_attr(pj_stun_msg *msg, */ PJ_DECL(pj_status_t) pj_stun_msg_encode(pj_stun_msg *msg, pj_uint8_t *pkt_buf, - unsigned buf_size, + pj_size_t buf_size, unsigned options, const pj_str_t *key, - unsigned *p_msg_len); + pj_size_t *p_msg_len); /** * Check that the PDU is potentially a valid STUN message. This function @@ -1345,7 +1344,7 @@ PJ_DECL(pj_status_t) pj_stun_msg_encode(pj_stun_msg *msg, * message. */ PJ_DECL(pj_status_t) pj_stun_msg_check(const pj_uint8_t *pdu, - unsigned pdu_len, unsigned options); + pj_size_t pdu_len, unsigned options); /** @@ -1371,10 +1370,10 @@ PJ_DECL(pj_status_t) pj_stun_msg_check(const pj_uint8_t *pdu, */ PJ_DECL(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool, const pj_uint8_t *pdu, - unsigned pdu_len, + pj_size_t pdu_len, unsigned options, pj_stun_msg **p_msg, - unsigned *p_parsed_len, + pj_size_t *p_parsed_len, pj_stun_msg **p_response); /** diff --git a/pjnath/include/pjnath/stun_session.h b/pjnath/include/pjnath/stun_session.h index 821e765b..896a2b58 100644 --- a/pjnath/include/pjnath/stun_session.h +++ b/pjnath/include/pjnath/stun_session.h @@ -213,6 +213,7 @@ struct pj_stun_rx_data */ struct pj_stun_tx_data { + /** PJLIB list interface */ PJ_DECL_LIST_MEMBER(struct pj_stun_tx_data); pj_pool_t *pool; /**< Pool. */ @@ -240,6 +241,21 @@ struct pj_stun_tx_data /** + * 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. @@ -258,11 +274,16 @@ PJ_DECL(pj_status_t) pj_stun_session_create(pj_stun_config *cfg, pj_stun_session **p_sess); /** - * Destroy the STUN session. + * 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); @@ -333,6 +354,14 @@ PJ_DECL(pj_status_t) pj_stun_session_set_server_name(pj_stun_session *sess, 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); /** * Create a STUN request message. After the message has been successfully @@ -381,7 +410,7 @@ PJ_DECL(pj_status_t) pj_stun_session_create_ind(pj_stun_session *sess, * call. * * @param sess The STUN session instance. - * @param req The STUN request where the response is to be created. + * @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 @@ -432,6 +461,9 @@ PJ_DECL(pj_status_t) pj_stun_session_create_res(pj_stun_session *sess, * 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, @@ -449,7 +481,7 @@ PJ_DECL(pj_status_t) pj_stun_session_send_msg(pj_stun_session *sess, * * @param sess The STUN session instance. * @param rdata The STUN request message to be responded. - * @param err_code Error code to be set in the response, if error response + * @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. @@ -472,6 +504,9 @@ PJ_DECL(pj_status_t) pj_stun_session_send_msg(pj_stun_session *sess, * @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, @@ -496,6 +531,9 @@ PJ_DECL(pj_status_t) pj_stun_session_respond(pj_stun_session *sess, * 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, @@ -511,6 +549,9 @@ PJ_DECL(pj_status_t) pj_stun_session_cancel_req(pj_stun_session *sess, * @param tdata The request message previously sent. * * @return PJ_SUCCESS on success, or the appropriate error. + * This function will return PJNATH_ESTUNDESTROYED if + * application has destroyed the session in \a on_send_msg() + * callback. */ PJ_DECL(pj_status_t) pj_stun_session_retransmit_req(pj_stun_session *sess, pj_stun_tx_data *tdata); @@ -548,6 +589,9 @@ PJ_DECL(pj_status_t) pj_stun_session_retransmit_req(pj_stun_session *sess, * @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, diff --git a/pjnath/include/pjnath/stun_sock.h b/pjnath/include/pjnath/stun_sock.h new file mode 100644 index 00000000..a5ac7f69 --- /dev/null +++ b/pjnath/include/pjnath/stun_sock.h @@ -0,0 +1,403 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJNATH_STUN_SOCK_H__ +#define __PJNATH_STUN_SOCK_H__ + +/** + * @file stun_sock.h + * @brief STUN aware socket transport + */ +#include <pjnath/stun_config.h> +#include <pjlib-util/resolver.h> +#include <pj/ioqueue.h> +#include <pj/sock.h> + + +PJ_BEGIN_DECL + + +/** + * @defgroup PJNATH_STUN_SOCK STUN aware socket transport + * @brief STUN aware socket transport + * @ingroup PJNATH_STUN + * @{ + * The STUN transport provides asynchronous UDP like socket transport + * with the additional capability to query the publicly mapped transport + * address (using STUN resolution), to refresh the NAT binding, and to + * demultiplex internal STUN messages from application data (the + * application data may be a STUN message as well). + */ + +/** + * 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, + +} pj_stun_sock_op; + + +/** + * This structure contains callbacks that will be called by the STUN + * transport to notify application about various events. + */ +typedef struct pj_stun_sock_cb +{ + /** + * Notification when incoming packet has been received. + * + * @param stun_sock The STUN transport. + * @param data The packet. + * @param data_len Length of the packet. + * @param src_addr The source address of the packet. + * @param addr_len The length of the source address. + * + * @return Application should normally return PJ_TRUE to let + * the STUN transport continue its operation. However + * it must return PJ_FALSE if it has destroyed the + * STUN transport in this callback. + */ + pj_bool_t (*on_rx_data)(pj_stun_sock *stun_sock, + void *pkt, + unsigned pkt_len, + const pj_sockaddr_t *src_addr, + unsigned addr_len); + + /** + * Notifification when asynchronous send operation has completed. + * + * @param stun_sock The STUN transport. + * @param send_key The send operation key that was given in + * #pj_stun_sock_sendto(). + * @param sent If value is positive non-zero it indicates the + * number of data sent. When the value is negative, + * it contains the error code which can be retrieved + * by negating the value (i.e. status=-sent). + * + * @return Application should normally return PJ_TRUE to let + * the STUN transport continue its operation. However + * it must return PJ_FALSE if it has destroyed the + * STUN transport in this callback. + */ + pj_bool_t (*on_data_sent)(pj_stun_sock *stun_sock, + pj_ioqueue_op_key_t *send_key, + pj_ssize_t sent); + + /** + * Notification when the status of the STUN transport has changed. This + * callback may be called for the following conditions: + * - the first time the publicly mapped address has been resolved from + * the STUN server, this callback will be called with \a op argument + * set to PJ_STUN_SOCK_BINDING_OP \a status argument set to + * PJ_SUCCESS. + * - anytime when the transport has detected that the publicly mapped + * address has changed, this callback will be called with \a op + * argument set to PJ_STUN_SOCK_KEEP_ALIVE_OP and \a status + * argument set to PJ_SUCCESS. On this case and the case above, + * application will get the resolved public address in the + * #pj_stun_sock_info structure. + * - for any terminal error (such as STUN time-out, DNS resolution + * failure, or keep-alive failure), this callback will be called + * with the \a status argument set to non-PJ_SUCCESS. + * + * @param stun_sock The STUN transport. + * @param op The operation that triggers the callback. + * @param status The status. + * + * @return Must return PJ_FALSE if it has destroyed the + * STUN transport in this callback. Application should + * normally destroy the socket and return PJ_FALSE + * upon encountering terminal error, otherwise it + * should return PJ_TRUE to let the STUN socket operation + * continues. + */ + pj_bool_t (*on_status)(pj_stun_sock *stun_sock, + pj_stun_sock_op op, + pj_status_t status); + +} pj_stun_sock_cb; + + +/** + * This structure contains information about the STUN transport. Application + * may query this information by calling #pj_stun_sock_get_info(). + */ +typedef struct pj_stun_sock_info +{ + /** + * The bound address of the socket. + */ + pj_sockaddr bound_addr; + + /** + * IP address of the STUN server. + */ + pj_sockaddr srv_addr; + + /** + * The publicly mapped address. It may contain zero address when the + * mapped address has not been resolved. Application may query whether + * this field contains valid address with pj_sockaddr_has_addr(). + */ + pj_sockaddr mapped_addr; + + /** + * Number of interface address aliases. The interface address aliases + * are list of all interface addresses in this host. + */ + unsigned alias_cnt; + + /** + * Array of interface address aliases. + */ + pj_sockaddr aliases[PJ_ICE_ST_MAX_CAND]; + +} pj_stun_sock_info; + + +/** + * This describe the settings to be given to the STUN transport during its + * creation. Application should initialize this structure by calling + * #pj_stun_sock_cfg_default(). + */ +typedef struct pj_stun_sock_cfg +{ + /** + * Packet buffer size. Default value is PJ_STUN_SOCK_PKT_LEN. + */ + unsigned max_pkt_size; + + /** + * Specify the number of simultaneous asynchronous read operations to + * be invoked to the ioqueue. Having more than one read operations will + * increase performance on multiprocessor systems since the application + * will be able to process more than one incoming packets simultaneously. + * Default value is 1. + */ + unsigned async_cnt; + + /** + * Specify the interface where the socket should be bound to. If the + * address is zero, socket will be bound to INADDR_ANY. If the address + * is non-zero, socket will be bound to this address only, and the + * transport will have only one address alias (the \a alias_cnt field + * in #pj_stun_sock_info structure. + */ + pj_sockaddr bound_addr; + + /** + * Specify the STUN keep-alive duration, in seconds. The STUN transport + * does keep-alive by sending STUN Binding request to the STUN server. + * If this value is zero, the PJ_STUN_KEEP_ALIVE_SEC value will be used. + * If the value is negative, it will disable STUN keep-alive. + */ + int ka_interval; + +} 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. + * + * @restun PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. + */ +PJ_DECL(pj_status_t) pj_stun_sock_create(pj_stun_config *stun_cfg, + const char *name, + int af, + const pj_stun_sock_cb *cb, + const pj_stun_sock_cfg *cfg, + void *user_data, + pj_stun_sock **p_sock); + + +/** + * Start the STUN transport. This will start the DNS SRV resolution for + * the STUN server (if desired), and once the server is resolved, STUN + * Binding request will be sent to resolve the publicly mapped address. + * Once the initial STUN Binding response is received, the keep-alive + * timer will be started. + * + * @param stun_sock The STUN transport instance. + * @param domain The domain, hostname, or IP address of the TURN + * server. When this parameter contains domain name, + * the \a resolver parameter must be set to activate + * DNS SRV resolution. + * @param default_port The default STUN port number to use when DNS SRV + * resolution is not used. If DNS SRV resolution is + * used, the server port number will be set from the + * DNS SRV records. The recommended value for this + * parameter is PJ_STUN_PORT. + * @param resolver If this parameter is not NULL, then the \a domain + * parameter will be first resolved with DNS SRV and + * then fallback to using DNS A/AAAA resolution when + * DNS SRV resolution fails. If this parameter is + * NULL, the \a domain parameter will be resolved as + * hostname. + * + * @return PJ_SUCCESS if the operation has been successfully + * queued, or the appropriate error code on failure. + * When this function returns PJ_SUCCESS, the final + * result of the allocation process will be notified + * to application in \a on_state() callback. + */ +PJ_DECL(pj_status_t) pj_stun_sock_start(pj_stun_sock *stun_sock, + const pj_str_t *domain, + pj_uint16_t default_port, + pj_dns_resolver *resolver); + +/** + * Destroy the STUN transport. + * + * @param sock The STUN transport socket. + * + * @restun 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. + * + * @restun 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. + * + * @restun The user/application data. + */ +PJ_DECL(void*) pj_stun_sock_get_user_data(pj_stun_sock *stun_sock); + + +/** + * Get the STUN transport info. The transport info contains, among other + * things, the allocated relay address. + * + * @param stun_sock The STUN transport instance. + * @param info Pointer to be filled with STUN transport info. + * + * @restun 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 op_key Optional send key for sending the packet down to + * the ioqueue. This value will be given back to + * \a on_data_sent() callback + * @param pkt The data/packet to be sent to peer. + * @param pkt_len Length of the data. + * @param flag pj_ioqueue_sendto() flag. + * @param dst_addr The remote address. + * @param addr_len Length of the address. + * + * @return PJ_SUCCESS if data has been sent immediately, or + * PJ_EPENDING if data cannot be sent immediately. In + * this case the \a on_data_sent() callback will be + * called when data is actually sent. Any other return + * value indicates error condition. + */ +PJ_DECL(pj_status_t) pj_stun_sock_sendto(pj_stun_sock *stun_sock, + pj_ioqueue_op_key_t *send_key, + const void *pkt, + unsigned pkt_len, + unsigned flag, + const pj_sockaddr_t *dst_addr, + unsigned addr_len); + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJNATH_STUN_SOCK_H__ */ + diff --git a/pjnath/include/pjnath/stun_transaction.h b/pjnath/include/pjnath/stun_transaction.h index c17bc359..842c8145 100644 --- a/pjnath/include/pjnath/stun_transaction.h +++ b/pjnath/include/pjnath/stun_transaction.h @@ -89,7 +89,9 @@ typedef struct pj_stun_tsx_cb * @param pkt_size Size of the STUN packet. * * @return If return value of the callback is not PJ_SUCCESS, - * the transaction will fail. + * 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, @@ -161,7 +163,8 @@ pj_stun_client_tsx_schedule_destroy(pj_stun_client_tsx *tsx, * * @param tsx The STUN transaction. * - * @return PJ_SUCCESS on success, or the appropriate error code. + * @return PJ_SUCCESS on success or PJ_EINVAL if the parameter + * is NULL. */ PJ_DECL(pj_status_t) pj_stun_client_tsx_destroy(pj_stun_client_tsx *tsx); @@ -214,7 +217,10 @@ PJ_DECL(void*) pj_stun_client_tsx_get_data(pj_stun_client_tsx *tsx); * @param pkt The STUN packet to send. * @param pkt_len Length of STUN packet. * - * @return PJ_SUCCESS on success or the appropriate error code. + * @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, @@ -228,7 +234,10 @@ PJ_DECL(pj_status_t) pj_stun_client_tsx_send_msg(pj_stun_client_tsx *tsx, * * @param tsx The STUN client transaction instance. * - * @return PJ_SUCCESS on success or the appropriate error code. + * @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); diff --git a/pjnath/include/pjnath/turn_session.h b/pjnath/include/pjnath/turn_session.h index 2c10387b..73be679c 100644 --- a/pjnath/include/pjnath/turn_session.h +++ b/pjnath/include/pjnath/turn_session.h @@ -29,12 +29,25 @@ PJ_BEGIN_DECL +/** + * @defgroup PJNATH_TURN TURN Client Library + */ + + /* **************************************************************************/ /** - * @defgroup PJNATH_TURN_SESSION TURN client session + * @defgroup PJNATH_TURN_SESSION Transport independent TURN client session * @brief Transport independent TURN client session - * @ingroup PJNATH_STUN + * @ingroup PJNATH_TURN * @{ + * + * This module describes the transport independent TURN client session. This + * interface is provided for implementors of a TURN client transport, and + * application usually will want to use \ref PJNATH_TURN_SOCK instead. + * + * The transport independent TURN client session is created to facilitate + * the creation of different types of transports between the client and the + * TURN server. */ /** @@ -43,18 +56,6 @@ PJ_BEGIN_DECL typedef struct pj_turn_session pj_turn_session; -#define PJ_TURN_INVALID_CHANNEL 0xFFFF -#define PJ_TURN_CHANNEL_MIN 0x4000 -#define PJ_TURN_CHANNEL_MAX 0xFFFE /* inclusive */ -#define PJ_TURN_NO_TIMEOUT ((long)0x7FFFFFFF) -#define PJ_TURN_MAX_PKT_LEN 3000 -#define PJ_TURN_PERM_TIMEOUT 300 /* Must be greater than REFRESH_SEC_BEFORE */ -#define PJ_TURN_CHANNEL_TIMEOUT 600 /* Must be greater than REFRESH_SEC_BEFORE */ -#define PJ_TURN_REFRESH_SEC_BEFORE 60 -#define PJ_TURN_KEEP_ALIVE_SEC 15 -#define PJ_TURN_PEER_HTABLE_SIZE 8 - - /** * 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 @@ -133,14 +134,21 @@ typedef enum pj_turn_state_t } pj_turn_state_t; -/* ChannelData header */ +#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; - pj_uint16_t length; + 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. @@ -151,18 +159,33 @@ typedef struct pj_turn_session_cb * This callback will be called by the TURN session whenever it * needs to send outgoing message. Since the TURN session doesn't * have a socket on its own, this callback must be implemented. + * + * @param sess The TURN session. + * @param pkt The packet/data to be sent. + * @param pkt_len Length of the packet/data. + * @param dst_addr Destination address of the packet. + * @param addr_len Length of the destination address. + * + * @return The callback should return the status of the + * send operation. */ pj_status_t (*on_send_pkt)(pj_turn_session *sess, const pj_uint8_t *pkt, unsigned pkt_len, const pj_sockaddr_t *dst_addr, - unsigned dst_addr_len); + unsigned addr_len); /** * Notification when peer address has been bound successfully to * a channel number. * - * This callback is optional. + * 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, @@ -173,10 +196,16 @@ typedef struct pj_turn_session_cb * Notification when incoming data has been received, either through * Data indication or ChannelData message from the TURN server. * - * This callback is optional. + * @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, - const pj_uint8_t *pkt, + void *pkt, unsigned pkt_len, const pj_sockaddr_t *peer_addr, unsigned addr_len); @@ -185,26 +214,50 @@ typedef struct pj_turn_session_cb * 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, + void (*on_state)(pj_turn_session *sess, + pj_turn_state_t old_state, pj_turn_state_t new_state); } pj_turn_session_cb; /** - * Allocate parameter. + * 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. + */ int bandwidth; + + /** + * The requested LIFETIME. Default is zero to not request any + * explicit allocation lifetime. + */ int lifetime; + + /** + * If set to non-zero, the TURN session will periodically send blank + * Send Indication every PJ_TURN_KEEP_ALIVE_SEC to refresh local + * NAT bindings. Default is zero. + */ int ka_interval; + } pj_turn_alloc_param; /** - * TURN session info. + * This structure describes TURN session info. */ typedef struct pj_turn_session_info { @@ -214,14 +267,14 @@ typedef struct pj_turn_session_info pj_turn_state_t state; /** - * Type of connection to the TURN server. + * Last error (if session was terminated because of error) */ - pj_turn_tp_type tp_type; + pj_status_t last_status; /** - * The relay address + * Type of connection to the TURN server. */ - pj_sockaddr relay_addr; + pj_turn_tp_type conn_type; /** * The selected TURN server address. @@ -229,6 +282,16 @@ typedef struct pj_turn_session_info 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; @@ -237,67 +300,173 @@ typedef struct pj_turn_session_info /** - * Create default pj_turn_alloc_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 TURN state name. + * 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 TURN client session. + * Create a TURN session instance with the specified address family and + * connection type. Once TURN session instance is created, application + * must call pj_turn_session_alloc() to allocate a relay address in the TURN + * server. + * + * @param cfg The STUN configuration which contains among other + * things the ioqueue and timer heap instance for + * the operation of this session. + * @param name Optional name to identify this session in the log. + * @param af Address family of the client connection. Currently + * pj_AF_INET() and pj_AF_INET6() are supported. + * @param conn_type Connection type to the TURN server. + * @param cb Callback to receive events from the TURN session. + * @param options Option flags, currently this value must be zero. + * @param user_data Arbitrary application data to be associated with + * this transport. + * @param p_sess Pointer to receive the created instance of the + * TURN session. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. */ -PJ_DECL(pj_status_t) pj_turn_session_create(pj_stun_config *cfg, +PJ_DECL(pj_status_t) pj_turn_session_create(const pj_stun_config *cfg, const char *name, int af, pj_turn_tp_type conn_type, const pj_turn_session_cb *cb, - void *user_data, unsigned options, + void *user_data, pj_turn_session **p_sess); - /** - * Shutdown TURN client session. + * 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. + * 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. + * + * @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); /** - * Get TURN session info. + * 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); /** - * Re-assign user data. + * 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 user data. + * Retrieve the previously assigned user data associated with this TURN + * session. + * + * @param sess The TURN client session. + * + * @return The user/application data. */ PJ_DECL(void*) pj_turn_session_get_user_data(pj_turn_session *sess); + +/** + * Configure message logging. By default all flags are enabled. + * + * @param sess The TURN client session. + * @param flags Bitmask combination of #pj_stun_sess_msg_log_flag + */ +PJ_DECL(void) pj_turn_session_set_log(pj_turn_session *sess, + unsigned flags); + + /** - * Set the server or domain name of the server. + * 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, @@ -306,43 +475,120 @@ PJ_DECL(pj_status_t) pj_turn_session_set_server(pj_turn_session *sess, /** - * Set credential to be used by the session. + * 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); /** - * Create TURN allocation. + * 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); /** - * Relay data to the specified peer through the session. + * Send a data to the specified peer address via the TURN relay. This + * function will encapsulate the data as STUN Send Indication or TURN + * ChannelData packet and send the message to the TURN server. The TURN + * server then will send the data to the peer. + * + * The allocation (pj_turn_session_alloc()) must have been successfully + * created before application can relay any data. + * + * Since TURN session is transport independent, this function will + * ultimately call \a on_send_pkt() callback to request the application + * to actually send the packet containing the data to the TURN server. + * + * @param sess The TURN client session. + * @param pkt The data/packet to be sent to peer. + * @param pkt_len Length of the data. + * @param peer_addr The remote peer address (the ultimate destination + * of the data, and not the TURN server address). + * @param addr_len Length of the address. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. */ PJ_DECL(pj_status_t) pj_turn_session_sendto(pj_turn_session *sess, const pj_uint8_t *pkt, unsigned pkt_len, - const pj_sockaddr_t *addr, + const pj_sockaddr_t *peer_addr, unsigned addr_len); /** - * Bind a peer address to a channel number. + * 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. - * The packet maybe a STUN packet or ChannelData packet. + * 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. + * + * @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, - const pj_uint8_t *pkt, - unsigned pkt_len, - pj_bool_t is_datagram); + void *pkt, + unsigned pkt_len); /** diff --git a/pjnath/include/pjnath/turn_sock.h b/pjnath/include/pjnath/turn_sock.h index 91bf9e20..875f6313 100644 --- a/pjnath/include/pjnath/turn_sock.h +++ b/pjnath/include/pjnath/turn_sock.h @@ -16,8 +16,8 @@ * 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__ +#ifndef __PJNATH_TURN_SOCK_H__ +#define __PJNATH_TURN_SOCK_H__ /** * @file turn_sock.h @@ -31,46 +31,87 @@ PJ_BEGIN_DECL /* **************************************************************************/ /** - * @defgroup PJNATH_TURN_UDP TURN TCP client - * @brief TURN relay using TCP client as transport protocol - * @ingroup PJNATH_STUN + * @defgroup PJNATH_TURN_SOCK TURN client transport + * @brief Client transport utilizing TURN relay + * @ingroup PJNATH_TURN * @{ + * + * The TURN relay client transport can be used to relay data from the client + * to peer via a TURN relay. The application establishes TURN connection to + * the TURN server using UDP or TCP as the transport, then creates a relay + * address in the TURN server to be advertised to remote peer(s) as the + * transport address. When application sends data to a remote address via + * this transport, the data will be sent via the TURN relay, and vice versa. */ /** - * Opaque declaration for TURN TCP client. + * 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, either through - * Data indication or ChannelData message from the TURN server. + * 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). * - * This callback is mandatory. + * @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, - const pj_uint8_t *pkt, + void *pkt, unsigned pkt_len, const pj_sockaddr_t *peer_addr, unsigned addr_len); /** * Notification when TURN session state has changed. Application should - * implement this callback to know that the TURN session is no longer - * available. + * 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, + void (*on_state)(pj_turn_sock *turn_sock, + pj_turn_state_t old_state, pj_turn_state_t new_state); } pj_turn_sock_cb; /** - * Create. + * 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 options Option flags, currently this value must be zero. + * @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, @@ -81,53 +122,174 @@ PJ_DECL(pj_status_t) pj_turn_sock_create(pj_stun_config *cfg, pj_turn_sock **p_turn_sock); /** - * Destroy. + * 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); + /** - * Set user data. + * 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); + void *user_data); /** - * Get 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 info. + * 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); + 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); + /** - * Initialize. + * 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(pj_status_t) pj_turn_sock_init(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); +PJ_DECL(void) pj_turn_sock_set_log(pj_turn_sock *turn_sock, + unsigned flags); /** - * Send packet. + * 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); + +/** + * Send a data to the specified peer address via the TURN relay. This + * function will encapsulate the data as STUN Send Indication or TURN + * ChannelData packet and send the message to the TURN server. The TURN + * server then will send the data to the peer. + * + * The allocation (pj_turn_sock_alloc()) must have been successfully + * created before application can relay any data. + * + * @param turn_sock The TURN transport instance. + * @param pkt The data/packet to be sent to peer. + * @param pkt_len Length of the data. + * @param peer_addr The remote peer address (the ultimate destination + * of the data, and not the TURN server address). + * @param addr_len Length of the address. + * + * @return PJ_SUCCESS if the operation has been successful, + * or the appropriate error code on failure. */ PJ_DECL(pj_status_t) pj_turn_sock_sendto(pj_turn_sock *turn_sock, const pj_uint8_t *pkt, unsigned pkt_len, - const pj_sockaddr_t *addr, + const pj_sockaddr_t *peer_addr, unsigned addr_len); /** - * Bind a peer address to a channel number. + * 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); + const pj_sockaddr_t *peer, + unsigned addr_len); /** @@ -138,5 +300,5 @@ PJ_DECL(pj_status_t) pj_turn_sock_bind_channel(pj_turn_sock *turn_sock, PJ_END_DECL -#endif /* __PJNATH_turn_sock_H__ */ +#endif /* __PJNATH_TURN_SOCK_H__ */ diff --git a/pjnath/include/pjnath/types.h b/pjnath/include/pjnath/types.h index 88872dcb..66ab4cdd 100644 --- a/pjnath/include/pjnath/types.h +++ b/pjnath/include/pjnath/types.h @@ -35,6 +35,13 @@ 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. @@ -43,7 +50,7 @@ PJ_DECL(pj_status_t) pjnath_init(void); /** - * Display error to the log. + * Display error to the log. * * @param sender The sender name. * @param title Title message. @@ -67,167 +74,216 @@ PJ_END_DECL /* Doxygen documentation below: */ /** - * @mainpage PJNATH - Open Source ICE, STUN, and TURN Library - * - * \n - * This is the documentation of PJNATH, an Open Source library providing - * NAT traversal helper functionalities by using standard based protocols. - * - * \n - * \section PJNATH_STUN STUN Protocol Library - * - * Session Traversal Utilities (STUN, or previously known as Simple - * Traversal of User Datagram Protocol (UDP) Through Network Address - * Translators (NAT)s), is a lightweight protocol that serves as a tool for - * application protocols in dealing with NAT traversal. It allows a client - * to determine the IP address and port allocated to them by a NAT and to - * keep NAT bindings open. - * - * The PJNATH library provides facilities to support both the core - * <B>STUN-bis</B> specification and the <B>TURN</B> usage of STUN, - * as well as other STUN usages. Please see #pj_stun_attr_type for - * list of STUN attributes supported by this library. - * - * - * The following are some design principles that have been utilized - * when implementing the STUN library in PJNATH: - * - * - layered architecture, with \ref PJNATH_STUN_MSG as the lowest - * layer and \ref PJNATH_STUN_SESSION as the highest abstraction - * layer, to accommodate various usage scenario of the library. - * - * - no transport -- the STUN library is pretty much transport - * independent and all sending and receiving functionalities will - * have to be implemented by application or higher level - * abstraction (such as ICE). This helps facilitating an even - * more usage scenarios of the library. - * - * - common functionalities for both STUN client and server - * development. All STUN components can be used to develop both - * STUN client and STUN server application, and in fact, in ICE, - * both STUN client and server functionality exist in a single - * ICE session. - * - * \n - * - * \subsection PJNATH_STUN_ARCH STUN Library Organization - * - * \image html stun-arch.jpg "STUN Library Architecture" - * - * The STUN library is organized as follows: - * - * - for both client and server, the highest abstraction is - * \ref PJNATH_STUN_SESSION, which provides management of incoming - * and outgoing messages and association of STUN credential to - * a STUN session. - * - * - for client, the next layer below is \ref PJNATH_STUN_TRANSACTION, - * which manages retransmissions of STUN request. Server side STUN - * transaction is handled in \ref PJNATH_STUN_SESSION layer above. - * - * - \ref PJNATH_STUN_AUTH provides mechanism to verify STUN - * credential in incoming STUN messages. - * - * - the lowest layer of the library is \ref PJNATH_STUN_MSG. This layer - * provides STUN message representation, validation, parsing, - * encoding MESSAGE-INTEGRITY for outgoing messages, and - * debugging (dump to log) of STUN messages. - * - * All STUN library components are independent of any transports. - * Application gives incoming packet to the STUN components for processing, - * and it must supply the STUN components with callback to send outgoing - * messages. - * - * - * \n - * - * \subsection PJNATH_STUN_CLASSES PJNATH Class Diagram - * - * - * \image html UML-class-diagram.png "Class Diagram" - * - * TBD: write descriptions. - * - * \subsection PJNATH_STUN_USING Using STUN Library - * - * [The developers guide documentation can certainly be improved here] - * - * For a sample STUN and TURN client, please see <tt>pjstun-client</tt> - * project under <tt>pjnath/src</tt> directory. - * - * For a sample STUN and TURN server, please see <tt>pjstun-srv-test</tt> - * project under <tt>pjnath/src</tt> directory. - * - * - * \subsection PJNATH_STUN_REF STUN Reference - * - * References for STUN: - * - * - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-rfc3489bis-15.txt"> - * <B>draft-ietf-behave-rfc3489bis-15</b></A>: Session Traversal - * Utilities for (NAT) (STUN), - * - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-turn-07.txt"> - * <B>draft-ietf-behave-turn-07</B></A>: Obtaining Relay Addresses - * from Simple Traversal Underneath NAT (STUN) - * - Obsoleted: <A HREF="http://www.ietf.org/rfc/rfc3489.txt">RFC 3489</A>. - * - * \n - * - * \section PJNATH_ICE ICE Implementation - * - * Interactive Connectivity Establishment (ICE) is a standard based - * methodology for traversing Network Address Translator (NAT), and - * is described in - * <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-mmusic-ice-19.txt"> - * <B>draft-ietf-mmusic-ice-19.txt</B></A> draft. The PJNATH ICE - * implementation is aimed to provide a usable and generic ICE transports - * for different types of application, including but not limited to - * the usage of ICE in SIP/SDP offer/answer. - * - * - * \subsection PJNATH_ICE_ARCH ICE Library Organization - * - * \image html ice-arch.jpg "ICE Architecture" - * - * The ICE library is organized as follows: - * - * - the highest abstraction is ICE media transport, which maintains - * ICE stream transport and provides SDP translations to be used - * for SIP offer/answer exchanges. ICE media transport is part - * of PJMEDIA library. - * - * - higher in the hierarchy is \ref PJNATH_ICE_STREAM_TRANSPORT, - * which binds ICE with UDP sockets, and provides STUN binding - * and relay/TURN allocation for the sockets. This component can - * be directly used by application, although normally application - * should use the next higher abstraction since it provides - * SDP translations and better integration with other PJ libraries - * such as PJSIP and PJMEDIA. - * - * - the lowest layer is \ref PJNATH_ICE_SESSION, which provides - * ICE management and negotiation in a transport-independent way. - * This layer contains the state machines to perform ICE - * negotiation, and provides the most flexibility to control all - * aspects of ICE session. This layer normally is only usable for - * ICE implementors. - * - * \subsection PJNATH_ICE_USING Using the ICE Library - * - * For ICE implementation that has been integrated with socket transport, - * please see \ref PJNATH_ICE_STREAM_TRANSPORT_USING. - * - * For ICE implementation that has not been integrated with socket - * transport, please see \ref pj_ice_sess_using_sec. - * - * \subsection PJNATH_ICE_REF Reference - * - * References for ICE: - * - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-mmusic-ice-19.txt"> - * <B>draft-ietf-mmusic-ice-19.txt</B></A>: Interactive Connectivity - * Establishment (ICE): A Methodology for Network Address Translator - * (NAT) Traversal for Offer/Answer Protocols - */ +@mainpage PJNATH - Open Source ICE, STUN, and TURN Library + +\n +This is the documentation of PJNATH, an Open Source library providing +NAT traversal helper functionalities by using standard based protocols +such as STUN, TURN, and ICE. + +\n +\n + +\section lib_comps Library Components + +\subsection comp_stun STUN + +Session Traversal Utilities (STUN, or previously known as Simple +Traversal of User Datagram Protocol (UDP) Through Network Address +Translators (NAT)s), is a lightweight protocol that serves as a tool for +application protocols in dealing with NAT traversal. It allows a client +to determine the IP address and port allocated to them by a NAT and to +keep NAT bindings open. + +This version of PJNATH implements the following STUN-bis draft: +- <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-rfc3489bis-15.txt"> + <B>draft-ietf-behave-rfc3489bis-15</b></A>: Session Traversal + Utilities for (NAT) (STUN), + + +\subsection comp_turn TURN + +Traversal Using Relays around NAT (TURN) allows the host to control the +operation of the relay and to exchange packets with its peers using the relay. + +This version of PJNATH implements both TCP and UDP client transport and it +complies with the following TURN draft: + - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-turn-07.txt"> + <B>draft-ietf-behave-turn-07</B></A>: Obtaining Relay Addresses + from Simple Traversal Underneath NAT (STUN) + + +\subsection comp_ice ICE + +Interactive Connectivity Establishment (ICE) is a standard based +methodology for traversing Network Address Translator (NAT). This +implementation is aimed to provide a usable and generic ICE transports +for different types of application, including but not limited to +the usage of ICE in SIP/SDP offer/answer. + + +This version of PJNATH implements the following ICE draft: + - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-mmusic-ice-19.txt"> + <B>draft-ietf-mmusic-ice-19.txt</B></A> draft. The PJNATH ICE + + +\subsection comp_natck NAT Classification Utility + +The PJNATH library also provides NAT classification utility as +described in <A HREF="http://www.ietf.org/rfc/rfc3489.txt">RFC 3489</A>. +While the practice to detect the NAT type to assist NAT traversal +has been deprecated in favor of ICE, the information may still be +useful for troubleshooting purposes, hence the utility is provided. + + +\n +\n + +\section lib_org Library Organization + +The PJNATH library consists of many components with each providing +specific functionality that may or may not be of the interests of +applications (or application developers). This section attempts to +give brief overview on the components provided by PJNATH. + +The PJNATH components from the highest layer to the lower layer are +as follows. + + +\n + +\subsection user_comp High-level Transport Objects + +PJNATH library provides some high-level objects that may be used +by applications: + + +\subsubsection stun_sock STUN Transport + +The \ref PJNATH_STUN_SOCK provides asynchronous UDP like socket transport +with the additional capability to query the publicly mapped transport +address (using STUN resolution), to refresh the NAT binding, and to +demultiplex internal STUN messages from application data (the +application data may be a STUN message as well). + + +\subsubsection turn_sock TURN Client Transport + +The \ref PJNATH_TURN_SOCK may be used by the application to send and +receive data via TURN server. For more information please see the +documentation of \ref PJNATH_TURN_SOCK. + + +\subsubsection ice_strans ICE Stream Transport + +The \ref PJNATH_ICE_STREAM_TRANSPORT provides transport interface to +send and receive data through connection that is negotiated +with ICE protocol. The \ref PJNATH_ICE_STREAM_TRANSPORT naturally +contains both STUN Transport and \ref PJNATH_TURN_SOCK. + +The \ref PJNATH_ICE_STREAM_TRANSPORT interface is suitable for both +SIP or non-SIP use. For SIP use, application may prefer to use the +ICE media transport in PJMEDIA instead where it has been integrated +with the SDP offer and answer mechanism. + + +\subsubsection natck NAT Classification Utility + +PJNATH also provides \a PJNATH_NAT_DETECT to assist troubleshooting +of problems related to NAT traversal. + + + +\n + + +\subsection sessions Transport Independent Sessions Layer + +Right below the high level transports objects are the transport +independent sessions. These sessions don't have access to sockets, +so higher level objects (such as transports) must give incoming +packets to the sessions and provide callback to be called by +sessions to send outgoing packets. + + +\subsubsection ice_sess ICE Session + +The \ref PJNATH_ICE_SESSION is used by the \ref PJNATH_ICE_STREAM_TRANSPORT +and contains the actual logic of the ICE negotiation. + + +\subsubsection turn_sess TURN Session + +The \ref PJNATH_TURN_SESSION is used by the \ref PJNATH_TURN_SOCK +and it contains TURN protocol logic. Implementors may implement +other types of TURN client connection (such as TURN TLS client) +by utilizing this session. + + +\subsubsection stun_sess STUN Session + +The \ref PJNATH_STUN_SESSION manages STUN message exchange between +a client and server (or vice versa). It manages \ref PJNATH_STUN_TRANSACTION +for sending or receiving requests and \ref PJNATH_STUN_AUTH for both +both incoming and outgoing STUN messages. + +The \ref PJNATH_STUN_SESSION is naturally used by the \ref PJNATH_TURN_SESSION +and \ref PJNATH_ICE_SESSION + + +\n + +\subsection stun_tsx STUN Transaction Layer + +The \ref PJNATH_STUN_TRANSACTION is a thin layer to manage retransmission +of STUN requests. + + +\n + + +\subsection stun_msg STUN Messaging Layer + +At the very bottom of the PJNATH components is the \ref PJNATH_STUN_MSG +layer. The API contains various representation of STUN messaging components +and it provides API to encode and decode STUN messages. + + + +\n +\n + +\section class_dia Class Diagram + + +The following class diagram shows the interactions between objects in +PJNATH: + +\image html UML-class-diagram.png "Class Diagram" +\image latex UML-class-diagram.png "Class Diagram" + + + +\n +\n + +\section samples Sample Applications + + +Some sample applications have been provided with PJNATH, and it's available +under <tt>pjnath/src</tt> directory: + + - <b>pjturn-client</b>: this is a stand-alone, console based TURN client + application to be used as a demonstration for PJNATH TURN client + transport API and for simple testing against TURN server implementations. + The client supports both UDP and TCP connection to the TURN server. + + - <b>pjturn-srv</b>: this is a simple TURN server to be used for testing + purposes. It supports both UDP and TCP connections to the clients. + + +*/ /** * @defgroup PJNATH_STUN STUN Library |