in device_firmware/libraries/freertos_plus/standard/freertos_plus_tcp/source/FreeRTOS_Sockets.c [1279:1645]
BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )
{
/* The standard Berkeley function returns 0 for success. */
BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;
BaseType_t lOptionValue;
FreeRTOS_Socket_t *pxSocket;
pxSocket = ( FreeRTOS_Socket_t * ) xSocket;
/* The function prototype is designed to maintain the expected Berkeley
sockets standard, but this implementation does not use all the parameters. */
( void ) lLevel;
( void ) xOptionLength;
configASSERT( xSocket );
switch( lOptionName )
{
case FREERTOS_SO_RCVTIMEO :
/* Receive time out. */
pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );
xReturn = 0;
break;
case FREERTOS_SO_SNDTIMEO :
pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );
if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )
{
/* The send time out is capped for the reason stated in the
comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined
in FreeRTOSIPConfig.h (assuming an official configuration file
is being used. */
if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
{
pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
}
}
else
{
/* For TCP socket, it isn't necessary to limit the blocking time
because the FreeRTOS_send() function does not wait for a network
buffer to become available. */
}
xReturn = 0;
break;
#if( ipconfigUDP_MAX_RX_PACKETS > 0 )
case FREERTOS_SO_UDP_MAX_RX_PACKETS:
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )
{
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );
xReturn = 0;
break;
#endif /* ipconfigUDP_MAX_RX_PACKETS */
case FREERTOS_SO_UDPCKSUM_OUT :
/* Turn calculating of the UDP checksum on/off for this socket. */
lOptionValue = ( BaseType_t ) pvOptionValue;
if( lOptionValue == 0 )
{
pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;
}
else
{
pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;
}
xReturn = 0;
break;
#if( ipconfigUSE_CALLBACKS == 1 )
#if( ipconfigUSE_TCP == 1 )
case FREERTOS_SO_TCP_CONN_HANDLER: /* Set a callback for (dis)connection events */
case FREERTOS_SO_TCP_RECV_HANDLER: /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
case FREERTOS_SO_TCP_SENT_HANDLER: /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
#endif /* ipconfigUSE_TCP */
case FREERTOS_SO_UDP_RECV_HANDLER: /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
case FREERTOS_SO_UDP_SENT_HANDLER: /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */
{
#if( ipconfigUSE_TCP == 1 )
{
UBaseType_t uxProtocol;
if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||
( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )
{
uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;
}
else
{
uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;
}
if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )
{
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
}
#else
{
/* No need to check if the socket has the right
protocol, because only UDP socket can be created. */
}
#endif /* ipconfigUSE_TCP */
switch( lOptionName )
{
#if ipconfigUSE_TCP == 1
case FREERTOS_SO_TCP_CONN_HANDLER:
pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;
break;
case FREERTOS_SO_TCP_RECV_HANDLER:
pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;
break;
case FREERTOS_SO_TCP_SENT_HANDLER:
pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;
break;
#endif /* ipconfigUSE_TCP */
case FREERTOS_SO_UDP_RECV_HANDLER:
pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;
break;
case FREERTOS_SO_UDP_SENT_HANDLER:
pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;
break;
default:
break;
}
}
xReturn = 0;
break;
#endif /* ipconfigUSE_CALLBACKS */
#if( ipconfigUSE_TCP != 0 )
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
/* Each socket has a semaphore on which the using task normally
sleeps. */
case FREERTOS_SO_SET_SEMAPHORE:
{
pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );
xReturn = 0;
}
break;
#endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
#if( ipconfigSOCKET_HAS_USER_WAKE_CALLBACK != 0 )
case FREERTOS_SO_WAKEUP_CALLBACK:
{
/* Each socket can have a callback function that is executed
when there is an event the socket's owner might want to
process. */
pxSocket->pxUserWakeCallback = ( SocketWakeupCallback_t ) pvOptionValue;
xReturn = 0;
}
break;
#endif /* ipconfigSOCKET_HAS_USER_WAKE_CALLBACK */
case FREERTOS_SO_SET_LOW_HIGH_WATER:
{
LowHighWater_t *pxLowHighWater = ( LowHighWater_t * ) pvOptionValue;
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
{
/* It is not allowed to access 'pxSocket->u.xTCP'. */
FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: wrong socket type\n" ) );
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
if( ( pxLowHighWater->uxLittleSpace >= pxLowHighWater->uxEnoughSpace ) ||
( pxLowHighWater->uxEnoughSpace > pxSocket->u.xTCP.uxRxStreamSize ) )
{
/* Impossible values. */
FreeRTOS_debug_printf( ( "FREERTOS_SO_SET_LOW_HIGH_WATER: bad values\n" ) );
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
/* Send a STOP when buffer space drops below 'uxLittleSpace' bytes. */
pxSocket->u.xTCP.uxLittleSpace = pxLowHighWater->uxLittleSpace;
/* Send a GO when buffer space grows above 'uxEnoughSpace' bytes. */
pxSocket->u.xTCP.uxEnoughSpace = pxLowHighWater->uxEnoughSpace;
xReturn = 0;
}
break;
case FREERTOS_SO_SNDBUF: /* Set the size of the send buffer, in units of MSS (TCP only) */
case FREERTOS_SO_RCVBUF: /* Set the size of the receive buffer, in units of MSS (TCP only) */
{
uint32_t ulNewValue;
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
{
FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",
( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||
( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )
{
FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",
( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
ulNewValue = *( ( uint32_t * ) pvOptionValue );
if( lOptionName == FREERTOS_SO_SNDBUF )
{
/* Round up to nearest MSS size */
ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );
pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;
}
else
{
pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;
}
}
xReturn = 0;
break;
case FREERTOS_SO_WIN_PROPERTIES: /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */
{
WinProperties_t* pxProps;
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
{
FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )
{
FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
pxProps = ( ( WinProperties_t * ) pvOptionValue );
if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) ) != 0 )
{
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
if ( FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) ) != 0 )
{
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
#if( ipconfigUSE_TCP_WIN == 1 )
{
pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */
pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */
}
#else
{
pxSocket->u.xTCP.uxRxWinSize = 1u;
pxSocket->u.xTCP.uxTxWinSize = 1u;
}
#endif
/* In case the socket has already initialised its tcpWin,
adapt the window size parameters */
if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )
{
pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;
pxSocket->u.xTCP.xTCPWindow.xSize.ulTxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;
}
}
xReturn = 0;
break;
case FREERTOS_SO_REUSE_LISTEN_SOCKET: /* If true, the server-socket will turn into a connected socket */
{
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
{
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
{
pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;
}
else
{
pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;
}
}
xReturn = 0;
break;
case FREERTOS_SO_CLOSE_AFTER_SEND: /* As soon as the last byte has been transmitted, finalise the connection */
{
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
{
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
{
pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;
}
else
{
pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;
}
}
xReturn = 0;
break;
case FREERTOS_SO_SET_FULL_SIZE: /* Refuse to send packets smaller than MSS */
{
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
{
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
{
pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;
}
else
{
pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;
}
if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&
( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&
( FreeRTOS_outstanding( pxSocket ) != 0 ) )
{
pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */
xSendEventToIPTask( eTCPTimerEvent );
}
}
xReturn = 0;
break;
case FREERTOS_SO_STOP_RX: /* Refuse to receive more packts */
{
if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )
{
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
}
if( *( ( BaseType_t * ) pvOptionValue ) != 0 )
{
pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;
}
else
{
pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;
}
pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */
xSendEventToIPTask( eTCPTimerEvent );
}
xReturn = 0;
break;
#endif /* ipconfigUSE_TCP == 1 */
default :
/* No other options are handled. */
xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;
break;
}
return xReturn;
} /* Tested */