LCOV - code coverage report
Current view: top level - discof/restore/utils - fd_ssresolve.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 9 361 2.5 %
Date: 2026-06-29 05:51:35 Functions: 2 16 12.5 %

          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 : }

Generated by: LCOV version 1.14