| /** @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; | |
| } |