int32_t SOCKETS_SetSockOpt()

in amazon-freertos/lib/secure_sockets/portable/ti/cc3220_launchpad/aws_secure_sockets.c [1018:1242]


int32_t SOCKETS_SetSockOpt( Socket_t xSocket,
                            int32_t lLevel,
                            int32_t lOptionName,
                            const void * pvOptionValue,
                            size_t xOptionLength )
{
    SSocketContextPtr_t pxSocketContext;
    SlSockNonblocking_t xSockNonblocking;
    struct SlTimeval_t xTimeVal;
    _i16 sTIRetCode;
    int32_t lRetCode = SOCKETS_SOCKET_ERROR;
    uint32_t ulTimeoutInMilliseconds;
    uint32_t ulSocketNumber = ( uint32_t ) xSocket;

    /* Remove compiler warnings about unused parameters. */
    ( void ) lLevel;

    /* Ensure that the socket is valid. */
    if( prvIsValidSocket( ulSocketNumber ) == pdTRUE )
    {
        /* Shortcut for easy access. */
        pxSocketContext = &( xSockets[ ulSocketNumber ] );

        switch( lOptionName )
        {
            case SOCKETS_SO_SERVER_NAME_INDICATION:

                if( ( pxSocketContext->ulFlags & securesocketsSOCKET_IS_CONNECTED ) == 0 )
                {
                    /* Set Server Name Indication (SNI) on the TI socket. */
                    sTIRetCode = sl_SetSockOpt( pxSocketContext->sSocketDescriptor,
                                                SL_SOL_SOCKET,
                                                SL_SO_SECURE_DOMAIN_NAME_VERIFICATION,
                                                pvOptionValue,
                                                ( SlSocklen_t ) xOptionLength );

                    /* If the above sl_SetSockOpt succeeded, return success to the user. */
                    if( sTIRetCode >= 0 )
                    {
                        lRetCode = SOCKETS_ERROR_NONE;
                    }
                    else
                    {
                        /* See \lib\third_party\mcu_vendor\ti\SimpleLink_CC32xx\v2_10_00_04\source\ti\drivers\net\wifi\errors.h */
                        SOCKETS_PRINT( ( "ERROR: %d SockOpt SNI failed.\r\n", sTIRetCode ) );
                    }
                }
                else
                {
                    lRetCode = SOCKETS_SOCKET_ERROR;
                    SOCKETS_PRINT( ( "ERROR: SNI must be set before connection is established.\r\n" ) );
                }

                break;

            case SOCKETS_SO_TRUSTED_SERVER_CERTIFICATE:

                if( ( pxSocketContext->ulFlags & securesocketsSOCKET_IS_CONNECTED ) == 0 )
                {
                    /* Write the certificate to the file system. */
                    lRetCode = prvWriteCertificate( socketsconfigSECURE_FILE_NAME_CUSTOMROOTCA,
                                                    pvOptionValue,
                                                    xOptionLength - 1U );

                    /* If the certificate was successfully written to the
                     * file system, use it for the socket. */
                    if( lRetCode == SOCKETS_ERROR_NONE )
                    {
                        sTIRetCode = sl_SetSockOpt( pxSocketContext->sSocketDescriptor,
                                                    SL_SOL_SOCKET,
                                                    SL_SO_SECURE_FILES_CA_FILE_NAME,
                                                    socketsconfigSECURE_FILE_NAME_CUSTOMROOTCA,
                                                    ( SlSocklen_t ) strlen( socketsconfigSECURE_FILE_NAME_CUSTOMROOTCA ) );

                        if( sTIRetCode >= 0 )
                        {
                            /* Mark the socket as having a custom trusted root CA. */
                            pxSocketContext->ulFlags |= securesocketsSOCKET_TRUSTED_SERVER_CERT_FLAG;
                        }
                        else
                        {
                            /* See \lib\third_party\mcu_vendor\ti\SimpleLink_CC32xx\v2_10_00_04\source\ti\drivers\net\wifi\errors.h */
                            SOCKETS_PRINT( ( "ERROR: %d Failed to set the custom root certificate.\r\n", sTIRetCode ) );
                            lRetCode = SOCKETS_SOCKET_ERROR;
                        }
                    }
                }
                else
                {
                    lRetCode = SOCKETS_SOCKET_ERROR;
                    SOCKETS_PRINT( ( "ERROR: Secure trusted cert must be set before connection is established.\r\n" ) );
                }

                break;

            case SOCKETS_SO_REQUIRE_TLS:

                if( ( pxSocketContext->ulFlags & securesocketsSOCKET_IS_CONNECTED ) == 0 )
                {
                    /* Create the semaphore required for synchronizing TLS handshake
                     * results returned in the SimpleLink socket event handler callback. */
                    pxSocketContext->xSSLSyncSemaphore = xSemaphoreCreateBinary();

                    if( pxSocketContext->xSSLSyncSemaphore != NULL )
                    {
                        /* Store that we need to use TLS on this socket. */
                        pxSocketContext->ulFlags |= securesocketsSOCKET_SECURE_FLAG;

                        /* Success. */
                        lRetCode = SOCKETS_ERROR_NONE;
                    }
                    else
                    {
                        /* Since we failed to create the TLS handshake synchronization
                         * semaphore, there is no point of turning the TLS flag on,
                         * as we will not be able to setup TLS connection. Let the user
                         * know that we failed to enable TLS. */
                        lRetCode = SOCKETS_SOCKET_ERROR;
                    }
                }
                else
                {
                    lRetCode = SOCKETS_SOCKET_ERROR;
                    SOCKETS_PRINT( ( "ERROR: Require TLS must be set before connection is established.\r\n" ) );
                }

                break;

            case SOCKETS_SO_RCVTIMEO:

                /* Ensure that uint32_t was passed as value. */
                configASSERT( ( xOptionLength == sizeof( uint32_t ) ) );

                /* Read the passed value. */
                ulTimeoutInMilliseconds = *( ( const uint32_t * ) pvOptionValue ); /*lint !e9079 !e9087 uint32_t type is expected. This function will hard-fault if the wrong type is passed. */

                /* Convert the milliseconds to the struct SlTimeval_t which
                 * contains seconds and microseconds. */
                xTimeVal.tv_sec = ( SlTime_t ) ( ulTimeoutInMilliseconds / 1000 );
                ulTimeoutInMilliseconds = ulTimeoutInMilliseconds - ( uint32_t ) xTimeVal.tv_sec * 1000U;
                xTimeVal.tv_usec = ( SlTime_t ) ( ulTimeoutInMilliseconds * 1000 );

                /* Set receive timeout on the TI socket. */
                sTIRetCode = sl_SetSockOpt( pxSocketContext->sSocketDescriptor,
                                            SL_SOL_SOCKET,
                                            SL_SO_RCVTIMEO,
                                            &( xTimeVal ),
                                            ( SlSocklen_t ) sizeof( xTimeVal ) );

                /* If the above sl_SetSockOpt succeeded, return success to the user. */
                if( sTIRetCode >= 0 )
                {
                    lRetCode = SOCKETS_ERROR_NONE;
                }
                else
                {
                    /* See \lib\third_party\mcu_vendor\ti\SimpleLink_CC32xx\v2_10_00_04\source\ti\drivers\net\wifi\errors.h */
                    SOCKETS_PRINT( ( "ERROR: %d SockOpt RCVTIMEO failed.\r\n", sTIRetCode ) );
                }

                break;

            case SOCKETS_SO_SNDTIMEO:

                /* Ensure that uint32_t was passed as value. */
                configASSERT( xOptionLength == sizeof( uint32_t ) );

                /* Simple Link socket layer does not provide socket send
                 * timeout. So currently we just store the user supplied
                 * timeout in the socket context and do not use it. In future,
                 * we may use it to simulate send timeout in secure sockets
                 * layer. */
                pxSocketContext->xSendTimeoutTicks = pdMS_TO_TICKS( *( ( const uint32_t * ) pvOptionValue ) ); /*lint !e9079 !e9087 uint32_t type is expected. This function will hard-fault if the wrong type is passed. */

                /* Success. */
                lRetCode = SOCKETS_ERROR_NONE;

                break;

            case SOCKETS_SO_NONBLOCK:

                if( ( pxSocketContext->ulFlags & securesocketsSOCKET_IS_CONNECTED ) != 0 )
                {
                    xSockNonblocking.NonBlockingEnabled = 1;

                    /* Mark the TI socket as non-blocking. */
                    sTIRetCode = sl_SetSockOpt( pxSocketContext->sSocketDescriptor,
                                                SL_SOL_SOCKET,
                                                SL_SO_NONBLOCKING,
                                                &( xSockNonblocking ),
                                                ( SlSocklen_t ) sizeof( xSockNonblocking ) );

                    /* If the above sl_SetSockOpt succeeded, return success to the user. */
                    if( sTIRetCode >= 0 )
                    {
                        lRetCode = SOCKETS_ERROR_NONE;
                    }
                    else
                    {
                        /* See \lib\third_party\mcu_vendor\ti\SimpleLink_CC32xx\v2_10_00_04\source\ti\drivers\net\wifi\errors.h */
                        SOCKETS_PRINT( ( "ERROR: %d SockOpt NONBLOCK failed.\r\n", sTIRetCode ) );
                    }
                }
                else
                {
                    lRetCode = SOCKETS_SOCKET_ERROR;
                    SOCKETS_PRINT( ( "ERROR: NONBLOCKING socket option must be called after connect. Nonblocking connect is not supported.\r\n" ) );
                }

                break;

            default:
                /* Invalid option. */
                lRetCode = SOCKETS_EINVAL;
                break;
        }
    }
    else
    {
        SOCKETS_PRINT( ( "ERROR: SOCKETS_Connect - Invalid Socket number.\r\n" ) );
        lRetCode = SOCKETS_EINVAL;
    }

    return lRetCode;
}