int pbntf_init(void) { m_watcher.mutw = xSemaphoreCreateRecursiveMutex(); if (NULL == m_watcher.mutw) { return -1; } m_watcher.xFD_set = FreeRTOS_CreateSocketSet(); if (NULL == m_watcher.xFD_set) { vSemaphoreDelete(m_watcher.mutw); return -1; } if (pdPASS != xTaskCreate( socket_watcher_task, "Pubnub socket watcher", SOCKET_WATCHER_STACK_DEPTH, &m_watcher, PUBNUB_TASK_PRIORITY, &m_watcher.task )) { vSemaphoreDelete(m_watcher.mutw); FreeRTOS_DeleteSocketSet(m_watcher.xFD_set); return -1; } return 0; }
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++; } } }