Purpose: Establish an SSL TCP connection to a server

Return TypeFunction nameArguments
hzEcodehzTcpClient::ConnectSSL(const char*,uint32_t,uint32_t,uint32_t,)

Declared in file: hzTcpClient.h
Defined in file : hzTcpClient.cpp

Function Logic:

0:START 1:unknown 2:items bBeenHere 3:unknown 4:unknown 5:Return E_OK 6:items m_pHost items 7:unknown 8:m_Hostname m_pHost 9:m_pHost 10:unknown 11:items 12:unknown 13:Return E_DNS_RETRY 14:unknown 15:Return E_DNS_NOHOST 16:unknown 17:Return E_DNS_FAILED 18:unknown 19:Return E_DNS_NODATA 20:items 21:Return hzerr(E_DNS_NOHOST,Unknown Host [%s]\n,hostname) 22:m_Hostname m_nPort items m_SvrAddr items m_SvrAddr 23:unknown 24:Return hzerr(E_INITFAIL,Could not create socket (returns %d, errno=%d),m_nSock,errno) 25:items sys_rc 26:unknown 27:items 28:Return hzerr(E_HOSTFAIL,Could not connect to host [%s] on port %d (errno=%d),*m_Hostname,m_nPort,errno) 29:items 30:unknown 31:nTimeoutR 32:unknown 33:nTimeoutS 34:unknown 35:rc 36:unknown 37:rc 38:unknown 39:Return hzerr(rc,Could not set connection timeouts) 40:items sslMethod 41:unknown 42:items 43:Return hzerr(E_INITFAIL,No SSL Client Method issued) 44:items sslCtx 45:unknown 46:items items 47:items m_pSSL 48:unknown 49:items 50:Return E_HOSTFAIL 51:items sys_rc 52:unknown 53:items 54:Return E_HOSTFAIL 55:items items items items sys_rc items 56:unknown 57:items 58:Return E_HOSTFAIL 59:items 60:Return E_OK

Function body:

hzEcode hzTcpClient::ConnectSSL (const char* hostname)uint32_t nPort, uint32_t nTimeoutR, uint32_t nTimeoutS, 
{
   //  Purpose: Establish an SSL TCP connection to a server
   //  
   //  Arguments: 1) hostname The server name or IP address
   //     2) nPort  The port number
   //     3) nTimeoutR Timeout (Recv)
   //     4) nTimeoutS Timeout (Send)
   //  
   //  Returns: E_DNS_NOHOST If the domain does not exist
   //     E_DNS_FAILED If the domain settings were invalid
   //     E_DNS_NODATA If the domain exists but no server found
   //     E_DNS_RETRY  If the DNS was busy
   //     E_INITFAIL  If the SSL client side settings fail
   //     E_NOSOCKET  If a socket could not be obtained
   //     E_HOSTFAIL  If no connection could be established or if socket options were not set.
   //     E_OK   If a connection to the host was established
   _hzfunc("hzTcpClient::ConnectSSL") ;
   static  bool    bBeenHere = false ;     //  OPENSSL init state
   const SSL_METHOD*   sslMethod = 0;      //  SSL client method
   SSL_CTX*            sslCtx = 0;     //  SSL client CTX structure
   int32_t     sys_rc ;        //  Return from connect call
   hzEcode     rc = E_OK ;     //  Return code
   //  Ensure SSL/TLS is initialized
   if (!bBeenHere)
   {
       #if OPENSSL_VERSION_NUMBER < 0x10100000L
           SSL_library_init();
       #else
           OPENSSL_init_ssl(0,NULL);
       #endif
       bBeenHere = true ;
   }
   //  Check we are not already connected
   if (m_nSock)
   {
       if (m_Hostname == hostname && m_nPort == nPort)
           return E_OK ;
       m_Hostname.Clear() ;
       m_pHost = 0;
       Close() ;
   }
   if (m_Hostname && m_Hostname != hostname)
   {
       //  At the point of call there was no socket but this hzTcpClient instance has a hostname from a previous connection. If this differs from the host now
       //  being sought then the m_pHost value will be invalid and a fresh call to gethostbyname is required.
       m_Hostname = hostname ;
       m_pHost = 0;
   }
   //  Get the host IP
   m_pHost = gethostbyname(hostname) ;
   if (!m_pHost)
   {
       threadLog("No Host found\n") ;
       if (h_errno == TRY_AGAIN)       return E_DNS_RETRY ;
       if (h_errno == HOST_NOT_FOUND)  return E_DNS_NOHOST ;
       if (h_errno == NO_RECOVERY)     return E_DNS_FAILED ;
       if (h_errno == NO_DATA || h_errno == NO_ADDRESS)
           return E_DNS_NODATA ;
       m_Hostname.Clear() ;
       return hzerr(E_DNS_NOHOST, "Unknown Host [%s]\n", hostname) ;
   }
   m_Hostname = hostname ;
   m_nPort = nPort ;
   //  Create the socket
   memset(&m_SvrAddr, 0,sizeof(m_SvrAddr)) ;
   m_SvrAddr.sin_family = AF_INET ;
   memcpy(&m_SvrAddr.sin_addr, m_pHost->h_addr, m_pHost->h_length) ;
   m_SvrAddr.sin_port = htons(nPort) ;
   if ((m_nSock = socket(AF_INET, SOCK_STREAM, 0))< 0)
       return hzerr(E_INITFAIL, "Could not create socket (returns %d, errno=%d)", m_nSock, errno) ;
   threadLog("Using socket %d\n", m_nSock) ;
   //  Establish a standard, non-SSL TCP/IP connection
   sys_rc = connect(m_nSock, (SOCKADDR*) &m_SvrAddr, sizeof(m_SvrAddr)) ;
   if (sys_rc < 0)
   {
       threadLog("Could not connect to host (returns %d)", sys_rc) ;
       return hzerr(E_HOSTFAIL, "Could not connect to host [%s] on port %d (errno=%d)", *m_Hostname, m_nPort, errno) ;
   }
   threadLog("Connected\n") ;
   //  Apply timeouts
   if (!nTimeoutR)     nTimeoutR = 90;
   if (!nTimeoutS)     nTimeoutS = 90;
   if (rc == E_OK)     rc = SetRecvTimeout(nTimeoutR) ;
   if (rc == E_OK)     rc = SetSendTimeout(nTimeoutS) ;
   if (rc != E_OK)
       return hzerr(rc, "Could not set connection timeouts") ;
   threadLog("Socket options set\n") ;
   /*
   **  ** SSL/TLS part
   **      */
   sslMethod = TLS_client_method() ;
   if (!sslMethod)
   {
       Close() ;
       return hzerr(E_INITFAIL, "No SSL Client Method issued") ;
   }
   threadLog("Method set\n") ;
   sslCtx = SSL_CTX_new(sslMethod) ;
   if (!sslCtx)
   {
       Close() ;
       hzerr(E_INITFAIL, "No SSL Structure issued") ;
   }
   threadLog("CTX Created\n") ;
   m_pSSL = SSL_new(sslCtx) ;
   if (!m_pSSL)
   {
       threadLog("Could not allocate SSL structure\n") ;
       return E_HOSTFAIL ;
   }
   threadLog("SSL allocated\n") ;
   /*
   **  if (SSL_CTX_set_cipher_list(sslCtx, "ECDHE-RSA-AES128-GCM-SHA256") <= 0)
   **   {
   **    threadLog("Error setting the cipher list.\n");
   **    return E_HOSTFAIL ;
   **   }
   **   threadLog("Cipers Listed\n") ;
   **      */
   sys_rc = SSL_set_fd(m_pSSL, m_nSock);
   if (sys_rc != 1)
   {
       threadLog("Could not set SSL file descriptor\n") ;
       return E_HOSTFAIL ;
   }
   threadLog("SSL fd set\n") ;
   SSL_set_tlsext_host_name(m_pSSL, *m_Hostname) ;
   SSL_set_connect_state(m_pSSL) ;
   threadLog("SSL set as client\n") ;
   sys_rc = SSL_connect(m_pSSL);
   //  sys_rc = SSL_do_handshake(m_pSSL);
   threadLog("Handshake done\n") ;
   if (sys_rc != 1)
   {
       threadLog("Could not connect: %s\n", ShowErrorSSL(SSL_get_error(m_pSSL, sys_rc))) ;
       return E_HOSTFAIL ;
   }
   threadLog("Connected Secure\n") ;
   /*
   **  Move to separate function or scrap
   **   if (bCheckCert)
   **   {
   **    if (SSL_get_peer_certificate(m_pSSL) != NULL)
   **    {
   **     if (SSL_get_verify_result(m_pSSL) == X509_V_OK)
   **      threadLog("Client verification with SSL_get_verify_result() succeeded.\n") ;
   **     else
   **      threadLog("Client verification with SSL_get_verify_result() failed.\n") ;
   **    }
   **   }
   **      */
   return E_OK ;
}