DWORD WINAPI prvWinPcapSendThread( void *pvParam ) { size_t xLength; uint8_t ucBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ]; static char cErrorMessage[ 1024 ]; const DWORD xMaxMSToWait = 1000; /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT OUT MESSAGES HERE. */ /* Remove compiler warnings about unused parameters. */ ( void ) pvParam; for( ;; ) { /* Wait until notified of something to send. */ WaitForSingleObject( pvSendEvent, xMaxMSToWait ); /* Is there more than the length value stored in the circular buffer used to pass data from the FreeRTOS simulator into this Win32 thread? */ while( uxStreamBufferGetSize( xSendBuffer ) > sizeof( xLength ) ) { uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE ); uxStreamBufferGet( xSendBuffer, 0, ( uint8_t* ) ucBuffer, xLength, pdFALSE ); if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength ) != 0 ) { ulWinPCAPSendFailures++; } } } }
/* * uxStreamBufferGet( ) * 'uxOffset' can be used to read data located at a certain offset from 'lTail'. * If 'pucData' equals NULL, the function is called to advance 'lTail' only. * if 'xPeek' is pdTRUE, or if 'uxOffset' is non-zero, the 'lTail' pointer will * not be advanced. */ size_t uxStreamBufferGet( StreamBuffer_t *pxBuffer, size_t uxOffset, uint8_t *pucData, size_t uxMaxCount, BaseType_t xPeek ) { size_t uxSize, uxCount, uxFirst, uxNextTail; /* How much data is available? */ uxSize = uxStreamBufferGetSize( pxBuffer ); if( uxSize > uxOffset ) { uxSize -= uxOffset; } else { uxSize = 0u; } /* Use the minimum of the wanted bytes and the available bytes. */ uxCount = FreeRTOS_min_uint32( uxSize, uxMaxCount ); if( uxCount > 0u ) { uxNextTail = pxBuffer->uxTail; if( uxOffset != 0u ) { uxNextTail += uxOffset; if( uxNextTail >= pxBuffer->LENGTH ) { uxNextTail -= pxBuffer->LENGTH; } } if( pucData != NULL ) { /* Calculate the number of bytes that can be read - which may be less than the number wanted if the data wraps around to the start of the buffer. */ uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextTail, uxCount ); /* Obtain the number of bytes it is possible to obtain in the first read. */ memcpy( pucData, pxBuffer->ucArray + uxNextTail, uxFirst ); /* If the total number of wanted bytes is greater than the number that could be read in the first read... */ if( uxCount > uxFirst ) { /*...then read the remaining bytes from the start of the buffer. */ memcpy( pucData + uxFirst, pxBuffer->ucArray, uxCount - uxFirst ); } } if( ( xPeek == pdFALSE ) && ( uxOffset == 0UL ) ) { /* Move the tail pointer to effecively remove the data read from the buffer. */ uxNextTail += uxCount; if( uxNextTail >= pxBuffer->LENGTH ) { uxNextTail -= pxBuffer->LENGTH; } pxBuffer->uxTail = uxNextTail; } } return uxCount; }
static void prvInterruptSimulatorTask( void *pvParameters ) { struct pcap_pkthdr xHeader; static struct pcap_pkthdr *pxHeader; const uint8_t *pucPacketData; uint8_t ucRecvBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ]; NetworkBufferDescriptor_t *pxNetworkBuffer; IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; eFrameProcessingResult_t eResult; /* Remove compiler warnings about unused parameters. */ ( void ) pvParameters; for( ;; ) { /* Does the circular buffer used to pass data from the Win32 thread that handles WinPCAP Rx into the FreeRTOS simulator contain another packet? */ if( uxStreamBufferGetSize( xRecvBuffer ) > sizeof( xHeader ) ) { /* Get the next packet. */ uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)&xHeader, sizeof( xHeader ), pdFALSE ); uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)ucRecvBuffer, ( size_t ) xHeader.len, pdFALSE ); pucPacketData = ucRecvBuffer; pxHeader = &xHeader; iptraceNETWORK_INTERFACE_RECEIVE(); eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData ); if( eResult == eProcessBuffer ) { /* Will the data fit into the frame buffer? */ if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE ) { /* Obtain a buffer into which the data can be placed. This is only an interrupt simulator, not a real interrupt, so it is ok to call the task level function here, but note that some buffer implementations cannot be called from a real interrupt. */ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 ); if( pxNetworkBuffer != NULL ) { memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len ); pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len; #if( niDISRUPT_PACKETS == 1 ) { pxNetworkBuffer = vRxFaultInjection( pxNetworkBuffer, pucPacketData ); } #endif /* niDISRUPT_PACKETS */ if( pxNetworkBuffer != NULL ) { xRxEvent.pvData = ( void * ) pxNetworkBuffer; /* Data was received and stored. Send a message to the IP task to let it know. */ if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL ) { /* The buffer could not be sent to the stack so must be released again. This is only an interrupt simulator, not a real interrupt, so it is ok to use the task level function here, but note no all buffer implementations will allow this function to be executed from a real interrupt. */ vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); iptraceETHERNET_RX_EVENT_LOST(); } } else { /* The packet was already released or stored inside vRxFaultInjection(). Don't release it here. */ } } else { iptraceETHERNET_RX_EVENT_LOST(); } } else { /* Log that a packet was dropped because it would have overflowed the buffer, but there may be more buffers to process. */ } } } else { /* There is no real way of simulating an interrupt. Make sure other tasks can run. */ vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ); } } }