summaryrefslogtreecommitdiff
path: root/pjsip/include
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2006-10-08 12:39:34 +0000
committerBenny Prijono <bennylp@teluu.com>2006-10-08 12:39:34 +0000
commit36413704c1ff24a8e38e0fcf47c9a9c87621e71a (patch)
tree4393a2f84da0f02f8b1374b0e3ff29d4dce50fb1 /pjsip/include
parentb1cdeda73284f461f15c68468369baf7556cb0e3 (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.h36
-rw-r--r--pjsip/include/pjsip/sip_endpoint.h43
-rw-r--r--pjsip/include/pjsip/sip_resolve.h193
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h14
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;