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