diff options
author | Benny Prijono <bennylp@teluu.com> | 2006-10-08 12:39:34 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2006-10-08 12:39:34 +0000 |
commit | 36413704c1ff24a8e38e0fcf47c9a9c87621e71a (patch) | |
tree | 4393a2f84da0f02f8b1374b0e3ff29d4dce50fb1 /pjsip/include | |
parent | b1cdeda73284f461f15c68468369baf7556cb0e3 (diff) |
Major addition to support DNS SRV resolution in PJSIP:
- added DNS asynchronous/caching resolver engine in
PJLIB-UTIL (resolver.[hc])
- modified SIP resolver (sip_resolve.c) to properly
perform DNS SRV/A resolution when DNS resolution is
enabled.
- added dns_test.c in PJSIP-TEST for testing the SIP
resolver.
- added nameserver configuration in PJSUA-LIB
- added "--nameserver" option in PJSUA.
- updated project/Makefiles and doxygen documentation.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@753 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/include')
-rw-r--r-- | pjsip/include/pjsip/sip_config.h | 36 | ||||
-rw-r--r-- | pjsip/include/pjsip/sip_endpoint.h | 43 | ||||
-rw-r--r-- | pjsip/include/pjsip/sip_resolve.h | 193 | ||||
-rw-r--r-- | pjsip/include/pjsua-lib/pjsua.h | 14 |
4 files changed, 269 insertions, 17 deletions
diff --git a/pjsip/include/pjsip/sip_config.h b/pjsip/include/pjsip/sip_config.h index e4b402fb..420a2a01 100644 --- a/pjsip/include/pjsip/sip_config.h +++ b/pjsip/include/pjsip/sip_config.h @@ -199,6 +199,42 @@ #endif +/** + * This macro specifies whether full DNS resolution should be used. + * When enabled, #pjsip_resolve() will perform asynchronous DNS SRV and + * A (or AAAA, when IPv6 is supported) resolution to resolve the SIP + * domain. + * + * Note that even when this setting is enabled, asynchronous DNS resolution + * will only be done when application calls #pjsip_endpt_create_resolver(), + * configure the nameservers with #pj_dns_resolver_set_ns(), and configure + * the SIP endpoint's DNS resolver with #pjsip_endpt_set_resolver(). If + * these steps are not followed, the domain will be resolved with normal + * pj_gethostbyname() function. + * + * Turning off this setting will save the footprint by about 16KB, since + * it should also exclude dns.o and resolve.o from PJLIB-UTIL. + * + * Default: 1 (enabled) + */ +#ifndef PJSIP_HAS_RESOLVER +# define PJSIP_HAS_RESOLVER 1 +#endif + + +/** + * Maximum number of addresses returned by the resolver. The number here + * will slightly affect stack usage, since each entry will occupy about + * 32 bytes of stack memory. + * + * Default: 8 + */ +#ifndef PJSIP_MAX_RESOLVED_ADDRESSES +# define PJSIP_MAX_RESOLVED_ADDRESSES 8 +#endif + + + /* Endpoint. */ #define PJSIP_MAX_TIMER_COUNT (2*PJSIP_MAX_TSX_COUNT + 2*PJSIP_MAX_DIALOG_COUNT) #define PJSIP_POOL_LEN_ENDPT (4000) diff --git a/pjsip/include/pjsip/sip_endpoint.h b/pjsip/include/pjsip/sip_endpoint.h index aed4d8a2..6e166090 100644 --- a/pjsip/include/pjsip/sip_endpoint.h +++ b/pjsip/include/pjsip/sip_endpoint.h @@ -275,12 +275,51 @@ PJ_DECL(pj_status_t) pjsip_endpt_create_tdata( pjsip_endpoint *endpt, pjsip_tx_data **p_tdata); /** + * Create the DNS resolver instance. Application creates the DNS + * resolver instance, set the nameserver to be used by the DNS + * resolver, then set the DNS resolver to be used by the endpoint + * by calling #pjsip_endpt_set_resolver(). + * + * @param endpt The SIP endpoint instance. + * @param p_resv Pointer to receive the DNS resolver instance. + * + * @return PJ_SUCCESS on success, or the appropriate error + * code. + */ +PJ_DECL(pj_status_t) pjsip_endpt_create_resolver(pjsip_endpoint *endpt, + pj_dns_resolver **p_resv); + +/** + * Set DNS resolver to be used by the SIP resolver. Application can set + * the resolver instance to NULL to disable DNS resolution (perhaps + * temporarily). When DNS resolver is disabled, the endpoint will resolve + * hostnames with the normal pj_gethostbyname() function. + * + * @param endpt The SIP endpoint instance. + * @param resv The resolver instance to be used by the SIP + * endpoint. + * + * @return PJ_SUCCESS on success, or the appropriate error + * code. + */ +PJ_DECL(pj_status_t) pjsip_endpt_set_resolver(pjsip_endpoint *endpt, + pj_dns_resolver *resv); + +/** + * Get the DNS resolver being used by the SIP resolver. + * + * @param endpt The SIP endpoint instance. + * + * @return The DNS resolver instance currently being used + * by the SIP endpoint. + */ +PJ_DECL(pj_dns_resolver*) pjsip_endpt_get_resolver(pjsip_endpoint *endpt); + +/** * Asynchronously resolve a SIP target host or domain according to rule * specified in RFC 3263 (Locating SIP Servers). When the resolving operation * has completed, the callback will be called. * - * Note: at the moment we don't have implementation of RFC 3263 yet! - * * @param endpt The endpoint instance. * @param pool The pool to allocate resolver job. * @param target The target specification to be resolved. diff --git a/pjsip/include/pjsip/sip_resolve.h b/pjsip/include/pjsip/sip_resolve.h index 3ebface3..a71dd5b5 100644 --- a/pjsip/include/pjsip/sip_resolve.h +++ b/pjsip/include/pjsip/sip_resolve.h @@ -27,26 +27,141 @@ */ #include <pjsip/sip_types.h> +#include <pjlib-util/resolver.h> #include <pj/sock.h> PJ_BEGIN_DECL /** - * @defgroup PJSIP_RESOLVE Server Resolution + * @defgroup PJSIP_RESOLVE SIP SRV Server Resolution (RFC 3263 - Locating SIP Servers) * @ingroup PJSIP_TRANSPORT * @brief Framework to resolve SIP servers based on RFC 3263. * @{ - * This is the server resolution framework, which is modelled after - * RFC 3263 - Locating SIP Servers document. The server resolution + * \section PJSIP_RESOLVE_FEATURES Features + * + * This is the SIP server resolution framework, which is modelled after + * RFC 3263 - Locating SIP Servers document. The SIP server resolution * framework is asynchronous; callback will be called once the server * address has been resolved (successfully or with errors). + * + * \subsection PJSIP_RESOLVE_CONFORMANT Conformance to RFC 3263 + * + * The SIP server resolution framework is modelled after RFC 3263 (Locating + * SIP Servers) document, and it provides a single function (#pjsip_resolve()) + * to resolve a domain into actual IP addresses of the servers, by querying + * DNS SRV record and DNS A record where necessary. + * + * The #pjsip_resolve() function performs the server resolution according + * to RFC 3263 with some additional fallback mechanisms, as follows: + * - if the target name is an IP address, the callback will be called + * immediately with the IP address. If port number was specified, this + * port number will be used, otherwise the default port number for the + * transport will be used (5060 for TCP/UDP, 5061 for TLS) if the transport + * is specified. If the transport is not specified, UDP with port number + * 5060 will be used. + * - if target name is not an IP address but it contains port number, + * then the target name is resolved with DNS A (or AAAA, when IPv6 is + * supported in the future) query, and the port is taken from the + * port number argument. The callback will be called once the DNS A + * resolution completes. If the DNS A resolution returns multiple IP + * addresses, these IP addresses will be returned to the caller. + * - if target name is not an IP address and port number is not specified, + * DNS SRV resolution will be performed for the specified name and + * transport type (or UDP when transport is not specified), + * then followed by DNS A (or AAAA, when IPv6 is supported) + * resolution for each target in the SRV record. If DNS SRV + * resolution returns error, DNS A (or AAAA) resolution will be + * performed for the original target (it is assumed that the target domain + * does not support SRV records). Upon successful completion, + * application callback will be called with each IP address of the + * target selected based on the load-balancing and fail-over criteria + * below. + * + * The above server resolution procedure differs from RFC 3263 in these + * regards: + * - currently #pjsip_resolve() doesn't support DNS NAPTR record. + * - if transport is not specified, it is assumed to be UDP (the proper + * behavior is to query the NAPTR record, but we don't support this + * yet). + * + * + * \subsection PJSIP_SIP_RESOLVE_FAILOVER_LOADBALANCE Load-Balancing and Fail-Over + * + * When multiple targets are returned in the DNS SRV response, server entries + * are selected based on the following rule (which is described in RFC 2782): + * - targets will be sorted based on the priority first. + * - for targets with the same priority, #pjsip_resolve() will select + * only one target according to its weight. To select this one target, + * the function associates running-sum for all targets, and generates + * a random number between zero and the total running-sum (inclusive). + * The target selected is the first target with running-sum greater than + * or equal to this random number. + * + * The above procedure will select one target for each priority, allowing + * application to fail-over to the next target when the previous target fails. + * These targets are returned in the #pjsip_server_addresses structure + * argument of the callback. + * + * \subsection PJSIP_SIP_RESOLVE_SIP_FEATURES SIP SRV Resolver Features + * + * Some features of the SIP resolver: + * - DNS SRV entries are returned on sorted order based on priority + * to allow failover to the next appropriate server. + * - The procedure in RFC 2782 is used to select server with the same + * priority to load-balance the servers load. + * - A single function (#pjsip_resolve()) performs all server resolution + * works, from resolving the SRV records to getting the actual IP addresses + * of the servers with DNS A (or AAAA) resolution. + * - When multiple DNS SRV records are returned, parallel DNS A (or AAAA) + * queries will be issued simultaneously. + * - The PJLIB-UTIL DNS resolver provides additional functionality such as + * response caching, query aggregation, parallel nameservers, fallback + * nameserver, etc., which will be described below. + * + * + * \subsection PJSIP_RESOLVE_DNS_FEATURES DNS Resolver Features + * + * The PJSIP server resolution framework uses PJLIB-UTIL DNS resolver engine + * for performing the asynchronous DNS request. The PJLIB-UTIL DNS resolver + * has some useful features, such as: + * - queries are asynchronous with configurable timeout, + * - query aggregation to combine multiple pending queries to the same + * DNS target into a single DNS request (to save message round-trip and + * processing), + * - response caching with TTL negotiated between the minimum TTL found in + * the response and the maximum TTL allowed in the configuration, + * - multiple nameservers, with active nameserver is selected from nameserver + * which provides the best response time, + * - fallback nameserver, with periodic detection of which name servers are + * active or down. + * - etc. + * + * Please consult PJLIB-UTIL DNS resolver documentation for more details. + * + * + * \section PJSIP_RESOLVE_USING Using the Resolver + * + * To maintain backward compatibility, the resolver MUST be enabled manually. + * With the default settings, the resolver WILL NOT perform DNS SRV resolution, + * as it will just resolve the name with standard pj_gethostbyname() function. + * + * Application can enable the SRV resolver by creating the PJLIB-UTIL DNS + * resolver with #pjsip_endpt_create_resolver(), configure the + * nameservers of the PJLIB-UTIL DNS resolver object by calling + * pj_dns_resolver_set_ns() function, and pass the DNS resolver object to + * #pjsip_resolver_set_resolver() function. + * + * Once the resolver is set, it will be used automatically by PJSIP everytime + * PJSIP needs to send SIP request/response messages. + * + * + * \section PJSIP_RESOLVE_REFERENCE Reference + * + * Reference: + * - RFC 2782: A DNS RR for specifying the location of services (DNS SRV) + * - RFC 3263: Locating SIP Servers */ -/** - * Maximum number of addresses returned by the resolver. - */ -#define PJSIP_MAX_RESOLVED_ADDRESSES 8 - /** * The server addresses returned by the resolver. */ @@ -61,6 +176,12 @@ typedef struct pjsip_server_addresses /** Preferable transport to be used to contact this address. */ pjsip_transport_type_e type; + /** Server priority (the lower the higher the priority). */ + unsigned priority; + + /** Server weight (the higher the more load it can handle). */ + unsigned weight; + /** The server's address. */ pj_sockaddr addr; @@ -85,15 +206,56 @@ typedef void pjsip_resolver_callback(pj_status_t status, const struct pjsip_server_addresses *addr); /** - * Create resolver engine. + * Create SIP resolver engine. Note that this function is normally called + * internally by pjsip_endpoint instance. + * + * @param pf The Pool Factory. + * @param p_res Pointer to receive SIP resolver instance. + * + * @return PJ_SUCCESS when resolver can be successfully created. + */ +PJ_DECL(pj_status_t) pjsip_resolver_create(pj_pool_t *pool, + pjsip_resolver_t **p_res); + +/** + * Set the DNS resolver instance of the SIP resolver engine. Before the + * DNS resolver is set, the SIP resolver will use standard pj_gethostbyname() + * to resolve addresses. * - * @param pool The Pool. - * @return The resolver engine. + * Note that application normally will use #pjsip_endpt_set_resolver() instead + * since it does not normally have access to the SIP resolver instance. + * + * @param res The SIP resolver engine. + * @param dns_res The DNS resolver instance to be used by the SIP resolver. + * This argument can be NULL to reset the internal DNS + * instance. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjsip_resolver_set_resolver(pjsip_resolver_t *res, + pj_dns_resolver *dns_res); + + +/** + * Get the DNS resolver instance of the SIP resolver engine. + * + * Note that application normally will use #pjsip_endpt_get_resolver() instead + * since it does not normally have access to the SIP resolver instance. + * + * @param res The SIP resolver engine. + * + * @return The DNS resolver instance (may be NULL) */ -PJ_DECL(pjsip_resolver_t*) pjsip_resolver_create(pj_pool_t *pool); +PJ_DECL(pj_dns_resolver*) pjsip_resolver_get_resolver(pjsip_resolver_t *res); /** - * Destroy resolver engine. + * Destroy resolver engine. Note that this will also destroy the internal + * DNS resolver inside the engine. If application doesn't want the internal + * DNS resolver to be destroyed, it should set the internal DNS resolver + * to NULL before calling this function. + * + * Note that this function will normally called by the SIP endpoint instance + * when the SIP endpoint instance is destroyed. * * @param resolver The resolver. */ @@ -104,7 +266,8 @@ PJ_DECL(void) pjsip_resolver_destroy(pjsip_resolver_t *resolver); * specified in RFC 3263 (Locating SIP Servers). When the resolving operation * has completed, the callback will be called. * - * Note: at the moment we don't have implementation of RFC 3263 yet! + * Note that application normally will use #pjsip_endpt_resolve() instead + * since it does not normally have access to the SIP resolver instance. * * @param resolver The resolver engine. * @param pool The pool to allocate resolver job. @@ -114,7 +277,7 @@ PJ_DECL(void) pjsip_resolver_destroy(pjsip_resolver_t *resolver); */ PJ_DECL(void) pjsip_resolve( pjsip_resolver_t *resolver, pj_pool_t *pool, - pjsip_host_info *target, + const pjsip_host_info *target, void *token, pjsip_resolver_callback *cb); diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h index 9ded3f15..2b11df01 100644 --- a/pjsip/include/pjsua-lib/pjsua.h +++ b/pjsip/include/pjsua-lib/pjsua.h @@ -388,6 +388,20 @@ typedef struct pjsua_config unsigned thread_cnt; /** + * Number of nameservers. If no name server is configured, the SIP SRV + * resolution would be disabled, and domain will be resolved with + * standard pj_gethostbyname() function. + */ + unsigned nameserver_count; + + /** + * Array of nameservers to be used by the SIP resolver subsystem. + * The order of the name server specifies the priority (first name + * server will be used first, unless it is not reachable). + */ + pj_str_t nameserver[4]; + + /** * Number of outbound proxies in the array. */ unsigned outbound_proxy_cnt; |