| /* |
| * FreeRTOS Secure Sockets for lwIP |
| * 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-2018. |
| */ |
| |
| /* 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 "aws_logging_task.h" |
| |
| /* LwIP includes. */ |
| #include "lwip/api.h" |
| #include "lwip/sockets.h" |
| #include "lwip/netdb.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; |
| |
| #if 0 |
| SemaphoreHandle_t recvMutex; |
| SemaphoreHandle_t sendMutex; |
| #endif |
| |
| 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; |
| |
| int ret = lwip_send( ( int ) pxContext->xSocket, |
| pucData, |
| xDataLength, |
| pxContext->xSendFlags ); |
| return ret; |
| } |
| |
| |
| |
| |
| /*-----------------------------------------------------------*/ |
| |
| |
| /* |
| * @brief Network receive callback. |
| */ |
| static BaseType_t prvNetworkRecv( void * pvContext, |
| unsigned char * pucReceiveBuffer, |
| size_t xReceiveLength ) |
| { |
| SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) pvContext; |
| struct timeval timeout = {0}; |
| int result = 0; |
| int fd_socket = ( int ) pxContext->xSocket; |
| fd_set read_set; |
| |
| FD_ZERO(&read_set); |
| FD_SET(fd_socket, &read_set); |
| |
| timeout.tv_sec = 0; |
| timeout.tv_usec = pxContext->ulRecvTimeout * 1000;\ |
| |
| do { |
| result = lwip_select(fd_socket+1, &read_set, NULL, NULL, &timeout); |
| if (result < 0) |
| { |
| result = SOCKETS_SOCKET_ERROR; |
| break; |
| } |
| |
| if (result > 0) |
| { |
| result = lwip_recv( ( int ) pxContext->xSocket, |
| pucReceiveBuffer, |
| xReceiveLength, |
| pxContext->xSendFlags ); |
| } |
| } while(0); |
| |
| return result; |
| } |
| |
| |
| static int socket_is_valid(Socket_t xSocket) |
| { |
| if ((NULL == (void*)xSocket) || (SOCKETS_INVALID_SOCKET == (void*)xSocket)) |
| { |
| return 0; |
| } |
| return 1; |
| } |
| |
| |
| /*-----------------------------------------------------------*/ |
| |
| /* |
| * Interface routines. |
| */ |
| |
| int32_t SOCKETS_Close( Socket_t xSocket ) |
| { |
| SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; |
| int32_t lStatus = SOCKETS_ERROR_NONE; |
| |
| if (!socket_is_valid(xSocket)) |
| return SOCKETS_EINVAL; |
| |
| pxContext->ulState &= ~(nxpsecuresocketsSOCKET_CONNECTED_FLAG); |
| |
| 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; |
| } |
| |
| lwip_close( ( int ) pxContext->xSocket ); |
| |
| #if 0 |
| /* Free recv mutex */ |
| if (NULL != pxContext->recvMutex) |
| { |
| vSemaphoreDelete(pxContext->recvMutex); |
| pxContext->recvMutex = NULL; |
| } |
| /* Free send mutex */ |
| if (NULL != pxContext->sendMutex) |
| { |
| vSemaphoreDelete(pxContext->sendMutex); |
| pxContext->sendMutex = NULL; |
| } |
| #endif |
| |
| vPortFree( pxContext ); |
| |
| 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 }; |
| struct sockaddr_in xTempAddress = { 0 }; |
| |
| if (!socket_is_valid(xSocket)) |
| return SOCKETS_EINVAL; |
| |
| if (( NULL == pxAddress ) || (SOCKETS_inet_addr_quick(0,0,0,0) == pxAddress->ulAddress) || (0 == pxAddress->usPort)) |
| return SOCKETS_EINVAL; |
| |
| #if 0 |
| if (( xAddressLength != sizeof(*pxAddress) )) |
| { |
| return SOCKETS_EINVAL; |
| } |
| #endif |
| |
| /* Connect the wrapped socket. */ |
| xTempAddress.sin_addr.s_addr = pxAddress->ulAddress; |
| xTempAddress.sin_port = pxAddress->usPort; |
| #if 0 /* Enable when the 'prvConnect_InvalidAddressLength' test case is fixed */ |
| xTempAddress.sin_family = pxAddress->ucSocketDomain; |
| #else |
| xTempAddress.sin_family = AF_INET; |
| #endif |
| xStatus = lwip_connect( ( int ) pxContext->xSocket, |
| ( struct sockaddr * ) &xTempAddress, |
| sizeof(struct sockaddr_in) ); |
| |
| /* 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 ); |
| } |
| } |
| |
| if (SOCKETS_ERROR_NONE == xStatus) |
| { |
| pxContext->ulState |= nxpsecuresocketsSOCKET_CONNECTED_FLAG; |
| } |
| |
| return xStatus; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| uint32_t SOCKETS_GetHostByName( const char * pcHostName ) |
| { |
| uint32_t addr = 0; |
| int ret = netconn_gethostbyname(pcHostName, (ip_addr_t*)&addr); |
| configASSERT(ret == ERR_OK); |
| |
| return addr; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| int32_t SOCKETS_Recv( Socket_t xSocket, |
| void * pvBuffer, |
| size_t xBufferLength, |
| uint32_t ulFlags ) |
| { |
| int32_t lStatus = SOCKETS_SOCKET_ERROR; |
| SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; |
| |
| if (!socket_is_valid(xSocket)) |
| return SOCKETS_EINVAL; |
| |
| if (!(pxContext->ulState & (nxpsecuresocketsSOCKET_CONNECTED_FLAG))) |
| return SOCKETS_SOCKET_ERROR; |
| |
| #if 0 |
| if (xSemaphoreTake(pxContext->recvMutex, pdMS_TO_TICKS(1000)) == pdTRUE) |
| { |
| #endif |
| pxContext->xRecvFlags = ( BaseType_t ) ulFlags; |
| |
| if( ( NULL != pvBuffer ) && |
| ( ( nxpsecuresocketsSOCKET_READ_CLOSED_FLAG & pxContext->xShutdownFlags ) == 0UL ) ) |
| { |
| 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 ); |
| } |
| } |
| #if 0 |
| xSemaphoreGive(pxContext->recvMutex); |
| } |
| #endif |
| |
| return lStatus; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| |
| |
| int32_t SOCKETS_Send( Socket_t xSocket, |
| const void * pvBuffer, |
| size_t xDataLength, |
| uint32_t ulFlags ) |
| { |
| int32_t lStatus = SOCKETS_SOCKET_ERROR; |
| SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; |
| |
| if (!socket_is_valid(xSocket)) |
| return SOCKETS_EINVAL; |
| |
| if (!(pxContext->ulState & (nxpsecuresocketsSOCKET_CONNECTED_FLAG))) |
| return SOCKETS_SOCKET_ERROR; |
| |
| #if 0 |
| if (xSemaphoreTake(pxContext->sendMutex, pdMS_TO_TICKS(500)) == pdTRUE) |
| { |
| #endif |
| if( ( NULL != pvBuffer ) && |
| ( ( nxpsecuresocketsSOCKET_WRITE_CLOSED_FLAG & pxContext->xShutdownFlags ) == 0UL ) ) |
| { |
| pxContext->xSendFlags = ( BaseType_t ) ulFlags; |
| if( pdTRUE == pxContext->xRequireTLS ) |
| { |
| /* Send through TLS pipe, if negotiated. */ |
| lStatus = TLS_Send( pxContext->pvTLSContext, pvBuffer, xDataLength ); |
| } |
| else |
| { |
| /* Send unencrypted. */ |
| lStatus = prvNetworkSend( pxContext, pvBuffer, xDataLength ); |
| } |
| } |
| #if 0 |
| xSemaphoreGive(pxContext->sendMutex); |
| } |
| #endif |
| |
| return lStatus; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| 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; |
| //int tmp_val; |
| |
| if (!socket_is_valid(xSocket)) |
| return SOCKETS_EINVAL; |
| |
| 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: Need further rework */ |
| pxContext->ulSendTimeout = 1; |
| pxContext->ulRecvTimeout = 1; |
| //tmp_val = 1; |
| //lStatus = lwip_ioctl( ( int ) pxContext->xSocket, FIONBIO, &tmp_val ); |
| } |
| 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 ) |
| { |
| return SOCKETS_ENOMEM; |
| } |
| |
| 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; |
| |
| return SOCKETS_ENOMEM;; |
| } |
| memcpy( pxContext->ppcAlpnProtocols[i], ((char **)pvOptionValue)[i], len ); |
| pxContext->ppcAlpnProtocols[i][len] = '\0'; |
| } |
| |
| pxContext->ppcAlpnProtocols[xOptionLength] = NULL; |
| pxContext->ulAlpnProtocolsCount = xOptionLength; |
| |
| break; |
| |
| default: |
| lStatus = lwip_setsockopt( ( int ) pxContext->xSocket, |
| lLevel, |
| lOptionName, |
| ( void * ) pvOptionValue, |
| xOptionLength ); |
| break; |
| } |
| |
| return lStatus; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| int32_t SOCKETS_Shutdown( Socket_t xSocket, |
| uint32_t ulHow ) |
| { |
| SSOCKETContextPtr_t pxSecureSocket = ( SSOCKETContextPtr_t) xSocket; |
| int32_t lRetVal = SOCKETS_SOCKET_ERROR; |
| |
| if (!socket_is_valid(xSocket)) |
| return SOCKETS_EINVAL; |
| |
| 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; |
| } |
| |
| return lRetVal; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| Socket_t SOCKETS_Socket( int32_t lDomain, |
| int32_t lType, |
| int32_t lProtocol ) |
| { |
| int32_t lStatus = SOCKETS_SOCKET_ERROR; |
| 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 ); |
| |
| do { |
| /* Allocate the internal context structure. */ |
| pxContext = pvPortMalloc( sizeof( SSOCKETContext_t ) ); |
| if (NULL == pxContext) |
| { |
| lStatus = SOCKETS_ENOMEM; |
| break; |
| } |
| memset( pxContext, 0, sizeof( SSOCKETContext_t ) ); |
| |
| #if 0 |
| /* Receive mutex */ |
| pxContext->recvMutex = xSemaphoreCreateBinary(); |
| if (NULL == pxContext->recvMutex) |
| break; |
| xSemaphoreGive(pxContext->recvMutex); |
| |
| /* Send mutex */ |
| pxContext->sendMutex = xSemaphoreCreateBinary(); |
| if (NULL == pxContext->sendMutex) |
| break; |
| xSemaphoreGive(pxContext->sendMutex); |
| #endif |
| |
| /* Create the wrapped socket. */ |
| xSocket = lwip_socket(lDomain, lType, lProtocol); |
| if (xSocket < 0) |
| break; |
| |
| pxContext->xSocket = ( Socket_t ) xSocket; |
| /* Set default timeouts. */ |
| pxContext->ulRecvTimeout = socketsconfigDEFAULT_RECV_TIMEOUT; |
| pxContext->ulSendTimeout = socketsconfigDEFAULT_SEND_TIMEOUT; |
| |
| /* Consider OK */ |
| lStatus = SOCKETS_ERROR_NONE; |
| } while(0); |
| |
| /* Cleanupt */ |
| if( lStatus != SOCKETS_ERROR_NONE ) |
| { |
| if (NULL != pxContext) |
| { |
| #if 0 |
| /* Free recv mutex */ |
| if (NULL != pxContext->recvMutex) |
| { |
| vSemaphoreDelete(pxContext->recvMutex); |
| pxContext->recvMutex = NULL; |
| } |
| /* Free send mutex */ |
| if (NULL != pxContext->sendMutex) |
| { |
| vSemaphoreDelete(pxContext->sendMutex); |
| pxContext->sendMutex = NULL; |
| } |
| #endif |
| /* Free pxContext */ |
| vPortFree( pxContext ); |
| /* Set pxContext to 0xFFFF_FFFF */ |
| pxContext = (SSOCKETContextPtr_t) SOCKETS_INVALID_SOCKET; |
| } |
| } |
| |
| return (Socket_t) pxContext; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| BaseType_t SOCKETS_Init( void ) |
| { |
| /* Empty initialization for NXP board. */ |
| return pdPASS; |
| } |