in amazon-freertos/lib/secure_sockets/portable/freertos_plus_tcp/aws_secure_sockets.c [274:461]
int32_t SOCKETS_SetSockOpt( Socket_t xSocket,
int32_t lLevel,
int32_t lOptionName,
const void * pvOptionValue,
size_t xOptionLength )
{
int32_t lStatus = SOCKETS_ERROR_NONE;
TickType_t xTimeout;
SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; /*lint !e9087 cast used for portability. */
char ** ppcAlpnIn = ( char ** ) pvOptionValue;
size_t xLength = 0;
uint32_t ulProtocol;
if( ( xSocket != SOCKETS_INVALID_SOCKET ) && ( xSocket != NULL ) )
{
switch( lOptionName )
{
case SOCKETS_SO_SERVER_NAME_INDICATION:
/* Do not set the SNI options if the socket is possibly already connected. */
if( pxContext->xConnectAttempted == pdTRUE )
{
lStatus = SOCKETS_EISCONN;
}
/* Non-NULL destination string indicates that SNI extension should
* be used during TLS negotiation. */
else if( NULL == ( pxContext->pcDestination =
( char * ) pvPortMalloc( 1U + xOptionLength ) ) )
{
lStatus = SOCKETS_ENOMEM;
}
else
{
memcpy( pxContext->pcDestination, pvOptionValue, xOptionLength );
pxContext->pcDestination[ xOptionLength ] = '\0';
}
break;
case SOCKETS_SO_TRUSTED_SERVER_CERTIFICATE:
/* Do not set the trusted server certificate if the socket is possibly already connected. */
if( pxContext->xConnectAttempted == pdTRUE )
{
lStatus = SOCKETS_EISCONN;
}
/* Non-NULL server certificate field indicates that the default trust
* list should not be used. */
else if( NULL == ( pxContext->pcServerCertificate =
( char * ) pvPortMalloc( xOptionLength ) ) )
{
lStatus = SOCKETS_ENOMEM;
}
else
{
memcpy( pxContext->pcServerCertificate, pvOptionValue, xOptionLength );
pxContext->ulServerCertificateLength = xOptionLength;
}
break;
case SOCKETS_SO_REQUIRE_TLS:
/* Do not set the TLS option if the socket is possibly already connected. */
if( pxContext->xConnectAttempted == pdTRUE )
{
lStatus = SOCKETS_EISCONN;
}
else
{
pxContext->xRequireTLS = pdTRUE;
}
break;
case SOCKETS_SO_ALPN_PROTOCOLS:
/* Do not set the ALPN option if the socket is already connected. */
if( pxContext->xConnectAttempted == pdTRUE )
{
lStatus = SOCKETS_EISCONN;
break;
}
/* Allocate a sufficiently long array of pointers. */
pxContext->ulAlpnProtocolsCount = 1 + xOptionLength;
if( NULL == ( pxContext->ppcAlpnProtocols =
( char ** ) pvPortMalloc( pxContext->ulAlpnProtocolsCount * sizeof( char * ) ) ) )
{
lStatus = SOCKETS_ENOMEM;
}
else
{
/* Zero out the pointers. */
memset( pxContext->ppcAlpnProtocols,
0,
pxContext->ulAlpnProtocolsCount * sizeof( char * ) );
}
/* Copy each protocol string. */
for( ulProtocol = 0;
( ulProtocol < pxContext->ulAlpnProtocolsCount - 1 ) &&
( pdFREERTOS_ERRNO_NONE == lStatus );
ulProtocol++ )
{
xLength = strlen( ppcAlpnIn[ ulProtocol ] );
if( NULL == ( pxContext->ppcAlpnProtocols[ ulProtocol ] =
( char * ) pvPortMalloc( 1 + xLength ) ) )
{
lStatus = SOCKETS_ENOMEM;
}
else
{
memcpy( pxContext->ppcAlpnProtocols[ ulProtocol ],
ppcAlpnIn[ ulProtocol ],
xLength );
pxContext->ppcAlpnProtocols[ ulProtocol ][ xLength ] = '\0';
}
}
break;
case SOCKETS_SO_NONBLOCK:
xTimeout = 0;
/* Non-blocking connect is not supported. Socket may be set to nonblocking
* only after a connection is made. */
if( pdTRUE == pxContext->xConnectAttempted )
{
lStatus = FreeRTOS_setsockopt( pxContext->xSocket,
lLevel,
SOCKETS_SO_RCVTIMEO,
&xTimeout,
sizeof( xTimeout ) );
if( lStatus == SOCKETS_ERROR_NONE )
{
lStatus = FreeRTOS_setsockopt( pxContext->xSocket,
lLevel,
SOCKETS_SO_SNDTIMEO,
&xTimeout,
sizeof( xTimeout ) );
}
}
else
{
lStatus = SOCKETS_EISCONN;
}
break;
case SOCKETS_SO_RCVTIMEO:
case SOCKETS_SO_SNDTIMEO:
/* Comply with Berkeley standard - a 0 timeout is wait forever. */
xTimeout = *( ( const TickType_t * ) pvOptionValue ); /*lint !e9087 pvOptionValue passed should be of TickType_t */
if( xTimeout == 0U )
{
xTimeout = portMAX_DELAY;
}
lStatus = FreeRTOS_setsockopt( pxContext->xSocket,
lLevel,
lOptionName,
&xTimeout,
xOptionLength );
break;
default:
lStatus = FreeRTOS_setsockopt( pxContext->xSocket,
lLevel,
lOptionName,
pvOptionValue,
xOptionLength );
break;
}
}
else
{
lStatus = SOCKETS_EINVAL;
}
return lStatus;
}