Add NetworkPkg (P.UDK2010.UP3.Network.P1)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10986 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
304
NetworkPkg/TcpDxe/ComponentName.c
Normal file
304
NetworkPkg/TcpDxe/ComponentName.c
Normal file
@@ -0,0 +1,304 @@
|
||||
/** @file
|
||||
Implementation of protocols EFI_COMPONENT_NAME_PROTOCOL and
|
||||
EFI_COMPONENT_NAME2_PROTOCOL.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "TcpMain.h"
|
||||
|
||||
//
|
||||
// EFI Component Name Functions
|
||||
//
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user-readable name of the driver.
|
||||
|
||||
This function retrieves the user-readable name of a driver in the form of a
|
||||
Unicode string. If the driver specified by This has a user-readable name in
|
||||
the language specified by Language, then a pointer to the driver name is
|
||||
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
|
||||
by This does not support the language specified by Language,
|
||||
then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param[in] Language A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name 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. Language is specified
|
||||
in RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param[out] 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.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the Driver specified by
|
||||
This, and the language specified by Language was
|
||||
returned in DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language or DriverName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user-readable name of the controller
|
||||
that is being managed by a driver.
|
||||
|
||||
This function retrieves the user-readable name of the controller specified by
|
||||
ControllerHandle and ChildHandle in the form of a Unicode string. If the
|
||||
driver specified by This has a user-readable name in the language specified by
|
||||
Language, then a pointer to the controller name is returned in ControllerName,
|
||||
and EFI_SUCCESS is returned. If the driver specified by This is not currently
|
||||
managing the controller specified by ControllerHandle and ChildHandle,
|
||||
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
|
||||
support the language specified by Language, then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param[in] 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.
|
||||
|
||||
@param[in] 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.
|
||||
|
||||
@param[in] Language A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name 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. Language is specified in
|
||||
RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param[out] 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.
|
||||
|
||||
@retval 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.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
|
||||
EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language or ControllerName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This is not currently
|
||||
managing the controller specified by
|
||||
ControllerHandle and ChildHandle.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
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
|
||||
///
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gTcpComponentName = {
|
||||
TcpComponentNameGetDriverName,
|
||||
TcpComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
///
|
||||
/// EFI Component Name 2 Protocol
|
||||
///
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gTcpComponentName2 = {
|
||||
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) TcpComponentNameGetDriverName,
|
||||
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) TcpComponentNameGetControllerName,
|
||||
"en"
|
||||
};
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mTcpDriverNameTable[] = {
|
||||
{
|
||||
"eng;en",
|
||||
L"TCP Network Service Driver"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user-readable name of the driver.
|
||||
|
||||
This function retrieves the user-readable name of a driver in the form of a
|
||||
Unicode string. If the driver specified by This has a user-readable name in
|
||||
the language specified by Language, then a pointer to the driver name is
|
||||
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
|
||||
by This does not support the language specified by Language,
|
||||
then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param[in] Language A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name 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. Language is specified
|
||||
in RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param[out] 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.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the Driver specified by
|
||||
This, and the language specified by Language was
|
||||
returned in DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language or DriverName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
{
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mTcpDriverNameTable,
|
||||
DriverName,
|
||||
(BOOLEAN) (This == &gTcpComponentName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user-readable name of the controller
|
||||
that is being managed by a driver.
|
||||
|
||||
This function retrieves the user-readable name of the controller specified by
|
||||
ControllerHandle and ChildHandle in the form of a Unicode string. If the
|
||||
driver specified by This has a user-readable name in the language specified by
|
||||
Language, then a pointer to the controller name is returned in ControllerName,
|
||||
and EFI_SUCCESS is returned. If the driver specified by This is not currently
|
||||
managing the controller specified by ControllerHandle and ChildHandle,
|
||||
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
|
||||
support the language specified by Language, then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param[in] 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.
|
||||
|
||||
@param[in] 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.
|
||||
|
||||
@param[in] Language A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name 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. Language is specified in
|
||||
RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param[out] 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.
|
||||
|
||||
@retval 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.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL, and it is not a valid
|
||||
EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language or ControllerName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This is not currently
|
||||
managing the controller specified by
|
||||
ControllerHandle and ChildHandle.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
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
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
1230
NetworkPkg/TcpDxe/SockImpl.c
Normal file
1230
NetworkPkg/TcpDxe/SockImpl.c
Normal file
File diff suppressed because it is too large
Load Diff
103
NetworkPkg/TcpDxe/SockImpl.h
Normal file
103
NetworkPkg/TcpDxe/SockImpl.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/** @file
|
||||
The function declaration that provided for Socket Interface.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SOCK_IMPL_H_
|
||||
#define _SOCK_IMPL_H_
|
||||
|
||||
#include "Socket.h"
|
||||
|
||||
/**
|
||||
Signal a event with the given status.
|
||||
|
||||
@param[in] Token The token's event is to be signaled.
|
||||
@param[in] TokenStatus The status to be sent with the event.
|
||||
|
||||
**/
|
||||
#define SIGNAL_TOKEN(Token, TokenStatus) \
|
||||
do { \
|
||||
(Token)->Status = (TokenStatus); \
|
||||
gBS->SignalEvent ((Token)->Event); \
|
||||
} while (0)
|
||||
|
||||
#define SOCK_HEADER_SPACE (60 + 60 + 72)
|
||||
|
||||
/**
|
||||
Process the TCP send data, buffer the tcp txdata and append
|
||||
the buffer to socket send buffer, then try to send it.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
@param[in] TcpTxData Pointer to the application provided send buffer.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed due to resource limits.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockProcessTcpSndData (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *TcpTxData
|
||||
);
|
||||
|
||||
/**
|
||||
Get received data from the socket layer to the receive token.
|
||||
|
||||
@param[in, out] Sock Pointer to the socket.
|
||||
@param[in, out] RcvToken Pointer to the application provided receive token.
|
||||
|
||||
@return The length of data received in this token.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
SockProcessRcvToken (
|
||||
IN OUT SOCKET *Sock,
|
||||
IN OUT SOCK_IO_TOKEN *RcvToken
|
||||
);
|
||||
|
||||
/**
|
||||
Flush the sndBuffer and rcvBuffer of socket.
|
||||
|
||||
@param[in, out] Sock Pointer to the socket.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SockConnFlush (
|
||||
IN OUT SOCKET *Sock
|
||||
);
|
||||
|
||||
/**
|
||||
Create a socket with initial data SockInitData.
|
||||
|
||||
@param[in] SockInitData Pointer to the initial data of the socket.
|
||||
|
||||
@return Pointer to the newly created socket, return NULL when exception occured.
|
||||
|
||||
**/
|
||||
SOCKET *
|
||||
SockCreate (
|
||||
IN SOCK_INIT_DATA *SockInitData
|
||||
);
|
||||
|
||||
/**
|
||||
Destroy a socket.
|
||||
|
||||
@param[in, out] Sock Pointer to the socket.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SockDestroy (
|
||||
IN OUT SOCKET *Sock
|
||||
);
|
||||
|
||||
#endif
|
999
NetworkPkg/TcpDxe/SockInterface.c
Normal file
999
NetworkPkg/TcpDxe/SockInterface.c
Normal file
@@ -0,0 +1,999 @@
|
||||
/** @file
|
||||
Interface function of the Socket.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "SockImpl.h"
|
||||
|
||||
/**
|
||||
Check whether the Event is in the List.
|
||||
|
||||
@param[in] List Pointer to the token list to be searched.
|
||||
@param[in] Event The event to be checked.
|
||||
|
||||
@retval TRUE The specific Event exists in the List.
|
||||
@retval FALSE The specific Event is not in the List.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
SockTokenExistedInList (
|
||||
IN LIST_ENTRY *List,
|
||||
IN EFI_EVENT Event
|
||||
)
|
||||
{
|
||||
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[in] Sock Pointer to the instance's socket.
|
||||
@param[in] Event The event to be checked.
|
||||
|
||||
@retval TRUE The Event exists in related socket's lists.
|
||||
@retval FALSE The Event is not in related socket's lists.
|
||||
|
||||
**/
|
||||
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 the socket Sock.
|
||||
|
||||
@param[in] Sock Pointer to the instance's socket.
|
||||
@param[in] List Pointer to the list to store the token.
|
||||
@param[in] Token Pointer to the token to be buffered.
|
||||
@param[in] DataLen The data length of the buffer contained in Token.
|
||||
|
||||
@return Pointer to the token that wraps Token. If NULL, an error condition occurred.
|
||||
|
||||
**/
|
||||
SOCK_TOKEN *
|
||||
SockBufferToken (
|
||||
IN SOCKET *Sock,
|
||||
IN LIST_ENTRY *List,
|
||||
IN VOID *Token,
|
||||
IN UINT32 DataLen
|
||||
)
|
||||
{
|
||||
SOCK_TOKEN *SockToken;
|
||||
|
||||
SockToken = AllocateZeroPool (sizeof (SOCK_TOKEN));
|
||||
if (NULL == SockToken) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"SockBufferIOToken: No Memory to allocate SockToken\n")
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SockToken->Sock = Sock;
|
||||
SockToken->Token = (SOCK_COMPLETION_TOKEN *) Token;
|
||||
SockToken->RemainDataLen = DataLen;
|
||||
InsertTailList (List, &SockToken->TokenList);
|
||||
|
||||
return SockToken;
|
||||
}
|
||||
|
||||
/**
|
||||
Destory the socket Sock and its associated protocol control block.
|
||||
|
||||
@param[in, out] Sock The socket to be destroyed.
|
||||
|
||||
@retval EFI_SUCCESS The socket Sock was destroyed successfully.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockDestroyChild (
|
||||
IN OUT SOCKET *Sock
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT ((Sock != NULL) && (Sock->ProtoHandler != NULL));
|
||||
|
||||
if (Sock->IsDestroyed) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Sock->IsDestroyed = TRUE;
|
||||
|
||||
Status = EfiAcquireLockOrFail (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_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)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_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;
|
||||
}
|
||||
|
||||
EfiReleaseLock (&(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[in] SockInitData Inital data to setting the socket.
|
||||
|
||||
@return Pointer to the newly created socket. If NULL, an error condition occured.
|
||||
|
||||
**/
|
||||
SOCKET *
|
||||
SockCreateChild (
|
||||
IN SOCK_INIT_DATA *SockInitData
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// create a new socket
|
||||
//
|
||||
Sock = SockCreate (SockInitData);
|
||||
if (NULL == Sock) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"SockCreateChild: No resource to create a new socket\n")
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Status = EfiAcquireLockOrFail (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_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)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"SockCreateChild: Protocol failed to attach a socket with %r\n",
|
||||
Status)
|
||||
);
|
||||
|
||||
SockDestroy (Sock);
|
||||
Sock = NULL;
|
||||
}
|
||||
|
||||
EfiReleaseLock (&(Sock->Lock));
|
||||
return Sock;
|
||||
}
|
||||
|
||||
/**
|
||||
Configure the specific socket Sock using configuration data ConfigData.
|
||||
|
||||
@param[in] Sock Pointer to the socket to be configured.
|
||||
@param[in] ConfigData Pointer to the configuration data.
|
||||
|
||||
@retval EFI_SUCCESS The socket 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 = EfiAcquireLockOrFail (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_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:
|
||||
EfiReleaseLock (&(Sock->Lock));
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Initiate a connection establishment process.
|
||||
|
||||
@param[in] Sock Pointer to the socket to initiate the initate the
|
||||
connection.
|
||||
@param[in] Token Pointer to the token used for the connection
|
||||
operation.
|
||||
|
||||
@retval EFI_SUCCESS The connection 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 = EfiAcquireLockOrFail (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_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:
|
||||
EfiReleaseLock (&(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[in] Sock Pointer to the socket to accept connections.
|
||||
@param[in] 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 limits.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockAccept (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token
|
||||
)
|
||||
{
|
||||
EFI_TCP4_LISTEN_TOKEN *ListenToken;
|
||||
LIST_ENTRY *ListEntry;
|
||||
EFI_STATUS Status;
|
||||
SOCKET *Socket;
|
||||
EFI_EVENT Event;
|
||||
|
||||
ASSERT (SockStream == Sock->Type);
|
||||
|
||||
Status = EfiAcquireLockOrFail (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_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);
|
||||
|
||||
RemoveEntryList (ListEntry);
|
||||
|
||||
ASSERT (Socket->Parent != NULL);
|
||||
|
||||
Socket->Parent->ConnCnt--;
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_INFO,
|
||||
"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:
|
||||
EfiReleaseLock (&(Sock->Lock));
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Issue a token with data to the socket to send out.
|
||||
|
||||
@param[in] Sock Pointer to the socket to process the token with
|
||||
data.
|
||||
@param[in] Token The token with data that needs to send out.
|
||||
|
||||
@retval EFI_SUCCESS The token 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 limits.
|
||||
|
||||
**/
|
||||
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 (SockStream == Sock->Type);
|
||||
|
||||
Status = EfiAcquireLockOrFail (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_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) {
|
||||
DEBUG (
|
||||
(EFI_D_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)) {
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"SockSend: Failed to process Snd Data\n",
|
||||
Status)
|
||||
);
|
||||
|
||||
RemoveEntryList (&(SockToken->TokenList));
|
||||
FreePool (SockToken);
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
EfiReleaseLock (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Issue a token to get data from the socket.
|
||||
|
||||
@param[in] Sock Pointer to the socket to get data from.
|
||||
@param[in] Token The token to store the received data from the
|
||||
socket.
|
||||
|
||||
@retval EFI_SUCCESS The token 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 (SockStream == Sock->Type);
|
||||
|
||||
Status = EfiAcquireLockOrFail (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_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:
|
||||
EfiReleaseLock (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Reset the socket and its associated protocol control block.
|
||||
|
||||
@param[in, out] 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 OUT SOCKET *Sock
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT (SockStream == Sock->Type);
|
||||
|
||||
Status = EfiAcquireLockOrFail (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"SockFlush: Get the access for socket failed with %r",
|
||||
Status)
|
||||
);
|
||||
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (!SOCK_IS_CONFIGURED (Sock)) {
|
||||
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_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:
|
||||
EfiReleaseLock (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Close or abort the socket associated connection.
|
||||
|
||||
@param[in, out] Sock Pointer to the socket of the connection to close
|
||||
or abort.
|
||||
@param[in] Token The token for a close operation.
|
||||
@param[in] OnAbort TRUE for aborting the connection; FALSE to close it.
|
||||
|
||||
@retval EFI_SUCCESS The close or abort operation 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 OUT SOCKET *Sock,
|
||||
IN VOID *Token,
|
||||
IN BOOLEAN OnAbort
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_EVENT Event;
|
||||
|
||||
ASSERT (SockStream == Sock->Type);
|
||||
|
||||
Status = EfiAcquireLockOrFail (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG (
|
||||
(EFI_D_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:
|
||||
EfiReleaseLock (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the mode data of the low layer protocol.
|
||||
|
||||
@param[in] Sock Pointer to the socket to get mode data from.
|
||||
@param[in, out] Mode Pointer to the data to store the low layer mode
|
||||
information.
|
||||
|
||||
@retval EFI_SUCCESS The mode data was obtained successfully.
|
||||
@retval EFI_NOT_STARTED The socket is not configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockGetMode (
|
||||
IN SOCKET *Sock,
|
||||
IN OUT 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[in] Sock Pointer to the socket of the connection to join the
|
||||
specific multicast group.
|
||||
@param[in] GroupInfo Pointer to the multicast group info.
|
||||
|
||||
@retval EFI_SUCCESS The configuration completed 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 = EfiAcquireLockOrFail (&(Sock->Lock));
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_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:
|
||||
EfiReleaseLock (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Add or remove route information in IP route table associated
|
||||
with this socket.
|
||||
|
||||
@param[in] Sock Pointer to the socket associated with the IP route
|
||||
table to operate on.
|
||||
@param[in] RouteInfo Pointer to the route information to be processed.
|
||||
|
||||
@retval EFI_SUCCESS The route table 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 = EfiAcquireLockOrFail (&(Sock->Lock));
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG (
|
||||
(EFI_D_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:
|
||||
EfiReleaseLock (&(Sock->Lock));
|
||||
return Status;
|
||||
}
|
||||
|
924
NetworkPkg/TcpDxe/Socket.h
Normal file
924
NetworkPkg/TcpDxe/Socket.h
Normal file
@@ -0,0 +1,924 @@
|
||||
/** @file
|
||||
Common head file for TCP socket.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SOCKET_H_
|
||||
#define _SOCKET_H_
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Protocol/Tcp4.h>
|
||||
#include <Protocol/Tcp6.h>
|
||||
|
||||
#include <Library/NetLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/DpcLib.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.
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
///
|
||||
/// Socket state
|
||||
///
|
||||
#define SO_CLOSED 0
|
||||
#define SO_LISTENING 1
|
||||
#define SO_CONNECTING 2
|
||||
#define SO_CONNECTED 3
|
||||
#define SO_DISCONNECTING 4
|
||||
|
||||
///
|
||||
/// Socket configure state
|
||||
///
|
||||
#define SO_UNCONFIGURED 0
|
||||
#define SO_CONFIGURED_ACTIVE 1
|
||||
#define SO_CONFIGURED_PASSIVE 2
|
||||
#define SO_NO_MAPPING 3
|
||||
|
||||
///
|
||||
/// The request issued from socket layer to protocol layer.
|
||||
///
|
||||
#define SOCK_ATTACH 0 ///< Attach current socket to a new PCB
|
||||
#define SOCK_DETACH 1 ///< Detach current socket from the PCB
|
||||
#define SOCK_CONFIGURE 2 ///< Configure attached PCB
|
||||
#define SOCK_FLUSH 3 ///< Flush attached PCB
|
||||
#define SOCK_SND 4 ///< Need protocol to send something
|
||||
#define SOCK_SNDPUSH 5 ///< Need protocol to send pushed data
|
||||
#define SOCK_SNDURG 6 ///< Need protocol to send urgent data
|
||||
#define SOCK_CONSUMED 7 ///< Application has retrieved data from socket
|
||||
#define SOCK_CONNECT 8 ///< Need to connect to a peer
|
||||
#define SOCK_CLOSE 9 ///< Need to close the protocol process
|
||||
#define SOCK_ABORT 10 ///< Need to reset the protocol process
|
||||
#define SOCK_POLL 11 ///< Need to poll to the protocol layer
|
||||
#define SOCK_ROUTE 12 ///< Need to add a route information
|
||||
#define SOCK_MODE 13 ///< Need to get the mode data of the protocol
|
||||
#define SOCK_GROUP 14 ///< Need to join a mcast group
|
||||
|
||||
/**
|
||||
Set socket SO_NO_MORE_DATA flag.
|
||||
|
||||
@param[in] Sock Pointer to the socket
|
||||
|
||||
**/
|
||||
#define SOCK_NO_MORE_DATA(Sock) ((Sock)->Flag |= SO_NO_MORE_DATA)
|
||||
|
||||
/**
|
||||
Check whether the socket is unconfigured.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@retval TRUE The socket is unconfigued.
|
||||
@retval FALSE The socket is not unconfigued.
|
||||
|
||||
**/
|
||||
#define SOCK_IS_UNCONFIGURED(Sock) ((Sock)->ConfigureState == SO_UNCONFIGURED)
|
||||
|
||||
/**
|
||||
Check whether the socket is configured.
|
||||
|
||||
@param[in] Sock Pointer to the socket
|
||||
|
||||
@retval TRUE The socket is configued
|
||||
@retval FALSE The socket is not configued
|
||||
|
||||
**/
|
||||
#define SOCK_IS_CONFIGURED(Sock) \
|
||||
(((Sock)->ConfigureState == SO_CONFIGURED_ACTIVE) || \
|
||||
((Sock)->ConfigureState == SO_CONFIGURED_PASSIVE))
|
||||
|
||||
/**
|
||||
Check whether the socket is configured to active mode.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@retval TRUE The socket is configued to active mode.
|
||||
@retval FALSE The socket is not configued to active mode.
|
||||
|
||||
**/
|
||||
#define SOCK_IS_CONFIGURED_ACTIVE(Sock) ((Sock)->ConfigureState == SO_CONFIGURED_ACTIVE)
|
||||
|
||||
/**
|
||||
Check whether the socket is configured to passive mode.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@retval TRUE The socket is configued to passive mode.
|
||||
@retval FALSE The socket is not configued to passive mode.
|
||||
|
||||
**/
|
||||
#define SOCK_IS_CONNECTED_PASSIVE(Sock) ((Sock)->ConfigureState == SO_CONFIGURED_PASSIVE)
|
||||
|
||||
/**
|
||||
Check whether the socket is mapped.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@retval TRUE The socket is not mapping.
|
||||
@retval FALSE The socket is mapped.
|
||||
|
||||
**/
|
||||
#define SOCK_IS_NO_MAPPING(Sock) ((Sock)->ConfigureState == SO_NO_MAPPING)
|
||||
|
||||
/**
|
||||
Check whether the socket is closed.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@retval TRUE The socket is closed.
|
||||
@retval FALSE The socket is not closed.
|
||||
|
||||
**/
|
||||
#define SOCK_IS_CLOSED(Sock) ((Sock)->State == SO_CLOSED)
|
||||
|
||||
/**
|
||||
Check whether the socket is listening.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@retval TRUE The socket is listening.
|
||||
@retval FALSE The socket is not listening.
|
||||
|
||||
**/
|
||||
#define SOCK_IS_LISTENING(Sock) ((Sock)->State == SO_LISTENING)
|
||||
|
||||
/**
|
||||
Check whether the socket is connecting.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@retval TRUE The socket is connecting.
|
||||
@retval FALSE The socket is not connecting.
|
||||
|
||||
**/
|
||||
#define SOCK_IS_CONNECTING(Sock) ((Sock)->State == SO_CONNECTING)
|
||||
|
||||
/**
|
||||
Check whether the socket has connected.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@retval TRUE The socket has connected.
|
||||
@retval FALSE The socket has not connected.
|
||||
|
||||
**/
|
||||
#define SOCK_IS_CONNECTED(Sock) ((Sock)->State == SO_CONNECTED)
|
||||
|
||||
/**
|
||||
Check whether the socket is disconnecting.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@retval TRUE The socket is disconnecting.
|
||||
@retval FALSE The socket is not disconnecting.
|
||||
|
||||
**/
|
||||
#define SOCK_IS_DISCONNECTING(Sock) ((Sock)->State == SO_DISCONNECTING)
|
||||
|
||||
/**
|
||||
Check whether the socket is no more data.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@retval TRUE The socket is no more data.
|
||||
@retval FALSE The socket still has data.
|
||||
|
||||
**/
|
||||
#define SOCK_IS_NO_MORE_DATA(Sock) (0 != ((Sock)->Flag & SO_NO_MORE_DATA))
|
||||
|
||||
/**
|
||||
Set the size of the receive buffer.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
@param[in] Size The size to set.
|
||||
|
||||
**/
|
||||
#define SET_RCV_BUFFSIZE(Sock, Size) ((Sock)->RcvBuffer.HighWater = (Size))
|
||||
|
||||
/**
|
||||
Get the size of the receive buffer.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@return The receive buffer size.
|
||||
|
||||
**/
|
||||
#define GET_RCV_BUFFSIZE(Sock) ((Sock)->RcvBuffer.HighWater)
|
||||
|
||||
/**
|
||||
Get the size of the receive data.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@return The received data size.
|
||||
|
||||
**/
|
||||
#define GET_RCV_DATASIZE(Sock) (((Sock)->RcvBuffer.DataQueue)->BufSize)
|
||||
|
||||
/**
|
||||
Set the size of the send buffer.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
@param[in] Size The size to set.
|
||||
|
||||
**/
|
||||
#define SET_SND_BUFFSIZE(Sock, Size) ((Sock)->SndBuffer.HighWater = (Size))
|
||||
|
||||
/**
|
||||
Get the size of the send buffer.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@return The send buffer size.
|
||||
|
||||
**/
|
||||
#define GET_SND_BUFFSIZE(Sock) ((Sock)->SndBuffer.HighWater)
|
||||
|
||||
/**
|
||||
Get the size of the send data.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@return The send data size.
|
||||
|
||||
**/
|
||||
#define GET_SND_DATASIZE(Sock) (((Sock)->SndBuffer.DataQueue)->BufSize)
|
||||
|
||||
/**
|
||||
Set the backlog value of the socket.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
@param[in] Value The value to set.
|
||||
|
||||
**/
|
||||
#define SET_BACKLOG(Sock, Value) ((Sock)->BackLog = (Value))
|
||||
|
||||
/**
|
||||
Get the backlog value of the socket.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
|
||||
@return The backlog value.
|
||||
|
||||
**/
|
||||
#define GET_BACKLOG(Sock) ((Sock)->BackLog)
|
||||
|
||||
/**
|
||||
Set the socket with error state.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
@param[in] Error The error state.
|
||||
|
||||
**/
|
||||
#define SOCK_ERROR(Sock, Error) ((Sock)->SockError = (Error))
|
||||
|
||||
#define SOCK_SIGNATURE SIGNATURE_32 ('S', 'O', 'C', 'K')
|
||||
|
||||
#define SOCK_FROM_THIS(a) CR ((a), SOCKET, NetProtocol, SOCK_SIGNATURE)
|
||||
|
||||
#define SOCK_FROM_TOKEN(Token) (((SOCK_TOKEN *) (Token))->Sock)
|
||||
|
||||
#define PROTO_TOKEN_FORM_SOCK(SockToken, Type) ((Type *) (((SOCK_TOKEN *) (SockToken))->Token))
|
||||
|
||||
typedef struct _TCP_SOCKET SOCKET;
|
||||
|
||||
///
|
||||
/// Socket completion token
|
||||
///
|
||||
typedef struct _SOCK_COMPLETION_TOKEN {
|
||||
EFI_EVENT Event; ///< The event to be issued
|
||||
EFI_STATUS Status; ///< The status to be issued
|
||||
} SOCK_COMPLETION_TOKEN;
|
||||
|
||||
typedef union {
|
||||
VOID *RxData;
|
||||
VOID *TxData;
|
||||
} SOCK_IO_DATA;
|
||||
|
||||
///
|
||||
/// The application token with data packet
|
||||
///
|
||||
typedef struct _SOCK_IO_TOKEN {
|
||||
SOCK_COMPLETION_TOKEN Token;
|
||||
SOCK_IO_DATA Packet;
|
||||
} SOCK_IO_TOKEN;
|
||||
|
||||
///
|
||||
/// The socket type.
|
||||
///
|
||||
typedef enum {
|
||||
SockDgram, ///< This socket providing datagram service
|
||||
SockStream ///< This socket providing stream service
|
||||
} SOCK_TYPE;
|
||||
|
||||
///
|
||||
/// 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 handler of protocol for request from socket.
|
||||
|
||||
@param[in] Socket The socket issuing the request to protocol.
|
||||
@param[in] Request The request issued by socket.
|
||||
@param[in] RequestData The request related data.
|
||||
|
||||
@retval EFI_SUCCESS The socket request is completed successfully.
|
||||
@retval other The error status returned by the corresponding TCP
|
||||
layer function.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(*SOCK_PROTO_HANDLER) (
|
||||
IN SOCKET *Socket,
|
||||
IN UINT8 Request,
|
||||
IN VOID *RequestData
|
||||
);
|
||||
|
||||
/**
|
||||
The Callback funtion called after the TCP socket is created.
|
||||
|
||||
@param[in] This Pointer to the socket just created.
|
||||
@param[in] Context Context of the socket.
|
||||
|
||||
@retval EFI_SUCCESS This protocol installed successfully.
|
||||
@retval other Some error occured.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(*SOCK_CREATE_CALLBACK) (
|
||||
IN SOCKET *This,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
The callback function called before the TCP socket is to be destroyed.
|
||||
|
||||
@param[in] This The TCP socket to be destroyed.
|
||||
@param[in] Context The context.
|
||||
|
||||
**/
|
||||
typedef
|
||||
VOID
|
||||
(*SOCK_DESTROY_CALLBACK) (
|
||||
IN SOCKET *This,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
///
|
||||
/// The initialize data for create a new socket.
|
||||
///
|
||||
typedef struct _SOCK_INIT_DATA {
|
||||
SOCK_TYPE Type;
|
||||
UINT8 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
|
||||
UINT8 IpVersion;
|
||||
VOID *Protocol; ///< The pointer to protocol function template
|
||||
///< wanted to install on socket
|
||||
|
||||
//
|
||||
// Callbacks after socket is created and before socket is to be destroyed.
|
||||
//
|
||||
SOCK_CREATE_CALLBACK CreateCallback; ///< Callback after created
|
||||
SOCK_DESTROY_CALLBACK DestroyCallback; ///< Callback before destroied
|
||||
VOID *Context; ///< The context of the callback
|
||||
|
||||
//
|
||||
// Opaque protocol data.
|
||||
//
|
||||
VOID *ProtoData;
|
||||
UINT32 DataSize;
|
||||
|
||||
SOCK_PROTO_HANDLER ProtoHandler; ///< The handler of protocol for socket request
|
||||
|
||||
EFI_HANDLE DriverBinding; ///< The driver binding handle
|
||||
} SOCK_INIT_DATA;
|
||||
|
||||
///
|
||||
/// The union type of TCP and UDP protocol.
|
||||
///
|
||||
typedef union _NET_PROTOCOL {
|
||||
EFI_TCP4_PROTOCOL Tcp4Protocol; ///< Tcp4 protocol
|
||||
EFI_TCP6_PROTOCOL Tcp6Protocol; ///< Tcp6 protocol
|
||||
} NET_PROTOCOL;
|
||||
///
|
||||
/// The socket structure representing a network service access point.
|
||||
///
|
||||
struct _TCP_SOCKET {
|
||||
//
|
||||
// Socket description information
|
||||
//
|
||||
UINT32 Signature; ///< Signature of the socket
|
||||
EFI_HANDLE SockHandle; ///< The virtual handle of the socket
|
||||
EFI_HANDLE DriverBinding; ///< Socket's driver binding protocol
|
||||
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
LIST_ENTRY Link;
|
||||
UINT8 ConfigureState;
|
||||
SOCK_TYPE Type;
|
||||
UINT8 State;
|
||||
UINT16 Flag;
|
||||
EFI_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
|
||||
LIST_ENTRY ConnectionList; ///< the connections maintained by this socket
|
||||
//
|
||||
// The queue to buffer application's asynchronous token
|
||||
//
|
||||
LIST_ENTRY ListenTokenList;
|
||||
LIST_ENTRY RcvTokenList;
|
||||
LIST_ENTRY SndTokenList;
|
||||
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
|
||||
UINT8 IpVersion;
|
||||
NET_PROTOCOL NetProtocol; ///< TCP or UDP protocol socket used
|
||||
//
|
||||
// Callbacks after socket is created and before socket is to be destroyed.
|
||||
//
|
||||
SOCK_CREATE_CALLBACK CreateCallback; ///< Callback after created
|
||||
SOCK_DESTROY_CALLBACK DestroyCallback; ///< Callback before destroied
|
||||
VOID *Context; ///< The context of the callback
|
||||
};
|
||||
|
||||
///
|
||||
/// The token structure buffered in socket layer.
|
||||
///
|
||||
typedef struct _SOCK_TOKEN {
|
||||
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 TCP driver.
|
||||
///
|
||||
typedef struct _TCP_RSV_DATA {
|
||||
UINT32 UrgLen;
|
||||
} TCP_RSV_DATA;
|
||||
|
||||
//
|
||||
// Socket provided oprerations for low layer protocol implemented in SockImpl.c
|
||||
//
|
||||
|
||||
/**
|
||||
Set the state of the socket.
|
||||
|
||||
@param[in, out] Sock Pointer to the socket.
|
||||
@param[in] State The new socket state to be set.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SockSetState (
|
||||
IN OUT SOCKET *Sock,
|
||||
IN UINT8 State
|
||||
);
|
||||
|
||||
/**
|
||||
Clone a new socket including its associated protocol control block.
|
||||
|
||||
@param[in] Sock Pointer to the socket to be cloned.
|
||||
|
||||
@return Pointer to the newly cloned socket. If NULL, an error condition occurred.
|
||||
|
||||
**/
|
||||
SOCKET *
|
||||
SockClone (
|
||||
IN SOCKET *Sock
|
||||
);
|
||||
|
||||
/**
|
||||
Called by the low layer protocol to indicate the socket a connection is
|
||||
established.
|
||||
|
||||
This function just changes the socket's state to SO_CONNECTED
|
||||
and signals the token used for connection establishment.
|
||||
|
||||
@param[in, out] Sock Pointer to the socket associated with the
|
||||
established connection.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SockConnEstablished (
|
||||
IN OUT SOCKET *Sock
|
||||
);
|
||||
|
||||
/**
|
||||
Called by the low layer protocol to indicate that the connection is closed.
|
||||
|
||||
This function flushes the socket, sets the state to SO_CLOSED, and signals
|
||||
the close token.
|
||||
|
||||
@param[in, out] Sock Pointer to the socket associated with the closed
|
||||
connection.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SockConnClosed (
|
||||
IN OUT SOCKET *Sock
|
||||
);
|
||||
|
||||
/**
|
||||
Called by low layer protocol to indicate that some data is sent or processed.
|
||||
|
||||
This function trims the sent data in the socket send buffer and signals the data
|
||||
token, if proper.
|
||||
|
||||
@param[in, out] Sock Pointer to the socket.
|
||||
@param[in] Count The length of the data processed or sent, in bytes.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SockDataSent (
|
||||
IN OUT SOCKET *Sock,
|
||||
IN UINT32 Count
|
||||
);
|
||||
|
||||
/**
|
||||
Called by the low layer protocol to copy some data in socket send
|
||||
buffer starting from the specific offset to a buffer provided by
|
||||
the caller.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
@param[in] Offset The start point of the data to be copied.
|
||||
@param[in] Len The length of the data to be copied.
|
||||
@param[out] Dest Pointer to the destination to copy the data.
|
||||
|
||||
@return The data size copied.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
SockGetDataToSend (
|
||||
IN SOCKET *Sock,
|
||||
IN UINT32 Offset,
|
||||
IN UINT32 Len,
|
||||
OUT UINT8 *Dest
|
||||
);
|
||||
|
||||
/**
|
||||
Called by the low layer protocol to deliver received data to socket layer.
|
||||
|
||||
This function appends the data to the socket receive buffer, set the
|
||||
urgent data length, then checks if any receive token can be signaled.
|
||||
|
||||
@param[in, out] Sock Pointer to the socket.
|
||||
@param[in, out] NetBuffer Pointer to the buffer that contains the received data.
|
||||
@param[in] UrgLen The length of the urgent data in the received data.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SockDataRcvd (
|
||||
IN OUT SOCKET *Sock,
|
||||
IN OUT NET_BUF *NetBuffer,
|
||||
IN UINT32 UrgLen
|
||||
);
|
||||
|
||||
/**
|
||||
Get the length of the free space of the specific socket buffer.
|
||||
|
||||
@param[in] Sock Pointer to the socket.
|
||||
@param[in] Which Flag to indicate which socket buffer to check:
|
||||
either send buffer or receive buffer.
|
||||
|
||||
@return The length of the free space, in bytes.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
SockGetFreeSpace (
|
||||
IN SOCKET *Sock,
|
||||
IN UINT32 Which
|
||||
);
|
||||
|
||||
/**
|
||||
Called by the low layer protocol to indicate that there will be no more data
|
||||
from the communication peer.
|
||||
|
||||
This function sets the socket's state to SO_NO_MORE_DATA and signals all queued
|
||||
IO tokens with the error status EFI_CONNECTION_FIN.
|
||||
|
||||
@param[in, out] Sock Pointer to the socket.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SockNoMoreData (
|
||||
IN OUT SOCKET *Sock
|
||||
);
|
||||
|
||||
//
|
||||
// Socket provided operations for user interface implemented in SockInterface.c
|
||||
//
|
||||
|
||||
/**
|
||||
Create a socket and its associated protocol control block
|
||||
with the intial data SockInitData and protocol specific
|
||||
data ProtoData.
|
||||
|
||||
@param[in] SockInitData Inital data to setting the socket.
|
||||
|
||||
@return Pointer to the newly created socket. If NULL, an error condition occured.
|
||||
|
||||
**/
|
||||
SOCKET *
|
||||
SockCreateChild (
|
||||
IN SOCK_INIT_DATA *SockInitData
|
||||
);
|
||||
|
||||
/**
|
||||
Destory the socket Sock and its associated protocol control block.
|
||||
|
||||
@param[in, out] Sock The socket to be destroyed.
|
||||
|
||||
@retval EFI_SUCCESS The socket Sock was destroyed successfully.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockDestroyChild (
|
||||
IN OUT SOCKET *Sock
|
||||
);
|
||||
|
||||
/**
|
||||
Configure the specific socket Sock using configuration data ConfigData.
|
||||
|
||||
@param[in] Sock Pointer to the socket to be configured.
|
||||
@param[in] ConfigData Pointer to the configuration data.
|
||||
|
||||
@retval EFI_SUCCESS The socket 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
|
||||
);
|
||||
|
||||
/**
|
||||
Initiate a connection establishment process.
|
||||
|
||||
@param[in] Sock Pointer to the socket to initiate the initate the
|
||||
connection.
|
||||
@param[in] Token Pointer to the token used for the connection
|
||||
operation.
|
||||
|
||||
@retval EFI_SUCCESS The connection 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
|
||||
);
|
||||
|
||||
/**
|
||||
Issue a listen token to get an existed connected network instance,
|
||||
or wait for a connection if there is none.
|
||||
|
||||
@param[in] Sock Pointer to the socket to accept connections.
|
||||
@param[in] Token The token to accept a connection.
|
||||
|
||||
@retval EFI_SUCCESS Either a connection is accepted or the Token is
|
||||
buffered for further acceptance.
|
||||
@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
|
||||
);
|
||||
|
||||
/**
|
||||
Issue a token with data to the socket to send out.
|
||||
|
||||
@param[in] Sock Pointer to the socket to process the token with
|
||||
data.
|
||||
@param[in] Token The token with data that needs to send out.
|
||||
|
||||
@retval EFI_SUCCESS The token 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 a memory limit.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockSend (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Issue a token to get data from the socket.
|
||||
|
||||
@param[in] Sock Pointer to the socket to get data from.
|
||||
@param[in] Token The token to store the received data from the
|
||||
socket.
|
||||
|
||||
@retval EFI_SUCCESS The token 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 a memory limit.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockRcv (
|
||||
IN SOCKET *Sock,
|
||||
IN VOID *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Reset the socket and its associated protocol control block.
|
||||
|
||||
@param[in, out] Sock Pointer to the socket to be flushed.
|
||||
|
||||
@retval EFI_SUCCESS The socket flushed successfully.
|
||||
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockFlush (
|
||||
IN OUT SOCKET *Sock
|
||||
);
|
||||
|
||||
/**
|
||||
Close or abort the socket associated connection.
|
||||
|
||||
@param[in, out] Sock Pointer to the socket of the connection to close
|
||||
or abort.
|
||||
@param[in] Token The token for close operation.
|
||||
@param[in] OnAbort TRUE for aborting the connection, FALSE to close it.
|
||||
|
||||
@retval EFI_SUCCESS The close or abort operation 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 OUT SOCKET *Sock,
|
||||
IN VOID *Token,
|
||||
IN BOOLEAN OnAbort
|
||||
);
|
||||
|
||||
/**
|
||||
Get the mode data of the low layer protocol.
|
||||
|
||||
@param[in] Sock Pointer to the socket to get mode data from.
|
||||
@param[in, out] Mode Pointer to the data to store the low layer mode
|
||||
information.
|
||||
|
||||
@retval EFI_SUCCESS The mode data was obtained successfully.
|
||||
@retval EFI_NOT_STARTED The socket is not configured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SockGetMode (
|
||||
IN SOCKET *Sock,
|
||||
IN OUT VOID *Mode
|
||||
);
|
||||
|
||||
/**
|
||||
Configure the low level protocol to join a multicast group for
|
||||
this socket's connection.
|
||||
|
||||
@param[in] Sock Pointer to the socket of the connection to join the
|
||||
specific multicast group.
|
||||
@param[in] GroupInfo Pointer to the multicast group information.
|
||||
|
||||
@retval EFI_SUCCESS The configuration completed 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
|
||||
);
|
||||
|
||||
/**
|
||||
Add or remove route information in IP route table associated
|
||||
with this socket.
|
||||
|
||||
@param[in] Sock Pointer to the socket associated with the IP route
|
||||
table to operate on.
|
||||
@param[in] RouteInfo Pointer to the route information to be processed.
|
||||
|
||||
@retval EFI_SUCCESS The route table 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
|
||||
);
|
||||
|
||||
#endif
|
861
NetworkPkg/TcpDxe/TcpDispatcher.c
Normal file
861
NetworkPkg/TcpDxe/TcpDispatcher.c
Normal file
@@ -0,0 +1,861 @@
|
||||
/** @file
|
||||
The implementation of a dispatch routine for processing TCP requests.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "TcpMain.h"
|
||||
|
||||
/**
|
||||
Add or remove a route entry in the IP route table associated with this TCP instance.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] RouteInfo Pointer to the route information to be processed.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_NOT_STARTED The driver instance has not been started.
|
||||
@retval EFI_NO_MAPPING When using the default address, configuration(DHCP,
|
||||
BOOTP, RARP, etc.) is not finished yet.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.
|
||||
@retval EFI_NOT_FOUND This route is not in the routing table
|
||||
(when RouteInfo->DeleteRoute is TRUE).
|
||||
@retval EFI_ACCESS_DENIED The route is already defined in the routing table
|
||||
(when RouteInfo->DeleteRoute is FALSE).
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tcp4Route (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP4_ROUTE_INFO *RouteInfo
|
||||
)
|
||||
{
|
||||
IP_IO_IP_PROTOCOL Ip;
|
||||
|
||||
Ip = Tcb->IpInfo->Ip;
|
||||
|
||||
ASSERT (Ip.Ip4!= NULL);
|
||||
|
||||
return Ip.Ip4->Routes (
|
||||
Ip.Ip4,
|
||||
RouteInfo->DeleteRoute,
|
||||
RouteInfo->SubnetAddress,
|
||||
RouteInfo->SubnetMask,
|
||||
RouteInfo->GatewayAddress
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Get the operational settings of this TCPv4 instance.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in, out] Mode Pointer to the buffer to store the operational
|
||||
settings.
|
||||
|
||||
@retval EFI_SUCCESS The mode data was read.
|
||||
@retval EFI_NOT_STARTED No configuration data is available because this
|
||||
instance hasn't been started.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tcp4GetMode (
|
||||
IN TCP_CB *Tcb,
|
||||
IN OUT 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 != NULL) {
|
||||
*(Mode->Tcp4State) = (EFI_TCP4_CONNECTION_STATE) Tcb->State;
|
||||
}
|
||||
|
||||
if (Mode->Tcp4ConfigData != NULL) {
|
||||
|
||||
ConfigData = Mode->Tcp4ConfigData;
|
||||
AccessPoint = &(ConfigData->AccessPoint);
|
||||
Option = ConfigData->ControlOption;
|
||||
|
||||
ConfigData->TypeOfService = Tcb->Tos;
|
||||
ConfigData->TimeToLive = Tcb->Ttl;
|
||||
|
||||
AccessPoint->UseDefaultAddress = Tcb->UseDefaultAddr;
|
||||
|
||||
CopyMem (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
AccessPoint->SubnetMask = Tcb->SubnetMask;
|
||||
AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port);
|
||||
|
||||
CopyMem (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip, sizeof (EFI_IPv4_ADDRESS));
|
||||
|
||||
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 = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE));
|
||||
Option->EnableTimeStamp = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS));
|
||||
Option->EnableWindowScaling = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS));
|
||||
|
||||
Option->EnableSelectiveAck = FALSE;
|
||||
Option->EnablePathMtuDiscovery = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Ip = Tcb->IpInfo->Ip.Ip4;
|
||||
ASSERT (Ip != NULL);
|
||||
|
||||
return Ip->GetModeData (Ip, Mode->Ip4ModeData, Mode->MnpConfigData, Mode->SnpModeData);
|
||||
}
|
||||
|
||||
/**
|
||||
Get the operational settings of this TCPv6 instance.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in, out] Mode Pointer to the buffer to store the operational
|
||||
settings.
|
||||
|
||||
@retval EFI_SUCCESS The mode data was read.
|
||||
@retval EFI_NOT_STARTED No configuration data is available because this
|
||||
instance hasn't been started.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tcp6GetMode (
|
||||
IN TCP_CB *Tcb,
|
||||
IN OUT TCP6_MODE_DATA *Mode
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
EFI_TCP6_CONFIG_DATA *ConfigData;
|
||||
EFI_TCP6_ACCESS_POINT *AccessPoint;
|
||||
EFI_TCP6_OPTION *Option;
|
||||
EFI_IP6_PROTOCOL *Ip;
|
||||
|
||||
Sock = Tcb->Sk;
|
||||
|
||||
if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp6ConfigData != NULL)) {
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
if (Mode->Tcp6State != NULL) {
|
||||
*(Mode->Tcp6State) = (EFI_TCP6_CONNECTION_STATE) (Tcb->State);
|
||||
}
|
||||
|
||||
if (Mode->Tcp6ConfigData != NULL) {
|
||||
|
||||
ConfigData = Mode->Tcp6ConfigData;
|
||||
AccessPoint = &(ConfigData->AccessPoint);
|
||||
Option = ConfigData->ControlOption;
|
||||
|
||||
ConfigData->TrafficClass = Tcb->Tos;
|
||||
ConfigData->HopLimit = Tcb->Ttl;
|
||||
|
||||
AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port);
|
||||
AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port);
|
||||
AccessPoint->ActiveFlag = (BOOLEAN) (Tcb->State != TCP_LISTEN);
|
||||
|
||||
IP6_COPY_ADDRESS (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip);
|
||||
IP6_COPY_ADDRESS (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip);
|
||||
|
||||
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 = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE));
|
||||
Option->EnableTimeStamp = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS));
|
||||
Option->EnableWindowScaling = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS));
|
||||
|
||||
Option->EnableSelectiveAck = FALSE;
|
||||
Option->EnablePathMtuDiscovery = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Ip = Tcb->IpInfo->Ip.Ip6;
|
||||
ASSERT (Ip != NULL);
|
||||
|
||||
return Ip->GetModeData (Ip, Mode->Ip6ModeData, Mode->MnpConfigData, Mode->SnpModeData);
|
||||
}
|
||||
|
||||
/**
|
||||
If TcpAp->StationPort isn't zero, check whether the access point
|
||||
is registered, else generate a random station port for this
|
||||
access point.
|
||||
|
||||
@param[in] TcpAp Pointer to the access point.
|
||||
@param[in] IpVersion IP_VERSION_4 or IP_VERSION_6
|
||||
|
||||
@retval EFI_SUCCESS The check 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.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpBind (
|
||||
IN TCP_ACCESS_POINT *TcpAp,
|
||||
IN UINT8 IpVersion
|
||||
)
|
||||
{
|
||||
BOOLEAN Cycle;
|
||||
EFI_IP_ADDRESS Local;
|
||||
UINT16 *Port;
|
||||
UINT16 *RandomPort;
|
||||
|
||||
if (IpVersion == IP_VERSION_4) {
|
||||
CopyMem (&Local, &TcpAp->Tcp4Ap.StationAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
Port = &TcpAp->Tcp4Ap.StationPort;
|
||||
RandomPort = &mTcp4RandomPort;
|
||||
} else {
|
||||
IP6_COPY_ADDRESS (&Local, &TcpAp->Tcp6Ap.StationAddress);
|
||||
Port = &TcpAp->Tcp6Ap.StationPort;
|
||||
RandomPort = &mTcp6RandomPort;
|
||||
}
|
||||
|
||||
if (0 != *Port) {
|
||||
//
|
||||
// Check if a same endpoing is bound.
|
||||
//
|
||||
if (TcpFindTcbByPeer (&Local, *Port, IpVersion)) {
|
||||
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// generate a random port
|
||||
//
|
||||
Cycle = FALSE;
|
||||
|
||||
if (TCP_PORT_USER_RESERVED == *RandomPort) {
|
||||
*RandomPort = TCP_PORT_KNOWN;
|
||||
}
|
||||
|
||||
(*RandomPort)++;
|
||||
|
||||
while (TcpFindTcbByPeer (&Local, *RandomPort, IpVersion)) {
|
||||
(*RandomPort)++;
|
||||
|
||||
if (*RandomPort <= TCP_PORT_KNOWN) {
|
||||
if (Cycle) {
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"TcpBind: no port can be allocated for this pcb\n")
|
||||
);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
*RandomPort = TCP_PORT_KNOWN + 1;
|
||||
|
||||
Cycle = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
*Port = *RandomPort;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Flush the Tcb add its associated protocols.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB to be flushed.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpFlushPcb (
|
||||
IN OUT TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
TCP_PROTO_DATA *TcpProto;
|
||||
|
||||
IpIoConfigIp (Tcb->IpInfo, NULL);
|
||||
|
||||
Sock = Tcb->Sk;
|
||||
TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved;
|
||||
|
||||
if (SOCK_IS_CONFIGURED (Sock)) {
|
||||
RemoveEntryList (&Tcb->List);
|
||||
|
||||
if (Sock->DevicePath != NULL) {
|
||||
//
|
||||
// Uninstall the device path protocl.
|
||||
//
|
||||
gBS->UninstallProtocolInterface (
|
||||
Sock->SockHandle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
Sock->DevicePath
|
||||
);
|
||||
|
||||
FreePool (Sock->DevicePath);
|
||||
Sock->DevicePath = NULL;
|
||||
}
|
||||
|
||||
TcpSetVariableData (TcpProto->TcpService);
|
||||
}
|
||||
|
||||
NetbufFreeList (&Tcb->SndQue);
|
||||
NetbufFreeList (&Tcb->RcvQue);
|
||||
Tcb->State = TCP_CLOSED;
|
||||
}
|
||||
|
||||
/**
|
||||
Attach a Pcb to the socket.
|
||||
|
||||
@param[in] Sk Pointer to the socket of this TCP instance.
|
||||
|
||||
@retval EFI_SUCCESS The operation completed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed due to resource limits.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpAttachPcb (
|
||||
IN SOCKET *Sk
|
||||
)
|
||||
{
|
||||
TCP_CB *Tcb;
|
||||
TCP_PROTO_DATA *ProtoData;
|
||||
IP_IO *IpIo;
|
||||
|
||||
Tcb = AllocateZeroPool (sizeof (TCP_CB));
|
||||
|
||||
if (Tcb == NULL) {
|
||||
|
||||
DEBUG ((EFI_D_ERROR, "TcpConfigurePcb: failed to allocate a TCB\n"));
|
||||
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
ProtoData = (TCP_PROTO_DATA *) Sk->ProtoReserved;
|
||||
IpIo = ProtoData->TcpService->IpIo;
|
||||
|
||||
//
|
||||
// Create an IpInfo for this Tcb.
|
||||
//
|
||||
Tcb->IpInfo = IpIoAddIp (IpIo);
|
||||
if (Tcb->IpInfo == NULL) {
|
||||
|
||||
FreePool (Tcb);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
InitializeListHead (&Tcb->List);
|
||||
InitializeListHead (&Tcb->SndQue);
|
||||
InitializeListHead (&Tcb->RcvQue);
|
||||
|
||||
Tcb->State = TCP_CLOSED;
|
||||
Tcb->Sk = Sk;
|
||||
ProtoData->TcpPcb = Tcb;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Detach the Pcb of the socket.
|
||||
|
||||
@param[in, out] Sk Pointer to the socket of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpDetachPcb (
|
||||
IN OUT SOCKET *Sk
|
||||
)
|
||||
{
|
||||
TCP_PROTO_DATA *ProtoData;
|
||||
TCP_CB *Tcb;
|
||||
|
||||
ProtoData = (TCP_PROTO_DATA *) Sk->ProtoReserved;
|
||||
Tcb = ProtoData->TcpPcb;
|
||||
|
||||
ASSERT (Tcb != NULL);
|
||||
|
||||
TcpFlushPcb (Tcb);
|
||||
|
||||
IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);
|
||||
|
||||
FreePool (Tcb);
|
||||
|
||||
ProtoData->TcpPcb = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Configure the Pcb using CfgData.
|
||||
|
||||
@param[in] Sk Pointer to the socket of this TCP instance.
|
||||
@param[in] CfgData Pointer to the TCP configuration data.
|
||||
|
||||
@retval EFI_SUCCESS The operation 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 limits.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpConfigurePcb (
|
||||
IN SOCKET *Sk,
|
||||
IN TCP_CONFIG_DATA *CfgData
|
||||
)
|
||||
{
|
||||
IP_IO_IP_CONFIG_DATA IpCfgData;
|
||||
EFI_STATUS Status;
|
||||
EFI_TCP4_OPTION *Option;
|
||||
TCP_PROTO_DATA *TcpProto;
|
||||
TCP_CB *Tcb;
|
||||
TCP_ACCESS_POINT *TcpAp;
|
||||
|
||||
ASSERT ((CfgData != NULL) && (Sk != NULL) && (Sk->SockHandle != NULL));
|
||||
|
||||
TcpProto = (TCP_PROTO_DATA *) Sk->ProtoReserved;
|
||||
Tcb = TcpProto->TcpPcb;
|
||||
|
||||
ASSERT (Tcb != NULL);
|
||||
|
||||
if (Sk->IpVersion == IP_VERSION_4) {
|
||||
//
|
||||
// Add Ip for send pkt to the peer
|
||||
//
|
||||
CopyMem (&IpCfgData.Ip4CfgData, &mIp4IoDefaultIpConfigData, sizeof (EFI_IP4_CONFIG_DATA));
|
||||
IpCfgData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
|
||||
IpCfgData.Ip4CfgData.TypeOfService = CfgData->Tcp4CfgData.TypeOfService;
|
||||
IpCfgData.Ip4CfgData.TimeToLive = CfgData->Tcp4CfgData.TimeToLive;
|
||||
IpCfgData.Ip4CfgData.UseDefaultAddress = CfgData->Tcp4CfgData.AccessPoint.UseDefaultAddress;
|
||||
IpCfgData.Ip4CfgData.SubnetMask = CfgData->Tcp4CfgData.AccessPoint.SubnetMask;
|
||||
IpCfgData.Ip4CfgData.ReceiveTimeout = (UINT32) (-1);
|
||||
CopyMem (
|
||||
&IpCfgData.Ip4CfgData.StationAddress,
|
||||
&CfgData->Tcp4CfgData.AccessPoint.StationAddress,
|
||||
sizeof (EFI_IPv4_ADDRESS)
|
||||
);
|
||||
|
||||
} else {
|
||||
ASSERT (Sk->IpVersion == IP_VERSION_6);
|
||||
|
||||
CopyMem (&IpCfgData.Ip6CfgData, &mIp6IoDefaultIpConfigData, sizeof (EFI_IP6_CONFIG_DATA));
|
||||
IpCfgData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
|
||||
IpCfgData.Ip6CfgData.TrafficClass = CfgData->Tcp6CfgData.TrafficClass;
|
||||
IpCfgData.Ip6CfgData.HopLimit = CfgData->Tcp6CfgData.HopLimit;
|
||||
IpCfgData.Ip6CfgData.ReceiveTimeout = (UINT32) (-1);
|
||||
IP6_COPY_ADDRESS (
|
||||
&IpCfgData.Ip6CfgData.StationAddress,
|
||||
&CfgData->Tcp6CfgData.AccessPoint.StationAddress
|
||||
);
|
||||
IP6_COPY_ADDRESS (
|
||||
&IpCfgData.Ip6CfgData.DestinationAddress,
|
||||
&CfgData->Tcp6CfgData.AccessPoint.RemoteAddress
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Configure the IP instance this Tcb consumes.
|
||||
//
|
||||
Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto OnExit;
|
||||
}
|
||||
|
||||
if (Sk->IpVersion == IP_VERSION_4) {
|
||||
//
|
||||
// Get the default address information if the instance is configured to use default address.
|
||||
//
|
||||
CfgData->Tcp4CfgData.AccessPoint.StationAddress = IpCfgData.Ip4CfgData.StationAddress;
|
||||
CfgData->Tcp4CfgData.AccessPoint.SubnetMask = IpCfgData.Ip4CfgData.SubnetMask;
|
||||
|
||||
TcpAp = (TCP_ACCESS_POINT *) &CfgData->Tcp4CfgData.AccessPoint;
|
||||
} else {
|
||||
IP6_COPY_ADDRESS (
|
||||
&CfgData->Tcp6CfgData.AccessPoint.StationAddress,
|
||||
&IpCfgData.Ip6CfgData.StationAddress
|
||||
);
|
||||
|
||||
TcpAp = (TCP_ACCESS_POINT *) &CfgData->Tcp6CfgData.AccessPoint;
|
||||
}
|
||||
|
||||
//
|
||||
// check if we can bind this endpoint in CfgData
|
||||
//
|
||||
Status = TcpBind (TcpAp, Sk->IpVersion);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"TcpConfigurePcb: Bind endpoint failed with %r\n",
|
||||
Status)
|
||||
);
|
||||
|
||||
goto OnExit;
|
||||
}
|
||||
|
||||
//
|
||||
// Initalize the operating information in this Tcb
|
||||
//
|
||||
ASSERT (Tcb->State == TCP_CLOSED &&
|
||||
IsListEmpty (&Tcb->SndQue) &&
|
||||
IsListEmpty (&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;
|
||||
|
||||
if (Sk->IpVersion == IP_VERSION_4) {
|
||||
//
|
||||
// initialize Tcb in the light of CfgData
|
||||
//
|
||||
Tcb->Ttl = CfgData->Tcp4CfgData.TimeToLive;
|
||||
Tcb->Tos = CfgData->Tcp4CfgData.TypeOfService;
|
||||
|
||||
Tcb->UseDefaultAddr = CfgData->Tcp4CfgData.AccessPoint.UseDefaultAddress;
|
||||
|
||||
CopyMem (&Tcb->LocalEnd.Ip, &CfgData->Tcp4CfgData.AccessPoint.StationAddress, sizeof (IP4_ADDR));
|
||||
Tcb->LocalEnd.Port = HTONS (CfgData->Tcp4CfgData.AccessPoint.StationPort);
|
||||
Tcb->SubnetMask = CfgData->Tcp4CfgData.AccessPoint.SubnetMask;
|
||||
|
||||
CopyMem (&Tcb->RemoteEnd.Ip, &CfgData->Tcp4CfgData.AccessPoint.RemoteAddress, sizeof (IP4_ADDR));
|
||||
Tcb->RemoteEnd.Port = HTONS (CfgData->Tcp4CfgData.AccessPoint.RemotePort);
|
||||
|
||||
Option = CfgData->Tcp4CfgData.ControlOption;
|
||||
} else {
|
||||
Tcb->Ttl = CfgData->Tcp6CfgData.HopLimit;
|
||||
Tcb->Tos = CfgData->Tcp6CfgData.TrafficClass;
|
||||
|
||||
IP6_COPY_ADDRESS (&Tcb->LocalEnd.Ip, &CfgData->Tcp6CfgData.AccessPoint.StationAddress);
|
||||
Tcb->LocalEnd.Port = HTONS (CfgData->Tcp6CfgData.AccessPoint.StationPort);
|
||||
|
||||
IP6_COPY_ADDRESS (&Tcb->RemoteEnd.Ip, &CfgData->Tcp6CfgData.AccessPoint.RemoteAddress);
|
||||
Tcb->RemoteEnd.Port = HTONS (CfgData->Tcp6CfgData.AccessPoint.RemotePort);
|
||||
|
||||
//
|
||||
// Type EFI_TCP4_OPTION and EFI_TCP6_OPTION are the same.
|
||||
//
|
||||
Option = (EFI_TCP4_OPTION *) CfgData->Tcp6CfgData.ControlOption;
|
||||
}
|
||||
|
||||
if (Option != NULL) {
|
||||
SET_RCV_BUFFSIZE (
|
||||
Sk,
|
||||
(UINT32) (TCP_COMP_VAL (
|
||||
TCP_RCV_BUF_SIZE_MIN,
|
||||
TCP_RCV_BUF_SIZE,
|
||||
TCP_RCV_BUF_SIZE,
|
||||
Option->ReceiveBufferSize
|
||||
)
|
||||
)
|
||||
);
|
||||
SET_SND_BUFFSIZE (
|
||||
Sk,
|
||||
(UINT32) (TCP_COMP_VAL (
|
||||
TCP_SND_BUF_SIZE_MIN,
|
||||
TCP_SND_BUF_SIZE,
|
||||
TCP_SND_BUF_SIZE,
|
||||
Option->SendBufferSize
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
SET_BACKLOG (
|
||||
Sk,
|
||||
(UINT32) (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,
|
||||
(UINT32) (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,
|
||||
(UINT32) (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,
|
||||
(UINT32) (Option->KeepAliveTime * TCP_TICK_HZ)
|
||||
);
|
||||
Tcb->KeepAlivePeriod = TCP_COMP_VAL (
|
||||
TCP_KEEPALIVE_PERIOD_MIN,
|
||||
TCP_KEEPALIVE_PERIOD,
|
||||
TCP_KEEPALIVE_PERIOD,
|
||||
(UINT32) (Option->KeepAliveInterval * TCP_TICK_HZ)
|
||||
);
|
||||
}
|
||||
|
||||
Tcb->ConnectTimeout = TCP_COMP_VAL (
|
||||
TCP_CONNECT_TIME_MIN,
|
||||
TCP_CONNECT_TIME,
|
||||
TCP_CONNECT_TIME,
|
||||
(UINT32) (Option->ConnectionTimeout * TCP_TICK_HZ)
|
||||
);
|
||||
|
||||
if (!Option->EnableNagle) {
|
||||
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
|
||||
}
|
||||
|
||||
if (!Option->EnableTimeStamp) {
|
||||
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
|
||||
}
|
||||
|
||||
if (!Option->EnableWindowScaling) {
|
||||
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is
|
||||
// determined, construct the IP device path and install it.
|
||||
//
|
||||
Status = TcpInstallDevicePath (Sk);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto OnExit;
|
||||
}
|
||||
|
||||
//
|
||||
// update state of Tcb and socket
|
||||
//
|
||||
if (((Sk->IpVersion == IP_VERSION_4) && !CfgData->Tcp4CfgData.AccessPoint.ActiveFlag) ||
|
||||
((Sk->IpVersion == IP_VERSION_6) && !CfgData->Tcp6CfgData.AccessPoint.ActiveFlag)
|
||||
) {
|
||||
|
||||
TcpSetState (Tcb, TCP_LISTEN);
|
||||
SockSetState (Sk, SO_LISTENING);
|
||||
|
||||
Sk->ConfigureState = SO_CONFIGURED_PASSIVE;
|
||||
} else {
|
||||
|
||||
Sk->ConfigureState = SO_CONFIGURED_ACTIVE;
|
||||
}
|
||||
|
||||
if (Sk->IpVersion == IP_VERSION_6) {
|
||||
Tcb->Tick = TCP6_REFRESH_NEIGHBOR_TICK;
|
||||
}
|
||||
|
||||
TcpInsertTcb (Tcb);
|
||||
|
||||
OnExit:
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
The procotol handler provided to the socket layer, which is used to
|
||||
dispatch the socket level requests by calling the corresponding
|
||||
TCP layer functions.
|
||||
|
||||
@param[in] Sock Pointer to the socket of this TCP instance.
|
||||
@param[in] Request The code of this operation request.
|
||||
@param[in] Data Pointer to the operation specific data passed in
|
||||
together with the operation request. This is an
|
||||
optional parameter that may be NULL.
|
||||
|
||||
@retval EFI_SUCCESS The socket request completed successfully.
|
||||
@retval other The error status returned by the corresponding TCP
|
||||
layer function.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpDispatcher (
|
||||
IN SOCKET *Sock,
|
||||
IN UINT8 Request,
|
||||
IN VOID *Data OPTIONAL
|
||||
)
|
||||
{
|
||||
TCP_CB *Tcb;
|
||||
TCP_PROTO_DATA *ProtoData;
|
||||
|
||||
ProtoData = (TCP_PROTO_DATA *) Sock->ProtoReserved;
|
||||
Tcb = ProtoData->TcpPcb;
|
||||
|
||||
switch (Request) {
|
||||
case SOCK_POLL:
|
||||
if (Tcb->Sk->IpVersion == IP_VERSION_4) {
|
||||
ProtoData->TcpService->IpIo->Ip.Ip4->Poll (ProtoData->TcpService->IpIo->Ip.Ip4);
|
||||
} else {
|
||||
ProtoData->TcpService->IpIo->Ip.Ip6->Poll (ProtoData->TcpService->IpIo->Ip.Ip6);
|
||||
}
|
||||
|
||||
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 != NULL);
|
||||
TcpOnAppConsume (Tcb);
|
||||
break;
|
||||
|
||||
case SOCK_SND:
|
||||
|
||||
ASSERT (Tcb != NULL);
|
||||
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 TcpAttachPcb (Sock);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_FLUSH:
|
||||
|
||||
TcpFlushPcb (Tcb);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_DETACH:
|
||||
|
||||
TcpDetachPcb (Sock);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_CONFIGURE:
|
||||
|
||||
return TcpConfigurePcb (
|
||||
Sock,
|
||||
(TCP_CONFIG_DATA *) Data
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_MODE:
|
||||
|
||||
ASSERT ((Data != NULL) && (Tcb != NULL));
|
||||
|
||||
if (Tcb->Sk->IpVersion == IP_VERSION_4) {
|
||||
|
||||
return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data);
|
||||
} else {
|
||||
|
||||
return Tcp6GetMode (Tcb, (TCP6_MODE_DATA *) Data);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SOCK_ROUTE:
|
||||
|
||||
ASSERT ((Data != NULL) && (Tcb != NULL) && (Tcb->Sk->IpVersion == IP_VERSION_4));
|
||||
|
||||
return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data);
|
||||
|
||||
default:
|
||||
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
891
NetworkPkg/TcpDxe/TcpDriver.c
Normal file
891
NetworkPkg/TcpDxe/TcpDriver.c
Normal file
@@ -0,0 +1,891 @@
|
||||
/** @file
|
||||
The driver binding and service binding protocol for the TCP driver.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "TcpMain.h"
|
||||
|
||||
UINT16 mTcp4RandomPort;
|
||||
UINT16 mTcp6RandomPort;
|
||||
|
||||
TCP_HEARTBEAT_TIMER mTcpTimer = {
|
||||
NULL,
|
||||
0
|
||||
};
|
||||
|
||||
EFI_TCP4_PROTOCOL gTcp4ProtocolTemplate = {
|
||||
Tcp4GetModeData,
|
||||
Tcp4Configure,
|
||||
Tcp4Routes,
|
||||
Tcp4Connect,
|
||||
Tcp4Accept,
|
||||
Tcp4Transmit,
|
||||
Tcp4Receive,
|
||||
Tcp4Close,
|
||||
Tcp4Cancel,
|
||||
Tcp4Poll
|
||||
};
|
||||
|
||||
EFI_TCP6_PROTOCOL gTcp6ProtocolTemplate = {
|
||||
Tcp6GetModeData,
|
||||
Tcp6Configure,
|
||||
Tcp6Connect,
|
||||
Tcp6Accept,
|
||||
Tcp6Transmit,
|
||||
Tcp6Receive,
|
||||
Tcp6Close,
|
||||
Tcp6Cancel,
|
||||
Tcp6Poll
|
||||
};
|
||||
|
||||
SOCK_INIT_DATA mTcpDefaultSockData = {
|
||||
SockStream,
|
||||
SO_CLOSED,
|
||||
NULL,
|
||||
TCP_BACKLOG,
|
||||
TCP_SND_BUF_SIZE,
|
||||
TCP_RCV_BUF_SIZE,
|
||||
IP_VERSION_4,
|
||||
NULL,
|
||||
TcpCreateSocketCallback,
|
||||
TcpDestroySocketCallback,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
TcpDispatcher,
|
||||
NULL,
|
||||
};
|
||||
|
||||
EFI_DRIVER_BINDING_PROTOCOL gTcpDriverBinding = {
|
||||
TcpDriverBindingSupported,
|
||||
TcpDriverBindingStart,
|
||||
TcpDriverBindingStop,
|
||||
0xa,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
EFI_SERVICE_BINDING_PROTOCOL gTcpServiceBinding = {
|
||||
TcpServiceBindingCreateChild,
|
||||
TcpServiceBindingDestroyChild
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Create and start the heartbeat timer for the TCP driver.
|
||||
|
||||
@retval EFI_SUCCESS The timer was successfully created and started.
|
||||
@retval other The timer was not created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpCreateTimer (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
if (mTcpTimer.RefCnt == 0) {
|
||||
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_TIMER | EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
TcpTicking,
|
||||
NULL,
|
||||
&mTcpTimer.TimerEvent
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
|
||||
Status = gBS->SetTimer (
|
||||
mTcpTimer.TimerEvent,
|
||||
TimerPeriodic,
|
||||
(UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
|
||||
mTcpTimer.RefCnt++;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Stop and destroy the heartbeat timer for TCP driver.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpDestroyTimer (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT (mTcpTimer.RefCnt > 0);
|
||||
|
||||
mTcpTimer.RefCnt--;
|
||||
|
||||
if (mTcpTimer.RefCnt > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
gBS->SetTimer (mTcpTimer.TimerEvent, TimerCancel, 0);
|
||||
gBS->CloseEvent (mTcpTimer.TimerEvent);
|
||||
mTcpTimer.TimerEvent = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
The entry point for Tcp driver, which is used to install Tcp driver on the ImageHandle.
|
||||
|
||||
@param[in] ImageHandle The firmware allocated handle for this driver image.
|
||||
@param[in] SystemTable Pointer to the EFI system table.
|
||||
|
||||
@retval EFI_SUCCESS The driver loaded.
|
||||
@retval other The driver did not load.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpDriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Seed;
|
||||
|
||||
//
|
||||
// Install the TCP Driver Binding Protocol
|
||||
//
|
||||
Status = EfiLibInstallDriverBindingComponentName2 (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gTcpDriverBinding,
|
||||
ImageHandle,
|
||||
&gTcpComponentName,
|
||||
&gTcpComponentName2
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize ISS and random port.
|
||||
//
|
||||
Seed = NetRandomInitSeed ();
|
||||
mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;
|
||||
mTcp4RandomPort = (UINT16) (TCP_PORT_KNOWN + (NET_RANDOM (Seed) % TCP_PORT_KNOWN));
|
||||
mTcp6RandomPort = mTcp4RandomPort;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Create a new TCP4 or TCP6 driver service binding protocol
|
||||
|
||||
@param[in] Controller Controller handle of device to bind driver to.
|
||||
@param[in] ImageHandle The TCP driver's image handle.
|
||||
@param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
|
||||
@retval EFI_SUCCESS A new IP6 service binding private was created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpCreateService (
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_HANDLE Image,
|
||||
IN UINT8 IpVersion
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_GUID *IpServiceBindingGuid;
|
||||
EFI_GUID *TcpServiceBindingGuid;
|
||||
TCP_SERVICE_DATA *TcpServiceData;
|
||||
IP_IO_OPEN_DATA OpenData;
|
||||
|
||||
if (IpVersion == IP_VERSION_4) {
|
||||
IpServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;
|
||||
TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
|
||||
} else {
|
||||
IpServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;
|
||||
TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
TcpServiceBindingGuid,
|
||||
NULL,
|
||||
Image,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
IpServiceBindingGuid,
|
||||
NULL,
|
||||
Image,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Create the TCP service data.
|
||||
//
|
||||
TcpServiceData = AllocateZeroPool (sizeof (TCP_SERVICE_DATA));
|
||||
if (TcpServiceData == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
TcpServiceData->Signature = TCP_DRIVER_SIGNATURE;
|
||||
TcpServiceData->ControllerHandle = Controller;
|
||||
TcpServiceData->DriverBindingHandle = Image;
|
||||
TcpServiceData->IpVersion = IpVersion;
|
||||
CopyMem (
|
||||
&TcpServiceData->ServiceBinding,
|
||||
&gTcpServiceBinding,
|
||||
sizeof (EFI_SERVICE_BINDING_PROTOCOL)
|
||||
);
|
||||
|
||||
TcpServiceData->IpIo = IpIoCreate (Image, Controller, IpVersion);
|
||||
if (TcpServiceData->IpIo == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
|
||||
InitializeListHead (&TcpServiceData->SocketList);
|
||||
ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));
|
||||
|
||||
if (IpVersion == IP_VERSION_4) {
|
||||
CopyMem (
|
||||
&OpenData.IpConfigData.Ip4CfgData,
|
||||
&mIp4IoDefaultIpConfigData,
|
||||
sizeof (EFI_IP4_CONFIG_DATA)
|
||||
);
|
||||
OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
|
||||
} else {
|
||||
CopyMem (
|
||||
&OpenData.IpConfigData.Ip6CfgData,
|
||||
&mIp6IoDefaultIpConfigData,
|
||||
sizeof (EFI_IP6_CONFIG_DATA)
|
||||
);
|
||||
OpenData.IpConfigData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
|
||||
}
|
||||
|
||||
OpenData.PktRcvdNotify = TcpRxCallback;
|
||||
Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = TcpCreateTimer ();
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&Controller,
|
||||
TcpServiceBindingGuid,
|
||||
&TcpServiceData->ServiceBinding,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
TcpDestroyTimer ();
|
||||
|
||||
goto ON_ERROR;
|
||||
}
|
||||
|
||||
TcpSetVariableData (TcpServiceData);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ON_ERROR:
|
||||
|
||||
if (TcpServiceData->IpIo != NULL) {
|
||||
IpIoDestroy (TcpServiceData->IpIo);
|
||||
}
|
||||
|
||||
FreePool (TcpServiceData);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Destroy a TCP6 or TCP4 service binding instance. It will release all
|
||||
the resources allocated by the instance.
|
||||
|
||||
@param[in] Controller Controller handle of device to bind driver to.
|
||||
@param[in] ImageHandle The TCP driver's image handle.
|
||||
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number
|
||||
of children is zero stop the entire bus driver.
|
||||
@param[in] IpVersion IP_VERSION_4 or IP_VERSION_6
|
||||
|
||||
@retval EFI_SUCCESS The resources used by the instance were cleaned up.
|
||||
@retval Others Failed to clean up some of the resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpDestroyService (
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN UINT8 IpVersion
|
||||
)
|
||||
{
|
||||
EFI_HANDLE NicHandle;
|
||||
EFI_GUID *IpProtocolGuid;
|
||||
EFI_GUID *ServiceBindingGuid;
|
||||
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
||||
TCP_SERVICE_DATA *TcpServiceData;
|
||||
EFI_STATUS Status;
|
||||
SOCKET *Sock;
|
||||
|
||||
ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
|
||||
|
||||
if (IpVersion == IP_VERSION_4) {
|
||||
IpProtocolGuid = &gEfiIp4ProtocolGuid;
|
||||
ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
|
||||
} else {
|
||||
IpProtocolGuid = &gEfiIp6ProtocolGuid;
|
||||
ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
|
||||
}
|
||||
|
||||
NicHandle = NetLibGetNicHandle (Controller, IpProtocolGuid);
|
||||
if (NicHandle == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
NicHandle,
|
||||
ServiceBindingGuid,
|
||||
(VOID **) &ServiceBinding,
|
||||
ImageHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
TcpServiceData = TCP_SERVICE_FROM_THIS (ServiceBinding);
|
||||
|
||||
if (NumberOfChildren == 0) {
|
||||
//
|
||||
// Uninstall TCP servicebinding protocol
|
||||
//
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
NicHandle,
|
||||
ServiceBindingGuid,
|
||||
ServiceBinding,
|
||||
NULL
|
||||
);
|
||||
|
||||
//
|
||||
// Destroy the IpIO consumed by TCP driver
|
||||
//
|
||||
IpIoDestroy (TcpServiceData->IpIo);
|
||||
|
||||
//
|
||||
// Destroy the heartbeat timer.
|
||||
//
|
||||
TcpDestroyTimer ();
|
||||
|
||||
//
|
||||
// Clear the variable.
|
||||
//
|
||||
TcpClearVariableData (TcpServiceData);
|
||||
|
||||
//
|
||||
// Release the TCP service data
|
||||
//
|
||||
FreePool (TcpServiceData);
|
||||
} else {
|
||||
|
||||
while (!IsListEmpty (&TcpServiceData->SocketList)) {
|
||||
Sock = NET_LIST_HEAD (&TcpServiceData->SocketList, SOCKET, Link);
|
||||
|
||||
ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to test.
|
||||
@param[in] 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
|
||||
TcpDriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN IsTcp4Started;
|
||||
|
||||
//
|
||||
// Test for the Tcp4ServiceBinding Protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiTcp4ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Test for the Ip4ServiceBinding Protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiIp4ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
IsTcp4Started = FALSE;
|
||||
} else {
|
||||
IsTcp4Started = TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Check the Tcp6ServiceBinding Protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiTcp6ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Test for the Ip6ServiceBinding Protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiIp6ServiceBindingProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
ControllerHandle,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
} else if (IsTcp4Started) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to bind driver to.
|
||||
@param[in] 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
|
||||
TcpDriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Tcp4Status;
|
||||
EFI_STATUS Tcp6Status;
|
||||
|
||||
Tcp4Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4);
|
||||
if ((Tcp4Status == EFI_ALREADY_STARTED) || (Tcp4Status == EFI_UNSUPPORTED)) {
|
||||
Tcp4Status = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Tcp6Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6);
|
||||
if ((Tcp6Status == EFI_ALREADY_STARTED) || (Tcp6Status == EFI_UNSUPPORTED)) {
|
||||
Tcp6Status = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Tcp4Status) || !EFI_ERROR (Tcp6Status)) {
|
||||
return EFI_SUCCESS;
|
||||
} else if (EFI_ERROR (Tcp4Status)) {
|
||||
return Tcp4Status;
|
||||
} else {
|
||||
return Tcp6Status;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle.
|
||||
|
||||
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
||||
@param[in] ControllerHandle A handle to the device being stopped. The handle must
|
||||
support a bus specific I/O protocol for the driver
|
||||
to use to stop the device.
|
||||
@param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
|
||||
@param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
|
||||
if NumberOfChildren is 0.
|
||||
|
||||
@retval EFI_SUCCESS The device was stopped.
|
||||
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpDriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Tcp4Status;
|
||||
EFI_STATUS Tcp6Status;
|
||||
|
||||
Tcp4Status = TcpDestroyService (
|
||||
ControllerHandle,
|
||||
This->DriverBindingHandle,
|
||||
NumberOfChildren,
|
||||
IP_VERSION_4
|
||||
);
|
||||
|
||||
Tcp6Status = TcpDestroyService (
|
||||
ControllerHandle,
|
||||
This->DriverBindingHandle,
|
||||
NumberOfChildren,
|
||||
IP_VERSION_6
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Tcp4Status) && EFI_ERROR (Tcp6Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
} else {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
The Callback funtion called after the TCP socket was created.
|
||||
|
||||
@param[in] This Pointer to the socket just created
|
||||
@param[in] Context Context of the socket
|
||||
|
||||
@retval EFI_SUCCESS This protocol installed successfully.
|
||||
@retval other An error occured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpCreateSocketCallback (
|
||||
IN SOCKET *This,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
TCP_SERVICE_DATA *TcpServiceData;
|
||||
EFI_GUID *IpProtocolGuid;
|
||||
VOID *Ip;
|
||||
|
||||
if (This->IpVersion == IP_VERSION_4) {
|
||||
IpProtocolGuid = &gEfiIp4ProtocolGuid;
|
||||
} else {
|
||||
IpProtocolGuid = &gEfiIp6ProtocolGuid;
|
||||
}
|
||||
|
||||
TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService;
|
||||
|
||||
//
|
||||
// Open the default IP protocol of IP_IO BY_DRIVER.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
TcpServiceData->IpIo->ChildHandle,
|
||||
IpProtocolGuid,
|
||||
&Ip,
|
||||
TcpServiceData->DriverBindingHandle,
|
||||
This->SockHandle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Open the device path on the handle where service binding resides on.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
TcpServiceData->ControllerHandle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
(VOID **) &This->ParentDevicePath,
|
||||
TcpServiceData->DriverBindingHandle,
|
||||
This->SockHandle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->CloseProtocol (
|
||||
TcpServiceData->IpIo->ChildHandle,
|
||||
IpProtocolGuid,
|
||||
TcpServiceData->DriverBindingHandle,
|
||||
This->SockHandle
|
||||
);
|
||||
} else {
|
||||
//
|
||||
// Insert this socket into the SocketList.
|
||||
//
|
||||
InsertTailList (&TcpServiceData->SocketList, &This->Link);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
The callback function called before the TCP socket was to be destroyed.
|
||||
|
||||
@param[in] This The TCP socket to be destroyed.
|
||||
@param[in] Context The context of the socket.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpDestroySocketCallback (
|
||||
IN SOCKET *This,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
TCP_SERVICE_DATA *TcpServiceData;
|
||||
EFI_GUID *IpProtocolGuid;
|
||||
|
||||
if (This->IpVersion == IP_VERSION_4) {
|
||||
IpProtocolGuid = &gEfiIp4ProtocolGuid;
|
||||
} else {
|
||||
IpProtocolGuid = &gEfiIp6ProtocolGuid;
|
||||
}
|
||||
|
||||
TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService;
|
||||
|
||||
//
|
||||
// Remove this node from the list.
|
||||
//
|
||||
RemoveEntryList (&This->Link);
|
||||
|
||||
//
|
||||
// Close the device path protocol
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
TcpServiceData->ControllerHandle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
TcpServiceData->DriverBindingHandle,
|
||||
This->SockHandle
|
||||
);
|
||||
|
||||
//
|
||||
// Close the IP protocol.
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
TcpServiceData->IpIo->ChildHandle,
|
||||
IpProtocolGuid,
|
||||
TcpServiceData->DriverBindingHandle,
|
||||
This->SockHandle
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a child handle with a set of TCP services.
|
||||
|
||||
The CreateChild() function installs a protocol on ChildHandle.
|
||||
If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
|
||||
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
|
||||
|
||||
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
||||
@param[in, out] ChildHandle Pointer to the handle of the child to create.
|
||||
If it is NULL, then a new handle is created.
|
||||
If it is a pointer to an existing UEFI handle,
|
||||
then the protocol is added to the existing UEFI handle.
|
||||
|
||||
@retval EFI_SUCCES The protocol was added to ChildHandle.
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
|
||||
the child.
|
||||
@retval other The child handle was not created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN OUT EFI_HANDLE *ChildHandle
|
||||
)
|
||||
{
|
||||
SOCKET *Sock;
|
||||
TCP_SERVICE_DATA *TcpServiceData;
|
||||
TCP_PROTO_DATA TcpProto;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if (NULL == This || NULL == ChildHandle) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
TcpServiceData = TCP_SERVICE_FROM_THIS (This);
|
||||
TcpProto.TcpService = TcpServiceData;
|
||||
TcpProto.TcpPcb = NULL;
|
||||
|
||||
//
|
||||
// Create a tcp instance with defualt Tcp default
|
||||
// sock init data and TcpProto
|
||||
//
|
||||
mTcpDefaultSockData.ProtoData = &TcpProto;
|
||||
mTcpDefaultSockData.DataSize = sizeof (TCP_PROTO_DATA);
|
||||
mTcpDefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;
|
||||
mTcpDefaultSockData.IpVersion = TcpServiceData->IpVersion;
|
||||
|
||||
if (TcpServiceData->IpVersion == IP_VERSION_4) {
|
||||
mTcpDefaultSockData.Protocol = &gTcp4ProtocolTemplate;
|
||||
} else {
|
||||
mTcpDefaultSockData.Protocol = &gTcp6ProtocolTemplate;
|
||||
}
|
||||
|
||||
Sock = SockCreateChild (&mTcpDefaultSockData);
|
||||
if (NULL == Sock) {
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"TcpDriverBindingCreateChild: No resource to create a Tcp Child\n")
|
||||
);
|
||||
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
*ChildHandle = Sock->SockHandle;
|
||||
}
|
||||
|
||||
mTcpDefaultSockData.ProtoData = NULL;
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Destroys a child handle with a set of TCP services.
|
||||
|
||||
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
|
||||
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
|
||||
last protocol on ChildHandle, then ChildHandle is destroyed.
|
||||
|
||||
@param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
||||
@param ChildHandle Handle of the child to be destroyed.
|
||||
|
||||
@retval EFI_SUCCES The protocol was removed from ChildHandle.
|
||||
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
|
||||
@retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
|
||||
@retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
|
||||
because its services are being used.
|
||||
@retval other The child handle was not destroyed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VOID *Tcp;
|
||||
SOCKET *Sock;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if (NULL == This || NULL == ChildHandle) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
//
|
||||
// retrieve the Tcp4 protocol from ChildHandle
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiTcp4ProtocolGuid,
|
||||
&Tcp,
|
||||
gTcpDriverBinding.DriverBindingHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// No Tcp4, try the Tcp6 protocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiTcp6ProtocolGuid,
|
||||
&Tcp,
|
||||
gTcpDriverBinding.DriverBindingHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// destroy this sock and related Tcp protocol control
|
||||
// block
|
||||
//
|
||||
Sock = SOCK_FROM_THIS (Tcp);
|
||||
|
||||
SockDestroyChild (Sock);
|
||||
}
|
||||
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
230
NetworkPkg/TcpDxe/TcpDriver.h
Normal file
230
NetworkPkg/TcpDxe/TcpDriver.h
Normal file
@@ -0,0 +1,230 @@
|
||||
/** @file
|
||||
The prototype of driver binding and service binding protocol for TCP driver.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _TCP_DRIVER_H_
|
||||
#define _TCP_DRIVER_H_
|
||||
|
||||
#define TCP_DRIVER_SIGNATURE SIGNATURE_32 ('T', 'C', 'P', 'D')
|
||||
|
||||
#define TCP_PORT_KNOWN 1024
|
||||
#define TCP_PORT_USER_RESERVED 65535
|
||||
|
||||
typedef struct _TCP_HEARTBEAT_TIMER {
|
||||
EFI_EVENT TimerEvent;
|
||||
INTN RefCnt;
|
||||
} TCP_HEARTBEAT_TIMER;
|
||||
|
||||
typedef struct _TCP_SERVICE_DATA {
|
||||
UINT32 Signature;
|
||||
EFI_HANDLE ControllerHandle;
|
||||
EFI_HANDLE DriverBindingHandle;
|
||||
UINT8 IpVersion;
|
||||
IP_IO *IpIo;
|
||||
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
|
||||
CHAR16 *MacString;
|
||||
LIST_ENTRY SocketList;
|
||||
} TCP_SERVICE_DATA;
|
||||
|
||||
typedef struct _TCP_PROTO_DATA {
|
||||
TCP_SERVICE_DATA *TcpService;
|
||||
TCP_CB *TcpPcb;
|
||||
} TCP_PROTO_DATA;
|
||||
|
||||
#define TCP_SERVICE_FROM_THIS(a) \
|
||||
CR ( \
|
||||
(a), \
|
||||
TCP_SERVICE_DATA, \
|
||||
ServiceBinding, \
|
||||
TCP_DRIVER_SIGNATURE \
|
||||
)
|
||||
|
||||
//
|
||||
// Function prototype for the driver's entry point
|
||||
//
|
||||
|
||||
/**
|
||||
The entry point for Tcp driver, used to install Tcp driver on the ImageHandle.
|
||||
|
||||
@param[in] ImageHandle The firmware allocated handle for this driver image.
|
||||
@param[in] SystemTable Pointer to the EFI system table.
|
||||
|
||||
@retval EFI_SUCCESS The driver loaded.
|
||||
@retval other The driver did not load.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpDriverEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
//
|
||||
// Function prototypes for the Driver Binding Protocol
|
||||
//
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of the device to test.
|
||||
@param[in] 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
|
||||
TcpDriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle.
|
||||
|
||||
@param[in] This Protocol instance pointer.
|
||||
@param[in] ControllerHandle Handle of device to bind driver to.
|
||||
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
||||
device to start.
|
||||
|
||||
@retval EFI_SUCCESS The driver was 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
|
||||
TcpDriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle.
|
||||
|
||||
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
||||
@param[in] ControllerHandle A handle to the device being stopped. The handle must
|
||||
support a bus specific I/O protocol for the driver
|
||||
to use to stop the device.
|
||||
@param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
|
||||
@param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
|
||||
if NumberOfChildren is 0.
|
||||
|
||||
@retval EFI_SUCCESS The device was stopped.
|
||||
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpDriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
The Callback funtion called after the TCP socket is created.
|
||||
|
||||
@param[in] This Pointer to the socket just created.
|
||||
@param[in] Context The context of the socket.
|
||||
|
||||
@retval EFI_SUCCESS This protocol is installed successfully.
|
||||
@retval other An error occured.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpCreateSocketCallback (
|
||||
IN SOCKET *This,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
The callback function called before the TCP socket is to be destroyed.
|
||||
|
||||
@param[in] This The TCP socket to be destroyed.
|
||||
@param[in] Context The context of the socket.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpDestroySocketCallback (
|
||||
IN SOCKET *This,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
//
|
||||
// Function ptototypes for the ServiceBinding Prococol
|
||||
//
|
||||
|
||||
/**
|
||||
Creates a child handle with a set of TCP services.
|
||||
|
||||
The CreateChild() function installs a protocol on ChildHandle.
|
||||
If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
|
||||
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
|
||||
|
||||
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
||||
@param[in, out] ChildHandle Pointer to the handle of the child to create.
|
||||
If it is NULL, then a new handle is created.
|
||||
If it is a pointer to an existing UEFI handle,
|
||||
then the protocol is added to the existing UEFI handle.
|
||||
|
||||
@retval EFI_SUCCES The protocol was added to ChildHandle.
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
|
||||
the child.
|
||||
@retval other The child handle was not created.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpServiceBindingCreateChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN OUT EFI_HANDLE *ChildHandle
|
||||
);
|
||||
|
||||
/**
|
||||
Destroys a child handle with a set of TCP services.
|
||||
|
||||
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
|
||||
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
|
||||
last protocol on ChildHandle, then ChildHandle is destroyed.
|
||||
|
||||
@param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
||||
@param ChildHandle Handle of the child to destroy.
|
||||
|
||||
@retval EFI_SUCCES The protocol was removed from ChildHandle.
|
||||
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
|
||||
@retval EFI_INVALID_PARAMETER The child handle is not a valid UEFI Handle.
|
||||
@retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
|
||||
because its services are being used.
|
||||
@retval other The child handle was not destroyed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TcpServiceBindingDestroyChild (
|
||||
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE ChildHandle
|
||||
);
|
||||
|
||||
#endif
|
83
NetworkPkg/TcpDxe/TcpDxe.inf
Normal file
83
NetworkPkg/TcpDxe/TcpDxe.inf
Normal file
@@ -0,0 +1,83 @@
|
||||
## @file TcpDxe.inf
|
||||
# Component description file for Tcp module.
|
||||
#
|
||||
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# 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 = TcpDxe
|
||||
FILE_GUID = 1A7E4468-2F55-4a56-903C-01265EB7622B
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = TcpDriverEntryPoint
|
||||
UNLOAD_IMAGE = NetLibDefaultUnload
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources]
|
||||
TcpDriver.c
|
||||
SockImpl.c
|
||||
SockInterface.c
|
||||
TcpDispatcher.c
|
||||
TcpOutput.c
|
||||
TcpMain.c
|
||||
SockImpl.h
|
||||
TcpMisc.c
|
||||
TcpProto.h
|
||||
TcpOption.c
|
||||
TcpInput.c
|
||||
TcpFunc.h
|
||||
TcpOption.h
|
||||
TcpTimer.c
|
||||
TcpMain.h
|
||||
Socket.h
|
||||
ComponentName.c
|
||||
TcpIo.c
|
||||
TcpDriver.h
|
||||
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DevicePathLib
|
||||
DebugLib
|
||||
MemoryAllocationLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiRuntimeServicesTableLib
|
||||
DpcLib
|
||||
NetLib
|
||||
IpIoLib
|
||||
|
||||
|
||||
[Protocols]
|
||||
gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiIp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiIp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiTcp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiTcp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiIp6ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiIp6ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiTcp6ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiTcp6ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
|
724
NetworkPkg/TcpDxe/TcpFunc.h
Normal file
724
NetworkPkg/TcpDxe/TcpFunc.h
Normal file
@@ -0,0 +1,724 @@
|
||||
/** @file
|
||||
Declaration of external functions shared in TCP driver.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _TCP_FUNC_H_
|
||||
#define _TCP_FUNC_H_
|
||||
|
||||
#include "TcpOption.h"
|
||||
|
||||
#define TCP_COMP_VAL(Min, Max, Default, Val) \
|
||||
((((Val) <= (Max)) && ((Val) >= (Min))) ? (Val) : (Default))
|
||||
|
||||
/**
|
||||
Timeout handler prototype.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
typedef
|
||||
VOID
|
||||
(*TCP_TIMER_HANDLER) (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
//
|
||||
// Functions in TcpMisc.c
|
||||
//
|
||||
|
||||
/**
|
||||
Initialize the Tcb locally related members.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpInitTcbLocal (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize the peer related members.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] Seg Pointer to the segment that contains the peer's intial information.
|
||||
@param[in] Opt Pointer to the options announced by the peer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpInitTcbPeer (
|
||||
IN OUT TCP_CB *Tcb,
|
||||
IN TCP_SEG *Seg,
|
||||
IN TCP_OPTION *Opt
|
||||
);
|
||||
|
||||
/**
|
||||
Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
|
||||
|
||||
@param[in] Addr Pointer to the IP address needs to match.
|
||||
@param[in] Port The port number needs to match.
|
||||
@param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack.
|
||||
IP_VERSION_6 indicates TCP is running on IP6 stack.
|
||||
|
||||
|
||||
@retval TRUE The Tcb which matches the <Addr Port> pairs exists.
|
||||
@retval FALSE Otherwise
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
TcpFindTcbByPeer (
|
||||
IN EFI_IP_ADDRESS *Addr,
|
||||
IN TCP_PORTNO Port,
|
||||
IN UINT8 Version
|
||||
);
|
||||
|
||||
/**
|
||||
Locate the TCP_CB related to the socket pair.
|
||||
|
||||
@param[in] LocalPort The local port number.
|
||||
@param[in] LocalIp The local IP address.
|
||||
@param[in] RemotePort The remote port number.
|
||||
@param[in] RemoteIp The remote IP address.
|
||||
@param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
|
||||
IP_VERSION_6 indicates TCP is running on IP6 stack.
|
||||
@param[in] Syn If TRUE, the listen sockets are searched.
|
||||
|
||||
@return Pointer to the related TCP_CB. If NULL, no match is found.
|
||||
|
||||
**/
|
||||
TCP_CB *
|
||||
TcpLocateTcb (
|
||||
IN TCP_PORTNO LocalPort,
|
||||
IN EFI_IP_ADDRESS *LocalIp,
|
||||
IN TCP_PORTNO RemotePort,
|
||||
IN EFI_IP_ADDRESS *RemoteIp,
|
||||
IN UINT8 Version,
|
||||
IN BOOLEAN Syn
|
||||
);
|
||||
|
||||
/**
|
||||
Insert a Tcb into the proper queue.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB to be inserted.
|
||||
|
||||
@retval 0 The Tcb was inserted successfully.
|
||||
@retval -1 An error condition occurred.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpInsertTcb (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Clone a TCP_CB from Tcb.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB to be cloned.
|
||||
|
||||
@return Pointer to the new cloned TCP_CB. If NULL, an error condition occurred.
|
||||
|
||||
**/
|
||||
TCP_CB *
|
||||
TcpCloneTcb (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Compute an ISS to be used by a new connection.
|
||||
|
||||
@return The result ISS.
|
||||
|
||||
**/
|
||||
TCP_SEQNO
|
||||
TcpGetIss (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Get the local mss.
|
||||
|
||||
@param[in] Sock Pointer to the socket to get mss.
|
||||
|
||||
@return The mss size.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
TcpGetRcvMss (
|
||||
IN SOCKET *Sock
|
||||
);
|
||||
|
||||
/**
|
||||
Set the Tcb's state.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] State The state to be set.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpSetState (
|
||||
IN TCP_CB *Tcb,
|
||||
IN UINT8 State
|
||||
);
|
||||
|
||||
/**
|
||||
Compute the TCP segment's checksum.
|
||||
|
||||
@param[in] Nbuf Pointer to the buffer that contains the TCP segment.
|
||||
@param[in] HeadSum The checksum value of the fixed part of pseudo header.
|
||||
|
||||
@return The checksum value.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
TcpChecksum (
|
||||
IN NET_BUF *Nbuf,
|
||||
IN UINT16 HeadSum
|
||||
);
|
||||
|
||||
/**
|
||||
Translate the information from the head of the received TCP
|
||||
segment Nbuf contains, and fill it into a TCP_SEG structure.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in, out] Nbuf Pointer to the buffer contains the TCP segment.
|
||||
|
||||
@return Pointer to the TCP_SEG that contains the translated TCP head information.
|
||||
|
||||
**/
|
||||
TCP_SEG *
|
||||
TcpFormatNetbuf (
|
||||
IN TCP_CB *Tcb,
|
||||
IN OUT NET_BUF *Nbuf
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize an active connection,
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
|
||||
connection.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpOnAppConnect (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Application has consumed some data, check whether
|
||||
to send a window update ack or a delayed ack.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpOnAppConsume (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Initiate the connection close procedure, called when
|
||||
applications want to close the connection.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpOnAppClose (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Check whether the application's newly delivered data can be sent out.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@retval 0 The data has been sent out successfully.
|
||||
@retval -1 The Tcb is not in a state that data is permitted to
|
||||
be sent out.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpOnAppSend (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Abort the connection by sending a reset segment: called
|
||||
when the application wants to abort the connection.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of the TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpOnAppAbort (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Reset the connection related with Tcb.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of the connection to be reset.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpResetConnection (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Set the Tcp variable data.
|
||||
|
||||
@param[in] TcpService Tcp service data.
|
||||
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources to set the variable.
|
||||
@retval other Set variable failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpSetVariableData (
|
||||
IN TCP_SERVICE_DATA *TcpService
|
||||
);
|
||||
|
||||
/**
|
||||
Clear the variable and free the resource.
|
||||
|
||||
@param[in] TcpService Tcp service data.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpClearVariableData (
|
||||
IN TCP_SERVICE_DATA *TcpService
|
||||
);
|
||||
|
||||
/**
|
||||
Install the device path protocol on the TCP instance.
|
||||
|
||||
@param[in] Sock Pointer to the socket representing the TCP instance.
|
||||
|
||||
@retval EFI_SUCCESS The device path protocol installed.
|
||||
@retval other Failed to install the device path protocol.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpInstallDevicePath (
|
||||
IN SOCKET *Sock
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// Functions in TcpOutput.c
|
||||
//
|
||||
|
||||
/**
|
||||
Compute the sequence space left in the old receive window.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return The sequence space left in the old receive window.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
TcpRcvWinOld (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Compute the current receive window.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return The size of the current receive window, in bytes.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
TcpRcvWinNow (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Get the maximum SndNxt.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return The sequence number of the maximum SndNxt.
|
||||
|
||||
**/
|
||||
TCP_SEQNO
|
||||
TcpGetMaxSndNxt (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Compute how much data to send.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] Force If TRUE, ignore the sender's SWS avoidance algorithm
|
||||
and send out data by force.
|
||||
|
||||
@return The length of the data that can be sent. If 0, no data can be sent.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
TcpDataToSend (
|
||||
IN TCP_CB *Tcb,
|
||||
IN INTN Force
|
||||
);
|
||||
|
||||
/**
|
||||
Retransmit the segment from sequence Seq.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] Seq The sequence number of the segment to be retransmitted.
|
||||
|
||||
@retval 0 The retransmission succeeded.
|
||||
@retval -1 An error condition occurred.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpRetransmit (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP_SEQNO Seq
|
||||
);
|
||||
|
||||
/**
|
||||
Check whether to send data/SYN/FIN and piggyback an ACK.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] Force If TRUE, ignore the sender's SWS avoidance algorithm
|
||||
and send out data by force.
|
||||
|
||||
@return The number of bytes sent.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpToSendData (
|
||||
IN OUT TCP_CB *Tcb,
|
||||
IN INTN Force
|
||||
);
|
||||
|
||||
/**
|
||||
Check whether to send an ACK or delayed ACK.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpToSendAck (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Send an ACK immediately.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpSendAck (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Send a zero probe segment. It can be used by keepalive and zero window probe.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@retval 0 The zero probe segment was sent out successfully.
|
||||
@retval other An error condition occurred.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpSendZeroProbe (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Send a RESET segment in response to the segment received.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance, may be NULL.
|
||||
@param[in] Head TCP header of the segment that triggers the reset.
|
||||
@param[in] Len Length of the segment that triggers the reset.
|
||||
@param[in] Local Local IP address.
|
||||
@param[in] Remote Remote peer's IP address.
|
||||
@param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
|
||||
IP_VERSION_6 indicates TCP is running on IP6 stack.
|
||||
|
||||
@retval 0 A reset is sent or no need to send it.
|
||||
@retval -1 No reset is sent.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpSendReset (
|
||||
IN TCP_CB *Tcb,
|
||||
IN TCP_HEAD *Head,
|
||||
IN INT32 Len,
|
||||
IN EFI_IP_ADDRESS *Local,
|
||||
IN EFI_IP_ADDRESS *Remote,
|
||||
IN UINT8 Version
|
||||
);
|
||||
|
||||
/**
|
||||
Verify that the segment is in good shape.
|
||||
|
||||
@param[in] Nbuf Buffer that contains the segment to be checked.
|
||||
|
||||
@retval 0 The segment is broken.
|
||||
@retval 1 The segment is in good shape.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpVerifySegment (
|
||||
IN NET_BUF *Nbuf
|
||||
);
|
||||
|
||||
//
|
||||
// Functions from TcpInput.c
|
||||
//
|
||||
|
||||
/**
|
||||
Process the received ICMP error messages for TCP.
|
||||
|
||||
@param[in] Nbuf Buffer that contains part of the TCP segment without IP header
|
||||
truncated from the ICMP error packet.
|
||||
@param[in] IcmpErr The ICMP error code interpreted from an ICMP error packet.
|
||||
@param[in] Src Source address of the ICMP error message.
|
||||
@param[in] Dst Destination address of the ICMP error message.
|
||||
@param[in] Version IP_VERSION_4 indicates IP4 stack, IP_VERSION_6 indicates
|
||||
IP6 stack.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpIcmpInput (
|
||||
IN NET_BUF *Nbuf,
|
||||
IN UINT8 IcmpErr,
|
||||
IN EFI_IP_ADDRESS *Src,
|
||||
IN EFI_IP_ADDRESS *Dst,
|
||||
IN UINT8 Version
|
||||
);
|
||||
|
||||
/**
|
||||
Process the received TCP segments.
|
||||
|
||||
@param[in] Nbuf Buffer that contains received TCP segment without an IP header.
|
||||
@param[in] Src Source address of the segment, or the peer's IP address.
|
||||
@param[in] Dst Destination address of the segment, or the local end's IP
|
||||
address.
|
||||
@param[in] Version IP_VERSION_4 indicates IP4 stack, IP_VERSION_6 indicates
|
||||
IP6 stack.
|
||||
|
||||
@retval 0 The segment processed successfully. It is either accepted or
|
||||
discarded. But no connection is reset by the segment.
|
||||
@retval -1 A connection is reset by the segment.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpInput (
|
||||
IN NET_BUF *Nbuf,
|
||||
IN EFI_IP_ADDRESS *Src,
|
||||
IN EFI_IP_ADDRESS *Dst,
|
||||
IN UINT8 Version
|
||||
);
|
||||
|
||||
//
|
||||
// Functions in TcpTimer.c
|
||||
//
|
||||
|
||||
/**
|
||||
Close the TCP connection.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpClose (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Heart beat timer handler, queues the DPC at TPL_CALLBACK.
|
||||
|
||||
@param[in] Event Timer event signaled, ignored.
|
||||
@param[in] Context Context of the timer event, ignored.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TcpTicking (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Enable a TCP timer.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] Timer The index of the timer to be enabled.
|
||||
@param[in] TimeOut The timeout value of this timer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpSetTimer (
|
||||
IN OUT TCP_CB *Tcb,
|
||||
IN UINT16 Timer,
|
||||
IN UINT32 TimeOut
|
||||
);
|
||||
|
||||
/**
|
||||
Clear one TCP timer.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] Timer The index of the timer to be cleared.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpClearTimer (
|
||||
IN OUT TCP_CB *Tcb,
|
||||
IN UINT16 Timer
|
||||
);
|
||||
|
||||
/**
|
||||
Clear all TCP timers.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpClearAllTimer (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Enable the window prober timer and set the timeout value.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpSetProbeTimer (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Enable the keepalive timer and set the timeout value.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpSetKeepaliveTimer (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
//
|
||||
// Functions in TcpIo.c
|
||||
//
|
||||
|
||||
/**
|
||||
Packet receive callback function provided to IP_IO. Used to call
|
||||
the proper function to handle the packet received by IP.
|
||||
|
||||
@param[in] Status Result of the receive request.
|
||||
@param[in] IcmpErr Valid when Status is EFI_ICMP_ERROR.
|
||||
@param[in] NetSession The IP session for the received packet.
|
||||
@param[in] Pkt Packet received.
|
||||
@param[in] Context The data provided by the user for the received packet when
|
||||
the callback is registered in IP_IO_OPEN_DATA::RcvdContext.
|
||||
This is an optional parameter that may be NULL.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TcpRxCallback (
|
||||
IN EFI_STATUS Status,
|
||||
IN UINT8 IcmpErr,
|
||||
IN EFI_NET_SESSION_DATA *NetSession,
|
||||
IN NET_BUF *Pkt,
|
||||
IN VOID *Context OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Send the segment to IP via IpIo function.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] Nbuf Pointer to the TCP segment to be sent.
|
||||
@param[in] Src Source address of the TCP segment.
|
||||
@param[in] Dest Destination address of the TCP segment.
|
||||
@param[in] Version IP_VERSION_4 or IP_VERSION_6
|
||||
|
||||
@retval 0 The segment was sent out successfully.
|
||||
@retval -1 The segment failed to be sent.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpSendIpPacket (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Nbuf,
|
||||
IN EFI_IP_ADDRESS *Src,
|
||||
IN EFI_IP_ADDRESS *Dest,
|
||||
IN UINT8 Version
|
||||
);
|
||||
|
||||
/**
|
||||
Refresh the remote peer's Neighbor Cache State if already exists.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] Neighbor Source address of the TCP segment.
|
||||
@param[in] Timeout Time in 100-ns units that this entry will remain
|
||||
in the neighbor cache. A value of zero means that
|
||||
the entry is permanent. A value of non-zero means
|
||||
that the entry is dynamic and will be deleted
|
||||
after Timeout.
|
||||
|
||||
@retval EFI_SUCCESS Successfully updated the neighbor relationship.
|
||||
@retval EFI_NOT_STARTED The IpIo is not configured.
|
||||
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
|
||||
@retval EFI_NOT_FOUND This entry is not in the neighbor table.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tcp6RefreshNeighbor (
|
||||
IN TCP_CB *Tcb,
|
||||
IN EFI_IP_ADDRESS *Neighbor,
|
||||
IN UINT32 Timeout
|
||||
);
|
||||
|
||||
//
|
||||
// Functions in TcpDispatcher.c
|
||||
//
|
||||
|
||||
/**
|
||||
The procotol handler provided to the socket layer, used to
|
||||
dispatch the socket level requests by calling the corresponding
|
||||
TCP layer functions.
|
||||
|
||||
@param[in] Sock Pointer to the socket of this TCP instance.
|
||||
@param[in] Request The code of this operation request.
|
||||
@param[in] Data Pointer to the operation specific data passed in
|
||||
together with the operation request. This is an
|
||||
optional parameter that may be NULL.
|
||||
|
||||
@retval EFI_SUCCESS The socket request completed successfully.
|
||||
@retval other The error status returned by the corresponding TCP
|
||||
layer function.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
TcpDispatcher (
|
||||
IN SOCKET *Sock,
|
||||
IN UINT8 Request,
|
||||
IN VOID *Data OPTIONAL
|
||||
);
|
||||
|
||||
#endif
|
1592
NetworkPkg/TcpDxe/TcpInput.c
Normal file
1592
NetworkPkg/TcpDxe/TcpInput.c
Normal file
File diff suppressed because it is too large
Load Diff
190
NetworkPkg/TcpDxe/TcpIo.c
Normal file
190
NetworkPkg/TcpDxe/TcpIo.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/** @file
|
||||
Implementation of I/O interfaces between TCP and IpIoLib.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "TcpMain.h"
|
||||
|
||||
/**
|
||||
Packet receive callback function provided to IP_IO, used to call
|
||||
the proper function to handle the packet received by IP.
|
||||
|
||||
@param[in] Status Result of the receive request.
|
||||
@param[in] IcmpErr Valid when Status is EFI_ICMP_ERROR.
|
||||
@param[in] NetSession The IP session for the received packet.
|
||||
@param[in] Pkt Packet received.
|
||||
@param[in] Context The data provided by the user for the received packet when
|
||||
the callback is registered in IP_IO_OPEN_DATA::RcvdContext.
|
||||
This is an optional parameter that may be NULL.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TcpRxCallback (
|
||||
IN EFI_STATUS Status,
|
||||
IN UINT8 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, NetSession->IpVersion);
|
||||
} else {
|
||||
TcpIcmpInput (
|
||||
Pkt,
|
||||
IcmpErr,
|
||||
&NetSession->Source,
|
||||
&NetSession->Dest,
|
||||
NetSession->IpVersion
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Send the segment to IP via IpIo function.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] Nbuf Pointer to the TCP segment to be sent.
|
||||
@param[in] Src Source address of the TCP segment.
|
||||
@param[in] Dest Destination address of the TCP segment.
|
||||
@param[in] Version IP_VERSION_4 or IP_VERSION_6
|
||||
|
||||
@retval 0 The segment was sent out successfully.
|
||||
@retval -1 The segment failed to send.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpSendIpPacket (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Nbuf,
|
||||
IN EFI_IP_ADDRESS *Src,
|
||||
IN EFI_IP_ADDRESS *Dest,
|
||||
IN UINT8 Version
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IP_IO *IpIo;
|
||||
IP_IO_OVERRIDE Override;
|
||||
SOCKET *Sock;
|
||||
VOID *IpSender;
|
||||
TCP_PROTO_DATA *TcpProto;
|
||||
|
||||
if (NULL == Tcb) {
|
||||
|
||||
IpIo = NULL;
|
||||
IpSender = IpIoFindSender (&IpIo, Version, Src);
|
||||
|
||||
if (IpSender == NULL) {
|
||||
DEBUG ((EFI_D_WARN, "TcpSendIpPacket: No appropriate IpSender.\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (Version == IP_VERSION_6) {
|
||||
//
|
||||
// It's tricky here. EFI IPv6 Spec don't allow an instance overriding the
|
||||
// destination address if the dest is already specified through the
|
||||
// configuration data. Here we get the IpIo we need and use the default IP
|
||||
// instance in this IpIo to send the packet. The dest address is configured
|
||||
// to be the unspecified address for the default IP instance.
|
||||
//
|
||||
IpSender = NULL;
|
||||
}
|
||||
} else {
|
||||
|
||||
Sock = Tcb->Sk;
|
||||
TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved;
|
||||
IpIo = TcpProto->TcpService->IpIo;
|
||||
IpSender = Tcb->IpInfo;
|
||||
|
||||
if (Version == IP_VERSION_6) {
|
||||
//
|
||||
// It's IPv6 and this TCP segment belongs to a solid TCB, in such case
|
||||
// the destination address can't be overridden, so reset the Dest to NULL.
|
||||
//
|
||||
Dest = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT (Version == IpIo->IpVersion);
|
||||
|
||||
if (Version == IP_VERSION_4) {
|
||||
Override.Ip4OverrideData.TypeOfService = 0;
|
||||
Override.Ip4OverrideData.TimeToLive = 255;
|
||||
Override.Ip4OverrideData.DoNotFragment = FALSE;
|
||||
Override.Ip4OverrideData.Protocol = EFI_IP_PROTO_TCP;
|
||||
ZeroMem (&Override.Ip4OverrideData.GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
|
||||
CopyMem (&Override.Ip4OverrideData.SourceAddress, Src, sizeof (EFI_IPv4_ADDRESS));
|
||||
} else {
|
||||
Override.Ip6OverrideData.Protocol = EFI_IP_PROTO_TCP;
|
||||
Override.Ip6OverrideData.HopLimit = 255;
|
||||
Override.Ip6OverrideData.FlowLabel = 0;
|
||||
}
|
||||
|
||||
Status = IpIoSend (IpIo, Nbuf, IpSender, NULL, NULL, Dest, &Override);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "TcpSendIpPacket: return %r error\n", Status));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Refresh the remote peer's Neighbor Cache State if already exists.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] Neighbor Source address of the TCP segment.
|
||||
@param[in] Timeout Time in 100-ns units that this entry will remain
|
||||
in the neighbor cache. A value of zero means that
|
||||
the entry is permanent. A value of non-zero means
|
||||
that the entry is dynamic and will be deleted
|
||||
after Timeout.
|
||||
|
||||
@retval EFI_SUCCESS Successfully updated the neighbor relationship.
|
||||
@retval EFI_NOT_STARTED The IpIo is not configured.
|
||||
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
|
||||
@retval EFI_NOT_FOUND This entry is not in the neighbor table.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Tcp6RefreshNeighbor (
|
||||
IN TCP_CB *Tcb,
|
||||
IN EFI_IP_ADDRESS *Neighbor,
|
||||
IN UINT32 Timeout
|
||||
)
|
||||
{
|
||||
IP_IO *IpIo;
|
||||
SOCKET *Sock;
|
||||
TCP_PROTO_DATA *TcpProto;
|
||||
|
||||
if (NULL == Tcb) {
|
||||
IpIo = NULL;
|
||||
IpIoFindSender (&IpIo, IP_VERSION_6, Neighbor);
|
||||
|
||||
if (IpIo == NULL) {
|
||||
DEBUG ((EFI_D_WARN, "Tcp6AddNeighbor: No appropriate IpIo.\n"));
|
||||
return EFI_NOT_STARTED;
|
||||
}
|
||||
|
||||
} else {
|
||||
Sock = Tcb->Sk;
|
||||
TcpProto = (TCP_PROTO_DATA *) Sock->ProtoReserved;
|
||||
IpIo = TcpProto->TcpService->IpIo;
|
||||
}
|
||||
|
||||
return IpIoRefreshNeighbor (IpIo, Neighbor, Timeout);
|
||||
}
|
||||
|
1074
NetworkPkg/TcpDxe/TcpMain.c
Normal file
1074
NetworkPkg/TcpDxe/TcpMain.c
Normal file
File diff suppressed because it is too large
Load Diff
758
NetworkPkg/TcpDxe/TcpMain.h
Normal file
758
NetworkPkg/TcpDxe/TcpMain.h
Normal file
@@ -0,0 +1,758 @@
|
||||
/** @file
|
||||
Declaration of protocol interfaces in EFI_TCP4_PROTOCOL and EFI_TCP6_PROTOCOL.
|
||||
It is the common head file for all Tcp*.c in TCP driver.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _TCP_MAIN_H_
|
||||
#define _TCP_MAIN_H_
|
||||
|
||||
#include <Protocol/ServiceBinding.h>
|
||||
#include <Protocol/DriverBinding.h>
|
||||
#include <Library/IpIoLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
|
||||
#include "Socket.h"
|
||||
#include "TcpProto.h"
|
||||
#include "TcpDriver.h"
|
||||
#include "TcpFunc.h"
|
||||
|
||||
extern UINT16 mTcp4RandomPort;
|
||||
extern UINT16 mTcp6RandomPort;
|
||||
extern CHAR16 *mTcpStateName[];
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gTcpComponentName;
|
||||
extern EFI_COMPONENT_NAME2_PROTOCOL gTcpComponentName2;
|
||||
|
||||
extern LIST_ENTRY mTcpRunQue;
|
||||
extern LIST_ENTRY mTcpListenQue;
|
||||
extern TCP_SEQNO mTcpGlobalIss;
|
||||
extern UINT32 mTcpTick;
|
||||
|
||||
///
|
||||
/// 30 seconds.
|
||||
///
|
||||
#define TCP6_KEEP_NEIGHBOR_TIME 30
|
||||
///
|
||||
/// 5 seconds, since 1 tick equals 200ms.
|
||||
///
|
||||
#define TCP6_REFRESH_NEIGHBOR_TICK 25
|
||||
|
||||
#define TCP_EXPIRE_TIME 65535
|
||||
|
||||
///
|
||||
/// The implementation selects the initial send sequence number and the unit to
|
||||
/// be added when it is increased.
|
||||
///
|
||||
#define TCP_BASE_ISS 0x4d7e980b
|
||||
#define TCP_ISS_INCREMENT_1 2048
|
||||
#define TCP_ISS_INCREMENT_2 100
|
||||
|
||||
typedef union {
|
||||
EFI_TCP4_CONFIG_DATA Tcp4CfgData;
|
||||
EFI_TCP6_CONFIG_DATA Tcp6CfgData;
|
||||
} TCP_CONFIG_DATA;
|
||||
|
||||
typedef union {
|
||||
EFI_TCP4_ACCESS_POINT Tcp4Ap;
|
||||
EFI_TCP6_ACCESS_POINT Tcp6Ap;
|
||||
} TCP_ACCESS_POINT;
|
||||
|
||||
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 _TCP6_MODE_DATA {
|
||||
EFI_TCP6_CONNECTION_STATE *Tcp6State;
|
||||
EFI_TCP6_CONFIG_DATA *Tcp6ConfigData;
|
||||
EFI_IP6_MODE_DATA *Ip6ModeData;
|
||||
EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData;
|
||||
EFI_SIMPLE_NETWORK_MODE *SnpModeData;
|
||||
} TCP6_MODE_DATA;
|
||||
|
||||
typedef struct _TCP4_ROUTE_INFO {
|
||||
BOOLEAN DeleteRoute;
|
||||
EFI_IPv4_ADDRESS *SubnetAddress;
|
||||
EFI_IPv4_ADDRESS *SubnetMask;
|
||||
EFI_IPv4_ADDRESS *GatewayAddress;
|
||||
} TCP4_ROUTE_INFO;
|
||||
|
||||
//
|
||||
// EFI_TCP4_PROTOCOL definitions.
|
||||
//
|
||||
|
||||
/**
|
||||
Get the current operational status.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param[out] Tcp4State Pointer to the buffer to receive the current TCP
|
||||
state. Optional parameter that may be NULL.
|
||||
@param[out] Tcp4ConfigData Pointer to the buffer to receive the current TCP
|
||||
configuration. Optional parameter that may be NULL.
|
||||
@param[out] Ip4ModeData Pointer to the buffer to receive the current
|
||||
IPv4 configuration. Optional parameter that may be NULL.
|
||||
@param[out] MnpConfigData Pointer to the buffer to receive the current MNP
|
||||
configuration data indirectly used by the TCPv4
|
||||
Instance. Optional parameter that may be NULL.
|
||||
@param[out] SnpModeData Pointer to the buffer to receive the current SNP
|
||||
configuration data indirectly used by the TCPv4
|
||||
Instance. Optional parameter that may be NULL.
|
||||
|
||||
@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
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize or brutally reset the operational parameters for
|
||||
this EFI TCPv4 instance.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param[in] TcpConfigData Pointer to the configure data to configure the
|
||||
instance. Optional parameter that may be NULL.
|
||||
|
||||
@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 the 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
|
||||
);
|
||||
|
||||
/**
|
||||
Add or delete routing entries.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param[in] DeleteRoute If TRUE, delete the specified route from routing
|
||||
table; if FALSE, add the specified route to
|
||||
routing table.
|
||||
@param[in] SubnetAddress The destination network.
|
||||
@param[in] SubnetMask The subnet mask for the destination network.
|
||||
@param[in] 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
|
||||
);
|
||||
|
||||
/**
|
||||
Initiate a nonblocking TCP connection request for an active TCP instance.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param[in] 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 resources 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
|
||||
);
|
||||
|
||||
/**
|
||||
Listen on the passive instance to accept an incoming connection request.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param[in] 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
|
||||
);
|
||||
|
||||
/**
|
||||
Queues outgoing data into the transmit queue
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP4_PROTOCOL instance
|
||||
@param[in] 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 a
|
||||
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
|
||||
);
|
||||
|
||||
/**
|
||||
Place an asynchronous receive request into the receiving queue.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param[in] 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 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
|
||||
);
|
||||
|
||||
/**
|
||||
Disconnecting a TCP connection gracefully or reset a TCP connection.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param[in] 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 resources to finish the
|
||||
operation.
|
||||
@retval EFI_DEVICE_ERROR Any unexpected error not belonging to the error
|
||||
categories given above.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Close (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN EFI_TCP4_CLOSE_TOKEN *CloseToken
|
||||
);
|
||||
|
||||
/**
|
||||
Abort an asynchronous connection, listen, transmission or receive request.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP4_PROTOCOL instance.
|
||||
@param[in] Token Pointer to a token that has been issued by
|
||||
Connect(), Accept(), Transmit() or Receive(). If
|
||||
NULL, all pending tokens issued by the above four
|
||||
functions will be aborted.
|
||||
|
||||
@retval EFI_UNSUPPORTED The operation is not supported in the current
|
||||
implementation.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp4Cancel (
|
||||
IN EFI_TCP4_PROTOCOL *This,
|
||||
IN EFI_TCP4_COMPLETION_TOKEN *Token OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Poll to receive incoming data and transmit outgoing segments.
|
||||
|
||||
@param[in] 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
|
||||
);
|
||||
|
||||
//
|
||||
// EFI_TCP6_PROTOCOL definitions.
|
||||
//
|
||||
|
||||
/**
|
||||
Get the current operational status.
|
||||
|
||||
The GetModeData() function copies the current operational settings of this EFI TCPv6
|
||||
Protocol instance into user-supplied buffers. This function can also be used to retrieve
|
||||
the operational setting of underlying drivers such as IPv6, MNP, or SNP.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
|
||||
@param[out] Tcp6State The buffer in which the current TCP state is
|
||||
returned. Optional parameter that may be NULL.
|
||||
@param[out] Tcp6ConfigData The buffer in which the current TCP configuration
|
||||
is returned. Optional parameter that may be NULL.
|
||||
@param[out] Ip6ModeData The buffer in which the current IPv6 configuration
|
||||
data used by the TCP instance is returned.
|
||||
Optional parameter that may be NULL.
|
||||
@param[out] MnpConfigData The buffer in which the current MNP configuration
|
||||
data used indirectly by the TCP instance is returned.
|
||||
Optional parameter that may be NULL.
|
||||
@param[out] SnpModeData The buffer in which the current SNP mode data
|
||||
used indirectly by the TCP instance is returned.
|
||||
Optional parameter that may be NULL.
|
||||
|
||||
@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
|
||||
Tcp6GetModeData (
|
||||
IN EFI_TCP6_PROTOCOL *This,
|
||||
OUT EFI_TCP6_CONNECTION_STATE *Tcp6State OPTIONAL,
|
||||
OUT EFI_TCP6_CONFIG_DATA *Tcp6ConfigData OPTIONAL,
|
||||
OUT EFI_IP6_MODE_DATA *Ip6ModeData OPTIONAL,
|
||||
OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
|
||||
OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize or brutally reset the operational parameters for this EFI TCPv6 instance.
|
||||
|
||||
The Configure() function does the following:
|
||||
- Initialize this TCP instance, i.e., initialize the communication end settings and
|
||||
specify active open or passive open for an instance.
|
||||
- Reset this TCP instance brutally, i.e., cancel all pending asynchronous tokens, flush
|
||||
transmission and receiving buffer directly without informing the communication peer.
|
||||
|
||||
No other TCPv6 Protocol operation except Poll() can be executed by this instance until
|
||||
it is configured properly. For an active TCP instance, after a proper configuration it
|
||||
may call Connect() to initiates the three-way handshake. For a passive TCP instance,
|
||||
its state will transit to Tcp6StateListen after configuration, and Accept() may be
|
||||
called to listen the incoming TCP connection requests. If Tcp6ConfigData is set to NULL,
|
||||
the instance is reset. Resetting process will be done brutally, the state machine will
|
||||
be set to Tcp6StateClosed directly, the receive queue and transmit queue will be flushed,
|
||||
and no traffic is allowed through this instance.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
|
||||
@param[in] Tcp6ConfigData Pointer to the configure data to configure the instance.
|
||||
If Tcp6ConfigData is set to NULL, the instance is reset.
|
||||
|
||||
@retval EFI_SUCCESS The operational settings were set, changed, or reset
|
||||
successfully.
|
||||
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
|
||||
address for this instance, but no source address was available for
|
||||
use.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions are TRUE:
|
||||
- This is NULL.
|
||||
- Tcp6ConfigData->AccessPoint.StationAddress is neither zero nor
|
||||
one of the configured IP addresses in the underlying IPv6 driver.
|
||||
- Tcp6ConfigData->AccessPoint.RemoteAddress isn't a valid unicast
|
||||
IPv6 address.
|
||||
- Tcp6ConfigData->AccessPoint.RemoteAddress is zero or
|
||||
Tcp6ConfigData->AccessPoint.RemotePort is zero when
|
||||
Tcp6ConfigData->AccessPoint.ActiveFlag is TRUE.
|
||||
- A same access point has been configured in other TCP
|
||||
instance properly.
|
||||
@retval EFI_ACCESS_DENIED Configuring TCP instance when it is configured without
|
||||
calling Configure() with NULL to reset it.
|
||||
@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 when
|
||||
executing Configure().
|
||||
@retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp6Configure (
|
||||
IN EFI_TCP6_PROTOCOL *This,
|
||||
IN EFI_TCP6_CONFIG_DATA *Tcp6ConfigData OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Initiate a nonblocking TCP connection request for an active TCP instance.
|
||||
|
||||
The Connect() function will initiate an active open to the remote peer configured
|
||||
in current TCP instance if it is configured active. If the connection succeeds or
|
||||
fails due to an error, the ConnectionToken->CompletionToken.Event will be signaled,
|
||||
and ConnectionToken->CompletionToken.Status will be updated accordingly. This
|
||||
function can only be called for the TCP instance in Tcp6StateClosed state. The
|
||||
instance will transfer into Tcp6StateSynSent if the function returns EFI_SUCCESS.
|
||||
If TCP three-way handshake succeeds, its state will become Tcp6StateEstablished;
|
||||
otherwise, the state will return to Tcp6StateClosed.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
|
||||
@param[in] ConnectionToken Pointer to the connection token to return when the TCP
|
||||
three-way handshake finishes.
|
||||
|
||||
@retval EFI_SUCCESS The connection request successfully initiated and the state of
|
||||
this TCP instance has been changed to Tcp6StateSynSent.
|
||||
@retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured.
|
||||
@retval EFI_ACCESS_DENIED One or more of the following conditions are TRUE:
|
||||
- This instance is not configured as an active instance.
|
||||
- This instance is not in Tcp6StateClosed state.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
|
||||
- This is NULL.
|
||||
- ConnectionToken is NULL.
|
||||
- ConnectionToken->CompletionToken.Event is NULL.
|
||||
@retval EFI_OUT_OF_RESOURCES The driver can't allocate enough resources to initiate the active open.
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp6Connect (
|
||||
IN EFI_TCP6_PROTOCOL *This,
|
||||
IN EFI_TCP6_CONNECTION_TOKEN *ConnectionToken
|
||||
);
|
||||
|
||||
/**
|
||||
Listen on the passive instance to accept an incoming connection request. This is a
|
||||
nonblocking operation.
|
||||
|
||||
The Accept() function initiates an asynchronous accept request to wait for an incoming
|
||||
connection on the passive TCP instance. If a remote peer successfully establishes a
|
||||
connection with this instance, a new TCP instance will be created and its handle will
|
||||
be returned in ListenToken->NewChildHandle. The newly created instance is configured
|
||||
by inheriting the passive instance's configuration, and is ready for use upon return.
|
||||
The new instance is in the Tcp6StateEstablished state.
|
||||
|
||||
The ListenToken->CompletionToken.Event will be signaled when a new connection is
|
||||
accepted, user aborts the listen or connection is reset.
|
||||
|
||||
This function only can be called when the current TCP instance is in Tcp6StateListen state.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
|
||||
@param[in] ListenToken Pointer to the listen token to return when the operation finishes.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The listen token was been queued successfully.
|
||||
@retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured.
|
||||
@retval EFI_ACCESS_DENIED One or more of the following are TRUE:
|
||||
- This instance is not a passive instance.
|
||||
- This instance is not in Tcp6StateListen state.
|
||||
- The same listen token has already existed in the listen
|
||||
token queue of this TCP instance.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
|
||||
- This is NULL.
|
||||
- ListenToken is NULL.
|
||||
- ListentToken->CompletionToken.Event is NULL.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to finish the operation.
|
||||
@retval EFI_DEVICE_ERROR Any unexpected error not belonging to the error
|
||||
categories given above.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp6Accept (
|
||||
IN EFI_TCP6_PROTOCOL *This,
|
||||
IN EFI_TCP6_LISTEN_TOKEN *ListenToken
|
||||
);
|
||||
|
||||
/**
|
||||
Queues outgoing data into the transmit queue.
|
||||
|
||||
The Transmit() function queues a sending request to this TCP instance along with the
|
||||
user data. The status of the token is updated and the event in the token will be
|
||||
signaled once the data is sent out or some error occurs.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
|
||||
@param[in] 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 This EFI TCPv6 Protocol instance has not been configured.
|
||||
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a
|
||||
source address for this instance, but no source address was
|
||||
available for use.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
|
||||
- This is NULL.
|
||||
- Token is NULL.
|
||||
- Token->CompletionToken.Event is NULL.
|
||||
- Token->Packet.TxData is NULL.
|
||||
- Token->Packet.FragmentCount is zero.
|
||||
- Token->Packet.DataLength is not equal to the sum of fragment lengths.
|
||||
@retval EFI_ACCESS_DENIED One or more of the following conditions are TRUE:
|
||||
- A transmit completion token with the same Token->
|
||||
CompletionToken.Event was already in the
|
||||
transmission queue.
|
||||
- The current instance is in Tcp6StateClosed state.
|
||||
- The current instance is a passive one and it is in
|
||||
Tcp6StateListen 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 a resource
|
||||
shortage.
|
||||
@retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or address.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp6Transmit (
|
||||
IN EFI_TCP6_PROTOCOL *This,
|
||||
IN EFI_TCP6_IO_TOKEN *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Places an asynchronous receive request into the receiving queue.
|
||||
|
||||
The Receive() function places a completion token into the receive packet queue. This
|
||||
function is always asynchronous. The caller must allocate the Token->CompletionToken.Event
|
||||
and the FragmentBuffer used to receive data. The caller also must fill the DataLength, which
|
||||
represents the whole length of all FragmentBuffer. When the receive operation completes, the
|
||||
EFI TCPv6 Protocol driver updates the Token->CompletionToken.Status and Token->Packet.RxData
|
||||
fields, and the Token->CompletionToken.Event is signaled. If data is obtained, the data and its length
|
||||
will be copied into the FragmentTable. At the same time the full length of received data will
|
||||
be recorded in the DataLength fields. Providing a proper notification function and context
|
||||
for the event enables the user to receive the notification and receiving status. That
|
||||
notification function is guaranteed to not be re-entered.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
|
||||
@param[in] 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 This EFI TCPv6 Protocol instance has not been configured.
|
||||
@retval EFI_NO_MAPPING The underlying IPv6 driver was responsible for choosing a source
|
||||
address for this instance, but no source address was available for use.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
- This is NULL.
|
||||
- Token is NULL.
|
||||
- Token->CompletionToken.Event is NULL.
|
||||
- Token->Packet.RxData is NULL.
|
||||
- Token->Packet.RxData->DataLength is 0.
|
||||
- The Token->Packet.RxData->DataLength is not the
|
||||
sum of all FragmentBuffer length in FragmentTable.
|
||||
@retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of
|
||||
system resources (usually memory).
|
||||
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
|
||||
The EFI TCPv6 Protocol instance has been reset to startup defaults.
|
||||
@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 Tcp6StateClosed state.
|
||||
- The current instance is a passive one and it is in
|
||||
Tcp6StateListen state.
|
||||
- The user has called Close() to disconnect this connection.
|
||||
@retval EFI_CONNECTION_FIN The communication peer has closed the connection, and there is no
|
||||
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
|
||||
Tcp6Receive (
|
||||
IN EFI_TCP6_PROTOCOL *This,
|
||||
IN EFI_TCP6_IO_TOKEN *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Disconnecting a TCP connection gracefully or reset a TCP connection. This function is a
|
||||
nonblocking operation.
|
||||
|
||||
Initiate an asynchronous close token to the TCP driver. After Close() is called, any buffered
|
||||
transmission data will be sent by the TCP driver, and the current instance will have a graceful close
|
||||
working flow described as RFC 793 if AbortOnClose is set to FALSE, otherwise, a rest packet
|
||||
will be sent by TCP driver to fast disconnect this connection. When the close operation completes
|
||||
successfully the TCP instance is in Tcp6StateClosed state, all pending asynchronous
|
||||
operations are signaled, and any buffers used for TCP network traffic are flushed.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
|
||||
@param[in] CloseToken Pointer to the close token to return when operation finishes.
|
||||
|
||||
@retval EFI_SUCCESS The Close() was called successfully.
|
||||
@retval EFI_NOT_STARTED This EFI TCPv6 Protocol instance has not been configured.
|
||||
@retval EFI_ACCESS_DENIED One or more of the following are TRUE:
|
||||
- CloseToken or CloseToken->CompletionToken.Event is already in use.
|
||||
- Previous Close() call on this instance has not finished.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
|
||||
- This is NULL.
|
||||
- CloseToken is NULL.
|
||||
- CloseToken->CompletionToken.Event is NULL.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to finish the operation.
|
||||
@retval EFI_DEVICE_ERROR Any unexpected error not belonging to the error categories given above.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp6Close (
|
||||
IN EFI_TCP6_PROTOCOL *This,
|
||||
IN EFI_TCP6_CLOSE_TOKEN *CloseToken
|
||||
);
|
||||
|
||||
/**
|
||||
Abort an asynchronous connection, listen, transmission or receive request.
|
||||
|
||||
The Cancel() function aborts a pending connection, listen, transmit or
|
||||
receive request.
|
||||
|
||||
If Token is not NULL and the token is in the connection, listen, transmission
|
||||
or receive queue when it is being cancelled, its Token->Status will be set
|
||||
to EFI_ABORTED and then Token->Event will be signaled.
|
||||
|
||||
If the token is not in one of the queues, which usually means that the
|
||||
asynchronous operation has completed, EFI_NOT_FOUND is returned.
|
||||
|
||||
If Token is NULL all asynchronous token issued by Connect(), Accept(),
|
||||
Transmit() and Receive() will be aborted.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP6_PROTOCOL instance.
|
||||
@param[in] Token Pointer to a token that has been issued by
|
||||
EFI_TCP6_PROTOCOL.Connect(),
|
||||
EFI_TCP6_PROTOCOL.Accept(),
|
||||
EFI_TCP6_PROTOCOL.Transmit() or
|
||||
EFI_TCP6_PROTOCOL.Receive(). If NULL, all pending
|
||||
tokens issued by above four functions will be aborted. Type
|
||||
EFI_TCP6_COMPLETION_TOKEN is defined in
|
||||
EFI_TCP_PROTOCOL.Connect().
|
||||
|
||||
@retval EFI_UNSUPPORTED The implementation does not support this function.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp6Cancel (
|
||||
IN EFI_TCP6_PROTOCOL *This,
|
||||
IN EFI_TCP6_COMPLETION_TOKEN *Token OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Poll to receive incoming data and transmit outgoing segments.
|
||||
|
||||
The Poll() function increases the rate that data is moved between the network
|
||||
and application and can be called when the TCP instance is created successfully.
|
||||
Its use is optional.
|
||||
|
||||
@param[in] This Pointer to the EFI_TCP6_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 is processed.
|
||||
@retval EFI_TIMEOUT Data was dropped out of the transmission or receive queue.
|
||||
Consider increasing the polling rate.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
Tcp6Poll (
|
||||
IN EFI_TCP6_PROTOCOL *This
|
||||
);
|
||||
|
||||
#endif
|
1281
NetworkPkg/TcpDxe/TcpMisc.c
Normal file
1281
NetworkPkg/TcpDxe/TcpMisc.c
Normal file
File diff suppressed because it is too large
Load Diff
374
NetworkPkg/TcpDxe/TcpOption.c
Normal file
374
NetworkPkg/TcpDxe/TcpOption.c
Normal file
@@ -0,0 +1,374 @@
|
||||
/** @file
|
||||
Routines to process TCP option.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "TcpMain.h"
|
||||
|
||||
/**
|
||||
Get a UINT16 value from buffer.
|
||||
|
||||
@param[in] Buf Pointer to input buffer.
|
||||
|
||||
@return The UINT16 value obtained from the buffer.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
TcpGetUint16 (
|
||||
IN UINT8 *Buf
|
||||
)
|
||||
{
|
||||
UINT16 Value;
|
||||
CopyMem (&Value, Buf, sizeof (UINT16));
|
||||
return NTOHS (Value);
|
||||
}
|
||||
|
||||
/**
|
||||
Get a UINT32 value from buffer.
|
||||
|
||||
@param[in] Buf Pointer to input buffer.
|
||||
|
||||
@return The UINT32 value obtained from the buffer.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
TcpGetUint32 (
|
||||
IN UINT8 *Buf
|
||||
)
|
||||
{
|
||||
UINT32 Value;
|
||||
CopyMem (&Value, Buf, sizeof (UINT32));
|
||||
return NTOHL (Value);
|
||||
}
|
||||
|
||||
/**
|
||||
Put a UINT32 value in buffer.
|
||||
|
||||
@param[out] Buf Pointer to the buffer.
|
||||
@param[in] Data The UINT32 Date to put in the buffer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpPutUint32 (
|
||||
OUT UINT8 *Buf,
|
||||
IN UINT32 Data
|
||||
)
|
||||
{
|
||||
Data = HTONL (Data);
|
||||
CopyMem (Buf, &Data, sizeof (UINT32));
|
||||
}
|
||||
|
||||
/**
|
||||
Compute the window scale value according to the given buffer size.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return The scale value.
|
||||
|
||||
**/
|
||||
UINT8
|
||||
TcpComputeScale (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
UINT8 Scale;
|
||||
UINT32 BufSize;
|
||||
|
||||
ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
|
||||
|
||||
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[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] 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
|
||||
)
|
||||
{
|
||||
UINT8 *Data;
|
||||
UINT16 Len;
|
||||
|
||||
ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));
|
||||
|
||||
Len = 0;
|
||||
|
||||
//
|
||||
// Add a timestamp option if not disabled by the 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 != NULL);
|
||||
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 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 != NULL);
|
||||
|
||||
Len += TCP_OPTION_WS_ALIGNED_LEN;
|
||||
TcpPutUint32 (Data, TCP_OPTION_WS_FAST | TcpComputeScale (Tcb));
|
||||
}
|
||||
|
||||
//
|
||||
// Build the MSS option.
|
||||
//
|
||||
Data = NetbufAllocSpace (Nbuf, TCP_OPTION_MSS_LEN, 1);
|
||||
ASSERT (Data != NULL);
|
||||
|
||||
Len += TCP_OPTION_MSS_LEN;
|
||||
TcpPutUint32 (Data, TCP_OPTION_MSS_FAST | Tcb->RcvMss);
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
/**
|
||||
Build the TCP option in synchronized states.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] 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
|
||||
)
|
||||
{
|
||||
UINT8 *Data;
|
||||
UINT16 Len;
|
||||
|
||||
ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));
|
||||
Len = 0;
|
||||
|
||||
//
|
||||
// Build the 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 != NULL);
|
||||
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[in] Tcp Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in, out] 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 OUT TCP_OPTION *Option
|
||||
)
|
||||
{
|
||||
UINT8 *Head;
|
||||
UINT8 TotalLen;
|
||||
UINT8 Cur;
|
||||
UINT8 Type;
|
||||
UINT8 Len;
|
||||
|
||||
ASSERT ((Tcp != NULL) && (Option != NULL));
|
||||
|
||||
Option->Flag = 0;
|
||||
|
||||
TotalLen = (UINT8) ((Tcp->HeadLen << 2) - sizeof (TCP_HEAD));
|
||||
if (TotalLen <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Head = (UINT8 *) (Tcp + 1);
|
||||
|
||||
//
|
||||
// Fast process of the 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 = (UINT8) 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 = (UINT8) (Cur + Len);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Check the segment against PAWS.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] 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;
|
||||
}
|
145
NetworkPkg/TcpDxe/TcpOption.h
Normal file
145
NetworkPkg/TcpDxe/TcpOption.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/** @file
|
||||
Tcp option's routine header file.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _TCP_OPTION_H_
|
||||
#define _TCP_OPTION_H_
|
||||
|
||||
//
|
||||
// Supported TCP option types and their length.
|
||||
//
|
||||
#define TCP_OPTION_EOP 0 ///< End Of oPtion
|
||||
#define TCP_OPTION_NOP 1 ///< No-Option.
|
||||
#define TCP_OPTION_MSS 2 ///< Maximum Segment Size
|
||||
#define TCP_OPTION_WS 3 ///< Window scale
|
||||
#define TCP_OPTION_TS 8 ///< Timestamp
|
||||
#define TCP_OPTION_MSS_LEN 4 ///< Length of MSS option
|
||||
#define TCP_OPTION_WS_LEN 3 ///< Length of window scale option
|
||||
#define TCP_OPTION_TS_LEN 10 ///< Length of timestamp option
|
||||
#define TCP_OPTION_WS_ALIGNED_LEN 4 ///< Length of window scale option, aligned
|
||||
#define TCP_OPTION_TS_ALIGNED_LEN 12 ///< Length of timestamp option, aligned
|
||||
|
||||
//
|
||||
// recommend format of timestamp window scale
|
||||
// option for fast process.
|
||||
//
|
||||
#define TCP_OPTION_TS_FAST ((TCP_OPTION_NOP << 24) | \
|
||||
(TCP_OPTION_NOP << 16) | \
|
||||
(TCP_OPTION_TS << 8) | \
|
||||
(TCP_OPTION_TS_LEN))
|
||||
|
||||
#define TCP_OPTION_WS_FAST ((TCP_OPTION_NOP << 24) | \
|
||||
(TCP_OPTION_WS << 16) | \
|
||||
(TCP_OPTION_WS_LEN << 8))
|
||||
|
||||
#define TCP_OPTION_MSS_FAST ((TCP_OPTION_MSS << 24) | (TCP_OPTION_MSS_LEN << 16))
|
||||
|
||||
//
|
||||
// Other misc definations
|
||||
//
|
||||
#define TCP_OPTION_RCVD_MSS 0x01
|
||||
#define TCP_OPTION_RCVD_WS 0x02
|
||||
#define TCP_OPTION_RCVD_TS 0x04
|
||||
#define TCP_OPTION_MAX_WS 14 ///< Maxium window scale value
|
||||
#define TCP_OPTION_MAX_WIN 0xffff ///< Max window size in TCP header
|
||||
|
||||
///
|
||||
/// The structure to store the parse option value.
|
||||
/// ParseOption only parses the options, doesn't process them.
|
||||
///
|
||||
typedef struct _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;
|
||||
|
||||
/**
|
||||
Compute the window scale value according to the given buffer size.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@return The scale value.
|
||||
|
||||
**/
|
||||
UINT8
|
||||
TcpComputeScale (
|
||||
IN TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Build the TCP option in three-way handshake.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] 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
|
||||
);
|
||||
|
||||
/**
|
||||
Build the TCP option in synchronized states.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] 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
|
||||
);
|
||||
|
||||
/**
|
||||
Parse the supported options.
|
||||
|
||||
@param[in] Tcp Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in, out] Option Pointer to the TCP_OPTION used to store the
|
||||
successfully pasrsed options.
|
||||
|
||||
@retval 0 The options successfully pasrsed.
|
||||
@retval -1 Ilegal option was found.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpParseOption (
|
||||
IN TCP_HEAD *Tcp,
|
||||
IN OUT TCP_OPTION *Option
|
||||
);
|
||||
|
||||
/**
|
||||
Check the segment against PAWS.
|
||||
|
||||
@param[in] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] 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
|
||||
);
|
||||
|
||||
#endif
|
1219
NetworkPkg/TcpDxe/TcpOutput.c
Normal file
1219
NetworkPkg/TcpDxe/TcpOutput.c
Normal file
File diff suppressed because it is too large
Load Diff
342
NetworkPkg/TcpDxe/TcpProto.h
Normal file
342
NetworkPkg/TcpDxe/TcpProto.h
Normal file
@@ -0,0 +1,342 @@
|
||||
/** @file
|
||||
TCP protocol header file.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _TCP_PROTO_H_
|
||||
#define _TCP_PROTO_H_
|
||||
|
||||
///
|
||||
/// Tcp states don't change their order. It is used as an
|
||||
/// index to mTcpOutFlag and other macros.
|
||||
///
|
||||
#define TCP_CLOSED 0
|
||||
#define TCP_LISTEN 1
|
||||
#define TCP_SYN_SENT 2
|
||||
#define TCP_SYN_RCVD 3
|
||||
#define TCP_ESTABLISHED 4
|
||||
#define TCP_FIN_WAIT_1 5
|
||||
#define TCP_FIN_WAIT_2 6
|
||||
#define TCP_CLOSING 7
|
||||
#define TCP_TIME_WAIT 8
|
||||
#define TCP_CLOSE_WAIT 9
|
||||
#define TCP_LAST_ACK 10
|
||||
|
||||
|
||||
///
|
||||
/// Flags in the TCP header
|
||||
///
|
||||
#define TCP_FLG_FIN 0x01
|
||||
#define TCP_FLG_SYN 0x02
|
||||
#define TCP_FLG_RST 0x04
|
||||
#define TCP_FLG_PSH 0x08
|
||||
#define TCP_FLG_ACK 0x10
|
||||
#define TCP_FLG_URG 0x20
|
||||
|
||||
//
|
||||
// mask for all the flags
|
||||
//
|
||||
#define TCP_FLG_FLAG 0x3F
|
||||
|
||||
|
||||
#define TCP_CONNECT_REFUSED (-1) ///< TCP error status
|
||||
#define TCP_CONNECT_RESET (-2) ///< TCP error status
|
||||
#define TCP_CONNECT_CLOSED (-3) ///< TCP error status
|
||||
|
||||
//
|
||||
// Current congestion status as suggested by RFC3782.
|
||||
//
|
||||
#define TCP_CONGEST_RECOVER 1 ///< During the NewReno fast recovery.
|
||||
#define TCP_CONGEST_LOSS 2 ///< Retxmit because of retxmit time out.
|
||||
#define TCP_CONGEST_OPEN 3 ///< TCP is opening its congestion window.
|
||||
|
||||
//
|
||||
// TCP control flags
|
||||
//
|
||||
#define TCP_CTRL_NO_NAGLE 0x0001 ///< Disable Nagle algorithm
|
||||
#define TCP_CTRL_NO_KEEPALIVE 0x0002 ///< Disable keepalive timer.
|
||||
#define TCP_CTRL_NO_WS 0x0004 ///< Disable window scale option.
|
||||
#define TCP_CTRL_RCVD_WS 0x0008 ///< Received a wnd scale option in syn.
|
||||
#define TCP_CTRL_NO_TS 0x0010 ///< Disable Timestamp option.
|
||||
#define TCP_CTRL_RCVD_TS 0x0020 ///< Received a Timestamp option in syn.
|
||||
#define TCP_CTRL_SND_TS 0x0040 ///< Send Timestamp option to remote.
|
||||
#define TCP_CTRL_SND_URG 0x0080 ///< In urgent send mode.
|
||||
#define TCP_CTRL_RCVD_URG 0x0100 ///< In urgent receive mode.
|
||||
#define TCP_CTRL_SND_PSH 0x0200 ///< In PUSH send mode.
|
||||
#define TCP_CTRL_FIN_SENT 0x0400 ///< FIN is sent.
|
||||
#define TCP_CTRL_FIN_ACKED 0x0800 ///< FIN is ACKed.
|
||||
#define TCP_CTRL_TIMER_ON 0x1000 ///< At least one of the timer is on.
|
||||
#define TCP_CTRL_RTT_ON 0x2000 ///< The RTT measurement is on.
|
||||
#define TCP_CTRL_ACK_NOW 0x4000 ///< Send the ACK now, don't delay.
|
||||
|
||||
//
|
||||
// Timer related values
|
||||
//
|
||||
#define TCP_TIMER_CONNECT 0 ///< Connection establishment timer.
|
||||
#define TCP_TIMER_REXMIT 1 ///< Retransmit timer.
|
||||
#define TCP_TIMER_PROBE 2 ///< Window probe timer.
|
||||
#define TCP_TIMER_KEEPALIVE 3 ///< Keepalive timer.
|
||||
#define TCP_TIMER_FINWAIT2 4 ///< FIN_WAIT_2 timer.
|
||||
#define TCP_TIMER_2MSL 5 ///< TIME_WAIT timer.
|
||||
#define TCP_TIMER_NUMBER 6 ///< The total number of the TCP timer.
|
||||
#define TCP_TICK 200 ///< Every TCP tick is 200ms.
|
||||
#define TCP_TICK_HZ 5 ///< The frequence of TCP tick.
|
||||
#define TCP_RTT_SHIFT 3 ///< SRTT & RTTVAR scaled by 8.
|
||||
#define TCP_RTO_MIN TCP_TICK_HZ ///< The minium value of RTO.
|
||||
#define TCP_RTO_MAX (TCP_TICK_HZ * 60) ///< The maxium value of RTO.
|
||||
#define TCP_FOLD_RTT 4 ///< Timeout threshod to fold RTT.
|
||||
|
||||
//
|
||||
// Default values for some timers
|
||||
//
|
||||
#define TCP_MAX_LOSS 12 ///< Default max times to retxmit.
|
||||
#define TCP_KEEPALIVE_IDLE_MIN (TCP_TICK_HZ * 60 * 60 * 2) ///< First keepalive.
|
||||
#define TCP_KEEPALIVE_PERIOD (TCP_TICK_HZ * 60)
|
||||
#define TCP_MAX_KEEPALIVE 8
|
||||
#define TCP_FIN_WAIT2_TIME (2 * TCP_TICK_HZ)
|
||||
#define TCP_TIME_WAIT_TIME (2 * TCP_TICK_HZ)
|
||||
#define TCP_PAWS_24DAY (24 * 24 * 60 * 60 * TCP_TICK_HZ)
|
||||
#define 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
|
||||
//
|
||||
#define TCP_MAX_HEAD 192
|
||||
|
||||
//
|
||||
// Value ranges for some control option
|
||||
//
|
||||
#define TCP_RCV_BUF_SIZE (2 * 1024 * 1024)
|
||||
#define TCP_RCV_BUF_SIZE_MIN (8 * 1024)
|
||||
#define TCP_SND_BUF_SIZE (2 * 1024 * 1024)
|
||||
#define TCP_SND_BUF_SIZE_MIN (8 * 1024)
|
||||
#define TCP_BACKLOG 10
|
||||
#define TCP_BACKLOG_MIN 5
|
||||
#define TCP_MAX_LOSS_MIN 6
|
||||
#define TCP_CONNECT_TIME_MIN (60 * TCP_TICK_HZ)
|
||||
#define TCP_MAX_KEEPALIVE_MIN 4
|
||||
#define TCP_KEEPALIVE_IDLE_MAX (TCP_TICK_HZ * 60 * 60 * 4)
|
||||
#define TCP_KEEPALIVE_PERIOD_MIN (TCP_TICK_HZ * 30)
|
||||
#define TCP_FIN_WAIT2_TIME_MAX (4 * TCP_TICK_HZ)
|
||||
#define TCP_TIME_WAIT_TIME_MAX (60 * TCP_TICK_HZ)
|
||||
|
||||
///
|
||||
/// 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)))
|
||||
|
||||
//
|
||||
// Check whether Flag is on
|
||||
//
|
||||
#define TCP_FLG_ON(Value, Flag) ((BOOLEAN) (((Value) & (Flag)) != 0))
|
||||
//
|
||||
// Set and Clear operation on a Flag
|
||||
//
|
||||
#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, Ver) \
|
||||
(((Pa)->Port == (Pb)->Port) && TcpIsIpEqual(&((Pa)->Ip), &((Pb)->Ip), Ver))
|
||||
|
||||
//
|
||||
// Test whether Pa matches Pb, or Pa is more specific
|
||||
// than pb. Zero means wildcard.
|
||||
//
|
||||
#define TCP_PEER_MATCH(Pa, Pb, Ver) \
|
||||
( \
|
||||
(((Pb)->Port == 0) || ((Pb)->Port == (Pa)->Port)) && \
|
||||
(TcpIsIpZero (&((Pb)->Ip), Ver) || TcpIsIpEqual (&((Pb)->Ip), &((Pa)->Ip), Ver)) \
|
||||
)
|
||||
|
||||
#define TCP_TIMER_ON(Flag, Timer) ((Flag) & (1 << (Timer)))
|
||||
#define TCP_SET_TIMER(Flag, Timer) ((Flag) = (UINT16) ((Flag) | (1 << (Timer))))
|
||||
#define TCP_CLEAR_TIMER(Flag, Timer) ((Flag) = (UINT16) ((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
|
||||
|
||||
///
|
||||
/// TCP segmentation data.
|
||||
///
|
||||
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 field in the segment.
|
||||
UINT8 Flag; ///< TCP header flags.
|
||||
UINT16 Urg; ///< Valid if URG flag is set.
|
||||
UINT32 Wnd; ///< TCP window size field.
|
||||
} TCP_SEG;
|
||||
|
||||
///
|
||||
/// Network endpoint, IP plus Port structure.
|
||||
///
|
||||
typedef struct _TCP_PEER {
|
||||
EFI_IP_ADDRESS Ip; ///< IP address, in network byte order.
|
||||
TCP_PORTNO Port; ///< Port number, in network byte order.
|
||||
} TCP_PEER;
|
||||
|
||||
typedef struct _TCP_CONTROL_BLOCK TCP_CB;
|
||||
|
||||
///
|
||||
/// TCP control block: it includes various states.
|
||||
///
|
||||
struct _TCP_CONTROL_BLOCK {
|
||||
LIST_ENTRY List; ///< Back and forward link entry
|
||||
TCP_CB *Parent; ///< The parent TCP_CB structure
|
||||
|
||||
SOCKET *Sk; ///< The socket it controled.
|
||||
TCP_PEER LocalEnd; ///< Local endpoint.
|
||||
TCP_PEER RemoteEnd;///< Remote endpoint.
|
||||
|
||||
LIST_ENTRY SndQue; ///< Retxmission queue.
|
||||
LIST_ENTRY RcvQue; ///< Reassemble queue.
|
||||
UINT32 CtrlFlag; ///< Control flags, such as NO_NAGLE.
|
||||
INT32 Error; ///< Soft error status, such as 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,
|
||||
///< do 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; ///< Countdown offset for the nearest timer.
|
||||
UINT32 Idle; ///< How long the connection is in idle.
|
||||
UINT32 ProbeTime; ///< The time out value for current window prober.
|
||||
BOOLEAN ProbeTimerOn;///< If TRUE, the probe time is on.
|
||||
|
||||
//
|
||||
// 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.
|
||||
|
||||
//
|
||||
// RFC2988 defined variables. about RTT measurement
|
||||
//
|
||||
TCP_SEQNO RttSeq; ///< The seq of measured segment now.
|
||||
UINT32 RttMeasure; ///< Currently measured RTT in heartbeats.
|
||||
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 timeout.
|
||||
UINT32 TimeWaitTimeout; ///< The TIME_WAIT timeout.
|
||||
UINT32 ConnectTimeout; ///< The connect establishment timeout.
|
||||
|
||||
//
|
||||
// configuration for tcp provided by user
|
||||
//
|
||||
BOOLEAN UseDefaultAddr;
|
||||
UINT8 Tos;
|
||||
UINT8 Ttl;
|
||||
EFI_IPv4_ADDRESS SubnetMask;
|
||||
|
||||
IP_IO_IP_INFO *IpInfo; ///< Pointer reference to Ip used to send pkt
|
||||
UINT32 Tick; ///< 1 tick = 200ms
|
||||
};
|
||||
|
||||
#endif
|
593
NetworkPkg/TcpDxe/TcpTimer.c
Normal file
593
NetworkPkg/TcpDxe/TcpTimer.c
Normal file
@@ -0,0 +1,593 @@
|
||||
/** @file
|
||||
TCP timer related functions.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "TcpMain.h"
|
||||
|
||||
UINT32 mTcpTick = 1000;
|
||||
|
||||
/**
|
||||
Connect timeout handler.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpConnectTimeout (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Timeout handler for TCP retransmission timer.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpRexmitTimeout (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Timeout handler for window probe timer.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpProbeTimeout (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Timeout handler for keepalive timer.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpKeepaliveTimeout (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Timeout handler for FIN_WAIT_2 timer.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpFinwait2Timeout (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
/**
|
||||
Timeout handler for 2MSL timer.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Tcp2MSLTimeout (
|
||||
IN OUT TCP_CB *Tcb
|
||||
);
|
||||
|
||||
TCP_TIMER_HANDLER mTcpTimerHandler[TCP_TIMER_NUMBER] = {
|
||||
TcpConnectTimeout,
|
||||
TcpRexmitTimeout,
|
||||
TcpProbeTimeout,
|
||||
TcpKeepaliveTimeout,
|
||||
TcpFinwait2Timeout,
|
||||
Tcp2MSLTimeout,
|
||||
};
|
||||
|
||||
/**
|
||||
Close the TCP connection.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpClose (
|
||||
IN OUT TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
NetbufFreeList (&Tcb->SndQue);
|
||||
NetbufFreeList (&Tcb->RcvQue);
|
||||
|
||||
TcpSetState (Tcb, TCP_CLOSED);
|
||||
}
|
||||
|
||||
/**
|
||||
Backoff the RTO.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpBackoffRto (
|
||||
IN OUT 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 != 0)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Connect timeout handler.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpConnectTimeout (
|
||||
IN OUT TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
if (!TCP_CONNECTED (Tcb->State)) {
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"TcpConnectTimeout: connection closed because conenction timer timeout for TCB %p\n",
|
||||
Tcb)
|
||||
);
|
||||
|
||||
if (EFI_ABORTED == Tcb->Sk->SockError) {
|
||||
SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
|
||||
}
|
||||
|
||||
if (TCP_SYN_RCVD == Tcb->State) {
|
||||
DEBUG (
|
||||
(EFI_D_WARN,
|
||||
"TcpConnectTimeout: send reset because connection timer timeout for TCB %p\n",
|
||||
Tcb)
|
||||
);
|
||||
|
||||
TcpResetConnection (Tcb);
|
||||
|
||||
}
|
||||
|
||||
TcpClose (Tcb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Timeout handler for TCP retransmission timer.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpRexmitTimeout (
|
||||
IN OUT TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
UINT32 FlightSize;
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_WARN,
|
||||
"TcpRexmitTimeout: transmission timeout for TCB %p\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 = 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)) {
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"TcpRexmitTimeout: connection closed because too many timeouts for TCB %p\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[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpProbeTimeout (
|
||||
IN OUT 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) != 0);
|
||||
Tcb->ProbeTimerOn = FALSE;
|
||||
return ;
|
||||
}
|
||||
|
||||
TcpSendZeroProbe (Tcb);
|
||||
TcpSetProbeTimer (Tcb);
|
||||
}
|
||||
|
||||
/**
|
||||
Timeout handler for keepalive timer.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpKeepaliveTimeout (
|
||||
IN OUT 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[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpFinwait2Timeout (
|
||||
IN OUT TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
DEBUG (
|
||||
(EFI_D_WARN,
|
||||
"TcpFinwait2Timeout: connection closed because FIN_WAIT2 timer timeouts for TCB %p\n",
|
||||
Tcb)
|
||||
);
|
||||
|
||||
TcpClose (Tcb);
|
||||
}
|
||||
|
||||
/**
|
||||
Timeout handler for 2MSL timer.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
Tcp2MSLTimeout (
|
||||
IN OUT TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
DEBUG (
|
||||
(EFI_D_WARN,
|
||||
"Tcp2MSLTimeout: connection closed because TIME_WAIT timer timeouts for TCB %p\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[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpUpdateTimer (
|
||||
IN OUT 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 = TCP_EXPIRE_TIME;
|
||||
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[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] Timer The index of the timer to be enabled.
|
||||
@param[in] TimeOut The timeout value of this timer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpSetTimer (
|
||||
IN OUT 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[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param[in] Timer The index of the timer to be cleared.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpClearTimer (
|
||||
IN OUT TCP_CB *Tcb,
|
||||
IN UINT16 Timer
|
||||
)
|
||||
{
|
||||
TCP_CLEAR_TIMER (Tcb->EnabledTimer, Timer);
|
||||
TcpUpdateTimer (Tcb);
|
||||
}
|
||||
|
||||
/**
|
||||
Clear all TCP timers.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpClearAllTimer (
|
||||
IN OUT TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
Tcb->EnabledTimer = 0;
|
||||
TcpUpdateTimer (Tcb);
|
||||
}
|
||||
|
||||
/**
|
||||
Enable the window prober timer and set the timeout value.
|
||||
|
||||
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpSetProbeTimer (
|
||||
IN OUT TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
if (!Tcb->ProbeTimerOn) {
|
||||
Tcb->ProbeTime = Tcb->Rto;
|
||||
Tcb->ProbeTimerOn = TRUE;
|
||||
|
||||
} 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[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
TcpSetKeepaliveTimer (
|
||||
IN OUT 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Heart beat timer handler.
|
||||
|
||||
@param[in] Context Context of the timer event, ignored.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TcpTickingDpc (
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *Next;
|
||||
TCP_CB *Tcb;
|
||||
INT16 Index;
|
||||
|
||||
mTcpTick++;
|
||||
mTcpGlobalIss += TCP_ISS_INCREMENT_2;
|
||||
|
||||
//
|
||||
// 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 != 0) {
|
||||
TcpSendAck (Tcb);
|
||||
}
|
||||
|
||||
if (Tcb->IpInfo->IpVersion == IP_VERSION_6 && Tcb->Tick > 0) {
|
||||
Tcb->Tick--;
|
||||
}
|
||||
|
||||
//
|
||||
// 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)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If the Tcb still exist or some timer is set, update the timer
|
||||
//
|
||||
if (Index == TCP_TIMER_NUMBER) {
|
||||
TcpUpdateTimer (Tcb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Heart beat timer handler, queues the DPC at TPL_CALLBACK.
|
||||
|
||||
@param[in] Event Timer event signaled, ignored.
|
||||
@param[in] Context Context of the timer event, ignored.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TcpTicking (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
QueueDpc (TPL_CALLBACK, TcpTickingDpc, Context);
|
||||
}
|
||||
|
Reference in New Issue
Block a user