DataSink.c revision 4fd606d1f5abe38e1f42c38de1d2e895166bd0f4
/** @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
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/UefiBootServicesTableLib.h>
#include <sys/EfiSysCall.h>
typedef struct _DT_PORT {
struct sockaddr_in RemoteAddress;
} DT_PORT;
struct sockaddr_in LocalAddress;
int ListenSocket;
//
// Forward routine declarations
//
/**
Check for control C entered at console
@retval EFI_SUCCESS Control C not entered
@retval EFI_ABORTED Control C entered
**/
)
{
//
// Assume no user intervention
//
//
// Display user stop request
//
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
**/
)
{
//
// Assume failure
//
//
// Bind to the local address
//
(struct sockaddr *) &LocalAddress,
if ( 0 == SocketStatus ) {
//
// Start listening on the local socket
//
if ( 0 == SocketStatus ) {
//
// Local socket in the listen state
//
//
// Allocate a port
//
}
}
//
// Return the operation status
//
return Status;
}
/**
Close the socket
@retval EFI_SUCCESS The application is running normally
@retval Other The user stopped the application
**/
)
{
//
// Determine if the socket is open
//
if ( -1 != ListenSocket ) {
//
// Attempt to close the socket
//
if ( 0 == CloseStatus ) {
DEBUG (( DEBUG_INFO,
"0x%08x: Socket closed\r\n",
ListenSocket ));
ListenSocket = -1;
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR: Failed to close socket, errno: %d\r\n",
errno ));
}
}
//
// Return the operation status
//
return Status;
}
/**
Create the socket
@retval EFI_SUCCESS The application is running normally
@retval Other The user stopped the application
**/
)
{
//
// Get the port number
//
//
// Loop creating the socket
//
DEBUG (( DEBUG_INFO,
"Creating the socket\r\n" ));
//
// Check for user stop request
//
Status = ControlCCheck ( );
//
// Attempt to create the socket
//
IPPROTO_TCP );
if ( -1 != ListenSocket ) {
DEBUG (( DEBUG_INFO,
"0x%08x: Socket created\r\n",
ListenSocket ));
}
else {
}
}
//
// 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
**/
)
{
int CloseStatus;
int FdCount;
struct sockaddr_in RemoteAddress;
int Socket;
//
// Check for control-C
//
Status = ControlCCheck ( );
//
// Poll the sockets
//
0 );
if ( -1 == FdCount ) {
//
// Poll error
//
DEBUG (( DEBUG_ERROR,
"ERROR - Poll error, errno: %d\r\n",
errno ));
}
else {
//
// Process the poll output
//
Index = 0;
while ( FdCount ) {
//
// Account for this descriptor
//
FdCount -= 1;
}
//
// Check for a broken connection
//
bListenError = TRUE;
DEBUG (( DEBUG_ERROR,
"ERROR - Network closed on listen socket, errno: %d\r\n",
errno ));
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR - Network closed on socket %d.%d.%d.%d:%d, errno: %d\r\n",
errno ));
//
// Close the socket
//
if ( 0 == CloseStatus ) {
DEBUG (( DEBUG_INFO,
"0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",
errno ));
}
}
}
//
// Check for a connection or read data
//
//
// Check for a connection
//
//
// Another client connection was received
//
LengthInBytes = sizeof ( RemoteAddress );
(struct sockaddr *) &RemoteAddress,
&LengthInBytes );
if ( -1 == Socket ) {
//
// Listen socket error
//
bListenError = 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 )
//
// Display the connection
//
Print ( L"Rejecting connection to remote system %d.%d.%d.%d:%d\r\n",
//
// No room for this connection
// Close the connection
//
if ( 0 == CloseStatus ) {
DEBUG (( DEBUG_INFO,
"0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to close socket 0x%08x, errno: %d\r\n",
errno ));
}
//
// Keep the application running
// No issue with the listen socket
//
}
else {
//
// Display the connection
//
Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",
//
// Allocate the client connection
//
}
}
}
else {
//
// Data received
//
&Buffer,
sizeof ( Buffer ));
if ( 0 < BytesReceived ) {
//
// Display the amount of data received
//
DEBUG (( DEBUG_INFO,
"0x%08x: Socket received 0x%08x bytes from %d.%d.%d.%d:%d\r\n",
//
// Synchronize with the TimerCallback routine
//
//
// Account for the data received
//
//
// Release the synchronization with the TimerCallback routine
//
}
else if ( -1 == BytesReceived ) {
//
// Close the socket
//
DEBUG (( DEBUG_INFO,
"ERROR - Receive failure for %d.%d.%d.%d:%d, errno: %d\r\n",
errno ));
if ( 0 == CloseStatus ) {
DEBUG (( DEBUG_INFO,
"0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",
errno ));
}
}
//
// Keep the application running
// No issue with the listen socket
//
}
}
//
// Remove the socket if necessary
//
if ( bRemoveSocket ) {
DEBUG (( DEBUG_INFO,
"0x%08x: Socket removed from polling\r\n",
MaxPort -= 1;
}
Index -= 1;
}
//
// Account for this socket
//
Index += 1;
}
}
}
//
// Return the listen failure if necessary
//
}
//
// 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
**/
)
{
//
// Notify the other code of the timer tick
//
//
// Walk the list of ports
//
//
// Determine if any data was received
//
&& ( 0 != BytesReceived )) {
//
// Update the average bytes per second
//
//
// Separate the samples
//
Print ( L"---------- Stable average ----------\r\n" );
}
//
// Display the data rate
//
if ( Average < RANGE_SWITCH ) {
}
else {
Average >>= 10;
if ( Average < RANGE_SWITCH ) {
}
else {
Average >>= 10;
if ( Average < RANGE_SWITCH ) {
}
else {
Average >>= 10;
if ( Average < RANGE_SWITCH ) {
}
else {
Average >>= 10;
if ( Average < RANGE_SWITCH ) {
Average );
}
else {
Average >>= 10;
}
}
}
}
}
}
}
}
/**
Create the timer
@retval EFI_SUCCESS The timer was successfully created
@retval Other Timer initialization failed
**/
)
{
//
// Create the timer
//
NULL,
&pTimer );
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
**/
)
{
//
// Assume success
//
//
// Determine if the timer is running
//
if ( bTimerRunning ) {
//
// Stop the timer
//
0 );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to stop the timer, Status: %r\r\n",
Status ));
}
else {
//
// Timer timer is now stopped
//
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
**/
)
{
//
// Stop the timer if necessary
//
if ( bTimerRunning ) {
}
//
// Compute the new delay
//
//
// Start the timer
//
TimeDelay );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to start the timer, Status: %r\r\n",
Status ));
}
else {
//
// The timer is now running
//
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
**/
)
{
//
// Assume success
//
//
// Determine if the timer is running
//
if ( bTimerRunning ) {
//
// Stop the timer
//
}
//
// Done with this timer
//
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 ));
}
}
//
// 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 (
)
{
DEBUG (( DEBUG_INFO,
"DataSink starting\r\n" ));
//
//
for ( ; ; ) {
//
// Create the timer
//
Status = TimerCreate ( );
break;
}
//
// Start a timer to perform network polling and display updates
//
break;
}
//
// Loop forever waiting for abuse
//
do {
ListenSocket = -1;
do {
//
// Complete any client operations
//
Status = SocketPoll ( );
//
// Control-C
//
break;
}
//
// Wait for a while
//
} while ( !bTick );
//
// Control-C
//
break;
}
//
// Wait for the network layer to initialize
//
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;
}
//
// Send data until the connection breaks
//
do {
Status = SocketPoll ( );
//
// Done with the socket
//
Status = SocketClose ( );
//
// 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;
}