- For reading sin_port, ntohs() must be used. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: lpleahy Reviewed-by: Laszlo Ersek <lersek@redhat.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14127 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1288 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1288 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Data source for network testing.
 | |
| 
 | |
|   Copyright (c) 2011-2012, Intel Corporation
 | |
|   All rights reserved. This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <errno.h>
 | |
| #include <Uefi.h>
 | |
| 
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/PcdLib.h>
 | |
| #include <Library/UefiBootServicesTableLib.h>
 | |
| #include <Library/UefiLib.h>
 | |
| 
 | |
| #include <netinet/in.h>
 | |
| 
 | |
| #include <sys/EfiSysCall.h>
 | |
| #include <sys/poll.h>
 | |
| #include <sys/socket.h>
 | |
| 
 | |
| 
 | |
| #define DATA_SAMPLE_SHIFT           5       ///<  Shift for number of samples
 | |
| #define MAX_CONNECTIONS       ( 1 + 16 )    ///<  Maximum number of client connections
 | |
| #define RANGE_SWITCH        ( 1024 * 1024 ) ///<  Switch display ranges
 | |
| #define DATA_RATE_UPDATE_SHIFT      2       ///<  2n seconds between updates
 | |
| #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT )  ///<  2n samples in average
 | |
| #define DATA_SAMPLES        ( 1 << DATA_SAMPLE_SHIFT )      ///<  Number of samples
 | |
| 
 | |
| #define TPL_DATASINK        TPL_CALLBACK  ///<  Synchronization TPL
 | |
| 
 | |
| #define PACKET_SIZE                 1448  ///<  Size of data packets
 | |
| #define DATA_BUFFER_SIZE    (( 65536 / PACKET_SIZE ) * PACKET_SIZE )  ///<  Buffer size in bytes
 | |
| 
 | |
| typedef struct _DT_PORT {
 | |
|   UINT64 BytesTotal;
 | |
|   struct sockaddr_in6 IpAddress;
 | |
|   UINT32 In;
 | |
|   UINT32 Samples;
 | |
|   UINT64 BytesReceived[ DATA_SAMPLES ];
 | |
| } DT_PORT;
 | |
| 
 | |
| volatile BOOLEAN bTick;
 | |
| BOOLEAN bTimerRunning;
 | |
| struct sockaddr_in6 LocalAddress;
 | |
| EFI_EVENT pTimer;
 | |
| int ListenSocket;
 | |
| UINT8 Buffer[ DATA_BUFFER_SIZE ];
 | |
| struct pollfd PollFd[ MAX_CONNECTIONS ];
 | |
| DT_PORT Port[ MAX_CONNECTIONS ];
 | |
| nfds_t MaxPort;
 | |
| 
 | |
| 
 | |
| //
 | |
| //  Forward routine declarations
 | |
| //
 | |
| EFI_STATUS TimerStart ( UINTN Milliseconds );
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Check for control C entered at console
 | |
| 
 | |
|   @retval  EFI_SUCCESS  Control C not entered
 | |
|   @retval  EFI_ABORTED  Control C entered
 | |
| **/
 | |
| EFI_STATUS
 | |
| ControlCCheck (
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   //
 | |
|   //  Assume no user intervention
 | |
|   //
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   //
 | |
|   //  Display user stop request
 | |
|   //
 | |
|   if ( EFI_ERROR ( Status )) {
 | |
|     DEBUG (( DEBUG_INFO,
 | |
|               "User stop request!\r\n" ));
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the check status
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Accept a socket connection
 | |
| 
 | |
|   @retval  EFI_SUCCESS      The application is running normally
 | |
|   @retval  EFI_NOT_STARTED  Error with the listen socket
 | |
|   @retval  Other            The user stopped the application
 | |
| **/
 | |
| EFI_STATUS
 | |
| SocketAccept (
 | |
|   )
 | |
| {
 | |
|   INT32 SocketStatus;
 | |
|   EFI_STATUS Status;
 | |
|   INTN Index;
 | |
| 
 | |
|   //
 | |
|   //  Assume failure
 | |
|   //
 | |
|   Status = EFI_DEVICE_ERROR;
 | |
| 
 | |
|   //
 | |
|   //  Bind to the local address
 | |
|   //
 | |
|   SocketStatus = bind ( ListenSocket,
 | |
|                         (struct sockaddr *) &LocalAddress,
 | |
|                         LocalAddress.sin6_len );
 | |
|   if ( 0 == SocketStatus ) {
 | |
|     //
 | |
|     //  Start listening on the local socket
 | |
|     //
 | |
|     SocketStatus = listen ( ListenSocket, 5 );
 | |
|     if ( 0 == SocketStatus ) {
 | |
|       //
 | |
|       //  Local socket in the listen state
 | |
|       //
 | |
|       Status = EFI_SUCCESS;
 | |
| 
 | |
|       //
 | |
|       //  Allocate a port
 | |
|       //
 | |
|       Index = MaxPort++;
 | |
|       PollFd[ Index ].fd = ListenSocket;
 | |
|       PollFd[ Index ].events = POLLRDNORM | POLLHUP;
 | |
|       PollFd[ Index ].revents = 0;
 | |
|       ZeroMem ( &Port[ Index ], sizeof ( Port[ Index ]));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the operation status
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Close the socket
 | |
| 
 | |
|   @retval  EFI_SUCCESS  The application is running normally
 | |
|   @retval  Other        The user stopped the application
 | |
| **/
 | |
| EFI_STATUS
 | |
| SocketClose (
 | |
|   )
 | |
| {
 | |
|   INT32 CloseStatus;
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   //
 | |
|   //  Determine if the socket is open
 | |
|   //
 | |
|   Status = EFI_DEVICE_ERROR;
 | |
|   if ( -1 != ListenSocket ) {
 | |
|     //
 | |
|     //  Attempt to close the socket
 | |
|     //
 | |
|     CloseStatus = close ( ListenSocket );
 | |
|     if ( 0 == CloseStatus ) {
 | |
|       DEBUG (( DEBUG_INFO,
 | |
|                 "0x%08x: Socket closed\r\n",
 | |
|                 ListenSocket ));
 | |
|       ListenSocket = -1;
 | |
|       Status = EFI_SUCCESS;
 | |
|     }
 | |
|     else {
 | |
|       DEBUG (( DEBUG_ERROR,
 | |
|                 "ERROR: Failed to close socket, errno: %d\r\n",
 | |
|                 errno ));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the operation status
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Create the socket
 | |
| 
 | |
|   @param [in] Family    Network family, AF_INET or AF_INET6
 | |
| 
 | |
|   @retval  EFI_SUCCESS  The application is running normally
 | |
|   @retval  Other        The user stopped the application
 | |
| **/
 | |
| EFI_STATUS
 | |
| SocketNew (
 | |
|   sa_family_t Family
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   //
 | |
|   //  Get the port number
 | |
|   //
 | |
|   ZeroMem ( &LocalAddress, sizeof ( LocalAddress ));
 | |
|   LocalAddress.sin6_len = sizeof ( LocalAddress );
 | |
|   LocalAddress.sin6_family = Family;
 | |
|   LocalAddress.sin6_port = htons ( PcdGet16 ( DataSource_Port ));
 | |
|   
 | |
|   //
 | |
|   //  Loop creating the socket
 | |
|   //
 | |
|   DEBUG (( DEBUG_INFO,
 | |
|             "Creating the socket\r\n" ));
 | |
| 
 | |
|   //
 | |
|   //  Check for user stop request
 | |
|   //
 | |
|   Status = ControlCCheck ( );
 | |
|   if ( !EFI_ERROR ( Status )) {
 | |
|     //
 | |
|     //  Attempt to create the socket
 | |
|     //
 | |
|     ListenSocket = socket ( LocalAddress.sin6_family,
 | |
|                             SOCK_STREAM,
 | |
|                             IPPROTO_TCP );
 | |
|     if ( -1 != ListenSocket ) {
 | |
|       DEBUG (( DEBUG_INFO,
 | |
|                 "0x%08x: Socket created\r\n",
 | |
|                 ListenSocket ));
 | |
|     }
 | |
|     else {
 | |
|       Status = EFI_NOT_STARTED;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the operation status
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Poll the socket for more work
 | |
| 
 | |
|   @retval  EFI_SUCCESS      The application is running normally
 | |
|   @retval  EFI_NOT_STARTED  Listen socket error
 | |
|   @retval  Other            The user stopped the application
 | |
| **/
 | |
| EFI_STATUS
 | |
| SocketPoll (
 | |
|   )
 | |
| {
 | |
|   BOOLEAN bRemoveSocket;
 | |
|   BOOLEAN bListenError;
 | |
|   size_t BytesReceived;
 | |
|   int CloseStatus;
 | |
|   nfds_t Entry;
 | |
|   INTN EntryPrevious;
 | |
|   int FdCount;
 | |
|   nfds_t Index;
 | |
|   socklen_t LengthInBytes;
 | |
|   struct sockaddr_in * pPortIpAddress4;
 | |
|   struct sockaddr_in6 * pPortIpAddress6;
 | |
|   struct sockaddr_in * pRemoteAddress4;
 | |
|   struct sockaddr_in6 * pRemoteAddress6;
 | |
|   struct sockaddr_in6 RemoteAddress;
 | |
|   int Socket;
 | |
|   EFI_STATUS Status;
 | |
|   EFI_TPL TplPrevious;
 | |
| 
 | |
|   //
 | |
|   //  Check for control-C
 | |
|   //
 | |
|   pRemoteAddress4 = (struct sockaddr_in *)&RemoteAddress;
 | |
|   pRemoteAddress6 = (struct sockaddr_in6 *)&RemoteAddress;
 | |
|   bListenError = FALSE;
 | |
|   Status = ControlCCheck ( );
 | |
|   if ( !EFI_ERROR ( Status )) {
 | |
|     //
 | |
|     //  Poll the sockets
 | |
|     //
 | |
|     FdCount = poll ( &PollFd[0],
 | |
|                      MaxPort,
 | |
|                      0 );
 | |
|     if ( -1 == FdCount ) {
 | |
|       //
 | |
|       //  Poll error
 | |
|       //
 | |
|       DEBUG (( DEBUG_ERROR,
 | |
|                 "ERROR - Poll error, errno: %d\r\n",
 | |
|                 errno ));
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|     }
 | |
|     else {
 | |
|       //
 | |
|       //  Process the poll output
 | |
|       //
 | |
|       Index = 0;
 | |
|       while ( FdCount ) {
 | |
|         bRemoveSocket = FALSE;
 | |
| 
 | |
|         //
 | |
|         //  Account for this descriptor
 | |
|         //
 | |
|         pPortIpAddress4 = (struct sockaddr_in *)&Port[ Index ].IpAddress;
 | |
|         pPortIpAddress6 = (struct sockaddr_in6 *)&Port[ Index ].IpAddress;
 | |
|         if ( 0 != PollFd[ Index ].revents ) {
 | |
|           FdCount -= 1;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         //  Check for a broken connection
 | |
|         //
 | |
|         if ( 0 != ( PollFd[ Index ].revents & POLLHUP )) {
 | |
|           bRemoveSocket = TRUE;
 | |
|           if ( ListenSocket == PollFd[ Index ].fd ) {
 | |
|             bListenError = TRUE;
 | |
|             DEBUG (( DEBUG_ERROR,
 | |
|                       "ERROR - Network closed on listen socket, errno: %d\r\n",
 | |
|                       errno ));
 | |
|           }
 | |
|           else {
 | |
|             if ( AF_INET == pPortIpAddress4->sin_family ) {
 | |
|               DEBUG (( DEBUG_ERROR,
 | |
|                         "ERROR - Network closed on socket %d.%d.%d.%d:%d, errno: %d\r\n",
 | |
|                         pPortIpAddress4->sin_addr.s_addr & 0xff,
 | |
|                         ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,
 | |
|                         ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,
 | |
|                         ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,
 | |
|                         ntohs ( pPortIpAddress4->sin_port ),
 | |
|                         errno ));
 | |
|             }
 | |
|             else {
 | |
|               DEBUG (( DEBUG_ERROR,
 | |
|                         "ERROR - Network closed on socket [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d, errno: %d\r\n",
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
 | |
|                         pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
 | |
|                         ntohs ( pPortIpAddress6->sin6_port ),
 | |
|                         errno ));
 | |
|             }
 | |
| 
 | |
|             //
 | |
|             //  Close the socket
 | |
|             //
 | |
|             CloseStatus = close ( PollFd[ Index ].fd );
 | |
|             if ( 0 == CloseStatus ) {
 | |
|               bRemoveSocket = TRUE;
 | |
|               if ( AF_INET == pPortIpAddress4->sin_family ) {
 | |
|                 DEBUG (( DEBUG_INFO,
 | |
|                           "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
 | |
|                           PollFd[ Index ].fd,
 | |
|                           pPortIpAddress4->sin_addr.s_addr & 0xff,
 | |
|                           ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,
 | |
|                           ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,
 | |
|                           ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,
 | |
|                           ntohs ( pPortIpAddress4->sin_port )));
 | |
|               }
 | |
|               else {
 | |
|                 DEBUG (( DEBUG_INFO,
 | |
|                           "0x%08x: Socket closed for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
 | |
|                           PollFd[ Index ].fd,
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
 | |
|                           ntohs ( pPortIpAddress6->sin6_port )));
 | |
|               }
 | |
|             }
 | |
|             else {
 | |
|               if ( AF_INET == pPortIpAddress4->sin_family ) {
 | |
|                 DEBUG (( DEBUG_ERROR,
 | |
|                           "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",
 | |
|                           PollFd[ Index ].fd,
 | |
|                           pPortIpAddress4->sin_addr.s_addr & 0xff,
 | |
|                           ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,
 | |
|                           ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,
 | |
|                           ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,
 | |
|                           ntohs ( pPortIpAddress4->sin_port ),
 | |
|                           errno ));
 | |
|               }
 | |
|               else {
 | |
|                 DEBUG (( DEBUG_ERROR,
 | |
|                           "ERROR - Failed to close socket 0x%08x for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d, errno: %d\r\n",
 | |
|                           PollFd[ Index ].fd,
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
 | |
|                           ntohs ( pPortIpAddress6->sin6_port ),
 | |
|                           errno ));
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         
 | |
|         //
 | |
|         //  Check for a connection or read data
 | |
|         //
 | |
|         if ( 0 != ( PollFd[ Index ].revents & POLLRDNORM )) {
 | |
|           //
 | |
|           //  Check for a connection
 | |
|           //
 | |
|           if ( ListenSocket == PollFd[ Index ].fd ) {
 | |
|             //
 | |
|             //  Another client connection was received
 | |
|             //
 | |
|             LengthInBytes = sizeof ( RemoteAddress );
 | |
|             Socket = accept ( ListenSocket,
 | |
|                               (struct sockaddr *) &RemoteAddress,
 | |
|                               &LengthInBytes );
 | |
|             if ( -1 == Socket ) {
 | |
|               //
 | |
|               //  Listen socket error
 | |
|               //
 | |
|               bListenError = TRUE;
 | |
|               bRemoveSocket = TRUE;
 | |
|               DEBUG (( DEBUG_ERROR,
 | |
|                         "ERROR - Listen socket failure, errno: %d\r\n",
 | |
|                         errno ));
 | |
|             }
 | |
|             else {
 | |
|               //
 | |
|               //  Determine if there is room for this connection
 | |
|               //
 | |
|               if (( MAX_CONNECTIONS <= MaxPort )
 | |
|                 || ((( MAX_CONNECTIONS - 1 ) == MaxPort ) && ( -1 == ListenSocket ))) {
 | |
|                 //
 | |
|                 //  Display the connection
 | |
|                 //
 | |
|                 if ( AF_INET == pRemoteAddress4->sin_family ) {
 | |
|                   Print ( L"Rejecting connection to remote system %d.%d.%d.%d:%d\r\n",
 | |
|                           pRemoteAddress4->sin_addr.s_addr & 0xff,
 | |
|                           ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,
 | |
|                           ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,
 | |
|                           ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,
 | |
|                           ntohs ( pRemoteAddress4->sin_port ));
 | |
|                 }
 | |
|                 else {
 | |
|                   Print ( L"Rejecting connection to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
 | |
|                           ntohs ( pRemoteAddress6->sin6_port ));
 | |
|                 }
 | |
| 
 | |
|                 //
 | |
|                 //  No room for this connection
 | |
|                 //  Close the connection
 | |
|                 //
 | |
|                 CloseStatus = close ( Socket );
 | |
|                 if ( 0 == CloseStatus ) {
 | |
|                   bRemoveSocket = TRUE;
 | |
|                   if ( AF_INET == pRemoteAddress4->sin_family ) {
 | |
|                     DEBUG (( DEBUG_INFO,
 | |
|                               "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
 | |
|                               PollFd[ Index ].fd,
 | |
|                               pRemoteAddress4->sin_addr.s_addr & 0xff,
 | |
|                               ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,
 | |
|                               ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,
 | |
|                               ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,
 | |
|                               ntohs ( pRemoteAddress4->sin_port )));
 | |
|                   }
 | |
|                   else {
 | |
|                     DEBUG (( DEBUG_INFO,
 | |
|                               "0x%08x: Socket closed for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
 | |
|                               PollFd[ Index ].fd,
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
 | |
|                               pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
 | |
|                               ntohs ( pRemoteAddress6->sin6_port )));
 | |
|                   }
 | |
|                 }
 | |
|                 else {
 | |
|                   DEBUG (( DEBUG_ERROR,
 | |
|                             "ERROR - Failed to close socket 0x%08x, errno: %d\r\n",
 | |
|                             PollFd[ Index ].fd,
 | |
|                             errno ));
 | |
|                 }
 | |
| 
 | |
|                 //
 | |
|                 //  Keep the application running
 | |
|                 //  No issue with the listen socket
 | |
|                 //
 | |
|                 Status = EFI_SUCCESS;
 | |
|               }
 | |
|               else {
 | |
|                 //
 | |
|                 //  Display the connection
 | |
|                 //
 | |
|                 if ( AF_INET == pRemoteAddress4->sin_family ) {
 | |
|                   Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",
 | |
|                           pRemoteAddress4->sin_addr.s_addr & 0xff,
 | |
|                           ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff,
 | |
|                           ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff,
 | |
|                           ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff,
 | |
|                           ntohs ( pRemoteAddress4->sin_port ));
 | |
|                 }
 | |
|                 else {
 | |
|                   Print ( L"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
 | |
|                           pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
 | |
|                           ntohs ( pRemoteAddress6->sin6_port ));
 | |
|                 }
 | |
| 
 | |
|                 //
 | |
|                 //  Allocate the client connection
 | |
|                 //
 | |
|                 Index = MaxPort++;
 | |
|                 ZeroMem ( &Port[ Index ], sizeof ( Port[ Index ]));
 | |
|                 CopyMem ( pPortIpAddress6, pRemoteAddress6, sizeof ( *pRemoteAddress6 ));
 | |
|                 PollFd[ Index ].fd = Socket;
 | |
|                 PollFd[ Index ].events = POLLRDNORM | POLLHUP;
 | |
|                 PollFd[ Index ].revents = 0;
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|           else {
 | |
|             //
 | |
|             //  Data received
 | |
|             //
 | |
|             BytesReceived = read ( PollFd[ Index ].fd,
 | |
|                                    &Buffer,
 | |
|                                    sizeof ( Buffer ));
 | |
|             if ( 0 < BytesReceived ) {
 | |
|               //
 | |
|               //  Display the amount of data received
 | |
|               //
 | |
|               if ( AF_INET == pPortIpAddress4->sin_family ) {
 | |
|                 DEBUG (( DEBUG_INFO,
 | |
|                           "0x%08x: Socket received 0x%08x bytes from %d.%d.%d.%d:%d\r\n",
 | |
|                           PollFd[ Index ].fd,
 | |
|                           BytesReceived,
 | |
|                           pPortIpAddress4->sin_addr.s_addr & 0xff,
 | |
|                           ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,
 | |
|                           ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,
 | |
|                           ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,
 | |
|                           ntohs ( pPortIpAddress4->sin_port )));
 | |
|               }
 | |
|               else {
 | |
|                 DEBUG (( DEBUG_INFO,
 | |
|                           "0x%08x: Socket received 0x%08x bytes from [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
 | |
|                           PollFd[ Index ].fd,
 | |
|                           BytesReceived,
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
 | |
|                           ntohs ( pPortIpAddress6->sin6_port )));
 | |
|               }
 | |
| 
 | |
|               //
 | |
|               //  Synchronize with the TimerCallback routine
 | |
|               //
 | |
|               TplPrevious = gBS->RaiseTPL ( TPL_DATASINK );
 | |
| 
 | |
|               //
 | |
|               //  Account for the data received
 | |
|               //
 | |
|               Port[ Index ].BytesTotal += BytesReceived;
 | |
| 
 | |
|               //
 | |
|               //  Release the synchronization with the TimerCallback routine
 | |
|               //
 | |
|               gBS->RestoreTPL ( TplPrevious );
 | |
|             }
 | |
|             else if ( -1 == BytesReceived ) {
 | |
|               //
 | |
|               //  Close the socket
 | |
|               //
 | |
|               if ( AF_INET == pPortIpAddress4->sin_family ) {
 | |
|                 DEBUG (( DEBUG_INFO,
 | |
|                           "ERROR - Receive failure for %d.%d.%d.%d:%d, errno: %d\r\n",
 | |
|                           pPortIpAddress4->sin_addr.s_addr & 0xff,
 | |
|                           ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,
 | |
|                           ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,
 | |
|                           ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,
 | |
|                           ntohs ( pPortIpAddress4->sin_port ),
 | |
|                           errno ));
 | |
|               }
 | |
|               else {
 | |
|                 DEBUG (( DEBUG_INFO,
 | |
|                           "ERROR - Receive failure for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d, errno: %d\r\n",
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
 | |
|                           pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
 | |
|                           ntohs ( pPortIpAddress6->sin6_port ),
 | |
|                           errno ));
 | |
|               }
 | |
|               CloseStatus = close ( PollFd[ Index ].fd );
 | |
|               if ( 0 == CloseStatus ) {
 | |
|                 bRemoveSocket = TRUE;
 | |
|                 if ( AF_INET == pPortIpAddress4->sin_family ) {
 | |
|                   DEBUG (( DEBUG_INFO,
 | |
|                             "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
 | |
|                             PollFd[ Index ].fd,
 | |
|                             pPortIpAddress4->sin_addr.s_addr & 0xff,
 | |
|                             ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,
 | |
|                             ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,
 | |
|                             ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,
 | |
|                             ntohs ( pPortIpAddress4->sin_port )));
 | |
|                 }
 | |
|                 else {
 | |
|                   DEBUG (( DEBUG_INFO,
 | |
|                             "0x%08x: Socket closed for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
 | |
|                             PollFd[ Index ].fd,
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
 | |
|                             ntohs ( pPortIpAddress6->sin6_port )));
 | |
|                 }
 | |
|               }
 | |
|               else {
 | |
|                 if ( AF_INET == pPortIpAddress4->sin_family ) {
 | |
|                   DEBUG (( DEBUG_ERROR,
 | |
|                             "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",
 | |
|                             PollFd[ Index ].fd,
 | |
|                             pPortIpAddress4->sin_addr.s_addr & 0xff,
 | |
|                             ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff,
 | |
|                             ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff,
 | |
|                             ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff,
 | |
|                             ntohs ( pPortIpAddress4->sin_port ),
 | |
|                             errno ));
 | |
|                 }
 | |
|                 else {
 | |
|                   DEBUG (( DEBUG_ERROR,
 | |
|                             "ERROR - Failed to close socket 0x%08x for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d, errno: %d\r\n",
 | |
|                             PollFd[ Index ].fd,
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ],
 | |
|                             pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ],
 | |
|                             ntohs ( pPortIpAddress6->sin6_port ),
 | |
|                             errno ));
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
| 
 | |
|             //
 | |
|             //  Keep the application running
 | |
|             //  No issue with the listen socket
 | |
|             //
 | |
|             Status = EFI_SUCCESS;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         //  Remove the socket if necessary
 | |
|         //
 | |
|         if ( bRemoveSocket ) {
 | |
|           DEBUG (( DEBUG_INFO,
 | |
|                     "0x%08x: Socket removed from polling\r\n",
 | |
|                     PollFd[ Index ].fd ));
 | |
|           MaxPort -= 1;
 | |
|           for ( Entry = Index + 1; MaxPort >= Entry; Entry++ ) {
 | |
|             EntryPrevious = Entry;
 | |
|             CopyMem ( &Port[ EntryPrevious ],
 | |
|                       &Port[ Entry ],
 | |
|                       sizeof ( Port[ Entry ]));
 | |
|             PollFd[ EntryPrevious ].events = PollFd[ Entry ].events;
 | |
|             PollFd[ EntryPrevious ].fd = PollFd[ Entry ].fd;
 | |
|             PollFd[ EntryPrevious ].revents = PollFd[ Entry ].revents;
 | |
|           }
 | |
|           PollFd[ MaxPort ].fd = -1;
 | |
|           Index -= 1;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         //  Account for this socket
 | |
|         //
 | |
|         Index += 1;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the listen failure if necessary
 | |
|   //
 | |
|   if (( !EFI_ERROR ( Status )) && bListenError ) {
 | |
|     Status = EFI_NOT_STARTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the poll status
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Handle the timer callback
 | |
| 
 | |
|   @param [in] Event     Event that caused this callback
 | |
|   @param [in] pContext  Context for this routine
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| TimerCallback (
 | |
|   IN EFI_EVENT Event,
 | |
|   IN VOID * pContext
 | |
|   )
 | |
| {
 | |
|   UINT32 Average;
 | |
|   UINT64 BitsPerSecond;
 | |
|   UINT64 BytesReceived;
 | |
|   UINT32 Count;
 | |
|   nfds_t Index;
 | |
|   UINT64 TotalBytes;
 | |
| 
 | |
|   //
 | |
|   //  Notify the other code of the timer tick
 | |
|   //
 | |
|   bTick = TRUE;
 | |
| 
 | |
|   //
 | |
|   //  Walk the list of ports
 | |
|   //
 | |
|   for ( Index = 0; MaxPort > Index; Index++ ) {
 | |
|     //
 | |
|     //  Determine if any data was received
 | |
|     //
 | |
|     BytesReceived = Port[ Index ].BytesTotal;
 | |
|     if (( ListenSocket != PollFd[ Index ].fd )
 | |
|       && ( 0 != BytesReceived )) {
 | |
|       //
 | |
|       //  Update the received data samples
 | |
|       //
 | |
|       Port[ Index ].BytesTotal = 0;
 | |
|       Port[ Index ].BytesReceived [ Port[ Index ].In ] = BytesReceived;
 | |
|       Port[ Index ].In += 1;
 | |
|       if ( DATA_SAMPLES <= Port[ Index ].In ) {
 | |
|         Port[ Index ].In = 0;
 | |
|       }
 | |
|       
 | |
|       //
 | |
|       //  Separate the samples
 | |
|       //
 | |
|       if ( DATA_SAMPLES == Port[ Index ].Samples ) {
 | |
|         Print ( L"---------- Stable average ----------\r\n" );
 | |
|       }
 | |
|       Port[ Index ].Samples += 1;
 | |
| 
 | |
|       //
 | |
|       //  Compute the data rate
 | |
|       //
 | |
|       TotalBytes = 0;
 | |
|       for ( Count = 0; DATA_SAMPLES > Count; Count++ )
 | |
|       {
 | |
|           TotalBytes += Port[ Index ].BytesReceived[ Count ];
 | |
|       }
 | |
|       Average = (UINT32)RShiftU64 ( TotalBytes, DATA_SAMPLE_SHIFT );
 | |
|       BitsPerSecond = Average * 8;
 | |
| 
 | |
|       //
 | |
|       //  Display the data rate
 | |
|       //
 | |
|       if (( RANGE_SWITCH >> 10 ) > Average ) {
 | |
|         Print ( L"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",
 | |
|                 Average,
 | |
|                 BitsPerSecond );
 | |
|       }
 | |
|       else {
 | |
|         BitsPerSecond /= 1000;
 | |
|         if ( RANGE_SWITCH > Average ) {
 | |
|           Print ( L"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",
 | |
|                   Average >> 10,
 | |
|                   (( Average & 0x3ff ) * 1000 ) >> 10,
 | |
|                   BitsPerSecond );
 | |
|         }
 | |
|         else {
 | |
|           BitsPerSecond /= 1000;
 | |
|           Average >>= 10;
 | |
|           if ( RANGE_SWITCH > Average ) {
 | |
|             Print ( L"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",
 | |
|                     Average >> 10,
 | |
|                     (( Average & 0x3ff ) * 1000 ) >> 10,
 | |
|                     BitsPerSecond );
 | |
|           }
 | |
|           else {
 | |
|             BitsPerSecond /= 1000;
 | |
|             Average >>= 10;
 | |
|             if ( RANGE_SWITCH > Average ) {
 | |
|               Print ( L"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",
 | |
|                       Average >> 10,
 | |
|                       (( Average & 0x3ff ) * 1000 ) >> 10,
 | |
|                       BitsPerSecond );
 | |
|             }
 | |
|             else {
 | |
|               BitsPerSecond /= 1000;
 | |
|               Average >>= 10;
 | |
|               if ( RANGE_SWITCH > Average ) {
 | |
|                 Print ( L"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",
 | |
|                         Average >> 10,
 | |
|                         (( Average & 0x3ff ) * 1000 ) >> 10,
 | |
|                         BitsPerSecond );
 | |
|               }
 | |
|               else {
 | |
|                 BitsPerSecond /= 1000;
 | |
|                 Average >>= 10;
 | |
|                 Print ( L"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",
 | |
|                         Average >> 10,
 | |
|                         (( Average & 0x3ff ) * 1000 ) >> 10,
 | |
|                         BitsPerSecond );
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Create the timer
 | |
| 
 | |
|   @retval  EFI_SUCCESS  The timer was successfully created
 | |
|   @retval  Other        Timer initialization failed
 | |
| **/
 | |
| EFI_STATUS
 | |
| TimerCreate (
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   //
 | |
|   //  Create the timer
 | |
|   //
 | |
|   Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL,
 | |
|                               TPL_DATASINK,
 | |
|                               TimerCallback,
 | |
|                               NULL,
 | |
|                               &pTimer );
 | |
|   if ( EFI_ERROR ( Status )) {
 | |
|     DEBUG (( DEBUG_ERROR,
 | |
|               "ERROR - Failed to allocate the timer event, Status: %r\r\n",
 | |
|               Status ));
 | |
|   }
 | |
|   else {
 | |
|     DEBUG (( DEBUG_INFO,
 | |
|               "0x%08x: Timer created\r\n",
 | |
|               pTimer ));
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the operation status
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Stop the timer
 | |
| 
 | |
|   @retval  EFI_SUCCESS  The timer was stopped successfully
 | |
|   @retval  Other        The timer failed to stop
 | |
| **/
 | |
| EFI_STATUS
 | |
| TimerStop (
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   //
 | |
|   //  Assume success
 | |
|   //
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   //
 | |
|   //  Determine if the timer is running
 | |
|   //
 | |
|   if ( bTimerRunning ) {
 | |
|     //
 | |
|     //  Stop the timer
 | |
|     //
 | |
|     Status = gBS->SetTimer ( pTimer,
 | |
|                              TimerCancel,
 | |
|                              0 );
 | |
|     if ( EFI_ERROR ( Status )) {
 | |
|       DEBUG (( DEBUG_ERROR,
 | |
|                 "ERROR - Failed to stop the timer, Status: %r\r\n",
 | |
|                 Status ));
 | |
|     }
 | |
|     else {
 | |
|       //
 | |
|       //  Timer timer is now stopped
 | |
|       //
 | |
|       bTimerRunning = FALSE;
 | |
|       DEBUG (( DEBUG_INFO,
 | |
|                 "0x%08x: Timer stopped\r\n",
 | |
|                 pTimer ));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the operation status
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Start the timer
 | |
| 
 | |
|   @param [in] Milliseconds  The number of milliseconds between timer callbacks
 | |
| 
 | |
|   @retval  EFI_SUCCESS  The timer was successfully created
 | |
|   @retval  Other        Timer initialization failed
 | |
| **/
 | |
| EFI_STATUS
 | |
| TimerStart (
 | |
|   UINTN Milliseconds
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS Status;
 | |
|   UINT64 TimeDelay;
 | |
| 
 | |
|   //
 | |
|   //  Stop the timer if necessary
 | |
|   //
 | |
|   Status = EFI_SUCCESS;
 | |
|   if ( bTimerRunning ) {
 | |
|     Status = TimerStop ( );
 | |
|   }
 | |
|   if ( !EFI_ERROR ( Status )) {
 | |
|     //
 | |
|     //  Compute the new delay
 | |
|     //
 | |
|     TimeDelay = Milliseconds;
 | |
|     TimeDelay *= 1000 * 10;
 | |
| 
 | |
|     //
 | |
|     //  Start the timer
 | |
|     //
 | |
|     Status = gBS->SetTimer ( pTimer,
 | |
|                              TimerPeriodic,
 | |
|                              TimeDelay );
 | |
|     if ( EFI_ERROR ( Status )) {
 | |
|       DEBUG (( DEBUG_ERROR,
 | |
|                 "ERROR - Failed to start the timer, Status: %r\r\n",
 | |
|                 Status ));
 | |
|     }
 | |
|     else {
 | |
|       //
 | |
|       //  The timer is now running
 | |
|       //
 | |
|       bTimerRunning = TRUE;
 | |
|       DEBUG (( DEBUG_INFO,
 | |
|         "0x%08x: Timer running\r\n",
 | |
|         pTimer ));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the operation status
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Destroy the timer
 | |
| 
 | |
|   @retval  EFI_SUCCESS  The timer was destroyed successfully
 | |
|   @retval  Other        Failed to destroy the timer
 | |
| **/
 | |
| EFI_STATUS
 | |
| TimerDestroy (
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   //
 | |
|   //  Assume success
 | |
|   //
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   //
 | |
|   //  Determine if the timer is running
 | |
|   //
 | |
|   if ( bTimerRunning ) {
 | |
|     //
 | |
|     //  Stop the timer
 | |
|     //
 | |
|     Status = TimerStop ( );
 | |
|   }
 | |
|   if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) {
 | |
|     //
 | |
|     //  Done with this timer
 | |
|     //
 | |
|     Status = gBS->CloseEvent ( pTimer );
 | |
|     if ( EFI_ERROR ( Status )) {
 | |
|       DEBUG (( DEBUG_ERROR,
 | |
|                 "ERROR - Failed to free the timer event, Status: %r\r\n",
 | |
|                 Status ));
 | |
|     }
 | |
|     else {
 | |
|       DEBUG (( DEBUG_INFO,
 | |
|                 "0x%08x: Timer Destroyed\r\n",
 | |
|                 pTimer ));
 | |
|       pTimer = NULL;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the operation status
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Receive data from the DataSource program to test a network's bandwidth.
 | |
| 
 | |
|   @param [in] Argc  The number of arguments
 | |
|   @param [in] Argv  The argument value array
 | |
| 
 | |
|   @retval  0        The application exited normally.
 | |
|   @retval  Other    An error occurred.
 | |
| **/
 | |
| int
 | |
| main (
 | |
|   IN int Argc,
 | |
|   IN char **Argv
 | |
|   )
 | |
| {
 | |
|   sa_family_t Family;
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   DEBUG (( DEBUG_INFO,
 | |
|             "DataSink starting\r\n" ));
 | |
| 
 | |
|   //
 | |
|   //  Determine the family to use
 | |
|   //
 | |
|   Family = ( 1 < Argc ) ? AF_INET6 : AF_INET;
 | |
| 
 | |
|   //
 | |
|   //  Use for/break instead of goto
 | |
|   //
 | |
|   for ( ; ; ) {
 | |
|     //
 | |
|     //  Create the timer
 | |
|     //
 | |
|     bTick = TRUE;
 | |
|     Status = TimerCreate ( );
 | |
|     if ( EFI_ERROR ( Status )) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     //  Start a timer to perform network polling and display updates
 | |
|     //
 | |
|     Status = TimerStart ( 1 * 1000 );
 | |
|     if ( EFI_ERROR ( Status )) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     //  Loop forever waiting for abuse
 | |
|     //
 | |
|     do {
 | |
|       ListenSocket = -1;
 | |
|       do {
 | |
|         //
 | |
|         //  Complete any client operations
 | |
|         //
 | |
|         Status = SocketPoll ( );
 | |
|         if ( EFI_ERROR ( Status )) {
 | |
|           //
 | |
|           //  Control-C
 | |
|           //
 | |
|           break;
 | |
|         }
 | |
|       
 | |
|         //
 | |
|         //  Wait for a while
 | |
|         //
 | |
|       } while ( !bTick );
 | |
|       if ( EFI_ERROR ( Status )) {
 | |
|         //
 | |
|         //  Control-C
 | |
|         //
 | |
|         break;
 | |
|       }
 | |
|       
 | |
|       //
 | |
|       //  Wait for the network layer to initialize
 | |
|       //
 | |
|       Status = SocketNew ( Family );
 | |
|       if ( EFI_ERROR ( Status )) {
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       //  Wait for the remote network application to start
 | |
|       //
 | |
|       Status = SocketAccept ( );
 | |
|       if ( EFI_NOT_STARTED == Status ) {
 | |
|         Status = SocketClose ( );
 | |
|         continue;
 | |
|       }
 | |
|       else if ( EFI_SUCCESS != Status ) {
 | |
|         //
 | |
|         //  Control-C
 | |
|         //
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       //  Receive data until the connection breaks
 | |
|       //
 | |
|       do {
 | |
|         Status = SocketPoll ( );
 | |
|       } while ( !EFI_ERROR ( Status ));
 | |
| 
 | |
|       //
 | |
|       //  Done with the socket
 | |
|       //
 | |
|       Status = SocketClose ( );
 | |
|     } while ( !EFI_ERROR ( Status ));
 | |
| 
 | |
|     //
 | |
|     //  Close the socket if necessary
 | |
|     //
 | |
|     SocketClose ( );
 | |
| 
 | |
|     //
 | |
|     //  All done
 | |
|     //
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Stop the timer if necessary
 | |
|   //
 | |
|   TimerStop ( );
 | |
|   TimerDestroy ( );
 | |
| 
 | |
|   //
 | |
|   //  Return the operation status
 | |
|   //
 | |
|   DEBUG (( DEBUG_INFO,
 | |
|             "DataSink exiting, Status: %r\r\n",
 | |
|             Status ));
 | |
|   return Status;
 | |
| }
 |