static void save_socket(struct SocketWatcherData *watcher, pubnub_t *pb) { if (watcher->apb_size == watcher->apb_cap) { size_t newcap = watcher->apb_cap + 2; pubnub_t **npapb = (pubnub_t**)realloc(watcher->apb, sizeof watcher->apb[0] * newcap); if (NULL == npapb) { return; } watcher->apb = npapb; watcher->apb_cap = newcap; } FreeRTOS_FD_SET(pb->pal.socket, watcher->xFD_set, eSELECT_ALL); watcher->apb[watcher->apb_size] = pb; ++watcher->apb_size; }
static BaseType_t prvSendFile( xHTTPClient *pxClient ) { size_t xSpace; size_t xCount; BaseType_t xRc = 0; if( pxClient->bits.bReplySent == pdFALSE ) { pxClient->bits.bReplySent = pdTRUE; strcpy( pxClient->pxParent->pcContentsType, pcGetContentsType( pxClient->pcCurrentFilename ) ); snprintf( pxClient->pxParent->pcExtraContents, sizeof pxClient->pxParent->pcExtraContents, "Content-Length: %d\r\n", ( int ) pxClient->xBytesLeft); xRc = prvSendReply( pxClient, WEB_REPLY_OK ); /* "Requested file action OK" */ } if( xRc >= 0 ) do { xSpace = FreeRTOS_tx_space( pxClient->xSocket ); if( pxClient->xBytesLeft < xSpace ) { xCount = pxClient->xBytesLeft; } else { xCount = xSpace; } if( xCount > 0 ) { if( xCount > sizeof( pxClient->pxParent->pcFileBuffer ) ) { xCount = sizeof( pxClient->pxParent->pcFileBuffer ); } ff_fread( pxClient->pxParent->pcFileBuffer, 1, xCount, pxClient->pxFileHandle ); pxClient->xBytesLeft -= xCount; xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pxParent->pcFileBuffer, xCount, 0 ); if( xRc < 0 ) { break; } } } while( xCount > 0 ); if( pxClient->xBytesLeft <= 0 ) { /* Writing is ready, no need for further 'eSELECT_WRITE' events. */ FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE ); prvFileClose( pxClient ); } else { /* Wake up the TCP task as soon as this socket may be written to. */ FreeRTOS_FD_SET( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE ); } return xRc; }
static void prvConnectionListeningTask( void *pvParameters ) { struct freertos_sockaddr xClient, xBindAddress; xSocket_t xListeningSocket; socklen_t xSize = sizeof( xClient ); static const TickType_t xReceiveTimeOut = 0; //portMAX_DELAY; const BaseType_t xBacklog = 10; xSocketSet_t xSocketSet; struct xTCP_SERVER *pxServerList = NULL; struct xTCP_SERVER *pxIterator; xWinProperties_t winProps; /* Just to prevent compiler warnings. */ ( void ) pvParameters; /* Attempt to open the socket. */ xListeningSocket = FreeRTOS_socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ); configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET ); /* Set a time out so accept() will just wait for a connection. */ FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); memset(&winProps, '\0', sizeof( winProps ) ); // Size in units of MSS winProps.lTxBufSize = 1 * 1460;//1000; winProps.lTxWinSize = 2; winProps.lRxBufSize = 2 * 1460; winProps.lRxWinSize = 2; FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &winProps, sizeof( winProps ) ); /* The strange casting is to remove compiler errors. */ xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL; xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port ); /* Bind the socket to the port that the client task will send to, then listen for incoming connections. */ while( FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) ) != 0 ); FreeRTOS_listen( xListeningSocket, xBacklog ); lastTickTime = xTaskGetTickCount (); pxServerList = NULL; xSocketSet = FreeRTOS_createsocketset( ); configASSERT( xSocketSet != NULL ); FreeRTOS_FD_SET( xListeningSocket, xSocketSet, eSELECT_READ ); for( ;; ) { TickType_t xMask = FreeRTOS_select( xSocketSet, 3000 ); if( FreeRTOS_FD_ISSET( xListeningSocket, xSocketSet ) ) { xSocket_t xNewSocket; xNewSocket = FreeRTOS_accept( xListeningSocket, &xClient, &xSize ); if ( xNewSocket && xNewSocket != FREERTOS_INVALID_SOCKET ) { xTcpServer_t *pxServer; FreeRTOS_debug_printf( ( "prvConnectionListeningTask: new connection %xip:%u\n", FreeRTOS_ntohl( xClient.sin_addr ), FreeRTOS_ntohs( xClient.sin_port ) ) ); pxServer = (xTcpServer_t *)pvPortMalloc( sizeof( *pxServer ) ); memset( pxServer, '\0', sizeof( *pxServer )); pxServer->xSocket = xNewSocket; FreeRTOS_FD_SET( xNewSocket, xSocketSet, eSELECT_READ | eSELECT_EXCEPT ); if( pxServerList == NULL ) { /* This is the first server */ pxServerList = pxServer; } else { /* Attach it to the end of the list */ for( pxIterator = pxServerList; pxIterator->pxNext != NULL; pxIterator = pxIterator->pxNext ) { } pxIterator->pxNext = pxServer; } prvTcpInit( pxServer ); } } { xTcpServer_t *pxThisServer = NULL; for( pxIterator = pxServerList; pxIterator != NULL; ) { BaseType_t rc; pxThisServer = pxIterator; /* Move to the next one before the current gets deleted */ pxIterator = pxIterator->pxNext; if( FreeRTOS_FD_ISSET( pxThisServer->xSocket, xSocketSet ) == 0 ) { continue; } rc = prvTcpWork( pxThisServer ); if( rc < 0) { FreeRTOS_FD_CLR( pxThisServer->xSocket, xSocketSet, eSELECT_ALL ); if( pxServerList = pxThisServer ) { pxServerList = pxThisServer->pxNext; } else { struct xTCP_SERVER *pxOther; for( pxOther = pxServerList; pxOther->pxNext != NULL; pxOther = pxOther->pxNext ) { if( pxOther->pxNext == pxThisServer ) { pxOther->pxNext == pxThisServer->pxNext; break; } } } /* Close the socket and free the space */ prvTcpClose( pxThisServer ); } else { pxThisServer->bHasSendRequest = prvTcpHasSendData( pxThisServer ); if( pxThisServer->bHasSendRequest ) FreeRTOS_FD_SET( pxThisServer->xSocket, xSocketSet, eSELECT_WRITE ); else FreeRTOS_FD_CLR( pxThisServer->xSocket, xSocketSet, eSELECT_WRITE ); //FreeRTOS_debug_printf( ( "SET_FD WRITE %d\n", pxServerFound->bHasSendRequest != 0 ) ); } } } if( ( xTaskGetTickCount () - lastTickTime ) > 30000 ) { lastTickTime = xTaskGetTickCount (); //plusPrintf( "ListeningTask %ld,%ld tasks\n", xTaskCount, xConfirmedCount ); } } }
static void prvMultipleSocketRxTask( void *pvParameters ) { xSocketSet_t xFD_Set; xSocket_t xSocket; struct freertos_sockaddr xAddress; uint32_t xClientLength = sizeof( struct freertos_sockaddr ), ulFirstRxPortNumber, x; uint32_t ulReceivedValue = 0, ulExpectedValue = 0UL, ulReceivedCount[ selNUMBER_OF_SOCKETS ] = { 0 }; int32_t lBytes; const TickType_t xRxBlockTime = 0; /* The number of the port the first Rx socket will be bound to is passed in as the task parameter. Other port numbers used are consecutive from this. */ ulFirstRxPortNumber = ( uint32_t ) pvParameters; /* Create the set of sockets that will be passed into FreeRTOS_select(). */ xFD_Set = FreeRTOS_CreateSocketSet( selSELECT_QUEUE_SIZE ); for( x = 0; x < selNUMBER_OF_SOCKETS; x++ ) { /* Create the next Rx socket. */ xRxSockets[ x ] = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); configASSERT( xRxSockets[ x ] ); /* Bind to the next port number. */ xAddress.sin_port = FreeRTOS_htons( ( uint16_t ) ( ulFirstRxPortNumber + x ) ); FreeRTOS_bind( xRxSockets[ x ], &xAddress, sizeof( struct freertos_sockaddr ) ); /* There should always be data available on the socket returned from FreeRTOS_select() so blocking on a read should not be necessary. */ FreeRTOS_setsockopt( xRxSockets[ x ], 0, FREERTOS_SO_RCVTIMEO, &xRxBlockTime, sizeof( xRxBlockTime ) ); /* Add the created socket to the set. */ FreeRTOS_FD_SET( xRxSockets[ x ], xFD_Set ); } for( ;; ) { /* Wait for a socket from the set to become available for reading. */ xSocket = FreeRTOS_select( xFD_Set, portMAX_DELAY ); /* xSocket should never be NULL because FreeRTOS_select() was called with an indefinite delay (assuming INCLUDE_vTaskSuspend is set to 1). */ configASSERT( xSocket ); lBytes = FreeRTOS_recvfrom( xSocket, &( ulReceivedValue ), sizeof( uint32_t ), 0, &xAddress, &xClientLength ); /* It is possible that the first value received will not be zero because the first few transmitted packets may have been dropped to send an ARP and then wait the ARP reply. */ if( ulExpectedValue == 0 ) { if( ulExpectedValue != ulReceivedValue ) { /* Correct for packets lost to ARP traffic. */ ulExpectedValue = ulReceivedValue; } } /* Data should always be available even though the block time was set to zero because the socket was returned from FreeRTOS_select(). */ configASSERT( lBytes == 4 ); configASSERT( ulReceivedValue == ulExpectedValue ); ulExpectedValue++; /* Keep a record of the number of times each socket has been used so it can be verified (using the debugger) that they all get used. */ for( x= 0; x < selNUMBER_OF_SOCKETS; x++ ) { if( xSocket == xRxSockets[ x ] ) { ( ulReceivedCount[ x ] )++; break; } } } }
static void prvMultipleSocketRxTask( void *pvParameters ) { xSocketSet_t xFD_Set; xSocket_t xSocket; struct freertos_sockaddr xAddress; uint32_t xClientLength = sizeof( struct freertos_sockaddr ), ulFirstRxPortNumber, x; uint32_t ulReceivedValue = 0, ulCount; uint8_t ucReceivedValues[ selMAX_TX_VALUE ]; /* If the array position is pdTRUE then the corresponding value has been received. */ int32_t lBytes; const TickType_t xRxBlockTime = 0; BaseType_t xResult; /* The number of the port the first Rx socket will be bound to is passed in as the task parameter. Other port numbers used are consecutive from this. */ ulFirstRxPortNumber = ( uint32_t ) pvParameters; /* Create the set for sockets that will be passed into FreeRTOS_select(). */ xFD_Set = FreeRTOS_CreateSocketSet(); /* Create the sockets and add them to the set. */ for( x = 0; x < selNUMBER_OF_SOCKETS; x++ ) { /* Create the next Rx socket. */ xRxSockets[ x ] = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); configASSERT( xRxSockets[ x ] != FREERTOS_INVALID_SOCKET ); /* Bind to the next port number. */ xAddress.sin_port = FreeRTOS_htons( ( uint16_t ) ( ulFirstRxPortNumber + x ) ); FreeRTOS_bind( xRxSockets[ x ], &xAddress, sizeof( struct freertos_sockaddr ) ); /* There should always be data available after FreeRTOS_select() so blocking on a read should not be necessary. */ FreeRTOS_setsockopt( xRxSockets[ x ], 0, FREERTOS_SO_RCVTIMEO, &xRxBlockTime, sizeof( xRxBlockTime ) ); /* Add the created socket to the set. */ FreeRTOS_FD_SET( xRxSockets[ x ], xFD_Set, eSELECT_ALL ); } for( ;; ) { /* No values have yet been received so set each array position to pdFALSE. Each expected Rx value has a corresponding array position. */ memset( ( void * ) ucReceivedValues, pdFALSE, sizeof( ucReceivedValues ) ); /* Wait for the other task to resume this task - indicating that it is about to start sending. */ vTaskSuspend( NULL ); /* Expect to receive selMAX_TX_VALUE values. */ ulCount = 0; while( ulCount < selMAX_TX_VALUE ) { /* Wait for a socket from the set to become available for reading. */ xResult = FreeRTOS_select( xFD_Set, xReceiveBlockTime ); if( xResult != 0 ) { /* See which sockets have data waiting to be read. */ for( x = 0; x < selNUMBER_OF_SOCKETS; x++ ) { xSocket = xRxSockets[ x ]; /* Find the expected value for this socket */ if( FreeRTOS_FD_ISSET( xSocket, xFD_Set ) != 0 ) { while( ( lBytes = FreeRTOS_recvfrom( xSocket, &( ulReceivedValue ), sizeof( uint32_t ), 0, &xAddress, &xClientLength ) ) > 0 ) { /* Received another message. */ ulCount++; /* It is always expected that the read will pass. */ configASSERT( ( size_t ) lBytes == ( sizeof( uint32_t ) ) ); /* Don't expect to receive anything greater than selMAX_TX_VALUE - 1. */ configASSERT( ulReceivedValue < selMAX_TX_VALUE ); /* Don't expect to receive any value twice. */ configASSERT( ucReceivedValues[ ulReceivedValue ] != pdTRUE ); if( ucReceivedValues[ ulReceivedValue ] != pdTRUE ) { /* Mark the value as received by setting its index in the received array to pdTRUE. */ ucReceivedValues[ ulReceivedValue ] = pdTRUE; } else { ulErrorOccurred = pdTRUE; } } } } } else { /* No value was received in time. */ break; } } /* Were all values received? */ if( ulCount == selMAX_TX_VALUE ) { /* Check all selMAX_TX_VALUE values are present and correct before starting a new cycle. It is valid for a few values at the beginning of the array to be missing as they may have been dropped for ARP messages, so start a few indexes in. */ for( ulCount = 4; ulCount < selMAX_TX_VALUE; ulCount++ ) { configASSERT( ucReceivedValues[ ulCount ] == pdTRUE ); if( ucReceivedValues[ ulCount ] != pdTRUE ) { /* The value corresponding to this array position was never received. In a real application UDP is not reliable, but in this tightly controlled test it is unusual for a packet to be dropped. */ ulErrorOccurred = pdTRUE; } } ulRxCycles++; } else { /* Just for viewing in the debugger. */ ulFailedRxCycles++; } } }