mirror of https://github.com/acidanthera/audk.git
1288 lines
45 KiB
C
1288 lines
45 KiB
C
/** @file
|
|
Data source for network testing.
|
|
|
|
Copyright (c) 2011, 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,
|
|
htons ( 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 ],
|
|
htons ( 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,
|
|
htons ( 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 ],
|
|
htons ( 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,
|
|
htons ( 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 ],
|
|
htons ( 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,
|
|
htons ( 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 ],
|
|
htons ( 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,
|
|
htons ( 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 ],
|
|
htons ( 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,
|
|
htons ( 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 ],
|
|
htons ( 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,
|
|
htons ( 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 ],
|
|
htons ( 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,
|
|
htons ( 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 ],
|
|
htons ( 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,
|
|
htons ( 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 ],
|
|
htons ( 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,
|
|
htons ( 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 ],
|
|
htons ( 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;
|
|
}
|