]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c
Sync with TCP version from AWS, including:
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / WinPCap / NetworkInterface.c
1 /*\r
2  * FreeRTOS+TCP V2.0.3\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://aws.amazon.com/freertos\r
23  * http://www.FreeRTOS.org\r
24  */\r
25 \r
26 \r
27 /* WinPCap includes. */\r
28 #define HAVE_REMOTE\r
29 #include "pcap.h"\r
30 \r
31 /* FreeRTOS includes. */\r
32 #include "FreeRTOS.h"\r
33 #include "task.h"\r
34 #include "semphr.h"\r
35 \r
36 /* FreeRTOS+TCP includes. */\r
37 #include "FreeRTOS_IP.h"\r
38 #include "FreeRTOS_IP_Private.h"\r
39 #include "NetworkBufferManagement.h"\r
40 \r
41 /* Thread-safe circular buffers are being used to pass data to and from the PCAP\r
42 access functions. */\r
43 #include "Win32-Extensions.h"\r
44 #include "FreeRTOS_Stream_Buffer.h"\r
45 \r
46 /* Sizes of the thread safe circular buffers used to pass data to and from the\r
47 WinPCAP Windows threads. */\r
48 #define xSEND_BUFFER_SIZE  32768\r
49 #define xRECV_BUFFER_SIZE  32768\r
50 \r
51 /* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
52 driver will filter incoming packets and only pass the stack those packets it\r
53 considers need processing. */\r
54 #if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
55         #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
56 #else\r
57         #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
58 #endif\r
59 \r
60 /* Used to insert test code only. */\r
61 #define niDISRUPT_PACKETS       0\r
62 \r
63 /*-----------------------------------------------------------*/\r
64 \r
65 /*\r
66  * Windows threads that are outside of the control of the FreeRTOS simulator are\r
67  * used to interface with the WinPCAP libraries.\r
68  */\r
69 DWORD WINAPI prvWinPcapRecvThread( void *pvParam );\r
70 DWORD WINAPI prvWinPcapSendThread( void *pvParam );\r
71 \r
72 /*\r
73  * Print out a numbered list of network interfaces that are available on the\r
74  * host computer.\r
75  */\r
76 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void );\r
77 \r
78 /*\r
79  * Open the network interface.  The number of the interface to be opened is set\r
80  * by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
81  */\r
82 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces );\r
83 static void prvOpenInterface( const char *pucName );\r
84 \r
85 /*\r
86  * Configure the capture filter to allow blocking reads, and to filter out\r
87  * packets that are not of interest to this demo.\r
88  */\r
89 static void prvConfigureCaptureBehaviour( void );\r
90 \r
91 /*\r
92  * A function that simulates Ethernet interrupts by periodically polling the\r
93  * WinPCap interface for new data.\r
94  */\r
95 static void prvInterruptSimulatorTask( void *pvParameters );\r
96 \r
97 /*\r
98  * Create the buffers that are used to pass data between the FreeRTOS simulator\r
99  * and the Win32 threads that manage WinPCAP.\r
100  */\r
101 static void prvCreateThreadSafeBuffers( void );\r
102 \r
103 /*\r
104  * Utility function used to format print messages only.\r
105  */\r
106 static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage );\r
107 \r
108 /*-----------------------------------------------------------*/\r
109 \r
110 /* Required by the WinPCap library. */\r
111 static char cErrorBuffer[ PCAP_ERRBUF_SIZE ];\r
112 \r
113 /* An event used to wake up the Win32 thread that sends data through the WinPCAP\r
114 library. */\r
115 static void *pvSendEvent = NULL;\r
116 \r
117 /* _HT_ made the PCAP interface number configurable through the program's\r
118 parameters in order to test in different machines. */\r
119 static BaseType_t xConfigNextworkInterfaceToUse = configNETWORK_INTERFACE_TO_USE;\r
120 \r
121 /* Handles to the Windows threads that handle the PCAP IO. */\r
122 static HANDLE vWinPcapRecvThreadHandle = NULL;\r
123 static HANDLE vWinPcapSendThreadHandle = NULL;;\r
124 \r
125 /* The interface being used by WinPCap. */\r
126 static pcap_t *pxOpenedInterfaceHandle = NULL;\r
127 \r
128 /* Circular buffers used by the PCAP Win32 threads. */\r
129 static StreamBuffer_t *xSendBuffer = NULL;\r
130 static StreamBuffer_t *xRecvBuffer = NULL;\r
131 \r
132 /* The MAC address initially set to the constants defined in FreeRTOSConfig.h. */\r
133 extern uint8_t ucMACAddress[ 6 ];\r
134 \r
135 /* Logs the number of WinPCAP send failures, for viewing in the debugger only. */\r
136 static volatile uint32_t ulWinPCAPSendFailures = 0;\r
137 \r
138 /*-----------------------------------------------------------*/\r
139 \r
140 BaseType_t xNetworkInterfaceInitialise( void )\r
141 {\r
142 BaseType_t xReturn = pdFALSE;\r
143 pcap_if_t *pxAllNetworkInterfaces;\r
144 \r
145         /* Query the computer the simulation is being executed on to find the\r
146         network interfaces it has installed. */\r
147         pxAllNetworkInterfaces = prvPrintAvailableNetworkInterfaces();\r
148 \r
149         /* Open the network interface.  The number of the interface to be opened is\r
150         set by the configNETWORK_INTERFACE_TO_USE constant in FreeRTOSConfig.h.\r
151         Calling this function will set the pxOpenedInterfaceHandle variable.  If,\r
152         after calling this function, pxOpenedInterfaceHandle is equal to NULL, then\r
153         the interface could not be opened. */\r
154         if( pxAllNetworkInterfaces != NULL )\r
155         {\r
156                 prvOpenSelectedNetworkInterface( pxAllNetworkInterfaces );\r
157         }\r
158 \r
159         if( pxOpenedInterfaceHandle != NULL )\r
160         {\r
161                 xReturn = pdPASS;\r
162         }\r
163 \r
164         return xReturn;\r
165 }\r
166 /*-----------------------------------------------------------*/\r
167 \r
168 static void prvCreateThreadSafeBuffers( void )\r
169 {\r
170         /* The buffer used to pass data to be transmitted from a FreeRTOS task to\r
171         the Win32 thread that sends via the WinPCAP library. */\r
172         if( xSendBuffer == NULL)\r
173         {\r
174                 xSendBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) + xSEND_BUFFER_SIZE + 1 );\r
175                 configASSERT( xSendBuffer );\r
176                 memset( xSendBuffer, '\0', sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) );\r
177                 xSendBuffer->LENGTH = xSEND_BUFFER_SIZE + 1;\r
178         }\r
179 \r
180         /* The buffer used to pass received data from the Win32 thread that receives\r
181         via the WinPCAP library to the FreeRTOS task. */\r
182         if( xRecvBuffer == NULL)\r
183         {\r
184                 xRecvBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) + xRECV_BUFFER_SIZE + 1 );\r
185                 configASSERT( xRecvBuffer );\r
186                 memset( xRecvBuffer, '\0', sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) );\r
187                 xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1;\r
188         }\r
189 }\r
190 /*-----------------------------------------------------------*/\r
191 \r
192 BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend )\r
193 {\r
194 size_t xSpace;\r
195 \r
196         iptraceNETWORK_INTERFACE_TRANSMIT();\r
197         configASSERT( xIsCallingFromIPTask() == pdTRUE );\r
198 \r
199         /* Both the length of the data being sent and the actual data being sent\r
200         are placed in the thread safe buffer used to pass data between the FreeRTOS\r
201         tasks and the Win32 thread that sends data via the WinPCAP library.  Drop\r
202         the packet if there is insufficient space in the buffer to hold both. */\r
203         xSpace = uxStreamBufferGetSpace( xSendBuffer );\r
204 \r
205         if( ( pxNetworkBuffer->xDataLength <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&\r
206                 ( xSpace >= ( pxNetworkBuffer->xDataLength + sizeof( pxNetworkBuffer->xDataLength ) ) ) )\r
207         {\r
208                 /* First write in the length of the data, then write in the data\r
209                 itself. */\r
210                 uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) &( pxNetworkBuffer->xDataLength ), sizeof( pxNetworkBuffer->xDataLength ) );\r
211                 uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );\r
212         }\r
213         else\r
214         {\r
215                 FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: send buffers full to store %lu\n", pxNetworkBuffer->xDataLength ) );\r
216         }\r
217 \r
218         /* Kick the Tx task in either case in case it doesn't know the buffer is\r
219         full. */\r
220         SetEvent( pvSendEvent );\r
221 \r
222         /* The buffer has been sent so can be released. */\r
223         if( bReleaseAfterSend != pdFALSE )\r
224         {\r
225                 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
226         }\r
227 \r
228         return pdPASS;\r
229 }\r
230 /*-----------------------------------------------------------*/\r
231 \r
232 static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )\r
233 {\r
234 pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;\r
235 int32_t lInterfaceNumber = 1;\r
236 char cBuffer[ 512 ];\r
237 static BaseType_t xInvalidInterfaceDetected = pdFALSE;\r
238 \r
239         if( xInvalidInterfaceDetected == pdFALSE )\r
240         {\r
241                 if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )\r
242                 {\r
243                         printf( "Could not obtain a list of network interfaces\n%s\n", cErrorBuffer );\r
244                         pxAllNetworkInterfaces = NULL;\r
245                 }\r
246                 else\r
247                 {\r
248                         printf( "\r\n\r\nThe following network interfaces are available:\r\n\r\n" );\r
249                 }\r
250 \r
251                 if( pxAllNetworkInterfaces != NULL )\r
252                 {\r
253                         /* Print out the list of network interfaces.  The first in the list\r
254                         is interface '1', not interface '0'. */\r
255                         for( xInterface = pxAllNetworkInterfaces; xInterface != NULL; xInterface = xInterface->next )\r
256                         {\r
257                                 /* The descriptions of the devices can be full of spaces, clean them\r
258                                 a little.  printf() can only be used here because the network is not\r
259                                 up yet - so no other network tasks will be running. */\r
260                                 printf( "Interface %d - %s\n", lInterfaceNumber, prvRemoveSpaces( cBuffer, sizeof( cBuffer ), xInterface->name ) );\r
261                                 printf( "              (%s)\n", prvRemoveSpaces(cBuffer, sizeof( cBuffer ), xInterface->description ? xInterface->description : "No description" ) );\r
262                                 printf( "\n" );\r
263                                 lInterfaceNumber++;\r
264                         }\r
265                 }\r
266 \r
267                 if( lInterfaceNumber == 1 )\r
268                 {\r
269                         /* The interface number was never incremented, so the above for() loop\r
270                         did not execute meaning no interfaces were found. */\r
271                         printf( " \nNo network interfaces were found.\n" );\r
272                         pxAllNetworkInterfaces = NULL;\r
273                 }\r
274 \r
275                 printf( "\r\nThe interface that will be opened is set by " );\r
276                 printf( "\"configNETWORK_INTERFACE_TO_USE\", which\r\nshould be defined in FreeRTOSConfig.h\r\n" );\r
277 \r
278                 if( ( xConfigNextworkInterfaceToUse < 1L ) || ( xConfigNextworkInterfaceToUse >= lInterfaceNumber ) )\r
279                 {\r
280                         printf( "\r\nERROR:  configNETWORK_INTERFACE_TO_USE is set to %d, which is an invalid value.\r\n", xConfigNextworkInterfaceToUse );\r
281                         printf( "Please set configNETWORK_INTERFACE_TO_USE to one of the interface numbers listed above,\r\n" );\r
282                         printf( "then re-compile and re-start the application.  Only Ethernet (as opposed to WiFi)\r\n" );\r
283                         printf( "interfaces are supported.\r\n\r\nHALTING\r\n\r\n\r\n" );\r
284                         xInvalidInterfaceDetected = pdTRUE;\r
285 \r
286                         if( pxAllNetworkInterfaces != NULL )\r
287                         {\r
288                                 /* Free the device list, as no devices are going to be opened. */\r
289                                 pcap_freealldevs( pxAllNetworkInterfaces );\r
290                                 pxAllNetworkInterfaces = NULL;\r
291                         }\r
292                 }\r
293                 else\r
294                 {\r
295                         printf( "Attempting to open interface number %d.\n", xConfigNextworkInterfaceToUse );\r
296                 }\r
297         }\r
298 \r
299         return pxAllNetworkInterfaces;\r
300 }\r
301 /*-----------------------------------------------------------*/\r
302 \r
303 static void prvOpenInterface( const char *pucName )\r
304 {\r
305 static char pucInterfaceName[ 256 ];\r
306 \r
307         if( pucName != NULL )\r
308         {\r
309                 strncpy( pucInterfaceName, pucName, sizeof( pucInterfaceName ) );\r
310         }\r
311 \r
312         pxOpenedInterfaceHandle = pcap_open(    pucInterfaceName,               /* The name of the selected interface. */\r
313                                                                                         ipTOTAL_ETHERNET_FRAME_SIZE, /* The size of the packet to capture. */\r
314                                                                                         PCAP_OPENFLAG_PROMISCUOUS,      /* Open in promiscuous mode as the MAC and\r
315                                                                                                                                                 IP address is going to be "simulated", and\r
316                                                                                                                                                 not be the real MAC and IP address.  This allows\r
317                                                                                                                                                 traffic to the simulated IP address to be routed\r
318                                                                                                                                                 to uIP, and traffic to the real IP address to be\r
319                                                                                                                                                 routed to the Windows TCP/IP stack. */\r
320                                                                                         100,\r
321                                                                                         NULL,                                   /* No authentication is required as this is\r
322                                                                                                                                                 not a remote capture session. */\r
323                                                                                         cErrorBuffer\r
324                                                                            );\r
325 \r
326         if ( pxOpenedInterfaceHandle == NULL )\r
327         {\r
328                 printf( "\n%s is not supported by WinPcap and cannot be opened\n", pucInterfaceName );\r
329         }\r
330         else\r
331         {\r
332                 /* Configure the capture filter to allow blocking reads, and to filter\r
333                 out packets that are not of interest to this demo. */\r
334                 prvConfigureCaptureBehaviour();\r
335         }\r
336 }\r
337 /*-----------------------------------------------------------*/\r
338 \r
339 static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )\r
340 {\r
341 pcap_if_t *xInterface;\r
342 int32_t x;\r
343 \r
344         /* Walk the list of devices until the selected device is located. */\r
345         xInterface = pxAllNetworkInterfaces;\r
346         for( x = 0L; x < ( xConfigNextworkInterfaceToUse - 1L ); x++ )\r
347         {\r
348                 xInterface = xInterface->next;\r
349         }\r
350 \r
351         /* Open the selected interface. */\r
352         prvOpenInterface( xInterface->name );\r
353 \r
354         /* The device list is no longer required. */\r
355         pcap_freealldevs( pxAllNetworkInterfaces );\r
356 }\r
357 /*-----------------------------------------------------------*/\r
358 \r
359 static void prvConfigureCaptureBehaviour( void )\r
360 {\r
361 struct bpf_program xFilterCode;\r
362 uint32_t ulNetMask;\r
363 \r
364         /* Set up a filter so only the packets of interest are passed to the IP\r
365         stack.  cErrorBuffer is used for convenience to create the string.  Don't\r
366         confuse this with an error message. */\r
367         sprintf( cErrorBuffer, "broadcast or multicast or ether host %x:%x:%x:%x:%x:%x",\r
368                 ucMACAddress[0], ucMACAddress[1], ucMACAddress[2], ucMACAddress[3], ucMACAddress[4], ucMACAddress[5] );\r
369 \r
370         ulNetMask = ( configNET_MASK3 << 24UL ) | ( configNET_MASK2 << 16UL ) | ( configNET_MASK1 << 8L ) | configNET_MASK0;\r
371 \r
372         if( pcap_compile( pxOpenedInterfaceHandle, &xFilterCode, cErrorBuffer, 1, ulNetMask ) < 0 )\r
373         {\r
374                 printf( "\nThe packet filter string is invalid\n" );\r
375         }\r
376         else\r
377         {\r
378                 if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )\r
379                 {\r
380                         printf( "\nAn error occurred setting the packet filter.\n" );\r
381                 }\r
382         }\r
383 \r
384         /* Create the buffers used to pass packets between the FreeRTOS simulator\r
385         and the Win32 threads that are handling WinPCAP. */\r
386         prvCreateThreadSafeBuffers();\r
387 \r
388         if( pvSendEvent == NULL )\r
389         {\r
390                 /* Create event used to signal the Win32 WinPCAP Tx thread. */\r
391                 pvSendEvent = CreateEvent( NULL, FALSE, TRUE, NULL );\r
392 \r
393                 /* Create the Win32 thread that handles WinPCAP Rx. */\r
394                 vWinPcapRecvThreadHandle = CreateThread(\r
395                         NULL,   /* Pointer to thread security attributes. */\r
396                         0,              /* Initial thread stack size, in bytes. */\r
397                         prvWinPcapRecvThread,   /* Pointer to thread function. */\r
398                         NULL,   /* Argument for new thread. */\r
399                         0,              /* Creation flags. */\r
400                         NULL );\r
401 \r
402                 /* Use the cores that are not used by the FreeRTOS tasks. */\r
403                 SetThreadAffinityMask( vWinPcapRecvThreadHandle, ~0x01u );\r
404 \r
405                 /* Create the Win32 thread that handlers WinPCAP Tx. */\r
406                 vWinPcapSendThreadHandle = CreateThread(\r
407                         NULL,   /* Pointer to thread security attributes. */\r
408                         0,              /* initial thread stack size, in bytes. */\r
409                         prvWinPcapSendThread,   /* Pointer to thread function. */\r
410                         NULL,   /* Argument for new thread. */\r
411                         0,              /* Creation flags. */\r
412                         NULL );\r
413 \r
414                 /* Use the cores that are not used by the FreeRTOS tasks. */\r
415                 SetThreadAffinityMask( vWinPcapSendThreadHandle, ~0x01u );\r
416 \r
417                 /* Create a task that simulates an interrupt in a real system.  This will\r
418                 block waiting for packets, then send a message to the IP task when data\r
419                 is available. */\r
420                 xTaskCreate( prvInterruptSimulatorTask, "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, configMAC_ISR_SIMULATOR_PRIORITY, NULL );\r
421         }\r
422 }\r
423 /*-----------------------------------------------------------*/\r
424 \r
425 /* WinPCAP function. */\r
426 void pcap_callback( u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data )\r
427 {\r
428         (void)user;\r
429 \r
430         /* THIS IS CALLED FROM A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS\r
431         OR TO PRINT OUT MESSAGES HERE. */\r
432 \r
433         /* Pass data to the FreeRTOS simulator on a thread safe circular buffer. */\r
434         if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&\r
435                 ( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) )\r
436         {\r
437                 uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_header, sizeof( *pkt_header ) );\r
438                 uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen );\r
439         }\r
440 }\r
441 /*-----------------------------------------------------------*/\r
442 \r
443 DWORD WINAPI prvWinPcapRecvThread ( void *pvParam )\r
444 {\r
445         ( void ) pvParam;\r
446 \r
447         /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT\r
448         OUT MESSAGES HERE. */\r
449 \r
450         for( ;; )\r
451         {\r
452                 pcap_dispatch( pxOpenedInterfaceHandle, 1, pcap_callback, ( u_char * ) "mydata" );\r
453         }\r
454 }\r
455 /*-----------------------------------------------------------*/\r
456 \r
457 DWORD WINAPI prvWinPcapSendThread( void *pvParam )\r
458 {\r
459 size_t xLength;\r
460 uint8_t ucBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];\r
461 static char cErrorMessage[ 1024 ];\r
462 const DWORD xMaxMSToWait = 1000;\r
463 \r
464         /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT\r
465         OUT MESSAGES HERE. */\r
466 \r
467         /* Remove compiler warnings about unused parameters. */\r
468         ( void ) pvParam;\r
469 \r
470         for( ;; )\r
471         {\r
472                 /* Wait until notified of something to send. */\r
473                 WaitForSingleObject( pvSendEvent, xMaxMSToWait );\r
474 \r
475                 /* Is there more than the length value stored in the circular buffer\r
476                 used to pass data from the FreeRTOS simulator into this Win32 thread? */\r
477                 while( uxStreamBufferGetSize( xSendBuffer ) > sizeof( xLength ) )\r
478                 {\r
479                         uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );\r
480                         uxStreamBufferGet( xSendBuffer, 0, ( uint8_t* ) ucBuffer, xLength, pdFALSE );\r
481                         if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength  ) != 0 )\r
482                         {\r
483                                 ulWinPCAPSendFailures++;\r
484                         }\r
485                 }\r
486         }\r
487 }\r
488 /*-----------------------------------------------------------*/\r
489 \r
490 static void prvInterruptSimulatorTask( void *pvParameters )\r
491 {\r
492 struct pcap_pkthdr xHeader;\r
493 static struct pcap_pkthdr *pxHeader;\r
494 const uint8_t *pucPacketData;\r
495 uint8_t ucRecvBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];\r
496 NetworkBufferDescriptor_t *pxNetworkBuffer;\r
497 IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
498 eFrameProcessingResult_t eResult;\r
499 \r
500         /* Remove compiler warnings about unused parameters. */\r
501         ( void ) pvParameters;\r
502 \r
503         for( ;; )\r
504         {\r
505                 /* Does the circular buffer used to pass data from the Win32 thread that\r
506                 handles WinPCAP Rx into the FreeRTOS simulator contain another packet? */\r
507                 if( uxStreamBufferGetSize( xRecvBuffer ) > sizeof( xHeader ) )\r
508                 {\r
509                         /* Get the next packet. */\r
510                         uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)&xHeader, sizeof( xHeader ), pdFALSE );\r
511                         uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)ucRecvBuffer, ( size_t ) xHeader.len, pdFALSE );\r
512                         pucPacketData = ucRecvBuffer;\r
513                         pxHeader = &xHeader;\r
514 \r
515                         iptraceNETWORK_INTERFACE_RECEIVE();\r
516 \r
517                         eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData );\r
518                         if( eResult == eProcessBuffer )\r
519                         {\r
520                                 /* Will the data fit into the frame buffer? */\r
521                                 if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE )\r
522                                 {\r
523                                         /* Obtain a buffer into which the data can be placed.  This\r
524                                         is only an interrupt simulator, not a real interrupt, so it\r
525                                         is ok to call the task level function here, but note that\r
526                                         some buffer implementations cannot be called from a real\r
527                                         interrupt. */\r
528                                         pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );\r
529 \r
530                                         if( pxNetworkBuffer != NULL )\r
531                                         {\r
532                                                 memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len );\r
533                                                 pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len;\r
534 \r
535                                                 #if( niDISRUPT_PACKETS == 1 )\r
536                                                 {\r
537                                                         pxNetworkBuffer = vRxFaultInjection( pxNetworkBuffer, pucPacketData );\r
538                                                 }\r
539                                                 #endif /* niDISRUPT_PACKETS */\r
540 \r
541                                                 if( pxNetworkBuffer != NULL )\r
542                                                 {\r
543                                                         xRxEvent.pvData = ( void * ) pxNetworkBuffer;\r
544 \r
545                                                         /* Data was received and stored.  Send a message to\r
546                                                         the IP task to let it know. */\r
547                                                         if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
548                                                         {\r
549                                                                 /* The buffer could not be sent to the stack so\r
550                                                                 must be released again.  This is only an\r
551                                                                 interrupt simulator, not a real interrupt, so it\r
552                                                                 is ok to use the task level function here, but\r
553                                                                 note no all buffer implementations will allow\r
554                                                                 this function to be executed from a real\r
555                                                                 interrupt. */\r
556                                                                 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
557                                                                 iptraceETHERNET_RX_EVENT_LOST();\r
558                                                         }\r
559                                                 }\r
560                                                 else\r
561                                                 {\r
562                                                         /* The packet was already released or stored inside\r
563                                                         vRxFaultInjection().  Don't release it here. */\r
564                                                 }\r
565                                         }\r
566                                         else\r
567                                         {\r
568                                                 iptraceETHERNET_RX_EVENT_LOST();\r
569                                         }\r
570                                 }\r
571                                 else\r
572                                 {\r
573                                         /* Log that a packet was dropped because it would have\r
574                                         overflowed the buffer, but there may be more buffers to\r
575                                         process. */\r
576                                 }\r
577                         }\r
578                 }\r
579                 else\r
580                 {\r
581                         /* There is no real way of simulating an interrupt.  Make sure\r
582                         other tasks can run. */\r
583                         vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY );\r
584                 }\r
585         }\r
586 }\r
587 /*-----------------------------------------------------------*/\r
588 \r
589 static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage )\r
590 {\r
591         char *pcTarget = pcBuffer;\r
592 \r
593         /* Utility function used to formap messages being printed only. */\r
594         while( ( *pcMessage != 0 ) && ( pcTarget < ( pcBuffer + aBuflen - 1 ) ) )\r
595         {\r
596                 *( pcTarget++ ) = *pcMessage;\r
597 \r
598                 if( isspace( *pcMessage ) != pdFALSE )\r
599                 {\r
600                         while( isspace( *pcMessage ) != pdFALSE )\r
601                         {\r
602                                 pcMessage++;\r
603                         }\r
604                 }\r
605                 else\r
606                 {\r
607                         pcMessage++;\r
608                 }\r
609         }\r
610 \r
611         *pcTarget = '\0';\r
612 \r
613         return pcBuffer;\r
614 }\r
615 \r