- 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;
 | 
						|
}
 |