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 0 : fd_ssresolve_align( void ) {
52 0 : return FD_SSRESOLVE_ALIGN;
53 0 : }
54 :
55 : FD_FN_CONST ulong
56 0 : fd_ssresolve_footprint( void ) {
57 0 : ulong l;
58 0 : l = FD_LAYOUT_INIT;
59 0 : l = FD_LAYOUT_APPEND( l, FD_SSRESOLVE_ALIGN, sizeof(fd_ssresolve_t) );
60 0 : return FD_LAYOUT_FINI( l, FD_SSRESOLVE_ALIGN );
61 0 : }
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 */
166 0 : FD_TEST( hostname && hostname[ 0 ]!='\0' );
167 0 : int set1_host_res = SSL_set1_host( ssresolve->ssl, hostname );
168 0 : if( FD_UNLIKELY( !set1_host_res ) ) {
169 0 : FD_LOG_ERR(( "SSL_set1_host failed (%d)", set1_host_res ));
170 0 : }
171 :
172 0 : FD_TEST( fd_openssl_ssl_set_fd( ssresolve->ssl, ssresolve->sockfd ) );
173 0 : }
174 : #endif
175 :
176 : static void
177 0 : fd_ssresolve_render_req( fd_ssresolve_t * ssresolve ) {
178 0 : char const * path = ssresolve->full ? "/snapshot.tar.bz2" : "/incremental-snapshot.tar.bz2";
179 :
180 0 : if( FD_LIKELY( ssresolve->hostname && ssresolve->hostname[ 0 ]!='\0' ) ) {
181 0 : FD_TEST( fd_cstr_printf_check( ssresolve->request, sizeof(ssresolve->request), &ssresolve->request_len,
182 0 : "HEAD %s HTTP/1.1\r\n"
183 0 : "User-Agent: Firedancer\r\n"
184 0 : "Accept: */*\r\n"
185 0 : "Accept-Encoding: identity\r\n"
186 0 : "Host: %s\r\n\r\n",
187 0 : path, ssresolve->hostname ) );
188 0 : } else {
189 0 : FD_TEST( fd_cstr_printf_check( ssresolve->request, sizeof(ssresolve->request), &ssresolve->request_len,
190 0 : "HEAD %s HTTP/1.1\r\n"
191 0 : "User-Agent: Firedancer\r\n"
192 0 : "Accept: */*\r\n"
193 0 : "Accept-Encoding: identity\r\n"
194 0 : "Host: " FD_IP4_ADDR_FMT "\r\n\r\n",
195 0 : path, FD_IP4_ADDR_FMT_ARGS( ssresolve->addr.addr ) ) );
196 0 : }
197 0 : }
198 :
199 : static int
200 0 : fd_ssresolve_send_request( fd_ssresolve_t * ssresolve ) {
201 0 : FD_TEST( ssresolve->state==FD_SSRESOLVE_STATE_REQ );
202 :
203 0 : if( FD_UNLIKELY( !ssresolve->request_len ) ) {
204 0 : fd_ssresolve_render_req( ssresolve );
205 0 : }
206 :
207 0 : long sent = 0L;
208 0 : if( FD_LIKELY( ssresolve->is_https ) ) {
209 0 : #if FD_HAS_OPENSSL
210 0 : int write_res = SSL_write( ssresolve->ssl, ssresolve->request+ssresolve->request_sent, (int)(ssresolve->request_len-ssresolve->request_sent) );
211 0 : if( FD_UNLIKELY( write_res<=0 ) ) {
212 0 : int ssl_err = SSL_get_error( ssresolve->ssl, write_res );
213 :
214 0 : if( FD_UNLIKELY( ssl_err!=SSL_ERROR_WANT_READ && ssl_err!=SSL_ERROR_WANT_WRITE ) ) {
215 0 : FD_LOG_WARNING(( "SSL_write failed (%d)", ssl_err ));
216 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
217 0 : }
218 :
219 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
220 0 : }
221 :
222 0 : sent = (long)write_res;
223 : #else
224 : FD_LOG_ERR(( "cannot use HTTPS without OpenSSL" ));
225 : #endif
226 0 : } else {
227 0 : sent = sendto( ssresolve->sockfd, ssresolve->request+ssresolve->request_sent, ssresolve->request_len-ssresolve->request_sent, MSG_NOSIGNAL, NULL, 0 );
228 0 : if( FD_UNLIKELY( -1==sent && errno==EAGAIN ) ) return FD_SSRESOLVE_ADVANCE_AGAIN;
229 0 : else if( FD_UNLIKELY( -1==sent ) ) {
230 0 : FD_LOG_WARNING(( "sendto() failed (%d-%s)", errno, fd_io_strerror( errno ) ));
231 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
232 0 : }
233 0 : }
234 :
235 0 : ssresolve->request_sent += (ulong)sent;
236 0 : if( FD_UNLIKELY( ssresolve->request_sent==ssresolve->request_len ) ) {
237 0 : ssresolve->state = FD_SSRESOLVE_STATE_RESP;
238 0 : return FD_SSRESOLVE_ADVANCE_SUCCESS;
239 0 : }
240 :
241 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
242 0 : }
243 :
244 : static int
245 : fd_ssresolve_parse_redirect( fd_ssresolve_t * ssresolve,
246 : struct phr_header * headers,
247 : ulong header_cnt,
248 0 : fd_ssresolve_result_t * result ) {
249 0 : ulong location_len = 0UL;
250 0 : char const * location = NULL;
251 :
252 0 : for( ulong i=0UL; i<header_cnt; i++ ) {
253 0 : if( FD_UNLIKELY( headers[ i ].name_len == 8 && !strncasecmp( headers[ i ].name, "location", headers[ i ].name_len ) ) ) {
254 0 : if( FD_UNLIKELY( !headers [ i ].value_len || headers[ i ].value[ 0 ]!='/' ) ) {
255 0 : FD_LOG_WARNING(( "invalid location header `%.*s`", (int)headers[ i ].value_len, headers[ i ].value ));
256 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
257 0 : }
258 :
259 0 : location_len = headers[ i ].value_len;
260 0 : location = headers[ i ].value;
261 0 : break;
262 0 : }
263 0 : }
264 :
265 0 : if( FD_UNLIKELY( !location_len ) ) {
266 0 : FD_LOG_WARNING(( "no location header in redirect response" ));
267 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
268 0 : }
269 :
270 0 : if( FD_UNLIKELY( location_len>=PATH_MAX-1UL ) ) {
271 0 : FD_LOG_WARNING(( "redirect location header too long (%lu)", location_len ));
272 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
273 0 : }
274 :
275 0 : char snapshot_name[ PATH_MAX ];
276 0 : fd_memcpy( snapshot_name, location+1UL, location_len-1UL );
277 0 : snapshot_name[ location_len-1UL ] = '\0';
278 :
279 0 : int is_zstd;
280 0 : ulong full_entry_slot, incremental_entry_slot;
281 0 : uchar decoded_hash[ FD_HASH_FOOTPRINT ];
282 0 : int err = fd_ssarchive_parse_filename( snapshot_name, &full_entry_slot, &incremental_entry_slot, decoded_hash, &is_zstd );
283 :
284 0 : if( FD_UNLIKELY( err || !is_zstd ) ) {
285 0 : FD_LOG_WARNING(( "unrecognized snapshot file `%s` in redirect location header", snapshot_name ));
286 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
287 0 : }
288 :
289 0 : fd_memcpy( result->hash, decoded_hash, FD_HASH_FOOTPRINT );
290 0 : if( FD_LIKELY( incremental_entry_slot==ULONG_MAX ) ) {
291 0 : result->slot = full_entry_slot;
292 0 : result->base_slot = ULONG_MAX;
293 0 : } else {
294 0 : result->slot = incremental_entry_slot;
295 0 : result->base_slot = full_entry_slot;
296 0 : }
297 :
298 0 : if( FD_UNLIKELY( ssresolve->is_https ) ) ssresolve->state = FD_SSRESOLVE_STATE_SHUTTING_DOWN;
299 0 : else ssresolve->state = FD_SSRESOLVE_STATE_DONE;
300 0 : return FD_SSRESOLVE_ADVANCE_RESULT;
301 0 : }
302 :
303 : static int
304 : fd_ssresolve_read_response( fd_ssresolve_t * ssresolve,
305 0 : fd_ssresolve_result_t * result ) {
306 0 : FD_TEST( ssresolve->state==FD_SSRESOLVE_STATE_RESP );
307 :
308 0 : long read = 0L;
309 0 : if( FD_LIKELY( ssresolve->is_https ) ) {
310 0 : #if FD_HAS_OPENSSL
311 0 : int read_res = SSL_read( ssresolve->ssl, ssresolve->response+ssresolve->response_len, (int)(sizeof(ssresolve->response)-ssresolve->response_len) );
312 0 : if( FD_UNLIKELY( read_res<=0 ) ) {
313 0 : int ssl_err = SSL_get_error( ssresolve->ssl, read_res );
314 :
315 0 : if( FD_UNLIKELY( ssl_err!=SSL_ERROR_WANT_READ && ssl_err!=SSL_ERROR_WANT_WRITE ) ) {
316 0 : FD_LOG_WARNING(( "SSL_read failed (%d)", ssl_err ));
317 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
318 0 : }
319 :
320 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
321 0 : }
322 :
323 0 : read = (long)read_res;
324 : #else
325 : FD_LOG_ERR(( "cannot use HTTPS without OpenSSL" ));
326 : #endif
327 0 : } else {
328 0 : read = recvfrom( ssresolve->sockfd, ssresolve->response+ssresolve->response_len, sizeof(ssresolve->response)-ssresolve->response_len, 0, NULL, NULL );
329 0 : if( FD_UNLIKELY( -1==read && errno==EAGAIN ) ) return FD_SSRESOLVE_ADVANCE_AGAIN;
330 0 : else if( FD_UNLIKELY( -1==read ) ) {
331 0 : FD_LOG_WARNING(( "recvfrom() failed (%d-%s)", errno, fd_io_strerror( errno ) ));
332 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
333 0 : }
334 0 : }
335 :
336 0 : ssresolve->response_len += (ulong)read;
337 :
338 0 : int minor_version;
339 0 : int status;
340 0 : const char * message;
341 0 : ulong message_len;
342 0 : struct phr_header headers[ 128UL ];
343 0 : ulong header_cnt = 128UL;
344 0 : int parsed = phr_parse_response( ssresolve->response,
345 0 : ssresolve->response_len,
346 0 : &minor_version,
347 0 : &status,
348 0 : &message,
349 0 : &message_len,
350 0 : headers,
351 0 : &header_cnt,
352 0 : ssresolve->response_len - (ulong)read );
353 0 : if( FD_UNLIKELY( parsed==-1 ) ) {
354 0 : FD_LOG_WARNING(( "malformed response body" ));
355 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
356 0 : } else if( parsed==-2 ) {
357 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
358 0 : }
359 :
360 0 : int is_redirect = (status==301) | (status==302) | (status==303) | (status==307) | (status==308);
361 0 : if( FD_UNLIKELY( is_redirect ) ) {
362 0 : return fd_ssresolve_parse_redirect( ssresolve, headers, header_cnt, result );
363 0 : }
364 :
365 0 : if( FD_UNLIKELY( status!=200 ) ) {
366 0 : char req_path[ 4096UL ];
367 0 : if( FD_LIKELY( ssresolve->is_https ) ) {
368 0 : FD_TEST( fd_cstr_printf_check( req_path, sizeof(req_path), NULL,
369 0 : "https://%s:%u%s", ssresolve->hostname, fd_ushort_bswap( ssresolve->addr.port ), ssresolve->full ? "/snapshot.tar.bz2" : "/incremental-snapshot.tar.bz2" ) );
370 0 : } else {
371 0 : FD_TEST( fd_cstr_printf_check( req_path, sizeof(req_path), NULL,
372 0 : "http://%s:%u%s", ssresolve->hostname, fd_ushort_bswap( ssresolve->addr.port ), ssresolve->full ? "/snapshot.tar.bz2" : "/incremental-snapshot.tar.bz2" ) );
373 0 : }
374 0 : FD_LOG_WARNING(( "unexpected response code %d accessing %s", status, req_path ));
375 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
376 0 : }
377 :
378 : /* 200 without a redirect: the server did not provide the actual
379 : snapshot filename, so we cannot determine the slot or hash. */
380 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
381 0 : }
382 :
383 : #if FD_HAS_OPENSSL
384 : static int
385 0 : ssresolve_connect_ssl( fd_ssresolve_t * ssresolve ) {
386 0 : FD_TEST( ssresolve->ssl );
387 0 : int ssl_err = SSL_connect( ssresolve->ssl );
388 0 : if( FD_UNLIKELY( ssl_err!=1 ) ) {
389 0 : int ssl_err_code = SSL_get_error( ssresolve->ssl, ssl_err );
390 0 : if( FD_UNLIKELY( ssl_err_code!=SSL_ERROR_WANT_READ && ssl_err_code!=SSL_ERROR_WANT_WRITE ) ) {
391 0 : FD_LOG_WARNING(( "SSL_connect failed (%d)", ssl_err_code ));
392 0 : SSL_free( ssresolve->ssl );
393 0 : ssresolve->ssl = NULL;
394 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
395 0 : }
396 : /* in progress */
397 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
398 0 : }
399 :
400 0 : ssresolve->state = FD_SSRESOLVE_STATE_REQ;
401 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
402 0 : }
403 :
404 : static int
405 0 : ssresolve_shutdown_ssl( fd_ssresolve_t * ssresolve ) {
406 0 : int res = SSL_shutdown( ssresolve->ssl );
407 0 : if( FD_LIKELY( res<=0 ) ) {
408 0 : int ssl_err_code = SSL_get_error( ssresolve->ssl, res );
409 0 : if( FD_UNLIKELY( ssl_err_code!=SSL_ERROR_WANT_READ && ssl_err_code!=SSL_ERROR_WANT_WRITE && res!=0 ) ) {
410 0 : FD_LOG_WARNING(( "SSL_shutdown failed (%d)", ssl_err_code ));
411 0 : SSL_free( ssresolve->ssl );
412 0 : ssresolve->ssl = NULL;
413 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
414 0 : }
415 :
416 0 : return FD_SSRESOLVE_ADVANCE_AGAIN;
417 0 : }
418 :
419 0 : ssresolve->state = FD_SSRESOLVE_STATE_DONE;
420 0 : return FD_SSRESOLVE_ADVANCE_SUCCESS;
421 0 : }
422 : #endif
423 :
424 : int
425 0 : fd_ssresolve_advance_poll_out( fd_ssresolve_t * ssresolve ) {
426 0 : int res;
427 0 : switch( ssresolve->state ) {
428 0 : #if FD_HAS_OPENSSL
429 0 : case FD_SSRESOLVE_CONNECT: {
430 0 : res = ssresolve_connect_ssl( ssresolve );
431 0 : break;
432 0 : }
433 0 : case FD_SSRESOLVE_STATE_SHUTTING_DOWN: {
434 0 : res = ssresolve_shutdown_ssl( ssresolve );
435 0 : break;
436 0 : }
437 0 : #endif
438 0 : case FD_SSRESOLVE_STATE_REQ: {
439 0 : res = fd_ssresolve_send_request( ssresolve );
440 0 : break;
441 0 : }
442 0 : case FD_SSRESOLVE_STATE_RESP: {
443 0 : res = FD_SSRESOLVE_ADVANCE_AGAIN;
444 0 : break;
445 0 : }
446 0 : default: {
447 0 : FD_LOG_ERR(( "unexpected state %d", ssresolve->state ));
448 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
449 0 : }
450 0 : }
451 0 : return res;
452 0 : }
453 :
454 : int
455 : fd_ssresolve_advance_poll_in( fd_ssresolve_t * ssresolve,
456 0 : fd_ssresolve_result_t * result ) {
457 0 : int res;
458 0 : switch( ssresolve->state ) {
459 0 : #if FD_HAS_OPENSSL
460 0 : case FD_SSRESOLVE_CONNECT: {
461 0 : res = ssresolve_connect_ssl( ssresolve );
462 0 : break;
463 0 : }
464 0 : case FD_SSRESOLVE_STATE_SHUTTING_DOWN: {
465 0 : res = ssresolve_shutdown_ssl( ssresolve );
466 0 : break;
467 0 : }
468 0 : #endif
469 0 : case FD_SSRESOLVE_STATE_RESP: {
470 0 : res = fd_ssresolve_read_response( ssresolve, result );
471 0 : break;
472 0 : }
473 0 : case FD_SSRESOLVE_STATE_REQ: {
474 0 : res = FD_SSRESOLVE_ADVANCE_AGAIN;
475 0 : break;
476 0 : }
477 0 : case FD_SSRESOLVE_STATE_DONE: {
478 0 : res = FD_SSRESOLVE_ADVANCE_SUCCESS;
479 0 : break;
480 0 : }
481 0 : default: {
482 0 : FD_LOG_ERR(( "unexpected state %d", ssresolve->state ));
483 0 : return FD_SSRESOLVE_ADVANCE_ERROR;
484 0 : }
485 0 : }
486 :
487 0 : return res;
488 0 : }
489 :
490 : int
491 0 : fd_ssresolve_is_done( fd_ssresolve_t * ssresolve ) {
492 0 : return ssresolve->state==FD_SSRESOLVE_STATE_DONE;
493 0 : }
494 :
495 : void
496 0 : fd_ssresolve_cancel( fd_ssresolve_t * ssresolve ) {
497 0 : if( FD_LIKELY( ssresolve->sockfd!=-1 ) ) {
498 0 : if( FD_UNLIKELY( -1==close( ssresolve->sockfd ) ) ) FD_LOG_ERR(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
499 0 : ssresolve->sockfd = -1;
500 0 : }
501 0 : #if FD_HAS_OPENSSL
502 0 : if( FD_LIKELY( ssresolve->ssl ) ) {
503 0 : SSL_free( ssresolve->ssl );
504 0 : ssresolve->ssl = NULL;
505 0 : }
506 0 : #endif
507 0 : }
|