source: azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/src/dns_resolver_sync.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 9.7 KB
Line 
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4
5#include <stdbool.h>
6#include <stdint.h>
7#include <stdlib.h>
8
9// This file is OS-specific, and is identified by setting include directories
10// in the project
11#include "socket_async_os.h"
12
13#include "azure_c_shared_utility/dns_resolver.h"
14#include "azure_c_shared_utility/gballoc.h"
15#include "azure_c_shared_utility/crt_abstractions.h"
16#include "azure_c_shared_utility/xlogging.h"
17
18
19// EXTRACT_IPV4 pulls the uint32_t IPv4 address out of an addrinfo struct
20// This will not be needed for the asynchronous design
21// The default definition handles lwIP. Please add comments for other systems tested.
22#define EXTRACT_IPV4(ptr) ((struct sockaddr_in *) ptr->ai_addr)->sin_addr.s_addr
23
24typedef struct
25{
26 char* hostname;
27 int port;
28 uint32_t ip_v4;
29 bool is_complete;
30 bool is_failed;
31 struct addrinfo* addrInfo;
32} DNSRESOLVER_INSTANCE;
33
34DNSRESOLVER_HANDLE dns_resolver_create(const char* hostname, int port, const DNSRESOLVER_OPTIONS* options)
35{
36 /* Codes_SRS_dns_resolver_30_012: [ The optional options parameter shall be ignored. ]*/
37 DNSRESOLVER_INSTANCE* result;
38 (void)options;
39 if (hostname == NULL)
40 {
41 /* Codes_SRS_dns_resolver_30_011: [ If the hostname parameter is NULL, dns_resolver_create shall log an error and return NULL. ]*/
42 LogError("NULL hostname");
43 result = NULL;
44 }
45 else
46 {
47 result = malloc(sizeof(DNSRESOLVER_INSTANCE));
48 if (result == NULL)
49 {
50 /* Codes_SRS_dns_resolver_30_014: [ On any failure, dns_resolver_create shall log an error and return NULL. ]*/
51 LogError("malloc instance failed");
52 result = NULL;
53 }
54 else
55 {
56 int ms_result;
57 result->is_complete = false;
58 result->is_failed = false;
59 result->ip_v4 = 0;
60 result->port = port;
61 /* Codes_SRS_dns_resolver_30_010: [ dns_resolver_create shall make a copy of the hostname parameter to allow immediate deletion by the caller. ]*/
62 ms_result = mallocAndStrcpy_s(&result->hostname, hostname);
63 if (ms_result != 0)
64 {
65 /* Codes_SRS_dns_resolver_30_014: [ On any failure, dns_resolver_create shall log an error and return NULL. ]*/
66 free(result);
67 result = NULL;
68 }
69 }
70 }
71 return result;
72}
73
74/* Codes_SRS_dns_resolver_30_021: [ dns_resolver_is_create_complete shall perform the asynchronous work of DNS lookup and log any errors. ]*/
75bool dns_resolver_is_lookup_complete(DNSRESOLVER_HANDLE dns_in)
76{
77 DNSRESOLVER_INSTANCE* dns = (DNSRESOLVER_INSTANCE*)dns_in;
78
79 bool result;
80 if (dns == NULL)
81 {
82 /* Codes_SRS_dns_resolver_30_020: [ If the dns parameter is NULL, dns_resolver_is_create_complete shall log an error and return false. ]*/
83 LogError("NULL dns");
84 result = false;
85 }
86 else
87 {
88 if (dns->is_complete)
89 {
90 /* Codes_SRS_dns_resolver_30_024: [ If dns_resolver_is_create_complete has previously returned true, dns_resolver_is_create_complete shall do nothing and return true. ]*/
91 result = true;
92 }
93 else
94 {
95 char portString[16];
96 struct addrinfo *addrInfo = NULL;
97 struct addrinfo *ptr = NULL;
98 struct addrinfo hints;
99 int getAddrResult;
100
101 //--------------------------------
102 // Setup the hints address info structure
103 // which is passed to the getaddrinfo() function
104 memset(&hints, 0, sizeof(hints));
105 hints.ai_family = AF_INET;
106 hints.ai_socktype = SOCK_STREAM;
107 hints.ai_protocol = 0;
108
109 //--------------------------------
110 // Call getaddrinfo(). If the call succeeds,
111 // the result variable will hold a linked list
112 // of addrinfo structures containing response
113 // information
114 if (sprintf(portString, "%u", dns->port) < 0)
115 {
116 LogError("Failure: sprintf failed to encode the port.");
117 result = MU_FAILURE;
118 }
119
120 getAddrResult = getaddrinfo(dns->hostname, portString, &hints, &addrInfo);
121 if (getAddrResult == 0)
122 {
123 dns->addrInfo = addrInfo;
124
125 // If we find the AF_INET address, use it as the return value
126 for (ptr = addrInfo; ptr != NULL; ptr = ptr->ai_next)
127 {
128 switch (ptr->ai_family)
129 {
130 case AF_INET:
131 /* Codes_SRS_dns_resolver_30_032: [ If dns_resolver_is_create_complete has returned true and the lookup process has succeeded, dns_resolver_get_ipv4 shall return the discovered IPv4 address. ]*/
132 dns->ip_v4 = EXTRACT_IPV4(ptr);
133 break;
134 }
135 }
136 /* Codes_SRS_dns_resolver_30_033: [ If dns_resolver_is_create_complete has returned true and the lookup process has failed, dns_resolver_get_ipv4 shall return 0. ]*/
137 dns->is_failed = (dns->ip_v4 == 0);
138 }
139 else
140 {
141 /* Codes_SRS_dns_resolver_30_033: [ If dns_resolver_is_create_complete has returned true and the lookup process has failed, dns_resolver_get_ipv4 shall return 0. ]*/
142 LogInfo("Failed DNS lookup for %s: %d", dns->hostname, getAddrResult);
143 dns->is_failed = true;
144 }
145
146 /* Codes_SRS_dns_resolver_30_021: [ dns_resolver_is_create_complete shall perform the asynchronous work of DNS lookup and log any errors. ]*/
147 // Only make one attempt at lookup for this
148 // synchronous implementation
149 dns->is_complete = true;
150
151 // This synchronous implementation is incapable of being incomplete, so SRS_dns_resolver_30_023 does not ever happen
152 /* Codes_SRS_dns_resolver_30_023: [ If the DNS lookup process is not yet complete, dns_resolver_is_create_complete shall return false. ]*/
153 /* Codes_SRS_dns_resolver_30_022: [ If the DNS lookup process has completed, dns_resolver_is_create_complete shall return true. ]*/
154 result = true;
155 }
156 }
157
158 return result;
159}
160
161void dns_resolver_destroy(DNSRESOLVER_HANDLE dns_in)
162{
163 DNSRESOLVER_INSTANCE* dns = (DNSRESOLVER_INSTANCE*)dns_in;
164 if (dns == NULL)
165 {
166 /* Codes_SRS_dns_resolver_30_050: [ If the dns parameter is NULL, dns_resolver_destroy shall log an error and do nothing. ]*/
167 LogError("NULL dns");
168 }
169 else
170 {
171 /* Codes_SRS_dns_resolver_30_051: [ dns_resolver_destroy shall delete all acquired resources and delete the DNSRESOLVER_HANDLE. ]*/
172 if(dns->is_complete && !dns->is_failed && dns->addrInfo != NULL)
173 {
174 freeaddrinfo(dns->addrInfo);
175 }
176
177 if(dns->hostname != NULL)
178 {
179 free(dns->hostname);
180 }
181
182 free(dns);
183 dns = NULL;
184 }
185}
186
187uint32_t dns_resolver_get_ipv4(DNSRESOLVER_HANDLE dns_in)
188{
189 DNSRESOLVER_INSTANCE* dns = (DNSRESOLVER_INSTANCE*)dns_in;
190 uint32_t result;
191 if (dns == NULL)
192 {
193 /* Codes_SRS_dns_resolver_30_030: [ If the dns parameter is NULL, dns_resolver_get_ipv4 shall log an error and return 0. ]*/
194 LogError("NULL dns");
195 result = 0;
196 }
197 else
198 {
199 if (dns->is_complete)
200 {
201 if (dns->is_failed)
202 {
203 /* Codes_SRS_dns_resolver_30_033: [ If dns_resolver_is_create_complete has returned true and the lookup process has failed, dns_resolver_get_ipv4 shall return 0. ]*/
204 result = 0;
205 }
206 else
207 {
208 /* Codes_SRS_dns_resolver_30_032: [ If dns_resolver_is_create_complete has returned true and the lookup process has succeeded, dns_resolver_get_ipv4 shall return the discovered IPv4 address. ]*/
209 result = dns->ip_v4;
210 }
211 }
212 else
213 {
214 /* Codes_SRS_dns_resolver_30_031: [ If dns_resolver_is_create_complete has not yet returned true, dns_resolver_get_ipv4 shall log an error and return 0. ]*/
215 LogError("dns_resolver_get_ipv4 when not complete");
216 result = 0;
217 }
218 }
219 return result;
220}
221
222struct addrinfo* dns_resolver_get_addrInfo(DNSRESOLVER_HANDLE dns_in)
223{
224 DNSRESOLVER_INSTANCE* dns = (DNSRESOLVER_INSTANCE*)dns_in;
225 struct addrinfo* result;
226 if (dns == NULL)
227 {
228 /* Codes_SRS_dns_resolver_30_030: [ If the dns parameter is NULL, dns_resolver_get_ipv4 shall log an error and return 0. ]*/
229 LogError("NULL dns");
230 result = NULL;
231 }
232 else
233 {
234 if (dns->is_complete)
235 {
236 if (dns->is_failed)
237 {
238 /* Codes_SRS_dns_resolver_30_033: [ If dns_resolver_is_create_complete has returned true and the lookup process has failed, dns_resolver_get_ipv4 shall return 0. ]*/
239 result = NULL;
240 }
241 else
242 {
243 /* Codes_SRS_dns_resolver_30_032: [ If dns_resolver_is_create_complete has returned true and the lookup process has succeeded, dns_resolver_get_ipv4 shall return the discovered IPv4 address. ]*/
244 result = dns->addrInfo;
245 }
246 }
247 else
248 {
249 /* Codes_SRS_dns_resolver_30_031: [ If dns_resolver_is_create_complete has not yet returned true, dns_resolver_get_ipv4 shall log an error and return 0. ]*/
250 LogError("dns_resolver_get_ipv4 when not complete");
251 result = NULL;
252 }
253 }
254 return result;
255}
Note: See TracBrowser for help on using the repository browser.