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 __PJLIB_UTIL_SRV_RESOLVER_H__
21 #define __PJLIB_UTIL_SRV_RESOLVER_H__
22 
23 /**
24  * @file srv_resolver.h
25  * @brief DNS SRV resolver
26  */
27 #include <pjlib-util/resolver.h>
28 
29 PJ_BEGIN_DECL
30 
31 /**
32  * @defgroup PJ_DNS_SRV_RESOLVER DNS SRV Resolution Helper
33  * @ingroup PJ_DNS
34  * @{
35  *
36  * \section PJ_DNS_SRV_RESOLVER_INTRO DNS SRV Resolution Helper
37  *
38  * This module provides an even higher layer of abstraction for the DNS
39  * resolution framework, to resolve DNS SRV names.
40  *
41  * The #pj_dns_srv_resolve() function will asynchronously resolve the server
42  * name into IP address(es) with a single function call. If the SRV name
43  * contains multiple names, then each will be resolved with individual
44  * DNS A resolution to get the IP addresses. Upon successful completion,
45  * application callback will be called with each IP address of the
46  * target selected based on the load-balancing and fail-over criteria
47  * below.
48  *
49  * When the resolver fails to resolve the name using DNS SRV resolution
50  * (for example when the DNS SRV record is not present in the DNS server),
51  * the resolver will fallback to using DNS A record resolution to resolve
52  * the name.
53  *
54  * \subsection PJ_DNS_SRV_RESOLVER_FAILOVER_LOADBALANCE Load-Balancing and Fail-Over
55  *
56  * When multiple targets are returned in the DNS SRV response, server entries
57  * are selected based on the following rule (which is described in RFC 2782):
58  *  - targets will be sorted based on the priority first.
59  *  - for targets with the same priority, #pj_dns_srv_resolve() will select
60  *    only one target according to its weight. To select this one target,
61  *    the function associates running-sum for all targets, and generates
62  *    a random number between zero and the total running-sum (inclusive).
63  *    The target selected is the first target with running-sum greater than
64  *    or equal to this random number.
65  *
66  * The above procedure will select one target for each priority, allowing
67  * application to fail-over to the next target when the previous target fails.
68  * These targets are returned in the #pj_dns_srv_record structure
69  * argument of the callback.
70  *
71  * \section PJ_DNS_SRV_RESOLVER_REFERENCE Reference
72  *
73  * Reference:
74  *  - <A HREF="http://www.ietf.org/rfc/rfc2782.txt">RFC 2782</A>:
75  *	A DNS RR for specifying the location of services (DNS SRV)
76  */
77 
78 /**
79  * Flags to be specified when starting the DNS SRV query.
80  */
81 typedef enum pj_dns_srv_option
82 {
83     /**
84      * Specify if the resolver should fallback with DNS A
85      * resolution when the SRV resolution fails. This option may
86      * be specified together with PJ_DNS_SRV_FALLBACK_AAAA to
87      * make the resolver fallback to both DNS A and DNS AAAA
88      * resolutions if SRV resolution fails.
89      */
90     PJ_DNS_SRV_FALLBACK_A	= 1,
91 
92     /**
93      * Specify if the resolver should fallback with DNS AAAA
94      * resolution when the SRV resolution fails. This option may
95      * be specified together with PJ_DNS_SRV_FALLBACK_AAAA to
96      * make the resolver fallback to both DNS A and DNS AAAA
97      * resolutions if SRV resolution fails.
98      */
99     PJ_DNS_SRV_FALLBACK_AAAA	= 2,
100 
101     /**
102      * Specify if the resolver should try to resolve with DNS AAAA
103      * resolution of each targets in the DNS SRV record. If this
104      * option is not specified, the SRV resolver will query the
105      * DNS A record for the target instead.
106      */
107     PJ_DNS_SRV_RESOLVE_AAAA	= 4,
108 
109     /**
110      * Specify if the resolver should try to resolve with DNS AAAA
111      * resolution only (i.e: without DNS A resolution) for each targets
112      * in the DNS SRV record.
113      */
114     PJ_DNS_SRV_RESOLVE_AAAA_ONLY = 8
115 
116 } pj_dns_srv_option;
117 
118 
119 /**
120  * This structure represents DNS SRV records as the result of DNS SRV
121  * resolution using #pj_dns_srv_resolve().
122  */
123 typedef struct pj_dns_srv_record
124 {
125     /** Number of address records. */
126     unsigned	count;
127 
128     /** Address records. */
129     struct
130     {
131 	/** Server priority (the lower the higher the priority). */
132 	unsigned		priority;
133 
134 	/** Server weight (the higher the more load it can handle). */
135 	unsigned		weight;
136 
137 	/** Port number. */
138 	pj_uint16_t		port;
139 
140 	/** The host address. */
141 	pj_dns_addr_record	server;
142 
143     } entry[PJ_DNS_SRV_MAX_ADDR];
144 
145 } pj_dns_srv_record;
146 
147 
148 /** Opaque declaration for DNS SRV query */
149 typedef struct pj_dns_srv_async_query pj_dns_srv_async_query;
150 
151 /**
152  * Type of callback function to receive notification from the resolver
153  * when the resolution process completes.
154  */
155 typedef void pj_dns_srv_resolver_cb(void *user_data,
156 				    pj_status_t status,
157 				    const pj_dns_srv_record *rec);
158 
159 
160 /**
161  * Start DNS SRV resolution for the specified name. The full name of the
162  * entry will be concatenated from \a res_name and \a domain_name fragments.
163  *
164  * @param domain_name	The domain name part of the name.
165  * @param res_name	The full service name, including the transport name
166  *			and with all the leading underscore characters and
167  *			ending dot (e.g. "_sip._udp.", "_stun._udp.").
168  * @param def_port	The port number to be assigned to the resolved address
169  *			when the DNS SRV resolution fails and the name is
170  *			resolved with DNS A resolution.
171  * @param pool		Memory pool used to allocate memory for the query.
172  * @param resolver	The resolver instance.
173  * @param option	Option flags, which can be constructed from
174  *			#pj_dns_srv_option bitmask. Note that this argument
175  *			was called "fallback_a" in pjsip version 0.8.0 and
176  *			older, but the new option should be backward
177  *			compatible with existing applications. If application
178  *			specifies PJ_TRUE as "fallback_a" value, it will
179  *			correspond to PJ_DNS_SRV_FALLBACK_A option.
180  * @param token		Arbitrary data to be associated with this query when
181  *			the calback is called.
182  * @param cb		Pointer to callback function to receive the
183  *			notification when the resolution process completes.
184  * @param p_query	Optional pointer to receive the query object, if one
185  *			was started. If this pointer is specified, a NULL may
186  *			be returned if response cache is available immediately.
187  *
188  * @return		PJ_SUCCESS on success, or the appropriate error code.
189  */
190 PJ_DECL(pj_status_t) pj_dns_srv_resolve(const pj_str_t *domain_name,
191 					const pj_str_t *res_name,
192 					unsigned def_port,
193 					pj_pool_t *pool,
194 					pj_dns_resolver *resolver,
195 					unsigned option,
196 					void *token,
197 					pj_dns_srv_resolver_cb *cb,
198 					pj_dns_srv_async_query **p_query);
199 
200 
201 /**
202  * Cancel an outstanding DNS SRV query.
203  *
204  * @param query	    The pending asynchronous query to be cancelled.
205  * @param notify    If non-zero, the callback will be called with failure
206  *		    status to notify that the query has been cancelled.
207  *
208  * @return	    PJ_SUCCESS on success, or the appropriate error code,
209  */
210 PJ_DECL(pj_status_t) pj_dns_srv_cancel_query(pj_dns_srv_async_query *query,
211 					     pj_bool_t notify);
212 
213 
214 /**
215  * @}
216  */
217 
218 PJ_END_DECL
219 
220 
221 #endif	/* __PJLIB_UTIL_SRV_RESOLVER_H__ */
222 
223