Import SnpDxe, Tcp4Dxe, Udp4Dxe and MnpDxe.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3416 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
169
MdeModulePkg/Universal/Network/Tcp4Dxe/ComponentName.c
Normal file
169
MdeModulePkg/Universal/Network/Tcp4Dxe/ComponentName.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2007, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
ComponentName.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Tcp4Main.h"
|
||||
|
||||
//
|
||||
// EFI Component Name Functions
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
);
|
||||
|
||||
//
|
||||
// EFI Component Name Protocol
|
||||
//
|
||||
EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName = {
|
||||
TcpComponentNameGetDriverName,
|
||||
TcpComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
static EFI_UNICODE_STRING_TABLE mTcpDriverNameTable[] = {
|
||||
{
|
||||
"eng",
|
||||
L"Tcp Network Service Driver"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Retrieves a Unicode string that is the user readable name of the EFI Driver.
|
||||
|
||||
Arguments:
|
||||
|
||||
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
Language - A pointer to a three character ISO 639-2 language identifier.
|
||||
This is the language of the driver name that that the caller
|
||||
is requesting, and it must match one of the languages
|
||||
specified in SupportedLanguages. The number of languages
|
||||
supported by a driver is up to the driver writer.
|
||||
DriverName - A pointer to the Unicode string to return. This Unicode
|
||||
string is the name of the driver specified by This in the
|
||||
language specified by Language.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCES - The Unicode string for the Driver specified by
|
||||
This and the language specified by Language was
|
||||
returned in DriverName.
|
||||
EFI_INVALID_PARAMETER - Language is NULL.
|
||||
EFI_INVALID_PARAMETER - DriverName is NULL.
|
||||
EFI_UNSUPPORTED - The driver specified by This does not support the
|
||||
language specified by Language.
|
||||
|
||||
--*/
|
||||
{
|
||||
return LookupUnicodeString (
|
||||
Language,
|
||||
gTcp4ComponentName.SupportedLanguages,
|
||||
mTcpDriverNameTable,
|
||||
DriverName
|
||||
);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Retrieves a Unicode string that is the user readable name of the controller
|
||||
that is being managed by an EFI Driver.
|
||||
|
||||
Arguments:
|
||||
|
||||
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
ControllerHandle - The handle of a controller that the driver specified by
|
||||
This is managing. This handle specifies the controller
|
||||
whose name is to be returned.
|
||||
ChildHandle - The handle of the child controller to retrieve the name
|
||||
of. This is an optional parameter that may be NULL.
|
||||
It will be NULL for device drivers. It will also be
|
||||
NULL for a bus drivers that wish to retrieve the name of
|
||||
the bus controller. It will not be NULL for a bus
|
||||
driver that wishes to retrieve the name of a child
|
||||
controller.
|
||||
Language - A pointer to a three character ISO 639-2 language
|
||||
identifier. This is the language of the controller
|
||||
name that that the caller is requesting, and it must
|
||||
match one of the languages specified in supported
|
||||
languages. The number of languages supported by a driver
|
||||
is up to the driver writer.
|
||||
ControllerName - A pointer to the Unicode string to return. This Unicode
|
||||
string is the name of the controller specified by
|
||||
ControllerHandle and ChildHandle in the language
|
||||
specified by Language from the point of view of the
|
||||
driver specified by This.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - The Unicode string for the user readable name in
|
||||
the language specified by Language for the driver
|
||||
specified by This was returned in DriverName.
|
||||
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
|
||||
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid
|
||||
EFI_HANDLE.
|
||||
EFI_INVALID_PARAMETER - Language is NULL.
|
||||
EFI_INVALID_PARAMETER - ControllerName is NULL.
|
||||
EFI_UNSUPPORTED - The driver specified by This is not currently
|
||||
managing the controller specified by
|
||||
ControllerHandle and ChildHandle.
|
||||
EFI_UNSUPPORTED - The driver specified by This does not support the
|
||||
language specified by Language.
|
||||
|
||||
--*/
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
1269
MdeModulePkg/Universal/Network/Tcp4Dxe/SockImpl.c
Normal file
1269
MdeModulePkg/Universal/Network/Tcp4Dxe/SockImpl.c
Normal file
File diff suppressed because it is too large
Load Diff
84
MdeModulePkg/Universal/Network/Tcp4Dxe/SockImpl.h
Normal file
84
MdeModulePkg/Universal/Network/Tcp4Dxe/SockImpl.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
SockImpl.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SOCK_IMPL_H_
|
||||
#define _SOCK_IMPL_H_
|
||||
|
||||
#include "Socket.h"
|
||||
|
||||
#define SOCK_DEBUG_ERROR(PrintArg) NET_DEBUG_ERROR("Sock", PrintArg)
|
||||
#define SOCK_DEBUG_WARN(PrintArg) NET_DEBUG_WARNING("Sock", PrintArg)
|
||||
#define SOCK_DEBUG_TRACE(PrintArg) NET_DEBUG_TRACE("Sock", PrintArg)
|
||||
|
||||
#define SOCK_TRIM_RCV_BUFF(Sock, Len) \
|
||||
(NetbufQueTrim ((Sock)->RcvBuffer.DataQueue, (Len)))
|
||||
|
||||
#define SIGNAL_TOKEN(Token, TokenStatus) \
|
||||
do { \
|
||||
(Token)->Status = (TokenStatus); \
|
||||
gBS->SignalEvent ((Token)->Event); \
|
||||
} while (0)
|
||||
|
||||
#define SOCK_HEADER_SPACE (60 + 60 + 72)
|
||||
|
||||
//
|
||||
// Supporting function for both SockImpl and SockInterface
|
||||
//
|
||||
VOID
|
||||
SockFreeFoo (
|
||||
IN EFI_EVENT Event
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
SockProcessTcpSndData (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *TcpTxData
|
||||
);
|
||||
|
||||
VOID
|
||||
SockSetTcpRxData (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *TcpRxData,
|
||||
IN UINT32 RcvdBytes,
|
||||
IN BOOLEAN IsOOB
|
||||
);
|
||||
|
||||
UINT32
|
||||
SockProcessRcvToken (
|
||||
IN SOCKET *Sock,
|
||||
IN SOCK_IO_TOKEN *RcvToken
|
||||
);
|
||||
|
||||
VOID
|
||||
SockConnFlush (
|
||||
IN SOCKET *Sock
|
||||
);
|
||||
|
||||
SOCKET *
|
||||
SockCreate (
|
||||
IN SOCK_INIT_DATA *SockInitData
|
||||
);
|
||||
|
||||
VOID
|
||||
SockDestroy (
|
||||
IN SOCKET *Sock
|
||||
);
|
||||
|
||||
#endif
|
980
MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c
Normal file
980
MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c
Normal file
@@ -0,0 +1,980 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
SockInterface.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include "SockImpl.h"
|
||||
|
||||
|
||||
/**
|
||||
Check whether the Event is in the List.
|
||||
|
||||
@param List Pointer to the token list to be searched.
|
||||
@param Event The event to be checked.
|
||||
|
||||
@retval BOOLEAN If TRUE, the specific Event exists in the List. If
|
||||
FALSE, the specific Event is not in the List.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
SockTokenExistedInList (
|
||||
IN NET_LIST_ENTRY *List,
|
||||
IN EFI_EVENT Event
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *ListEntry;
|
||||
SOCK_TOKEN *SockToken;
|
||||
|
||||
NET_LIST_FOR_EACH (ListEntry, List) {
|
||||
SockToken = NET_LIST_USER_STRUCT (
|
||||
ListEntry,
|
||||
SOCK_TOKEN,
|
||||
TokenList
|
||||
);
|
||||
|
||||
if (Event == SockToken->Token->Event) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Call SockTokenExistedInList() to check whether the Event is
|
||||
in the related socket's lists.
|
||||
|
||||
@param Sock Pointer to the instance's socket.
|
||||
@param Event The event to be checked.
|
||||
|
||||
@return The specific Event exists in one of socket's lists or not.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
SockTokenExisted (
|
||||
IN SOCKET *Sock,
|
||||
IN EFI_EVENT Event
|
||||
)
|
||||
{
|
||||
|
||||
if (SockTokenExistedInList (&Sock->SndTokenList, Event) ||
|
||||
SockTokenExistedInList (&Sock->ProcessingSndTokenList, Event) ||
|
||||
SockTokenExistedInList (&Sock->RcvTokenList, Event) ||
|
||||
SockTokenExistedInList (&Sock->ListenTokenList, Event)
|
||||
) {
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((Sock->ConnectionToken != NULL) &&
|
||||
(Sock->ConnectionToken->Event == Event)) {
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((Sock->CloseToken != NULL) && (Sock->CloseToken->Event == Event)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Buffer a token into the specific list of socket Sock.
|
||||
|
||||
@param Sock Pointer to the instance's socket.
|
||||
@param List Pointer to the list to store the token.
|
||||
@param Token Pointer to the token to be buffered.
|
||||
@param DataLen The data length of the buffer contained in Token.
|
||||
|
||||
@return Pointer to the token that wraps Token. If NULL, error condition occurred.
|
||||
|
||||
**/
|
||||
SOCK_TOKEN *
|
||||
SockBufferToken (
|
||||
IN SOCKET *Sock,
|
||||
IN NET_LIST_ENTRY *List,
|
||||
IN VOID *Token,
|
||||
IN UINT32 DataLen
|
||||
)
|
||||
{
|
||||
SOCK_TOKEN *SockToken;
|
||||
|
||||
SockToken = NetAllocatePool (sizeof (SOCK_TOKEN));
|
||||
if (NULL == SockToken) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockBufferIOToken: No Memory "
|
||||
"to allocate SockToken\n"));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SockToken->Sock = Sock;
|
||||
SockToken->Token = (SOCK_COMPLETION_TOKEN *) Token;
|
||||
SockToken->RemainDataLen = DataLen;
|
||||
NetListInsertTail (List, &SockToken->TokenList);
|
||||
|
||||
return SockToken;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destory the socket Sock and its associated protocol control block.
|
||||
|
||||
@param Sock The socket to be destroyed.
|
||||
|
||||
@retval EFI_SUCCESS The socket Sock is destroyed successfully.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockDestroyChild (
|
||||
IN SOCKET *Sock
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT (Sock && Sock->ProtoHandler);
|
||||
|
||||
if (Sock->IsDestroyed) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Sock->IsDestroyed = TRUE;
|
||||
|
||||
Status = NET_TRYLOCK (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockDestroyChild: Get the lock to "
|
||||
"access socket failed with %r\n", Status));
|
||||
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
//
|
||||
// force protocol layer to detach the PCB
|
||||
//
|
||||
Status = Sock->ProtoHandler (Sock, SOCK_DETACH, NULL);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockDestroyChild: Protocol detach socket"
|
||||
" failed with %r\n", Status));
|
||||
|
||||
Sock->IsDestroyed = FALSE;
|
||||
} else if (SOCK_IS_CONFIGURED (Sock)) {
|
||||
|
||||
SockConnFlush (Sock);
|
||||
SockSetState (Sock, SO_CLOSED);
|
||||
|
||||
Sock->ConfigureState = SO_UNCONFIGURED;
|
||||
}
|
||||
|
||||
NET_UNLOCK (&(Sock->Lock));
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
SockDestroy (Sock);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create a socket and its associated protocol control block
|
||||
with the intial data SockInitData and protocol specific
|
||||
data ProtoData.
|
||||
|
||||
@param SockInitData Inital data to setting the socket.
|
||||
@param ProtoData Pointer to the protocol specific data.
|
||||
@param Len Length of the protocol specific data.
|
||||
|
||||
@return Pointer to the newly created socket. If NULL, error condition occured.
|
||||
|
||||
**/
|
||||
SOCKET *
|
||||
SockCreateChild (
|
||||
IN SOCK_INIT_DATA *SockInitData,
|
||||
IN VOID *ProtoData,
|
||||
IN UINT32 Len
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT (ProtoData && (Len <= PROTO_RESERVED_LEN));
|
||||
|
||||
//
|
||||
// create a new socket
|
||||
//
|
||||
Sock = SockCreate (SockInitData);
|
||||
if (NULL == Sock) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockCreateChild: No resource to "
|
||||
"create a new socket\n"));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Open the
|
||||
//
|
||||
|
||||
//
|
||||
// copy the protodata into socket
|
||||
//
|
||||
NetCopyMem (Sock->ProtoReserved, ProtoData, Len);
|
||||
|
||||
Status = NET_TRYLOCK (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockCreateChild: Get the lock to "
|
||||
"access socket failed with %r\n", Status));
|
||||
|
||||
SockDestroy (Sock);
|
||||
return NULL;
|
||||
}
|
||||
//
|
||||
// inform the protocol layer to attach the socket
|
||||
// with a new protocol control block
|
||||
//
|
||||
Status = Sock->ProtoHandler (Sock, SOCK_ATTACH, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockCreateChild: Protocol failed to"
|
||||
" attach a socket with %r\n", Status));
|
||||
|
||||
SockDestroy (Sock);
|
||||
Sock = NULL;
|
||||
}
|
||||
|
||||
NET_UNLOCK (&(Sock->Lock));
|
||||
return Sock;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Configure the specific socket Sock using configuration data
|
||||
ConfigData.
|
||||
|
||||
@param Sock Pointer to the socket to be configured.
|
||||
@param ConfigData Pointer to the configuration data.
|
||||
|
||||
@retval EFI_SUCCESS The socket is configured successfully.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
|
||||
socket is already configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockConfigure (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *ConfigData
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = NET_TRYLOCK (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockConfigure: Get the access for "
|
||||
"socket failed with %r", Status));
|
||||
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (SOCK_IS_CONFIGURED (Sock)) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto OnExit;
|
||||
}
|
||||
|
||||
ASSERT (Sock->State == SO_CLOSED);
|
||||
|
||||
Status = Sock->ProtoHandler (Sock, SOCK_CONFIGURE, ConfigData);
|
||||
|
||||
OnExit:
|
||||
NET_UNLOCK (&(Sock->Lock));
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initiate a connection establishment process.
|
||||
|
||||
@param Sock Pointer to the socket to initiate the initate the
|
||||
connection.
|
||||
@param Token Pointer to the token used for the connection
|
||||
operation.
|
||||
|
||||
@retval EFI_SUCCESS The connection is initialized successfully.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
|
||||
socket is closed, or the socket is not configured to
|
||||
be an active one, or the token is already in one of
|
||||
this socket's lists.
|
||||
@retval EFI_NO_MAPPING The IP address configuration operation is not
|
||||
finished.
|
||||
@retval EFI_NOT_STARTED The socket is not configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockConnect (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_EVENT Event;
|
||||
|
||||
Status = NET_TRYLOCK (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockConnect: Get the access for "
|
||||
"socket failed with %r", Status));
|
||||
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (SOCK_IS_NO_MAPPING (Sock)) {
|
||||
Status = EFI_NO_MAPPING;
|
||||
goto OnExit;
|
||||
}
|
||||
|
||||
if (SOCK_IS_UNCONFIGURED (Sock)) {
|
||||
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto OnExit;
|
||||
}
|
||||
|
||||
if (!SOCK_IS_CLOSED (Sock) || !SOCK_IS_CONFIGURED_ACTIVE (Sock)) {
|
||||
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto OnExit;
|
||||
}
|
||||
|
||||
Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
|
||||
|
||||
if (SockTokenExisted (Sock, Event)) {
|
||||
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto OnExit;
|
||||
}
|
||||
|
||||
Sock->ConnectionToken = (SOCK_COMPLETION_TOKEN *) Token;
|
||||
SockSetState (Sock, SO_CONNECTING);
|
||||
Status = Sock->ProtoHandler (Sock, SOCK_CONNECT, NULL);
|
||||
|
||||
OnExit:
|
||||
NET_UNLOCK (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Issue a listen token to get an existed connected network instance
|
||||
or wait for a connection if there is none.
|
||||
|
||||
@param Sock Pointer to the socket to accept connections.
|
||||
@param Token The token to accept a connection.
|
||||
|
||||
@retval EFI_SUCCESS Either a connection is accpeted or the Token is
|
||||
buffered for further acception.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
|
||||
socket is closed, or the socket is not configured to
|
||||
be a passive one, or the token is already in one of
|
||||
this socket's lists.
|
||||
@retval EFI_NO_MAPPING The IP address configuration operation is not
|
||||
finished.
|
||||
@retval EFI_NOT_STARTED The socket is not configured.
|
||||
@retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockAccept (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token
|
||||
)
|
||||
{
|
||||
EFI_TCP4_LISTEN_TOKEN *ListenToken;
|
||||
NET_LIST_ENTRY *ListEntry;
|
||||
EFI_STATUS Status;
|
||||
SOCKET *Socket;
|
||||
EFI_EVENT Event;
|
||||
|
||||
ASSERT (SOCK_STREAM == Sock->Type);
|
||||
|
||||
Status = NET_TRYLOCK (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockAccept: Get the access for socket"
|
||||
" failed with %r", Status));
|
||||
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (SOCK_IS_NO_MAPPING (Sock)) {
|
||||
Status = EFI_NO_MAPPING;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (SOCK_IS_UNCONFIGURED (Sock)) {
|
||||
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (!SOCK_IS_LISTENING (Sock)) {
|
||||
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
|
||||
|
||||
if (SockTokenExisted (Sock, Event)) {
|
||||
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ListenToken = (EFI_TCP4_LISTEN_TOKEN *) Token;
|
||||
|
||||
//
|
||||
// Check if a connection has already in this Sock->ConnectionList
|
||||
//
|
||||
NET_LIST_FOR_EACH (ListEntry, &Sock->ConnectionList) {
|
||||
|
||||
Socket = NET_LIST_USER_STRUCT (ListEntry, SOCKET, ConnectionList);
|
||||
|
||||
if (SOCK_IS_CONNECTED (Socket)) {
|
||||
ListenToken->NewChildHandle = Socket->SockHandle;
|
||||
SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);
|
||||
|
||||
NetListRemoveEntry (ListEntry);
|
||||
|
||||
ASSERT (Socket->Parent);
|
||||
|
||||
Socket->Parent->ConnCnt--;
|
||||
|
||||
SOCK_DEBUG_WARN (("SockAccept: Accept a socket,"
|
||||
"now conncount is %d", Socket->Parent->ConnCnt)
|
||||
);
|
||||
Socket->Parent = NULL;
|
||||
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Buffer this token for latter incoming connection request
|
||||
//
|
||||
if (NULL == SockBufferToken (Sock, &(Sock->ListenTokenList), Token, 0)) {
|
||||
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Exit:
|
||||
NET_UNLOCK (&(Sock->Lock));
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Issue a token with data to the socket to send out.
|
||||
|
||||
@param Sock Pointer to the socket to process the token with
|
||||
data.
|
||||
@param Token The token with data that needs to send out.
|
||||
|
||||
@retval EFI_SUCCESS The token is processed successfully.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
|
||||
socket is closed, or the socket is not in a
|
||||
synchronized state , or the token is already in one
|
||||
of this socket's lists.
|
||||
@retval EFI_NO_MAPPING The IP address configuration operation is not
|
||||
finished.
|
||||
@retval EFI_NOT_STARTED The socket is not configured.
|
||||
@retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockSend (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token
|
||||
)
|
||||
{
|
||||
SOCK_IO_TOKEN *SndToken;
|
||||
EFI_EVENT Event;
|
||||
UINT32 FreeSpace;
|
||||
EFI_TCP4_TRANSMIT_DATA *TxData;
|
||||
EFI_STATUS Status;
|
||||
SOCK_TOKEN *SockToken;
|
||||
UINT32 DataLen;
|
||||
|
||||
ASSERT (SOCK_STREAM == Sock->Type);
|
||||
|
||||
Status = NET_TRYLOCK (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockSend: Get the access for socket"
|
||||
" failed with %r", Status));
|
||||
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (SOCK_IS_NO_MAPPING (Sock)) {
|
||||
Status = EFI_NO_MAPPING;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
SndToken = (SOCK_IO_TOKEN *) Token;
|
||||
TxData = (EFI_TCP4_TRANSMIT_DATA *) SndToken->Packet.TxData;
|
||||
|
||||
if (SOCK_IS_UNCONFIGURED (Sock)) {
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (!(SOCK_IS_CONNECTING (Sock) || SOCK_IS_CONNECTED (Sock))) {
|
||||
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// check if a token is already in the token buffer
|
||||
//
|
||||
Event = SndToken->Token.Event;
|
||||
|
||||
if (SockTokenExisted (Sock, Event)) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
DataLen = TxData->DataLength;
|
||||
|
||||
//
|
||||
// process this sending token now or buffer it only?
|
||||
//
|
||||
FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);
|
||||
|
||||
if ((FreeSpace < Sock->SndBuffer.LowWater) || !SOCK_IS_CONNECTED (Sock)) {
|
||||
|
||||
SockToken = SockBufferToken (
|
||||
Sock,
|
||||
&Sock->SndTokenList,
|
||||
SndToken,
|
||||
DataLen
|
||||
);
|
||||
|
||||
if (NULL == SockToken) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
} else {
|
||||
|
||||
SockToken = SockBufferToken (
|
||||
Sock,
|
||||
&Sock->ProcessingSndTokenList,
|
||||
SndToken,
|
||||
DataLen
|
||||
);
|
||||
|
||||
if (NULL == SockToken) {
|
||||
SOCK_DEBUG_ERROR (("SockSend: Failed to buffer IO token into"
|
||||
" socket processing SndToken List\n", Status));
|
||||
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = SockProcessTcpSndData (Sock, TxData);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
SOCK_DEBUG_ERROR (("SockSend: Failed to process "
|
||||
"Snd Data\n", Status));
|
||||
|
||||
NetListRemoveEntry (&(SockToken->TokenList));
|
||||
NetFreePool (SockToken);
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
NET_UNLOCK (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Issue a token to get data from the socket.
|
||||
|
||||
@param Sock Pointer to the socket to get data from.
|
||||
@param Token The token to store the received data from the
|
||||
socket.
|
||||
|
||||
@retval EFI_SUCCESS The token is processed successfully.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
|
||||
socket is closed, or the socket is not in a
|
||||
synchronized state , or the token is already in one
|
||||
of this socket's lists.
|
||||
@retval EFI_NO_MAPPING The IP address configuration operation is not
|
||||
finished.
|
||||
@retval EFI_NOT_STARTED The socket is not configured.
|
||||
@retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
|
||||
@retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockRcv (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token
|
||||
)
|
||||
{
|
||||
SOCK_IO_TOKEN *RcvToken;
|
||||
UINT32 RcvdBytes;
|
||||
EFI_STATUS Status;
|
||||
EFI_EVENT Event;
|
||||
|
||||
ASSERT (SOCK_STREAM == Sock->Type);
|
||||
|
||||
Status = NET_TRYLOCK (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockRcv: Get the access for socket"
|
||||
" failed with %r", Status));
|
||||
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (SOCK_IS_NO_MAPPING (Sock)) {
|
||||
|
||||
Status = EFI_NO_MAPPING;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (SOCK_IS_UNCONFIGURED (Sock)) {
|
||||
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (!(SOCK_IS_CONNECTED (Sock) || SOCK_IS_CONNECTING (Sock))) {
|
||||
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
RcvToken = (SOCK_IO_TOKEN *) Token;
|
||||
|
||||
//
|
||||
// check if a token is already in the token buffer of this socket
|
||||
//
|
||||
Event = RcvToken->Token.Event;
|
||||
if (SockTokenExisted (Sock, Event)) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
RcvToken = (SOCK_IO_TOKEN *) Token;
|
||||
RcvdBytes = GET_RCV_DATASIZE (Sock);
|
||||
|
||||
//
|
||||
// check whether an error has happened before
|
||||
//
|
||||
if (EFI_ABORTED != Sock->SockError) {
|
||||
|
||||
SIGNAL_TOKEN (&(RcvToken->Token), Sock->SockError);
|
||||
Sock->SockError = EFI_ABORTED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// check whether can not receive and there is no any
|
||||
// data buffered in Sock->RcvBuffer
|
||||
//
|
||||
if (SOCK_IS_NO_MORE_DATA (Sock) && (0 == RcvdBytes)) {
|
||||
|
||||
Status = EFI_CONNECTION_FIN;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (RcvdBytes != 0) {
|
||||
Status = SockProcessRcvToken (Sock, RcvToken);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);
|
||||
} else {
|
||||
|
||||
if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
NET_UNLOCK (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reset the socket and its associated protocol control block.
|
||||
|
||||
@param Sock Pointer to the socket to be flushed.
|
||||
|
||||
@retval EFI_SUCCESS The socket is flushed successfully.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockFlush (
|
||||
IN SOCKET *Sock
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT (SOCK_STREAM == Sock->Type);
|
||||
|
||||
Status = NET_TRYLOCK (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockFlush: Get the access for socket"
|
||||
" failed with %r", Status));
|
||||
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (!SOCK_IS_CONFIGURED (Sock)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockFlush: Protocol failed handling"
|
||||
" SOCK_FLUSH with %r", Status));
|
||||
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
SOCK_ERROR (Sock, EFI_ABORTED);
|
||||
SockConnFlush (Sock);
|
||||
SockSetState (Sock, SO_CLOSED);
|
||||
|
||||
Sock->ConfigureState = SO_UNCONFIGURED;
|
||||
|
||||
Exit:
|
||||
NET_UNLOCK (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Close or abort the socket associated connection.
|
||||
|
||||
@param Sock Pointer to the socket of the connection to close or
|
||||
abort.
|
||||
@param Token The token for close operation.
|
||||
@param OnAbort TRUE for aborting the connection, FALSE to close it.
|
||||
|
||||
@retval EFI_SUCCESS The close or abort operation is initialized
|
||||
successfully.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
|
||||
socket is closed, or the socket is not in a
|
||||
synchronized state , or the token is already in one
|
||||
of this socket's lists.
|
||||
@retval EFI_NO_MAPPING The IP address configuration operation is not
|
||||
finished.
|
||||
@retval EFI_NOT_STARTED The socket is not configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockClose (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token,
|
||||
IN BOOLEAN OnAbort
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_EVENT Event;
|
||||
|
||||
ASSERT (SOCK_STREAM == Sock->Type);
|
||||
|
||||
Status = NET_TRYLOCK (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
SOCK_DEBUG_ERROR (("SockClose: Get the access for socket"
|
||||
" failed with %r", Status));
|
||||
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (SOCK_IS_NO_MAPPING (Sock)) {
|
||||
Status = EFI_NO_MAPPING;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (SOCK_IS_UNCONFIGURED (Sock)) {
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (SOCK_IS_DISCONNECTING (Sock)) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
|
||||
|
||||
if (SockTokenExisted (Sock, Event)) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Sock->CloseToken = Token;
|
||||
SockSetState (Sock, SO_DISCONNECTING);
|
||||
|
||||
if (OnAbort) {
|
||||
Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);
|
||||
} else {
|
||||
Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);
|
||||
}
|
||||
|
||||
Exit:
|
||||
NET_UNLOCK (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the mode data of the low layer protocol.
|
||||
|
||||
@param Sock Pointer to the socket to get mode data from.
|
||||
@param Mode Pointer to the data to store the low layer mode
|
||||
information.
|
||||
|
||||
@retval EFI_SUCCESS The mode data is got successfully.
|
||||
@retval EFI_NOT_STARTED The socket is not configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockGetMode (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Mode
|
||||
)
|
||||
{
|
||||
return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Configure the low level protocol to join a multicast group for
|
||||
this socket's connection.
|
||||
|
||||
@param Sock Pointer to the socket of the connection to join the
|
||||
specific multicast group.
|
||||
@param GroupInfo Pointer to the multicast group info.
|
||||
|
||||
@retval EFI_SUCCESS The configuration is done successfully.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
|
||||
@retval EFI_NOT_STARTED The socket is not configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockGroup (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *GroupInfo
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = NET_TRYLOCK (&(Sock->Lock));
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
SOCK_DEBUG_ERROR (("SockGroup: Get the access for socket"
|
||||
" failed with %r", Status));
|
||||
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (SOCK_IS_UNCONFIGURED (Sock)) {
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = Sock->ProtoHandler (Sock, SOCK_GROUP, GroupInfo);
|
||||
|
||||
Exit:
|
||||
NET_UNLOCK (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Add or remove route information in IP route table associated
|
||||
with this socket.
|
||||
|
||||
@param Sock Pointer to the socket associated with the IP route
|
||||
table to operate on.
|
||||
@param RouteInfo Pointer to the route information to be processed.
|
||||
|
||||
@retval EFI_SUCCESS The route table is updated successfully.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
|
||||
@retval EFI_NO_MAPPING The IP address configuration operation is not
|
||||
finished.
|
||||
@retval EFI_NOT_STARTED The socket is not configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockRoute (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *RouteInfo
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = NET_TRYLOCK (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
SOCK_DEBUG_ERROR (("SockRoute: Get the access for socket"
|
||||
" failed with %r", Status));
|
||||
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (SOCK_IS_NO_MAPPING (Sock)) {
|
||||
Status = EFI_NO_MAPPING;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (SOCK_IS_UNCONFIGURED (Sock)) {
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);
|
||||
|
||||
Exit:
|
||||
NET_UNLOCK (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
518
MdeModulePkg/Universal/Network/Tcp4Dxe/Socket.h
Normal file
518
MdeModulePkg/Universal/Network/Tcp4Dxe/Socket.h
Normal file
@@ -0,0 +1,518 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Socket.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SOCKET_H_
|
||||
#define _SOCKET_H_
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/IP4.h>
|
||||
#include <Protocol/Tcp4.h>
|
||||
#include <Protocol/Udp4.h>
|
||||
|
||||
#include <Library/NetLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
|
||||
#define SOCK_SND_BUF 0
|
||||
#define SOCK_RCV_BUF 1
|
||||
|
||||
#define SOCK_BUFF_LOW_WATER 2 * 1024
|
||||
#define SOCK_RCV_BUFF_SIZE 8 * 1024
|
||||
#define SOCK_SND_BUFF_SIZE 8 * 1024
|
||||
#define SOCK_BACKLOG 5
|
||||
|
||||
#define PROTO_RESERVED_LEN 20
|
||||
|
||||
#define SO_NO_MORE_DATA 0x0001
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
// When a socket is created it enters into SO_UNCONFIGURED,
|
||||
// no actions can be taken on this socket, only after calling
|
||||
// SockConfigure. The state transition diagram of socket is
|
||||
// as following:
|
||||
//
|
||||
// SO_UNCONFIGURED --- SO_CONFIGURED --- SO_CONNECTING
|
||||
// ^ | |
|
||||
// | ---> SO_LISTENING |
|
||||
// | |
|
||||
// |------------------SO_DISCONNECTING<-- SO_CONNECTED
|
||||
//
|
||||
// A passive socket can only go into SO_LISTENING and
|
||||
// SO_UNCONFIGURED state. SO_XXXING state is a middle state
|
||||
// when a socket is undergoing a protocol procedure such
|
||||
// as requesting a TCP connection.
|
||||
//
|
||||
//
|
||||
//
|
||||
typedef enum {
|
||||
SO_CLOSED = 0,
|
||||
SO_LISTENING,
|
||||
SO_CONNECTING,
|
||||
SO_CONNECTED,
|
||||
SO_DISCONNECTING
|
||||
} SOCK_STATE;
|
||||
|
||||
typedef enum {
|
||||
SO_UNCONFIGURED = 0,
|
||||
SO_CONFIGURED_ACTIVE,
|
||||
SO_CONFIGURED_PASSIVE,
|
||||
SO_NO_MAPPING
|
||||
} SOCK_CONFIGURE_STATE;
|
||||
|
||||
#define SOCK_NO_MORE_DATA(Sock) ((Sock)->Flag |= SO_NO_MORE_DATA)
|
||||
|
||||
#define SOCK_IS_UNCONFIGURED(Sock) ((Sock)->ConfigureState == SO_UNCONFIGURED)
|
||||
|
||||
#define SOCK_IS_CONFIGURED(Sock) \
|
||||
(((Sock)->ConfigureState == SO_CONFIGURED_ACTIVE) || \
|
||||
((Sock)->ConfigureState == SO_CONFIGURED_PASSIVE))
|
||||
|
||||
#define SOCK_IS_CONFIGURED_ACTIVE(Sock) \
|
||||
((Sock)->ConfigureState == SO_CONFIGURED_ACTIVE)
|
||||
|
||||
#define SOCK_IS_CONNECTED_PASSIVE(Sock) \
|
||||
((Sock)->ConfigureState == SO_CONFIGURED_PASSIVE)
|
||||
|
||||
#define SOCK_IS_NO_MAPPING(Sock) \
|
||||
((Sock)->ConfigureState == SO_NO_MAPPING)
|
||||
|
||||
#define SOCK_IS_CLOSED(Sock) ((Sock)->State == SO_CLOSED)
|
||||
|
||||
#define SOCK_IS_LISTENING(Sock) ((Sock)->State == SO_LISTENING)
|
||||
|
||||
#define SOCK_IS_CONNECTING(Sock) ((Sock)->State == SO_CONNECTING)
|
||||
|
||||
#define SOCK_IS_CONNECTED(Sock) ((Sock)->State == SO_CONNECTED)
|
||||
|
||||
#define SOCK_IS_DISCONNECTING(Sock) ((Sock)->State == SO_DISCONNECTING)
|
||||
|
||||
#define SOCK_IS_NO_MORE_DATA(Sock) (0 != ((Sock)->Flag & SO_NO_MORE_DATA))
|
||||
|
||||
#define SOCK_SIGNATURE EFI_SIGNATURE_32 ('S', 'O', 'C', 'K')
|
||||
|
||||
#define SOCK_FROM_THIS(a) CR ((a), SOCKET, NetProtocol, SOCK_SIGNATURE)
|
||||
|
||||
#define SET_RCV_BUFFSIZE(Sock, Size) ((Sock)->RcvBuffer.HighWater = (Size))
|
||||
|
||||
#define GET_RCV_BUFFSIZE(Sock) ((Sock)->RcvBuffer.HighWater)
|
||||
|
||||
#define GET_RCV_DATASIZE(Sock) (((Sock)->RcvBuffer.DataQueue)->BufSize)
|
||||
|
||||
#define SET_SND_BUFFSIZE(Sock, Size) ((Sock)->SndBuffer.HighWater = (Size))
|
||||
|
||||
#define GET_SND_BUFFSIZE(Sock) ((Sock)->SndBuffer.HighWater)
|
||||
|
||||
#define GET_SND_DATASIZE(Sock) (((Sock)->SndBuffer.DataQueue)->BufSize)
|
||||
|
||||
#define SET_BACKLOG(Sock, Value) ((Sock)->BackLog = (Value))
|
||||
|
||||
#define GET_BACKLOG(Sock) ((Sock)->BackLog)
|
||||
|
||||
#define SOCK_ERROR(Sock, Error) ((Sock)->SockError = (Error))
|
||||
|
||||
#define SND_BUF_HDR_LEN(Sock) \
|
||||
((SockBufFirst (&((Sock)->SndBuffer)))->TotalSize)
|
||||
|
||||
#define RCV_BUF_HDR_LEN(Sock) \
|
||||
((SockBufFirst (&((Sock)->RcvBuffer)))->TotalSize)
|
||||
|
||||
#define SOCK_FROM_TOKEN(Token) (((SOCK_TOKEN *) (Token))->Sock)
|
||||
|
||||
#define PROTO_TOKEN_FORM_SOCK(SockToken, Type) \
|
||||
((Type *) (((SOCK_TOKEN *) (SockToken))->Token))
|
||||
|
||||
typedef struct _SOCKET SOCKET;
|
||||
|
||||
typedef struct _SOCK_COMPLETION_TOKEN {
|
||||
EFI_EVENT Event;
|
||||
EFI_STATUS Status;
|
||||
} SOCK_COMPLETION_TOKEN;
|
||||
|
||||
typedef struct _SOCK_IO_TOKEN {
|
||||
SOCK_COMPLETION_TOKEN Token;
|
||||
union {
|
||||
VOID *RxData;
|
||||
VOID *TxData;
|
||||
} Packet;
|
||||
} SOCK_IO_TOKEN;
|
||||
|
||||
//
|
||||
// the request issued from socket layer to protocol layer
|
||||
//
|
||||
typedef enum {
|
||||
SOCK_ATTACH, // attach current socket to a new PCB
|
||||
SOCK_DETACH, // detach current socket from the PCB
|
||||
SOCK_CONFIGURE, // configure attached PCB
|
||||
SOCK_FLUSH, // flush attached PCB
|
||||
SOCK_SND, // need protocol to send something
|
||||
SOCK_SNDPUSH, // need protocol to send pushed data
|
||||
SOCK_SNDURG, // need protocol to send urgent data
|
||||
SOCK_CONSUMED, // application has retrieved data from socket
|
||||
SOCK_CONNECT, // need to connect to a peer
|
||||
SOCK_CLOSE, // need to close the protocol process
|
||||
SOCK_ABORT, // need to reset the protocol process
|
||||
SOCK_POLL, // need to poll to the protocol layer
|
||||
SOCK_ROUTE, // need to add a route information
|
||||
SOCK_MODE, // need to get the mode data of the protocol
|
||||
SOCK_GROUP // need to join a mcast group
|
||||
} SOCK_REQUEST;
|
||||
|
||||
//
|
||||
// the socket type
|
||||
//
|
||||
typedef enum {
|
||||
SOCK_DGRAM, // this socket providing datagram service
|
||||
SOCK_STREAM // this socket providing stream service
|
||||
} SOCK_TYPE;
|
||||
|
||||
//
|
||||
// the handler of protocol for request from socket
|
||||
//
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(*SOCK_PROTO_HANDLER) (
|
||||
IN SOCKET * Socket, // the socket issuing the request to protocol
|
||||
IN SOCK_REQUEST Request, // the request issued by socket
|
||||
IN VOID *RequestData // the request related data
|
||||
);
|
||||
|
||||
//
|
||||
// the buffer structure of rcvd data and send data used by socket
|
||||
//
|
||||
typedef struct _SOCK_BUFFER {
|
||||
UINT32 HighWater; // the buffersize upper limit of sock_buffer
|
||||
UINT32 LowWater; // the low warter mark of sock_buffer
|
||||
NET_BUF_QUEUE *DataQueue; // the queue to buffer data
|
||||
} SOCK_BUFFER;
|
||||
|
||||
//
|
||||
// the initialize data for create a new socket
|
||||
//
|
||||
typedef struct _SOCK_INIT_DATA {
|
||||
SOCK_TYPE Type;
|
||||
SOCK_STATE State;
|
||||
|
||||
SOCKET *Parent; // the parent of this socket
|
||||
UINT32 BackLog; // the connection limit for listening socket
|
||||
UINT32 SndBufferSize; // the high warter mark of send buffer
|
||||
UINT32 RcvBufferSize; // the high warter mark of receive buffer
|
||||
VOID *Protocol; // the pointer to protocol function template
|
||||
// wanted to install on socket
|
||||
|
||||
SOCK_PROTO_HANDLER ProtoHandler;
|
||||
|
||||
EFI_HANDLE DriverBinding; // the driver binding handle
|
||||
} SOCK_INIT_DATA;
|
||||
|
||||
//
|
||||
// socket provided oprerations for low layer protocol
|
||||
//
|
||||
|
||||
//
|
||||
// socket provided operations for user interface
|
||||
//
|
||||
VOID
|
||||
SockSetState (
|
||||
IN SOCKET *Sock,
|
||||
IN SOCK_STATE State
|
||||
);
|
||||
|
||||
//
|
||||
// when the connection establishment process for a Sock
|
||||
// is finished low layer protocol calling this function
|
||||
// to notify socket layer
|
||||
//
|
||||
VOID
|
||||
SockConnEstablished (
|
||||
IN SOCKET *Sock
|
||||
);
|
||||
|
||||
VOID
|
||||
SockConnClosed (
|
||||
IN SOCKET *Sock
|
||||
);
|
||||
|
||||
//
|
||||
// called by low layer protocol to trim send buffer of
|
||||
// Sock, when Count data is sent out completely
|
||||
//
|
||||
VOID
|
||||
SockDataSent (
|
||||
IN SOCKET *Sock,
|
||||
IN UINT32 Count
|
||||
);
|
||||
|
||||
//
|
||||
// called by low layer protocol to get Len of data from
|
||||
// socket to send and copy it in Dest
|
||||
//
|
||||
UINT32
|
||||
SockGetDataToSend (
|
||||
IN SOCKET *Sock,
|
||||
IN UINT32 Offset,
|
||||
IN UINT32 Len,
|
||||
IN UINT8 *Dest
|
||||
);
|
||||
|
||||
//
|
||||
// called by low layer protocol to notify socket no more data can be
|
||||
// received
|
||||
//
|
||||
VOID
|
||||
SockNoMoreData (
|
||||
IN SOCKET *Sock
|
||||
);
|
||||
|
||||
//
|
||||
// called by low layer protocol to append a NetBuffer
|
||||
// to rcv buffer of sock
|
||||
//
|
||||
VOID
|
||||
SockDataRcvd (
|
||||
IN SOCKET *Sock,
|
||||
IN NET_BUF *NetBuffer,
|
||||
IN UINT32 UrgLen
|
||||
);
|
||||
|
||||
UINT32
|
||||
SockGetFreeSpace (
|
||||
IN SOCKET *Sock,
|
||||
IN UINT32 Which
|
||||
);
|
||||
|
||||
SOCKET *
|
||||
SockClone (
|
||||
IN SOCKET *Sock
|
||||
);
|
||||
|
||||
VOID
|
||||
SockRcvdErr (
|
||||
IN SOCKET *Sock,
|
||||
IN EFI_STATUS Error
|
||||
);
|
||||
|
||||
//
|
||||
// the socket structure representing a network service access point
|
||||
//
|
||||
typedef struct _SOCKET {
|
||||
|
||||
//
|
||||
// socket description information
|
||||
//
|
||||
UINT32 Signature;
|
||||
EFI_HANDLE SockHandle; // the virtual handle of the socket
|
||||
EFI_HANDLE DriverBinding; // socket't driver binding protocol
|
||||
SOCK_CONFIGURE_STATE ConfigureState;
|
||||
SOCK_TYPE Type;
|
||||
SOCK_STATE State;
|
||||
UINT16 Flag;
|
||||
NET_LOCK Lock; // the lock of socket
|
||||
SOCK_BUFFER SndBuffer; // send buffer of application's data
|
||||
SOCK_BUFFER RcvBuffer; // receive buffer of received data
|
||||
EFI_STATUS SockError; // the error returned by low layer protocol
|
||||
BOOLEAN IsDestroyed;
|
||||
|
||||
//
|
||||
// fields used to manage the connection request
|
||||
//
|
||||
UINT32 BackLog; // the limit of connection to this socket
|
||||
UINT32 ConnCnt; // the current count of connections to it
|
||||
SOCKET *Parent; // listening parent that accept the connection
|
||||
NET_LIST_ENTRY ConnectionList; // the connections maintained by this socket
|
||||
//
|
||||
// the queue to buffer application's asynchronous token
|
||||
//
|
||||
NET_LIST_ENTRY ListenTokenList;
|
||||
NET_LIST_ENTRY RcvTokenList;
|
||||
NET_LIST_ENTRY SndTokenList;
|
||||
NET_LIST_ENTRY ProcessingSndTokenList;
|
||||
|
||||
SOCK_COMPLETION_TOKEN *ConnectionToken; // app's token to signal if connected
|
||||
SOCK_COMPLETION_TOKEN *CloseToken; // app's token to signal if closed
|
||||
|
||||
//
|
||||
// interface for low level protocol
|
||||
//
|
||||
SOCK_PROTO_HANDLER ProtoHandler; // the request handler of protocol
|
||||
UINT8 ProtoReserved[PROTO_RESERVED_LEN]; // Data fields reserved for protocol
|
||||
union {
|
||||
EFI_TCP4_PROTOCOL TcpProtocol;
|
||||
EFI_UDP4_PROTOCOL UdpProtocol;
|
||||
} NetProtocol;
|
||||
} SOCKET;
|
||||
|
||||
//
|
||||
// the token structure buffered in socket layer
|
||||
//
|
||||
typedef struct _SOCK_TOKEN {
|
||||
NET_LIST_ENTRY TokenList; // the entry to add in the token list
|
||||
SOCK_COMPLETION_TOKEN *Token; // The application's token
|
||||
UINT32 RemainDataLen; // unprocessed data length
|
||||
SOCKET *Sock; // the poninter to the socket this token
|
||||
// belongs to
|
||||
} SOCK_TOKEN;
|
||||
|
||||
//
|
||||
// reserved data to access the NET_BUF delivered by UDP driver
|
||||
//
|
||||
typedef struct _UDP_RSV_DATA {
|
||||
EFI_TIME TimeStamp;
|
||||
EFI_UDP4_SESSION_DATA Session;
|
||||
} UDP_RSV_DATA;
|
||||
|
||||
//
|
||||
// reserved data to access the NET_BUF delivered by TCP driver
|
||||
//
|
||||
typedef struct _TCP_RSV_DATA {
|
||||
UINT32 UrgLen;
|
||||
} TCP_RSV_DATA;
|
||||
|
||||
//
|
||||
// call it to creat a socket and attach it to a PCB
|
||||
//
|
||||
SOCKET *
|
||||
SockCreateChild (
|
||||
IN SOCK_INIT_DATA *SockInitData,
|
||||
IN VOID *ProtoData,
|
||||
IN UINT32 Len
|
||||
);
|
||||
|
||||
//
|
||||
// call it to destroy a socket and its related PCB
|
||||
//
|
||||
EFI_STATUS
|
||||
SockDestroyChild (
|
||||
IN SOCKET *Sock
|
||||
);
|
||||
|
||||
//
|
||||
// call it to configure a socket and its related PCB
|
||||
//
|
||||
EFI_STATUS
|
||||
SockConfigure (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *ConfigData
|
||||
);
|
||||
|
||||
//
|
||||
// call it to connect a socket to the peer
|
||||
//
|
||||
EFI_STATUS
|
||||
SockConnect (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token
|
||||
);
|
||||
|
||||
//
|
||||
// call it to issue an asynchronous listen token to the socket
|
||||
//
|
||||
EFI_STATUS
|
||||
SockAccept (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token
|
||||
);
|
||||
|
||||
//
|
||||
// Call it to send data using this socket
|
||||
//
|
||||
EFI_STATUS
|
||||
SockSend (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token
|
||||
);
|
||||
|
||||
//
|
||||
// Call it to receive data from this socket
|
||||
//
|
||||
EFI_STATUS
|
||||
SockRcv (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token
|
||||
);
|
||||
|
||||
//
|
||||
// Call it to flush a socket
|
||||
//
|
||||
EFI_STATUS
|
||||
SockFlush (
|
||||
IN SOCKET *Sock
|
||||
);
|
||||
|
||||
//
|
||||
// Call it to close a socket in the light of policy in Token
|
||||
//
|
||||
EFI_STATUS
|
||||
SockClose (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token,
|
||||
IN BOOLEAN OnAbort
|
||||
);
|
||||
|
||||
//
|
||||
// Call it to get the mode data of low layer protocol
|
||||
//
|
||||
EFI_STATUS
|
||||
SockGetMode (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Mode
|
||||
);
|
||||
|
||||
//
|
||||
// call it to add this socket instance into a group
|
||||
//
|
||||
EFI_STATUS
|
||||
SockGroup (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *GroupInfo
|
||||
);
|
||||
|
||||
//
|
||||
// call it to add a route entry for this socket instance
|
||||
//
|
||||
EFI_STATUS
|
||||
SockRoute (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *RouteInfo
|
||||
);
|
||||
|
||||
//
|
||||
// Supporting function to operate on socket buffer
|
||||
//
|
||||
NET_BUF *
|
||||
SockBufFirst (
|
||||
IN SOCK_BUFFER *Sockbuf
|
||||
);
|
||||
|
||||
NET_BUF *
|
||||
SockBufNext (
|
||||
IN SOCK_BUFFER *Sockbuf,
|
||||
IN NET_BUF *SockEntry
|
||||
);
|
||||
|
||||
#endif
|
680
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dispatcher.c
Normal file
680
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dispatcher.c
Normal file
@@ -0,0 +1,680 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Tcp4Dispatcher.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Tcp4Main.h"
|
||||
|
||||
#define TCP_COMP_VAL(Min, Max, Default, Val) \
|
||||
((((Val) <= (Max)) && ((Val) >= (Min))) ? (Val) : (Default))
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Tcp4Route (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP4_ROUTE_INFO *RouteInfo
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Add or remove a route entry in the IP route table associated
|
||||
with this TCP instance.
|
||||
|
||||
Arguments:
|
||||
|
||||
Tcb - Pointer to the TCP_CB of this TCP instance.
|
||||
RouteInfo - Pointer to the route info to be processed.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - The operation completed successfully.
|
||||
EFI_NOT_STARTED - The driver instance has not been started.
|
||||
EFI_NO_MAPPING - When using the default address, configuration(DHCP,
|
||||
BOOTP, RARP, etc.) is not finished yet.
|
||||
EFI_OUT_OF_RESOURCES - Could not add the entry to the routing table.
|
||||
EFI_NOT_FOUND - This route is not in the routing table
|
||||
(when RouteInfo->DeleteRoute is TRUE).
|
||||
EFI_ACCESS_DENIED - The route is already defined in the routing table
|
||||
(when RouteInfo->DeleteRoute is FALSE).
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_IP4_PROTOCOL *Ip;
|
||||
|
||||
Ip = Tcb->IpInfo->Ip;
|
||||
|
||||
ASSERT (Ip);
|
||||
|
||||
return Ip->Routes (
|
||||
Ip,
|
||||
RouteInfo->DeleteRoute,
|
||||
RouteInfo->SubnetAddress,
|
||||
RouteInfo->SubnetMask,
|
||||
RouteInfo->GatewayAddress
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the operational settings of this TCP instance.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param Mode Pointer to the buffer to store the operational
|
||||
settings.
|
||||
|
||||
@retval EFI_SUCCESS The mode data is read.
|
||||
@retval EFI_NOT_STARTED No configuration data is available because this
|
||||
instance hasn't been started.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Tcp4GetMode (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP4_MODE_DATA *Mode
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
EFI_TCP4_CONFIG_DATA *ConfigData;
|
||||
EFI_TCP4_ACCESS_POINT *AccessPoint;
|
||||
EFI_TCP4_OPTION *Option;
|
||||
EFI_IP4_PROTOCOL *Ip;
|
||||
|
||||
Sock = Tcb->Sk;
|
||||
|
||||
if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp4ConfigData != NULL)) {
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
if (Mode->Tcp4State) {
|
||||
*(Mode->Tcp4State) = Tcb->State;
|
||||
}
|
||||
|
||||
if (Mode->Tcp4ConfigData) {
|
||||
|
||||
ConfigData = Mode->Tcp4ConfigData;
|
||||
AccessPoint = &(ConfigData->AccessPoint);
|
||||
Option = ConfigData->ControlOption;
|
||||
|
||||
ConfigData->TypeOfService = Tcb->TOS;
|
||||
ConfigData->TimeToLive = Tcb->TTL;
|
||||
|
||||
AccessPoint->UseDefaultAddress = Tcb->UseDefaultAddr;
|
||||
|
||||
EFI_IP4 (AccessPoint->StationAddress) = Tcb->LocalEnd.Ip;
|
||||
AccessPoint->SubnetMask = Tcb->SubnetMask;
|
||||
AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port);
|
||||
|
||||
EFI_IP4 (AccessPoint->RemoteAddress) = Tcb->RemoteEnd.Ip;
|
||||
AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port);
|
||||
AccessPoint->ActiveFlag = (BOOLEAN) (Tcb->State != TCP_LISTEN);
|
||||
|
||||
if (Option != NULL) {
|
||||
Option->ReceiveBufferSize = GET_RCV_BUFFSIZE (Tcb->Sk);
|
||||
Option->SendBufferSize = GET_SND_BUFFSIZE (Tcb->Sk);
|
||||
Option->MaxSynBackLog = GET_BACKLOG (Tcb->Sk);
|
||||
|
||||
Option->ConnectionTimeout = Tcb->ConnectTimeout / TCP_TICK_HZ;
|
||||
Option->DataRetries = Tcb->MaxRexmit;
|
||||
Option->FinTimeout = Tcb->FinWait2Timeout / TCP_TICK_HZ;
|
||||
Option->TimeWaitTimeout = Tcb->TimeWaitTimeout / TCP_TICK_HZ;
|
||||
Option->KeepAliveProbes = Tcb->MaxKeepAlive;
|
||||
Option->KeepAliveTime = Tcb->KeepAliveIdle / TCP_TICK_HZ;
|
||||
Option->KeepAliveInterval = Tcb->KeepAlivePeriod / TCP_TICK_HZ;
|
||||
|
||||
Option->EnableNagle = !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
|
||||
Option->EnableTimeStamp = !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
|
||||
Option->EnableWindowScaling = !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS);
|
||||
|
||||
Option->EnableSelectiveAck = FALSE;
|
||||
Option->EnablePathMtuDiscovery = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Ip = Tcb->IpInfo->Ip;
|
||||
ASSERT (Ip);
|
||||
|
||||
return Ip->GetModeData (Ip, Mode->Ip4ModeData, Mode->MnpConfigData, Mode->SnpModeData);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
If AP->StationPort isn't zero, check whether the access point
|
||||
is registered, else generate a random station port for this
|
||||
access point.
|
||||
|
||||
@param AP Pointer to the access point.
|
||||
|
||||
@retval EFI_SUCCESS The check is passed or the port is assigned.
|
||||
@retval EFI_INVALID_PARAMETER The non-zero station port is already used.
|
||||
@retval EFI_OUT_OF_RESOURCES No port can be allocated.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Tcp4Bind (
|
||||
IN EFI_TCP4_ACCESS_POINT *AP
|
||||
)
|
||||
{
|
||||
BOOLEAN Cycle;
|
||||
|
||||
if (0 != AP->StationPort) {
|
||||
//
|
||||
// check if a same endpoint is bound
|
||||
//
|
||||
if (TcpFindTcbByPeer (&AP->StationAddress, AP->StationPort)) {
|
||||
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// generate a random port
|
||||
//
|
||||
Cycle = FALSE;
|
||||
|
||||
if (TCP4_PORT_USER_RESERVED == mTcp4RandomPort) {
|
||||
mTcp4RandomPort = TCP4_PORT_KNOWN;
|
||||
}
|
||||
|
||||
mTcp4RandomPort++;
|
||||
|
||||
while (TcpFindTcbByPeer (&AP->StationAddress, mTcp4RandomPort)) {
|
||||
|
||||
mTcp4RandomPort++;
|
||||
|
||||
if (mTcp4RandomPort <= TCP4_PORT_KNOWN) {
|
||||
|
||||
if (Cycle) {
|
||||
TCP4_DEBUG_ERROR (("Tcp4Bind: no port can be allocated "
|
||||
"for this pcb\n"));
|
||||
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
mTcp4RandomPort = TCP4_PORT_KNOWN + 1;
|
||||
|
||||
Cycle = TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AP->StationPort = mTcp4RandomPort;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Flush the Tcb add its associated protocols..
|
||||
|
||||
@param Tcb Pointer to the TCP_CB to be flushed.
|
||||
|
||||
@retval EFI_SUCCESS The operation is completed successfully.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
Tcp4FlushPcb (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
TCP4_PROTO_DATA *TcpProto;
|
||||
|
||||
IpIoConfigIp (Tcb->IpInfo, NULL);
|
||||
|
||||
Sock = Tcb->Sk;
|
||||
TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
|
||||
|
||||
if (SOCK_IS_CONFIGURED (Sock)) {
|
||||
NetListRemoveEntry (&Tcb->List);
|
||||
|
||||
TcpSetVariableData (TcpProto->TcpService);
|
||||
}
|
||||
|
||||
NetbufFreeList (&Tcb->SndQue);
|
||||
NetbufFreeList (&Tcb->RcvQue);
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Tcp4AttachPcb (
|
||||
IN SOCKET *Sk
|
||||
)
|
||||
{
|
||||
TCP_CB *Tcb;
|
||||
TCP4_PROTO_DATA *ProtoData;
|
||||
IP_IO *IpIo;
|
||||
|
||||
Tcb = NetAllocateZeroPool (sizeof (TCP_CB));
|
||||
|
||||
if (Tcb == NULL) {
|
||||
|
||||
TCP4_DEBUG_ERROR (("Tcp4ConfigurePcb: failed to allocate a TCB\n"));
|
||||
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
|
||||
IpIo = ProtoData->TcpService->IpIo;
|
||||
|
||||
//
|
||||
// Create an IpInfo for this Tcb.
|
||||
//
|
||||
Tcb->IpInfo = IpIoAddIp (IpIo);
|
||||
if (Tcb->IpInfo == NULL) {
|
||||
|
||||
NetFreePool (Tcb);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
NetListInit (&Tcb->List);
|
||||
NetListInit (&Tcb->SndQue);
|
||||
NetListInit (&Tcb->RcvQue);
|
||||
|
||||
Tcb->State = TCP_CLOSED;
|
||||
Tcb->Sk = Sk;
|
||||
ProtoData->TcpPcb = Tcb;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
Tcp4DetachPcb (
|
||||
IN SOCKET *Sk
|
||||
)
|
||||
{
|
||||
TCP4_PROTO_DATA *ProtoData;
|
||||
TCP_CB *Tcb;
|
||||
|
||||
ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
|
||||
Tcb = ProtoData->TcpPcb;
|
||||
|
||||
ASSERT (Tcb != NULL);
|
||||
|
||||
Tcp4FlushPcb (Tcb);
|
||||
|
||||
IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);
|
||||
|
||||
NetFreePool (Tcb);
|
||||
|
||||
ProtoData->TcpPcb = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Configure the Tcb using CfgData.
|
||||
|
||||
@param Sk Pointer to the socket of this TCP instance.
|
||||
@param SkTcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param CfgData Pointer to the TCP configuration data.
|
||||
|
||||
@retval EFI_SUCCESS The operation is completed successfully.
|
||||
@retval EFI_INVALID_PARAMETER A same access point has been configured in
|
||||
another TCP instance.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Tcp4ConfigurePcb (
|
||||
IN SOCKET *Sk,
|
||||
IN EFI_TCP4_CONFIG_DATA *CfgData
|
||||
)
|
||||
{
|
||||
IP_IO *IpIo;
|
||||
EFI_IP4_CONFIG_DATA IpCfgData;
|
||||
EFI_STATUS Status;
|
||||
EFI_TCP4_OPTION *Option;
|
||||
TCP4_PROTO_DATA *TcpProto;
|
||||
TCP_CB *Tcb;
|
||||
|
||||
ASSERT (CfgData && Sk && Sk->SockHandle);
|
||||
|
||||
TcpProto = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
|
||||
Tcb = TcpProto->TcpPcb;
|
||||
IpIo = TcpProto->TcpService->IpIo;
|
||||
|
||||
ASSERT (Tcb != NULL);
|
||||
|
||||
//
|
||||
// Add Ip for send pkt to the peer
|
||||
//
|
||||
IpCfgData = mIpIoDefaultIpConfigData;
|
||||
IpCfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
|
||||
IpCfgData.UseDefaultAddress = CfgData->AccessPoint.UseDefaultAddress;
|
||||
IpCfgData.StationAddress = CfgData->AccessPoint.StationAddress;
|
||||
IpCfgData.SubnetMask = CfgData->AccessPoint.SubnetMask;
|
||||
IpCfgData.ReceiveTimeout = (UINT32) (-1);
|
||||
|
||||
//
|
||||
// Configure the IP instance this Tcb consumes.
|
||||
//
|
||||
Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto OnExit;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the default address info if the instance is configured to use default address.
|
||||
//
|
||||
if (CfgData->AccessPoint.UseDefaultAddress) {
|
||||
CfgData->AccessPoint.StationAddress = IpCfgData.StationAddress;
|
||||
CfgData->AccessPoint.SubnetMask = IpCfgData.SubnetMask;
|
||||
}
|
||||
|
||||
//
|
||||
// check if we can bind this endpoint in CfgData
|
||||
//
|
||||
Status = Tcp4Bind (&(CfgData->AccessPoint));
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
TCP4_DEBUG_ERROR (("Tcp4ConfigurePcb: Bind endpoint failed "
|
||||
"with %r\n", Status));
|
||||
|
||||
goto OnExit;
|
||||
}
|
||||
|
||||
//
|
||||
// Initalize the operating information in this Tcb
|
||||
//
|
||||
ASSERT (Tcb->State == TCP_CLOSED &&
|
||||
NetListIsEmpty (&Tcb->SndQue) &&
|
||||
NetListIsEmpty (&Tcb->RcvQue));
|
||||
|
||||
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
|
||||
Tcb->State = TCP_CLOSED;
|
||||
|
||||
Tcb->SndMss = 536;
|
||||
Tcb->RcvMss = TcpGetRcvMss (Sk);
|
||||
|
||||
Tcb->SRtt = 0;
|
||||
Tcb->Rto = 3 * TCP_TICK_HZ;
|
||||
|
||||
Tcb->CWnd = Tcb->SndMss;
|
||||
Tcb->Ssthresh = 0xffffffff;
|
||||
|
||||
Tcb->CongestState = TCP_CONGEST_OPEN;
|
||||
|
||||
Tcb->KeepAliveIdle = TCP_KEEPALIVE_IDLE_MIN;
|
||||
Tcb->KeepAlivePeriod = TCP_KEEPALIVE_PERIOD;
|
||||
Tcb->MaxKeepAlive = TCP_MAX_KEEPALIVE;
|
||||
Tcb->MaxRexmit = TCP_MAX_LOSS;
|
||||
Tcb->FinWait2Timeout = TCP_FIN_WAIT2_TIME;
|
||||
Tcb->TimeWaitTimeout = TCP_TIME_WAIT_TIME;
|
||||
Tcb->ConnectTimeout = TCP_CONNECT_TIME;
|
||||
|
||||
//
|
||||
// initialize Tcb in the light of CfgData
|
||||
//
|
||||
Tcb->TTL = CfgData->TimeToLive;
|
||||
Tcb->TOS = CfgData->TypeOfService;
|
||||
|
||||
Tcb->LocalEnd.Ip = EFI_IP4 (CfgData->AccessPoint.StationAddress);
|
||||
Tcb->LocalEnd.Port = HTONS (CfgData->AccessPoint.StationPort);
|
||||
Tcb->SubnetMask = CfgData->AccessPoint.SubnetMask;
|
||||
|
||||
Tcb->RemoteEnd.Ip = EFI_IP4 (CfgData->AccessPoint.RemoteAddress);
|
||||
Tcb->RemoteEnd.Port = HTONS (CfgData->AccessPoint.RemotePort);
|
||||
|
||||
Option = CfgData->ControlOption;
|
||||
|
||||
if (Option != NULL) {
|
||||
SET_RCV_BUFFSIZE (
|
||||
Sk,
|
||||
TCP_COMP_VAL (TCP_RCV_BUF_SIZE_MIN,
|
||||
TCP_RCV_BUF_SIZE,
|
||||
TCP_RCV_BUF_SIZE,
|
||||
Option->ReceiveBufferSize)
|
||||
);
|
||||
SET_SND_BUFFSIZE (
|
||||
Sk,
|
||||
TCP_COMP_VAL (TCP_SND_BUF_SIZE_MIN,
|
||||
TCP_SND_BUF_SIZE,
|
||||
TCP_SND_BUF_SIZE,
|
||||
Option->SendBufferSize)
|
||||
);
|
||||
|
||||
SET_BACKLOG (
|
||||
Sk,
|
||||
TCP_COMP_VAL (TCP_BACKLOG_MIN,
|
||||
TCP_BACKLOG,
|
||||
TCP_BACKLOG,
|
||||
Option->MaxSynBackLog)
|
||||
);
|
||||
|
||||
Tcb->MaxRexmit = (UINT16) TCP_COMP_VAL (
|
||||
TCP_MAX_LOSS_MIN,
|
||||
TCP_MAX_LOSS,
|
||||
TCP_MAX_LOSS,
|
||||
Option->DataRetries
|
||||
);
|
||||
Tcb->FinWait2Timeout = TCP_COMP_VAL (
|
||||
TCP_FIN_WAIT2_TIME,
|
||||
TCP_FIN_WAIT2_TIME_MAX,
|
||||
TCP_FIN_WAIT2_TIME,
|
||||
Option->FinTimeout * TCP_TICK_HZ
|
||||
);
|
||||
|
||||
if (Option->TimeWaitTimeout != 0) {
|
||||
Tcb->TimeWaitTimeout = TCP_COMP_VAL (
|
||||
TCP_TIME_WAIT_TIME,
|
||||
TCP_TIME_WAIT_TIME_MAX,
|
||||
TCP_TIME_WAIT_TIME,
|
||||
Option->TimeWaitTimeout * TCP_TICK_HZ
|
||||
);
|
||||
} else {
|
||||
Tcb->TimeWaitTimeout = 0;
|
||||
}
|
||||
|
||||
if (Option->KeepAliveProbes != 0) {
|
||||
TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
|
||||
|
||||
Tcb->MaxKeepAlive = (UINT8) TCP_COMP_VAL (
|
||||
TCP_MAX_KEEPALIVE_MIN,
|
||||
TCP_MAX_KEEPALIVE,
|
||||
TCP_MAX_KEEPALIVE,
|
||||
Option->KeepAliveProbes
|
||||
);
|
||||
Tcb->KeepAliveIdle = TCP_COMP_VAL (
|
||||
TCP_KEEPALIVE_IDLE_MIN,
|
||||
TCP_KEEPALIVE_IDLE_MAX,
|
||||
TCP_KEEPALIVE_IDLE_MIN,
|
||||
Option->KeepAliveTime * TCP_TICK_HZ
|
||||
);
|
||||
Tcb->KeepAlivePeriod = TCP_COMP_VAL (
|
||||
TCP_KEEPALIVE_PERIOD_MIN,
|
||||
TCP_KEEPALIVE_PERIOD,
|
||||
TCP_KEEPALIVE_PERIOD,
|
||||
Option->KeepAliveInterval * TCP_TICK_HZ
|
||||
);
|
||||
}
|
||||
|
||||
Tcb->ConnectTimeout = TCP_COMP_VAL (
|
||||
TCP_CONNECT_TIME_MIN,
|
||||
TCP_CONNECT_TIME,
|
||||
TCP_CONNECT_TIME,
|
||||
Option->ConnectionTimeout * TCP_TICK_HZ
|
||||
);
|
||||
|
||||
if (Option->EnableNagle == FALSE) {
|
||||
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
|
||||
}
|
||||
|
||||
if (Option->EnableTimeStamp == FALSE) {
|
||||
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
|
||||
}
|
||||
|
||||
if (Option->EnableWindowScaling == FALSE) {
|
||||
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// update state of Tcb and socket
|
||||
//
|
||||
if (CfgData->AccessPoint.ActiveFlag == FALSE) {
|
||||
|
||||
TcpSetState (Tcb, TCP_LISTEN);
|
||||
SockSetState (Sk, SO_LISTENING);
|
||||
|
||||
Sk->ConfigureState = SO_CONFIGURED_PASSIVE;
|
||||
} else {
|
||||
|
||||
Sk->ConfigureState = SO_CONFIGURED_ACTIVE;
|
||||
}
|
||||
|
||||
TcpInsertTcb (Tcb);
|
||||
|
||||
OnExit:
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The procotol handler provided to the socket layer, used to
|
||||
dispatch the socket level requests by calling the corresponding
|
||||
TCP layer functions.
|
||||
|
||||
@param Sock Pointer to the socket of this TCP instance.
|
||||
@param Request The code of this operation request.
|
||||
@param Data Pointer to the operation specific data passed in
|
||||
together with the operation request.
|
||||
|
||||
@retval EFI_SUCCESS The socket request is completed successfully.
|
||||
@retval other The error status returned by the corresponding TCP
|
||||
layer function.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tcp4Dispatcher (
|
||||
IN SOCKET *Sock,
|
||||
IN SOCK_REQUEST Request,
|
||||
IN VOID *Data OPTIONAL
|
||||
)
|
||||
{
|
||||
TCP_CB *Tcb;
|
||||
TCP4_PROTO_DATA *ProtoData;
|
||||
EFI_IP4_PROTOCOL *Ip;
|
||||
|
||||
ProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
|
||||
Tcb = ProtoData->TcpPcb;
|
||||
|
||||
switch (Request) {
|
||||
case SOCK_POLL:
|
||||
Ip = ProtoData->TcpService->IpIo->Ip;
|
||||
Ip->Poll (Ip);
|
||||
break;
|
||||
|
||||
case SOCK_CONSUMED:
|
||||
//
|
||||
// After user received data from socket buffer, socket will
|
||||
// notify TCP using this message to give it a chance to send out
|
||||
// window update information
|
||||
//
|
||||
ASSERT (Tcb);
|
||||
TcpOnAppConsume (Tcb);
|
||||
break;
|
||||
|
||||
case SOCK_SND:
|
||||
|
||||
ASSERT (Tcb);
|
||||
TcpOnAppSend (Tcb);
|
||||
break;
|
||||
|
||||
case SOCK_CLOSE:
|
||||
|
||||
TcpOnAppClose (Tcb);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_ABORT:
|
||||
|
||||
TcpOnAppAbort (Tcb);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_SNDPUSH:
|
||||
Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk);
|
||||
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_SNDURG:
|
||||
Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1;
|
||||
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_CONNECT:
|
||||
|
||||
TcpOnAppConnect (Tcb);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_ATTACH:
|
||||
|
||||
return Tcp4AttachPcb (Sock);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_FLUSH:
|
||||
|
||||
Tcp4FlushPcb (Tcb);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_DETACH:
|
||||
|
||||
Tcp4DetachPcb (Sock);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_CONFIGURE:
|
||||
|
||||
return Tcp4ConfigurePcb (
|
||||
Sock,
|
||||
(EFI_TCP4_CONFIG_DATA *) Data
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_MODE:
|
||||
|
||||
ASSERT (Data && Tcb);
|
||||
|
||||
return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_ROUTE:
|
||||
|
||||
ASSERT (Data && Tcb);
|
||||
|
||||
return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data);
|
||||
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
}
|
669
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c
Normal file
669
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c
Normal file
@@ -0,0 +1,669 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2007, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Tcp4Driver.c
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Tcp4Main.h"
|
||||
|
||||
|
||||
UINT16 mTcp4RandomPort;
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName;
|
||||
|
||||
TCP4_HEARTBEAT_TIMER mTcp4Timer = {
|
||||
NULL,
|
||||
0
|
||||
};
|
||||
|
||||
EFI_TCP4_PROTOCOL mTcp4ProtocolTemplate = {
|
||||
Tcp4GetModeData,
|
||||
Tcp4Configure,
|
||||
Tcp4Routes,
|
||||
Tcp4Connect,
|
||||
Tcp4Accept,
|
||||
Tcp4Transmit,
|
||||
Tcp4Receive,
|
||||
Tcp4Close,
|
||||
Tcp4Cancel,
|
||||
Tcp4Poll
|
||||
};
|
||||
|
||||
SOCK_INIT_DATA mTcp4DefaultSockData = {
|
||||
SOCK_STREAM,
|
||||
0,
|
||||
NULL,
|
||||
TCP_BACKLOG,
|
||||
TCP_SND_BUF_SIZE,
|
||||
TCP_RCV_BUF_SIZE,
|
||||
&mTcp4ProtocolTemplate,
|
||||
Tcp4Dispatcher,
|
||||
NULL,
|
||||
};
|
||||
|
||||
EFI_DRIVER_BINDING_PROTOCOL mTcp4DriverBinding = {
|
||||
Tcp4DriverBindingSupported,
|
||||
Tcp4DriverBindingStart,
|
||||
Tcp4DriverBindingStop,
|
||||
0xa,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
EFI_SERVICE_BINDING_PROTOCOL mTcp4ServiceBinding = {
|
||||
Tcp4ServiceBindingCreateChild,
|
||||
Tcp4ServiceBindingDestroyChild
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Create and start the heartbeat timer for TCP driver.
|
||||
|
||||
None.
|
||||
|
||||
@retval EFI_SUCCESS The timer is successfully created and started.
|
||||
@retval other The timer is not created.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Tcp4CreateTimer (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
if (mTcp4Timer.RefCnt == 0) {
|
||||
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_TIMER | EVT_NOTIFY_SIGNAL,
|
||||
NET_TPL_TIMER,
|
||||
TcpTicking,
|
||||
NULL,
|
||||
&mTcp4Timer.TimerEvent
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
|
||||
Status = gBS->SetTimer (
|
||||
mTcp4Timer.TimerEvent,
|
||||
TimerPeriodic,
|
||||
(UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
|
||||
mTcp4Timer.RefCnt++;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Stop and destroy the heartbeat timer for TCP driver.
|
||||
|
||||
None.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
Tcp4DestroyTimer (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT (mTcp4Timer.RefCnt > 0);
|
||||
|
||||
mTcp4Timer.RefCnt--;
|
||||
|
||||
if (mTcp4Timer.RefCnt > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
gBS->SetTimer (mTcp4Timer.TimerEvent, TimerCancel, 0);
|
||||
gBS->CloseEvent (mTcp4Timer.TimerEvent);
|
||||
mTcp4Timer.TimerEvent = NULL;
|
||||
}
|
||||
|
||||
//@MT: EFI_DRIVER_ENTRY_POINT (Tcp4DriverEntryPoint)
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The entry point for Tcp4 driver. used to install
|
||||
Tcp4 driver on the ImageHandle.
|
||||
|
||||
Arguments:
|
||||
|
||||
ImageHandle - The firmware allocated handle for this
|
||||
driver image.
|
||||
SystemTable - Pointer to the EFI system table.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - Driver loaded.
|
||||
other - Driver not loaded.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Seed;
|
||||
|
||||
//
|
||||
// Install the TCP4 Driver Binding Protocol
|
||||
//
|
||||
Status = NetLibInstallAllDriverProtocols (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&mTcp4DriverBinding,
|
||||
ImageHandle,
|
||||
&gTcp4ComponentName,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
//
|
||||
// Initialize ISS and random port.
|
||||
//
|
||||
Seed = NetRandomInitSeed ();
|
||||
mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;
|
||||
mTcp4RandomPort = TCP4_PORT_KNOWN +
|
||||
(UINT16) (NET_RANDOM(Seed) % TCP4_PORT_KNOWN);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to test.
|
||||
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS This driver supports this device.
|
||||
@retval EFI_ALREADY_STARTED This driver is already running on this device.
|
||||
@retval other This driver does not support this device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL * This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Test for the Tcp4ServiceBinding Protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiTcp4ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Test for the Ip4 Protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to bind driver to.
|
||||
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS The driver is added to ControllerHandle.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources to start the
|
||||
driver.
|
||||
@retval other The driver cannot be added to ControllerHandle.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL * This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
TCP4_SERVICE_DATA *TcpServiceData;
|
||||
IP_IO_OPEN_DATA OpenData;
|
||||
|
||||
TcpServiceData = NetAllocateZeroPool (sizeof (TCP4_SERVICE_DATA));
|
||||
|
||||
if (NULL == TcpServiceData) {
|
||||
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStart: Have no enough"
|
||||
" resource to create a Tcp Servcie Data!\n"));
|
||||
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a new IP IO to Consume it
|
||||
//
|
||||
TcpServiceData->IpIo = IpIoCreate (This->DriverBindingHandle, ControllerHandle);
|
||||
if (NULL == TcpServiceData->IpIo) {
|
||||
|
||||
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStart: Have no enough"
|
||||
" resource to create an Ip Io!\n"));
|
||||
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ReleaseServiceData;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure and start IpIo.
|
||||
//
|
||||
NetZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));
|
||||
|
||||
OpenData.IpConfigData = mIpIoDefaultIpConfigData;
|
||||
OpenData.IpConfigData.DefaultProtocol = EFI_IP_PROTO_TCP;
|
||||
|
||||
OpenData.PktRcvdNotify = Tcp4RxCallback;
|
||||
Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ReleaseServiceData;
|
||||
}
|
||||
|
||||
//
|
||||
// Create the timer event used by TCP driver
|
||||
//
|
||||
Status = Tcp4CreateTimer ();
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStart: Create TcpTimer"
|
||||
" Event failed with %r\n", Status));
|
||||
|
||||
goto ReleaseIpIo;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the Tcp4ServiceBinding Protocol on the
|
||||
// controller handle
|
||||
//
|
||||
TcpServiceData->Tcp4ServiceBinding = mTcp4ServiceBinding;
|
||||
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&ControllerHandle,
|
||||
&gEfiTcp4ServiceBindingProtocolGuid,
|
||||
&TcpServiceData->Tcp4ServiceBinding,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStart: Install Tcp4 Service Binding"
|
||||
" Protocol failed for %r\n", Status));
|
||||
|
||||
goto ReleaseTimer;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize member in TcpServiceData
|
||||
//
|
||||
TcpServiceData->ControllerHandle = ControllerHandle;
|
||||
TcpServiceData->Signature = TCP4_DRIVER_SIGNATURE;
|
||||
TcpServiceData->DriverBindingHandle = This->DriverBindingHandle;
|
||||
|
||||
TcpSetVariableData (TcpServiceData);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ReleaseTimer:
|
||||
|
||||
Tcp4DestroyTimer ();
|
||||
|
||||
ReleaseIpIo:
|
||||
|
||||
IpIoDestroy (TcpServiceData->IpIo);
|
||||
|
||||
ReleaseServiceData:
|
||||
|
||||
NetFreePool (TcpServiceData);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to stop driver on.
|
||||
@param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
|
||||
of children is zero stop the entire bus driver.
|
||||
@param ChildHandleBuffer List of Child Handles to Stop.
|
||||
|
||||
@retval EFI_SUCCESS This driver is removed from ControllerHandle.
|
||||
@retval other This driver is not removed from ControllerHandle.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE NicHandle;
|
||||
EFI_SERVICE_BINDING_PROTOCOL *Tcp4ServiceBinding;
|
||||
TCP4_SERVICE_DATA *TcpServiceData;
|
||||
TCP_CB *TcpPcb;
|
||||
SOCKET *Sock;
|
||||
TCP4_PROTO_DATA *TcpProto;
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *NextEntry;
|
||||
|
||||
// Find the NicHandle where Tcp4 ServiceBinding Protocol is installed.
|
||||
//
|
||||
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
|
||||
if (NicHandle == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve the TCP driver Data Structure
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
NicHandle,
|
||||
&gEfiTcp4ServiceBindingProtocolGuid,
|
||||
(VOID **) &Tcp4ServiceBinding,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStop: Locate Tcp4 Service "
|
||||
" Binding Protocol failed with %r\n", Status));
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
TcpServiceData = TCP4_FROM_THIS (Tcp4ServiceBinding);
|
||||
|
||||
//
|
||||
// Kill TCP driver
|
||||
//
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mTcpRunQue) {
|
||||
TcpPcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
|
||||
|
||||
//
|
||||
// Try to destroy this child
|
||||
//
|
||||
Sock = TcpPcb->Sk;
|
||||
TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
|
||||
|
||||
if (TcpProto->TcpService == TcpServiceData) {
|
||||
Status = SockDestroyChild (Sock);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStop: Destroy Tcp "
|
||||
"instance failed with %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mTcpListenQue) {
|
||||
TcpPcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
|
||||
|
||||
//
|
||||
// Try to destroy this child
|
||||
//
|
||||
Sock = TcpPcb->Sk;
|
||||
TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
|
||||
|
||||
if (TcpProto->TcpService == TcpServiceData) {
|
||||
Status = SockDestroyChild (TcpPcb->Sk);
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStop: Destroy Tcp "
|
||||
"instance failed with %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Uninstall TCP servicebinding protocol
|
||||
//
|
||||
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||
NicHandle,
|
||||
&gEfiTcp4ServiceBindingProtocolGuid,
|
||||
Tcp4ServiceBinding,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStop: Uninstall TCP service "
|
||||
"binding protocol failed with %r\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Destroy the IpIO consumed by TCP driver
|
||||
//
|
||||
Status = IpIoDestroy (TcpServiceData->IpIo);
|
||||
|
||||
//
|
||||
// Destroy the heartbeat timer.
|
||||
//
|
||||
Tcp4DestroyTimer ();
|
||||
|
||||
//
|
||||
// Clear the variable.
|
||||
//
|
||||
TcpClearVariableData (TcpServiceData);
|
||||
|
||||
//
|
||||
// Release the TCP service data
|
||||
//
|
||||
NetFreePool (TcpServiceData);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Creates a child handle with a set of TCP4 services.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ChildHandle Pointer to the handle of the child to create. If
|
||||
it is NULL, then a new handle is created. If it is
|
||||
not NULL, then the I/O services are added to the
|
||||
existing child handle.
|
||||
|
||||
@retval EFI_SUCCESS The child handle is created.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources to create the
|
||||
child.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
TCP4_SERVICE_DATA *TcpServiceData;
|
||||
TCP4_PROTO_DATA TcpProto;
|
||||
EFI_STATUS Status;
|
||||
VOID *Ip4;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if (NULL == This || NULL == ChildHandle) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
TcpServiceData = TCP4_FROM_THIS (This);
|
||||
TcpProto.TcpService = TcpServiceData;
|
||||
TcpProto.TcpPcb = NULL;
|
||||
|
||||
//
|
||||
// Create a tcp instance with defualt Tcp default
|
||||
// sock init data and TcpProto
|
||||
//
|
||||
mTcp4DefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;
|
||||
|
||||
Sock = SockCreateChild (&mTcp4DefaultSockData, &TcpProto, sizeof (TCP4_PROTO_DATA));
|
||||
if (NULL == Sock) {
|
||||
TCP4_DEBUG_ERROR (("Tcp4DriverBindingCreateChild: "
|
||||
"No resource to create a Tcp Child\n"));
|
||||
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
*ChildHandle = Sock->SockHandle;
|
||||
|
||||
//
|
||||
// Open the default Ip4 protocol of IP_IO BY_DRIVER.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
TcpServiceData->IpIo->ChildHandle,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
(VOID **) &Ip4,
|
||||
TcpServiceData->DriverBindingHandle,
|
||||
Sock->SockHandle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
SockDestroyChild (Sock);
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destroys a child handle with a set of UDP4 services.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ChildHandle Handle of the child to be destroyed.
|
||||
|
||||
@retval EFI_SUCCESS The TCP4 services are removed from the child
|
||||
handle.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval other The child handle is not destroyed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_TCP4_PROTOCOL *Tcp4;
|
||||
SOCKET *Sock;
|
||||
TCP4_PROTO_DATA *TcpProtoData;
|
||||
TCP4_SERVICE_DATA *TcpServiceData;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if (NULL == This || NULL == ChildHandle) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
|
||||
|
||||
//
|
||||
// retrieve the Tcp4 protocol from ChildHandle
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiTcp4ProtocolGuid,
|
||||
(VOID **) &Tcp4,
|
||||
mTcp4DriverBinding.DriverBindingHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// destroy this sock and related Tcp protocol control
|
||||
// block
|
||||
//
|
||||
Sock = SOCK_FROM_THIS (Tcp4);
|
||||
TcpProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
|
||||
TcpServiceData = TcpProtoData->TcpService;
|
||||
|
||||
Status = SockDestroyChild (Sock);
|
||||
|
||||
//
|
||||
// Close the Ip4 protocol.
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
TcpServiceData->IpIo->ChildHandle,
|
||||
&gEfiIp4ProtocolGuid,
|
||||
TcpServiceData->DriverBindingHandle,
|
||||
ChildHandle
|
||||
);
|
||||
|
||||
ON_EXIT:
|
||||
NET_RESTORE_TPL (OldTpl);
|
||||
return Status;
|
||||
}
|
141
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.h
Normal file
141
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Tcp4Driver.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _TCP4_DRIVER_H_
|
||||
#define _TCP4_DRIVER_H_
|
||||
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
#include <Library/IpIoLib.h>
|
||||
|
||||
#define TCP4_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('T', 'C', 'P', '4')
|
||||
|
||||
#define TCP4_PORT_KNOWN 1024
|
||||
#define TCP4_PORT_USER_RESERVED 65535
|
||||
|
||||
typedef struct _TCP4_HEARTBEAT_TIMER {
|
||||
EFI_EVENT TimerEvent;
|
||||
INTN RefCnt;
|
||||
} TCP4_HEARTBEAT_TIMER;
|
||||
|
||||
typedef struct _TCP4_SERVICE_DATA {
|
||||
UINT32 Signature;
|
||||
EFI_HANDLE ControllerHandle;
|
||||
IP_IO *IpIo; // IP Io consumed by TCP4
|
||||
EFI_SERVICE_BINDING_PROTOCOL Tcp4ServiceBinding;
|
||||
EFI_HANDLE DriverBindingHandle;
|
||||
CHAR16 *MacString;
|
||||
} TCP4_SERVICE_DATA;
|
||||
|
||||
//
|
||||
// Prototype for TCP4 driver Rcv callback function registered to IP_IO
|
||||
//
|
||||
VOID
|
||||
Tcp4RxCallback (
|
||||
IN EFI_STATUS Status,
|
||||
IN ICMP_ERROR IcmpErr,
|
||||
IN EFI_NET_SESSION_DATA *NetSession,
|
||||
IN NET_BUF *Pkt,
|
||||
IN VOID *Context OPTIONAL
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpSendIpPacket (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Nbuf,
|
||||
IN UINT32 Src,
|
||||
IN UINT32 Dest
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
Tcp4Dispatcher (
|
||||
IN SOCKET *Sock,
|
||||
IN SOCK_REQUEST Request,
|
||||
IN VOID *Data OPTIONAL
|
||||
);
|
||||
|
||||
typedef struct _TCP4_PROTO_DATA {
|
||||
TCP4_SERVICE_DATA *TcpService;
|
||||
TCP_CB *TcpPcb;
|
||||
} TCP4_PROTO_DATA;
|
||||
|
||||
#define TCP4_FROM_THIS(a) \
|
||||
CR ( \
|
||||
(a), \
|
||||
TCP4_SERVICE_DATA, \
|
||||
Tcp4ServiceBinding, \
|
||||
TCP4_DRIVER_SIGNATURE \
|
||||
)
|
||||
|
||||
//
|
||||
// Function prototype for the driver's entry point
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4DriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
//
|
||||
// Function prototypes for the Drivr Binding Protocol
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4DriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL * This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4DriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL * This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4DriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
//
|
||||
// Function ptototypes for the ServiceBinding Prococol
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4ServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE *ChildHandle
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4ServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
);
|
||||
|
||||
#endif
|
77
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf
Normal file
77
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf
Normal file
@@ -0,0 +1,77 @@
|
||||
#/** @file
|
||||
# Component name for module Tcp4
|
||||
#
|
||||
# FIX ME!
|
||||
# Copyright (c) 2006, Intel Corporation. All right reserved.
|
||||
#
|
||||
# All rights reserved. This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = Tcp4Dxe
|
||||
FILE_GUID = 6d6963ab-906d-4a65-a7ca-bd40e5d6af4d
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
EDK_RELEASE_VERSION = 0x00020000
|
||||
EFI_SPECIFICATION_VERSION = 0x00020000
|
||||
|
||||
ENTRY_POINT = Tcp4DriverEntryPoint
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
SockImpl.c
|
||||
SockInterface.c
|
||||
Tcp4Proto.h
|
||||
Tcp4Main.h
|
||||
SockImpl.h
|
||||
Tcp4Output.c
|
||||
Tcp4Timer.c
|
||||
Tcp4Option.h
|
||||
Tcp4Dispatcher.c
|
||||
Tcp4Input.c
|
||||
Tcp4Misc.c
|
||||
Tcp4Main.c
|
||||
Socket.h
|
||||
ComponentName.c
|
||||
Tcp4Driver.h
|
||||
Tcp4Io.c
|
||||
Tcp4Driver.c
|
||||
Tcp4Func.h
|
||||
Tcp4Option.c
|
||||
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
UefiLib
|
||||
BaseLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiRuntimeServicesTableLib
|
||||
DebugLib
|
||||
NetLib
|
||||
IpIoLib
|
||||
|
||||
[Protocols]
|
||||
gEfiIp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiTcp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiIp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiTcp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
|
90
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.msa
Normal file
90
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.msa
Normal file
@@ -0,0 +1,90 @@
|
||||
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<MsaHeader>
|
||||
<ModuleName>Tcp4Dxe</ModuleName>
|
||||
<ModuleType>DXE_DRIVER</ModuleType>
|
||||
<GuidValue>6d6963ab-906d-4a65-a7ca-bd40e5d6af4d</GuidValue>
|
||||
<Version>1.0</Version>
|
||||
<Abstract>Component name for module Tcp4</Abstract>
|
||||
<Description>FIX ME!</Description>
|
||||
<Copyright>Copyright (c) 2006, Intel Corporation. All right reserved.</Copyright>
|
||||
<License>All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
|
||||
<Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
|
||||
</MsaHeader>
|
||||
<ModuleDefinitions>
|
||||
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
|
||||
<BinaryModule>false</BinaryModule>
|
||||
<OutputFileBasename>Tcp4Dxe</OutputFileBasename>
|
||||
</ModuleDefinitions>
|
||||
<LibraryClassDefinitions>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>DebugLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiRuntimeServicesTableLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiDriverEntryPoint</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiBootServicesTableLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>BaseLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiLib</Keyword>
|
||||
</LibraryClass>
|
||||
</LibraryClassDefinitions>
|
||||
<SourceFiles>
|
||||
<Filename>Tcp4Option.c</Filename>
|
||||
<Filename>Tcp4Func.h</Filename>
|
||||
<Filename>Tcp4Driver.c</Filename>
|
||||
<Filename>Tcp4Io.c</Filename>
|
||||
<Filename>Tcp4Driver.h</Filename>
|
||||
<Filename>ComponentName.c</Filename>
|
||||
<Filename>Socket.h</Filename>
|
||||
<Filename>Tcp4Main.c</Filename>
|
||||
<Filename>Tcp4Misc.c</Filename>
|
||||
<Filename>Tcp4Input.c</Filename>
|
||||
<Filename>Tcp4Dispatcher.c</Filename>
|
||||
<Filename>Tcp4Option.h</Filename>
|
||||
<Filename>Tcp4Timer.c</Filename>
|
||||
<Filename>Tcp4Output.c</Filename>
|
||||
<Filename>SockImpl.h</Filename>
|
||||
<Filename>Tcp4Main.h</Filename>
|
||||
<Filename>Tcp4Proto.h</Filename>
|
||||
<Filename>SockInterface.c</Filename>
|
||||
<Filename>SockImpl.c</Filename>
|
||||
</SourceFiles>
|
||||
<PackageDependencies>
|
||||
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
|
||||
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
|
||||
</PackageDependencies>
|
||||
<Protocols>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiTcp4ProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiIp4ServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiTcp4ServiceBindingProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiIp4ProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
</Protocols>
|
||||
<Externs>
|
||||
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
|
||||
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
|
||||
<Extern>
|
||||
<ModuleEntryPoint>Tcp4DriverEntryPoint</ModuleEntryPoint>
|
||||
</Extern>
|
||||
</Externs>
|
||||
</ModuleSurfaceArea>
|
353
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Func.h
Normal file
353
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Func.h
Normal file
@@ -0,0 +1,353 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Tcp4Func.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _TCP4_FUNC_H_
|
||||
#define _TCP4_FUNC_H_
|
||||
|
||||
//
|
||||
// Declaration of all the functions in TCP
|
||||
// protocol. It is intended to keep tcp.h
|
||||
// clear.
|
||||
//
|
||||
|
||||
//
|
||||
// Functions in tcp.c
|
||||
//
|
||||
BOOLEAN
|
||||
TcpFindTcbByPeer (
|
||||
IN EFI_IPv4_ADDRESS *Addr,
|
||||
IN TCP_PORTNO Port
|
||||
);
|
||||
|
||||
TCP_CB *
|
||||
TcpLocateTcb (
|
||||
IN TCP_PORTNO LocalPort,
|
||||
IN UINT32 LocalIp,
|
||||
IN TCP_PORTNO RemotePort,
|
||||
IN UINT32 RemoteIp,
|
||||
IN BOOLEAN Syn
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpInsertTcb (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
TCP_CB *
|
||||
TcpCloneTcb (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
TCP_SEQNO
|
||||
TcpGetIss (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpInitTcbLocal (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpInitTcbPeer (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP_SEG *Seg,
|
||||
IN TCP_OPTION *Opt
|
||||
);
|
||||
|
||||
UINT16
|
||||
TcpGetRcvMss (
|
||||
IN SOCKET *Sock
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpSetState (
|
||||
IN TCP_CB *Tcb,
|
||||
IN UINT8 State
|
||||
);
|
||||
|
||||
//
|
||||
// Functions in Tcp4Output.c
|
||||
//
|
||||
INTN
|
||||
TcpSendIpPacket (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Nbuf,
|
||||
IN UINT32 Src,
|
||||
IN UINT32 Dst
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpToSendData (
|
||||
IN TCP_CB *Tcb,
|
||||
IN INTN Force
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpToSendAck (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpSendAck (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpSendZeroProbe (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpDeliverData (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpSendReset (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP_HEAD *Head,
|
||||
IN INT32 Len,
|
||||
IN UINT32 Local,
|
||||
IN UINT32 Remote
|
||||
);
|
||||
|
||||
UINT32
|
||||
TcpRcvWinOld (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
UINT32
|
||||
TcpRcvWinNow (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpRetransmit (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP_SEQNO Seq
|
||||
);
|
||||
|
||||
UINT32
|
||||
TcpDataToSend (
|
||||
IN TCP_CB *Tcb,
|
||||
IN INTN Force
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpVerifySegment (
|
||||
IN NET_BUF *Nbuf
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpCheckSndQue (
|
||||
IN NET_LIST_ENTRY *Head
|
||||
);
|
||||
|
||||
NET_BUF *
|
||||
TcpGetSegmentSndQue (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP_SEQNO Seq,
|
||||
IN UINT32 Len
|
||||
);
|
||||
|
||||
NET_BUF *
|
||||
TcpGetSegmentSock (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP_SEQNO Seq,
|
||||
IN UINT32 Len
|
||||
);
|
||||
|
||||
NET_BUF *
|
||||
TcpGetSegment (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP_SEQNO Seq,
|
||||
IN UINT32 Len
|
||||
);
|
||||
|
||||
TCP_SEQNO
|
||||
TcpGetMaxSndNxt (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
//
|
||||
// Functions from Tcp4Input.c
|
||||
//
|
||||
VOID
|
||||
TcpIcmpInput (
|
||||
IN NET_BUF *Nbuf,
|
||||
IN ICMP_ERROR IcmpErr,
|
||||
IN UINT32 Src,
|
||||
IN UINT32 Dst
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpInput (
|
||||
IN NET_BUF *Nbuf,
|
||||
IN UINT32 Src,
|
||||
IN UINT32 Dst
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpSeqAcceptable (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP_SEG *Seg
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpFastRecover (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP_SEG *Seg
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpFastLossRecover (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP_SEG *Seg
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpComputeRtt (
|
||||
IN TCP_CB *Tcb,
|
||||
IN UINT32 Measure
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpTrimInWnd (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Buf
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpQueueData (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Nbuf
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpAdjustSndQue (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP_SEQNO Ack
|
||||
);
|
||||
|
||||
//
|
||||
// Functions from Tcp4Misc.c
|
||||
//
|
||||
UINT16
|
||||
TcpChecksum (
|
||||
IN NET_BUF *Buf,
|
||||
IN UINT16 HeadChecksum
|
||||
);
|
||||
|
||||
TCP_SEG *
|
||||
TcpFormatNetbuf (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Nbuf
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpOnAppConnect (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpOnAppConsume (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpOnAppClose (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpOnAppSend (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpOnAppAbort (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpResetConnection (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
//
|
||||
// Functions in Tcp4Timer.c
|
||||
//
|
||||
VOID
|
||||
TcpClose (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
TcpTicking (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpSetTimer (
|
||||
IN TCP_CB *Tcb,
|
||||
IN UINT16 Timer,
|
||||
IN UINT32 TimeOut
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpClearTimer (
|
||||
IN TCP_CB *Tcb,
|
||||
IN UINT16 Timer
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpClearAllTimer (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpSetProbeTimer (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpSetKeepaliveTimer (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpBackoffRto (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
TcpSetVariableData (
|
||||
IN TCP4_SERVICE_DATA *Tcp4Service
|
||||
);
|
||||
|
||||
VOID
|
||||
TcpClearVariableData (
|
||||
IN TCP4_SERVICE_DATA *Tcp4Service
|
||||
);
|
||||
|
||||
#endif
|
1486
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Input.c
Normal file
1486
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Input.c
Normal file
File diff suppressed because it is too large
Load Diff
117
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Io.c
Normal file
117
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Io.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Tcp4Io.c
|
||||
|
||||
Abstract:
|
||||
|
||||
I/O interfaces between TCP and IpIo.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include "Tcp4Main.h"
|
||||
|
||||
|
||||
/**
|
||||
Packet receive callback function provided to IP_IO, used to call
|
||||
the proper function to handle the packet received by IP.
|
||||
|
||||
@param Status Status of the received packet.
|
||||
@param IcmpErr ICMP error number.
|
||||
@param NetSession Pointer to the net session of this packet.
|
||||
@param Pkt Pointer to the recieved packet.
|
||||
@param Context Pointer to the context configured in IpIoOpen(), not used
|
||||
now.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
VOID
|
||||
Tcp4RxCallback (
|
||||
IN EFI_STATUS Status,
|
||||
IN ICMP_ERROR IcmpErr,
|
||||
IN EFI_NET_SESSION_DATA *NetSession,
|
||||
IN NET_BUF *Pkt,
|
||||
IN VOID *Context OPTIONAL
|
||||
)
|
||||
{
|
||||
if (EFI_SUCCESS == Status) {
|
||||
TcpInput (Pkt, NetSession->Source, NetSession->Dest);
|
||||
} else {
|
||||
TcpIcmpInput (Pkt, IcmpErr, NetSession->Source, NetSession->Dest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Send the segment to IP via IpIo function.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param Nbuf Pointer to the TCP segment to be sent.
|
||||
@param Src Source address of the TCP segment.
|
||||
@param Dest Destination address of the TCP segment.
|
||||
|
||||
@retval 0 The segment was sent out successfully.
|
||||
@retval -1 The segment was failed to send.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpSendIpPacket (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Nbuf,
|
||||
IN UINT32 Src,
|
||||
IN UINT32 Dest
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IP_IO *IpIo;
|
||||
IP_IO_OVERRIDE Override;
|
||||
SOCKET *Sock;
|
||||
VOID *IpSender;
|
||||
TCP4_PROTO_DATA *TcpProto;
|
||||
|
||||
if (NULL == Tcb) {
|
||||
|
||||
IpIo = NULL;
|
||||
IpSender = IpIoFindSender (&IpIo, Src);
|
||||
|
||||
if (IpSender == NULL) {
|
||||
TCP4_DEBUG_WARN (("TcpSendIpPacket: No appropriate IpSender.\n"));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
|
||||
Sock = Tcb->Sk;
|
||||
TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
|
||||
IpIo = TcpProto->TcpService->IpIo;
|
||||
IpSender = Tcb->IpInfo;
|
||||
}
|
||||
|
||||
Override.TypeOfService = 0;
|
||||
Override.TimeToLive = 255;
|
||||
Override.DoNotFragment = FALSE;
|
||||
Override.Protocol = EFI_IP_PROTO_TCP;
|
||||
EFI_IP4 (Override.GatewayAddress) = 0;
|
||||
EFI_IP4 (Override.SourceAddress) = Src;
|
||||
|
||||
Status = IpIoSend (IpIo, Nbuf, IpSender, NULL, NULL, Dest, &Override);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
TCP4_DEBUG_ERROR (("TcpSendIpPacket: return %r error\n", Status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
564
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Main.c
Normal file
564
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Main.c
Normal file
@@ -0,0 +1,564 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Tcp4Main.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Implementation of TCP4 protocol services.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Tcp4Main.h"
|
||||
|
||||
|
||||
/**
|
||||
Check the integrity of the data buffer.
|
||||
|
||||
@param DataLen The total length of the data buffer.
|
||||
@param FragmentCount The fragment count of the fragment table.
|
||||
@param FragmentTable Pointer to the fragment table of the data
|
||||
buffer.
|
||||
|
||||
@retval EFI_SUCCESS The integrity check is passed.
|
||||
@retval EFI_INVALID_PARAMETER The integrity check is failed.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
Tcp4ChkDataBuf (
|
||||
IN UINT32 DataLen,
|
||||
IN UINT32 FragmentCount,
|
||||
IN EFI_TCP4_FRAGMENT_DATA *FragmentTable
|
||||
)
|
||||
{
|
||||
UINT32 Index;
|
||||
|
||||
UINT32 Len;
|
||||
|
||||
for (Index = 0, Len = 0; Index < FragmentCount; Index++) {
|
||||
Len = Len + FragmentTable[Index].FragmentLength;
|
||||
}
|
||||
|
||||
if (DataLen != Len) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the current operational status.
|
||||
|
||||
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param Tcp4State Pointer to the buffer to receive the current TCP
|
||||
state.
|
||||
@param Tcp4ConfigData Pointer to the buffer to receive the current TCP
|
||||
configuration.
|
||||
@param Ip4ModeData Pointer to the buffer to receive the current
|
||||
IPv4 configuration.
|
||||
@param MnpConfigData Pointer to the buffer to receive the current MNP
|
||||
configuration data indirectly used by the TCPv4
|
||||
Instance.
|
||||
@param SnpModeData Pointer to the buffer to receive the current SNP
|
||||
configuration data indirectly used by the TCPv4
|
||||
Instance.
|
||||
|
||||
@retval EFI_SUCCESS The mode data was read.
|
||||
@retval EFI_NOT_STARTED No configuration data is available because this
|
||||
instance hasn't been started.
|
||||
@retval EFI_INVALID_PARAMETER This is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4GetModeData (
|
||||
IN CONST EFI_TCP4_PROTOCOL * This,
|
||||
OUT EFI_TCP4_CONNECTION_STATE * Tcp4State OPTIONAL,
|
||||
OUT EFI_TCP4_CONFIG_DATA * Tcp4ConfigData OPTIONAL,
|
||||
OUT EFI_IP4_MODE_DATA * Ip4ModeData OPTIONAL,
|
||||
OUT EFI_MANAGED_NETWORK_CONFIG_DATA * MnpConfigData OPTIONAL,
|
||||
OUT EFI_SIMPLE_NETWORK_MODE * SnpModeData OPTIONAL
|
||||
)
|
||||
{
|
||||
TCP4_MODE_DATA TcpMode;
|
||||
SOCKET *Sock;
|
||||
|
||||
if (NULL == This) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Sock = SOCK_FROM_THIS (This);
|
||||
|
||||
TcpMode.Tcp4State = Tcp4State;
|
||||
TcpMode.Tcp4ConfigData = Tcp4ConfigData;
|
||||
TcpMode.Ip4ModeData = Ip4ModeData;
|
||||
TcpMode.MnpConfigData = MnpConfigData;
|
||||
TcpMode.SnpModeData = SnpModeData;
|
||||
|
||||
return SockGetMode (Sock, &TcpMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initialize or brutally reset the operational parameters for
|
||||
this EFI TCPv4 instance.
|
||||
|
||||
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param TcpConfigData Pointer to the configure data to configure the
|
||||
instance.
|
||||
|
||||
@retval EFI_SUCCESS The operational settings are set, changed, or
|
||||
reset successfully.
|
||||
@retval EFI_NO_MAPPING When using a default address, configuration
|
||||
(through DHCP, BOOTP, RARP, etc.) is not
|
||||
finished.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_ACCESS_DENIED Configuring TCP instance when it is already
|
||||
configured.
|
||||
@retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
|
||||
@retval EFI_UNSUPPORTED One or more of the control options are not
|
||||
supported in the implementation.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Configure (
|
||||
IN EFI_TCP4_PROTOCOL * This,
|
||||
IN EFI_TCP4_CONFIG_DATA * TcpConfigData OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_TCP4_OPTION *Option;
|
||||
SOCKET *Sock;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (NULL == This) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Tcp protocol related parameter check will be conducted here
|
||||
//
|
||||
if (NULL != TcpConfigData) {
|
||||
if ((EFI_IP4 (TcpConfigData->AccessPoint.RemoteAddress) != 0) &&
|
||||
!Ip4IsUnicast (EFI_NTOHL (TcpConfigData->AccessPoint.RemoteAddress), 0)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!TcpConfigData->AccessPoint.UseDefaultAddress) {
|
||||
if (!Ip4IsUnicast (EFI_NTOHL (TcpConfigData->AccessPoint.StationAddress), 0) ||
|
||||
!IP4_IS_VALID_NETMASK (EFI_NTOHL (TcpConfigData->AccessPoint.SubnetMask))
|
||||
) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
if (TcpConfigData->AccessPoint.ActiveFlag &&
|
||||
(0 == TcpConfigData->AccessPoint.RemotePort ||
|
||||
(EFI_IP4 (TcpConfigData->AccessPoint.RemoteAddress) == 0))
|
||||
) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Option = TcpConfigData->ControlOption;
|
||||
if ((NULL != Option) &&
|
||||
(Option->EnableSelectiveAck || Option->EnablePathMtuDiscovery)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
Sock = SOCK_FROM_THIS (This);
|
||||
|
||||
if (NULL == TcpConfigData) {
|
||||
return SockFlush (Sock);
|
||||
}
|
||||
|
||||
Status = SockConfigure (Sock, TcpConfigData);
|
||||
|
||||
if (EFI_NO_MAPPING == Status) {
|
||||
Sock->ConfigureState = SO_NO_MAPPING;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Add or delete routing entries.
|
||||
|
||||
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param DeleteRoute If TRUE, delete the specified route from routing
|
||||
table; if FALSE, add the specified route to
|
||||
routing table.
|
||||
@param SubnetAddress The destination network.
|
||||
@param SubnetMask The subnet mask for the destination network.
|
||||
@param GatewayAddress The gateway address for this route.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance has not been
|
||||
configured.
|
||||
@retval EFI_NO_MAPPING When using a default address, configuration
|
||||
(through DHCP, BOOTP, RARP, etc.) is not
|
||||
finished.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to add the
|
||||
entry to the routing table.
|
||||
@retval EFI_NOT_FOUND This route is not in the routing table.
|
||||
@retval EFI_ACCESS_DENIED This route is already in the routing table.
|
||||
@retval EFI_UNSUPPORTED The TCP driver does not support this operation.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Routes (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN BOOLEAN DeleteRoute,
|
||||
IN EFI_IPv4_ADDRESS *SubnetAddress,
|
||||
IN EFI_IPv4_ADDRESS *SubnetMask,
|
||||
IN EFI_IPv4_ADDRESS *GatewayAddress
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
TCP4_ROUTE_INFO RouteInfo;
|
||||
|
||||
if (NULL == This) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Sock = SOCK_FROM_THIS (This);
|
||||
|
||||
RouteInfo.DeleteRoute = DeleteRoute;
|
||||
RouteInfo.SubnetAddress = SubnetAddress;
|
||||
RouteInfo.SubnetMask = SubnetMask;
|
||||
RouteInfo.GatewayAddress = GatewayAddress;
|
||||
|
||||
return SockRoute (Sock, &RouteInfo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Initiate a nonblocking TCP connection request for an active TCP instance.
|
||||
|
||||
@param This Pointer to the EFI_TCP4_PROTOCOL instance
|
||||
@param ConnectionToken Pointer to the connection token to return when
|
||||
the TCP three way handshake finishes.
|
||||
|
||||
@retval EFI_SUCCESS The connection request is successfully
|
||||
initiated.
|
||||
@retval EFI_NOT_STARTED This EFI_TCP4_PROTOCOL instance hasn't been
|
||||
configured.
|
||||
@retval EFI_ACCESS_DENIED The instance is not configured as an active one
|
||||
or it is not in Tcp4StateClosed state.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES The driver can't allocate enough resource to
|
||||
initiate the active open.
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Connect (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
|
||||
if (NULL == This ||
|
||||
NULL == ConnectionToken ||
|
||||
NULL == ConnectionToken->CompletionToken.Event) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Sock = SOCK_FROM_THIS (This);
|
||||
|
||||
return SockConnect (Sock, ConnectionToken);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Listen on the passive instance to accept an incoming connection request.
|
||||
|
||||
@param This Pointer to the EFI_TCP4_PROTOCOL instance
|
||||
@param ListenToken Pointer to the listen token to return when
|
||||
operation finishes.
|
||||
|
||||
@retval EFI_SUCCESS The listen token has been queued successfully.
|
||||
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
|
||||
configured.
|
||||
@retval EFI_ACCESS_DENIED The instatnce is not a passive one or it is not
|
||||
in Tcp4StateListen state or a same listen token
|
||||
has already existed in the listen token queue of
|
||||
this TCP instance.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to finish
|
||||
the operation.
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Accept (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN EFI_TCP4_LISTEN_TOKEN *ListenToken
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
|
||||
if (NULL == This ||
|
||||
NULL == ListenToken ||
|
||||
NULL == ListenToken->CompletionToken.Event) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Sock = SOCK_FROM_THIS (This);
|
||||
|
||||
return SockAccept (Sock, ListenToken);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Queues outgoing data into the transmit queue
|
||||
|
||||
@param This Pointer to the EFI_TCP4_PROTOCOL instance
|
||||
@param Token Pointer to the completion token to queue to the
|
||||
transmit queue
|
||||
|
||||
@retval EFI_SUCCESS The data has been queued for transmission
|
||||
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
|
||||
configured.
|
||||
@retval EFI_NO_MAPPING When using a default address, configuration
|
||||
(DHCP, BOOTP, RARP, etc.) is not finished yet.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid
|
||||
@retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:
|
||||
* A transmit completion token with the same
|
||||
Token-> CompletionToken.Event was already in the
|
||||
transmission queue. * The current instance is in
|
||||
Tcp4StateClosed state * The current instance is
|
||||
a passive one and it is in Tcp4StateListen
|
||||
state. * User has called Close() to disconnect
|
||||
this connection.
|
||||
@retval EFI_NOT_READY The completion token could not be queued because
|
||||
the transmit queue is full.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not queue the transmit data because of
|
||||
resource shortage.
|
||||
@retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or
|
||||
address.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Transmit (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN EFI_TCP4_IO_TOKEN *Token
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (NULL == This ||
|
||||
NULL == Token ||
|
||||
NULL == Token->CompletionToken.Event ||
|
||||
NULL == Token->Packet.TxData ||
|
||||
0 == Token->Packet.TxData->FragmentCount ||
|
||||
0 == Token->Packet.TxData->DataLength
|
||||
) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = Tcp4ChkDataBuf (
|
||||
Token->Packet.TxData->DataLength,
|
||||
Token->Packet.TxData->FragmentCount,
|
||||
Token->Packet.TxData->FragmentTable
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Sock = SOCK_FROM_THIS (This);
|
||||
|
||||
return SockSend (Sock, Token);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Place an asynchronous receive request into the receiving queue.
|
||||
|
||||
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param Token Pointer to a token that is associated with the
|
||||
receive data descriptor.
|
||||
|
||||
@retval EFI_SUCCESS The receive completion token was cached
|
||||
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
|
||||
configured.
|
||||
@retval EFI_NO_MAPPING When using a default address, configuration
|
||||
(DHCP, BOOTP, RARP, etc.) is not finished yet.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued
|
||||
due to a lack of system resources.
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
@retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:
|
||||
* A receive completion token with the same
|
||||
Token->CompletionToken.Event was already in the
|
||||
receive queue. * The current instance is in
|
||||
Tcp4StateClosed state. * The current instance is
|
||||
a passive one and it is in Tcp4StateListen
|
||||
state. * User has called Close() to disconnect
|
||||
this connection.
|
||||
@retval EFI_CONNECTION_FIN The communication peer has closed the connection
|
||||
and there is no any buffered data in the receive
|
||||
buffer of this instance.
|
||||
@retval EFI_NOT_READY The receive request could not be queued because
|
||||
the receive queue is full.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Receive (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN EFI_TCP4_IO_TOKEN *Token
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (NULL == This ||
|
||||
NULL == Token ||
|
||||
NULL == Token->CompletionToken.Event ||
|
||||
NULL == Token->Packet.RxData ||
|
||||
0 == Token->Packet.RxData->FragmentCount ||
|
||||
0 == Token->Packet.RxData->DataLength
|
||||
) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = Tcp4ChkDataBuf (
|
||||
Token->Packet.RxData->DataLength,
|
||||
Token->Packet.RxData->FragmentCount,
|
||||
Token->Packet.RxData->FragmentTable
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Sock = SOCK_FROM_THIS (This);
|
||||
|
||||
return SockRcv (Sock, Token);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Disconnecting a TCP connection gracefully or reset a TCP connection.
|
||||
|
||||
@param This Pointer to the EFI_TCP4_PROTOCOL instance
|
||||
@param CloseToken Pointer to the close token to return when
|
||||
operation finishes.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully
|
||||
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
|
||||
configured.
|
||||
@retval EFI_ACCESS_DENIED One or more of the following are TRUE: *
|
||||
Configure() has been called with TcpConfigData
|
||||
set to NULL and this function has not returned.
|
||||
* Previous Close() call on this instance has not
|
||||
finished.
|
||||
@retval EFI_INVALID_PARAMETER One ore more parameters are invalid
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the
|
||||
operation
|
||||
@retval EFI_DEVICE_ERROR Any unexpected and not belonged to above
|
||||
category error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Close (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN EFI_TCP4_CLOSE_TOKEN *CloseToken
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
|
||||
if (NULL == This ||
|
||||
NULL == CloseToken ||
|
||||
NULL == CloseToken->CompletionToken.Event) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Sock = SOCK_FROM_THIS (This);
|
||||
|
||||
return SockClose (Sock, CloseToken, CloseToken->AbortOnClose);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Abort an asynchronous connection, listen, transmission or receive request.
|
||||
|
||||
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param Token Pointer to a token that has been issued by
|
||||
Connect(), Accept(), Transmit() or Receive(). If
|
||||
NULL, all pending tokens issued by above four
|
||||
functions will be aborted.
|
||||
|
||||
@retval EFI_UNSUPPORTED The operation is not supported in current
|
||||
implementation.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Cancel (
|
||||
IN EFI_TCP4_PROTOCOL * This,
|
||||
IN EFI_TCP4_COMPLETION_TOKEN * Token OPTIONAL
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Poll to receive incoming data and transmit outgoing segments.
|
||||
|
||||
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS Incoming or outgoing data was processed.
|
||||
@retval EFI_INVALID_PARAMETER This is NULL.
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
@retval EFI_NOT_READY No incoming or outgoing data was processed.
|
||||
@retval EFI_TIMEOUT Data was dropped out of the transmission or
|
||||
receive queue. Consider increasing the polling
|
||||
rate.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Poll (
|
||||
IN EFI_TCP4_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (NULL == This) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Sock = SOCK_FROM_THIS (This);
|
||||
|
||||
Status = Sock->ProtoHandler (Sock, SOCK_POLL, NULL);
|
||||
|
||||
return Status;
|
||||
}
|
176
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Main.h
Normal file
176
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Main.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Tcp4Main.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _TCP4_MAIN_H_
|
||||
#define _TCP4_MAIN_H_
|
||||
|
||||
#include "Socket.h"
|
||||
|
||||
#include "Tcp4Proto.h"
|
||||
#include "Tcp4Driver.h"
|
||||
|
||||
|
||||
extern UINT16 mTcp4RandomPort;
|
||||
|
||||
//
|
||||
// Driver Produced Protocol Prototypes
|
||||
//
|
||||
//@MT:#include EFI_PROTOCOL_PRODUCER (Tcp4)
|
||||
|
||||
#define TCP4_DEBUG_ERROR(PrintArg) NET_DEBUG_ERROR ("Tcp", PrintArg)
|
||||
#define TCP4_DEBUG_WARN(PrintArg) NET_DEBUG_WARNING ("Tcp", PrintArg)
|
||||
#define TCP4_DEBUG_TRACE(PrintArg) NET_DEBUG_TRACE ("Tcp", PrintArg)
|
||||
|
||||
//
|
||||
// Function prototype for the Tcp4 socket request handler
|
||||
//
|
||||
EFI_STATUS
|
||||
Tcp4Dispatcher (
|
||||
IN SOCKET *Sock,
|
||||
IN SOCK_REQUEST Request,
|
||||
IN VOID *Data OPTIONAL
|
||||
);
|
||||
|
||||
typedef struct _TCP4_MODE_DATA {
|
||||
EFI_TCP4_CONNECTION_STATE *Tcp4State;
|
||||
EFI_TCP4_CONFIG_DATA *Tcp4ConfigData;
|
||||
EFI_IP4_MODE_DATA *Ip4ModeData;
|
||||
EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData;
|
||||
EFI_SIMPLE_NETWORK_MODE *SnpModeData;
|
||||
} TCP4_MODE_DATA;
|
||||
|
||||
typedef struct _TCP4_ROUTE_INFO {
|
||||
BOOLEAN DeleteRoute;
|
||||
EFI_IPv4_ADDRESS *SubnetAddress;
|
||||
EFI_IPv4_ADDRESS *SubnetMask;
|
||||
EFI_IPv4_ADDRESS *GatewayAddress;
|
||||
} TCP4_ROUTE_INFO;
|
||||
|
||||
//
|
||||
// Get the mode data of a TCP instance
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4GetModeData (
|
||||
IN CONST EFI_TCP4_PROTOCOL * This,
|
||||
OUT EFI_TCP4_CONNECTION_STATE * Tcp4State OPTIONAL,
|
||||
OUT EFI_TCP4_CONFIG_DATA * Tcp4ConfigData OPTIONAL,
|
||||
OUT EFI_IP4_MODE_DATA * Ip4ModeData OPTIONAL,
|
||||
OUT EFI_MANAGED_NETWORK_CONFIG_DATA * MnpConfigData OPTIONAL,
|
||||
OUT EFI_SIMPLE_NETWORK_MODE * SnpModeData OPTIONAL
|
||||
);
|
||||
|
||||
//
|
||||
// Initialize or reset a TCP instance
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Configure (
|
||||
IN EFI_TCP4_PROTOCOL * This,
|
||||
IN EFI_TCP4_CONFIG_DATA * TcpConfigData OPTIONAL
|
||||
);
|
||||
|
||||
//
|
||||
// Add a route entry to the route table
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Routes (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN BOOLEAN DeleteRoute,
|
||||
IN EFI_IPv4_ADDRESS *SubnetAddress,
|
||||
IN EFI_IPv4_ADDRESS *SubnetMask,
|
||||
IN EFI_IPv4_ADDRESS *GatewayAddress
|
||||
);
|
||||
|
||||
//
|
||||
// Issue an asynchronous connection establishment
|
||||
// request to the peer
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Connect (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken
|
||||
);
|
||||
|
||||
//
|
||||
// Issue an asynchronous listent token to accept an
|
||||
// incoming connection reques
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Accept (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN EFI_TCP4_LISTEN_TOKEN *ListenToken
|
||||
);
|
||||
|
||||
//
|
||||
// Issue an asynchronous IO token to transmit some data
|
||||
// through this TCP instance
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Transmit (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN EFI_TCP4_IO_TOKEN *Token
|
||||
);
|
||||
|
||||
//
|
||||
// Issue an asynchronous IO token to receive some data
|
||||
// through this TCP instance
|
||||
//
|
||||
EFI_STATUS
|
||||
Tcp4Receive (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN EFI_TCP4_IO_TOKEN *Token
|
||||
);
|
||||
|
||||
//
|
||||
// Issue an asynchronous CloseToken to close a TCP
|
||||
// connection represented by instance
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Close (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN EFI_TCP4_CLOSE_TOKEN *CloseToken
|
||||
);
|
||||
|
||||
//
|
||||
// cancle an connect, listent or IO token
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Cancel (
|
||||
IN EFI_TCP4_PROTOCOL * This,
|
||||
IN EFI_TCP4_COMPLETION_TOKEN * Token OPTIONAL
|
||||
);
|
||||
|
||||
//
|
||||
// poll data from NIC for receive
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Poll (
|
||||
IN EFI_TCP4_PROTOCOL *This
|
||||
);
|
||||
|
||||
#endif
|
1091
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Misc.c
Normal file
1091
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Misc.c
Normal file
File diff suppressed because it is too large
Load Diff
380
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Option.c
Normal file
380
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Option.c
Normal file
@@ -0,0 +1,380 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Tcp4Option.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Routines to process TCP option.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Tcp4Main.h"
|
||||
|
||||
STATIC
|
||||
UINT16
|
||||
TcpGetUint16 (
|
||||
IN UINT8 *Buf
|
||||
)
|
||||
{
|
||||
UINT16 Value;
|
||||
NetCopyMem (&Value, Buf, sizeof (UINT16));
|
||||
return NTOHS (Value);
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
TcpPutUint16 (
|
||||
IN UINT8 *Buf,
|
||||
IN UINT16 Data
|
||||
)
|
||||
{
|
||||
Data = HTONS (Data);
|
||||
NetCopyMem (Buf, &Data, sizeof (UINT16));
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT32
|
||||
TcpGetUint32 (
|
||||
IN UINT8 *Buf
|
||||
)
|
||||
{
|
||||
UINT32 Value;
|
||||
NetCopyMem (&Value, Buf, sizeof (UINT32));
|
||||
return NTOHL (Value);
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
TcpPutUint32 (
|
||||
IN UINT8 *Buf,
|
||||
IN UINT32 Data
|
||||
)
|
||||
{
|
||||
Data = HTONL (Data);
|
||||
NetCopyMem (Buf, &Data, sizeof (UINT32));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Compute the window scale value according to the given
|
||||
buffer size.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@retval UINT8 The scale value.
|
||||
|
||||
**/
|
||||
UINT8
|
||||
TcpComputeScale (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
UINT8 Scale;
|
||||
UINT32 BufSize;
|
||||
|
||||
ASSERT (Tcb && Tcb->Sk);
|
||||
|
||||
BufSize = GET_RCV_BUFFSIZE (Tcb->Sk);
|
||||
|
||||
Scale = 0;
|
||||
while ((Scale < TCP_OPTION_MAX_WS) &&
|
||||
((UINT32) (TCP_OPTION_MAX_WIN << Scale) < BufSize)) {
|
||||
|
||||
Scale++;
|
||||
}
|
||||
|
||||
return Scale;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build the TCP option in three-way handshake.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param Nbuf Pointer to the buffer to store the options.
|
||||
|
||||
@return The total length of the TCP option field.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
TcpSynBuildOption (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Nbuf
|
||||
)
|
||||
{
|
||||
char *Data;
|
||||
UINT16 Len;
|
||||
|
||||
ASSERT (Tcb && Nbuf && !Nbuf->Tcp);
|
||||
|
||||
Len = 0;
|
||||
|
||||
//
|
||||
// Add timestamp option if not disabled by application
|
||||
// and it is the first SYN segment or the peer has sent
|
||||
// us its timestamp.
|
||||
//
|
||||
if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS) &&
|
||||
(!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
|
||||
TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS))) {
|
||||
|
||||
Data = NetbufAllocSpace (
|
||||
Nbuf,
|
||||
TCP_OPTION_TS_ALIGNED_LEN,
|
||||
NET_BUF_HEAD
|
||||
);
|
||||
|
||||
ASSERT (Data);
|
||||
Len += TCP_OPTION_TS_ALIGNED_LEN;
|
||||
|
||||
TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
|
||||
TcpPutUint32 (Data + 4, mTcpTick);
|
||||
TcpPutUint32 (Data + 8, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Build window scale option, only when are configured
|
||||
// to send WS option, and either we are doing active
|
||||
// open or we have received WS option from peer.
|
||||
//
|
||||
if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS) &&
|
||||
(!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
|
||||
TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS))) {
|
||||
|
||||
Data = NetbufAllocSpace (
|
||||
Nbuf,
|
||||
TCP_OPTION_WS_ALIGNED_LEN,
|
||||
NET_BUF_HEAD
|
||||
);
|
||||
|
||||
ASSERT (Data);
|
||||
|
||||
Len += TCP_OPTION_WS_ALIGNED_LEN;
|
||||
TcpPutUint32 (Data, TCP_OPTION_WS_FAST | TcpComputeScale (Tcb));
|
||||
}
|
||||
|
||||
//
|
||||
// Build MSS option
|
||||
//
|
||||
Data = NetbufAllocSpace (Nbuf, TCP_OPTION_MSS_LEN, 1);
|
||||
ASSERT (Data);
|
||||
|
||||
Len += TCP_OPTION_MSS_LEN;
|
||||
TcpPutUint32 (Data, TCP_OPTION_MSS_FAST | Tcb->RcvMss);
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build the TCP option in synchronized states.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param Nbuf Pointer to the buffer to store the options.
|
||||
|
||||
@return The total length of the TCP option field.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
TcpBuildOption (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Nbuf
|
||||
)
|
||||
{
|
||||
char *Data;
|
||||
UINT16 Len;
|
||||
|
||||
ASSERT (Tcb && Nbuf && !Nbuf->Tcp);
|
||||
Len = 0;
|
||||
|
||||
//
|
||||
// Build Timestamp option
|
||||
//
|
||||
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_TS) &&
|
||||
!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_RST)) {
|
||||
|
||||
Data = NetbufAllocSpace (
|
||||
Nbuf,
|
||||
TCP_OPTION_TS_ALIGNED_LEN,
|
||||
NET_BUF_HEAD
|
||||
);
|
||||
|
||||
ASSERT (Data);
|
||||
Len += TCP_OPTION_TS_ALIGNED_LEN;
|
||||
|
||||
TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
|
||||
TcpPutUint32 (Data + 4, mTcpTick);
|
||||
TcpPutUint32 (Data + 8, Tcb->TsRecent);
|
||||
}
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the supported options.
|
||||
|
||||
@param Tcp Pointer to the TCP_CB of this TCP instance.
|
||||
@param Option Pointer to the TCP_OPTION used to store the successfully pasrsed
|
||||
options.
|
||||
|
||||
@retval 0 The options are successfully pasrsed.
|
||||
@retval -1 Ilegal option was found.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpParseOption (
|
||||
IN TCP_HEAD *Tcp,
|
||||
IN TCP_OPTION *Option
|
||||
)
|
||||
{
|
||||
UINT8 *Head;
|
||||
UINT8 TotalLen;
|
||||
UINT8 Cur;
|
||||
UINT8 Type;
|
||||
UINT8 Len;
|
||||
|
||||
ASSERT (Tcp && Option);
|
||||
|
||||
Option->Flag = 0;
|
||||
|
||||
TotalLen = (Tcp->HeadLen << 2) - sizeof (TCP_HEAD);
|
||||
if (TotalLen <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Head = (UINT8 *) (Tcp + 1);
|
||||
|
||||
//
|
||||
// Fast process of timestamp option
|
||||
//
|
||||
if ((TotalLen == TCP_OPTION_TS_ALIGNED_LEN) &&
|
||||
(TcpGetUint32 (Head) == TCP_OPTION_TS_FAST)) {
|
||||
|
||||
Option->TSVal = TcpGetUint32 (Head + 4);
|
||||
Option->TSEcr = TcpGetUint32 (Head + 8);
|
||||
Option->Flag = TCP_OPTION_RCVD_TS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Slow path to process the options.
|
||||
//
|
||||
Cur = 0;
|
||||
|
||||
while (Cur < TotalLen) {
|
||||
Type = Head[Cur];
|
||||
|
||||
switch (Type) {
|
||||
case TCP_OPTION_MSS:
|
||||
Len = Head[Cur + 1];
|
||||
|
||||
if ((Len != TCP_OPTION_MSS_LEN) ||
|
||||
(TotalLen - Cur < TCP_OPTION_MSS_LEN)) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Option->Mss = TcpGetUint16 (&Head[Cur + 2]);
|
||||
TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_MSS);
|
||||
|
||||
Cur += TCP_OPTION_MSS_LEN;
|
||||
break;
|
||||
|
||||
case TCP_OPTION_WS:
|
||||
Len = Head[Cur + 1];
|
||||
|
||||
if ((Len != TCP_OPTION_WS_LEN) ||
|
||||
(TotalLen - Cur < TCP_OPTION_WS_LEN)) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Option->WndScale = NET_MIN (14, Head[Cur + 2]);
|
||||
TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_WS);
|
||||
|
||||
Cur += TCP_OPTION_WS_LEN;
|
||||
break;
|
||||
|
||||
case TCP_OPTION_TS:
|
||||
Len = Head[Cur + 1];
|
||||
|
||||
if ((Len != TCP_OPTION_TS_LEN) ||
|
||||
(TotalLen - Cur < TCP_OPTION_TS_LEN)) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Option->TSVal = TcpGetUint32 (&Head[Cur + 2]);
|
||||
Option->TSEcr = TcpGetUint32 (&Head[Cur + 6]);
|
||||
TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_TS);
|
||||
|
||||
Cur += TCP_OPTION_TS_LEN;
|
||||
break;
|
||||
|
||||
case TCP_OPTION_NOP:
|
||||
Cur++;
|
||||
break;
|
||||
|
||||
case TCP_OPTION_EOP:
|
||||
Cur = TotalLen;
|
||||
break;
|
||||
|
||||
default:
|
||||
Len = Head[Cur + 1];
|
||||
|
||||
if (TotalLen - Cur < Len || Len < 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Cur = Cur + Len;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check the segment against PAWS.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param TSVal The timestamp value.
|
||||
|
||||
@retval 1 The segment passed the PAWS check.
|
||||
@retval 0 The segment failed to pass the PAWS check.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
TcpPawsOK (
|
||||
IN TCP_CB *Tcb,
|
||||
IN UINT32 TSVal
|
||||
)
|
||||
{
|
||||
//
|
||||
// PAWS as defined in RFC1323, buggy...
|
||||
//
|
||||
if (TCP_TIME_LT (TSVal, Tcb->TsRecent) &&
|
||||
TCP_TIME_LT (Tcb->TsRecentAge + TCP_PAWS_24DAY, mTcpTick)) {
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
107
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Option.h
Normal file
107
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Option.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Tcp4Option.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _TCP4_OPTION_H_
|
||||
#define _TCP4_OPTION_H_
|
||||
|
||||
//
|
||||
// The structure to store the parse option value.
|
||||
// ParseOption only parse the options, don't process them.
|
||||
//
|
||||
typedef struct s_TCP_OPTION {
|
||||
UINT8 Flag; // flag such as TCP_OPTION_RCVD_MSS
|
||||
UINT8 WndScale; // the WndScale received
|
||||
UINT16 Mss; // the Mss received
|
||||
UINT32 TSVal; // the TSVal field in a timestamp option
|
||||
UINT32 TSEcr; // the TSEcr field in a timestamp option
|
||||
} TCP_OPTION;
|
||||
|
||||
enum {
|
||||
|
||||
//
|
||||
// supported TCP option type and their length
|
||||
//
|
||||
TCP_OPTION_EOP = 0, // End Of oPtion
|
||||
TCP_OPTION_NOP = 1, // No-Option.
|
||||
TCP_OPTION_MSS = 2, // Maximum Segment Size
|
||||
TCP_OPTION_WS = 3, // Window scale
|
||||
TCP_OPTION_TS = 8, // Timestamp
|
||||
TCP_OPTION_MSS_LEN = 4, // length of MSS option
|
||||
TCP_OPTION_WS_LEN = 3, // length of window scale option
|
||||
TCP_OPTION_TS_LEN = 10, // length of timestamp option
|
||||
TCP_OPTION_WS_ALIGNED_LEN = 4, // length of window scale option, aligned
|
||||
TCP_OPTION_TS_ALIGNED_LEN = 12, // length of timestamp option, aligned
|
||||
|
||||
//
|
||||
// recommend format of timestamp window scale
|
||||
// option for fast process.
|
||||
//
|
||||
TCP_OPTION_TS_FAST = ((TCP_OPTION_NOP << 24) |
|
||||
(TCP_OPTION_NOP << 16) |
|
||||
(TCP_OPTION_TS << 8) |
|
||||
TCP_OPTION_TS_LEN),
|
||||
|
||||
TCP_OPTION_WS_FAST = ((TCP_OPTION_NOP << 24) |
|
||||
(TCP_OPTION_WS << 16) |
|
||||
(TCP_OPTION_WS_LEN << 8)),
|
||||
|
||||
TCP_OPTION_MSS_FAST = ((TCP_OPTION_MSS << 24) |
|
||||
(TCP_OPTION_MSS_LEN << 16)),
|
||||
|
||||
//
|
||||
// Other misc definations
|
||||
//
|
||||
TCP_OPTION_MAX_WS = 14, // Maxium window scale value
|
||||
TCP_OPTION_MAX_WIN = 0xffff, // max window size in TCP header
|
||||
TCP_OPTION_RCVD_MSS = 0x01,
|
||||
TCP_OPTION_RCVD_WS = 0x02,
|
||||
TCP_OPTION_RCVD_TS = 0x04,
|
||||
};
|
||||
|
||||
UINT8
|
||||
TcpComputeScale (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
UINT16
|
||||
TcpSynBuildOption (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Buf
|
||||
);
|
||||
|
||||
UINT16
|
||||
TcpBuildOption (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Buf
|
||||
);
|
||||
|
||||
INTN
|
||||
TcpParseOption (
|
||||
IN TCP_HEAD *Tcp,
|
||||
IN TCP_OPTION *Option
|
||||
);
|
||||
|
||||
UINT32
|
||||
TcpPawsOK (
|
||||
IN TCP_CB *Tcb,
|
||||
IN UINT32 TSVal
|
||||
);
|
||||
|
||||
#endif
|
1218
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Output.c
Normal file
1218
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Output.c
Normal file
File diff suppressed because it is too large
Load Diff
355
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Proto.h
Normal file
355
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Proto.h
Normal file
@@ -0,0 +1,355 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Tcp4Proto.h
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _TCP4_PROTO_H_
|
||||
#define _TCP4_PROTO_H_
|
||||
|
||||
typedef struct _TCP_CB TCP_CB;
|
||||
|
||||
#include "Tcp4Driver.h"
|
||||
#include "Socket.h"
|
||||
#include "Tcp4Option.h"
|
||||
|
||||
//
|
||||
// tcp states, Don't change their order, it is used as
|
||||
// index to mTcpOutFlag and other macros
|
||||
//
|
||||
enum {
|
||||
TCP_CLOSED = 0,
|
||||
TCP_LISTEN,
|
||||
TCP_SYN_SENT,
|
||||
TCP_SYN_RCVD,
|
||||
TCP_ESTABLISHED,
|
||||
TCP_FIN_WAIT_1,
|
||||
TCP_FIN_WAIT_2,
|
||||
TCP_CLOSING,
|
||||
TCP_TIME_WAIT,
|
||||
TCP_CLOSE_WAIT,
|
||||
TCP_LAST_ACK,
|
||||
};
|
||||
|
||||
//
|
||||
// flags in the TCP header
|
||||
//
|
||||
enum {
|
||||
|
||||
TCP_FLG_FIN = 0x01,
|
||||
TCP_FLG_SYN = 0x02,
|
||||
TCP_FLG_RST = 0x04,
|
||||
TCP_FLG_PSH = 0x08,
|
||||
TCP_FLG_ACK = 0x10,
|
||||
TCP_FLG_URG = 0x20,
|
||||
TCP_FLG_FLAG = 0x3F, // mask for all the flags
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
//
|
||||
// TCP error status
|
||||
//
|
||||
TCP_CONNECT_REFUSED = -1,
|
||||
TCP_CONNECT_RESET = -2,
|
||||
TCP_CONNECT_CLOSED = -3,
|
||||
|
||||
//
|
||||
// Current congestion status as suggested by RFC3782.
|
||||
//
|
||||
TCP_CONGEST_RECOVER = 1, // during the NewReno fast recovery
|
||||
TCP_CONGEST_LOSS = 2, // retxmit because of retxmit time out
|
||||
TCP_CONGEST_OPEN = 3, // TCP is opening its congestion window
|
||||
|
||||
//
|
||||
// TCP control flags
|
||||
//
|
||||
TCP_CTRL_NO_NAGLE = 0x0001, // disable Nagle algorithm
|
||||
TCP_CTRL_NO_KEEPALIVE = 0x0002, // disable keepalive timer
|
||||
TCP_CTRL_NO_WS = 0x0004, // disable window scale option
|
||||
TCP_CTRL_RCVD_WS = 0x0008, // rcvd a wnd scale option in syn
|
||||
TCP_CTRL_NO_TS = 0x0010, // disable Timestamp option
|
||||
TCP_CTRL_RCVD_TS = 0x0020, // rcvd a Timestamp option in syn
|
||||
TCP_CTRL_SND_TS = 0x0040, // Send Timestamp option to remote
|
||||
TCP_CTRL_SND_URG = 0x0080, // in urgent send mode
|
||||
TCP_CTRL_RCVD_URG = 0x0100, // in urgent receive mode
|
||||
TCP_CTRL_SND_PSH = 0x0200, // in PUSH send mode
|
||||
TCP_CTRL_FIN_SENT = 0x0400, // FIN is sent
|
||||
TCP_CTRL_FIN_ACKED = 0x0800, // FIN is ACKed.
|
||||
TCP_CTRL_TIMER_ON = 0x1000, // At least one of the timer is on
|
||||
TCP_CTRL_RTT_ON = 0x2000, // The RTT measurement is on
|
||||
TCP_CTRL_ACK_NOW = 0x4000, // Send the ACK now, don't delay
|
||||
|
||||
//
|
||||
// Timer related values
|
||||
//
|
||||
TCP_TIMER_CONNECT = 0, // Connection establishment timer
|
||||
TCP_TIMER_REXMIT = 1, // retransmit timer
|
||||
TCP_TIMER_PROBE = 2, // Window probe timer
|
||||
TCP_TIMER_KEEPALIVE = 3, // Keepalive timer
|
||||
TCP_TIMER_FINWAIT2 = 4, // FIN_WAIT_2 timer
|
||||
TCP_TIMER_2MSL = 5, // TIME_WAIT tiemr
|
||||
TCP_TIMER_NUMBER = 6, // the total number of TCP timer.
|
||||
TCP_TICK = 200, // every TCP tick is 200ms
|
||||
TCP_TICK_HZ = 5, // the frequence of TCP tick
|
||||
TCP_RTT_SHIFT = 3, // SRTT & RTTVAR scaled by 8
|
||||
TCP_RTO_MIN = TCP_TICK_HZ, // the minium value of RTO
|
||||
TCP_RTO_MAX = TCP_TICK_HZ *60, // the maxium value of RTO
|
||||
TCP_FOLD_RTT = 4, // timeout threshod to fold RTT
|
||||
|
||||
//
|
||||
// default values for some timers
|
||||
//
|
||||
TCP_MAX_LOSS = 12, // default max times to retxmit
|
||||
TCP_KEEPALIVE_IDLE_MIN = TCP_TICK_HZ *60 *60 *2, // First keep alive
|
||||
TCP_KEEPALIVE_PERIOD = TCP_TICK_HZ *60,
|
||||
TCP_MAX_KEEPALIVE = 8,
|
||||
TCP_FIN_WAIT2_TIME = 2 *TCP_TICK_HZ, // * 60,
|
||||
TCP_TIME_WAIT_TIME = 2 *TCP_TICK_HZ,
|
||||
TCP_PAWS_24DAY = 24 *24 *60 *60 *TCP_TICK_HZ,
|
||||
TCP_CONNECT_TIME = 75 *TCP_TICK_HZ,
|
||||
|
||||
//
|
||||
// The header space to be reserved before TCP data to accomodate :
|
||||
// 60byte IP head + 60byte TCP head + link layer head
|
||||
//
|
||||
TCP_MAX_HEAD = 192,
|
||||
|
||||
//
|
||||
// value ranges for some control option
|
||||
//
|
||||
TCP_RCV_BUF_SIZE = 2 *1024 *1024,
|
||||
TCP_RCV_BUF_SIZE_MIN = 8 *1024,
|
||||
TCP_SND_BUF_SIZE = 2 *1024 *1024,
|
||||
TCP_SND_BUF_SIZE_MIN = 8 *1024,
|
||||
TCP_BACKLOG = 10,
|
||||
TCP_BACKLOG_MIN = 5,
|
||||
TCP_MAX_LOSS_MIN = 6,
|
||||
TCP_CONNECT_TIME_MIN = 60 *TCP_TICK_HZ,
|
||||
TCP_MAX_KEEPALIVE_MIN = 4,
|
||||
TCP_KEEPALIVE_IDLE_MAX = TCP_TICK_HZ *60 *60 *4,
|
||||
TCP_KEEPALIVE_PERIOD_MIN= TCP_TICK_HZ *30,
|
||||
TCP_FIN_WAIT2_TIME_MAX = 4 *TCP_TICK_HZ,
|
||||
TCP_TIME_WAIT_TIME_MAX = 60 *TCP_TICK_HZ,
|
||||
};
|
||||
|
||||
typedef struct _TCP_SEG {
|
||||
TCP_SEQNO Seq; // Starting sequence number
|
||||
TCP_SEQNO End; // The sequence of the last byte + 1,
|
||||
// include SYN/FIN. End-Seq = SEG.LEN
|
||||
TCP_SEQNO Ack; // ACK fild in the segment
|
||||
UINT8 Flag; // TCP header flags
|
||||
UINT16 Urg; // Valid if URG flag is set.
|
||||
UINT32 Wnd; // TCP window size field
|
||||
} TCP_SEG;
|
||||
|
||||
typedef struct _TCP_PEER {
|
||||
UINT32 Ip; // Network byte order
|
||||
TCP_PORTNO Port; // Network byte order
|
||||
} TCP_PEER;
|
||||
|
||||
//
|
||||
// tcp control block, it includes various states
|
||||
//
|
||||
typedef struct _TCP_CB {
|
||||
NET_LIST_ENTRY List;
|
||||
TCP_CB *Parent;
|
||||
|
||||
SOCKET *Sk;
|
||||
TCP_PEER LocalEnd;
|
||||
TCP_PEER RemoteEnd;
|
||||
|
||||
NET_LIST_ENTRY SndQue; // retxmission queue
|
||||
NET_LIST_ENTRY RcvQue; // reassemble queue
|
||||
UINT32 CtrlFlag; // control flags, such as NO_NAGLE
|
||||
INT32 Error; // soft error status,TCP_CONNECT_RESET...
|
||||
|
||||
//
|
||||
// RFC793 and RFC1122 defined variables
|
||||
//
|
||||
UINT8 State; // TCP state, such as SYN_SENT, LISTEN
|
||||
UINT8 DelayedAck; // number of delayed ACKs
|
||||
UINT16 HeadSum; // checksum of the fixed parts of pesudo
|
||||
// header: Src IP, Dst IP, 0, Protocol,
|
||||
// not include the TCP length.
|
||||
|
||||
TCP_SEQNO Iss; // Initial Sending Sequence
|
||||
TCP_SEQNO SndUna; // first unacknowledged data
|
||||
TCP_SEQNO SndNxt; // next data sequence to send.
|
||||
TCP_SEQNO SndPsh; // Send PUSH point
|
||||
TCP_SEQNO SndUp; // Send urgent point
|
||||
UINT32 SndWnd; // Window advertised by the remote peer
|
||||
UINT32 SndWndMax; // max send window advertised by the peer
|
||||
TCP_SEQNO SndWl1; // Seq number used for last window update
|
||||
TCP_SEQNO SndWl2; // ack no of last window update
|
||||
UINT16 SndMss; // Max send segment size
|
||||
TCP_SEQNO RcvNxt; // Next sequence no to receive
|
||||
UINT32 RcvWnd; // Window advertised by the local peer
|
||||
TCP_SEQNO RcvWl2; // The RcvNxt (or ACK) of last window update.
|
||||
// It is necessary because of delayed ACK
|
||||
|
||||
TCP_SEQNO RcvUp; // urgent point;
|
||||
TCP_SEQNO Irs; // Initial Receiving Sequence
|
||||
UINT16 RcvMss; // Max receive segment size
|
||||
UINT16 EnabledTimer; // which timer is currently enabled
|
||||
UINT32 Timer[TCP_TIMER_NUMBER]; // when the timer will expire
|
||||
INT32 NextExpire; // count down offset for the nearest timer
|
||||
UINT32 Idle; // How long the connection is in idle
|
||||
UINT32 ProbeTime; // the time out value for current window prober
|
||||
|
||||
//
|
||||
// RFC1323 defined variables, about window scale,
|
||||
// timestamp and PAWS
|
||||
//
|
||||
UINT8 SndWndScale; // Wndscale received from the peer
|
||||
UINT8 RcvWndScale; // Wndscale used to scale local buffer
|
||||
UINT32 TsRecent; // TsRecent to echo to the remote peer
|
||||
UINT32 TsRecentAge; // When this TsRecent is updated
|
||||
|
||||
// TCP_SEQNO LastAckSent;
|
||||
// It isn't necessary to add LastAckSent here,
|
||||
// since it is the same as RcvWl2
|
||||
|
||||
//
|
||||
// RFC2988 defined variables. about RTT measurement
|
||||
//
|
||||
TCP_SEQNO RttSeq; // the seq of measured segment now
|
||||
UINT32 RttMeasure; // currently measured RTT in heart beats
|
||||
UINT32 SRtt; // Smoothed RTT, scaled by 8
|
||||
UINT32 RttVar; // RTT variance, scaled by 8
|
||||
UINT32 Rto; // Current RTO, not scaled
|
||||
|
||||
//
|
||||
// RFC2581, and 3782 variables.
|
||||
// Congestion control + NewReno fast recovery.
|
||||
//
|
||||
UINT32 CWnd; // Sender's congestion window
|
||||
UINT32 Ssthresh; // Slow start threshold.
|
||||
TCP_SEQNO Recover; // recover point for NewReno
|
||||
UINT16 DupAck; // number of duplicate ACKs
|
||||
UINT8 CongestState; // the current congestion state(RFC3782)
|
||||
UINT8 LossTimes; // number of retxmit timeouts in a row
|
||||
TCP_SEQNO LossRecover; // recover point for retxmit
|
||||
|
||||
//
|
||||
// configuration parameters, for EFI_TCP4_PROTOCOL specification
|
||||
//
|
||||
UINT32 KeepAliveIdle; // idle time before sending first probe
|
||||
UINT32 KeepAlivePeriod; // interval for subsequent keep alive probe
|
||||
UINT8 MaxKeepAlive; // Maxium keep alive probe times.
|
||||
UINT8 KeepAliveProbes; // the number of keep alive probe.
|
||||
UINT16 MaxRexmit; // The maxium number of retxmit before abort
|
||||
UINT32 FinWait2Timeout; // The FIN_WAIT_2 time out
|
||||
UINT32 TimeWaitTimeout; // The TIME_WAIT time out
|
||||
UINT32 ConnectTimeout;
|
||||
|
||||
//
|
||||
// configuration for tcp provided by user
|
||||
//
|
||||
BOOLEAN UseDefaultAddr;
|
||||
UINT8 TOS;
|
||||
UINT8 TTL;
|
||||
EFI_IPv4_ADDRESS SubnetMask;
|
||||
|
||||
//
|
||||
// pointer reference to Ip used to send pkt
|
||||
//
|
||||
IP_IO_IP_INFO *IpInfo;
|
||||
} TCP_CB;
|
||||
|
||||
extern NET_LIST_ENTRY mTcpRunQue;
|
||||
extern NET_LIST_ENTRY mTcpListenQue;
|
||||
extern TCP_SEQNO mTcpGlobalIss;
|
||||
extern UINT32 mTcpTick;
|
||||
|
||||
//
|
||||
// TCP_CONNECTED: both ends have synchronized their ISN.
|
||||
//
|
||||
#define TCP_CONNECTED(state) ((state) > TCP_SYN_RCVD)
|
||||
|
||||
#define TCP_FIN_RCVD(State) \
|
||||
(((State) == TCP_CLOSE_WAIT) || \
|
||||
((State) == TCP_LAST_ACK) || \
|
||||
((State) == TCP_CLOSING) || \
|
||||
((State) == TCP_TIME_WAIT))
|
||||
|
||||
#define TCP_LOCAL_CLOSED(State) \
|
||||
(((State) == TCP_FIN_WAIT_1) || \
|
||||
((State) == TCP_FIN_WAIT_2) || \
|
||||
((State) == TCP_CLOSING) || \
|
||||
((State) == TCP_TIME_WAIT) || \
|
||||
((State) == TCP_LAST_ACK))
|
||||
|
||||
//
|
||||
// Get the TCP_SEG point from a net buffer's ProtoData
|
||||
//
|
||||
#define TCPSEG_NETBUF(NBuf) ((TCP_SEG *) ((NBuf)->ProtoData))
|
||||
|
||||
//
|
||||
// macros to compare sequence no
|
||||
//
|
||||
#define TCP_SEQ_LT(SeqA, SeqB) ((INT32) ((SeqA) - (SeqB)) < 0)
|
||||
#define TCP_SEQ_LEQ(SeqA, SeqB) ((INT32) ((SeqA) - (SeqB)) <= 0)
|
||||
#define TCP_SEQ_GT(SeqA, SeqB) ((INT32) ((SeqB) - (SeqA)) < 0)
|
||||
#define TCP_SEQ_GEQ(SeqA, SeqB) ((INT32) ((SeqB) - (SeqA)) <= 0)
|
||||
|
||||
//
|
||||
// TCP_SEQ_BETWEEN return whether b <= m <= e
|
||||
//
|
||||
#define TCP_SEQ_BETWEEN(b, m, e) ((e) - (b) >= (m) - (b))
|
||||
|
||||
//
|
||||
// TCP_SUB_SEQ returns Seq1 - Seq2. Make sure Seq1 >= Seq2
|
||||
//
|
||||
#define TCP_SUB_SEQ(Seq1, Seq2) ((UINT32) ((Seq1) - (Seq2)))
|
||||
|
||||
#define TCP_FLG_ON(Value, Flag) ((BOOLEAN) (((Value) & (Flag)) != 0))
|
||||
#define TCP_SET_FLG(Value, Flag) ((Value) |= (Flag))
|
||||
#define TCP_CLEAR_FLG(Value, Flag) ((Value) &= ~(Flag))
|
||||
|
||||
//
|
||||
// test whether two peers are equal
|
||||
//
|
||||
#define TCP_PEER_EQUAL(Pa, Pb) \
|
||||
(((Pa)->Ip == (Pb)->Ip) && ((Pa)->Port == (Pb)->Port))
|
||||
|
||||
//
|
||||
// test whether Pa matches Pb, or Pa is more specific
|
||||
// than pb. Zero means wildcard.
|
||||
//
|
||||
#define TCP_PEER_MATCH(Pa, Pb) \
|
||||
((((Pb)->Ip == 0) || ((Pb)->Ip == (Pa)->Ip)) && \
|
||||
(((Pb)->Port == 0) || ((Pb)->Port == (Pa)->Port)))
|
||||
|
||||
#define TCP_TIMER_ON(Flag, Timer) ((Flag) & (1 << (Timer)))
|
||||
#define TCP_SET_TIMER(Flag, Timer) ((Flag) |= (1 << (Timer)))
|
||||
#define TCP_CLEAR_TIMER(Flag, Timer) ((Flag) &= ~(1 << (Timer)))
|
||||
|
||||
#define TCP_TIME_LT(Ta, Tb) ((INT32) ((Ta) - (Tb)) < 0)
|
||||
#define TCP_TIME_LEQ(Ta, Tb) ((INT32) ((Ta) - (Tb)) <= 0)
|
||||
#define TCP_SUB_TIME(Ta, Tb) ((UINT32) ((Ta) - (Tb)))
|
||||
|
||||
#define TCP_MAX_WIN 0xFFFFU
|
||||
|
||||
typedef
|
||||
VOID
|
||||
(*TCP_TIMER_HANDLER) (
|
||||
IN TCP_CB * Tcb
|
||||
);
|
||||
|
||||
#include "Tcp4Func.h"
|
||||
#endif
|
582
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Timer.c
Normal file
582
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Timer.c
Normal file
@@ -0,0 +1,582 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Tcp4Timer.c
|
||||
|
||||
Abstract:
|
||||
|
||||
TCP timer related functions.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Tcp4Main.h"
|
||||
|
||||
UINT32 mTcpTick = 1000;
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
TcpConnectTimeout (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
TcpRexmitTimeout (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
TcpProbeTimeout (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
TcpKeepaliveTimeout (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
TcpFinwait2Timeout (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
Tcp2MSLTimeout (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
TCP_TIMER_HANDLER mTcpTimerHandler[TCP_TIMER_NUMBER] = {
|
||||
TcpConnectTimeout,
|
||||
TcpRexmitTimeout,
|
||||
TcpProbeTimeout,
|
||||
TcpKeepaliveTimeout,
|
||||
TcpFinwait2Timeout,
|
||||
Tcp2MSLTimeout,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Close the TCP connection.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpClose (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
NetbufFreeList (&Tcb->SndQue);
|
||||
NetbufFreeList (&Tcb->RcvQue);
|
||||
|
||||
TcpSetState (Tcb, TCP_CLOSED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Connect timeout handler.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
TcpConnectTimeout (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
if (!TCP_CONNECTED (Tcb->State)) {
|
||||
TCP4_DEBUG_ERROR (("TcpConnectTimeout: connection closed "
|
||||
"because conenction timer timeout for TCB %x\n", Tcb));
|
||||
|
||||
if (EFI_ABORTED == Tcb->Sk->SockError) {
|
||||
SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
|
||||
}
|
||||
|
||||
if (TCP_SYN_RCVD == Tcb->State) {
|
||||
TCP4_DEBUG_WARN (("TcpConnectTimeout: send reset because "
|
||||
"connection timer timeout for TCB %x\n", Tcb));
|
||||
|
||||
TcpResetConnection (Tcb);
|
||||
|
||||
}
|
||||
|
||||
TcpClose (Tcb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Timeout handler for TCP retransmission timer.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
TcpRexmitTimeout (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
UINT32 FlightSize;
|
||||
|
||||
TCP4_DEBUG_WARN (("TcpRexmitTimeout: transmission "
|
||||
"timeout for TCB %x\n", Tcb));
|
||||
|
||||
//
|
||||
// Set the congestion window. FlightSize is the
|
||||
// amount of data that has been sent but not
|
||||
// yet ACKed.
|
||||
//
|
||||
FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);
|
||||
Tcb->Ssthresh = NET_MAX ((UINT32) (2 * Tcb->SndMss), FlightSize / 2);
|
||||
|
||||
Tcb->CWnd = Tcb->SndMss;
|
||||
Tcb->LossRecover = Tcb->SndNxt;
|
||||
|
||||
Tcb->LossTimes++;
|
||||
if (Tcb->LossTimes > Tcb->MaxRexmit &&
|
||||
!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_CONNECT)) {
|
||||
|
||||
TCP4_DEBUG_ERROR (("TcpRexmitTimeout: connection closed "
|
||||
"because too many timeouts for TCB %x\n", Tcb));
|
||||
|
||||
if (EFI_ABORTED == Tcb->Sk->SockError) {
|
||||
SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
|
||||
}
|
||||
|
||||
TcpClose (Tcb);
|
||||
return ;
|
||||
}
|
||||
|
||||
TcpBackoffRto (Tcb);
|
||||
TcpRetransmit (Tcb, Tcb->SndUna);
|
||||
TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);
|
||||
|
||||
Tcb->CongestState = TCP_CONGEST_LOSS;
|
||||
|
||||
TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Timeout handler for window probe timer.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
TcpProbeTimeout (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
//
|
||||
// This is the timer for sender's SWSA. RFC1122 requires
|
||||
// a timer set for sender's SWSA, and suggest combine it
|
||||
// with window probe timer. If data is sent, don't set
|
||||
// the probe timer, since retransmit timer is on.
|
||||
//
|
||||
if ((TcpDataToSend (Tcb, 1) != 0) && (TcpToSendData (Tcb, 1) > 0)) {
|
||||
|
||||
ASSERT (TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT));
|
||||
return ;
|
||||
}
|
||||
|
||||
TcpSendZeroProbe (Tcb);
|
||||
TcpSetProbeTimer (Tcb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Timeout handler for keepalive timer.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
TcpKeepaliveTimeout (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
Tcb->KeepAliveProbes++;
|
||||
|
||||
//
|
||||
// Too many Keep-alive probes, drop the connection
|
||||
//
|
||||
if (Tcb->KeepAliveProbes > Tcb->MaxKeepAlive) {
|
||||
|
||||
if (EFI_ABORTED == Tcb->Sk->SockError) {
|
||||
SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
|
||||
}
|
||||
|
||||
TcpClose (Tcb);
|
||||
return ;
|
||||
}
|
||||
|
||||
TcpSendZeroProbe (Tcb);
|
||||
TcpSetKeepaliveTimer (Tcb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Timeout handler for FIN_WAIT_2 timer.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
TcpFinwait2Timeout (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
TCP4_DEBUG_WARN (("TcpFinwait2Timeout: connection closed "
|
||||
"because FIN_WAIT2 timer timeouts for TCB %x\n", Tcb));
|
||||
|
||||
TcpClose (Tcb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Timeout handler for 2MSL timer.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
Tcp2MSLTimeout (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
TCP4_DEBUG_WARN (("Tcp2MSLTimeout: connection closed "
|
||||
"because TIME_WAIT timer timeouts for TCB %x\n", Tcb));
|
||||
|
||||
TcpClose (Tcb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Update the timer status and the next expire time
|
||||
according to the timers to expire in a specific
|
||||
future time slot.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
TcpUpdateTimer (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
UINT16 Index;
|
||||
|
||||
//
|
||||
// Don't use a too large value to init NextExpire
|
||||
// since mTcpTick wraps around as sequence no does.
|
||||
//
|
||||
Tcb->NextExpire = 65535;
|
||||
TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON);
|
||||
|
||||
for (Index = 0; Index < TCP_TIMER_NUMBER; Index++) {
|
||||
|
||||
if (TCP_TIMER_ON (Tcb->EnabledTimer, Index) &&
|
||||
TCP_TIME_LT (Tcb->Timer[Index], mTcpTick + Tcb->NextExpire)) {
|
||||
|
||||
Tcb->NextExpire = TCP_SUB_TIME (Tcb->Timer[Index], mTcpTick);
|
||||
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Enable a TCP timer.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param Timer The index of the timer to be enabled.
|
||||
@param TimeOut The timeout value of this timer.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpSetTimer (
|
||||
IN TCP_CB *Tcb,
|
||||
IN UINT16 Timer,
|
||||
IN UINT32 TimeOut
|
||||
)
|
||||
{
|
||||
TCP_SET_TIMER (Tcb->EnabledTimer, Timer);
|
||||
Tcb->Timer[Timer] = mTcpTick + TimeOut;
|
||||
|
||||
TcpUpdateTimer (Tcb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Clear one TCP timer.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param Timer The index of the timer to be cleared.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpClearTimer (
|
||||
IN TCP_CB *Tcb,
|
||||
IN UINT16 Timer
|
||||
)
|
||||
{
|
||||
TCP_CLEAR_TIMER (Tcb->EnabledTimer, Timer);
|
||||
TcpUpdateTimer (Tcb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Clear all TCP timers.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpClearAllTimer (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
Tcb->EnabledTimer = 0;
|
||||
TcpUpdateTimer (Tcb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Enable the window prober timer and set the timeout value.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpSetProbeTimer (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_PROBE)) {
|
||||
Tcb->ProbeTime = Tcb->Rto;
|
||||
|
||||
} else {
|
||||
Tcb->ProbeTime <<= 1;
|
||||
}
|
||||
|
||||
if (Tcb->ProbeTime < TCP_RTO_MIN) {
|
||||
|
||||
Tcb->ProbeTime = TCP_RTO_MIN;
|
||||
} else if (Tcb->ProbeTime > TCP_RTO_MAX) {
|
||||
|
||||
Tcb->ProbeTime = TCP_RTO_MAX;
|
||||
}
|
||||
|
||||
TcpSetTimer (Tcb, TCP_TIMER_PROBE, Tcb->ProbeTime);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Enable the keepalive timer and set the timeout value.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpSetKeepaliveTimer (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE)) {
|
||||
return ;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Set the timer to KeepAliveIdle if either
|
||||
// 1. the keepalive timer is off
|
||||
// 2. The keepalive timer is on, but the idle
|
||||
// is less than KeepAliveIdle, that means the
|
||||
// connection is alive since our last probe.
|
||||
//
|
||||
if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_KEEPALIVE) ||
|
||||
(Tcb->Idle < Tcb->KeepAliveIdle)) {
|
||||
|
||||
TcpSetTimer (Tcb, TCP_TIMER_KEEPALIVE, Tcb->KeepAliveIdle);
|
||||
Tcb->KeepAliveProbes = 0;
|
||||
|
||||
} else {
|
||||
|
||||
TcpSetTimer (Tcb, TCP_TIMER_KEEPALIVE, Tcb->KeepAlivePeriod);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Backoff the RTO.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpBackoffRto (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
//
|
||||
// Fold the RTT estimate if too many times, the estimate
|
||||
// may be wrong, fold it. So the next time a valid
|
||||
// measurement is sampled, we can start fresh.
|
||||
//
|
||||
if ((Tcb->LossTimes >= TCP_FOLD_RTT) && Tcb->SRtt) {
|
||||
Tcb->RttVar += Tcb->SRtt >> 2;
|
||||
Tcb->SRtt = 0;
|
||||
}
|
||||
|
||||
Tcb->Rto <<= 1;
|
||||
|
||||
if (Tcb->Rto < TCP_RTO_MIN) {
|
||||
|
||||
Tcb->Rto = TCP_RTO_MIN;
|
||||
} else if (Tcb->Rto > TCP_RTO_MAX) {
|
||||
|
||||
Tcb->Rto = TCP_RTO_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Heart beat timer handler.
|
||||
|
||||
@param Event Timer event signaled, ignored.
|
||||
@param Context Context of the timer event, ignored.
|
||||
|
||||
@return None.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TcpTicking (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
NET_LIST_ENTRY *Entry;
|
||||
NET_LIST_ENTRY *Next;
|
||||
TCP_CB *Tcb;
|
||||
INT16 Index;
|
||||
|
||||
mTcpTick++;
|
||||
mTcpGlobalIss += 100;
|
||||
|
||||
//
|
||||
// Don't use LIST_FOR_EACH, which isn't delete safe.
|
||||
//
|
||||
for (Entry = mTcpRunQue.ForwardLink; Entry != &mTcpRunQue; Entry = Next) {
|
||||
|
||||
Next = Entry->ForwardLink;
|
||||
|
||||
Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
|
||||
|
||||
if (Tcb->State == TCP_CLOSED) {
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// The connection is doing RTT measurement.
|
||||
//
|
||||
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
|
||||
Tcb->RttMeasure++;
|
||||
}
|
||||
|
||||
Tcb->Idle++;
|
||||
|
||||
if (Tcb->DelayedAck) {
|
||||
TcpSendAck (Tcb);
|
||||
}
|
||||
|
||||
//
|
||||
// No timer is active or no timer expired
|
||||
//
|
||||
if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON) ||
|
||||
((--Tcb->NextExpire) > 0)) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Call the timeout handler for each expired timer.
|
||||
//
|
||||
for (Index = 0; Index < TCP_TIMER_NUMBER; Index++) {
|
||||
|
||||
if (TCP_TIMER_ON (Tcb->EnabledTimer, Index) &&
|
||||
TCP_TIME_LEQ (Tcb->Timer[Index], mTcpTick)) {
|
||||
//
|
||||
// disable the timer before calling the handler
|
||||
// in case the handler enables it again.
|
||||
//
|
||||
TCP_CLEAR_TIMER (Tcb->EnabledTimer, Index);
|
||||
mTcpTimerHandler[Index](Tcb);
|
||||
|
||||
//
|
||||
// The Tcb may have been deleted by the timer, or
|
||||
// no other timer is set.
|
||||
//
|
||||
if ((Next->BackLink != Entry) ||
|
||||
(Tcb->EnabledTimer == 0)) {
|
||||
|
||||
goto NextConnection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TcpUpdateTimer (Tcb);
|
||||
NextConnection:
|
||||
;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user