int32_t Openssl_Send()

in platform/posix/transport/src/openssl_posix.c [868:949]


int32_t Openssl_Send( NetworkContext_t * pNetworkContext,
                      const void * pBuffer,
                      size_t bytesToSend )
{
    OpensslParams_t * pOpensslParams = NULL;
    int32_t bytesSent = 0;

    if( !isValidNetworkContext( pNetworkContext ) ||
        ( pBuffer == NULL ) ||
        ( bytesToSend == 0 ) )
    {
        LogError( ( "Parameter check failed: invalid input, pNetworkContext is invalid or pBuffer = %p, bytesToSend = %lu", pBuffer, bytesToSend ) );
        bytesSent = -1;
    }
    else
    {
        struct pollfd pollFds;
        int32_t pollStatus;

        pOpensslParams = pNetworkContext->pParams;

        /* Initialize the file descriptor. */
        pollFds.events = POLLOUT;
        pollFds.revents = 0;
        /* Set the file descriptor for poll. */
        pollFds.fd = pOpensslParams->socketDescriptor;

        /* `poll` checks if the socket is ready to send data.
         * Note: This is done to avoid blocking on SSL_write()
         * when TCP socket is not ready to accept more data for
         * network transmission (possibly due to a full TX buffer). */
        pollStatus = poll( &pollFds, 1, 0 );

        if( pollStatus > 0 )
        {
            /* SSL write of data. */
            bytesSent = ( int32_t ) SSL_write( pOpensslParams->pSsl, pBuffer,
                                               ( int32_t ) bytesToSend );

            if( bytesSent <= 0 )
            {
                LogError(
                    ( "Failed to send data over network: SSL_write of OpenSSL failed: "
                      "ErrorStatus=%s.",
                      ERR_reason_error_string( SSL_get_error( pOpensslParams->pSsl, bytesSent ) ) ) );

                /* As the SSL context is configured for blocking mode, the SSL_write()
                 * function does not return an SSL_ERROR_WANT_READ or
                 * SSL_ERROR_WANT_WRITE error code. The SSL_ERROR_WANT_READ and
                 * SSL_ERROR_WANT_WRITE error codes signify that the write operation can
                 * be retried. However, in the blocking mode, as the SSL_write()
                 * function does not return either of the error codes, we cannot retry
                 * the operation on failure, and thus, this function will never return a
                 * zero error code.
                 */

                /* The transport interface requires zero return code only when the send
                 * operation can be retried to achieve success. Thus, convert a zero
                 * error code to a negative return value as this cannot be retried. */
                if( bytesSent == 0 )
                {
                    bytesSent = -1;
                }
            }
        }
        else if( pollStatus < 0 )
        {
            /* An error occurred while polling. */
            LogError( ( "Unable to send TLS data on network: "
                        "An error occurred while checking availability of TCP socket %d.",
                        pOpensslParams->socketDescriptor ) );
            bytesSent = -1;
        }
        else
        {
            /* Socket is not available for sending data. Set return code for retrying send. */
            bytesSent = 0;
        }
    }

    return bytesSent;
}