]> git.proxmox.com Git - mirror_edk2.git/blobdiff - AppPkg/Applications/Sockets/TftpServer/TftpServer.h
Merged socket development branch:
[mirror_edk2.git] / AppPkg / Applications / Sockets / TftpServer / TftpServer.h
index b1e9f83ce59995d1f99080d9f5d2242d16e65dfb..79b64c2820cda05d5583209a5d1fdc7cd7ccfe21 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Definitions for the TFTP server.\r
 \r
-  Copyright (c) 2011, Intel Corporation\r
+  Copyright (c) 2011, 2012, Intel Corporation\r
   All rights reserved. This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -16,6 +16,7 @@
 #define _TFTP_SERVER_H_\r
 \r
 #include <errno.h>\r
+#include <stdio.h>\r
 #include <stdlib.h>\r
 #include <string.h>\r
 #include <Uefi.h>\r
 \r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
 #include <Library/PcdLib.h>\r
+#include <Library/TimerLib.h>\r
 #include <Library/UefiApplicationEntryPoint.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiLib.h>\r
 #include <Protocol/BlockIo.h>\r
 \r
 #include <netinet/in.h>\r
+#include <netinet6/in6.h>\r
 \r
 #include <sys/EfiSysCall.h>\r
 #include <sys/poll.h>\r
 #include <sys/socket.h>\r
+#include <sys/Stat.h>\r
 \r
 //------------------------------------------------------------------------------\r
 //  Macros\r
 //------------------------------------------------------------------------------\r
 \r
 #if defined(_MSC_VER)           /* Handle Microsoft VC++ compiler specifics. */\r
-#define DBG_ENTER()             DEBUG (( DEBUG_INFO, "Entering " __FUNCTION__ "\n" )) ///<  Display routine entry\r
-#define DBG_EXIT()              DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ "\n" ))  ///<  Display routine exit\r
-#define DBG_EXIT_DEC(Status)    DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: %d\n", Status ))      ///<  Display routine exit with decimal value\r
-#define DBG_EXIT_HEX(Status)    DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status ))  ///<  Display routine exit with hex value\r
-#define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_INFO, "Exiting " __FUNCTION__ ", Status: %r\n", Status ))      ///<  Display routine exit with status value\r
-#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\r
+#define DBG_ENTER()             DEBUG (( DEBUG_ENTER_EXIT, "Entering " __FUNCTION__ "\n" )) ///<  Display routine entry\r
+#define DBG_EXIT()              DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ "\n" ))  ///<  Display routine exit\r
+#define DBG_EXIT_DEC(Status)    DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: %d\n", Status ))      ///<  Display routine exit with decimal value\r
+#define DBG_EXIT_HEX(Status)    DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: 0x%08x\n", Status ))  ///<  Display routine exit with hex value\r
+#define DBG_EXIT_STATUS(Status) DEBUG (( DEBUG_ENTER_EXIT, "Exiting " __FUNCTION__ ", Status: %r\n", Status ))      ///<  Display routine exit with status value\r
+#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\r
 #else   //  _MSC_VER\r
 #define DBG_ENTER()\r
 #define DBG_EXIT()\r
 //  Constants\r
 //------------------------------------------------------------------------------\r
 \r
-#define DEBUG_PORT_WORK         0x40000000  ///<  Display the port work messages\r
-#define DEBUG_SERVER_TIMER      0x20000000  ///<  Display the socket poll messages\r
-#define DEBUG_TFTP_PORT         0x10000000  ///<  Display the TFTP port messages\r
-#define DEBUG_TFTP_REQUEST      0x08000000  ///<  Display the TFTP request messages\r
-#define DEBUG_TX                0x04000000  ///<  Display transmit messages\r
-#define DEBUG_SOCKET_POLL       0x02000000  ///<  Display the socket poll messages\r
-#define DEBUG_RX                0x01000000  ///<  Display receive messages\r
-#define DEBUG_TFTP_ACK          0x00800000  ///<  Display the TFTP ACK messages\r
+#define ACK_SHIFT               4           ///<  Number of samples in ACK average\r
+\r
+#define DEBUG_WINDOW            0x00000001  ///<  Display the window messages\r
+#define DEBUG_TX_PACKET         0x00000002  ///<  Display the transmit packet messages\r
+#define DEBUG_FILE_BUFFER       0x00000004  ///<  Display the file buffer messages\r
+#define DEBUG_SERVER_TIMER      0x00000008  ///<  Display the socket poll messages\r
+#define DEBUG_TFTP_REQUEST      0x00000010  ///<  Display the TFTP request messages\r
+#define DEBUG_PORT_WORK         0x00000020  ///<  Display the port work messages\r
+#define DEBUG_SOCKET_POLL       0x00000040  ///<  Display the socket poll messages\r
+#define DEBUG_TFTP_PORT         0x00000080  ///<  Display the TFTP port messages\r
+#define DEBUG_TX                0x00000100  ///<  Display transmit messages\r
+#define DEBUG_RX                0x00000200  ///<  Display receive messages\r
+#define DEBUG_TFTP_ACK          0x00000400  ///<  Display the TFTP ACK messages\r
+#define DEBUG_ENTER_EXIT        0x00000800  ///<  Display entry and exit messages\r
+\r
+#define MAX_PACKETS             8           ///<  Maximum number of packets in the window\r
 \r
 #define TFTP_PORT_POLL_DELAY  ( 2 * 1000 )  ///<  Delay in milliseconds for attempts to open the TFTP port\r
 #define CLIENT_POLL_DELAY     50            ///<  Delay in milliseconds between client polls\r
 \r
 #define TFTP_MAX_BLOCK_SIZE       4096  ///<  Maximum block size\r
 \r
+#define TFTP_ERROR_SEE_MSG          0   ///<  See the error message\r
+#define TFTP_ERROR_NOT_FOUND        1   ///<  File not found\r
+#define TFTP_ERROR_ACCESS_VIOLATION 2   ///<  Access violation\r
+#define TFTP_ERROR_DISK_FULL        3   ///<  Disk full\r
+#define TFTP_ERROR_ILLEGAL_OP       4   ///<  Illegal operation\r
+#define TFTP_ERROR_UNKNOWN_XFER_ID  5   ///<  Unknown transfer ID\r
+#define TFTP_ERROR_FILE_EXISTS      6   ///<  File already exists\r
+#define TFTP_ERROR_NO_SUCH_USER     7   ///<  No such user\r
+\r
 //------------------------------------------------------------------------------\r
 //  Data Types\r
 //------------------------------------------------------------------------------\r
 \r
+/**\r
+  Packet structure\r
+**/\r
+typedef struct _TFTP_PACKET TFTP_PACKET;\r
+typedef struct _TFTP_PACKET {\r
+  TFTP_PACKET * pNext;          ///<  Next packet in list\r
+  UINT64    TxTime;             ///<  Time the transmit was performed\r
+  ssize_t   TxBytes;            ///<  Bytes in the TX buffer\r
+  UINT32    RetryCount;         ///<  Number of transmissions\r
+  UINT16    BlockNumber;        ///<  Block number of this packet\r
+  UINT8     TxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ];  ///<  Transmit buffer\r
+} GCC_TFTP_PACKET;\r
+\r
 /**\r
   Port control structure\r
 **/\r
@@ -135,33 +170,49 @@ typedef struct _TSDT_CONNECTION_CONTEXT {
   //\r
   //  Remote connection management\r
   //\r
-  TSDT_CONNECTION_CONTEXT * pNext;  ///<  Next context in the connection list\r
-  struct sockaddr_in RemoteAddress; ///<  Remote address\r
-\r
-  //\r
-  //  TFTP management parameters\r
-  //\r
-  UINT16 AckNext;               ///<  Next block to be received\r
-  BOOLEAN bExpectAck;           ///<  TRUE for read, FALSE for write\r
-  UINT32 BlockSize;             ///<  Negotiated block size\r
-  UINT32 Timeout;               ///<  Number of seconds to wait before retransmission\r
+  TSDT_CONNECTION_CONTEXT * pNext;    ///<  Next context in the connection list\r
+  struct sockaddr_in6 RemoteAddress;  ///<  Remote address\r
+  int SocketFd;                       ///<  Socket file descriptor\r
 \r
   //\r
   //  File management parameters\r
   //\r
-  EFI_HANDLE File;              ///<  NULL while file is closed\r
+  FILE * File;                  ///<  NULL while file is closed\r
   UINT64 LengthInBytes;         ///<  Size of the file\r
-  UINT64 MaxTransferSize;       ///<  Maximum transfer size\r
+  UINT64 BytesRemaining;        ///<  Number of bytes remaining to be sent\r
+  UINT64 BytesToSend;           ///<  Number of bytes to send\r
+  UINT64 ValidBytes;            ///<  Number of valid bytes in the buffer\r
   BOOLEAN bEofSent;             ///<  End of file sent\r
+  UINT8 * pFill;                ///<  Next portion of the buffer to fill\r
   UINT8 * pBuffer;              ///<  Pointer into the file data\r
   UINT8 * pEnd;                 ///<  End of the file data\r
-  UINT8 FileData[ 64 * TFTP_MAX_BLOCK_SIZE ]; ///<  File data to send\r
+  UINT8 FileData[ 2 * MAX_PACKETS * TFTP_MAX_BLOCK_SIZE ];  ///<  File data to send\r
+  UINT64 TimeStart;             ///<  Start of file transfer\r
+\r
+  //\r
+  //  TFTP management parameters\r
+  //\r
+  UINT16 BlockNumber;           ///<  Next block to be transmitted\r
+  UINT32 BlockSize;             ///<  Negotiated block size\r
+\r
+  //\r
+  //  Window management\r
+  //\r
+  UINT32 AckCount;              ///<  Number of ACKs to receive before increasing the window\r
+  UINT32 PacketsInWindow;       ///<  Number of packets in the window\r
+  UINT32 Threshold;             ///<  Size of window when ACK count becomes logrithmic\r
+  UINT32 WindowSize;            ///<  Size of the transmit window\r
+  UINT64 MaxTimeout;            ///<  Maximum number of seconds to wait before retransmission\r
+  UINT64 Rtt2x;                 ///<  Twice the average round trip time in nanoseconds\r
 \r
   //\r
   //  Buffer management\r
   //\r
-  ssize_t   TxBytes;            ///<  Bytes in the TX buffer\r
-  UINT8     TxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ];  ///<  Transmit buffer\r
+  TFTP_PACKET * pFreeList;      ///<  List of free packets\r
+  TFTP_PACKET * pTxHead;        ///<  First packet in the list of packets for transmission\r
+  TFTP_PACKET * pTxTail;        ///<  Last packet in the list of packets for transmission\r
+  TFTP_PACKET ErrorPacket;      ///<  Error packet\r
+  TFTP_PACKET Tx[ MAX_PACKETS ];///<  Transmit packets\r
 }GCC_TSDT_CONNECTION_CONTEXT;\r
 \r
 /**\r
@@ -175,20 +226,32 @@ typedef struct {
   //\r
   EFI_HANDLE ImageHandle;       ///<  Image handle\r
 \r
+  //\r
+  //  Performance management\r
+  //\r
+  UINT64 ClockFrequency;        ///<  Frequency of the clock\r
+  UINT64 Time1;                 ///<  Clock value after rollover\r
+  UINT64 Time2;                 ///<  Clock value before rollover\r
+  UINT64 RxTime;                ///<  Time when the packet was recevied\r
+\r
   //\r
   //  TFTP port management\r
   //\r
-  BOOLEAN   bTimerRunning;      ///<  Port creation timer status\r
   EFI_EVENT TimerEvent;         ///<  Timer to open TFTP port\r
-  struct pollfd TftpPort;       ///<  Poll descriptor for the TFTP port\r
-  struct sockaddr_in TftpServerAddress; ///<  Address of the local TFTP server\r
+  int Udpv4Index;               ///<  Entry for UDPv4\r
+  int Udpv6Index;               ///<  Entry for UDPv6\r
+  int Entries;                  ///<  Number of TFTP ports\r
+  struct pollfd TftpPort [ 2 ]; ///<  Poll descriptor for the TFTP ports (UDP4, UDP6)\r
 \r
   //\r
   //  Request management\r
   //\r
-  struct sockaddr_in RemoteAddress; ///<  Remote address\r
-  ssize_t   RxBytes;                ///<  Receive data length in bytes\r
-  UINT8     RxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ];  ///<  Receive buffer\r
+  union {\r
+    struct sockaddr_in v4;      ///<  UDP4 address\r
+    struct sockaddr_in6 v6;     ///<  UDP6 address\r
+  } RemoteAddress;              ///<  Remote address\r
+  ssize_t RxBytes;              ///<  Receive data length in bytes\r
+  UINT8 RxBuffer[ 2 + 2 + TFTP_MAX_BLOCK_SIZE ];  ///<  Receive buffer\r
 \r
   //\r
   //  Client port management\r
@@ -205,37 +268,77 @@ extern TSDT_TFTP_SERVER mTftpServer;
 //------------------------------------------------------------------------------\r
 \r
 /**\r
-  Process the TFTP request\r
+  Queue data packets for transmission\r
 \r
-  @param [in] pOption   Address of the first zero terminated option string\r
-  @param [in] pValue    Address to receive the value\r
+  @param [in] pContext    Connection context structure address\r
 \r
-  @retval EFI_SUCCESS   Option translated into a value\r
+  @retval TRUE if a read error occurred\r
 \r
 **/\r
-EFI_STATUS\r
-TftpOptionValue (\r
-  IN UINT8 * pOption,\r
-  IN INT32 * pValue\r
+BOOLEAN\r
+PacketFill (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext\r
   );\r
 \r
 /**\r
-  Process the TFTP request\r
+  Free the packet\r
 \r
-  @param [in] pTftpServer The TFTP server control structure address.\r
-  @param [in] pContext    Connection context structure address\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] pPacket     Address of a ::TFTP_PACKET structure\r
 \r
 **/\r
 VOID\r
-TftpProcessRequest (\r
-  IN TSDT_TFTP_SERVER * pTftpServer,\r
+PacketFree(\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN TFTP_PACKET * pPacket\r
+  );\r
+\r
+/**\r
+  Get a packet for transmission\r
+\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+\r
+  @retval Address of a ::TFTP_PACKET structure\r
+\r
+**/\r
+TFTP_PACKET *\r
+PacketGet (\r
   IN TSDT_CONNECTION_CONTEXT * pContext\r
   );\r
 \r
+/**\r
+  Queue the packet for transmission\r
+\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] pPacket     Address of a ::TFTP_PACKET structure\r
+\r
+  @retval TRUE if a transmission error has occurred\r
+\r
+**/\r
+BOOLEAN\r
+PacketQueue (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN TFTP_PACKET * pPacket\r
+  );\r
+\r
+/**\r
+  Transmit the packet\r
+\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] pPacket     Address of a ::TFTP_PACKET structure\r
+\r
+  @retval EFI_SUCCESS   Message processed successfully\r
+\r
+**/\r
+EFI_STATUS\r
+PacketTx (\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN TFTP_PACKET * pPacket\r
+  );\r
+\r
 /**\r
   Build and send an error packet\r
 \r
-  @param [in] pTftpServer The TFTP server control structure address.\r
   @param [in] pContext    The context structure address.\r
   @param [in] Error       Error number for the packet\r
   @param [in] pError      Zero terminated error string address\r
@@ -244,85 +347,82 @@ TftpProcessRequest (
 \r
 **/\r
 EFI_STATUS\r
-TftpSendError (\r
-  IN TSDT_TFTP_SERVER * pTftpServer,\r
+SendError (\r
   IN TSDT_CONNECTION_CONTEXT * pContext,\r
   IN UINT16 Error,\r
   IN UINT8 * pError\r
   );\r
 \r
 /**\r
-  Send the next block of file system data\r
+  Process the TFTP request\r
 \r
-  @param [in] pTftpServer The TFTP server control structure address.\r
-  @param [in] pContext    The context structure address.\r
+  @param [in] pOption   Address of the first zero terminated option string\r
+  @param [in] pValue    Address to receive the value\r
 \r
-  @retval EFI_SUCCESS   Message processed successfully\r
+  @retval EFI_SUCCESS   Option translated into a value\r
 \r
 **/\r
 EFI_STATUS\r
-TftpSendNextBlock (\r
-  IN TSDT_TFTP_SERVER * pTftpServer,\r
-  IN TSDT_CONNECTION_CONTEXT * pContext\r
+TftpOptionValue (\r
+  IN UINT8 * pOption,\r
+  IN INT32 * pValue\r
   );\r
 \r
 /**\r
-  TFTP port creation timer routine\r
-\r
-  This routine polls the socket layer waiting for the initial network connection\r
-  which will enable the creation of the TFTP port.  The socket layer will manage\r
-  the coming and going of the network connections after that until the last network\r
-  connection is broken.\r
+  Process the TFTP request\r
 \r
-  @param [in] pTftpServer  The TFTP server control structure address.\r
+  @param [in] pTftpServer The TFTP server control structure address.\r
+  @param [in] pContext    Connection context structure address\r
+  @param [in] SocketFd    Socket file descriptor\r
 \r
 **/\r
 VOID\r
-TftpServerTimer (\r
-  IN TSDT_TFTP_SERVER * pTftpServer\r
+TftpProcessRequest (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN int SocketFd\r
   );\r
 \r
 /**\r
-  Start the TFTP server port creation timer\r
+  Process the read request\r
 \r
-  @param [in] pTftpServer  The TFTP server control structure address.\r
+  @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure\r
+  @param [in] pContext    Connection context structure address\r
+  @param [in] SocketFd    Socket file descriptor\r
 \r
-  @retval EFI_SUCCESS         The timer was successfully started.\r
-  @retval EFI_ALREADY_STARTED The timer is already running.\r
-  @retval Other               The timer failed to start.\r
+  @retval TRUE if the context should be closed\r
 \r
 **/\r
-EFI_STATUS\r
-TftpServerTimerStart (\r
-  IN TSDT_TFTP_SERVER * pTftpServer\r
+BOOLEAN\r
+TftpRead (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN int SocketFd\r
   );\r
 \r
 /**\r
-  Stop the TFTP server port creation timer\r
-\r
-  @param [in] pTftpServer  The TFTP server control structure address.\r
+  Update the window due to the ACK\r
 \r
-  @retval EFI_SUCCESS   The TFTP port timer is stopped\r
-  @retval Other         Failed to stop the TFTP port timer\r
+  @param [in] pTftpServer Address of the ::TSDT_TFTP_SERVER structure\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
+  @param [in] pPacket     Address of a ::TFTP_PACKET structure\r
 \r
 **/\r
-EFI_STATUS\r
-TftpServerTimerStop (\r
-  IN TSDT_TFTP_SERVER * pTftpServer\r
+VOID\r
+WindowAck (\r
+  IN TSDT_TFTP_SERVER * pTftpServer,\r
+  IN TSDT_CONNECTION_CONTEXT * pContext,\r
+  IN TFTP_PACKET * pPacket\r
   );\r
 \r
 /**\r
-  Send the next TFTP packet\r
-\r
-  @param [in] pTftpServer   The TFTP server control structure address.\r
-  @param [in] pContext      The context structure address.\r
+  A timeout has occurred, close the window\r
 \r
-  @retval EFI_SUCCESS   Message processed successfully\r
+  @param [in] pContext    Address of a ::TSDT_CONNECTION_CONTEXT structure\r
 \r
 **/\r
-EFI_STATUS\r
-TftpTxPacket (\r
-  IN TSDT_TFTP_SERVER * pTftpServer,\r
+VOID\r
+WindowTimeout (\r
   IN TSDT_CONNECTION_CONTEXT * pContext\r
   );\r
 \r