summaryrefslogtreecommitdiff
path: root/StdLib/EfiSocketLib/Tcp4.c
diff options
context:
space:
mode:
authorlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>2011-09-30 23:02:35 +0000
committerlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>2011-09-30 23:02:35 +0000
commita88c31639bb24c73383a4528a5b77066e805148b (patch)
tree058801cd8687b0a0c6f82459b56b2ad3beb43bf4 /StdLib/EfiSocketLib/Tcp4.c
parentdf7499fcc1fbd6c825cabf19bbed379688416125 (diff)
downloadedk2-platforms-a88c31639bb24c73383a4528a5b77066e805148b.tar.xz
Update the sockets library code
* Passes conformance and functional tests. * Builds with GCC 4.4 compiler. Signed-off by: lpleahy git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12497 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'StdLib/EfiSocketLib/Tcp4.c')
-rw-r--r--StdLib/EfiSocketLib/Tcp4.c2973
1 files changed, 905 insertions, 2068 deletions
diff --git a/StdLib/EfiSocketLib/Tcp4.c b/StdLib/EfiSocketLib/Tcp4.c
index b489608a5b..ec03b96bc1 100644
--- a/StdLib/EfiSocketLib/Tcp4.c
+++ b/StdLib/EfiSocketLib/Tcp4.c
@@ -10,19 +10,88 @@
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ \section ConnectionManagement Connection Management
+
+ The ::EslTcp4Listen routine initially places the SOCK_STREAM or
+ SOCK_SEQPACKET socket into a listen state. When a remote machine
+ makes a connection to the socket, the TCPv4 network layer calls
+ ::EslTcp4ListenComplete to complete the connection processing.
+ EslTcp4ListenComplete manages the connections by placing them in
+ FIFO order in a queue to be serviced by the application. When the
+ number of connections exceeds the backlog (ESL_SOCKET::MaxFifoDepth),
+ the new connection is closed. Eventually, the application indirectly
+ calls ::EslTcp4Accept to remove the next connection from the queue
+ and get the associated socket.
+
**/
#include "Socket.h"
/**
+ Attempt to connect to a remote TCP port
+
+ This routine starts the connection processing for a SOCK_STREAM
+ or SOCK_SEQPAKCET socket using the TCPv4 network layer. It
+ configures the local TCPv4 connection point and then attempts to
+ connect to a remote system. Upon completion, the
+ ::EslTcp4ConnectComplete routine gets called with the connection
+ status.
+
+ This routine is called by ::EslSocketConnect to initiate the TCPv4
+ network specific connect operations. The connection processing is
+ initiated by this routine and finished by ::EslTcp4ConnectComplete.
+ This pair of routines walks through the list of local TCPv4
+ connection points until a connection to the remote system is
+ made.
+
+ @param [in] pSocket Address of an ::ESL_SOCKET structure.
+
+ @retval EFI_SUCCESS The connection was successfully established.
+ @retval EFI_NOT_READY The connection is in progress, call this routine again.
+ @retval Others The connection attempt failed.
+
+ **/
+EFI_STATUS
+EslTcp4ConnectStart (
+ IN ESL_SOCKET * pSocket
+ );
+
+
+/**
+ Process the connection attempt
+
+ A system has initiated a connection attempt with a socket in the
+ listen state. Attempt to complete the connection.
+
+ The TCPv4 layer calls this routine when a connection is made to
+ the socket in the listen state. See the
+ \ref ConnectionManagement section.
+
+ @param [in] Event The listen completion event
+
+ @param [in] pPort Address of an ::ESL_PORT structure.
+
+**/
+VOID
+EslTcp4ListenComplete (
+ IN EFI_EVENT Event,
+ IN ESL_PORT * pPort
+ );
+
+
+/**
Accept a network connection.
- The SocketAccept routine waits for a network connection to the socket.
- It is able to return the remote network address to the caller if
- requested.
+ This routine waits for a network connection to the socket and
+ returns the remote network address to the caller if requested.
+
+ This routine is called by ::EslSocketAccept to handle the TCPv4 protocol
+ specific accept operations for SOCK_STREAM and SOCK_SEQPACKET sockets.
+ See the \ref ConnectionManagement section.
- @param [in] pSocket Address of the socket structure.
+ @param [in] pSocket Address of an ::ESL_SOCKET structure.
@param [in] pSockAddr Address of a buffer to receive the remote
network address.
@@ -36,15 +105,15 @@
**/
EFI_STATUS
-EslTcpAccept4 (
- IN DT_SOCKET * pSocket,
+EslTcp4Accept (
+ IN ESL_SOCKET * pSocket,
IN struct sockaddr * pSockAddr,
IN OUT socklen_t * pSockAddrLength
)
{
- DT_PORT * pPort;
+ ESL_PORT * pPort;
struct sockaddr_in * pRemoteAddress;
- DT_TCP4_CONTEXT * pTcp4;
+ ESL_TCP4_CONTEXT * pTcp4;
UINT32 RemoteAddress;
EFI_STATUS Status;
@@ -102,302 +171,37 @@ EslTcpAccept4 (
/**
- Bind a name to a socket.
-
- The ::TcpBind4 routine connects a name to a TCP4 stack on the local machine.
-
- @param [in] pSocket Address of the socket structure.
-
- @param [in] pSockAddr Address of a sockaddr structure that contains the
- connection point on the local machine. An IPv4 address
- of INADDR_ANY specifies that the connection is made to
- all of the network stacks on the platform. Specifying a
- specific IPv4 address restricts the connection to the
- network stack supporting that address. Specifying zero
- for the port causes the network layer to assign a port
- number from the dynamic range. Specifying a specific
- port number causes the network layer to use that port.
-
- @param [in] SockAddrLen Specifies the length in bytes of the sockaddr structure.
-
- @retval EFI_SUCCESS - Socket successfully created
-
- **/
-EFI_STATUS
-EslTcpBind4 (
- IN DT_SOCKET * pSocket,
- IN const struct sockaddr * pSockAddr,
- IN socklen_t SockAddrLength
- )
-{
- EFI_HANDLE ChildHandle;
- DT_LAYER * pLayer;
- DT_PORT * pPort;
- DT_SERVICE * pService;
- CONST struct sockaddr_in * pIp4Address;
- EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service;
- EFI_STATUS Status;
- EFI_STATUS TempStatus;
-
- DBG_ENTER ( );
-
- //
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
- //
- // Assume success
- //
- pSocket->errno = 0;
- Status = EFI_SUCCESS;
-
- //
- // Validate the address length
- //
- pIp4Address = (CONST struct sockaddr_in *) pSockAddr;
- if ( SockAddrLength >= ( sizeof ( *pIp4Address )
- - sizeof ( pIp4Address->sin_zero ))) {
-
- //
- // Walk the list of services
- //
- pLayer = &mEslLayer;
- pService = pLayer->pTcp4List;
- while ( NULL != pService ) {
- //
- // Create the TCP port
- //
- pTcp4Service = pService->pInterface;
- ChildHandle = NULL;
- Status = pTcp4Service->CreateChild ( pTcp4Service,
- &ChildHandle );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_BIND | DEBUG_POOL,
- "0x%08x: Tcp4 port handle created\r\n",
- ChildHandle ));
-
- //
- // Open the port
- //
- Status = EslTcpPortAllocate4 ( pSocket,
- pService,
- ChildHandle,
- (UINT8 *) &pIp4Address->sin_addr.s_addr,
- SwapBytes16 ( pIp4Address->sin_port ),
- DEBUG_BIND,
- &pPort );
- }
- else {
- DEBUG (( DEBUG_BIND | DEBUG_POOL,
- "ERROR - Failed to open Tcp4 port handle, Status: %r\r\n",
- Status ));
- ChildHandle = NULL;
- }
-
- //
- // Close the port if necessary
- //
- if (( EFI_ERROR ( Status )) && ( NULL != ChildHandle )) {
- TempStatus = pTcp4Service->DestroyChild ( pTcp4Service,
- ChildHandle );
- if ( !EFI_ERROR ( TempStatus )) {
- DEBUG (( DEBUG_BIND | DEBUG_POOL,
- "0x%08x: Tcp4 port handle destroyed\r\n",
- ChildHandle ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DEBUG_BIND | DEBUG_POOL,
- "ERROR - Failed to destroy the Tcp4 port handle 0x%08x, Status: %r\r\n",
- ChildHandle,
- TempStatus ));
- ASSERT ( EFI_SUCCESS == TempStatus );
- }
- }
-
- //
- // Set the next service
- //
- pService = pService->pNext;
- }
-
- //
- // Verify that at least one network connection was found
- //
- if ( NULL == pSocket->pPortList ) {
- DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,
- "Socket address %d.%d.%d.%d (0x%08x) is not available!\r\n",
- ( pIp4Address->sin_addr.s_addr >> 24 ) & 0xff,
- ( pIp4Address->sin_addr.s_addr >> 16 ) & 0xff,
- ( pIp4Address->sin_addr.s_addr >> 8 ) & 0xff,
- pIp4Address->sin_addr.s_addr & 0xff,
- pIp4Address->sin_addr.s_addr ));
- pSocket->errno = EADDRNOTAVAIL;
- Status = EFI_INVALID_PARAMETER;
- }
- }
- else {
- DEBUG (( DEBUG_BIND,
- "ERROR - Invalid TCP4 address length: %d\r\n",
- SockAddrLength ));
- Status = EFI_INVALID_PARAMETER;
- pSocket->errno = EINVAL;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Attempt to connect to a remote TCP port
-
- @param [in] pSocket Address of the socket structure.
-
- @retval EFI_SUCCESS The connection was successfully established.
- @retval EFI_NOT_READY The connection is in progress, call this routine again.
- @retval Others The connection attempt failed.
-
- **/
-EFI_STATUS
-EslTcpConnectAttempt4 (
- IN DT_SOCKET * pSocket
- )
-{
- DT_PORT * pPort;
- DT_TCP4_CONTEXT * pTcp4;
- EFI_TCP4_PROTOCOL * pTcp4Protocol;
- EFI_STATUS Status;
+ Process the remote connection completion event.
- DBG_ENTER ( );
-
- //
- // Determine if any more local adapters are available
- //
- pPort = pSocket->pPortList;
- if ( NULL != pPort ) {
- //
- // Configure the port
- //
- pTcp4 = &pPort->Context.Tcp4;
- pTcp4->ConfigData.AccessPoint.ActiveFlag = TRUE;
- pTcp4->ConfigData.TimeToLive = 255;
- pTcp4Protocol = pTcp4->pProtocol;
- Status = pTcp4Protocol->Configure ( pTcp4Protocol,
- &pTcp4->ConfigData );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_CONNECT,
- "ERROR - Failed to configure the Tcp4 port, Status: %r\r\n",
- Status ));
- switch ( Status ) {
- case EFI_ACCESS_DENIED:
- pSocket->errno = EACCES;
- break;
-
- default:
- case EFI_DEVICE_ERROR:
- pSocket->errno = EIO;
- break;
-
- case EFI_INVALID_PARAMETER:
- pSocket->errno = EADDRNOTAVAIL;
- break;
-
- case EFI_NO_MAPPING:
- pSocket->errno = EAFNOSUPPORT;
- break;
-
- case EFI_OUT_OF_RESOURCES:
- pSocket->errno = ENOBUFS;
- break;
-
- case EFI_UNSUPPORTED:
- pSocket->errno = EOPNOTSUPP;
- break;
- }
- }
- else {
- DEBUG (( DEBUG_CONNECT,
- "0x%08x: Port configured\r\n",
- pPort ));
- pTcp4->bConfigured = TRUE;
-
- //
- // Attempt the connection to the remote system
- //
- Status = pTcp4Protocol->Connect ( pTcp4Protocol,
- &pTcp4->ConnectToken );
- if ( !EFI_ERROR ( Status )) {
- //
- // Connection in progress
- //
- pSocket->errno = EINPROGRESS;
- Status = EFI_NOT_READY;
- DEBUG (( DEBUG_CONNECT,
- "0x%08x: Port attempting connection to %d.%d.%d.%d:%d\r\n",
- pPort,
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],
- pTcp4->ConfigData.AccessPoint.RemotePort ));
- }
- else {
- //
- // Connection error
- //
- pSocket->errno = EINVAL;
- DEBUG (( DEBUG_CONNECT,
- "ERROR - Port 0x%08x not connected, Status: %r\r\n",
- pPort,
- Status ));
- }
- }
- }
- else {
- //
- // No more local adapters available
- //
- pSocket->errno = ENETUNREACH;
- Status = EFI_NO_RESPONSE;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Process the remote connection attempt
-
- A connection attempt to a remote system has just completed when
- this routine is invoked. Release the port in the case of an
+ This routine handles the completion of a connection attempt. It
+ releases the port (TCPv4 adapter connection) in the case of an
error and start a connection attempt on the next port. If the
- connection attempt was successful, then release all of the other
- ports.
+ connection attempt was successful then this routine releases all
+ of the other ports.
- @param Event The connect completion event
+ This routine is called by the TCPv4 layer when a connect request
+ completes. It sets the ESL_SOCKET::bConnected flag to notify the
+ ::EslTcp4ConnectComplete routine that the connection is available.
+ The flag is set when the connection is established or no more ports
+ exist in the list. The connection status is passed via
+ ESL_SOCKET::ConnectStatus.
- @param pPort The DT_PORT structure address
+ @param [in] Event The connect completion event
+
+ @param [in] pPort Address of an ::ESL_PORT structure.
**/
VOID
-EslTcpConnectComplete4 (
+EslTcp4ConnectComplete (
IN EFI_EVENT Event,
- IN DT_PORT * pPort
+ IN ESL_PORT * pPort
)
{
BOOLEAN bRemoveFirstPort;
BOOLEAN bRemovePorts;
- DT_PORT * pNextPort;
- DT_SOCKET * pSocket;
- DT_TCP4_CONTEXT * pTcp4;
+ ESL_PORT * pNextPort;
+ ESL_SOCKET * pSocket;
+ ESL_TCP4_CONTEXT * pTcp4;
EFI_STATUS Status;
DBG_ENTER ( );
@@ -422,10 +226,10 @@ EslTcpConnectComplete4 (
DEBUG (( DEBUG_CONNECT,
"0x%08x: Port connected to %d.%d.%d.%d:%d\r\n",
pPort,
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [0],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [1],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [2],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [3],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],
pTcp4->ConfigData.AccessPoint.RemotePort ));
//
@@ -440,17 +244,17 @@ EslTcpConnectComplete4 (
DEBUG (( DEBUG_CONNECT,
"0x%08x: Port connection to %d.%d.%d.%d:%d failed, Status: %r\r\n",
pPort,
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [0],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [1],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [2],
- pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr [3],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],
pTcp4->ConfigData.AccessPoint.RemotePort,
Status ));
//
// Close the current port
//
- Status = EslTcpPortClose4 ( pPort );
+ Status = EslSocketPortClose ( pPort );
if ( !EFI_ERROR ( Status )) {
DEBUG (( DEBUG_CONNECT,
"0x%08x: Port closed\r\n",
@@ -466,7 +270,7 @@ EslTcpConnectComplete4 (
//
// Try to connect using the next port
//
- Status = EslTcpConnectAttempt4 ( pSocket );
+ Status = EslTcp4ConnectStart ( pSocket );
if ( EFI_NOT_READY != Status ) {
pSocket->ConnectStatus = Status;
bRemoveFirstPort = TRUE;
@@ -490,7 +294,7 @@ EslTcpConnectComplete4 (
//
while ( NULL != pPort ) {
pNextPort = pPort->pLinkSocket;
- EslTcpPortClose4 ( pPort );
+ EslSocketPortClose ( pPort );
if ( !EFI_ERROR ( Status )) {
DEBUG (( DEBUG_CONNECT,
"0x%08x: Port closed\r\n",
@@ -518,10 +322,16 @@ EslTcpConnectComplete4 (
/**
Poll for completion of the connection attempt.
- The ::TcpConnectPoll4 routine determines when the connection
- attempt transitions from being in process to being complete.
+ This routine polls the ESL_SOCKET::bConnected flag to determine
+ when the connection attempt is complete.
+
+ This routine is called from ::EslSocketConnect to determine when
+ the connection is complete. The ESL_SOCKET::bConnected flag is
+ set by ::EslTcp4ConnectComplete when the TCPv4 layer establishes
+ a connection or runs out of local network adapters. This routine
+ gets the connection status from ESL_SOCKET::ConnectStatus.
- @param [in] pSocket Address of the socket structure.
+ @param [in] pSocket Address of an ::ESL_SOCKET structure.
@retval EFI_SUCCESS The connection was successfully established.
@retval EFI_NOT_READY The connection is in progress, call this routine again.
@@ -529,8 +339,8 @@ EslTcpConnectComplete4 (
**/
EFI_STATUS
-EslTcpConnectPoll4 (
- IN DT_SOCKET * pSocket
+EslTcp4ConnectPoll (
+ IN ESL_SOCKET * pSocket
)
{
EFI_STATUS Status;
@@ -612,292 +422,165 @@ EslTcpConnectPoll4 (
/**
- Connect to a remote system via the network.
+ Attempt to connect to a remote TCP port
- The ::TcpConnectStart4= routine starts the connection processing
- for a TCP4 port.
+ This routine starts the connection processing for a SOCK_STREAM
+ or SOCK_SEQPAKCET socket using the TCPv4 network layer. It
+ configures the local TCPv4 connection point and then attempts to
+ connect to a remote system. Upon completion, the
+ ::EslTcp4ConnectComplete routine gets called with the connection
+ status.
- @param [in] pSocket Address of the socket structure.
+ This routine is called by ::EslSocketConnect to initiate the TCPv4
+ network specific connect operations. The connection processing is
+ initiated by this routine and finished by ::EslTcp4ConnectComplete.
+ This pair of routines walks through the list of local TCPv4
+ connection points until a connection to the remote system is
+ made.
+
+ @param [in] pSocket Address of an ::ESL_SOCKET structure.
- @param [in] pSockAddr Network address of the remote system.
-
- @param [in] SockAddrLength Length in bytes of the network address.
-
@retval EFI_SUCCESS The connection was successfully established.
@retval EFI_NOT_READY The connection is in progress, call this routine again.
@retval Others The connection attempt failed.
**/
EFI_STATUS
-EslTcpConnectStart4 (
- IN DT_SOCKET * pSocket,
- IN const struct sockaddr * pSockAddr,
- IN socklen_t SockAddrLength
+EslTcp4ConnectStart (
+ IN ESL_SOCKET * pSocket
)
{
- struct sockaddr_in LocalAddress;
- DT_PORT * pPort;
- DT_TCP4_CONTEXT * pTcp4;
- CONST struct sockaddr_in * pIp4Address;
+ ESL_PORT * pPort;
+ ESL_TCP4_CONTEXT * pTcp4;
+ EFI_TCP4_PROTOCOL * pTcp4Protocol;
EFI_STATUS Status;
DBG_ENTER ( );
-
+
//
- // Validate the address length
+ // Determine if any more local adapters are available
//
- Status = EFI_SUCCESS;
- pIp4Address = (CONST struct sockaddr_in *) pSockAddr;
- if ( SockAddrLength >= ( sizeof ( *pIp4Address )
- - sizeof ( pIp4Address->sin_zero ))) {
+ pPort = pSocket->pPortList;
+ if ( NULL != pPort ) {
//
- // Determine if BIND was already called
+ // Configure the port
//
- if ( NULL == pSocket->pPortList ) {
- //
- // Allow any local port
- //
- ZeroMem ( &LocalAddress, sizeof ( LocalAddress ));
- LocalAddress.sin_len = sizeof ( LocalAddress );
- LocalAddress.sin_family = AF_INET;
- Status = EslSocketBind ( &pSocket->SocketProtocol,
- (struct sockaddr *)&LocalAddress,
- LocalAddress.sin_len,
- &pSocket->errno );
+ pTcp4 = &pPort->Context.Tcp4;
+ pTcp4->ConfigData.AccessPoint.ActiveFlag = TRUE;
+ pTcp4->ConfigData.TimeToLive = 255;
+ pTcp4Protocol = pPort->pProtocol.TCPv4;
+ Status = pTcp4Protocol->Configure ( pTcp4Protocol,
+ &pTcp4->ConfigData );
+ if ( EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Failed to configure the Tcp4 port, Status: %r\r\n",
+ Status ));
+ switch ( Status ) {
+ case EFI_ACCESS_DENIED:
+ pSocket->errno = EACCES;
+ break;
+
+ default:
+ case EFI_DEVICE_ERROR:
+ pSocket->errno = EIO;
+ break;
+
+ case EFI_INVALID_PARAMETER:
+ pSocket->errno = EADDRNOTAVAIL;
+ break;
+
+ case EFI_NO_MAPPING:
+ pSocket->errno = EAFNOSUPPORT;
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ pSocket->errno = ENOBUFS;
+ break;
+
+ case EFI_UNSUPPORTED:
+ pSocket->errno = EOPNOTSUPP;
+ break;
+ }
}
- if ( NULL != pSocket->pPortList ) {
+ else {
+ DEBUG (( DEBUG_CONNECT,
+ "0x%08x: Port configured\r\n",
+ pPort ));
+ pPort->bConfigured = TRUE;
+
//
- // Walk the list of ports
+ // Attempt the connection to the remote system
//
- pPort = pSocket->pPortList;
- while ( NULL != pPort ) {
+ Status = pTcp4Protocol->Connect ( pTcp4Protocol,
+ &pTcp4->ConnectToken );
+ if ( !EFI_ERROR ( Status )) {
//
- // Set the remote address
+ // Connection in progress
//
- pTcp4 = &pPort->Context.Tcp4;
- *(UINT32 *)&pTcp4->ConfigData.AccessPoint.RemoteAddress = pIp4Address->sin_addr.s_addr;
- pTcp4->ConfigData.AccessPoint.RemotePort = SwapBytes16 ( pIp4Address->sin_port );
-
+ pSocket->errno = EINPROGRESS;
+ Status = EFI_NOT_READY;
+ DEBUG (( DEBUG_CONNECT,
+ "0x%08x: Port attempting connection to %d.%d.%d.%d:%d\r\n",
+ pPort,
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],
+ pTcp4->ConfigData.AccessPoint.RemotePort ));
+ }
+ else {
//
- // Set the next port
+ // Connection error
//
- pPort = pPort->pLinkSocket;
- }
-
- //
- // Attempt a connection using the first adapter
- //
- Status = EslTcpConnectAttempt4 ( pSocket );
- }
- }
- else {
- DEBUG (( DEBUG_CONNECT,
- "ERROR - Invalid TCP4 address length: %d\r\n",
- SockAddrLength ));
- Status = EFI_INVALID_PARAMETER;
- pSocket->errno = EINVAL;
- }
-
- //
- // Return the initialization status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Initialize the TCP4 service.
-
- This routine initializes the TCP4 service after its service binding
- protocol was located on a controller.
-
- @param [in] pService DT_SERVICE structure address
-
- @retval EFI_SUCCESS The service was properly initialized
- @retval other A failure occurred during the service initialization
-
-**/
-EFI_STATUS
-EFIAPI
-EslTcpInitialize4 (
- IN DT_SERVICE * pService
- )
-{
- DT_LAYER * pLayer;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Identify the service
- //
- pService->NetworkType = NETWORK_TYPE_TCP4;
-
- //
- // Connect this service to the service list
- //
- pLayer = &mEslLayer;
- pService->pNext = pLayer->pTcp4List;
- pLayer->pTcp4List = pService;
-
- //
- // Assume the list is empty
- //
- Status = EFI_SUCCESS;
-
- //
- // Return the initialization status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Get the local socket address
-
- @param [in] pSocket Address of the socket structure.
-
- @param [out] pAddress Network address to receive the local system address
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Port 0x%08x not connected, Status: %r\r\n",
+ pPort,
+ Status ));
+ //
+ // Determine the errno value
+ //
+ switch ( Status ) {
+ default:
+ pSocket->errno = EIO;
+ break;
- @param [in,out] pAddressLength Length of the local network address structure
+ case EFI_OUT_OF_RESOURCES:
+ pSocket->errno = ENOBUFS;
+ break;
- @retval EFI_SUCCESS - Address available
- @retval Other - Failed to get the address
+ case EFI_TIMEOUT:
+ pSocket->errno = ETIMEDOUT;
+ break;
-**/
-EFI_STATUS
-EslTcpGetLocalAddress4 (
- IN DT_SOCKET * pSocket,
- OUT struct sockaddr * pAddress,
- IN OUT socklen_t * pAddressLength
- )
-{
- socklen_t LengthInBytes;
- DT_PORT * pPort;
- struct sockaddr_in * pLocalAddress;
- DT_TCP4_CONTEXT * pTcp4;
- EFI_STATUS Status;
+ case EFI_NETWORK_UNREACHABLE:
+ pSocket->errno = ENETDOWN;
+ break;
- DBG_ENTER ( );
+ case EFI_HOST_UNREACHABLE:
+ pSocket->errno = EHOSTUNREACH;
+ break;
- //
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
+ case EFI_PORT_UNREACHABLE:
+ case EFI_PROTOCOL_UNREACHABLE:
+ case EFI_CONNECTION_REFUSED:
+ pSocket->errno = ECONNREFUSED;
+ break;
- //
- // Verify that there is just a single connection
- //
- pPort = pSocket->pPortList;
- if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {
- //
- // Verify the address length
- //
- LengthInBytes = sizeof ( struct sockaddr_in );
- if ( LengthInBytes <= * pAddressLength ) {
- //
- // Return the local address
- //
- pTcp4 = &pPort->Context.Tcp4;
- pLocalAddress = (struct sockaddr_in *)pAddress;
- ZeroMem ( pLocalAddress, LengthInBytes );
- pLocalAddress->sin_family = AF_INET;
- pLocalAddress->sin_len = (uint8_t)LengthInBytes;
- pLocalAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.StationPort );
- CopyMem ( &pLocalAddress->sin_addr,
- &pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0],
- sizeof ( pLocalAddress->sin_addr ));
- pSocket->errno = 0;
- Status = EFI_SUCCESS;
- }
- else {
- pSocket->errno = EINVAL;
- Status = EFI_INVALID_PARAMETER;
+ case EFI_CONNECTION_RESET:
+ pSocket->errno = ECONNRESET;
+ break;
+ }
+ }
}
}
else {
- pSocket->errno = ENOTCONN;
- Status = EFI_NOT_STARTED;
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Get the remote socket address
-
- @param [in] pSocket Address of the socket structure.
-
- @param [out] pAddress Network address to receive the remote system address
-
- @param [in,out] pAddressLength Length of the remote network address structure
-
- @retval EFI_SUCCESS - Address available
- @retval Other - Failed to get the address
-
-**/
-EFI_STATUS
-EslTcpGetRemoteAddress4 (
- IN DT_SOCKET * pSocket,
- OUT struct sockaddr * pAddress,
- IN OUT socklen_t * pAddressLength
- )
-{
- socklen_t LengthInBytes;
- DT_PORT * pPort;
- struct sockaddr_in * pRemoteAddress;
- DT_TCP4_CONTEXT * pTcp4;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
- //
- // Verify that there is just a single connection
- //
- pPort = pSocket->pPortList;
- if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {
//
- // Verify the address length
+ // No more local adapters available
//
- LengthInBytes = sizeof ( struct sockaddr_in );
- if ( LengthInBytes <= * pAddressLength ) {
- //
- // Return the local address
- //
- pTcp4 = &pPort->Context.Tcp4;
- pRemoteAddress = (struct sockaddr_in *)pAddress;
- ZeroMem ( pRemoteAddress, LengthInBytes );
- pRemoteAddress->sin_family = AF_INET;
- pRemoteAddress->sin_len = (uint8_t)LengthInBytes;
- pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );
- CopyMem ( &pRemoteAddress->sin_addr,
- &pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
- sizeof ( pRemoteAddress->sin_addr ));
- pSocket->errno = 0;
- Status = EFI_SUCCESS;
- }
- else {
- pSocket->errno = EINVAL;
- Status = EFI_INVALID_PARAMETER;
- }
- }
- else {
- pSocket->errno = ENOTCONN;
- Status = EFI_NOT_STARTED;
+ pSocket->errno = ENETUNREACH;
+ Status = EFI_NO_RESPONSE;
}
-
+
//
// Return the operation status
//
@@ -909,27 +592,27 @@ EslTcpGetRemoteAddress4 (
/**
Establish the known port to listen for network connections.
- The ::Tcp4Listen routine places the port into a state that enables connection
- attempts. Connections are placed into FIFO order in a queue to be serviced
- by the application. The application calls the ::Tcp4Accept routine to remove
- the next connection from the queue and get the associated socket. The
- <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html">POSIX</a>
- documentation for the listen routine is available online for reference.
+ This routine places the port into a state that enables connection
+ attempts.
+
+ This routine is called by ::EslSocketListen to handle the network
+ specifics of the listen operation for SOCK_STREAM and SOCK_SEQPACKET
+ sockets. See the \ref ConnectionManagement section.
- @param [in] pSocket Address of the socket structure.
+ @param [in] pSocket Address of an ::ESL_SOCKET structure.
@retval EFI_SUCCESS - Socket successfully created
@retval Other - Failed to enable the socket for listen
**/
EFI_STATUS
-EslTcpListen4 (
- IN DT_SOCKET * pSocket
+EslTcp4Listen (
+ IN ESL_SOCKET * pSocket
)
{
- DT_PORT * pNextPort;
- DT_PORT * pPort;
- DT_TCP4_CONTEXT * pTcp4;
+ ESL_PORT * pNextPort;
+ ESL_PORT * pPort;
+ ESL_TCP4_CONTEXT * pTcp4;
EFI_TCP4_PROTOCOL * pTcp4Protocol;
EFI_STATUS Status;
@@ -970,7 +653,7 @@ EslTcpListen4 (
pTcp4 = &pPort->Context.Tcp4;
Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslTcpListenComplete4,
+ (EFI_EVENT_NOTIFY)EslTcp4ListenComplete,
pPort,
&pTcp4->ListenToken.CompletionToken.Event );
if ( EFI_ERROR ( Status )) {
@@ -987,7 +670,7 @@ EslTcpListen4 (
//
// Configure the port
//
- pTcp4Protocol = pTcp4->pProtocol;
+ pTcp4Protocol = pPort->pProtocol.TCPv4;
Status = pTcp4Protocol->Configure ( pTcp4Protocol,
&pTcp4->ConfigData );
if ( EFI_ERROR ( Status )) {
@@ -1025,7 +708,7 @@ EslTcpListen4 (
DEBUG (( DEBUG_LISTEN,
"0x%08x: Port configured\r\n",
pPort ));
- pTcp4->bConfigured = TRUE;
+ pPort->bConfigured = TRUE;
//
// Start the listen operation on the port
@@ -1078,9 +761,8 @@ EslTcpListen4 (
//
// Close the port upon error
//
- if ( EFI_ERROR ( Status ))
- {
- EslTcpPortCloseStart4 ( pPort, TRUE, DEBUG_LISTEN );
+ if ( EFI_ERROR ( Status )) {
+ EslSocketPortCloseStart ( pPort, TRUE, DEBUG_LISTEN );
}
//
@@ -1132,30 +814,36 @@ EslTcpListen4 (
A system has initiated a connection attempt with a socket in the
listen state. Attempt to complete the connection.
- @param Event The listen completion event
+ The TCPv4 layer calls this routine when a connection is made to
+ the socket in the listen state. See the
+ \ref ConnectionManagement section.
+
+ @param [in] Event The listen completion event
- @param pPort The DT_PORT structure address
+ @param [in] pPort Address of an ::ESL_PORT structure.
**/
VOID
-EslTcpListenComplete4 (
+EslTcp4ListenComplete (
IN EFI_EVENT Event,
- IN DT_PORT * pPort
+ IN ESL_PORT * pPort
)
{
EFI_HANDLE ChildHandle;
+ struct sockaddr_in LocalAddress;
EFI_TCP4_CONFIG_DATA * pConfigData;
- DT_LAYER * pLayer;
- DT_PORT * pNewPort;
- DT_SOCKET * pNewSocket;
- DT_SOCKET * pSocket;
- DT_TCP4_CONTEXT * pTcp4;
+ ESL_LAYER * pLayer;
+ ESL_PORT * pNewPort;
+ ESL_SOCKET * pNewSocket;
+ ESL_SOCKET * pSocket;
+ ESL_TCP4_CONTEXT * pTcp4;
EFI_TCP4_PROTOCOL * pTcp4Protocol;
EFI_STATUS Status;
EFI_HANDLE TcpPortHandle;
EFI_STATUS TempStatus;
DBG_ENTER ( );
+ VERIFY_AT_TPL ( TPL_SOCKETS );
//
// Assume success
@@ -1181,26 +869,36 @@ EslTcpListenComplete4 (
//
// Clone the socket parameters
//
+ pNewSocket->pApi = pSocket->pApi;
pNewSocket->Domain = pSocket->Domain;
pNewSocket->Protocol = pSocket->Protocol;
pNewSocket->Type = pSocket->Type;
//
- // Allocate a port for this connection
+ // Build the local address
//
pTcp4 = &pPort->Context.Tcp4;
- Status = EslTcpPortAllocate4 ( pNewSocket,
- pPort->pService,
- TcpPortHandle,
- &pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0],
- 0,
- DEBUG_CONNECTION,
- &pNewPort );
+ LocalAddress.sin_len = (uint8_t)pNewSocket->pApi->MinimumAddressLength;
+ LocalAddress.sin_family = AF_INET;
+ LocalAddress.sin_port = 0;
+ LocalAddress.sin_addr.s_addr = *(UINT32 *)&pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0];
+
+ //
+ // Allocate a port for this connection
+ // Note in this instance Configure may not be called with NULL!
+ //
+ Status = EslSocketPortAllocate ( pNewSocket,
+ pPort->pService,
+ TcpPortHandle,
+ (struct sockaddr *)&LocalAddress,
+ FALSE,
+ DEBUG_CONNECTION,
+ &pNewPort );
if ( !EFI_ERROR ( Status )) {
//
// Restart the listen operation on the port
//
- pTcp4Protocol = pTcp4->pProtocol;
+ pTcp4Protocol = pPort->pProtocol.TCPv4;
Status = pTcp4Protocol->Accept ( pTcp4Protocol,
&pTcp4->ListenToken );
@@ -1209,7 +907,6 @@ EslTcpListenComplete4 (
//
TcpPortHandle = NULL;
pTcp4 = &pNewPort->Context.Tcp4;
- pTcp4->bConfigured = TRUE;
//
// Check for an accept call error
@@ -1218,9 +915,10 @@ EslTcpListenComplete4 (
//
// Get the port configuration
//
+ pNewPort->bConfigured = TRUE;
pConfigData = &pTcp4->ConfigData;
pConfigData->ControlOption = &pTcp4->Option;
- pTcp4Protocol = pTcp4->pProtocol;
+ pTcp4Protocol = pNewPort->pProtocol.TCPv4;
Status = pTcp4Protocol->GetModeData ( pTcp4Protocol,
NULL,
pConfigData,
@@ -1276,7 +974,7 @@ EslTcpListenComplete4 (
//
// Start the receive operation
//
- EslTcpRxStart4 ( pNewPort );
+ EslSocketRxStart ( pNewPort );
}
else {
DEBUG (( DEBUG_ERROR | DEBUG_CONNECTION | DEBUG_INFO,
@@ -1297,7 +995,7 @@ EslTcpListenComplete4 (
//
// Close the listening port
//
- EslTcpPortCloseStart4 ( pPort, TRUE, DEBUG_LISTEN );
+ EslSocketPortCloseStart ( pPort, TRUE, DEBUG_LISTEN );
}
}
@@ -1343,137 +1041,228 @@ EslTcpListenComplete4 (
/**
- Allocate and initialize a DT_PORT structure.
+ Get the local socket address.
- @param [in] pSocket Address of the socket structure.
- @param [in] pService Address of the DT_SERVICE structure.
- @param [in] ChildHandle TCP4 child handle
- @param [in] pIpAddress Buffer containing IP4 network address of the local host
- @param [in] PortNumber Tcp4 port number
- @param [in] DebugFlags Flags for debug messages
- @param [out] ppPort Buffer to receive new DT_PORT structure address
+ This routine returns the IPv4 address and TCP port number associated
+ with the local socket.
- @retval EFI_SUCCESS - Socket successfully created
+ This routine is called by ::EslSocketGetLocalAddress to determine the
+ network address for the SOCK_STREAM or SOCK_SEQPACKET socket.
+
+ @param [in] pPort Address of an ::ESL_PORT structure.
+
+ @param [out] pSockAddr Network address to receive the local system address
+
+**/
+VOID
+EslTcp4LocalAddressGet (
+ IN ESL_PORT * pPort,
+ OUT struct sockaddr * pSockAddr
+ )
+{
+ struct sockaddr_in * pLocalAddress;
+ ESL_TCP4_CONTEXT * pTcp4;
+
+ DBG_ENTER ( );
+
+ //
+ // Return the local address
+ //
+ pTcp4 = &pPort->Context.Tcp4;
+ pLocalAddress = (struct sockaddr_in *)pSockAddr;
+ pLocalAddress->sin_family = AF_INET;
+ pLocalAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.StationPort );
+ CopyMem ( &pLocalAddress->sin_addr,
+ &pTcp4->ConfigData.AccessPoint.StationAddress.Addr[0],
+ sizeof ( pLocalAddress->sin_addr ));
+
+ DBG_EXIT ( );
+}
+
+
+/**
+ Set the local port address.
+
+ This routine sets the local port address.
+
+ This support routine is called by ::EslSocketPortAllocate.
+
+ @param [in] pPort Address of an ESL_PORT structure
+ @param [in] pSockAddr Address of a sockaddr structure that contains the
+ connection point on the local machine. An IPv4 address
+ of INADDR_ANY specifies that the connection is made to
+ all of the network stacks on the platform. Specifying a
+ specific IPv4 address restricts the connection to the
+ network stack supporting that address. Specifying zero
+ for the port causes the network layer to assign a port
+ number from the dynamic range. Specifying a specific
+ port number causes the network layer to use that port.
+
+ @param [in] bBindTest TRUE = run bind testing
+
+ @retval EFI_SUCCESS The operation was successful
**/
EFI_STATUS
-EslTcpPortAllocate4 (
- IN DT_SOCKET * pSocket,
- IN DT_SERVICE * pService,
- IN EFI_HANDLE ChildHandle,
- IN CONST UINT8 * pIpAddress,
- IN UINT16 PortNumber,
- IN UINTN DebugFlags,
- OUT DT_PORT ** ppPort
+EslTcp4LocalAddressSet (
+ IN ESL_PORT * pPort,
+ IN CONST struct sockaddr * pSockAddr,
+ IN BOOLEAN bBindTest
)
{
- UINTN LengthInBytes;
EFI_TCP4_ACCESS_POINT * pAccessPoint;
- DT_LAYER * pLayer;
- DT_PORT * pPort;
- DT_TCP4_CONTEXT * pTcp4;
+ CONST struct sockaddr_in * pIpAddress;
+ CONST UINT8 * pIpv4Address;
EFI_STATUS Status;
DBG_ENTER ( );
//
- // Use for/break instead of goto
- for ( ; ; ) {
+ // Validate the address
+ //
+ pIpAddress = (struct sockaddr_in *)pSockAddr;
+ if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) {
//
- // Allocate a port structure
+ // The local address must not be the broadcast address
//
- pLayer = &mEslLayer;
- LengthInBytes = sizeof ( *pPort );
- Status = gBS->AllocatePool ( EfiRuntimeServicesData,
- LengthInBytes,
- (VOID **)&pPort );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL | DEBUG_INIT,
- "ERROR - Failed to allocate the port structure, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- pPort = NULL;
- break;
- }
- DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,
- "0x%08x: Allocate pPort, %d bytes\r\n",
- pPort,
- LengthInBytes ));
-
+ Status = EFI_INVALID_PARAMETER;
+ pPort->pSocket->errno = EADDRNOTAVAIL;
+ }
+ else {
//
- // Initialize the port
+ // Set the local address
//
- ZeroMem ( pPort, LengthInBytes );
- pPort->Signature = PORT_SIGNATURE;
- pPort->pService = pService;
- pPort->pSocket = pSocket;
- pPort->pfnCloseStart = EslTcpPortCloseStart4;
- pPort->DebugFlags = DebugFlags;
+ pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr;
+ pAccessPoint = &pPort->Context.Tcp4.ConfigData.AccessPoint;
+ pAccessPoint->StationAddress.Addr[0] = pIpv4Address[0];
+ pAccessPoint->StationAddress.Addr[1] = pIpv4Address[1];
+ pAccessPoint->StationAddress.Addr[2] = pIpv4Address[2];
+ pAccessPoint->StationAddress.Addr[3] = pIpv4Address[3];
//
- // Allocate the receive event
+ // Determine if the default address is used
//
- pTcp4 = &pPort->Context.Tcp4;
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslTcpRxComplete4,
- pPort,
- &pTcp4->RxToken.CompletionToken.Event);
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to create the receive event, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- break;
- }
- DEBUG (( DEBUG_RX | DEBUG_POOL,
- "0x%08x: Created receive event\r\n",
- pTcp4->RxToken.CompletionToken.Event ));
-
+ pAccessPoint->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr );
+
//
- // Allocate the urgent transmit event
+ // Set the subnet mask
//
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslTcpTxOobComplete4,
- pPort,
- &pTcp4->TxOobToken.CompletionToken.Event);
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to create the urgent transmit event, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- break;
+ if ( pAccessPoint->UseDefaultAddress ) {
+ pAccessPoint->SubnetMask.Addr[0] = 0;
+ pAccessPoint->SubnetMask.Addr[1] = 0;
+ pAccessPoint->SubnetMask.Addr[2] = 0;
+ pAccessPoint->SubnetMask.Addr[3] = 0;
+ }
+ else {
+ pAccessPoint->SubnetMask.Addr[0] = 0xff;
+ pAccessPoint->SubnetMask.Addr[1] = 0xff;
+ pAccessPoint->SubnetMask.Addr[2] = 0xff;
+ pAccessPoint->SubnetMask.Addr[3] = 0xff;
}
- DEBUG (( DEBUG_CLOSE | DEBUG_POOL,
- "0x%08x: Created urgent transmit event\r\n",
- pTcp4->TxOobToken.CompletionToken.Event ));
//
- // Allocate the normal transmit event
+ // Validate the IP address
//
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslTcpTxComplete4,
- pPort,
- &pTcp4->TxToken.CompletionToken.Event);
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to create the normal transmit event, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- break;
+ pAccessPoint->StationPort = 0;
+ Status = bBindTest ? EslSocketBindTest ( pPort, EADDRNOTAVAIL )
+ : EFI_SUCCESS;
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Set the port number
+ //
+ pAccessPoint->StationPort = SwapBytes16 ( pIpAddress->sin_port );
+
+ //
+ // Display the local address
+ //
+ DEBUG (( DEBUG_BIND,
+ "0x%08x: Port, Local TCP4 Address: %d.%d.%d.%d:%d\r\n",
+ pPort,
+ pAccessPoint->StationAddress.Addr[0],
+ pAccessPoint->StationAddress.Addr[1],
+ pAccessPoint->StationAddress.Addr[2],
+ pAccessPoint->StationAddress.Addr[3],
+ pAccessPoint->StationPort ));
}
- DEBUG (( DEBUG_CLOSE | DEBUG_POOL,
- "0x%08x: Created normal transmit event\r\n",
- pTcp4->TxToken.CompletionToken.Event ));
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
+ Free a receive packet
+
+ This routine performs the network specific operations necessary
+ to free a receive packet.
+
+ This routine is called by ::EslSocketPortCloseTxDone to free a
+ receive packet.
+
+ @param [in] pPacket Address of an ::ESL_PACKET structure.
+ @param [in, out] pRxBytes Address of the count of RX bytes
+
+**/
+VOID
+EslTcp4PacketFree (
+ IN ESL_PACKET * pPacket,
+ IN OUT size_t * pRxBytes
+ )
+{
+ DBG_ENTER ( );
+ //
+ // Account for the receive bytes
+ //
+ *pRxBytes -= pPacket->Op.Tcp4Rx.RxData.DataLength;
+ DBG_EXIT ( );
+}
+
+
+/**
+ Initialize the network specific portions of an ::ESL_PORT structure.
+
+ This routine initializes the network specific portions of an
+ ::ESL_PORT structure for use by the socket.
+
+ This support routine is called by ::EslSocketPortAllocate
+ to connect the socket with the underlying network adapter
+ running the TCPv4 protocol.
+
+ @param [in] pPort Address of an ESL_PORT structure
+ @param [in] DebugFlags Flags for debug messages
+
+ @retval EFI_SUCCESS - Socket successfully created
+
+ **/
+EFI_STATUS
+EslTcp4PortAllocate (
+ IN ESL_PORT * pPort,
+ IN UINTN DebugFlags
+ )
+{
+ EFI_TCP4_ACCESS_POINT * pAccessPoint;
+ ESL_SOCKET * pSocket;
+ ESL_TCP4_CONTEXT * pTcp4;
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Use for/break instead of goto
+ for ( ; ; ) {
//
// Allocate the close event
//
+ pSocket = pPort->pSocket;
+ pTcp4 = &pPort->Context.Tcp4;
Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslTcpPortCloseComplete4,
+ (EFI_EVENT_NOTIFY)EslSocketPortCloseComplete,
pPort,
&pTcp4->CloseToken.CompletionToken.Event);
if ( EFI_ERROR ( Status )) {
@@ -1492,7 +1281,7 @@ EslTcpPortAllocate4 (
//
Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslTcpConnectComplete4,
+ (EFI_EVENT_NOTIFY)EslTcp4ConnectComplete,
pPort,
&pTcp4->ConnectToken.CompletionToken.Event);
if ( EFI_ERROR ( Status )) {
@@ -1507,90 +1296,30 @@ EslTcpPortAllocate4 (
pTcp4->ConnectToken.CompletionToken.Event ));
//
- // Open the port protocol
- //
- Status = gBS->OpenProtocol (
- ChildHandle,
- &gEfiTcp4ProtocolGuid,
- (VOID **) &pTcp4->pProtocol,
- pLayer->ImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to open gEfiTcp4ProtocolGuid on controller 0x%08x\r\n",
- pTcp4->Handle ));
- pSocket->errno = EEXIST;
- break;
- }
- DEBUG (( DebugFlags,
- "0x%08x: gEfiTcp4ProtocolGuid opened on controller 0x%08x\r\n",
- pTcp4->pProtocol,
- ChildHandle ));
-
- //
- // Set the port address
- //
- pTcp4->Handle = ChildHandle;
- pAccessPoint = &pPort->Context.Tcp4.ConfigData.AccessPoint;
- pAccessPoint->StationPort = PortNumber;
- if (( 0 == pIpAddress[0])
- && ( 0 == pIpAddress[1])
- && ( 0 == pIpAddress[2])
- && ( 0 == pIpAddress[3])) {
- pAccessPoint->UseDefaultAddress = TRUE;
- }
- else {
- pAccessPoint->StationAddress.Addr[0] = pIpAddress[0];
- pAccessPoint->StationAddress.Addr[1] = pIpAddress[1];
- pAccessPoint->StationAddress.Addr[2] = pIpAddress[2];
- pAccessPoint->StationAddress.Addr[3] = pIpAddress[3];
- pAccessPoint->SubnetMask.Addr[0] = 0xff;
- pAccessPoint->SubnetMask.Addr[1] = 0xff;
- pAccessPoint->SubnetMask.Addr[2] = 0xff;
- pAccessPoint->SubnetMask.Addr[3] = 0xff;
- }
- pAccessPoint->ActiveFlag = FALSE;
- pTcp4->ConfigData.TimeToLive = 255;
-
- //
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
- //
- // Add this port to the socket
+ // Initialize the port
//
- pPort->pLinkSocket = pSocket->pPortList;
- pSocket->pPortList = pPort;
- DEBUG (( DebugFlags,
- "0x%08x: Socket adding port: 0x%08x\r\n",
- pSocket,
- pPort ));
+ pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Tcp4Tx.TxData );
+ pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Tcp4Tx.CompletionToken.Event );
+ pSocket->TxTokenOffset = OFFSET_OF ( EFI_TCP4_IO_TOKEN, Packet.TxData );
//
- // Add this port to the service
+ // Save the cancel, receive and transmit addresses
+ // pPort->pfnRxCancel = NULL; since the UEFI implementation returns EFI_UNSUPPORTED
//
- pPort->pLinkService = pService->pPortList;
- pService->pPortList = pPort;
+ pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.TCPv4->Configure;
+ pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Receive;
+ pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Transmit;
//
- // Return the port
+ // Set the configuration flags
//
- *ppPort = pPort;
+ pAccessPoint = &pPort->Context.Tcp4.ConfigData.AccessPoint;
+ pAccessPoint->ActiveFlag = FALSE;
+ pTcp4->ConfigData.TimeToLive = 255;
break;
}
//
- // Clean up after the error if necessary
- //
- if (( EFI_ERROR ( Status )) && ( NULL != pPort )) {
- //
- // Close the port
- //
- EslTcpPortClose4 ( pPort );
- }
- //
// Return the operation status
//
DBG_EXIT_STATUS ( Status );
@@ -1601,127 +1330,35 @@ EslTcpPortAllocate4 (
/**
Close a TCP4 port.
- This routine releases the resources allocated by
- ::TcpPortAllocate4().
+ This routine releases the network specific resources allocated by
+ ::EslTcp4PortAllocate.
+
+ This routine is called by ::EslSocketPortClose.
+ See the \ref PortCloseStateMachine section.
- @param [in] pPort Address of the port structure.
+ @param [in] pPort Address of an ::ESL_PORT structure.
@retval EFI_SUCCESS The port is closed
@retval other Port close error
**/
EFI_STATUS
-EslTcpPortClose4 (
- IN DT_PORT * pPort
+EslTcp4PortClose (
+ IN ESL_PORT * pPort
)
{
UINTN DebugFlags;
- DT_LAYER * pLayer;
- DT_PACKET * pPacket;
- DT_PORT * pPreviousPort;
- DT_SERVICE * pService;
- DT_SOCKET * pSocket;
- EFI_SERVICE_BINDING_PROTOCOL * pTcp4Service;
- DT_TCP4_CONTEXT * pTcp4;
+ ESL_TCP4_CONTEXT * pTcp4;
EFI_STATUS Status;
DBG_ENTER ( );
//
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
- //
// Locate the port in the socket list
//
Status = EFI_SUCCESS;
- pLayer = &mEslLayer;
DebugFlags = pPort->DebugFlags;
- pSocket = pPort->pSocket;
- pPreviousPort = pSocket->pPortList;
- if ( pPreviousPort == pPort ) {
- //
- // Remove this port from the head of the socket list
- //
- pSocket->pPortList = pPort->pLinkSocket;
- }
- else {
- //
- // Locate the port in the middle of the socket list
- //
- while (( NULL != pPreviousPort )
- && ( pPreviousPort->pLinkSocket != pPort )) {
- pPreviousPort = pPreviousPort->pLinkSocket;
- }
- if ( NULL != pPreviousPort ) {
- //
- // Remove the port from the middle of the socket list
- //
- pPreviousPort->pLinkSocket = pPort->pLinkSocket;
- }
- }
-
- //
- // Locate the port in the service list
- //
- pService = pPort->pService;
- pPreviousPort = pService->pPortList;
- if ( pPreviousPort == pPort ) {
- //
- // Remove this port from the head of the service list
- //
- pService->pPortList = pPort->pLinkService;
- }
- else {
- //
- // Locate the port in the middle of the service list
- //
- while (( NULL != pPreviousPort )
- && ( pPreviousPort->pLinkService != pPort )) {
- pPreviousPort = pPreviousPort->pLinkService;
- }
- if ( NULL != pPreviousPort ) {
- //
- // Remove the port from the middle of the service list
- //
- pPreviousPort->pLinkService = pPort->pLinkService;
- }
- }
-
- //
- // Empty the urgent receive queue
- //
pTcp4 = &pPort->Context.Tcp4;
- while ( NULL != pSocket->pRxOobPacketListHead ) {
- pPacket = pSocket->pRxOobPacketListHead;
- pSocket->pRxOobPacketListHead = pPacket->pNext;
- pSocket->RxOobBytes -= pPacket->Op.Tcp4Rx.ValidBytes;
- EslSocketPacketFree ( pPacket, DEBUG_RX );
- }
- pSocket->pRxOobPacketListTail = NULL;
- ASSERT ( 0 == pSocket->RxOobBytes );
-
- //
- // Empty the receive queue
- //
- while ( NULL != pSocket->pRxPacketListHead ) {
- pPacket = pSocket->pRxPacketListHead;
- pSocket->pRxPacketListHead = pPacket->pNext;
- pSocket->RxBytes -= pPacket->Op.Tcp4Rx.ValidBytes;
- EslSocketPacketFree ( pPacket, DEBUG_RX );
- }
- pSocket->pRxPacketListTail = NULL;
- ASSERT ( 0 == pSocket->RxBytes );
-
- //
- // Empty the receive free queue
- //
- while ( NULL != pSocket->pRxFree ) {
- pPacket = pSocket->pRxFree;
- pSocket->pRxFree = pPacket->pNext;
- EslSocketPacketFree ( pPacket, DEBUG_RX );
- }
//
// Done with the connect event
@@ -1778,121 +1415,6 @@ EslTcpPortClose4 (
}
//
- // Done with the receive event
- //
- if ( NULL != pTcp4->RxToken.CompletionToken.Event ) {
- Status = gBS->CloseEvent ( pTcp4->RxToken.CompletionToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed receive event\r\n",
- pTcp4->RxToken.CompletionToken.Event ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close the receive event, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
- // Done with the normal transmit event
- //
- if ( NULL != pTcp4->TxToken.CompletionToken.Event ) {
- Status = gBS->CloseEvent ( pTcp4->TxToken.CompletionToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed normal transmit event\r\n",
- pTcp4->TxToken.CompletionToken.Event ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close the normal transmit event, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
- // Done with the urgent transmit event
- //
- if ( NULL != pTcp4->TxOobToken.CompletionToken.Event ) {
- Status = gBS->CloseEvent ( pTcp4->TxOobToken.CompletionToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed urgent transmit event\r\n",
- pTcp4->TxOobToken.CompletionToken.Event ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close the urgent transmit event, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
- // Done with the TCP protocol
- //
- pTcp4Service = pService->pInterface;
- if ( NULL != pTcp4->pProtocol ) {
- Status = gBS->CloseProtocol ( pTcp4->Handle,
- &gEfiTcp4ProtocolGuid,
- pLayer->ImageHandle,
- NULL );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags,
- "0x%08x: gEfiTcp4ProtocolGuid closed on controller 0x%08x\r\n",
- pTcp4->pProtocol,
- pTcp4->Handle ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close gEfiTcp4ProtocolGuid opened on controller 0x%08x, Status: %r\r\n",
- pTcp4->Handle,
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
- // Done with the TCP port
- //
- if ( NULL != pTcp4->Handle ) {
- Status = pTcp4Service->DestroyChild ( pTcp4Service,
- pTcp4->Handle );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Tcp4 port handle destroyed\r\n",
- pTcp4->Handle ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,
- "ERROR - Failed to destroy the Tcp4 port handle, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
- // Release the port structure
- //
- Status = gBS->FreePool ( pPort );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Free pPort, %d bytes\r\n",
- pPort,
- sizeof ( *pPort )));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags | DEBUG_POOL,
- "ERROR - Failed to free pPort: 0x%08x, Status: %r\r\n",
- pPort,
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
-
- //
// Return the operation status
//
DBG_EXIT_STATUS ( Status );
@@ -1901,94 +1423,52 @@ EslTcpPortClose4 (
/**
- Process the port close completion
-
- @param Event The close completion event
-
- @param pPort The DT_PORT structure address
-
-**/
-VOID
-EslTcpPortCloseComplete4 (
- IN EFI_EVENT Event,
- IN DT_PORT * pPort
- )
-{
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Update the port state
- //
- pPort->State = PORT_STATE_CLOSE_DONE;
-
- //
- // Release the resources once the receive operation completes
- //
- Status = EslTcpPortCloseRxDone4 ( pPort );
- DBG_EXIT_STATUS ( Status );
-}
+ Perform the network specific close operation on the port.
+ This routine performs a cancel operations on the TCPv4 port to
+ shutdown the receive operations on the port.
-/**
- Start the close operation on a TCP4 port, state 1.
+ This routine is called by the ::EslSocketPortCloseTxDone
+ routine after the port completes all of the transmission.
- Closing a port goes through the following states:
- 1. Port close starting - Mark the port as closing and wait for transmission to complete
- 2. Port TX close done - Transmissions complete, close the port and abort the receives
- 3. Port RX close done - Receive operations complete, close the port
- 4. Port closed - Release the port resources
-
- @param [in] pPort Address of the port structure.
- @param [in] bCloseNow Set TRUE to abort active transfers
- @param [in] DebugFlags Flags for debug messages
+ @param [in] pPort Address of an ::ESL_PORT structure.
@retval EFI_SUCCESS The port is closed, not normally returned
- @retval EFI_NOT_READY The port has started the closing process
+ @retval EFI_NOT_READY The port is still closing
@retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
most likely the routine was called already.
**/
EFI_STATUS
-EslTcpPortCloseStart4 (
- IN DT_PORT * pPort,
- IN BOOLEAN bCloseNow,
- IN UINTN DebugFlags
+EslTcp4PortCloseOp (
+ IN ESL_PORT * pPort
)
{
- DT_SOCKET * pSocket;
+ ESL_TCP4_CONTEXT * pTcp4;
+ EFI_TCP4_PROTOCOL * pTcp4Protocol;
EFI_STATUS Status;
DBG_ENTER ( );
//
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
- //
- // Mark the port as closing
+ // Close the configured port
//
- Status = EFI_ALREADY_STARTED;
- pSocket = pPort->pSocket;
- pSocket->errno = EALREADY;
- if ( PORT_STATE_CLOSE_STARTED > pPort->State ) {
-
- //
- // Update the port state
- //
- pPort->State = PORT_STATE_CLOSE_STARTED;
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close State: PORT_STATE_CLOSE_STARTED\r\n",
+ Status = EFI_SUCCESS;
+ pTcp4 = &pPort->Context.Tcp4;
+ pTcp4Protocol = pPort->pProtocol.TCPv4;
+ pTcp4->CloseToken.AbortOnClose = pPort->bCloseNow;
+ Status = pTcp4Protocol->Close ( pTcp4Protocol,
+ &pTcp4->CloseToken );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Port close started\r\n",
pPort ));
- pPort->bCloseNow = bCloseNow;
- pPort->DebugFlags = DebugFlags;
-
- //
- // Determine if transmits are complete
- //
- Status = EslTcpPortCloseTxDone4 ( pPort );
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
+ "ERROR - Close failed on port 0x%08x, Status: %r\r\n",
+ pPort,
+ Status ));
}
//
@@ -2000,562 +1480,224 @@ EslTcpPortCloseStart4 (
/**
- Port close state 3
+ Receive data from a network connection.
- Continue the close operation after the receive is complete.
+ This routine attempts to return buffered data to the caller. The
+ data is removed from the urgent queue if the message flag MSG_OOB
+ is specified, otherwise data is removed from the normal queue.
+ See the \ref ReceiveEngine section.
- @param [in] pPort Address of the port structure.
+ This routine is called by ::EslSocketReceive to handle the network
+ specific receive operation to support SOCK_STREAM and SOCK_SEQPACKET
+ sockets.
- @retval EFI_SUCCESS The port is closed
- @retval EFI_NOT_READY The port is still closing
- @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
- most likely the routine was called already.
+ @param [in] pPort Address of an ::ESL_PORT structure.
-**/
-EFI_STATUS
-EslTcpPortCloseRxDone4 (
- IN DT_PORT * pPort
+ @param [in] pPacket Address of an ::ESL_PACKET structure.
+
+ @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
+
+ @param [in] BufferLength Length of the the buffer
+
+ @param [in] pBuffer Address of a buffer to receive the data.
+
+ @param [in] pDataLength Number of received data bytes in the buffer.
+
+ @param [out] pAddress Network address to receive the remote system address
+
+ @param [out] pSkipBytes Address to receive the number of bytes skipped
+
+ @return Returns the address of the next free byte in the buffer.
+
+ **/
+UINT8 *
+EslTcp4Receive (
+ IN ESL_PORT * pPort,
+ IN ESL_PACKET * pPacket,
+ IN BOOLEAN * pbConsumePacket,
+ IN size_t BufferLength,
+ IN UINT8 * pBuffer,
+ OUT size_t * pDataLength,
+ OUT struct sockaddr * pAddress,
+ OUT size_t * pSkipBytes
)
{
- PORT_STATE PortState;
- DT_TCP4_CONTEXT * pTcp4;
- EFI_STATUS Status;
+ size_t DataLength;
+ struct sockaddr_in * pRemoteAddress;
+ ESL_TCP4_CONTEXT * pTcp4;
DBG_ENTER ( );
//
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
- //
- // Verify that the port is closing
+ // Return the remote system address if requested
//
- Status = EFI_ALREADY_STARTED;
- PortState = pPort->State;
- if (( PORT_STATE_CLOSE_TX_DONE == PortState )
- || ( PORT_STATE_CLOSE_DONE == PortState )) {
+ if ( NULL != pAddress ) {
//
- // Determine if the receive operation is pending
+ // Build the remote address
//
- Status = EFI_NOT_READY;
pTcp4 = &pPort->Context.Tcp4;
- if ( NULL == pTcp4->pReceivePending ) {
- //
- // The receive operation is complete
- // Update the port state
- //
- pPort->State = PORT_STATE_CLOSE_RX_DONE;
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close State: PORT_STATE_CLOSE_RX_DONE\r\n",
- pPort ));
-
- //
- // Determine if the close operation has completed
- //
- if ( PORT_STATE_CLOSE_DONE == PortState ) {
- //
- // The close operation has completed
- // Release the port resources
- //
- Status = EslTcpPortClose4 ( pPort );
- }
- else
- {
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close: Close operation still pending!\r\n",
- pPort ));
- }
- }
- else {
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close: Receive still pending!\r\n",
- pPort ));
- }
+ DEBUG (( DEBUG_RX,
+ "Getting packet remote address: %d.%d.%d.%d:%d\r\n",
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2],
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3],
+ pTcp4->ConfigData.AccessPoint.RemotePort ));
+ pRemoteAddress = (struct sockaddr_in *)pAddress;
+ CopyMem ( &pRemoteAddress->sin_addr,
+ &pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
+ sizeof ( pRemoteAddress->sin_addr ));
+ pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );
}
//
- // Return the operation status
+ // Determine the amount of received data
//
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Port close state 2
-
- Continue the close operation after the transmission is complete.
-
- @param [in] pPort Address of the port structure.
-
- @retval EFI_SUCCESS The port is closed, not normally returned
- @retval EFI_NOT_READY The port is still closing
- @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
- most likely the routine was called already.
-
-**/
-EFI_STATUS
-EslTcpPortCloseTxDone4 (
- IN DT_PORT * pPort
- )
-{
- DT_SOCKET * pSocket;
- DT_TCP4_CONTEXT * pTcp4;
- EFI_TCP4_PROTOCOL * pTcp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
+ DataLength = pPacket->ValidBytes;
+ if ( BufferLength < DataLength ) {
+ DataLength = BufferLength;
+ }
//
- // Verify the socket layer synchronization
+ // Move the data into the buffer
//
- VERIFY_TPL ( TPL_SOCKETS );
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",
+ pPort,
+ pPacket,
+ pBuffer,
+ DataLength ));
+ CopyMem ( pBuffer, pPacket->pBuffer, DataLength );
//
- // All transmissions are complete or must be stopped
- // Mark the port as TX complete
+ // Determine if the data is being read
//
- Status = EFI_ALREADY_STARTED;
- if ( PORT_STATE_CLOSE_STARTED == pPort->State ) {
+ if ( *pbConsumePacket ) {
//
- // Verify that the transmissions are complete
+ // Account for the bytes consumed
//
- pSocket = pPort->pSocket;
- if ( pPort->bCloseNow
- || ( EFI_SUCCESS != pSocket->TxError )
- || (( 0 == pSocket->TxOobBytes )
- && ( 0 == pSocket->TxBytes ))) {
- //
- // Start the close operation on the port
- //
- pTcp4 = &pPort->Context.Tcp4;
- pTcp4->CloseToken.AbortOnClose = FALSE;
- pTcp4Protocol = pTcp4->pProtocol;
- if ( !pTcp4->bConfigured ) {
- //
- // Skip the close operation since the port is not
- // configured
- //
- // Update the port state
- //
- pPort->State = PORT_STATE_CLOSE_DONE;
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close State: PORT_STATE_CLOSE_DONE\r\n",
- pPort ));
- Status = EFI_SUCCESS;
- }
- else {
- //
- // Close the configured port
- //
- Status = pTcp4Protocol->Close ( pTcp4Protocol,
- &pTcp4->CloseToken );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port close started\r\n",
- pPort ));
-
- //
- // Update the port state
- //
- pPort->State = PORT_STATE_CLOSE_TX_DONE;
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close State: PORT_STATE_CLOSE_TX_DONE\r\n",
- pPort ));
- }
- else {
- DEBUG (( DEBUG_ERROR | pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
- "ERROR - Close failed on port 0x%08x, Status: %r\r\n",
- pPort,
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
+ pPacket->pBuffer += DataLength;
+ pPacket->ValidBytes -= DataLength;
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port account for 0x%08x bytes\r\n",
+ pPort,
+ DataLength ));
+ //
+ // Determine if the entire packet was consumed
+ //
+ if (( 0 == pPacket->ValidBytes )
+ || ( SOCK_STREAM != pPort->pSocket->Type )) {
//
- // Determine if the receive operation is pending
+ // All done with this packet
+ // Account for any discarded data
//
- if ( !EFI_ERROR ( Status )) {
- Status = EslTcpPortCloseRxDone4 ( pPort );
- }
+ *pSkipBytes = pPacket->ValidBytes;
}
- else {
+ else
+ {
//
- // Transmissions are still active, exit
+ // More data to consume later
//
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Port Close: Transmits are still pending!\r\n",
- pPort ));
- Status = EFI_NOT_READY;
- pSocket->errno = EAGAIN;
+ *pbConsumePacket = FALSE;
}
}
//
- // Return the operation status
+ // Return the data length and the buffer address
//
- DBG_EXIT_STATUS ( Status );
- return Status;
+ *pDataLength = DataLength;
+ DBG_EXIT_HEX ( pBuffer );
+ return pBuffer;
}
/**
- Receive data from a network connection.
-
+ Get the remote socket address.
- @param [in] pSocket Address of a DT_SOCKET structure
-
- @param [in] Flags Message control flags
-
- @param [in] BufferLength Length of the the buffer
-
- @param [in] pBuffer Address of a buffer to receive the data.
-
- @param [in] pDataLength Number of received data bytes in the buffer.
+ This routine returns the address of the remote connection point
+ associated with the SOCK_STREAM or SOCK_SEQPACKET socket.
- @param [out] pAddress Network address to receive the remote system address
+ This routine is called by ::EslSocketGetPeerAddress to detemine
+ the TCPv4 address and por number associated with the network adapter.
- @param [in,out] pAddressLength Length of the remote network address structure
+ @param [in] pPort Address of an ::ESL_PORT structure.
- @retval EFI_SUCCESS - Socket data successfully received
+ @param [out] pAddress Network address to receive the remote system address
- **/
-EFI_STATUS
-EslTcpReceive4 (
- IN DT_SOCKET * pSocket,
- IN INT32 Flags,
- IN size_t BufferLength,
- IN UINT8 * pBuffer,
- OUT size_t * pDataLength,
- OUT struct sockaddr * pAddress,
- IN OUT socklen_t * pAddressLength
+**/
+VOID
+EslTcp4RemoteAddressGet (
+ IN ESL_PORT * pPort,
+ OUT struct sockaddr * pAddress
)
{
- socklen_t AddressLength;
- size_t BytesToCopy;
- in_addr_t IpAddress;
- size_t LengthInBytes;
- DT_PACKET * pPacket;
- DT_PORT * pPort;
- DT_PACKET ** ppQueueHead;
- DT_PACKET ** ppQueueTail;
struct sockaddr_in * pRemoteAddress;
- size_t * pRxDataBytes;
- DT_TCP4_CONTEXT * pTcp4;
- struct sockaddr_in RemoteAddress;
- EFI_STATUS Status;
+ ESL_TCP4_CONTEXT * pTcp4;
DBG_ENTER ( );
//
- // Assume failure
- //
- Status = EFI_UNSUPPORTED;
- pSocket->errno = ENOTCONN;
-
- //
- // Verify that the socket is connected
+ // Return the remote address
//
- if (( SOCKET_STATE_CONNECTED == pSocket->State )
- || ( PORT_STATE_RX_ERROR == pSocket->State )) {
- //
- // Locate the port
- //
- pPort = pSocket->pPortList;
- if ( NULL != pPort ) {
- //
- // Determine the queue head
- //
- pTcp4 = &pPort->Context.Tcp4;
- if ( 0 != ( Flags & MSG_OOB )) {
- ppQueueHead = &pSocket->pRxOobPacketListHead;
- ppQueueTail = &pSocket->pRxOobPacketListTail;
- pRxDataBytes = &pSocket->RxOobBytes;
- }
- else {
- ppQueueHead = &pSocket->pRxPacketListHead;
- ppQueueTail = &pSocket->pRxPacketListTail;
- pRxDataBytes = &pSocket->RxBytes;
- }
-
- //
- // Determine if there is any data on the queue
- //
- pPacket = *ppQueueHead;
- if ( NULL != pPacket ) {
- //
- // Validate the return address parameters
- //
- if (( NULL == pAddress ) || ( NULL != pAddressLength )) {
- //
- // Return the remote system address if requested
- //
- if ( NULL != pAddress ) {
- //
- // Build the remote address
- //
- ZeroMem ( &RemoteAddress, sizeof ( RemoteAddress ));
- RemoteAddress.sin_len = sizeof ( RemoteAddress );
- RemoteAddress.sin_family = AF_INET;
- IpAddress = pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3];
- IpAddress <<= 8;
- IpAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2];
- IpAddress <<= 8;
- IpAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1];
- IpAddress <<= 8;
- IpAddress |= pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0];
- RemoteAddress.sin_addr.s_addr = IpAddress;
- RemoteAddress.sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );
-
- //
- // Copy the address
- //
- pRemoteAddress = (struct sockaddr_in *)pAddress;
- AddressLength = sizeof ( *pRemoteAddress );
- if ( AddressLength > *pAddressLength ) {
- AddressLength = *pAddressLength;
- }
- CopyMem ( pRemoteAddress,
- &RemoteAddress,
- AddressLength );
-
- //
- // Update the address length
- //
- *pAddressLength = AddressLength;
- }
-
- //
- // Copy the received data
- //
- LengthInBytes = 0;
- do {
- //
- // Determine the amount of received data
- //
- BytesToCopy = pPacket->Op.Tcp4Rx.ValidBytes;
- if (( BufferLength - LengthInBytes ) < BytesToCopy ) {
- BytesToCopy = BufferLength - LengthInBytes;
- }
- LengthInBytes += BytesToCopy;
-
- //
- // Move the data into the buffer
- //
- DEBUG (( DEBUG_RX,
- "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",
- pPort,
- pPacket,
- pBuffer,
- BytesToCopy ));
- CopyMem ( pBuffer, pPacket->Op.Tcp4Rx.pBuffer, BytesToCopy );
-
- //
- // Determine if the data is being read
- //
- if ( 0 == ( Flags & MSG_PEEK )) {
- //
- // Account for the bytes consumed
- //
- pPacket->Op.Tcp4Rx.pBuffer += BytesToCopy;
- pPacket->Op.Tcp4Rx.ValidBytes -= BytesToCopy;
- *pRxDataBytes -= BytesToCopy;
- DEBUG (( DEBUG_RX,
- "0x%08x: Port account for 0x%08x bytes\r\n",
- pPort,
- BytesToCopy ));
-
- //
- // Determine if the entire packet was consumed
- //
- if (( 0 == pPacket->Op.Tcp4Rx.ValidBytes )
- || ( SOCK_STREAM != pSocket->Type )) {
- //
- // All done with this packet
- // Account for any discarded data
- //
- *pRxDataBytes -= pPacket->Op.Tcp4Rx.ValidBytes;
- if ( 0 != pPacket->Op.Tcp4Rx.ValidBytes ) {
- DEBUG (( DEBUG_RX,
- "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n",
- pPort,
- pPacket->Op.Tcp4Rx.ValidBytes ));
- }
-
- //
- // Remove this packet from the queue
- //
- *ppQueueHead = pPacket->pNext;
- if ( NULL == *ppQueueHead ) {
- *ppQueueTail = NULL;
- }
-
- //
- // Move the packet to the free queue
- //
- pPacket->pNext = pSocket->pRxFree;
- pSocket->pRxFree = pPacket;
- DEBUG (( DEBUG_RX,
- "0x%08x: Port freeing packet 0x%08x\r\n",
- pPort,
- pPacket ));
-
- //
- // Restart this receive operation if necessary
- //
- if (( NULL == pTcp4->pReceivePending )
- && ( MAX_RX_DATA > pSocket->RxBytes )) {
- EslTcpRxStart4 ( pPort );
- }
- }
- }
-
- //
- // Get the next packet
- //
- pPacket = *ppQueueHead;
- } while (( SOCK_STREAM == pSocket->Type )
- && ( NULL != pPacket )
- && ( 0 == ( Flags & MSG_PEEK ))
- && ( BufferLength > LengthInBytes ));
+ pTcp4 = &pPort->Context.Tcp4;
+ pRemoteAddress = (struct sockaddr_in *)pAddress;
+ pRemoteAddress->sin_family = AF_INET;
+ pRemoteAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.RemotePort );
+ CopyMem ( &pRemoteAddress->sin_addr,
+ &pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0],
+ sizeof ( pRemoteAddress->sin_addr ));
- //
- // Return the data length
- //
- *pDataLength = LengthInBytes;
+ DBG_EXIT ( );
+}
- //
- // Successful operation
- //
- Status = EFI_SUCCESS;
- pSocket->errno = 0;
- }
- else {
- //
- // Bad return address pointer and length
- //
- Status = EFI_INVALID_PARAMETER;
- pSocket->errno = EINVAL;
- }
- }
- else {
- //
- // The queue is empty
- // Determine if it is time to return the receive error
- //
- if ( EFI_ERROR ( pSocket->RxError )
- && ( NULL == pSocket->pRxPacketListHead )
- && ( NULL == pSocket->pRxOobPacketListHead )) {
- Status = pSocket->RxError;
- pSocket->RxError = EFI_SUCCESS;
- switch ( Status ) {
- default:
- pSocket->errno = EIO;
- break;
-
- case EFI_CONNECTION_FIN:
- //
- // Continue to return zero bytes received when the
- // peer has successfully closed the connection
- //
- pSocket->RxError = EFI_CONNECTION_FIN;
- *pDataLength = 0;
- pSocket->errno = 0;
- Status = EFI_SUCCESS;
- break;
- case EFI_CONNECTION_REFUSED:
- pSocket->errno = ECONNREFUSED;
- break;
+/**
+ Set the remote address
- case EFI_CONNECTION_RESET:
- pSocket->errno = ECONNRESET;
- break;
+ This routine sets the remote address in the port.
- case EFI_HOST_UNREACHABLE:
- pSocket->errno = EHOSTUNREACH;
- break;
-
- case EFI_NETWORK_UNREACHABLE:
- pSocket->errno = ENETUNREACH;
- break;
-
- case EFI_PORT_UNREACHABLE:
- pSocket->errno = EPROTONOSUPPORT;
- break;
-
- case EFI_PROTOCOL_UNREACHABLE:
- pSocket->errno = ENOPROTOOPT;
- break;
- }
- }
- else {
- Status = EFI_NOT_READY;
- pSocket->errno = EAGAIN;
- }
- }
- }
- }
+ This routine is called by ::EslSocketConnect to specify the
+ remote network address.
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
+ @param [in] pPort Address of an ::ESL_PORT structure.
+ @param [in] pSockAddr Network address of the remote system.
-/**
- Cancel the receive operations
+ @param [in] SockAddrLength Length in bytes of the network address.
- @param [in] pSocket Address of a DT_SOCKET structure
-
- @retval EFI_SUCCESS - The cancel was successful
+ @retval EFI_SUCCESS The operation was successful
**/
EFI_STATUS
-EslTcpRxCancel4 (
- IN DT_SOCKET * pSocket
+EslTcp4RemoteAddressSet (
+ IN ESL_PORT * pPort,
+ IN CONST struct sockaddr * pSockAddr,
+ IN socklen_t SockAddrLength
)
{
- DT_PACKET * pPacket;
- DT_PORT * pPort;
- DT_TCP4_CONTEXT * pTcp4;
- EFI_TCP4_PROTOCOL * pTcp4Protocol;
+ CONST struct sockaddr_in * pRemoteAddress;
+ ESL_TCP4_CONTEXT * pTcp4;
EFI_STATUS Status;
DBG_ENTER ( );
//
- // Assume failure
- //
- Status = EFI_NOT_FOUND;
-
+ // Set the remote address
//
- // Locate the port
- //
- pPort = pSocket->pPortList;
- if ( NULL != pPort ) {
- //
- // Determine if a receive is pending
- //
- pTcp4 = &pPort->Context.Tcp4;
- pPacket = pTcp4->pReceivePending;
- if ( NULL != pPacket ) {
- //
- // Attempt to cancel the receive operation
- //
- pTcp4Protocol = pTcp4->pProtocol;
- Status = pTcp4Protocol->Cancel ( pTcp4Protocol,
- &pTcp4->RxToken.CompletionToken );
- if ( EFI_NOT_FOUND == Status ) {
- //
- // The receive is complete
- //
- Status = EFI_SUCCESS;
- }
- }
+ pTcp4 = &pPort->Context.Tcp4;
+ pRemoteAddress = (struct sockaddr_in *)pSockAddr;
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );
+ pTcp4->ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );
+ pTcp4->ConfigData.AccessPoint.RemotePort = SwapBytes16 ( pRemoteAddress->sin_port );
+ Status = EFI_SUCCESS;
+ if ( INADDR_BROADCAST == pRemoteAddress->sin_addr.s_addr ) {
+ DEBUG (( DEBUG_CONNECT,
+ "ERROR - Invalid remote address\r\n" ));
+ Status = EFI_INVALID_PARAMETER;
+ pPort->pSocket->errno = EAFNOSUPPORT;
}
//
@@ -2569,321 +1711,107 @@ EslTcpRxCancel4 (
/**
Process the receive completion
+ This routine queues the data in FIFO order in either the urgent
+ or normal data queues depending upon the type of data received.
+ See the \ref ReceiveEngine section.
+
+ This routine is called by the TCPv4 driver when some data is
+ received.
+
Buffer the data that was just received.
- @param Event The receive completion event
+ @param [in] Event The receive completion event
- @param pPort The DT_PORT structure address
+ @param [in] pIo Address of an ::ESL_IO_MGMT structure
**/
VOID
-EslTcpRxComplete4 (
+EslTcp4RxComplete (
IN EFI_EVENT Event,
- IN DT_PORT * pPort
+ IN ESL_IO_MGMT * pIo
)
{
BOOLEAN bUrgent;
size_t LengthInBytes;
- DT_PACKET * pPacket;
- DT_PACKET * pPrevious;
- DT_SOCKET * pSocket;
- DT_TCP4_CONTEXT * pTcp4;
+ ESL_PACKET * pPacket;
EFI_STATUS Status;
DBG_ENTER ( );
//
- // Mark this receive complete
+ // Get the operation status.
//
- pTcp4 = &pPort->Context.Tcp4;
- pPacket = pTcp4->pReceivePending;
- pTcp4->pReceivePending = NULL;
+ Status = pIo->Token.Tcp4Rx.CompletionToken.Status;
//
- // Determine if this receive was successful
+ // +--------------------+ +---------------------------+
+ // | ESL_IO_MGMT | | ESL_PACKET |
+ // | | | |
+ // | +---------------+ +-----------------------+ |
+ // | | Token | | EFI_TCP4_RECEIVE_DATA | |
+ // | | RxData --> | | |
+ // | | | +-----------------------+---+
+ // | | Event | | Data Buffer |
+ // +----+---------------+ | |
+ // | |
+ // +---------------------------+
//
- pSocket = pPort->pSocket;
- Status = pTcp4->RxToken.CompletionToken.Status;
- if (( !EFI_ERROR ( Status )) && ( !pSocket->bRxDisable )) {
- //
- // Set the buffer size and address
- //
- pPacket->Op.Tcp4Rx.pBuffer = pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer;
- LengthInBytes = pPacket->Op.Tcp4Rx.RxData.DataLength;
- pPacket->Op.Tcp4Rx.ValidBytes = LengthInBytes;
- pPacket->pNext = NULL;
-
- //
- // Queue this packet
- //
- bUrgent = pPacket->Op.Tcp4Rx.RxData.UrgentFlag;
- if ( bUrgent ) {
- //
- // Add packet to the urgent list
- //
- pPrevious = pSocket->pRxOobPacketListTail;
- if ( NULL == pPrevious ) {
- pSocket->pRxOobPacketListHead = pPacket;
- }
- else {
- pPrevious->pNext = pPacket;
- }
- pSocket->pRxOobPacketListTail = pPacket;
-
- //
- // Account for the urgent data
- //
- pSocket->RxOobBytes += LengthInBytes;
- }
- else {
- //
- // Add packet to the normal list
- //
- pPrevious = pSocket->pRxPacketListTail;
- if ( NULL == pPrevious ) {
- pSocket->pRxPacketListHead = pPacket;
- }
- else {
- pPrevious->pNext = pPacket;
- }
- pSocket->pRxPacketListTail = pPacket;
-
- //
- // Account for the normal data
- //
- pSocket->RxBytes += LengthInBytes;
- }
-
- //
- // Log the received data
- //
- DEBUG (( DEBUG_RX | DEBUG_INFO,
- "0x%08x: Packet queued on port 0x%08x with 0x%08x bytes of %s data\r\n",
- pPacket,
- pPort,
- LengthInBytes,
- bUrgent ? L"urgent" : L"normal" ));
-
- //
- // Attempt to restart this receive operation
- //
- if ( pSocket->MaxRxBuf > pSocket->RxBytes ) {
- EslTcpRxStart4 ( pPort );
- }
- else {
- DEBUG (( DEBUG_RX,
- "0x%08x: Port RX suspended, 0x%08x bytes queued\r\n",
- pPort,
- pSocket->RxBytes ));
- }
- }
- else
- {
- DEBUG (( DEBUG_RX | DEBUG_INFO,
- "ERROR - Receiving packet 0x%08x, on port 0x%08x, Status:%r\r\n",
- pPacket,
- pPort,
- Status ));
-
- //
- // Receive error, free the packet save the error
- //
- EslSocketPacketFree ( pPacket, DEBUG_RX );
- if ( !EFI_ERROR ( pSocket->RxError )) {
- pSocket->RxError = Status;
- }
-
- //
- // Update the port state
- //
- if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {
- EslTcpPortCloseRxDone4 ( pPort );
- }
- else {
- if ( EFI_ERROR ( Status )) {
- pPort->State = PORT_STATE_RX_ERROR;
- }
- }
- }
-
- DBG_EXIT ( );
-}
-
-
-/**
- Start a receive operation
-
- @param [in] pPort Address of the DT_PORT structure.
-
- **/
-VOID
-EslTcpRxStart4 (
- IN DT_PORT * pPort
- )
-{
- size_t LengthInBytes;
- DT_PACKET * pPacket;
- DT_SOCKET * pSocket;
- DT_TCP4_CONTEXT * pTcp4;
- EFI_TCP4_PROTOCOL * pTcp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
//
- // Determine if a receive is already pending
+ // Duplicate the buffer address and length for use by the
+ // buffer handling code in EslTcp4Receive. These fields are
+ // used when a partial read is done of the data from the
+ // packet.
//
- Status = EFI_SUCCESS;
- pPacket = NULL;
- pSocket = pPort->pSocket;
- pTcp4 = &pPort->Context.Tcp4;
- if ( !EFI_ERROR ( pPort->pSocket->RxError )) {
- if (( NULL == pTcp4->pReceivePending )
- && ( PORT_STATE_CLOSE_STARTED > pPort->State )) {
- //
- // Determine if there are any free packets
- //
- pPacket = pSocket->pRxFree;
- LengthInBytes = sizeof ( pPacket->Op.Tcp4Rx.Buffer );
- if ( NULL != pPacket ) {
- //
- // Remove this packet from the free list
- //
- pSocket->pRxFree = pPacket->pNext;
- DEBUG (( DEBUG_RX,
- "0x%08x: Port removed packet 0x%08x from free list\r\n",
- pPort,
- pPacket ));
- }
- else {
- //
- // Allocate a packet structure
- //
- Status = EslSocketPacketAllocate ( &pPacket,
- sizeof ( pPacket->Op.Tcp4Rx ),
- DEBUG_RX );
- if ( EFI_ERROR ( Status )) {
- pPacket = NULL;
- DEBUG (( DEBUG_ERROR | DEBUG_RX,
- "0x%08x: Port failed to allocate RX packet, Status: %r\r\n",
- pPort,
- Status ));
- }
- }
-
- //
- // Determine if a packet is available
- //
- if ( NULL != pPacket ) {
- //
- // Initialize the buffer for receive
- //
- pTcp4->RxToken.Packet.RxData = &pPacket->Op.Tcp4Rx.RxData;
- pPacket->Op.Tcp4Rx.RxData.DataLength = (UINT32) LengthInBytes;
- pPacket->Op.Tcp4Rx.RxData.FragmentCount = 1;
- pPacket->Op.Tcp4Rx.RxData.FragmentTable [0].FragmentLength = (UINT32) LengthInBytes;
- pPacket->Op.Tcp4Rx.RxData.FragmentTable [0].FragmentBuffer = &pPacket->Op.Tcp4Rx.Buffer [0];
- pTcp4->pReceivePending = pPacket;
+ pPacket = pIo->pPacket;
+ pPacket->pBuffer = pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer;
+ LengthInBytes = pPacket->Op.Tcp4Rx.RxData.DataLength;
+ pPacket->ValidBytes = LengthInBytes;
- //
- // Start the receive on the packet
- //
- pTcp4Protocol = pTcp4->pProtocol;
- Status = pTcp4Protocol->Receive ( pTcp4Protocol,
- &pTcp4->RxToken );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_RX | DEBUG_INFO,
- "0x%08x: Packet receive pending on port 0x%08x\r\n",
- pPacket,
- pPort ));
- }
- else {
- DEBUG (( DEBUG_RX | DEBUG_INFO,
- "ERROR - Failed to post a receive on port 0x%08x, Status: %r\r\n",
- pPort,
- Status ));
- pTcp4->pReceivePending = NULL;
- if ( !EFI_ERROR ( pSocket->RxError )) {
- //
- // Save the error status
- //
- pSocket->RxError = Status;
- }
- }
- }
- }
- }
+ //
+ // Get the data type so that it may be linked to the
+ // correct receive buffer list on the ESL_SOCKET structure
+ //
+ bUrgent = pPacket->Op.Tcp4Rx.RxData.UrgentFlag;
+ //
+ // Complete this request
+ //
+ EslSocketRxComplete ( pIo, Status, LengthInBytes, bUrgent );
DBG_EXIT ( );
}
/**
- Shutdown the TCP4 service.
+ Start a receive operation
- This routine undoes the work performed by ::TcpInitialize4.
+ This routine posts a receive buffer to the TCPv4 driver.
+ See the \ref ReceiveEngine section.
- @param [in] pService DT_SERVICE structure address
+ This support routine is called by EslSocketRxStart.
-**/
+ @param [in] pPort Address of an ::ESL_PORT structure.
+ @param [in] pIo Address of an ::ESL_IO_MGMT structure.
+
+ **/
VOID
-EFIAPI
-EslTcpShutdown4 (
- IN DT_SERVICE * pService
+EslTcp4RxStart (
+ IN ESL_PORT * pPort,
+ IN ESL_IO_MGMT * pIo
)
{
- DT_LAYER * pLayer;
- DT_PORT * pPort;
- DT_SERVICE * pPreviousService;
+ ESL_PACKET * pPacket;
DBG_ENTER ( );
//
- // Verify the socket layer synchronization
- //
- VERIFY_TPL ( TPL_SOCKETS );
-
- //
- // Walk the list of ports
- //
- do {
- pPort = pService->pPortList;
- if ( NULL != pPort ) {
- //
- // Remove the port from the port list
- //
- pService->pPortList = pPort->pLinkService;
-
- //
- // Close the port
- // TODO: Fix this
- //
-// pPort->pfnClosePort ( pPort, DEBUG_LISTEN | DEBUG_CONNECTION );
- }
- } while ( NULL != pPort );
-
- //
- // Remove the service from the service list
+ // Initialize the buffer for receive
//
- pLayer = &mEslLayer;
- pPreviousService = pLayer->pTcp4List;
- if ( pService == pPreviousService ) {
- //
- // Remove the service from the beginning of the list
- //
- pLayer->pTcp4List = pService->pNext;
- }
- else {
- //
- // Remove the service from the middle of the list
- //
- while ( NULL != pPreviousService ) {
- if ( pService == pPreviousService->pNext ) {
- pPreviousService->pNext = pService->pNext;
- break;
- }
- }
- }
+ pPacket = pIo->pPacket;
+ pIo->Token.Tcp4Rx.Packet.RxData = &pPacket->Op.Tcp4Rx.RxData;
+ pPacket->Op.Tcp4Rx.RxData.DataLength = sizeof ( pPacket->Op.Tcp4Rx.Buffer );
+ pPacket->Op.Tcp4Rx.RxData.FragmentCount = 1;
+ pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentLength = pPacket->Op.Tcp4Rx.RxData.DataLength;
+ pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Tcp4Rx.Buffer[0];
DBG_EXIT ( );
}
@@ -2892,16 +1820,21 @@ EslTcpShutdown4 (
/**
Determine if the socket is configured.
+ This routine uses the flag ESL_SOCKET::bConfigured to determine
+ if the network layer's configuration routine has been called.
+
+ This routine is called by EslSocketIsConfigured to verify
+ that the socket has been configured.
+
+ @param [in] pSocket Address of an ::ESL_SOCKET structure.
- @param [in] pSocket Address of a DT_SOCKET structure
-
@retval EFI_SUCCESS - The port is connected
@retval EFI_NOT_STARTED - The port is not connected
**/
EFI_STATUS
- EslTcpSocketIsConfigured4 (
- IN DT_SOCKET * pSocket
+ EslTcp4SocketIsConfigured (
+ IN ESL_SOCKET * pSocket
)
{
EFI_STATUS Status;
@@ -2924,22 +1857,22 @@ EslTcpShutdown4 (
/**
Buffer data for transmission over a network connection.
- This routine is called by the socket layer API to buffer
- data for transmission. When necessary, this routine will
- start the transmit engine that performs the data transmission
- on the network connection.
+ This routine buffers data for the transmit engine in one of two
+ queues, one for urgent (out-of-band) data and the other for normal
+ data. The urgent data is provided to TCP as soon as it is available,
+ allowing the TCP layer to schedule transmission of the urgent data
+ between packets of normal data.
- The transmit engine uses two queues, one for urgent (out-of-band)
- data and the other for normal data. The urgent data is provided
- to TCP as soon as it is available, allowing the TCP layer to
- schedule transmission of the urgent data between packets of normal
- data.
+ This routine is called by ::EslSocketTransmit to buffer
+ data for transmission. When the \ref TransmitEngine has resources,
+ this routine will start the transmission of the next buffer on
+ the network connection.
Transmission errors are returned during the next transmission or
during the close operation. Only buffering errors are returned
during the current transmission attempt.
- @param [in] pSocket Address of a DT_SOCKET structure
+ @param [in] pSocket Address of an ::ESL_SOCKET structure
@param [in] Flags Message control flags
@@ -2949,27 +1882,34 @@ EslTcpShutdown4 (
@param [in] pDataLength Number of received data bytes in the buffer.
+ @param [in] pAddress Network address of the remote system address
+
+ @param [in] AddressLength Length of the remote network address structure
+
@retval EFI_SUCCESS - Socket data successfully buffered
**/
EFI_STATUS
-EslTcpTxBuffer4 (
- IN DT_SOCKET * pSocket,
+EslTcp4TxBuffer (
+ IN ESL_SOCKET * pSocket,
IN int Flags,
IN size_t BufferLength,
IN CONST UINT8 * pBuffer,
- OUT size_t * pDataLength
+ OUT size_t * pDataLength,
+ IN const struct sockaddr * pAddress,
+ IN socklen_t AddressLength
)
{
BOOLEAN bUrgent;
- DT_PACKET * pPacket;
- DT_PACKET * pPreviousPacket;
- DT_PACKET ** ppPacket;
- DT_PACKET ** ppQueueHead;
- DT_PACKET ** ppQueueTail;
- DT_PORT * pPort;
- DT_TCP4_CONTEXT * pTcp4;
- EFI_TCP4_IO_TOKEN * pToken;
+ BOOLEAN bUrgentQueue;
+ ESL_PACKET * pPacket;
+ ESL_IO_MGMT ** ppActive;
+ ESL_IO_MGMT ** ppFree;
+ ESL_PORT * pPort;
+ ESL_PACKET ** ppQueueHead;
+ ESL_PACKET ** ppQueueTail;
+ ESL_PACKET * pPreviousPacket;
+ ESL_TCP4_CONTEXT * pTcp4;
size_t * pTxBytes;
EFI_TCP4_TRANSMIT_DATA * pTxData;
EFI_STATUS Status;
@@ -2982,7 +1922,7 @@ EslTcpTxBuffer4 (
//
Status = EFI_UNSUPPORTED;
pSocket->errno = ENOTCONN;
- * pDataLength = 0;
+ *pDataLength = 0;
//
// Verify that the socket is connected
@@ -2998,18 +1938,21 @@ EslTcpTxBuffer4 (
//
pTcp4 = &pPort->Context.Tcp4;
bUrgent = (BOOLEAN)( 0 != ( Flags & MSG_OOB ));
- if ( bUrgent ) {
+ bUrgentQueue = bUrgent
+ && ( !pSocket->bOobInLine )
+ && pSocket->pApi->bOobSupported;
+ if ( bUrgentQueue ) {
ppQueueHead = &pSocket->pTxOobPacketListHead;
ppQueueTail = &pSocket->pTxOobPacketListTail;
- ppPacket = &pTcp4->pTxOobPacket;
- pToken = &pTcp4->TxOobToken;
+ ppActive = &pPort->pTxOobActive;
+ ppFree = &pPort->pTxOobFree;
pTxBytes = &pSocket->TxOobBytes;
}
else {
ppQueueHead = &pSocket->pTxPacketListHead;
ppQueueTail = &pSocket->pTxPacketListTail;
- ppPacket = &pTcp4->pTxPacket;
- pToken = &pTcp4->TxToken;
+ ppActive = &pPort->pTxActive;
+ ppFree = &pPort->pTxFree;
pTxBytes = &pSocket->TxBytes;
}
@@ -3018,6 +1961,15 @@ EslTcpTxBuffer4 (
// transmit operation
//
if ( pSocket->MaxTxBuf > *pTxBytes ) {
+ if ( pPort->bTxFlowControl ) {
+ DEBUG (( DEBUG_TX,
+ "TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\r\n0x%08x: pPort, TX flow control released, Max bytes: %d > %d bufferred bytes\r\n",
+ pPort,
+ pSocket->MaxTxBuf,
+ *pTxBytes ));
+ pPort->bTxFlowControl = FALSE;
+ }
+
//
// Attempt to allocate the packet
//
@@ -3025,13 +1977,14 @@ EslTcpTxBuffer4 (
sizeof ( pPacket->Op.Tcp4Tx )
- sizeof ( pPacket->Op.Tcp4Tx.Buffer )
+ BufferLength,
+ 0,
DEBUG_TX );
if ( !EFI_ERROR ( Status )) {
//
// Initialize the transmit operation
//
pTxData = &pPacket->Op.Tcp4Tx.TxData;
- pTxData->Push = TRUE;
+ pTxData->Push = TRUE || bUrgent;
pTxData->Urgent = bUrgent;
pTxData->DataLength = (UINT32) BufferLength;
pTxData->FragmentCount = 1;
@@ -3078,7 +2031,7 @@ EslTcpTxBuffer4 (
DEBUG (( DEBUG_TX,
"0x%08x: Packet on %s transmit list\r\n",
pPacket,
- bUrgent ? L"urgent" : L"normal" ));
+ bUrgentQueue ? L"urgent" : L"normal" ));
//
// Account for the buffered data
@@ -3089,12 +2042,12 @@ EslTcpTxBuffer4 (
//
// Start the transmit engine if it is idle
//
- if ( NULL == *ppPacket ) {
- EslTcpTxStart4 ( pSocket->pPortList,
- pToken,
- ppQueueHead,
- ppQueueTail,
- ppPacket );
+ if ( NULL != *ppFree ) {
+ EslSocketTxStart ( pPort,
+ ppQueueHead,
+ ppQueueTail,
+ ppActive,
+ ppFree );
}
}
else {
@@ -3124,6 +2077,14 @@ EslTcpTxBuffer4 (
}
}
else {
+ if ( !pPort->bTxFlowControl ) {
+ DEBUG (( DEBUG_TX,
+ "0x%08x: pPort, TX flow control applied, Max bytes %d <= %d bufferred bytes\r\nTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\r\n",
+ pPort,
+ pSocket->MaxTxBuf,
+ *pTxBytes ));
+ pPort->bTxFlowControl = TRUE;
+ }
//
// Not enough buffer space available
//
@@ -3144,104 +2105,56 @@ EslTcpTxBuffer4 (
/**
Process the normal data transmit completion
- @param Event The normal transmit completion event
+ This routine use ::EslSocketTxComplete to perform the transmit
+ completion processing for normal data.
- @param pPort The DT_PORT structure address
+ This routine is called by the TCPv4 network layer when a
+ normal data transmit request completes.
+
+ @param [in] Event The normal transmit completion event
+
+ @param [in] pIo The ESL_IO_MGMT structure address
**/
VOID
-EslTcpTxComplete4 (
+EslTcp4TxComplete (
IN EFI_EVENT Event,
- IN DT_PORT * pPort
+ IN ESL_IO_MGMT * pIo
)
{
UINT32 LengthInBytes;
- DT_PACKET * pCurrentPacket;
- DT_PACKET * pNextPacket;
- DT_PACKET * pPacket;
- DT_SOCKET * pSocket;
- DT_TCP4_CONTEXT * pTcp4;
+ ESL_PACKET * pPacket;
+ ESL_PORT * pPort;
+ ESL_SOCKET * pSocket;
EFI_STATUS Status;
DBG_ENTER ( );
-
+
//
// Locate the active transmit packet
//
+ pPacket = pIo->pPacket;
+ pPort = pIo->pPort;
pSocket = pPort->pSocket;
- pTcp4 = &pPort->Context.Tcp4;
- pPacket = pTcp4->pTxPacket;
-
+
//
- // Mark this packet as complete
+ // Get the transmit length and status
//
- pTcp4->pTxPacket = NULL;
LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength;
pSocket->TxBytes -= LengthInBytes;
-
- //
- // Save any transmit error
- //
- Status = pTcp4->TxToken.CompletionToken.Status;
- if ( EFI_ERROR ( Status )) {
- if ( !EFI_ERROR ( pSocket->TxError )) {
- pSocket->TxError = Status;
- }
- DEBUG (( DEBUG_TX | DEBUG_INFO,
- "ERROR - Transmit failure for packet 0x%08x, Status: %r\r\n",
- pPacket,
- Status ));
+ Status = pIo->Token.Tcp4Tx.CompletionToken.Status;
- //
- // Empty the normal transmit list
- //
- pCurrentPacket = pPacket;
- pNextPacket = pSocket->pTxPacketListHead;
- while ( NULL != pNextPacket ) {
- pPacket = pNextPacket;
- pNextPacket = pPacket->pNext;
- EslSocketPacketFree ( pPacket, DEBUG_TX );
- }
- pSocket->pTxPacketListHead = NULL;
- pSocket->pTxPacketListTail = NULL;
- pPacket = pCurrentPacket;
- }
- else
- {
- DEBUG (( DEBUG_TX | DEBUG_INFO,
- "0x%08x: Packet transmitted %d bytes successfully\r\n",
- pPacket,
- LengthInBytes ));
-
- //
- // Verify the transmit engine is still running
- //
- if ( !pPort->bCloseNow ) {
- //
- // Start the next packet transmission
- //
- EslTcpTxStart4 ( pPort,
- &pTcp4->TxToken,
- &pSocket->pTxPacketListHead,
- &pSocket->pTxPacketListTail,
- &pTcp4->pTxPacket );
- }
- }
-
- //
- // Release this packet
//
- EslSocketPacketFree ( pPacket, DEBUG_TX );
-
- //
- // Finish the close operation if necessary
+ // Complete the transmit operation
//
- if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {
- //
- // Indicate that the transmit is complete
- //
- EslTcpPortCloseTxDone4 ( pPort );
- }
+ EslSocketTxComplete ( pIo,
+ LengthInBytes,
+ Status,
+ "Normal ",
+ &pSocket->pTxPacketListHead,
+ &pSocket->pTxPacketListTail,
+ &pPort->pTxActive,
+ &pPort->pTxFree );
DBG_EXIT ( );
}
@@ -3249,23 +2162,27 @@ EslTcpTxComplete4 (
/**
Process the urgent data transmit completion
- @param Event The urgent transmit completion event
+ This routine use ::EslSocketTxComplete to perform the transmit
+ completion processing for urgent data.
- @param pPort The DT_PORT structure address
+ This routine is called by the TCPv4 network layer when a
+ urgent data transmit request completes.
+
+ @param [in] Event The urgent transmit completion event
+
+ @param [in] pIo The ESL_IO_MGMT structure address
**/
VOID
-EslTcpTxOobComplete4 (
+EslTcp4TxOobComplete (
IN EFI_EVENT Event,
- IN DT_PORT * pPort
+ IN ESL_IO_MGMT * pIo
)
{
UINT32 LengthInBytes;
- DT_PACKET * pCurrentPacket;
- DT_PACKET * pNextPacket;
- DT_PACKET * pPacket;
- DT_SOCKET * pSocket;
- DT_TCP4_CONTEXT * pTcp4;
+ ESL_PACKET * pPacket;
+ ESL_PORT * pPort;
+ ESL_SOCKET * pSocket;
EFI_STATUS Status;
DBG_ENTER ( );
@@ -3273,150 +2190,70 @@ EslTcpTxOobComplete4 (
//
// Locate the active transmit packet
//
+ pPacket = pIo->pPacket;
+ pPort = pIo->pPort;
pSocket = pPort->pSocket;
- pTcp4 = &pPort->Context.Tcp4;
- pPacket = pTcp4->pTxOobPacket;
//
- // Mark this packet as complete
+ // Get the transmit length and status
//
- pTcp4->pTxOobPacket = NULL;
LengthInBytes = pPacket->Op.Tcp4Tx.TxData.DataLength;
pSocket->TxOobBytes -= LengthInBytes;
+ Status = pIo->Token.Tcp4Tx.CompletionToken.Status;
//
- // Save any transmit error
- //
- Status = pTcp4->TxOobToken.CompletionToken.Status;
- if ( EFI_ERROR ( Status )) {
- if ( !EFI_ERROR ( Status )) {
- pSocket->TxError = Status;
- }
- DEBUG (( DEBUG_TX | DEBUG_INFO,
- "ERROR - Transmit failure for urgent packet 0x%08x, Status: %r\r\n",
- pPacket,
- Status ));
-
-
- //
- // Empty the OOB transmit list
- //
- pCurrentPacket = pPacket;
- pNextPacket = pSocket->pTxOobPacketListHead;
- while ( NULL != pNextPacket ) {
- pPacket = pNextPacket;
- pNextPacket = pPacket->pNext;
- EslSocketPacketFree ( pPacket, DEBUG_TX );
- }
- pSocket->pTxOobPacketListHead = NULL;
- pSocket->pTxOobPacketListTail = NULL;
- pPacket = pCurrentPacket;
- }
- else
- {
- DEBUG (( DEBUG_TX | DEBUG_INFO,
- "0x%08x: Urgent packet transmitted %d bytes successfully\r\n",
- pPacket,
- LengthInBytes ));
-
- //
- // Verify the transmit engine is still running
- //
- if ( !pPort->bCloseNow ) {
- //
- // Start the next packet transmission
- //
- EslTcpTxStart4 ( pPort,
- &pTcp4->TxOobToken,
- &pSocket->pTxOobPacketListHead,
- &pSocket->pTxOobPacketListTail,
- &pTcp4->pTxOobPacket );
- }
- }
-
- //
- // Release this packet
- //
- EslSocketPacketFree ( pPacket, DEBUG_TX );
-
- //
- // Finish the close operation if necessary
+ // Complete the transmit operation
//
- if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {
- //
- // Indicate that the transmit is complete
- //
- EslTcpPortCloseTxDone4 ( pPort );
- }
+ EslSocketTxComplete ( pIo,
+ LengthInBytes,
+ Status,
+ "Urgent ",
+ &pSocket->pTxOobPacketListHead,
+ &pSocket->pTxOobPacketListTail,
+ &pPort->pTxOobActive,
+ &pPort->pTxOobFree );
DBG_EXIT ( );
}
/**
- Transmit data using a network connection.
-
-
- @param [in] pPort Address of a DT_PORT structure
- @param [in] pToken Address of either the OOB or normal transmit token
- @param [in] ppQueueHead Transmit queue head address
- @param [in] ppQueueTail Transmit queue tail address
- @param [in] ppPacket Active transmit packet address
-
- **/
-VOID
-EslTcpTxStart4 (
- IN DT_PORT * pPort,
- IN EFI_TCP4_IO_TOKEN * pToken,
- IN DT_PACKET ** ppQueueHead,
- IN DT_PACKET ** ppQueueTail,
- IN DT_PACKET ** ppPacket
- )
-{
- DT_PACKET * pNextPacket;
- DT_PACKET * pPacket;
- DT_SOCKET * pSocket;
- EFI_TCP4_PROTOCOL * pTcp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Assume success
- //
- Status = EFI_SUCCESS;
-
- //
- // Get the packet from the queue head
- //
- pPacket = *ppQueueHead;
- if ( NULL != pPacket ) {
- //
- // Remove the packet from the queue
- //
- pNextPacket = pPacket->pNext;
- *ppQueueHead = pNextPacket;
- if ( NULL == pNextPacket ) {
- *ppQueueTail = NULL;
- }
-
- //
- // Set the packet as active
- //
- *ppPacket = pPacket;
-
- //
- // Start the transmit operation
- //
- pTcp4Protocol = pPort->Context.Tcp4.pProtocol;
- pToken->Packet.TxData = &pPacket->Op.Tcp4Tx.TxData;
- Status = pTcp4Protocol->Transmit ( pTcp4Protocol, pToken );
- if ( EFI_ERROR ( Status )) {
- pSocket = pPort->pSocket;
- if ( EFI_SUCCESS == pSocket->TxError ) {
- pSocket->TxError = Status;
- }
- }
- }
-
- DBG_EXIT ( );
-}
+ Interface between the socket layer and the network specific
+ code that supports SOCK_STREAM and SOCK_SEQPACKET sockets
+ over TCPv4.
+**/
+CONST ESL_PROTOCOL_API cEslTcp4Api = {
+ "TCPv4",
+ IPPROTO_TCP,
+ OFFSET_OF ( ESL_PORT, Context.Tcp4.ConfigData ),
+ OFFSET_OF ( ESL_LAYER, pTcp4List ),
+ OFFSET_OF ( struct sockaddr_in, sin_zero ),
+ sizeof ( struct sockaddr_in ),
+ AF_INET,
+ sizeof (((ESL_PACKET *)0 )->Op.Tcp4Rx ),
+ OFFSET_OF ( ESL_PACKET, Op.Tcp4Rx.Buffer ) - OFFSET_OF ( ESL_PACKET, Op ),
+ OFFSET_OF ( ESL_IO_MGMT, Token.Tcp4Rx.Packet.RxData ),
+ TRUE,
+ EADDRINUSE,
+ EslTcp4Accept,
+ EslTcp4ConnectPoll,
+ EslTcp4ConnectStart,
+ EslTcp4SocketIsConfigured,
+ EslTcp4LocalAddressGet,
+ EslTcp4LocalAddressSet,
+ EslTcp4Listen,
+ NULL, // OptionGet
+ NULL, // OptionSet
+ EslTcp4PacketFree,
+ EslTcp4PortAllocate,
+ EslTcp4PortClose,
+ EslTcp4PortCloseOp,
+ FALSE,
+ EslTcp4Receive,
+ EslTcp4RemoteAddressGet,
+ EslTcp4RemoteAddressSet,
+ EslTcp4RxComplete,
+ EslTcp4RxStart,
+ EslTcp4TxBuffer,
+ EslTcp4TxComplete,
+ EslTcp4TxOobComplete
+};