Line data Source code
1 : #include "fd_ssresolve.h"
2 : #include "fd_ssarchive.h"
3 :
4 : #include "../../../waltz/http/picohttpparser.h"
5 : #include "../../../waltz/openssl/fd_openssl.h"
6 : #include "../../../util/log/fd_log.h"
7 :
8 : #include <unistd.h>
9 : #include <errno.h>
10 : #include <stdlib.h>
11 : #include <strings.h>
12 :
13 : #include <sys/socket.h>
14 : #include <netinet/tcp.h>
15 : #include <netinet/in.h>
16 :
17 : /* TODO: consider refactoring the common http code in ssresolve and
18 : sshttp into a common library */
19 :
20 0 : #define FD_SSRESOLVE_CONNECT (0) /* connecting ssl */
21 0 : #define FD_SSRESOLVE_STATE_REQ (1) /* sending request for snapshot */
22 0 : #define FD_SSRESOLVE_STATE_RESP (2) /* receiving snapshot response */
23 0 : #define FD_SSRESOLVE_STATE_SHUTTING_DOWN (3) /* shutting down ssl */
24 0 : #define FD_SSRESOLVE_STATE_DONE (4) /* done */
25 :
26 : struct fd_ssresolve_private {
27 : int state;
28 : long deadline;
29 :
30 : fd_ip4_port_t addr;
31 : int sockfd;
32 : int full;
33 : int is_https;
34 : char const * hostname;
35 :
36 : char request[ 4096UL ];
37 : ulong request_sent;
38 : ulong request_len;
39 :
40 : ulong response_len;
41 : char response[ USHORT_MAX ];
42 :
43 : #if FD_HAS_OPENSSL
44 : SSL * ssl;
45 : #endif
46 :
47 : ulong magic;
48 : };
49 :
50 : FD_FN_CONST ulong
51 7680 : fd_ssresolve_align( void ) {
52 7680 : return FD_SSRESOLVE_ALIGN;
53 7680 : }
54 :
55 : FD_FN_CONST ulong
56 3840 : fd_ssresolve_footprint( void ) {
57 3840 : ulong l;
58 3840 : l = FD_LAYOUT_INIT;
59 3840 : l = FD_LAYOUT_APPEND( l, FD_SSRESOLVE_ALIGN, sizeof(fd_ssresolve_t) );
60 3840 : return FD_LAYOUT_FINI( l, FD_SSRESOLVE_ALIGN );
61 3840 : }
62 :
63 : void *
64 0 : fd_ssresolve_new( void * shmem ) {
65 0 : if( FD_UNLIKELY( !shmem ) ) {
66 0 : FD_LOG_WARNING(( "NULL shmem" ));
67 0 : return NULL;
68 0 : }
69 :
70 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_ssresolve_align() ) ) ) {
71 0 : FD_LOG_WARNING(( "unaligned shmem" ));
72 0 : return NULL;
73 0 : }
74 :
75 0 : FD_SCRATCH_ALLOC_INIT( l, shmem );
76 0 : fd_ssresolve_t * ssresolve = FD_SCRATCH_ALLOC_APPEND( l, FD_SSRESOLVE_ALIGN, sizeof(fd_ssresolve_t) );
77 :
78 0 : ssresolve->state = FD_SSRESOLVE_STATE_REQ;
79 0 : ssresolve->request_sent = 0UL;
80 0 : ssresolve->request_len = 0UL;
81 0 : ssresolve->response_len = 0UL;
82 0 : ssresolve->sockfd = -1;
83 :
84 0 : #if FD_HAS_OPENSSL
85 0 : ssresolve->ssl = NULL;
86 0 : #endif
87 :
88 0 : FD_COMPILER_MFENCE();
89 0 : FD_VOLATILE( ssresolve->magic ) = FD_SSRESOLVE_MAGIC;
90 0 : FD_COMPILER_MFENCE();
91 :
92 0 : return (void *)ssresolve;
93 0 : }
94 :
95 : fd_ssresolve_t *
96 0 : fd_ssresolve_join( void * _ssresolve ) {
97 0 : if( FD_UNLIKELY( !_ssresolve ) ) {
98 0 : FD_LOG_WARNING(( "NULL ssresolve" ));
99 0 : return NULL;
100 0 : }
101 :
102 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)_ssresolve, fd_ssresolve_align() ) ) ) {
103 0 : FD_LOG_WARNING(( "misaligned ssresolve" ));
104 0 : return NULL;
105 0 : }
106 :
107 0 : fd_ssresolve_t * ssresolve = (fd_ssresolve_t *)_ssresolve;
108 :
109 0 : if( FD_UNLIKELY( ssresolve->magic!=FD_SSRESOLVE_MAGIC ) ) {
110 0 : FD_LOG_WARNING(( "bad magic" ));
111 0 : return NULL;
112 0 : }
113 :
114 0 : return ssresolve;
115 0 : }
116 :
117 : void
118 : fd_ssresolve_init( fd_ssresolve_t * ssresolve,
119 : fd_ip4_port_t addr,
120 : int sockfd,
121 : int full,
122 0 : char const * hostname ) {
123 0 : ssresolve->addr = addr;
124 0 : ssresolve->sockfd = sockfd;
125 0 : ssresolve->full = full;
126 :
127 0 : ssresolve->state = FD_SSRESOLVE_STATE_REQ;
128 0 : ssresolve->request_sent = 0UL;
129 0 : ssresolve->request_len = 0UL;
130 0 : ssresolve->response_len = 0UL;
131 0 : ssresolve->is_https = 0;
132 0 : ssresolve->hostname = hostname;
133 0 : }
134 :
135 : #if FD_HAS_OPENSSL
136 : void
137 : fd_ssresolve_init_https( fd_ssresolve_t * ssresolve,
138 : fd_ip4_port_t addr,
139 : int sockfd,
140 : int full,
141 : char const * hostname,
142 0 : SSL_CTX * ssl_ctx ) {
143 0 : ssresolve->addr = addr;
144 0 : ssresolve->sockfd = sockfd;
145 0 : ssresolve->full = full;
146 :
147 0 : ssresolve->state = FD_SSRESOLVE_CONNECT;
148 0 : ssresolve->request_sent = 0UL;
149 0 : ssresolve->request_len = 0UL;
150 0 : ssresolve->response_len = 0UL;
151 0 : ssresolve->is_https = 1;
152 0 : ssresolve->hostname = hostname;
153 :
154 0 : ssresolve->ssl = SSL_new( ssl_ctx );
155 0 : if( FD_UNLIKELY( !ssresolve->ssl ) ) {
156 0 : FD_LOG_ERR(( "SSL_new failed" ));
157 0 : }
158 :
159 0 : static uchar const alpn_protos[] = { 8, 'h', 't', 't', 'p', '/', '1', '.', '1' };
160 0 : int alpn_res = SSL_set_alpn_protos( ssresolve->ssl, alpn_protos, sizeof(alpn_protos) );
161 0 : if( FD_UNLIKELY( alpn_res!=0 ) ) {
162 0 : FD_LOG_ERR(( "SSL_set_alpn_protos failed (%d)", alpn_res ));
163 0 : }
164 :
165 : /* set SNI and hostname verification */
166 0 : FD_TEST( hostname && hostname[ 0 ]!='\0' );
167 0 : long sni_res = SSL_set_tlsext_host_name( ssresolve->ssl, hostname );
168 0 : if( FD_UNLIKELY( !sni_res ) ) {
169 0 : FD_LOG_ERR(( "SSL_set_tlsext_host_name failed (%ld) for %s", sni_res, hostname ));
170 0 : }
171 0 : int set1_host_res = SSL_set1_host( ssresolve->ssl, hostname );
172 0 : if( FD_UNLIKELY( !set1_host_res ) ) {
173 0 : FD_LOG_ERR(( "SSL_set1_host failed (%d) for %s", set1_host_res, hostname ));
174 0 : }
175 :
176 0 : FD_TEST( fd_openssl_ssl_set_fd( ssresolve->ssl, ssresolve->sockfd ) );
177 0 : }
178 : #endif
179 :
180 : static void
181 0 : fd_ssresolve_render_req( fd_ssresolve_t * ssresolve ) {
182 0 : char const * path = ssresolve->full ? "/snapshot.tar.bz2" : "/incremental-snapshot.tar.bz2";
183 :
184 0 : if( FD_LIKELY( ssresolve->hostname && ssresolve->hostname[ 0 ]!='\0' ) ) {
185 0 : FD_TEST( fd_cstr_printf_check( ssresolve->request, sizeof(ssresolve->request), &ssresolve->request_len,
186 0 : "HEAD %s HTTP/1.1\r\n"
187 0 : "User-Agent: Firedancer\r\n"
188 0 : "Accept: */*\r\n"
189 0 : "Accept-Encoding: identity\r\n"
190 0 : "Host: %s\r\n\r\n",
191 0 : path, ssresolve->hostname ) );
192 0 : } else {
193 0 : FD_TEST( fd_cstr_printf_check( ssresolve->request, sizeof(ssresolve->request), &ssresolve->request_len,
194 0 : "HEAD %s HTTP/1.1\r\n"
195 0 : "User-Agent: Firedancer\r\n"
196 0 : "Accept: */*\r\n"
197 0 : "Accept-Encoding: identity\r\n"
198 0 : "Host: " FD_IP4_ADDR_FMT "\r\n\r\n",
199 0 : path, FD_IP4_ADDR_FMT_ARGS( ssresolve->addr.addr ) ) );
200 0 : }
201 0 : }
202 :
203 : static int
204 0 : fd_ssresolve_send_request( fd_ssresolve_t * ssresolve ) {
205 0 : FD_TEST( ssresolve->state==FD_SSRESOLVE_STATE_REQ );
206 :
207 0 : if( FD_UNLIKELY( !ssresolve->request_len ) ) {
208 0 : fd_ssresolve_render_req( ssresolve );
209 0 : }
210 :
211 0 : long sent = 0L;
212 0 : if( FD_LIKELY( ssresolve->is_https ) ) {
213 0 : #if FD_HAS_OPENSSL
214 0 : int write_res = SSL_write( ssresolve->ssl, ssresolve->request+ssresolve->request_sent, (int)(ssresolve->request_len-ssresolve->request_sent) );
215 0 : if( FD_UNLIKELY( write_res<=0 ) ) {
216 0 : int ssl_err = SSL_get_error( ssresolve->ssl, write_res );
217 :
218 0 : if( FD_UNLIKELY( ssl_err!=SSL_ERROR_WANT_READ && ssl_err!=SSL_ERROR_WANT_WRITE ) ) {
219 0 : FD_LOG_WARNING(( "SSL_write failed (%d)", ssl_err ));
220 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
221 0 : }
222 :
223 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
224 0 : }
225 :
226 0 : sent = (long)write_res;
227 : #else
228 : FD_LOG_ERR(( "cannot use HTTPS without OpenSSL" ));
229 : #endif
230 0 : } else {
231 0 : sent = sendto( ssresolve->sockfd, ssresolve->request+ssresolve->request_sent, ssresolve->request_len-ssresolve->request_sent, MSG_NOSIGNAL, NULL, 0 );
232 0 : if( FD_UNLIKELY( -1==sent && errno==EAGAIN ) ) return FD_SSRESOLVE_ADVANCE_AGAIN;
233 0 : else if( FD_UNLIKELY( -1==sent ) ) {
234 0 : FD_LOG_WARNING(( "sendto() failed (%d-%s)", errno, fd_io_strerror( errno ) ));
235 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
236 0 : }
237 0 : }
238 :
239 0 : ssresolve->request_sent += (ulong)sent;
240 0 : if( FD_UNLIKELY( ssresolve->request_sent==ssresolve->request_len ) ) {
241 0 : ssresolve->state = FD_SSRESOLVE_STATE_RESP;
242 0 : return FD_SSRESOLVE_ADVANCE_SUCCESS;
243 0 : }
244 :
245 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
246 0 : }
247 :
248 : static int
249 : fd_ssresolve_parse_redirect( fd_ssresolve_t * ssresolve,
250 : struct phr_header * headers,
251 : ulong header_cnt,
252 0 : fd_ssresolve_result_t * result ) {
253 0 : ulong location_len = 0UL;
254 0 : char const * location = NULL;
255 :
256 0 : for( ulong i=0UL; i<header_cnt; i++ ) {
257 0 : if( FD_UNLIKELY( headers[ i ].name_len == 8 && !strncasecmp( headers[ i ].name, "location", headers[ i ].name_len ) ) ) {
258 0 : if( FD_UNLIKELY( !headers [ i ].value_len || headers[ i ].value[ 0 ]!='/' ) ) {
259 0 : FD_LOG_WARNING(( "invalid location header `%.*s`", (int)headers[ i ].value_len, headers[ i ].value ));
260 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
261 0 : }
262 :
263 0 : location_len = headers[ i ].value_len;
264 0 : location = headers[ i ].value;
265 0 : break;
266 0 : }
267 0 : }
268 :
269 0 : if( FD_UNLIKELY( !location_len ) ) {
270 0 : FD_LOG_WARNING(( "no location header in redirect response" ));
271 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
272 0 : }
273 :
274 0 : if( FD_UNLIKELY( location_len>=PATH_MAX-1UL ) ) {
275 0 : FD_LOG_WARNING(( "redirect location header too long (%lu)", location_len ));
276 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
277 0 : }
278 :
279 0 : char snapshot_name[ PATH_MAX ];
280 0 : fd_memcpy( snapshot_name, location+1UL, location_len-1UL );
281 0 : snapshot_name[ location_len-1UL ] = '\0';
282 :
283 0 : int is_zstd;
284 0 : ulong full_entry_slot, incremental_entry_slot;
285 0 : uchar decoded_hash[ FD_HASH_FOOTPRINT ];
286 0 : int err = fd_ssarchive_parse_filename( snapshot_name, &full_entry_slot, &incremental_entry_slot, decoded_hash, &is_zstd );
287 :
288 0 : if( FD_UNLIKELY( err || !is_zstd ) ) {
289 0 : FD_LOG_WARNING(( "unrecognized snapshot file `%s` in redirect location header", snapshot_name ));
290 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
291 0 : }
292 :
293 0 : fd_memcpy( result->hash, decoded_hash, FD_HASH_FOOTPRINT );
294 0 : if( FD_LIKELY( incremental_entry_slot==ULONG_MAX ) ) {
295 0 : result->slot = full_entry_slot;
296 0 : result->base_slot = ULONG_MAX;
297 0 : } else {
298 0 : result->slot = incremental_entry_slot;
299 0 : result->base_slot = full_entry_slot;
300 0 : }
301 :
302 0 : if( FD_UNLIKELY( ssresolve->is_https ) ) ssresolve->state = FD_SSRESOLVE_STATE_SHUTTING_DOWN;
303 0 : else ssresolve->state = FD_SSRESOLVE_STATE_DONE;
304 0 : return FD_SSRESOLVE_ADVANCE_RESULT;
305 0 : }
306 :
307 : static int
308 : fd_ssresolve_read_response( fd_ssresolve_t * ssresolve,
309 0 : fd_ssresolve_result_t * result ) {
310 0 : FD_TEST( ssresolve->state==FD_SSRESOLVE_STATE_RESP );
311 :
312 0 : long read = 0L;
313 0 : if( FD_LIKELY( ssresolve->is_https ) ) {
314 0 : #if FD_HAS_OPENSSL
315 0 : int read_res = SSL_read( ssresolve->ssl, ssresolve->response+ssresolve->response_len, (int)(sizeof(ssresolve->response)-ssresolve->response_len) );
316 0 : if( FD_UNLIKELY( read_res<=0 ) ) {
317 0 : int ssl_err = SSL_get_error( ssresolve->ssl, read_res );
318 :
319 0 : if( FD_UNLIKELY( ssl_err!=SSL_ERROR_WANT_READ && ssl_err!=SSL_ERROR_WANT_WRITE ) ) {
320 0 : FD_LOG_WARNING(( "SSL_read failed (%d)", ssl_err ));
321 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
322 0 : }
323 :
324 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
325 0 : }
326 :
327 0 : read = (long)read_res;
328 : #else
329 : FD_LOG_ERR(( "cannot use HTTPS without OpenSSL" ));
330 : #endif
331 0 : } else {
332 0 : read = recvfrom( ssresolve->sockfd, ssresolve->response+ssresolve->response_len, sizeof(ssresolve->response)-ssresolve->response_len, 0, NULL, NULL );
333 0 : if( FD_UNLIKELY( -1==read && errno==EAGAIN ) ) return FD_SSRESOLVE_ADVANCE_AGAIN;
334 0 : else if( FD_UNLIKELY( -1==read ) ) {
335 0 : FD_LOG_WARNING(( "recvfrom() failed (%d-%s)", errno, fd_io_strerror( errno ) ));
336 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
337 0 : }
338 0 : }
339 :
340 0 : ssresolve->response_len += (ulong)read;
341 :
342 0 : int minor_version;
343 0 : int status;
344 0 : const char * message;
345 0 : ulong message_len;
346 0 : struct phr_header headers[ 128UL ];
347 0 : ulong header_cnt = 128UL;
348 0 : int parsed = phr_parse_response( ssresolve->response,
349 0 : ssresolve->response_len,
350 0 : &minor_version,
351 0 : &status,
352 0 : &message,
353 0 : &message_len,
354 0 : headers,
355 0 : &header_cnt,
356 0 : ssresolve->response_len - (ulong)read );
357 0 : if( FD_UNLIKELY( parsed==-1 ) ) {
358 0 : FD_LOG_WARNING(( "malformed response body" ));
359 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
360 0 : } else if( parsed==-2 ) {
361 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
362 0 : }
363 :
364 0 : int is_redirect = (status==301) | (status==302) | (status==303) | (status==307) | (status==308);
365 0 : if( FD_UNLIKELY( is_redirect ) ) {
366 0 : return fd_ssresolve_parse_redirect( ssresolve, headers, header_cnt, result );
367 0 : }
368 :
369 0 : if( FD_UNLIKELY( status!=200 ) ) {
370 0 : char req_path[ 4096UL ];
371 0 : if( FD_LIKELY( ssresolve->is_https ) ) {
372 0 : FD_TEST( fd_cstr_printf_check( req_path, sizeof(req_path), NULL,
373 0 : "https://%s:%u%s", ssresolve->hostname, fd_ushort_bswap( ssresolve->addr.port ), ssresolve->full ? "/snapshot.tar.bz2" : "/incremental-snapshot.tar.bz2" ) );
374 0 : } else {
375 0 : FD_TEST( fd_cstr_printf_check( req_path, sizeof(req_path), NULL,
376 0 : "http://%s:%u%s", ssresolve->hostname, fd_ushort_bswap( ssresolve->addr.port ), ssresolve->full ? "/snapshot.tar.bz2" : "/incremental-snapshot.tar.bz2" ) );
377 0 : }
378 0 : FD_LOG_WARNING(( "unexpected response code %d accessing %s", status, req_path ));
379 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
380 0 : }
381 :
382 : /* 200 without a redirect: the server did not provide the actual
383 : snapshot filename, so we cannot determine the slot or hash. */
384 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
385 0 : }
386 :
387 : #if FD_HAS_OPENSSL
388 : static int
389 0 : ssresolve_connect_ssl( fd_ssresolve_t * ssresolve ) {
390 0 : FD_TEST( ssresolve->ssl );
391 0 : int ssl_err = SSL_connect( ssresolve->ssl );
392 0 : if( FD_UNLIKELY( ssl_err!=1 ) ) {
393 0 : int ssl_err_code = SSL_get_error( ssresolve->ssl, ssl_err );
394 0 : if( FD_UNLIKELY( ssl_err_code!=SSL_ERROR_WANT_READ && ssl_err_code!=SSL_ERROR_WANT_WRITE ) ) {
395 0 : FD_LOG_WARNING(( "SSL_connect failed (%d)", ssl_err_code ));
396 0 : SSL_free( ssresolve->ssl );
397 0 : ssresolve->ssl = NULL;
398 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
399 0 : }
400 : /* in progress */
401 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
402 0 : }
403 :
404 0 : ssresolve->state = FD_SSRESOLVE_STATE_REQ;
405 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
406 0 : }
407 :
408 : static int
409 0 : ssresolve_shutdown_ssl( fd_ssresolve_t * ssresolve ) {
410 0 : int res = SSL_shutdown( ssresolve->ssl );
411 0 : if( FD_LIKELY( res<=0 ) ) {
412 0 : int ssl_err_code = SSL_get_error( ssresolve->ssl, res );
413 0 : if( FD_UNLIKELY( ssl_err_code!=SSL_ERROR_WANT_READ && ssl_err_code!=SSL_ERROR_WANT_WRITE && res!=0 ) ) {
414 0 : FD_LOG_WARNING(( "SSL_shutdown failed (%d)", ssl_err_code ));
415 0 : SSL_free( ssresolve->ssl );
416 0 : ssresolve->ssl = NULL;
417 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
418 0 : }
419 :
420 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
421 0 : }
422 :
423 0 : ssresolve->state = FD_SSRESOLVE_STATE_DONE;
424 0 : return FD_SSRESOLVE_ADVANCE_SUCCESS;
425 0 : }
426 : #endif
427 :
428 : int
429 0 : fd_ssresolve_advance_poll_out( fd_ssresolve_t * ssresolve ) {
430 0 : int res;
431 0 : switch( ssresolve->state ) {
432 0 : #if FD_HAS_OPENSSL
433 0 : case FD_SSRESOLVE_CONNECT: {
434 0 : res = ssresolve_connect_ssl( ssresolve );
435 0 : break;
436 0 : }
437 0 : case FD_SSRESOLVE_STATE_SHUTTING_DOWN: {
438 0 : res = ssresolve_shutdown_ssl( ssresolve );
439 0 : break;
440 0 : }
441 0 : #endif
442 0 : case FD_SSRESOLVE_STATE_REQ: {
443 0 : res = fd_ssresolve_send_request( ssresolve );
444 0 : break;
445 0 : }
446 0 : case FD_SSRESOLVE_STATE_RESP: {
447 0 : res = FD_SSRESOLVE_ADVANCE_AGAIN;
448 0 : break;
449 0 : }
450 0 : default: {
451 0 : FD_LOG_ERR(( "unexpected state %d", ssresolve->state ));
452 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
453 0 : }
454 0 : }
455 0 : return res;
456 0 : }
457 :
458 : int
459 : fd_ssresolve_advance_poll_in( fd_ssresolve_t * ssresolve,
460 0 : fd_ssresolve_result_t * result ) {
461 0 : int res;
462 0 : switch( ssresolve->state ) {
463 0 : #if FD_HAS_OPENSSL
464 0 : case FD_SSRESOLVE_CONNECT: {
465 0 : res = ssresolve_connect_ssl( ssresolve );
466 0 : break;
467 0 : }
468 0 : case FD_SSRESOLVE_STATE_SHUTTING_DOWN: {
469 0 : res = ssresolve_shutdown_ssl( ssresolve );
470 0 : break;
471 0 : }
472 0 : #endif
473 0 : case FD_SSRESOLVE_STATE_RESP: {
474 0 : res = fd_ssresolve_read_response( ssresolve, result );
475 0 : break;
476 0 : }
477 0 : case FD_SSRESOLVE_STATE_REQ: {
478 0 : res = FD_SSRESOLVE_ADVANCE_AGAIN;
479 0 : break;
480 0 : }
481 0 : case FD_SSRESOLVE_STATE_DONE: {
482 0 : res = FD_SSRESOLVE_ADVANCE_SUCCESS;
483 0 : break;
484 0 : }
485 0 : default: {
486 0 : FD_LOG_ERR(( "unexpected state %d", ssresolve->state ));
487 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
488 0 : }
489 0 : }
490 :
491 0 : return res;
492 0 : }
493 :
494 : int
495 0 : fd_ssresolve_is_done( fd_ssresolve_t * ssresolve ) {
496 0 : return ssresolve->state==FD_SSRESOLVE_STATE_DONE;
497 0 : }
498 :
499 : void
500 0 : fd_ssresolve_cancel( fd_ssresolve_t * ssresolve ) {
501 0 : if( FD_LIKELY( ssresolve->sockfd!=-1 ) ) {
502 0 : if( FD_UNLIKELY( -1==close( ssresolve->sockfd ) ) ) FD_LOG_ERR(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
503 0 : ssresolve->sockfd = -1;
504 0 : }
505 0 : #if FD_HAS_OPENSSL
506 0 : if( FD_LIKELY( ssresolve->ssl ) ) {
507 0 : SSL_free( ssresolve->ssl );
508 : ssresolve->ssl = NULL;
509 0 : }
510 0 : #endif
511 0 : }
|