Merged socket development branch:
* Add TCPv6 support to DataSink * Add TCPv6 support to DataSource * Add GetAddrInfo test application * Add GetNameInfo test application * Fixed copyright date * Completed TFTP server - now downloads files from local directory * Added ports and exit pages to web server * Made PCD values package specific Signed-off-by: lpleahy git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13003 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
Definitions for the TFTP server.
|
||||
|
||||
Copyright (c) 2011, Intel Corporation
|
||||
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
|
||||
@@ -16,6 +16,7 @@
|
||||
#define _TFTP_SERVER_H_
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <Uefi.h>
|
||||
@@ -24,29 +25,33 @@
|
||||
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
#include <Library/UefiApplicationEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet6/in6.h>
|
||||
|
||||
#include <sys/EfiSysCall.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/Stat.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Macros
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if defined(_MSC_VER) /* Handle Microsoft VC++ compiler specifics. */
|
||||
#define DBG_ENTER() DEBUG (( DEBUG_INFO, "Entering " __FUNCTION__ "\n" )) ///< Display routine entry
|
||||
#define DBG_EXIT() DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ "\n" )) ///< Display routine exit
|
||||
#define DBG_EXIT_DEC(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: %d\n", Status )) ///< Display routine exit with decimal value
|
||||
#define DBG_EXIT_HEX(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status )) ///< Display routine exit with hex value
|
||||
#define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: %r\n", Status )) ///< Display routine exit with status value
|
||||
#define DBG_EXIT_TF(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", returning %s\n", (FALSE == Status) ? L"FALSE" : L"TRUE" )) ///< Display routine with TRUE/FALSE value
|
||||
#define DBG_ENTER() DEBUG (( DEBUG_ENTER_EXIT, "Entering " __FUNCTION__ "\n" )) ///< Display routine entry
|
||||
#define DBG_EXIT() DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ "\n" )) ///< Display routine exit
|
||||
#define DBG_EXIT_DEC(Status) DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: %d\n", Status )) ///< Display routine exit with decimal value
|
||||
#define DBG_EXIT_HEX(Status) DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status )) ///< Display routine exit with hex value
|
||||
#define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: %r\n", Status )) ///< Display routine exit with status value
|
||||
#define DBG_EXIT_TF(Status) DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", returning %s\n", (FALSE == Status) ? L"FALSE" : L"TRUE" )) ///< Display routine with TRUE/FALSE value
|
||||
#else // _MSC_VER
|
||||
#define DBG_ENTER()
|
||||
#define DBG_EXIT()
|
||||
@@ -62,14 +67,22 @@
|
||||
// Constants
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#define DEBUG_PORT_WORK 0x40000000 ///< Display the port work messages
|
||||
#define DEBUG_SERVER_TIMER 0x20000000 ///< Display the socket poll messages
|
||||
#define DEBUG_TFTP_PORT 0x10000000 ///< Display the TFTP port messages
|
||||
#define DEBUG_TFTP_REQUEST 0x08000000 ///< Display the TFTP request messages
|
||||
#define DEBUG_TX 0x04000000 ///< Display transmit messages
|
||||
#define DEBUG_SOCKET_POLL 0x02000000 ///< Display the socket poll messages
|
||||
#define DEBUG_RX 0x01000000 ///< Display receive messages
|
||||
#define DEBUG_TFTP_ACK 0x00800000 ///< Display the TFTP ACK messages
|
||||
#define ACK_SHIFT 4 ///< Number of samples in ACK average
|
||||
|
||||
#define DEBUG_WINDOW 0x00000001 ///< Display the window messages
|
||||
#define DEBUG_TX_PACKET 0x00000002 ///< Display the transmit packet messages
|
||||
#define DEBUG_FILE_BUFFER 0x00000004 ///< Display the file buffer messages
|
||||
#define DEBUG_SERVER_TIMER 0x00000008 ///< Display the socket poll messages
|
||||
#define DEBUG_TFTP_REQUEST 0x00000010 ///< Display the TFTP request messages
|
||||
#define DEBUG_PORT_WORK 0x00000020 ///< Display the port work messages
|
||||
#define DEBUG_SOCKET_POLL 0x00000040 ///< Display the socket poll messages
|
||||
#define DEBUG_TFTP_PORT 0x00000080 ///< Display the TFTP port messages
|
||||
#define DEBUG_TX 0x00000100 ///< Display transmit messages
|
||||
#define DEBUG_RX 0x00000200 ///< Display receive messages
|
||||
#define DEBUG_TFTP_ACK 0x00000400 ///< Display the TFTP ACK messages
|
||||
#define DEBUG_ENTER_EXIT 0x00000800 ///< Display entry and exit messages
|
||||
|
||||
#define MAX_PACKETS 8 ///< Maximum number of packets in the window
|
||||
|
||||
#define TFTP_PORT_POLL_DELAY ( 2 * 1000 ) ///< Delay in milliseconds for attempts to open the TFTP port
|
||||
#define CLIENT_POLL_DELAY 50 ///< Delay in milliseconds between client polls
|
||||
@@ -123,10 +136,32 @@
|
||||
|
||||
#define TFTP_MAX_BLOCK_SIZE 4096 ///< Maximum block size
|
||||
|
||||
#define TFTP_ERROR_SEE_MSG 0 ///< See the error message
|
||||
#define TFTP_ERROR_NOT_FOUND 1 ///< File not found
|
||||
#define TFTP_ERROR_ACCESS_VIOLATION 2 ///< Access violation
|
||||
#define TFTP_ERROR_DISK_FULL 3 ///< Disk full
|
||||
#define TFTP_ERROR_ILLEGAL_OP 4 ///< Illegal operation
|
||||
#define TFTP_ERROR_UNKNOWN_XFER_ID 5 ///< Unknown transfer ID
|
||||
#define TFTP_ERROR_FILE_EXISTS 6 ///< File already exists
|
||||
#define TFTP_ERROR_NO_SUCH_USER 7 ///< No such user
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Data Types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Packet structure
|
||||
**/
|
||||
typedef struct _TFTP_PACKET TFTP_PACKET;
|
||||
typedef struct _TFTP_PACKET {
|
||||
TFTP_PACKET * pNext; ///< Next packet in list
|
||||
UINT64 TxTime; ///< Time the transmit was performed
|
||||
ssize_t TxBytes; ///< Bytes in the TX buffer
|
||||
UINT32 RetryCount; ///< Number of transmissions
|
||||
UINT16 BlockNumber; ///< Block number of this packet
|
||||
UINT8 TxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ]; ///< Transmit buffer
|
||||
} GCC_TFTP_PACKET;
|
||||
|
||||
/**
|
||||
Port control structure
|
||||
**/
|
||||
@@ -135,33 +170,49 @@ typedef struct _TSDT_CONNECTION_CONTEXT {
|
||||
//
|
||||
// Remote connection management
|
||||
//
|
||||
TSDT_CONNECTION_CONTEXT * pNext; ///< Next context in the connection list
|
||||
struct sockaddr_in RemoteAddress; ///< Remote address
|
||||
|
||||
//
|
||||
// TFTP management parameters
|
||||
//
|
||||
UINT16 AckNext; ///< Next block to be received
|
||||
BOOLEAN bExpectAck; ///< TRUE for read, FALSE for write
|
||||
UINT32 BlockSize; ///< Negotiated block size
|
||||
UINT32 Timeout; ///< Number of seconds to wait before retransmission
|
||||
TSDT_CONNECTION_CONTEXT * pNext; ///< Next context in the connection list
|
||||
struct sockaddr_in6 RemoteAddress; ///< Remote address
|
||||
int SocketFd; ///< Socket file descriptor
|
||||
|
||||
//
|
||||
// File management parameters
|
||||
//
|
||||
EFI_HANDLE File; ///< NULL while file is closed
|
||||
FILE * File; ///< NULL while file is closed
|
||||
UINT64 LengthInBytes; ///< Size of the file
|
||||
UINT64 MaxTransferSize; ///< Maximum transfer size
|
||||
UINT64 BytesRemaining; ///< Number of bytes remaining to be sent
|
||||
UINT64 BytesToSend; ///< Number of bytes to send
|
||||
UINT64 ValidBytes; ///< Number of valid bytes in the buffer
|
||||
BOOLEAN bEofSent; ///< End of file sent
|
||||
UINT8 * pFill; ///< Next portion of the buffer to fill
|
||||
UINT8 * pBuffer; ///< Pointer into the file data
|
||||
UINT8 * pEnd; ///< End of the file data
|
||||
UINT8 FileData[ 64 * TFTP_MAX_BLOCK_SIZE ]; ///< File data to send
|
||||
UINT8 FileData[ 2 * MAX_PACKETS * TFTP_MAX_BLOCK_SIZE ]; ///< File data to send
|
||||
UINT64 TimeStart; ///< Start of file transfer
|
||||
|
||||
//
|
||||
// TFTP management parameters
|
||||
//
|
||||
UINT16 BlockNumber; ///< Next block to be transmitted
|
||||
UINT32 BlockSize; ///< Negotiated block size
|
||||
|
||||
//
|
||||
// Window management
|
||||
//
|
||||
UINT32 AckCount; ///< Number of ACKs to receive before increasing the window
|
||||
UINT32 PacketsInWindow; ///< Number of packets in the window
|
||||
UINT32 Threshold; ///< Size of window when ACK count becomes logrithmic
|
||||
UINT32 WindowSize; ///< Size of the transmit window
|
||||
UINT64 MaxTimeout; ///< Maximum number of seconds to wait before retransmission
|
||||
UINT64 Rtt2x; ///< Twice the average round trip time in nanoseconds
|
||||
|
||||
//
|
||||
// Buffer management
|
||||
//
|
||||
ssize_t TxBytes; ///< Bytes in the TX buffer
|
||||
UINT8 TxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ]; ///< Transmit buffer
|
||||
TFTP_PACKET * pFreeList; ///< List of free packets
|
||||
TFTP_PACKET * pTxHead; ///< First packet in the list of packets for transmission
|
||||
TFTP_PACKET * pTxTail; ///< Last packet in the list of packets for transmission
|
||||
TFTP_PACKET ErrorPacket; ///< Error packet
|
||||
TFTP_PACKET Tx[ MAX_PACKETS ];///< Transmit packets
|
||||
}GCC_TSDT_CONNECTION_CONTEXT;
|
||||
|
||||
/**
|
||||
@@ -175,20 +226,32 @@ typedef struct {
|
||||
//
|
||||
EFI_HANDLE ImageHandle; ///< Image handle
|
||||
|
||||
//
|
||||
// Performance management
|
||||
//
|
||||
UINT64 ClockFrequency; ///< Frequency of the clock
|
||||
UINT64 Time1; ///< Clock value after rollover
|
||||
UINT64 Time2; ///< Clock value before rollover
|
||||
UINT64 RxTime; ///< Time when the packet was recevied
|
||||
|
||||
//
|
||||
// TFTP port management
|
||||
//
|
||||
BOOLEAN bTimerRunning; ///< Port creation timer status
|
||||
EFI_EVENT TimerEvent; ///< Timer to open TFTP port
|
||||
struct pollfd TftpPort; ///< Poll descriptor for the TFTP port
|
||||
struct sockaddr_in TftpServerAddress; ///< Address of the local TFTP server
|
||||
int Udpv4Index; ///< Entry for UDPv4
|
||||
int Udpv6Index; ///< Entry for UDPv6
|
||||
int Entries; ///< Number of TFTP ports
|
||||
struct pollfd TftpPort [ 2 ]; ///< Poll descriptor for the TFTP ports (UDP4, UDP6)
|
||||
|
||||
//
|
||||
// Request management
|
||||
//
|
||||
struct sockaddr_in RemoteAddress; ///< Remote address
|
||||
ssize_t RxBytes; ///< Receive data length in bytes
|
||||
UINT8 RxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ]; ///< Receive buffer
|
||||
union {
|
||||
struct sockaddr_in v4; ///< UDP4 address
|
||||
struct sockaddr_in6 v6; ///< UDP6 address
|
||||
} RemoteAddress; ///< Remote address
|
||||
ssize_t RxBytes; ///< Receive data length in bytes
|
||||
UINT8 RxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ]; ///< Receive buffer
|
||||
|
||||
//
|
||||
// Client port management
|
||||
@@ -204,6 +267,92 @@ extern TSDT_TFTP_SERVER mTftpServer;
|
||||
// Support routines
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Queue data packets for transmission
|
||||
|
||||
@param [in] pContext Connection context structure address
|
||||
|
||||
@retval TRUE if a read error occurred
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PacketFill (
|
||||
IN TSDT_CONNECTION_CONTEXT * pContext
|
||||
);
|
||||
|
||||
/**
|
||||
Free the packet
|
||||
|
||||
@param [in] pContext Address of a ::TSDT_CONNECTION_CONTEXT structure
|
||||
@param [in] pPacket Address of a ::TFTP_PACKET structure
|
||||
|
||||
**/
|
||||
VOID
|
||||
PacketFree(
|
||||
IN TSDT_CONNECTION_CONTEXT * pContext,
|
||||
IN TFTP_PACKET * pPacket
|
||||
);
|
||||
|
||||
/**
|
||||
Get a packet for transmission
|
||||
|
||||
@param [in] pContext Address of a ::TSDT_CONNECTION_CONTEXT structure
|
||||
|
||||
@retval Address of a ::TFTP_PACKET structure
|
||||
|
||||
**/
|
||||
TFTP_PACKET *
|
||||
PacketGet (
|
||||
IN TSDT_CONNECTION_CONTEXT * pContext
|
||||
);
|
||||
|
||||
/**
|
||||
Queue the packet for transmission
|
||||
|
||||
@param [in] pContext Address of a ::TSDT_CONNECTION_CONTEXT structure
|
||||
@param [in] pPacket Address of a ::TFTP_PACKET structure
|
||||
|
||||
@retval TRUE if a transmission error has occurred
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
PacketQueue (
|
||||
IN TSDT_CONNECTION_CONTEXT * pContext,
|
||||
IN TFTP_PACKET * pPacket
|
||||
);
|
||||
|
||||
/**
|
||||
Transmit the packet
|
||||
|
||||
@param [in] pContext Address of a ::TSDT_CONNECTION_CONTEXT structure
|
||||
@param [in] pPacket Address of a ::TFTP_PACKET structure
|
||||
|
||||
@retval EFI_SUCCESS Message processed successfully
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PacketTx (
|
||||
IN TSDT_CONNECTION_CONTEXT * pContext,
|
||||
IN TFTP_PACKET * pPacket
|
||||
);
|
||||
|
||||
/**
|
||||
Build and send an error packet
|
||||
|
||||
@param [in] pContext The context structure address.
|
||||
@param [in] Error Error number for the packet
|
||||
@param [in] pError Zero terminated error string address
|
||||
|
||||
@retval EFI_SUCCESS Message processed successfully
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SendError (
|
||||
IN TSDT_CONNECTION_CONTEXT * pContext,
|
||||
IN UINT16 Error,
|
||||
IN UINT8 * pError
|
||||
);
|
||||
|
||||
/**
|
||||
Process the TFTP request
|
||||
|
||||
@@ -224,105 +373,56 @@ TftpOptionValue (
|
||||
|
||||
@param [in] pTftpServer The TFTP server control structure address.
|
||||
@param [in] pContext Connection context structure address
|
||||
@param [in] SocketFd Socket file descriptor
|
||||
|
||||
**/
|
||||
VOID
|
||||
TftpProcessRequest (
|
||||
IN TSDT_TFTP_SERVER * pTftpServer,
|
||||
IN TSDT_CONNECTION_CONTEXT * pContext
|
||||
IN TSDT_CONNECTION_CONTEXT * pContext,
|
||||
IN int SocketFd
|
||||
);
|
||||
|
||||
/**
|
||||
Build and send an error packet
|
||||
Process the read request
|
||||
|
||||
@param [in] pTftpServer The TFTP server control structure address.
|
||||
@param [in] pContext The context structure address.
|
||||
@param [in] Error Error number for the packet
|
||||
@param [in] pError Zero terminated error string address
|
||||
@param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure
|
||||
@param [in] pContext Connection context structure address
|
||||
@param [in] SocketFd Socket file descriptor
|
||||
|
||||
@retval EFI_SUCCESS Message processed successfully
|
||||
@retval TRUE if the context should be closed
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TftpSendError (
|
||||
BOOLEAN
|
||||
TftpRead (
|
||||
IN TSDT_TFTP_SERVER * pTftpServer,
|
||||
IN TSDT_CONNECTION_CONTEXT * pContext,
|
||||
IN UINT16 Error,
|
||||
IN UINT8 * pError
|
||||
IN int SocketFd
|
||||
);
|
||||
|
||||
/**
|
||||
Send the next block of file system data
|
||||
Update the window due to the ACK
|
||||
|
||||
@param [in] pTftpServer The TFTP server control structure address.
|
||||
@param [in] pContext The context structure address.
|
||||
|
||||
@retval EFI_SUCCESS Message processed successfully
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TftpSendNextBlock (
|
||||
IN TSDT_TFTP_SERVER * pTftpServer,
|
||||
IN TSDT_CONNECTION_CONTEXT * pContext
|
||||
);
|
||||
|
||||
/**
|
||||
TFTP port creation timer routine
|
||||
|
||||
This routine polls the socket layer waiting for the initial network connection
|
||||
which will enable the creation of the TFTP port. The socket layer will manage
|
||||
the coming and going of the network connections after that until the last network
|
||||
connection is broken.
|
||||
|
||||
@param [in] pTftpServer The TFTP server control structure address.
|
||||
@param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure
|
||||
@param [in] pContext Address of a ::TSDT_CONNECTION_CONTEXT structure
|
||||
@param [in] pPacket Address of a ::TFTP_PACKET structure
|
||||
|
||||
**/
|
||||
VOID
|
||||
TftpServerTimer (
|
||||
IN TSDT_TFTP_SERVER * pTftpServer
|
||||
);
|
||||
|
||||
/**
|
||||
Start the TFTP server port creation timer
|
||||
|
||||
@param [in] pTftpServer The TFTP server control structure address.
|
||||
|
||||
@retval EFI_SUCCESS The timer was successfully started.
|
||||
@retval EFI_ALREADY_STARTED The timer is already running.
|
||||
@retval Other The timer failed to start.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TftpServerTimerStart (
|
||||
IN TSDT_TFTP_SERVER * pTftpServer
|
||||
);
|
||||
|
||||
/**
|
||||
Stop the TFTP server port creation timer
|
||||
|
||||
@param [in] pTftpServer The TFTP server control structure address.
|
||||
|
||||
@retval EFI_SUCCESS The TFTP port timer is stopped
|
||||
@retval Other Failed to stop the TFTP port timer
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TftpServerTimerStop (
|
||||
IN TSDT_TFTP_SERVER * pTftpServer
|
||||
);
|
||||
|
||||
/**
|
||||
Send the next TFTP packet
|
||||
|
||||
@param [in] pTftpServer The TFTP server control structure address.
|
||||
@param [in] pContext The context structure address.
|
||||
|
||||
@retval EFI_SUCCESS Message processed successfully
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TftpTxPacket (
|
||||
WindowAck (
|
||||
IN TSDT_TFTP_SERVER * pTftpServer,
|
||||
IN TSDT_CONNECTION_CONTEXT * pContext,
|
||||
IN TFTP_PACKET * pPacket
|
||||
);
|
||||
|
||||
/**
|
||||
A timeout has occurred, close the window
|
||||
|
||||
@param [in] pContext Address of a ::TSDT_CONNECTION_CONTEXT structure
|
||||
|
||||
**/
|
||||
VOID
|
||||
WindowTimeout (
|
||||
IN TSDT_CONNECTION_CONTEXT * pContext
|
||||
);
|
||||
|
||||
|
Reference in New Issue
Block a user