Alexandre Lision | 8af73cb | 2013-12-10 14:11:20 -0500 | [diff] [blame] | 1 | /* $Id$ */ |
| 2 | /* |
| 3 | * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) |
| 4 | * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; either version 2 of the License, or |
| 9 | * (at your option) any later version. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License |
| 17 | * along with this program; if not, write to the Free Software |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ |
| 20 | #ifndef __PJSIP_SIP_RESOLVE_H__ |
| 21 | #define __PJSIP_SIP_RESOLVE_H__ |
| 22 | |
| 23 | /** |
| 24 | * @file sip_resolve.h |
| 25 | * @brief |
| 26 | * This module contains the mechanism to resolve server address as specified by |
| 27 | * RFC 3263 - Locating SIP Servers |
| 28 | */ |
| 29 | |
| 30 | #include <pjsip/sip_types.h> |
| 31 | #include <pjlib-util/resolver.h> |
| 32 | #include <pj/sock.h> |
| 33 | |
| 34 | PJ_BEGIN_DECL |
| 35 | |
| 36 | /** |
| 37 | * @defgroup PJSIP_RESOLVE SIP SRV Server Resolution (RFC 3263 - Locating SIP Servers) |
| 38 | * @ingroup PJSIP_TRANSPORT |
| 39 | * @brief Framework to resolve SIP servers based on RFC 3263. |
| 40 | * @{ |
| 41 | * \section PJSIP_RESOLVE_FEATURES Features |
| 42 | * |
| 43 | * This is the SIP server resolution framework, which is modelled after |
| 44 | * RFC 3263 - Locating SIP Servers document. The SIP server resolution |
| 45 | * framework is asynchronous; callback will be called once the server |
| 46 | * address has been resolved (successfully or with errors). |
| 47 | * |
| 48 | * \subsection PJSIP_RESOLVE_CONFORMANT Conformance to RFC 3263 |
| 49 | * |
| 50 | * The SIP server resolution framework is modelled after RFC 3263 (Locating |
| 51 | * SIP Servers) document, and it provides a single function (#pjsip_resolve()) |
| 52 | * to resolve a domain into actual IP addresses of the servers, by querying |
| 53 | * DNS SRV record and DNS A record where necessary. |
| 54 | * |
| 55 | * The #pjsip_resolve() function performs the server resolution according |
| 56 | * to RFC 3263 with some additional fallback mechanisms, as follows: |
| 57 | * - if the target name is an IP address, the callback will be called |
| 58 | * immediately with the IP address. If port number was specified, this |
| 59 | * port number will be used, otherwise the default port number for the |
| 60 | * transport will be used (5060 for TCP/UDP, 5061 for TLS) if the transport |
| 61 | * is specified. If the transport is not specified, UDP with port number |
| 62 | * 5060 will be used. |
| 63 | * - if target name is not an IP address but it contains port number, |
| 64 | * then the target name is resolved with DNS A (or AAAA, when IPv6 is |
| 65 | * supported in the future) query, and the port is taken from the |
| 66 | * port number argument. The callback will be called once the DNS A |
| 67 | * resolution completes. If the DNS A resolution returns multiple IP |
| 68 | * addresses, these IP addresses will be returned to the caller. |
| 69 | * - if target name is not an IP address and port number is not specified, |
| 70 | * DNS SRV resolution will be performed for the specified name and |
| 71 | * transport type (or UDP when transport is not specified), |
| 72 | * then followed by DNS A (or AAAA, when IPv6 is supported) |
| 73 | * resolution for each target in the SRV record. If DNS SRV |
| 74 | * resolution returns error, DNS A (or AAAA) resolution will be |
| 75 | * performed for the original target (it is assumed that the target domain |
| 76 | * does not support SRV records). Upon successful completion, |
| 77 | * application callback will be called with each IP address of the |
| 78 | * target selected based on the load-balancing and fail-over criteria |
| 79 | * below. |
| 80 | * |
| 81 | * The above server resolution procedure differs from RFC 3263 in these |
| 82 | * regards: |
| 83 | * - currently #pjsip_resolve() doesn't support DNS NAPTR record. |
| 84 | * - if transport is not specified, it is assumed to be UDP (the proper |
| 85 | * behavior is to query the NAPTR record, but we don't support this |
| 86 | * yet). |
| 87 | * |
| 88 | * |
| 89 | * \subsection PJSIP_SIP_RESOLVE_FAILOVER_LOADBALANCE Load-Balancing and Fail-Over |
| 90 | * |
| 91 | * When multiple targets are returned in the DNS SRV response, server entries |
| 92 | * are selected based on the following rule (which is described in RFC 2782): |
| 93 | * - targets will be sorted based on the priority first. |
| 94 | * - for targets with the same priority, #pjsip_resolve() will select |
| 95 | * only one target according to its weight. To select this one target, |
| 96 | * the function associates running-sum for all targets, and generates |
| 97 | * a random number between zero and the total running-sum (inclusive). |
| 98 | * The target selected is the first target with running-sum greater than |
| 99 | * or equal to this random number. |
| 100 | * |
| 101 | * The above procedure will select one target for each priority, allowing |
| 102 | * application to fail-over to the next target when the previous target fails. |
| 103 | * These targets are returned in the #pjsip_server_addresses structure |
| 104 | * argument of the callback. |
| 105 | * |
| 106 | * \subsection PJSIP_SIP_RESOLVE_SIP_FEATURES SIP SRV Resolver Features |
| 107 | * |
| 108 | * Some features of the SIP resolver: |
| 109 | * - DNS SRV entries are returned on sorted order based on priority |
| 110 | * to allow failover to the next appropriate server. |
| 111 | * - The procedure in RFC 2782 is used to select server with the same |
| 112 | * priority to load-balance the servers load. |
| 113 | * - A single function (#pjsip_resolve()) performs all server resolution |
| 114 | * works, from resolving the SRV records to getting the actual IP addresses |
| 115 | * of the servers with DNS A (or AAAA) resolution. |
| 116 | * - When multiple DNS SRV records are returned, parallel DNS A (or AAAA) |
| 117 | * queries will be issued simultaneously. |
| 118 | * - The PJLIB-UTIL DNS resolver provides additional functionality such as |
| 119 | * response caching, query aggregation, parallel nameservers, fallback |
| 120 | * nameserver, etc., which will be described below. |
| 121 | * |
| 122 | * |
| 123 | * \subsection PJSIP_RESOLVE_DNS_FEATURES DNS Resolver Features |
| 124 | * |
| 125 | * The PJSIP server resolution framework uses PJLIB-UTIL DNS resolver engine |
| 126 | * for performing the asynchronous DNS request. The PJLIB-UTIL DNS resolver |
| 127 | * has some useful features, such as: |
| 128 | * - queries are asynchronous with configurable timeout, |
| 129 | * - query aggregation to combine multiple pending queries to the same |
| 130 | * DNS target into a single DNS request (to save message round-trip and |
| 131 | * processing), |
| 132 | * - response caching with TTL negotiated between the minimum TTL found in |
| 133 | * the response and the maximum TTL allowed in the configuration, |
| 134 | * - multiple nameservers, with active nameserver is selected from nameserver |
| 135 | * which provides the best response time, |
| 136 | * - fallback nameserver, with periodic detection of which name servers are |
| 137 | * active or down. |
| 138 | * - etc. |
| 139 | * |
| 140 | * Please consult PJLIB-UTIL DNS resolver documentation for more details. |
| 141 | * |
| 142 | * |
| 143 | * \section PJSIP_RESOLVE_USING Using the Resolver |
| 144 | * |
| 145 | * To maintain backward compatibility, the resolver MUST be enabled manually. |
| 146 | * With the default settings, the resolver WILL NOT perform DNS SRV resolution, |
| 147 | * as it will just resolve the name with standard pj_gethostbyname() function. |
| 148 | * |
| 149 | * Application can enable the SRV resolver by creating the PJLIB-UTIL DNS |
| 150 | * resolver with #pjsip_endpt_create_resolver(), configure the |
| 151 | * nameservers of the PJLIB-UTIL DNS resolver object by calling |
| 152 | * pj_dns_resolver_set_ns() function, and pass the DNS resolver object to |
| 153 | * #pjsip_resolver_set_resolver() function. |
| 154 | * |
| 155 | * Once the resolver is set, it will be used automatically by PJSIP everytime |
| 156 | * PJSIP needs to send SIP request/response messages. |
| 157 | * |
| 158 | * |
| 159 | * \section PJSIP_RESOLVE_REFERENCE Reference |
| 160 | * |
| 161 | * Reference: |
| 162 | * - RFC 2782: A DNS RR for specifying the location of services (DNS SRV) |
| 163 | * - RFC 3263: Locating SIP Servers |
| 164 | */ |
| 165 | |
| 166 | /** |
| 167 | * The server addresses returned by the resolver. |
| 168 | */ |
| 169 | typedef struct pjsip_server_addresses |
| 170 | { |
| 171 | /** Number of address records. */ |
| 172 | unsigned count; |
| 173 | |
| 174 | /** Address records. */ |
| 175 | struct |
| 176 | { |
| 177 | /** Preferable transport to be used to contact this address. */ |
| 178 | pjsip_transport_type_e type; |
| 179 | |
| 180 | /** Server priority (the lower the higher the priority). */ |
| 181 | unsigned priority; |
| 182 | |
| 183 | /** Server weight (the higher the more load it can handle). */ |
| 184 | unsigned weight; |
| 185 | |
| 186 | /** The server's address. */ |
| 187 | pj_sockaddr addr; |
| 188 | |
| 189 | /** Address length. */ |
| 190 | int addr_len; |
| 191 | |
| 192 | } entry[PJSIP_MAX_RESOLVED_ADDRESSES]; |
| 193 | |
| 194 | } pjsip_server_addresses; |
| 195 | |
| 196 | |
| 197 | /** |
| 198 | * The type of callback function to be called when resolver finishes the job. |
| 199 | * |
| 200 | * @param status The status of the operation, which is zero on success. |
| 201 | * @param token The token that was associated with the job when application |
| 202 | * call the resolve function. |
| 203 | * @param addr The addresses resolved by the operation. |
| 204 | */ |
| 205 | typedef void pjsip_resolver_callback(pj_status_t status, |
| 206 | void *token, |
| 207 | const struct pjsip_server_addresses *addr); |
| 208 | |
| 209 | /** |
| 210 | * Create SIP resolver engine. Note that this function is normally called |
| 211 | * internally by pjsip_endpoint instance. |
| 212 | * |
| 213 | * @param pool Pool to allocate memory from. |
| 214 | * @param p_res Pointer to receive SIP resolver instance. |
| 215 | * |
| 216 | * @return PJ_SUCCESS when resolver can be successfully created. |
| 217 | */ |
| 218 | PJ_DECL(pj_status_t) pjsip_resolver_create(pj_pool_t *pool, |
| 219 | pjsip_resolver_t **p_res); |
| 220 | |
| 221 | /** |
| 222 | * Set the DNS resolver instance of the SIP resolver engine. Before the |
| 223 | * DNS resolver is set, the SIP resolver will use standard pj_gethostbyname() |
| 224 | * to resolve addresses. |
| 225 | * |
| 226 | * Note that application normally will use #pjsip_endpt_set_resolver() instead |
| 227 | * since it does not normally have access to the SIP resolver instance. |
| 228 | * |
| 229 | * @param res The SIP resolver engine. |
| 230 | * @param dns_res The DNS resolver instance to be used by the SIP resolver. |
| 231 | * This argument can be NULL to reset the internal DNS |
| 232 | * instance. |
| 233 | * |
| 234 | * @return PJ_SUCCESS on success, or the appropriate error code. |
| 235 | */ |
| 236 | PJ_DECL(pj_status_t) pjsip_resolver_set_resolver(pjsip_resolver_t *res, |
| 237 | pj_dns_resolver *dns_res); |
| 238 | |
| 239 | |
| 240 | /** |
| 241 | * Get the DNS resolver instance of the SIP resolver engine. |
| 242 | * |
| 243 | * Note that application normally will use #pjsip_endpt_get_resolver() instead |
| 244 | * since it does not normally have access to the SIP resolver instance. |
| 245 | * |
| 246 | * @param res The SIP resolver engine. |
| 247 | * |
| 248 | * @return The DNS resolver instance (may be NULL) |
| 249 | */ |
| 250 | PJ_DECL(pj_dns_resolver*) pjsip_resolver_get_resolver(pjsip_resolver_t *res); |
| 251 | |
| 252 | /** |
| 253 | * Destroy resolver engine. Note that this will also destroy the internal |
| 254 | * DNS resolver inside the engine. If application doesn't want the internal |
| 255 | * DNS resolver to be destroyed, it should set the internal DNS resolver |
| 256 | * to NULL before calling this function. |
| 257 | * |
| 258 | * Note that this function will normally called by the SIP endpoint instance |
| 259 | * when the SIP endpoint instance is destroyed. |
| 260 | * |
| 261 | * @param resolver The resolver. |
| 262 | */ |
| 263 | PJ_DECL(void) pjsip_resolver_destroy(pjsip_resolver_t *resolver); |
| 264 | |
| 265 | /** |
| 266 | * Asynchronously resolve a SIP target host or domain according to rule |
| 267 | * specified in RFC 3263 (Locating SIP Servers). When the resolving operation |
| 268 | * has completed, the callback will be called. |
| 269 | * |
| 270 | * Note that application normally will use #pjsip_endpt_resolve() instead |
| 271 | * since it does not normally have access to the SIP resolver instance. |
| 272 | * |
| 273 | * @param resolver The resolver engine. |
| 274 | * @param pool The pool to allocate resolver job. |
| 275 | * @param target The target specification to be resolved. |
| 276 | * @param token A user defined token to be passed back to callback function. |
| 277 | * @param cb The callback function. |
| 278 | */ |
| 279 | PJ_DECL(void) pjsip_resolve( pjsip_resolver_t *resolver, |
| 280 | pj_pool_t *pool, |
| 281 | const pjsip_host_info *target, |
| 282 | void *token, |
| 283 | pjsip_resolver_callback *cb); |
| 284 | |
| 285 | /** |
| 286 | * @} |
| 287 | */ |
| 288 | |
| 289 | PJ_END_DECL |
| 290 | |
| 291 | #endif /* __PJSIP_SIP_RESOLVE_H__ */ |