| /* |
| * FreeRTOS Secure Sockets for NXP54018_IoT_Module V1.0.0 Beta 4 |
| * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy of |
| * this software and associated documentation files (the "Software"), to deal in |
| * the Software without restriction, including without limitation the rights to |
| * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
| * the Software, and to permit persons to whom the Software is furnished to do so, |
| * subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in all |
| * copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
| * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
| * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
| * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| * |
| * http://aws.amazon.com/freertos |
| * http://www.FreeRTOS.org |
| */ |
| |
| /* |
| * Copyright (C) NXP 2017-2019. |
| */ |
| |
| /* Define _SECURE_SOCKETS_WRAPPER_NOT_REDEFINE to prevent secure sockets functions |
| * from redefining in iot_secure_sockets_wrapper_metrics.h */ |
| #define _SECURE_SOCKETS_WRAPPER_NOT_REDEFINE |
| |
| /* FreeRTOS includes. */ |
| #include "FreeRTOS.h" |
| #include "iot_secure_sockets.h" |
| #include "iot_tls.h" |
| #include "task.h" |
| |
| /* Logging includes. */ |
| //#include "iot_logging_task.h" |
| |
| /* Third-party wifi driver include. */ |
| #include "qcom_api.h" |
| #include "iot_wifi.h" |
| #include "custom_stack_offload.h" |
| #include "atheros_stack_offload.h" |
| |
| #undef _SECURE_SOCKETS_WRAPPER_NOT_REDEFINE |
| |
| /** |
| * @brief Flag indicating that socket send operations are not permitted. |
| * |
| * If a WR shutdown in SOCKETS_Shutdown() is invoked, this flag is |
| * set in the socket's xShutdownFlags member. |
| */ |
| #define nxpsecuresocketsSOCKET_WRITE_CLOSED_FLAG ( 1UL << 2 ) |
| |
| /** |
| * @brief Flag indicating that socket receive operations are not permitted. |
| * |
| * If a RD shutdown in SOCKETS_Shutdown() is invoked, this flag is |
| * set in the socket's xShutdownFlags member. |
| */ |
| #define nxpsecuresocketsSOCKET_READ_CLOSED_FLAG ( 1UL << 1 ) |
| |
| /** |
| * @brief Delay used between network select attempts when effecting a receive timeout. |
| * |
| * Timeouts are mocked in the secure sockets layer, and this constant sets the |
| * sleep time between each read attempt during the receive timeout period. |
| */ |
| #define nxpsecuresocketsFIVE_MILLISECONDS ( pdMS_TO_TICKS( 5 ) ) |
| |
| /** |
| * @brief The timeout supplied to the t_select function. |
| * |
| * Receive timeout are emulated in secure sockets layer and therefore we |
| * do not want the Inventek module to block. Setting to zero means |
| * no timeout, so one is the smallest value we can set it to. |
| */ |
| #define nxpsecuresocketsONE_MILLISECOND ( 1 ) |
| #define nxpsecuresocketsSOCKET_CONNECTED_FLAG ( 1 ) |
| |
| /* Internal context structure. */ |
| typedef struct SSOCKETContext |
| { |
| Socket_t xSocket; |
| char * pcDestination; |
| void * pvTLSContext; |
| BaseType_t xRequireTLS; |
| BaseType_t xSendFlags; |
| BaseType_t xRecvFlags; |
| BaseType_t xShutdownFlags; |
| uint32_t ulSendTimeout; |
| uint32_t ulRecvTimeout; |
| char * pcServerCertificate; |
| uint32_t ulServerCertificateLength; |
| uint32_t ulState; |
| char ** ppcAlpnProtocols; |
| uint32_t ulAlpnProtocolsCount; |
| } SSOCKETContext_t, * SSOCKETContextPtr_t; |
| |
| /* |
| * Helper routines. |
| */ |
| |
| /* |
| * @brief Network send callback. |
| */ |
| static BaseType_t prvNetworkSend( void * pvContext, |
| const unsigned char * pucData, |
| size_t xDataLength ) |
| { |
| SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) pvContext; |
| |
| /* Do not send data on unconnected socket */ |
| if( !( pxContext->ulState & nxpsecuresocketsSOCKET_CONNECTED_FLAG ) ) |
| { |
| return -1; |
| } |
| |
| char * sendBuf = custom_alloc( xDataLength ); |
| |
| if( sendBuf == NULL ) |
| { |
| return -1; |
| } |
| |
| memcpy( sendBuf, pucData, xDataLength ); |
| int ret = qcom_send( ( int ) pxContext->xSocket, |
| sendBuf, |
| xDataLength, |
| pxContext->xSendFlags ); |
| custom_free( sendBuf ); |
| |
| return ret; |
| } |
| |
| |
| |
| /*-----------------------------------------------------------*/ |
| |
| |
| QCA_CONTEXT_STRUCT * wlan_get_context( void ); |
| |
| /* |
| * @brief Network receive callback. |
| */ |
| static BaseType_t prvNetworkRecv( void * pvContext, |
| unsigned char * pucReceiveBuffer, |
| size_t xReceiveLength ) |
| { |
| SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) pvContext; |
| TickType_t xTimeOnEntering = xTaskGetTickCount(); |
| |
| /* Do not receive data on unconnected socket */ |
| if( !( pxContext->ulState & nxpsecuresocketsSOCKET_CONNECTED_FLAG ) ) |
| { |
| return -1; |
| } |
| |
| QCA_CONTEXT_STRUCT * enetCtx = wlan_get_context(); |
| A_STATUS xStatus; |
| |
| char * buffLoc = NULL; |
| int xRetVal = 0; |
| |
| for( ; ; ) |
| { |
| /* Check if there is anything to be received on this socket. */ |
| xStatus = ( A_STATUS ) t_select( enetCtx, |
| ( uint32_t ) pxContext->xSocket, |
| nxpsecuresocketsONE_MILLISECOND ); |
| |
| if( xStatus == A_OK ) /* Data available. */ |
| { |
| xRetVal = qcom_recv( ( int ) pxContext->xSocket, &buffLoc, xReceiveLength, 0 ); |
| |
| if( xRetVal > 0 ) /* Data received. */ |
| { |
| memcpy( pucReceiveBuffer, buffLoc, xRetVal ); |
| break; |
| } |
| else /* Error occured. */ |
| { |
| /*int errno = t_errno( wlan_get_context(), ( uint32_t ) pxContext->xSocket ); */ |
| xRetVal = SOCKETS_SOCKET_ERROR; |
| break; |
| } |
| } |
| else if( xStatus == A_ERROR ) /* A_ERROR is returned from t_select on timeout. */ |
| { |
| if( ( xTaskGetTickCount() - xTimeOnEntering ) < pxContext->ulRecvTimeout ) |
| { |
| vTaskDelay( nxpsecuresocketsFIVE_MILLISECONDS ); |
| } |
| else |
| { |
| xRetVal = 0;// return -1; |
| break; |
| } |
| } |
| else |
| { |
| xRetVal = SOCKETS_SOCKET_ERROR; |
| break; |
| } |
| } |
| |
| if( buffLoc != NULL ) |
| { |
| zero_copy_free( buffLoc ); |
| } |
| |
| return xRetVal; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| /* |
| * Interface routines. |
| */ |
| |
| int32_t SOCKETS_Close( Socket_t xSocket ) |
| { |
| SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; |
| int32_t lStatus = SOCKETS_ERROR_NONE; |
| |
| if( ( NULL != pxContext ) && ( SOCKETS_INVALID_SOCKET != pxContext->xSocket ) ) |
| { |
| pxContext->ulState = 0; |
| |
| if( NULL != pxContext->pcDestination ) |
| { |
| vPortFree( pxContext->pcDestination ); |
| } |
| |
| if( NULL != pxContext->pcServerCertificate ) |
| { |
| vPortFree( pxContext->pcServerCertificate ); |
| } |
| |
| if( pdTRUE == pxContext->xRequireTLS ) |
| { |
| TLS_Cleanup( pxContext->pvTLSContext ); |
| } |
| |
| if( NULL != pxContext->ppcAlpnProtocols ) |
| { |
| int i; |
| for( i = 0; i < pxContext->ulAlpnProtocolsCount; i++ ) |
| { |
| vPortFree( pxContext->ppcAlpnProtocols[i] ); |
| } |
| vPortFree( pxContext->ppcAlpnProtocols ); |
| pxContext->ulAlpnProtocolsCount = 0; |
| } |
| |
| qcom_socket_close( ( int ) pxContext->xSocket ); |
| vPortFree( pxContext ); |
| } |
| else |
| { |
| lStatus = SOCKETS_EINVAL; |
| } |
| |
| return lStatus; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| int32_t SOCKETS_Connect( Socket_t xSocket, |
| SocketsSockaddr_t * pxAddress, |
| Socklen_t xAddressLength ) |
| { |
| int32_t xStatus = SOCKETS_ERROR_NONE; |
| SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; |
| TLSParams_t xTLSParams = { 0 }; |
| SOCKADDR_T xTempAddress = { 0 }; |
| |
| if( ( SOCKETS_INVALID_SOCKET != pxContext->xSocket ) && ( NULL != pxAddress ) && WIFI_IsConnected()) |
| { |
| /* Connect the wrapped socket. */ |
| |
| |
| /* The driver code expects the endianess of the address and port in host order and then swaps before |
| * sending the connection data to the firmware. */ |
| xTempAddress.sin_addr.s_addr = SOCKETS_ntohl( pxAddress->ulAddress ); |
| xTempAddress.sin_family = pxAddress->ucSocketDomain; |
| xTempAddress.sin_port = SOCKETS_ntohs( pxAddress->usPort ); |
| xStatus = qcom_connect( ( int ) pxContext->xSocket, |
| ( struct sockaddr * ) &xTempAddress, |
| xAddressLength ); |
| |
| /* Keep socket state - connected */ |
| if( SOCKETS_ERROR_NONE == xStatus ) |
| { |
| pxContext->ulState |= nxpsecuresocketsSOCKET_CONNECTED_FLAG; |
| } |
| |
| /* Negotiate TLS if requested. */ |
| if( ( SOCKETS_ERROR_NONE == xStatus ) && ( pdTRUE == pxContext->xRequireTLS ) ) |
| { |
| xTLSParams.ulSize = sizeof( xTLSParams ); |
| xTLSParams.pcDestination = pxContext->pcDestination; |
| xTLSParams.pcServerCertificate = pxContext->pcServerCertificate; |
| xTLSParams.ulServerCertificateLength = pxContext->ulServerCertificateLength; |
| xTLSParams.pvCallerContext = pxContext; |
| xTLSParams.pxNetworkRecv = prvNetworkRecv; |
| xTLSParams.pxNetworkSend = prvNetworkSend; |
| xTLSParams.ppcAlpnProtocols = ( const char ** ) pxContext->ppcAlpnProtocols; |
| xTLSParams.ulAlpnProtocolsCount = pxContext->ulAlpnProtocolsCount; |
| xStatus = TLS_Init( &pxContext->pvTLSContext, &xTLSParams ); |
| |
| if( SOCKETS_ERROR_NONE == xStatus ) |
| { |
| xStatus = TLS_Connect( pxContext->pvTLSContext ); |
| |
| /* Report positive error codes as negative number */ |
| xStatus = xStatus > 0 ? SOCKETS_TLS_HANDSHAKE_ERROR : xStatus; |
| } |
| } |
| } |
| else |
| { |
| xStatus = SOCKETS_SOCKET_ERROR; |
| } |
| |
| return xStatus; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| |
| /* Convert IP address in uint32_t to comma separated bytes. */ |
| #define UINT32_IPADDR_TO_CSV_BYTES( a ) \ |
| ( ( ( a ) >> 24 ) & 0xFF ), ( ( ( a ) >> 16 ) & 0xFF ), \ |
| ( ( ( a ) >> 8 ) & 0xFF ), ( ( a ) & 0xFF ) |
| |
| /*-----------------------------------------------------------*/ |
| |
| uint32_t SOCKETS_GetHostByName( const char * pcHostName ) |
| { |
| uint32_t ulAddr = 0; |
| |
| if( strlen( pcHostName ) <= ( size_t ) securesocketsMAX_DNS_NAME_LENGTH ) |
| { |
| WIFI_GetHostIP( ( char * ) pcHostName, ( uint8_t * ) &ulAddr ); |
| configPRINTF( ( "Looked up %s as %d.%d.%d.%d\r\n", |
| pcHostName, |
| UINT32_IPADDR_TO_CSV_BYTES( ulAddr ) ) ); |
| } |
| else |
| { |
| configPRINTF( ( "Malformed URL, Host name: %s is too long.", pcHostName ) ); |
| } |
| |
| /* This api is to return the address in network order. WIFI_GetHostIP returns the host IP |
| * in host order. |
| */ |
| ulAddr = SOCKETS_htonl( ulAddr ); |
| |
| return ulAddr; |
| } |
| |
| /*-----------------------------------------------------------*/ |
| |
| int32_t SOCKETS_Recv( Socket_t xSocket, |
| void * pvBuffer, |
| size_t xBufferLength, |
| uint32_t ulFlags ) |
| { |
| int32_t lStatus = SOCKETS_ERROR_NONE; |
| SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; |
| |
| |
| if( ( SOCKETS_INVALID_SOCKET != xSocket ) && |
| ( NULL != pvBuffer ) && |
| ( ( nxpsecuresocketsSOCKET_READ_CLOSED_FLAG & pxContext->xShutdownFlags ) == 0UL ) && |
| ( pxContext->ulState & ( nxpsecuresocketsSOCKET_CONNECTED_FLAG ) ) |
| ) |
| { |
| pxContext->xRecvFlags = ( BaseType_t ) ulFlags; |
| if( pdTRUE == pxContext->xRequireTLS ) |
| { |
| /* Receive through TLS pipe, if negotiated. */ |
| lStatus = TLS_Recv( pxContext->pvTLSContext, pvBuffer, xBufferLength ); |
| } |
| else |
| { |
| /* Receive unencrypted. */ |
| lStatus = prvNetworkRecv( pxContext, pvBuffer, xBufferLength ); |
| } |
| } |
| else |
| { |
| lStatus = SOCKETS_SOCKET_ERROR; |
| } |
| |
| return lStatus; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| int32_t SOCKETS_Send( Socket_t xSocket, |
| const void * pvBuffer, |
| size_t xDataLength, |
| uint32_t ulFlags ) |
| { |
| /* The WiFi module refuses to send data if it exceeds this threshold defined in |
| * atheros_stack_offload.h */ |
| uint32_t ulSendMaxLength = IPV4_FRAGMENTATION_THRESHOLD; |
| int32_t lWritten = 0, lWrittenPerLoop = 0; |
| SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; |
| |
| if( ( SOCKETS_INVALID_SOCKET != pxContext->xSocket ) && |
| ( NULL != pvBuffer ) && |
| ( ( nxpsecuresocketsSOCKET_WRITE_CLOSED_FLAG & pxContext->xShutdownFlags ) == 0UL ) && |
| ( pxContext->ulState & ( nxpsecuresocketsSOCKET_CONNECTED_FLAG ) ) |
| ) |
| { |
| pxContext->xSendFlags = ( BaseType_t ) ulFlags; |
| |
| if( pdTRUE == pxContext->xRequireTLS ) |
| { |
| /* In case of TLS, reserve extra space for SSL meta data (header, maclen, ivlen, ... = 45B) */ |
| ulSendMaxLength = 1531; |
| |
| for( |
| uint32_t ulToRemain = xDataLength, ulBufferPos = 0, ulToSend = 0; |
| ulToRemain; |
| ulBufferPos += ulToSend, ulToRemain -= ulToSend |
| ) |
| { |
| ulToSend = ulToRemain > ulSendMaxLength ? ulSendMaxLength : ulToRemain; |
| /* Send through TLS pipe, if negotiated. */ |
| lWrittenPerLoop = TLS_Send( pxContext->pvTLSContext, |
| &( ( unsigned char const * ) pvBuffer )[ ulBufferPos ], |
| ulToSend ); |
| |
| /* Error code < 0. */ |
| if( lWrittenPerLoop < 0 ) |
| { |
| /* Set the error code to be returned */ |
| lWritten = lWrittenPerLoop; |
| break; |
| } |
| |
| /* Number of lWritten bytes. */ |
| lWritten += lWrittenPerLoop; |
| |
| if( lWrittenPerLoop != ulToSend ) |
| { |
| break; |
| } |
| } |
| } |
| else |
| { |
| for( |
| uint32_t ulToRemain = xDataLength, ulBufferPos = 0, ulToSend = 0; |
| ulToRemain; |
| ulBufferPos += ulToSend, ulToRemain -= ulToSend |
| ) |
| { |
| ulToSend = ulToRemain > ulSendMaxLength ? ulSendMaxLength : ulToRemain; |
| lWrittenPerLoop = prvNetworkSend( pxContext, |
| &( ( unsigned char const * ) pvBuffer )[ ulBufferPos ], |
| ulToSend ); |
| |
| /* Error code < 0. */ |
| if( lWrittenPerLoop < 0 ) |
| { |
| /* Set the error code to be returned */ |
| lWritten = lWrittenPerLoop; |
| break; |
| } |
| |
| /* Number of lWritten bytes. */ |
| lWritten += lWrittenPerLoop; |
| |
| if( lWrittenPerLoop != ulToSend ) |
| { |
| break; |
| } |
| } |
| } |
| } |
| else |
| { |
| lWritten = SOCKETS_SOCKET_ERROR; |
| } |
| |
| return lWritten; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| 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; |
| |
| if( ( NULL != pxContext ) && ( SOCKETS_INVALID_SOCKET != pxContext->xSocket ) ) |
| { |
| switch( lOptionName ) |
| { |
| case SOCKETS_SO_SERVER_NAME_INDICATION: |
| |
| /* Secure socket option cannot be used on connected socket */ |
| if( pxContext->ulState & ( nxpsecuresocketsSOCKET_CONNECTED_FLAG ) ) |
| { |
| lStatus = SOCKETS_SOCKET_ERROR; |
| break; |
| } |
| |
| /* Non-NULL destination string indicates that SNI extension should |
| * be used during TLS negotiation. */ |
| if( NULL == ( pxContext->pcDestination = |
| ( char * ) pvPortMalloc( 1 + xOptionLength ) ) ) |
| { |
| lStatus = SOCKETS_ENOMEM; |
| } |
| else |
| { |
| memcpy( pxContext->pcDestination, pvOptionValue, xOptionLength ); |
| pxContext->pcDestination[ xOptionLength ] = '\0'; |
| } |
| |
| break; |
| |
| case SOCKETS_SO_TRUSTED_SERVER_CERTIFICATE: |
| |
| /* Secure socket option cannot be used on connected socket */ |
| if( pxContext->ulState & ( nxpsecuresocketsSOCKET_CONNECTED_FLAG ) ) |
| { |
| lStatus = SOCKETS_SOCKET_ERROR; |
| break; |
| } |
| |
| /* Non-NULL server certificate field indicates that the default trust |
| * list should not be used. */ |
| 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: |
| |
| /* Secure socket option cannot be used on connected socket */ |
| if( pxContext->ulState & ( nxpsecuresocketsSOCKET_CONNECTED_FLAG ) ) |
| { |
| lStatus = SOCKETS_SOCKET_ERROR; |
| break; |
| } |
| |
| pxContext->xRequireTLS = pdTRUE; |
| break; |
| |
| case SOCKETS_SO_NONBLOCK: |
| |
| if( pxContext->ulState & ( nxpsecuresocketsSOCKET_CONNECTED_FLAG ) ) |
| { |
| xTimeout = 0; |
| /* TODO: Investigate the NONBLOCK compile time config. */ |
| pxContext->ulSendTimeout = 1; |
| pxContext->ulRecvTimeout = 1; |
| } |
| else |
| { |
| lStatus = SOCKETS_SOCKET_ERROR; |
| } |
| |
| break; |
| |
| case SOCKETS_SO_RCVTIMEO: |
| xTimeout = *( ( const TickType_t * ) pvOptionValue ); /*lint !e9087 pvOptionValue passed should be of TickType_t. */ |
| |
| if( xTimeout == 0U ) |
| { |
| pxContext->ulRecvTimeout = portMAX_DELAY; |
| } |
| else |
| { |
| pxContext->ulRecvTimeout = xTimeout; |
| } |
| |
| break; |
| |
| 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 ) |
| { |
| pxContext->ulSendTimeout = portMAX_DELAY; |
| } |
| else |
| { |
| pxContext->ulSendTimeout = xTimeout; |
| } |
| |
| break; |
| |
| case SOCKETS_SO_ALPN_PROTOCOLS: |
| |
| /* Secure socket option cannot be used on connected socket */ |
| if( pxContext->ulState & ( nxpsecuresocketsSOCKET_CONNECTED_FLAG ) ) |
| { |
| lStatus = SOCKETS_SOCKET_ERROR; |
| break; |
| } |
| |
| /* Prepare list of supported protocols, must be NULL-terminated */ |
| pxContext->ppcAlpnProtocols = (char **)pvPortMalloc((xOptionLength + 1 )*sizeof(char*)); |
| if( pxContext->ppcAlpnProtocols == NULL ) |
| { |
| lStatus = SOCKETS_SOCKET_ERROR; |
| break; |
| } |
| |
| int i; |
| for( i = 0; i < xOptionLength; i++ ) |
| { |
| int len = strlen( ((char **)pvOptionValue)[i] ); |
| pxContext->ppcAlpnProtocols[i] = (char *)pvPortMalloc(len + 1); |
| if( pxContext->ppcAlpnProtocols[i] == NULL ) |
| { |
| /* Malloc failed - remove created list and set error return value */ |
| while(i) |
| { |
| vPortFree( pxContext->ppcAlpnProtocols[i - 1] ); |
| i--; |
| } |
| vPortFree( pxContext->ppcAlpnProtocols ); |
| pxContext->ppcAlpnProtocols = NULL; |
| pxContext->ulAlpnProtocolsCount = 0; |
| |
| lStatus = SOCKETS_SOCKET_ERROR; |
| break; |
| } |
| memcpy( pxContext->ppcAlpnProtocols[i], ((char **)pvOptionValue)[i], len ); |
| pxContext->ppcAlpnProtocols[i][len] = '\0'; |
| } |
| |
| if( lStatus != SOCKETS_SOCKET_ERROR ) |
| { |
| pxContext->ppcAlpnProtocols[xOptionLength] = NULL; |
| pxContext->ulAlpnProtocolsCount = xOptionLength; |
| } |
| |
| break; |
| |
| default: |
| lStatus = qcom_setsockopt( ( int ) pxContext->xSocket, |
| lLevel, |
| lOptionName, |
| ( void * ) pvOptionValue, |
| xOptionLength ); |
| break; |
| } |
| } |
| else |
| { |
| lStatus = SOCKETS_SOCKET_ERROR; |
| } |
| |
| return lStatus; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| int32_t SOCKETS_Shutdown( Socket_t xSocket, |
| uint32_t ulHow ) |
| { |
| SSOCKETContextPtr_t pxSecureSocket = ( SSOCKETContextPtr_t ) xSocket; |
| int32_t lRetVal = SOCKETS_SOCKET_ERROR; |
| |
| /* Ensure that a valid socket was passed. */ |
| if( ( SOCKETS_INVALID_SOCKET != pxSecureSocket->xSocket ) ) |
| { |
| switch( ulHow ) |
| { |
| case SOCKETS_SHUT_RD: |
| /* Further receive calls on this socket should return error. */ |
| pxSecureSocket->xShutdownFlags |= nxpsecuresocketsSOCKET_READ_CLOSED_FLAG; |
| |
| /* Return success to the user. */ |
| lRetVal = SOCKETS_ERROR_NONE; |
| break; |
| |
| case SOCKETS_SHUT_WR: |
| /* Further send calls on this socket should return error. */ |
| pxSecureSocket->xShutdownFlags |= nxpsecuresocketsSOCKET_WRITE_CLOSED_FLAG; |
| |
| /* Return success to the user. */ |
| lRetVal = SOCKETS_ERROR_NONE; |
| break; |
| |
| case SOCKETS_SHUT_RDWR: |
| /* Further send or receive calls on this socket should return error. */ |
| pxSecureSocket->xShutdownFlags |= nxpsecuresocketsSOCKET_READ_CLOSED_FLAG; |
| pxSecureSocket->xShutdownFlags |= nxpsecuresocketsSOCKET_WRITE_CLOSED_FLAG; |
| |
| /* Return success to the user. */ |
| lRetVal = SOCKETS_ERROR_NONE; |
| break; |
| |
| default: |
| /* An invalid value was passed for ulHow. */ |
| lRetVal = SOCKETS_EINVAL; |
| break; |
| } |
| } |
| else |
| { |
| return SOCKETS_EINVAL; |
| } |
| |
| return lRetVal; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| Socket_t SOCKETS_Socket( int32_t lDomain, |
| int32_t lType, |
| int32_t lProtocol ) |
| { |
| int32_t lStatus = SOCKETS_ERROR_NONE; |
| int32_t xSocket = 0; |
| SSOCKETContextPtr_t pxContext = NULL; |
| |
| /* Ensure that only supported values are supplied. */ |
| configASSERT( lDomain == SOCKETS_AF_INET ); |
| configASSERT( lType == SOCKETS_SOCK_STREAM ); |
| configASSERT( lProtocol == SOCKETS_IPPROTO_TCP ); |
| |
| /* Allocate the internal context structure. */ |
| pxContext = pvPortMalloc( sizeof( SSOCKETContext_t ) ); |
| |
| if( pxContext != NULL ) |
| { |
| memset( pxContext, 0, sizeof( SSOCKETContext_t ) ); |
| |
| /* Create the wrapped socket. */ |
| xSocket = qcom_socket( ATH_AF_INET, |
| SOCK_STREAM_TYPE, |
| 0 ); /*xProtocol*/ |
| |
| if( xSocket != A_ERROR ) |
| { |
| pxContext->xSocket = ( Socket_t ) xSocket; |
| /* Set default timeouts. */ |
| pxContext->ulRecvTimeout = socketsconfigDEFAULT_RECV_TIMEOUT; |
| pxContext->ulSendTimeout = socketsconfigDEFAULT_SEND_TIMEOUT; |
| } |
| else /* Driver could not allocate socket. */ |
| { |
| lStatus = SOCKETS_SOCKET_ERROR; |
| vPortFree( pxContext ); |
| } |
| } |
| else /* Malloc failed. */ |
| { |
| lStatus = SOCKETS_ENOMEM; |
| } |
| |
| if( lStatus != SOCKETS_ERROR_NONE ) |
| { |
| pxContext = (SSOCKETContextPtr_t) SOCKETS_INVALID_SOCKET; |
| } |
| |
| return (Socket_t) pxContext; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| BaseType_t SOCKETS_Init( void ) |
| { |
| /* Empty initialization for NXP board. */ |
| return pdPASS; |
| } |