Mstdlib-1.24.0
m_dns.h
1/* The MIT License (MIT)
2 *
3 * Copyright (c) 2017 Monetra Technologies, LLC.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#ifndef __M_DNS_H__
25#define __M_DNS_H__
26
27#include <mstdlib/mstdlib.h>
28#include <mstdlib/io/m_event.h>
29
30__BEGIN_DECLS
31
32/*! \addtogroup m_dns DNS Functions
33 * \ingroup m_io_net
34 *
35 * It's intended that a single global DNS object will be created to allow for
36 * caching. Aiding with caching, Happy eyeballs is used to aid in choosing the
37 * best server when DNS resolves multiple addresses.
38 *
39 * @{
40 */
41
42struct M_dns;
43typedef struct M_dns M_dns_t;
44
45/*! Create a DNS resolver handle.
46 *
47 * This resolver handle is responsible for caching DNS results as well as
48 * tracking which associated IP addresses resulted in successful or failed
49 * connections for optimizing future connection attempts. This DNS handle will
50 * be passed into functions that require DNS resolution like
51 * M_io_net_client_create().
52 *
53 * It is recommended to create a single DNS resolver handle at startup and
54 * pass the same handle to all functions which need it, and destroy the handle
55 * at shutdown.
56 *
57 * \return Initialized DNS handle
58 */
60
61
62/*! Destroys the memory associated with a DNS handle.
63 *
64 * DNS uses reference counters, and will delay destruction until after last consumer is destroyed.
65 *
66 * \param[in] dns Handle initialized via M_dns_create().
67 * \return M_TRUE on success, M_FALSE if handle is actively being used.
68 */
69M_API M_bool M_dns_destroy(M_dns_t *dns);
70
71
72/*! Set the maximum query time before a timeout is returned.
73 *
74 * In some cases, if a prior result is cached, the query may still return
75 * success rather than a timeout failure at the end of a timeout, but the
76 * result will be stale. If set to 0, will use the internal default of 5000ms
77 * (5s)
78 *
79 * \param[in] dns Initialized DNS object
80 * \param[in] timeout_ms Timeout specified in milliseconds. If provided as 0,
81 * will use the default of 5000ms (5s).
82 *
83 * \return M_TRUE if set successfully, M_FALSE otherwise
84 */
85M_API M_bool M_dns_set_query_timeout(M_dns_t *dns, M_uint64 timeout_ms);
86
87
88/*! Set the maximum amount of time a DNS query can be cached for where results are
89 * served out of the cache rather than querying a remote DNS server.
90 *
91 * \param[in] dns Initialized DNS object
92 * \param[in] max_timeout_s Specify the maximum timeout of the cached results, even if no
93 * DNS server is reachable. Stale results can no longer be delivered
94 * after this timeframe and will result in DNS errors being returned.
95 * If 0 is specified, will use the default of 3600s (1 hr).
96 *
97 * \return M_TRUE if set successfully, M_FALSE otherwise
98 */
99M_API M_bool M_dns_set_cache_timeout(M_dns_t *dns, M_uint64 max_timeout_s);
100
101
102/*! RFC 6555/8305 Happy Eyeballs status codes */
104 M_HAPPYEB_STATUS_GOOD = 0, /*!< Successfully connected to server */
105 M_HAPPYEB_STATUS_UNKNOWN = 1, /*!< Don't know, probably not attempted */
106 M_HAPPYEB_STATUS_SLOW = 2, /*!< Don't know for sure its bad, but we started and
107 * a different connection finished first */
108 M_HAPPYEB_STATUS_BAD = 3, /*!< Recieved a connection error */
109};
111
112
113/*! Result codes for DNS queries */
115 M_DNS_RESULT_SUCCESS = 0, /*!< DNS result successful */
116 M_DNS_RESULT_SUCCESS_CACHE = 1, /*!< DNS result successful, returned from cache */
117 M_DNS_RESULT_SUCCESS_CACHE_EVICT = 2, /*!< DNS result successful, evicting old cache */
118 M_DNS_RESULT_SERVFAIL = 3, /*!< DNS server failure */
119 M_DNS_RESULT_NOTFOUND = 4, /*!< DNS server returned a Not Found error */
120 M_DNS_RESULT_TIMEOUT = 5, /*!< Timeout resolving DNS name */
121 M_DNS_RESULT_INVALID = 6 /*!< Invalid use */
124
125/*! Returned IP address list is cleaned up immediately after the callback returns, if persistence
126 * is needed, duplicate the list. The list is returned sorted in preference order:
127 * * List starts as alternating between ipv6 and ipv4 addresses in the order returned from
128 * the DNS server, such as ipv6-1, ipv4-1, ipv6-2, ipv4-2 and so on.
129 * * List then is updated with the happyeyeballs RFC6555/8305 status for prior connection
130 * attempts.
131 * * Finally the list is sorted by happyeyeballs status as the primary sort comparison,
132 * followed by the original order as per server preference.
133 * \param[in] ipaddrs Ip addresses resolved in string form, nor NULL if none
134 * \param[in] cb_data Callback data provided to M_dns_gethostbyname()
135 * \param[in] result Result code of DNS lookup
136 */
137typedef void (*M_dns_ghbn_callback_t)(const M_list_str_t *ipaddrs, void *cb_data, M_dns_result_t result);
138
139
140/*! Request to resolve a DNS hostname to one or more IP addresses. When the resolution
141 * is complete, the callback passed in will be called. This function may call the
142 * callback immediately if the DNS result is cached. Once the supplied callback is
143 * called, the query will be automatically cleaned up.
144 *
145 * \param[in] dns Handle to DNS pointer created with M_dns_create()
146 * \param[in] event Optional. Event handle to use to deliver the result callback
147 * to. This is useful to ensure the result is enqueued to the
148 * same event loop as requested which may limit need for
149 * possible external locking.
150 * \param[in] hostname Hostname to look up.
151 * \param[in] type Type of lookup to perform (IPv4, IPv6, or both/any)
152 * \param[in] callback Callback to call on completion
153 * \param[in] cb_data User data handle passed to callback on completion
154 */
155M_API void M_dns_gethostbyname(M_dns_t *dns, M_event_t *event, const char *hostname, M_io_net_type_t type, M_dns_ghbn_callback_t callback, void *cb_data);
156
157/*! Notify the DNS subsystem of any updates to connection status on a given
158 * IP address. This will cause future results of M_dns_gethostbyname() to be
159 * sorted based on success or failure of past connections.
160 * \param[in] dns Handle to DNS pointer created with M_dns_create()
161 * \param[in] ipaddr String form of IP address
162 * \param[in] status Status of connection attempt.
163 */
164M_API void M_dns_happyeyeballs_update(M_dns_t *dns, const char *ipaddr, M_dns_happyeb_status_t status);
165
166
167/*! Convert the string form ip address of the given address family to its binary form.
168 *
169 * \param[in] af Address family of AF_INET or AF_INET6
170 * \param[in] src Null-terminated string represenation of IP address
171 * \param[out] dst Buffer of adequate size to hold AF_INET (32bits) or AF_INET6 (128bits) result
172 * \return M_TRUE on success, M_FALSE on conversion failure
173 */
174M_API M_bool M_dns_pton(int af, const char *src, void *dst);
175
176/*! Convert the binary form of ip address of the given address family to its string form.
177 * \param[in] af Address family of AF_INET or AF_INET6
178 * \param[in] src Buffer containing binary representation of ip address. 32bits for AF_INET, 128bits for AF_INET6.
179 * \param[out] addr Destination buffer to write string represenation of ip address.
180 * \param[in] addr_size Size of destination buffer
181 * \return M_TRUE on success, M_FALSE on conversion failure.
182 */
183M_API M_bool M_dns_ntop(int af, const void *src, char *addr, size_t addr_size);
184
185/*! @} */
186
187__END_DECLS
188
189#endif
M_bool M_dns_set_query_timeout(M_dns_t *dns, M_uint64 timeout_ms)
M_bool M_dns_destroy(M_dns_t *dns)
void(* M_dns_ghbn_callback_t)(const M_list_str_t *ipaddrs, void *cb_data, M_dns_result_t result)
Definition: m_dns.h:137
void M_dns_happyeyeballs_update(M_dns_t *dns, const char *ipaddr, M_dns_happyeb_status_t status)
void M_dns_gethostbyname(M_dns_t *dns, M_event_t *event, const char *hostname, M_io_net_type_t type, M_dns_ghbn_callback_t callback, void *cb_data)
M_dns_happyeb_status
Definition: m_dns.h:103
struct M_dns M_dns_t
Definition: m_dns.h:43
enum M_dns_happyeb_status M_dns_happyeb_status_t
Definition: m_dns.h:110
M_bool M_dns_pton(int af, const char *src, void *dst)
M_dns_t * M_dns_create(M_event_t *event)
enum M_dns_result M_dns_result_t
Definition: m_dns.h:123
M_bool M_dns_ntop(int af, const void *src, char *addr, size_t addr_size)
M_dns_result
Definition: m_dns.h:114
M_bool M_dns_set_cache_timeout(M_dns_t *dns, M_uint64 max_timeout_s)
@ M_HAPPYEB_STATUS_SLOW
Definition: m_dns.h:106
@ M_HAPPYEB_STATUS_UNKNOWN
Definition: m_dns.h:105
@ M_HAPPYEB_STATUS_GOOD
Definition: m_dns.h:104
@ M_HAPPYEB_STATUS_BAD
Definition: m_dns.h:108
@ M_DNS_RESULT_SUCCESS_CACHE
Definition: m_dns.h:116
@ M_DNS_RESULT_SERVFAIL
Definition: m_dns.h:118
@ M_DNS_RESULT_INVALID
Definition: m_dns.h:121
@ M_DNS_RESULT_SUCCESS_CACHE_EVICT
Definition: m_dns.h:117
@ M_DNS_RESULT_NOTFOUND
Definition: m_dns.h:119
@ M_DNS_RESULT_TIMEOUT
Definition: m_dns.h:120
@ M_DNS_RESULT_SUCCESS
Definition: m_dns.h:115
struct M_event M_event_t
Definition: m_event.h:210
enum M_io_net_type M_io_net_type_t
Definition: m_io_net.h:340
struct M_list_str M_list_str_t
Definition: m_list_str.h:80