X-Git-Url: https://git.sur5r.net/?p=freertos;a=blobdiff_plain;f=FreeRTOS-Plus%2FSource%2FFreeRTOS-Plus-TCP%2Fportable%2FNetworkInterface%2FWinPCap%2FNetworkInterface.c;fp=FreeRTOS-Plus%2FSource%2FFreeRTOS-Plus-TCP%2Fportable%2FNetworkInterface%2FWinPCap%2FNetworkInterface.c;h=c4a12515b0891a151d7a5063428e77157ac80cf5;hp=474629e4632d4a552efa3e2afe016bd053b53068;hb=b15dfacb6026af3b0ba697e5753844923b468d2b;hpb=4334233a064299a09d167a497889d3860932a587 diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c index 474629e46..c4a12515b 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c @@ -1,634 +1,634 @@ -/* -FreeRTOS+TCP V2.0.11 -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 -*/ - -/* WinPCap includes. */ -#define HAVE_REMOTE -#include "pcap.h" - -/* FreeRTOS includes. */ -#include "FreeRTOS.h" -#include "task.h" -#include "semphr.h" - -/* FreeRTOS+TCP includes. */ -#include "FreeRTOS_IP.h" -#include "FreeRTOS_IP_Private.h" -#include "NetworkBufferManagement.h" - -/* Thread-safe circular buffers are being used to pass data to and from the PCAP -access functions. */ -#include "Win32-Extensions.h" -#include "FreeRTOS_Stream_Buffer.h" - -/* Sizes of the thread safe circular buffers used to pass data to and from the -WinPCAP Windows threads. */ -#define xSEND_BUFFER_SIZE 32768 -#define xRECV_BUFFER_SIZE 32768 - -/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet -driver will filter incoming packets and only pass the stack those packets it -considers need processing. */ -#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) - #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer -#else - #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) -#endif - -/* Used to insert test code only. */ -#define niDISRUPT_PACKETS 0 - -/*-----------------------------------------------------------*/ - -/* - * Windows threads that are outside of the control of the FreeRTOS simulator are - * used to interface with the WinPCAP libraries. - */ -DWORD WINAPI prvWinPcapRecvThread( void *pvParam ); -DWORD WINAPI prvWinPcapSendThread( void *pvParam ); - -/* - * Print out a numbered list of network interfaces that are available on the - * host computer. - */ -static pcap_if_t * prvPrintAvailableNetworkInterfaces( void ); - -/* - * Open the network interface. The number of the interface to be opened is set - * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h. - */ -static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces ); -static int prvOpenInterface( const char *pucName ); - -/* - * Configure the capture filter to allow blocking reads, and to filter out - * packets that are not of interest to this demo. - */ -static void prvConfigureCaptureBehaviour( void ); - -/* - * A function that simulates Ethernet interrupts by periodically polling the - * WinPCap interface for new data. - */ -static void prvInterruptSimulatorTask( void *pvParameters ); - -/* - * Create the buffers that are used to pass data between the FreeRTOS simulator - * and the Win32 threads that manage WinPCAP. - */ -static void prvCreateThreadSafeBuffers( void ); - -/* - * Utility function used to format print messages only. - */ -static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage ); - -/*-----------------------------------------------------------*/ - -/* Required by the WinPCap library. */ -static char cErrorBuffer[ PCAP_ERRBUF_SIZE ]; - -/* An event used to wake up the Win32 thread that sends data through the WinPCAP -library. */ -static void *pvSendEvent = NULL; - -/* _HT_ made the PCAP interface number configurable through the program's -parameters in order to test in different machines. */ -static BaseType_t xConfigNetworkInterfaceToUse = configNETWORK_INTERFACE_TO_USE; - -/* Handles to the Windows threads that handle the PCAP IO. */ -static HANDLE vWinPcapRecvThreadHandle = NULL; -static HANDLE vWinPcapSendThreadHandle = NULL;; - -/* The interface being used by WinPCap. */ -static pcap_t *pxOpenedInterfaceHandle = NULL; - -/* Circular buffers used by the PCAP Win32 threads. */ -static StreamBuffer_t *xSendBuffer = NULL; -static StreamBuffer_t *xRecvBuffer = NULL; - -/* The MAC address initially set to the constants defined in FreeRTOSConfig.h. */ -extern uint8_t ucMACAddress[ 6 ]; - -/* Logs the number of WinPCAP send failures, for viewing in the debugger only. */ -static volatile uint32_t ulWinPCAPSendFailures = 0; - -/*-----------------------------------------------------------*/ - -BaseType_t xNetworkInterfaceInitialise( void ) -{ -BaseType_t xReturn = pdFALSE; -pcap_if_t *pxAllNetworkInterfaces; - - /* Query the computer the simulation is being executed on to find the - network interfaces it has installed. */ - pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces(); - - /* Open the network interface. The number of the interface to be opened is - set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h. - Calling this function will set the pxOpenedInterfaceHandle variable. If, - after calling this function, pxOpenedInterfaceHandle is equal to NULL, then - the interface could not be opened. */ - if( pxAllNetworkInterfaces != NULL ) - { - prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces ); - } - - if( pxOpenedInterfaceHandle != NULL ) - { - xReturn = pdPASS; - } - - return xReturn; -} -/*-----------------------------------------------------------*/ - -static void prvCreateThreadSafeBuffers( void ) -{ - /* The buffer used to pass data to be transmitted from a FreeRTOS task to - the Win32 thread that sends via the WinPCAP library. */ - if( xSendBuffer == NULL) - { - xSendBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) + xSEND_BUFFER_SIZE + 1 ); - configASSERT( xSendBuffer ); - memset( xSendBuffer, '\0', sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) ); - xSendBuffer->LENGTH = xSEND_BUFFER_SIZE + 1; - } - - /* The buffer used to pass received data from the Win32 thread that receives - via the WinPCAP library to the FreeRTOS task. */ - if( xRecvBuffer == NULL) - { - xRecvBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) + xRECV_BUFFER_SIZE + 1 ); - configASSERT( xRecvBuffer ); - memset( xRecvBuffer, '\0', sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) ); - xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1; - } -} -/*-----------------------------------------------------------*/ - -BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend ) -{ -size_t xSpace; - - iptraceNETWORK_INTERFACE_TRANSMIT(); - configASSERT( xIsCallingFromIPTask() == pdTRUE ); - - /* Both the length of the data being sent and the actual data being sent - are placed in the thread safe buffer used to pass data between the FreeRTOS - tasks and the Win32 thread that sends data via the WinPCAP library. Drop - the packet if there is insufficient space in the buffer to hold both. */ - xSpace = uxStreamBufferGetSpace( xSendBuffer ); - - if( ( pxNetworkBuffer->xDataLength <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) && - ( xSpace >= ( pxNetworkBuffer->xDataLength + sizeof( pxNetworkBuffer->xDataLength ) ) ) ) - { - /* First write in the length of the data, then write in the data - itself. */ - uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) &( pxNetworkBuffer->xDataLength ), sizeof( pxNetworkBuffer->xDataLength ) ); - uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength ); - } - else - { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: send buffers full to store %lu\n", pxNetworkBuffer->xDataLength ) ); - } - - /* Kick the Tx task in either case in case it doesn't know the buffer is - full. */ - SetEvent( pvSendEvent ); - - /* The buffer has been sent so can be released. */ - if( bReleaseAfterSend != pdFALSE ) - { - vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); - } - - return pdPASS; -} -/*-----------------------------------------------------------*/ - -static pcap_if_t * prvPrintAvailableNetworkInterfaces( void ) -{ -pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface; -int32_t lInterfaceNumber = 1; -char cBuffer[ 512 ]; -static BaseType_t xInvalidInterfaceDetected = pdFALSE; - - if( xInvalidInterfaceDetected == pdFALSE ) - { - if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 ) - { - printf( "Could not obtain a list of network interfaces\n%s\n", cErrorBuffer ); - pxAllNetworkInterfaces = NULL; - } - else - { - printf( "\r\n\r\nThe following network interfaces are available:\r\n\r\n" ); - } - - if( pxAllNetworkInterfaces != NULL ) - { - /* Print out the list of network interfaces. The first in the list - is interface '1', not interface '0'. */ - for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next ) - { - /* The descriptions of the devices can be full of spaces, clean them - a little. printf() can only be used here because the network is not - up yet - so no other network tasks will be running. */ - printf( "Interface %d - %s\n", lInterfaceNumber, prvRemoveSpaces( cBuffer, sizeof( cBuffer ), xInterface->name ) ); - printf( " (%s)\n", prvRemoveSpaces(cBuffer, sizeof( cBuffer ), xInterface->description ? xInterface->description : "No description" ) ); - printf( "\n" ); - lInterfaceNumber++; - } - } - - if( lInterfaceNumber == 1 ) - { - /* The interface number was never incremented, so the above for() loop - did not execute meaning no interfaces were found. */ - printf( " \nNo network interfaces were found.\n" ); - pxAllNetworkInterfaces = NULL; - } - - printf( "\r\nThe interface that will be opened is set by " ); - printf( "\"configNETWORK_INTERFACE_TO_USE\", which\r\nshould be defined in FreeRTOSConfig.h\r\n" ); - - if( ( xConfigNetworkInterfaceToUse < 1L ) || ( xConfigNetworkInterfaceToUse >= lInterfaceNumber ) ) - { - printf( "\r\nERROR: configNETWORK_INTERFACE_TO_USE is set to %d, which is an invalid value.\r\n", xConfigNetworkInterfaceToUse ); - printf( "Please set configNETWORK_INTERFACE_TO_USE to one of the interface numbers listed above,\r\n" ); - printf( "then re-compile and re-start the application. Only Ethernet (as opposed to WiFi)\r\n" ); - printf( "interfaces are supported.\r\n\r\nHALTING\r\n\r\n\r\n" ); - xInvalidInterfaceDetected = pdTRUE; - - if( pxAllNetworkInterfaces != NULL ) - { - /* Free the device list, as no devices are going to be opened. */ - pcap_freealldevs( pxAllNetworkInterfaces ); - pxAllNetworkInterfaces = NULL; - } - } - else - { - printf( "Attempting to open interface number %d.\n", xConfigNetworkInterfaceToUse ); - } - } - - return pxAllNetworkInterfaces; -} -/*-----------------------------------------------------------*/ - -static int prvOpenInterface( const char *pucName ) -{ -static char pucInterfaceName[ 256 ]; - - if( pucName != NULL ) - { - strncpy( pucInterfaceName, pucName, sizeof( pucInterfaceName ) ); - } - - pxOpenedInterfaceHandle = pcap_open( pucInterfaceName, /* The name of the selected interface. */ - ipTOTAL_ETHERNET_FRAME_SIZE, /* The size of the packet to capture. */ - PCAP_OPENFLAG_PROMISCUOUS, /* Open in promiscuous mode as the MAC and - IP address is going to be "simulated", and - not be the real MAC and IP address. This allows - traffic to the simulated IP address to be routed - to uIP, and traffic to the real IP address to be - routed to the Windows TCP/IP stack. */ - 100, - NULL, /* No authentication is required as this is - not a remote capture session. */ - cErrorBuffer - ); - - if ( pxOpenedInterfaceHandle == NULL ) - { - printf( "\n%s is not supported by WinPcap and cannot be opened\n", pucInterfaceName ); - return 1; - } - else - { - /* Configure the capture filter to allow blocking reads, and to filter - out packets that are not of interest to this demo. */ - prvConfigureCaptureBehaviour(); - } - return 0; -} -/*-----------------------------------------------------------*/ - -static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces ) -{ -pcap_if_t *pxInterface; -int32_t x; - - /* Walk the list of devices until the selected device is located. */ - pxInterface = pxAllNetworkInterfaces; - for( x = 0L; x < ( xConfigNetworkInterfaceToUse - 1L ); x++ ) - { - pxInterface = pxInterface->next; - } - - /* Open the selected interface. */ - if( prvOpenInterface( pxInterface->name ) == 0 ) - { - printf( "Successfully opened interface number %d.\n", x + 1 ); - } - else - { - printf( "Failed to open interface number %d.\n", x + 1 ); - } - - /* The device list is no longer required. */ - pcap_freealldevs( pxAllNetworkInterfaces ); -} -/*-----------------------------------------------------------*/ - -static void prvConfigureCaptureBehaviour( void ) -{ -struct bpf_program xFilterCode; -uint32_t ulNetMask; - - /* Set up a filter so only the packets of interest are passed to the IP - stack. cErrorBuffer is used for convenience to create the string. Don't - confuse this with an error message. */ - sprintf( cErrorBuffer, "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x", - ucMACAddress[0], ucMACAddress[1], ucMACAddress[2], ucMACAddress[3], ucMACAddress[4], ucMACAddress[5] ); - - ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0; - - if( pcap_compile( pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 ) - { - printf( "\nThe packet filter string is invalid\n" ); - } - else - { - if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 ) - { - printf( "\nAn error occurred setting the packet filter.\n" ); - } - /* When pcap_compile() succeeds, it allocates memory for the memory pointed to by the bpf_program struct - parameter.pcap_freecode() will free that memory. */ - pcap_freecode( &xFilterCode ); - } - - /* Create the buffers used to pass packets between the FreeRTOS simulator - and the Win32 threads that are handling WinPCAP. */ - prvCreateThreadSafeBuffers(); - - if( pvSendEvent == NULL ) - { - /* Create event used to signal the Win32 WinPCAP Tx thread. */ - pvSendEvent = CreateEvent( NULL, FALSE, TRUE, NULL ); - - /* Create the Win32 thread that handles WinPCAP Rx. */ - vWinPcapRecvThreadHandle = CreateThread( - NULL, /* Pointer to thread security attributes. */ - 0, /* Initial thread stack size, in bytes. */ - prvWinPcapRecvThread, /* Pointer to thread function. */ - NULL, /* Argument for new thread. */ - 0, /* Creation flags. */ - NULL ); - - /* Use the cores that are not used by the FreeRTOS tasks. */ - SetThreadAffinityMask( vWinPcapRecvThreadHandle, ~0x01u ); - - /* Create the Win32 thread that handlers WinPCAP Tx. */ - vWinPcapSendThreadHandle = CreateThread( - NULL, /* Pointer to thread security attributes. */ - 0, /* initial thread stack size, in bytes. */ - prvWinPcapSendThread, /* Pointer to thread function. */ - NULL, /* Argument for new thread. */ - 0, /* Creation flags. */ - NULL ); - - /* Use the cores that are not used by the FreeRTOS tasks. */ - SetThreadAffinityMask( vWinPcapSendThreadHandle, ~0x01u ); - - /* Create a task that simulates an interrupt in a real system. This will - block waiting for packets, then send a message to the IP task when data - is available. */ - xTaskCreate( prvInterruptSimulatorTask, "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, configMAC_ISR_SIMULATOR_PRIORITY, NULL ); - } -} -/*-----------------------------------------------------------*/ - -/* WinPCAP function. */ -void pcap_callback( u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data ) -{ - (void)user; - - /* THIS IS CALLED FROM A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS - OR TO PRINT OUT MESSAGES HERE. */ - - /* Pass data to the FreeRTOS simulator on a thread safe circular buffer. */ - if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) && - ( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) ) - { - uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_header, sizeof( *pkt_header ) ); - uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen ); - } -} -/*-----------------------------------------------------------*/ - -DWORD WINAPI prvWinPcapRecvThread ( void *pvParam ) -{ - ( void ) pvParam; - - /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT - OUT MESSAGES HERE. */ - - for( ;; ) - { - pcap_dispatch( pxOpenedInterfaceHandle, 1, pcap_callback, ( u_char * ) "mydata" ); - } -} -/*-----------------------------------------------------------*/ - -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++; - } - } - } -} -/*-----------------------------------------------------------*/ - -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(); - - /* Check for minimal size. */ - if( pxHeader->len >= sizeof( EthernetHeader_t ) ) - { - eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData ); - } - else - { - eResult = eReleaseBuffer; - } - - 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 ); - } - } -} -/*-----------------------------------------------------------*/ - -static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage ) -{ - char *pcTarget = pcBuffer; - - /* Utility function used to formap messages being printed only. */ - while( ( *pcMessage != 0 ) && ( pcTarget < ( pcBuffer + aBuflen - 1 ) ) ) - { - *( pcTarget++ ) = *pcMessage; - - if( isspace( *pcMessage ) != pdFALSE ) - { - while( isspace( *pcMessage ) != pdFALSE ) - { - pcMessage++; - } - } - else - { - pcMessage++; - } - } - - *pcTarget = '\0'; - - return pcBuffer; -} +/* +FreeRTOS+TCP V2.0.11 +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 +*/ + +/* WinPCap includes. */ +#define HAVE_REMOTE +#include "pcap.h" + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* FreeRTOS+TCP includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_IP_Private.h" +#include "NetworkBufferManagement.h" + +/* Thread-safe circular buffers are being used to pass data to and from the PCAP +access functions. */ +#include "Win32-Extensions.h" +#include "FreeRTOS_Stream_Buffer.h" + +/* Sizes of the thread safe circular buffers used to pass data to and from the +WinPCAP Windows threads. */ +#define xSEND_BUFFER_SIZE 32768 +#define xRECV_BUFFER_SIZE 32768 + +/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet +driver will filter incoming packets and only pass the stack those packets it +considers need processing. */ +#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) + #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer +#else + #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) +#endif + +/* Used to insert test code only. */ +#define niDISRUPT_PACKETS 0 + +/*-----------------------------------------------------------*/ + +/* + * Windows threads that are outside of the control of the FreeRTOS simulator are + * used to interface with the WinPCAP libraries. + */ +DWORD WINAPI prvWinPcapRecvThread( void *pvParam ); +DWORD WINAPI prvWinPcapSendThread( void *pvParam ); + +/* + * Print out a numbered list of network interfaces that are available on the + * host computer. + */ +static pcap_if_t * prvPrintAvailableNetworkInterfaces( void ); + +/* + * Open the network interface. The number of the interface to be opened is set + * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h. + */ +static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces ); +static int prvOpenInterface( const char *pucName ); + +/* + * Configure the capture filter to allow blocking reads, and to filter out + * packets that are not of interest to this demo. + */ +static void prvConfigureCaptureBehaviour( void ); + +/* + * A function that simulates Ethernet interrupts by periodically polling the + * WinPCap interface for new data. + */ +static void prvInterruptSimulatorTask( void *pvParameters ); + +/* + * Create the buffers that are used to pass data between the FreeRTOS simulator + * and the Win32 threads that manage WinPCAP. + */ +static void prvCreateThreadSafeBuffers( void ); + +/* + * Utility function used to format print messages only. + */ +static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage ); + +/*-----------------------------------------------------------*/ + +/* Required by the WinPCap library. */ +static char cErrorBuffer[ PCAP_ERRBUF_SIZE ]; + +/* An event used to wake up the Win32 thread that sends data through the WinPCAP +library. */ +static void *pvSendEvent = NULL; + +/* _HT_ made the PCAP interface number configurable through the program's +parameters in order to test in different machines. */ +static BaseType_t xConfigNetworkInterfaceToUse = configNETWORK_INTERFACE_TO_USE; + +/* Handles to the Windows threads that handle the PCAP IO. */ +static HANDLE vWinPcapRecvThreadHandle = NULL; +static HANDLE vWinPcapSendThreadHandle = NULL;; + +/* The interface being used by WinPCap. */ +static pcap_t *pxOpenedInterfaceHandle = NULL; + +/* Circular buffers used by the PCAP Win32 threads. */ +static StreamBuffer_t *xSendBuffer = NULL; +static StreamBuffer_t *xRecvBuffer = NULL; + +/* The MAC address initially set to the constants defined in FreeRTOSConfig.h. */ +extern uint8_t ucMACAddress[ 6 ]; + +/* Logs the number of WinPCAP send failures, for viewing in the debugger only. */ +static volatile uint32_t ulWinPCAPSendFailures = 0; + +/*-----------------------------------------------------------*/ + +BaseType_t xNetworkInterfaceInitialise( void ) +{ +BaseType_t xReturn = pdFALSE; +pcap_if_t *pxAllNetworkInterfaces; + + /* Query the computer the simulation is being executed on to find the + network interfaces it has installed. */ + pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces(); + + /* Open the network interface. The number of the interface to be opened is + set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h. + Calling this function will set the pxOpenedInterfaceHandle variable. If, + after calling this function, pxOpenedInterfaceHandle is equal to NULL, then + the interface could not be opened. */ + if( pxAllNetworkInterfaces != NULL ) + { + prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces ); + } + + if( pxOpenedInterfaceHandle != NULL ) + { + xReturn = pdPASS; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static void prvCreateThreadSafeBuffers( void ) +{ + /* The buffer used to pass data to be transmitted from a FreeRTOS task to + the Win32 thread that sends via the WinPCAP library. */ + if( xSendBuffer == NULL) + { + xSendBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) + xSEND_BUFFER_SIZE + 1 ); + configASSERT( xSendBuffer ); + memset( xSendBuffer, '\0', sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) ); + xSendBuffer->LENGTH = xSEND_BUFFER_SIZE + 1; + } + + /* The buffer used to pass received data from the Win32 thread that receives + via the WinPCAP library to the FreeRTOS task. */ + if( xRecvBuffer == NULL) + { + xRecvBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) + xRECV_BUFFER_SIZE + 1 ); + configASSERT( xRecvBuffer ); + memset( xRecvBuffer, '\0', sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) ); + xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1; + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend ) +{ +size_t xSpace; + + iptraceNETWORK_INTERFACE_TRANSMIT(); + configASSERT( xIsCallingFromIPTask() == pdTRUE ); + + /* Both the length of the data being sent and the actual data being sent + are placed in the thread safe buffer used to pass data between the FreeRTOS + tasks and the Win32 thread that sends data via the WinPCAP library. Drop + the packet if there is insufficient space in the buffer to hold both. */ + xSpace = uxStreamBufferGetSpace( xSendBuffer ); + + if( ( pxNetworkBuffer->xDataLength <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) && + ( xSpace >= ( pxNetworkBuffer->xDataLength + sizeof( pxNetworkBuffer->xDataLength ) ) ) ) + { + /* First write in the length of the data, then write in the data + itself. */ + uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) &( pxNetworkBuffer->xDataLength ), sizeof( pxNetworkBuffer->xDataLength ) ); + uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength ); + } + else + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: send buffers full to store %lu\n", pxNetworkBuffer->xDataLength ) ); + } + + /* Kick the Tx task in either case in case it doesn't know the buffer is + full. */ + SetEvent( pvSendEvent ); + + /* The buffer has been sent so can be released. */ + if( bReleaseAfterSend != pdFALSE ) + { + vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); + } + + return pdPASS; +} +/*-----------------------------------------------------------*/ + +static pcap_if_t * prvPrintAvailableNetworkInterfaces( void ) +{ +pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface; +int32_t lInterfaceNumber = 1; +char cBuffer[ 512 ]; +static BaseType_t xInvalidInterfaceDetected = pdFALSE; + + if( xInvalidInterfaceDetected == pdFALSE ) + { + if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 ) + { + printf( "Could not obtain a list of network interfaces\n%s\n", cErrorBuffer ); + pxAllNetworkInterfaces = NULL; + } + else + { + printf( "\r\n\r\nThe following network interfaces are available:\r\n\r\n" ); + } + + if( pxAllNetworkInterfaces != NULL ) + { + /* Print out the list of network interfaces. The first in the list + is interface '1', not interface '0'. */ + for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next ) + { + /* The descriptions of the devices can be full of spaces, clean them + a little. printf() can only be used here because the network is not + up yet - so no other network tasks will be running. */ + printf( "Interface %d - %s\n", lInterfaceNumber, prvRemoveSpaces( cBuffer, sizeof( cBuffer ), xInterface->name ) ); + printf( " (%s)\n", prvRemoveSpaces(cBuffer, sizeof( cBuffer ), xInterface->description ? xInterface->description : "No description" ) ); + printf( "\n" ); + lInterfaceNumber++; + } + } + + if( lInterfaceNumber == 1 ) + { + /* The interface number was never incremented, so the above for() loop + did not execute meaning no interfaces were found. */ + printf( " \nNo network interfaces were found.\n" ); + pxAllNetworkInterfaces = NULL; + } + + printf( "\r\nThe interface that will be opened is set by " ); + printf( "\"configNETWORK_INTERFACE_TO_USE\", which\r\nshould be defined in FreeRTOSConfig.h\r\n" ); + + if( ( xConfigNetworkInterfaceToUse < 1L ) || ( xConfigNetworkInterfaceToUse >= lInterfaceNumber ) ) + { + printf( "\r\nERROR: configNETWORK_INTERFACE_TO_USE is set to %d, which is an invalid value.\r\n", xConfigNetworkInterfaceToUse ); + printf( "Please set configNETWORK_INTERFACE_TO_USE to one of the interface numbers listed above,\r\n" ); + printf( "then re-compile and re-start the application. Only Ethernet (as opposed to WiFi)\r\n" ); + printf( "interfaces are supported.\r\n\r\nHALTING\r\n\r\n\r\n" ); + xInvalidInterfaceDetected = pdTRUE; + + if( pxAllNetworkInterfaces != NULL ) + { + /* Free the device list, as no devices are going to be opened. */ + pcap_freealldevs( pxAllNetworkInterfaces ); + pxAllNetworkInterfaces = NULL; + } + } + else + { + printf( "Attempting to open interface number %d.\n", xConfigNetworkInterfaceToUse ); + } + } + + return pxAllNetworkInterfaces; +} +/*-----------------------------------------------------------*/ + +static int prvOpenInterface( const char *pucName ) +{ +static char pucInterfaceName[ 256 ]; + + if( pucName != NULL ) + { + strncpy( pucInterfaceName, pucName, sizeof( pucInterfaceName ) ); + } + + pxOpenedInterfaceHandle = pcap_open( pucInterfaceName, /* The name of the selected interface. */ + ipTOTAL_ETHERNET_FRAME_SIZE, /* The size of the packet to capture. */ + PCAP_OPENFLAG_PROMISCUOUS, /* Open in promiscuous mode as the MAC and + IP address is going to be "simulated", and + not be the real MAC and IP address. This allows + traffic to the simulated IP address to be routed + to uIP, and traffic to the real IP address to be + routed to the Windows TCP/IP stack. */ + 100, + NULL, /* No authentication is required as this is + not a remote capture session. */ + cErrorBuffer + ); + + if ( pxOpenedInterfaceHandle == NULL ) + { + printf( "\n%s is not supported by WinPcap and cannot be opened\n", pucInterfaceName ); + return 1; + } + else + { + /* Configure the capture filter to allow blocking reads, and to filter + out packets that are not of interest to this demo. */ + prvConfigureCaptureBehaviour(); + } + return 0; +} +/*-----------------------------------------------------------*/ + +static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces ) +{ +pcap_if_t *pxInterface; +int32_t x; + + /* Walk the list of devices until the selected device is located. */ + pxInterface = pxAllNetworkInterfaces; + for( x = 0L; x < ( xConfigNetworkInterfaceToUse - 1L ); x++ ) + { + pxInterface = pxInterface->next; + } + + /* Open the selected interface. */ + if( prvOpenInterface( pxInterface->name ) == 0 ) + { + printf( "Successfully opened interface number %d.\n", x + 1 ); + } + else + { + printf( "Failed to open interface number %d.\n", x + 1 ); + } + + /* The device list is no longer required. */ + pcap_freealldevs( pxAllNetworkInterfaces ); +} +/*-----------------------------------------------------------*/ + +static void prvConfigureCaptureBehaviour( void ) +{ +struct bpf_program xFilterCode; +uint32_t ulNetMask; + + /* Set up a filter so only the packets of interest are passed to the IP + stack. cErrorBuffer is used for convenience to create the string. Don't + confuse this with an error message. */ + sprintf( cErrorBuffer, "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x", + ucMACAddress[0], ucMACAddress[1], ucMACAddress[2], ucMACAddress[3], ucMACAddress[4], ucMACAddress[5] ); + + ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0; + + if( pcap_compile( pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 ) + { + printf( "\nThe packet filter string is invalid\n" ); + } + else + { + if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 ) + { + printf( "\nAn error occurred setting the packet filter.\n" ); + } + /* When pcap_compile() succeeds, it allocates memory for the memory pointed to by the bpf_program struct + parameter.pcap_freecode() will free that memory. */ + pcap_freecode( &xFilterCode ); + } + + /* Create the buffers used to pass packets between the FreeRTOS simulator + and the Win32 threads that are handling WinPCAP. */ + prvCreateThreadSafeBuffers(); + + if( pvSendEvent == NULL ) + { + /* Create event used to signal the Win32 WinPCAP Tx thread. */ + pvSendEvent = CreateEvent( NULL, FALSE, TRUE, NULL ); + + /* Create the Win32 thread that handles WinPCAP Rx. */ + vWinPcapRecvThreadHandle = CreateThread( + NULL, /* Pointer to thread security attributes. */ + 0, /* Initial thread stack size, in bytes. */ + prvWinPcapRecvThread, /* Pointer to thread function. */ + NULL, /* Argument for new thread. */ + 0, /* Creation flags. */ + NULL ); + + /* Use the cores that are not used by the FreeRTOS tasks. */ + SetThreadAffinityMask( vWinPcapRecvThreadHandle, ~0x01u ); + + /* Create the Win32 thread that handlers WinPCAP Tx. */ + vWinPcapSendThreadHandle = CreateThread( + NULL, /* Pointer to thread security attributes. */ + 0, /* initial thread stack size, in bytes. */ + prvWinPcapSendThread, /* Pointer to thread function. */ + NULL, /* Argument for new thread. */ + 0, /* Creation flags. */ + NULL ); + + /* Use the cores that are not used by the FreeRTOS tasks. */ + SetThreadAffinityMask( vWinPcapSendThreadHandle, ~0x01u ); + + /* Create a task that simulates an interrupt in a real system. This will + block waiting for packets, then send a message to the IP task when data + is available. */ + xTaskCreate( prvInterruptSimulatorTask, "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, configMAC_ISR_SIMULATOR_PRIORITY, NULL ); + } +} +/*-----------------------------------------------------------*/ + +/* WinPCAP function. */ +void pcap_callback( u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data ) +{ + (void)user; + + /* THIS IS CALLED FROM A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS + OR TO PRINT OUT MESSAGES HERE. */ + + /* Pass data to the FreeRTOS simulator on a thread safe circular buffer. */ + if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) && + ( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) ) + { + uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_header, sizeof( *pkt_header ) ); + uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen ); + } +} +/*-----------------------------------------------------------*/ + +DWORD WINAPI prvWinPcapRecvThread ( void *pvParam ) +{ + ( void ) pvParam; + + /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT + OUT MESSAGES HERE. */ + + for( ;; ) + { + pcap_dispatch( pxOpenedInterfaceHandle, 1, pcap_callback, ( u_char * ) "mydata" ); + } +} +/*-----------------------------------------------------------*/ + +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++; + } + } + } +} +/*-----------------------------------------------------------*/ + +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(); + + /* Check for minimal size. */ + if( pxHeader->len >= sizeof( EthernetHeader_t ) ) + { + eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData ); + } + else + { + eResult = eReleaseBuffer; + } + + 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 ); + } + } +} +/*-----------------------------------------------------------*/ + +static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage ) +{ + char *pcTarget = pcBuffer; + + /* Utility function used to formap messages being printed only. */ + while( ( *pcMessage != 0 ) && ( pcTarget < ( pcBuffer + aBuflen - 1 ) ) ) + { + *( pcTarget++ ) = *pcMessage; + + if( isspace( *pcMessage ) != pdFALSE ) + { + while( isspace( *pcMessage ) != pdFALSE ) + { + pcMessage++; + } + } + else + { + pcMessage++; + } + } + + *pcTarget = '\0'; + + return pcBuffer; +}