MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf\r
MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf\r
MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf\r
- MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf\r
MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf\r
\r
MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PcatSingleSegmentPciCfg2Pei.inf\r
+++ /dev/null
-/** @file\r
- UEFI Component Name(2) protocol implementation for Tcp4Dxe driver.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Tcp4Main.h"\r
-\r
-/**\r
- Retrieves a Unicode string that is the user readable name of the driver.\r
-\r
- This function retrieves the user readable name of a driver in the form of a\r
- Unicode string. If the driver specified by This has a user readable name in\r
- the language specified by Language, then a pointer to the driver name is\r
- returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
- by This does not support the language specified by Language,\r
- then EFI_UNSUPPORTED is returned.\r
-\r
- @param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
- EFI_COMPONENT_NAME_PROTOCOL instance.\r
-\r
- @param[in] Language A pointer to a Null-terminated ASCII string\r
- array indicating the language. This is the\r
- language of the driver name that the caller is\r
- requesting, and it must match one of the\r
- languages specified in SupportedLanguages. The\r
- number of languages supported by a driver is up\r
- to the driver writer. Language is specified\r
- in RFC 4646 or ISO 639-2 language code format.\r
-\r
- @param[out] DriverName A pointer to the Unicode string to return.\r
- This Unicode string is the name of the\r
- driver specified by This in the language\r
- specified by Language.\r
-\r
- @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
- This and the language specified by Language was\r
- returned in DriverName.\r
-\r
- @retval EFI_INVALID_PARAMETER Language is NULL.\r
-\r
- @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
-\r
- @retval EFI_UNSUPPORTED The driver specified by This does not support\r
- the language specified by Language.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TcpComponentNameGetDriverName (\r
- IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
- IN CHAR8 *Language,\r
- OUT CHAR16 **DriverName\r
- );\r
-\r
-\r
-/**\r
- Retrieves a Unicode string that is the user readable name of the controller\r
- that is being managed by a driver.\r
-\r
- This function retrieves the user readable name of the controller specified by\r
- ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
- driver specified by This has a user readable name in the language specified by\r
- Language, then a pointer to the controller name is returned in ControllerName,\r
- and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
- managing the controller specified by ControllerHandle and ChildHandle,\r
- then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
- support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
-\r
- @param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
- EFI_COMPONENT_NAME_PROTOCOL instance.\r
-\r
- @param[in] ControllerHandle The handle of a controller that the driver\r
- specified by This is managing. This handle\r
- specifies the controller whose name is to be\r
- returned.\r
-\r
- @param[in] ChildHandle The handle of the child controller to retrieve\r
- the name of. This is an optional parameter that\r
- may be NULL. It will be NULL for device\r
- drivers. It will also be NULL for a bus drivers\r
- that wish to retrieve the name of the bus\r
- controller. It will not be NULL for a bus\r
- driver that wishes to retrieve the name of a\r
- child controller.\r
-\r
- @param[in] Language A pointer to a Null-terminated ASCII string\r
- array indicating the language. This is the\r
- language of the driver name that the caller is\r
- requesting, and it must match one of the\r
- languages specified in SupportedLanguages. The\r
- number of languages supported by a driver is up\r
- to the driver writer. Language is specified in\r
- RFC 4646 or ISO 639-2 language code format.\r
-\r
- @param[out] ControllerName A pointer to the Unicode string to return.\r
- This Unicode string is the name of the\r
- controller specified by ControllerHandle and\r
- ChildHandle in the language specified by\r
- Language from the point of view of the driver\r
- specified by This.\r
-\r
- @retval EFI_SUCCESS The Unicode string for the user readable name in\r
- the language specified by Language for the\r
- driver specified by This was returned in\r
- DriverName.\r
-\r
- @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.\r
-\r
- @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
- EFI_HANDLE.\r
-\r
- @retval EFI_INVALID_PARAMETER Language is NULL.\r
-\r
- @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
-\r
- @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
- managing the controller specified by\r
- ControllerHandle and ChildHandle.\r
-\r
- @retval EFI_UNSUPPORTED The driver specified by This does not support\r
- the language specified by Language.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TcpComponentNameGetControllerName (\r
- IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN EFI_HANDLE ChildHandle OPTIONAL,\r
- IN CHAR8 *Language,\r
- OUT CHAR16 **ControllerName\r
- );\r
-\r
-\r
-///\r
-/// EFI Component Name Protocol\r
-///\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName = {\r
- TcpComponentNameGetDriverName,\r
- TcpComponentNameGetControllerName,\r
- "eng"\r
-};\r
-\r
-///\r
-/// EFI Component Name 2 Protocol\r
-///\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gTcp4ComponentName2 = {\r
- (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) TcpComponentNameGetDriverName,\r
- (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) TcpComponentNameGetControllerName,\r
- "en"\r
-};\r
-\r
-\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mTcpDriverNameTable[] = {\r
- {\r
- "eng;en",\r
- L"Tcp Network Service Driver"\r
- },\r
- {\r
- NULL,\r
- NULL\r
- }\r
-};\r
-\r
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable = NULL;\r
-\r
-/**\r
- Retrieves a Unicode string that is the user readable name of the driver.\r
-\r
- This function retrieves the user readable name of a driver in the form of a\r
- Unicode string. If the driver specified by This has a user readable name in\r
- the language specified by Language, then a pointer to the driver name is\r
- returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
- by This does not support the language specified by Language,\r
- then EFI_UNSUPPORTED is returned.\r
-\r
- @param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
- EFI_COMPONENT_NAME_PROTOCOL instance.\r
-\r
- @param[in] Language A pointer to a Null-terminated ASCII string\r
- array indicating the language. This is the\r
- language of the driver name that the caller is\r
- requesting, and it must match one of the\r
- languages specified in SupportedLanguages. The\r
- number of languages supported by a driver is up\r
- to the driver writer. Language is specified\r
- in RFC 4646 or ISO 639-2 language code format.\r
-\r
- @param[out] DriverName A pointer to the Unicode string to return.\r
- This Unicode string is the name of the\r
- driver specified by This in the language\r
- specified by Language.\r
-\r
- @retval EFI_SUCCESS The Unicode string for the Driver specified by\r
- This and the language specified by Language was\r
- returned in DriverName.\r
-\r
- @retval EFI_INVALID_PARAMETER Language is NULL.\r
-\r
- @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
-\r
- @retval EFI_UNSUPPORTED The driver specified by This does not support\r
- the language specified by Language.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TcpComponentNameGetDriverName (\r
- IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
- IN CHAR8 *Language,\r
- OUT CHAR16 **DriverName\r
- )\r
-{\r
- return LookupUnicodeString2 (\r
- Language,\r
- This->SupportedLanguages,\r
- mTcpDriverNameTable,\r
- DriverName,\r
- (BOOLEAN) (This == &gTcp4ComponentName)\r
- );\r
-}\r
-\r
-/**\r
- Update the component name for the Tcp4 child handle.\r
-\r
- @param Tcp4[in] A pointer to the EFI_TCP4_PROTOCOL.\r
-\r
-\r
- @retval EFI_SUCCESS Update the ControllerNameTable of this instance successfully.\r
- @retval EFI_INVALID_PARAMETER The input parameter is invalid.\r
-\r
-**/\r
-EFI_STATUS\r
-UpdateName (\r
- IN EFI_TCP4_PROTOCOL *Tcp4\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 HandleName[80];\r
- EFI_TCP4_CONFIG_DATA Tcp4ConfigData;\r
-\r
- if (Tcp4 == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Format the child name into the string buffer as:\r
- // TCPv4 (SrcPort=59, DestPort=60, ActiveFlag=TRUE)\r
- //\r
- ZeroMem (&Tcp4ConfigData, sizeof (Tcp4ConfigData));\r
- Status = Tcp4->GetModeData (Tcp4, NULL, &Tcp4ConfigData, NULL, NULL, NULL);\r
- if (!EFI_ERROR (Status)) {\r
- UnicodeSPrint (HandleName, sizeof (HandleName),\r
- L"TCPv4 (SrcPort=%d, DestPort=%d, ActiveFlag=%s)",\r
- Tcp4ConfigData.AccessPoint.StationPort,\r
- Tcp4ConfigData.AccessPoint.RemotePort,\r
- (Tcp4ConfigData.AccessPoint.ActiveFlag ? L"TRUE" : L"FALSE")\r
- );\r
- } else if (Status == EFI_NOT_STARTED) {\r
- UnicodeSPrint (\r
- HandleName,\r
- sizeof (HandleName),\r
- L"TCPv4 (Not started)"\r
- );\r
- } else {\r
- return Status;\r
- }\r
-\r
- if (gTcpControllerNameTable != NULL) {\r
- FreeUnicodeStringTable (gTcpControllerNameTable);\r
- gTcpControllerNameTable = NULL;\r
- }\r
-\r
- Status = AddUnicodeString2 (\r
- "eng",\r
- gTcp4ComponentName.SupportedLanguages,\r
- &gTcpControllerNameTable,\r
- HandleName,\r
- TRUE\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- return AddUnicodeString2 (\r
- "en",\r
- gTcp4ComponentName2.SupportedLanguages,\r
- &gTcpControllerNameTable,\r
- HandleName,\r
- FALSE\r
- );\r
-}\r
-\r
-/**\r
- Retrieves a Unicode string that is the user readable name of the controller\r
- that is being managed by a driver.\r
-\r
- This function retrieves the user readable name of the controller specified by\r
- ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
- driver specified by This has a user readable name in the language specified by\r
- Language, then a pointer to the controller name is returned in ControllerName,\r
- and EFI_SUCCESS is returned. If the driver specified by This is not currently\r
- managing the controller specified by ControllerHandle and ChildHandle,\r
- then EFI_UNSUPPORTED is returned. If the driver specified by This does not\r
- support the language specified by Language, then EFI_UNSUPPORTED is returned.\r
-\r
- @param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or\r
- EFI_COMPONENT_NAME_PROTOCOL instance.\r
-\r
- @param[in] ControllerHandle The handle of a controller that the driver\r
- specified by This is managing. This handle\r
- specifies the controller whose name is to be\r
- returned.\r
-\r
- @param[in] ChildHandle The handle of the child controller to retrieve\r
- the name of. This is an optional parameter that\r
- may be NULL. It will be NULL for device\r
- drivers. It will also be NULL for a bus drivers\r
- that wish to retrieve the name of the bus\r
- controller. It will not be NULL for a bus\r
- driver that wishes to retrieve the name of a\r
- child controller.\r
-\r
- @param[in] Language A pointer to a Null-terminated ASCII string\r
- array indicating the language. This is the\r
- language of the driver name that the caller is\r
- requesting, and it must match one of the\r
- languages specified in SupportedLanguages. The\r
- number of languages supported by a driver is up\r
- to the driver writer. Language is specified in\r
- RFC 4646 or ISO 639-2 language code format.\r
-\r
- @param[out] ControllerName A pointer to the Unicode string to return.\r
- This Unicode string is the name of the\r
- controller specified by ControllerHandle and\r
- ChildHandle in the language specified by\r
- Language from the point of view of the driver\r
- specified by This.\r
-\r
- @retval EFI_SUCCESS The Unicode string for the user readable name in\r
- the language specified by Language for the\r
- driver specified by This was returned in\r
- DriverName.\r
-\r
- @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.\r
-\r
- @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
- EFI_HANDLE.\r
-\r
- @retval EFI_INVALID_PARAMETER Language is NULL.\r
-\r
- @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
-\r
- @retval EFI_UNSUPPORTED The driver specified by This is not currently\r
- managing the controller specified by\r
- ControllerHandle and ChildHandle.\r
-\r
- @retval EFI_UNSUPPORTED The driver specified by This does not support\r
- the language specified by Language.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TcpComponentNameGetControllerName (\r
- IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN EFI_HANDLE ChildHandle OPTIONAL,\r
- IN CHAR8 *Language,\r
- OUT CHAR16 **ControllerName\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_TCP4_PROTOCOL *Tcp4;\r
-\r
- //\r
- // Only provide names for child handles.\r
- //\r
- if (ChildHandle == NULL) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Make sure this driver produced ChildHandle\r
- //\r
- Status = EfiTestChildHandle (\r
- ControllerHandle,\r
- ChildHandle,\r
- &gEfiIp4ProtocolGuid\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Retrieve an instance of a produced protocol from ChildHandle\r
- //\r
- Status = gBS->OpenProtocol (\r
- ChildHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- (VOID **)&Tcp4,\r
- NULL,\r
- NULL,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Update the component name for this child handle.\r
- //\r
- Status = UpdateName (Tcp4);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- return LookupUnicodeString2 (\r
- Language,\r
- This->SupportedLanguages,\r
- gTcpControllerNameTable,\r
- ControllerName,\r
- (BOOLEAN)(This == &gTcp4ComponentName)\r
- );\r
-}\r
+++ /dev/null
-/** @file\r
- Implementation of the Socket.\r
-\r
-Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "SockImpl.h"\r
-\r
-/**\r
- Get the length of the data that can be retrieved from the socket\r
- receive buffer.\r
-\r
- @param SockBuffer Pointer to the socket receive buffer.\r
- @param IsUrg Pointer to a BOOLEAN variable. If TRUE the data is\r
- OOB.\r
- @param BufLen The maximum length of the data buffer to store the\r
- received data in socket layer.\r
-\r
- @return The length of the data can be retreived.\r
-\r
-**/\r
-UINT32\r
-SockTcpDataToRcv (\r
- IN SOCK_BUFFER *SockBuffer,\r
- OUT BOOLEAN *IsUrg,\r
- IN UINT32 BufLen\r
- );\r
-\r
-/**\r
- Process the send token.\r
-\r
- @param Sock Pointer to the socket.\r
-\r
-**/\r
-VOID\r
-SockProcessSndToken (\r
- IN OUT SOCKET *Sock\r
- );\r
-\r
-/**\r
- Supporting function for both SockImpl and SockInterface.\r
-\r
- @param Event The Event this notify function registered to, ignored.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SockFreeFoo (\r
- IN EFI_EVENT Event\r
- )\r
-{\r
- return ;\r
-}\r
-\r
-\r
-/**\r
- Get the length of the data that can be retrieved from the socket\r
- receive buffer.\r
-\r
- @param SockBuffer Pointer to the socket receive buffer.\r
- @param IsUrg Pointer to a BOOLEAN variable. If TRUE the data is\r
- OOB.\r
- @param BufLen The maximum length of the data buffer to store the\r
- received data in socket layer.\r
-\r
- @return The length of the data can be retreived.\r
-\r
-**/\r
-UINT32\r
-SockTcpDataToRcv (\r
- IN SOCK_BUFFER *SockBuffer,\r
- OUT BOOLEAN *IsUrg,\r
- IN UINT32 BufLen\r
- )\r
-{\r
- NET_BUF *RcvBufEntry;\r
- UINT32 DataLen;\r
- TCP_RSV_DATA *TcpRsvData;\r
- BOOLEAN Urg;\r
- ASSERT ((SockBuffer != NULL) && (IsUrg != NULL) && (BufLen > 0));\r
-\r
- RcvBufEntry = SockBufFirst (SockBuffer);\r
- ASSERT (RcvBufEntry != NULL);\r
-\r
- TcpRsvData = (TCP_RSV_DATA *) RcvBufEntry->ProtoData;\r
-\r
- *IsUrg = (BOOLEAN) ((TcpRsvData->UrgLen > 0) ? TRUE : FALSE);\r
-\r
- if (*IsUrg && TcpRsvData->UrgLen < RcvBufEntry->TotalSize) {\r
-\r
- DataLen = MIN (TcpRsvData->UrgLen, BufLen);\r
-\r
- if (DataLen < TcpRsvData->UrgLen) {\r
- TcpRsvData->UrgLen = TcpRsvData->UrgLen - DataLen;\r
- } else {\r
- TcpRsvData->UrgLen = 0;\r
- }\r
-\r
- return DataLen;\r
-\r
- }\r
-\r
- DataLen = RcvBufEntry->TotalSize;\r
-\r
- RcvBufEntry = SockBufNext (SockBuffer, RcvBufEntry);\r
-\r
- while ((BufLen > DataLen) && (RcvBufEntry != NULL)) {\r
-\r
- TcpRsvData = (TCP_RSV_DATA *) RcvBufEntry->ProtoData;\r
-\r
- Urg = (BOOLEAN) ((TcpRsvData->UrgLen > 0) ? TRUE : FALSE);\r
-\r
- if (*IsUrg != Urg) {\r
- break;\r
- }\r
-\r
- if (*IsUrg && TcpRsvData->UrgLen < RcvBufEntry->TotalSize) {\r
-\r
- if (TcpRsvData->UrgLen + DataLen < BufLen) {\r
- TcpRsvData->UrgLen = 0;\r
- } else {\r
- TcpRsvData->UrgLen = TcpRsvData->UrgLen - (BufLen - DataLen);\r
- }\r
-\r
- return MIN (TcpRsvData->UrgLen + DataLen, BufLen);\r
-\r
- }\r
-\r
- DataLen += RcvBufEntry->TotalSize;\r
-\r
- RcvBufEntry = SockBufNext (SockBuffer, RcvBufEntry);\r
- }\r
-\r
- DataLen = MIN (BufLen, DataLen);\r
- return DataLen;\r
-}\r
-\r
-\r
-/**\r
- Copy data from socket buffer to application provided receive buffer.\r
-\r
- @param Sock Pointer to the socket.\r
- @param TcpRxData Pointer to the application provided receive buffer.\r
- @param RcvdBytes The maximum length of the data can be copied.\r
- @param IsOOB If TRUE the data is OOB, FALSE the data is normal.\r
-\r
-**/\r
-VOID\r
-SockSetTcpRxData (\r
- IN SOCKET *Sock,\r
- IN VOID *TcpRxData,\r
- IN UINT32 RcvdBytes,\r
- IN BOOLEAN IsOOB\r
- )\r
-{\r
- UINT32 Index;\r
- UINT32 CopyBytes;\r
- UINT32 OffSet;\r
- EFI_TCP4_RECEIVE_DATA *RxData;\r
- EFI_TCP4_FRAGMENT_DATA *Fragment;\r
-\r
- RxData = (EFI_TCP4_RECEIVE_DATA *) TcpRxData;\r
-\r
- OffSet = 0;\r
-\r
- ASSERT (RxData->DataLength >= RcvdBytes);\r
-\r
- RxData->DataLength = RcvdBytes;\r
- RxData->UrgentFlag = IsOOB;\r
-\r
- for (Index = 0; (Index < RxData->FragmentCount) && (RcvdBytes > 0); Index++) {\r
-\r
- Fragment = &RxData->FragmentTable[Index];\r
- CopyBytes = MIN ((UINT32) (Fragment->FragmentLength), RcvdBytes);\r
-\r
- NetbufQueCopy (\r
- Sock->RcvBuffer.DataQueue,\r
- OffSet,\r
- CopyBytes,\r
- Fragment->FragmentBuffer\r
- );\r
-\r
- Fragment->FragmentLength = CopyBytes;\r
- RcvdBytes -= CopyBytes;\r
- OffSet += CopyBytes;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Get received data from the socket layer to the receive token.\r
-\r
- @param Sock Pointer to the socket.\r
- @param RcvToken Pointer to the application provided receive token.\r
-\r
- @return The length of data received in this token.\r
-\r
-**/\r
-UINT32\r
-SockProcessRcvToken (\r
- IN SOCKET *Sock,\r
- IN OUT SOCK_IO_TOKEN *RcvToken\r
- )\r
-{\r
- UINT32 TokenRcvdBytes;\r
- EFI_TCP4_RECEIVE_DATA *RxData;\r
- BOOLEAN IsUrg;\r
-\r
- ASSERT (Sock != NULL);\r
-\r
- ASSERT (SockStream == Sock->Type);\r
-\r
- RxData = RcvToken->Packet.RxData;\r
-\r
- TokenRcvdBytes = SockTcpDataToRcv (\r
- &Sock->RcvBuffer,\r
- &IsUrg,\r
- (UINT32) RxData->DataLength\r
- );\r
-\r
- //\r
- // Copy data from RcvBuffer of socket to user\r
- // provided RxData and set the fields in TCP RxData\r
- //\r
- SockSetTcpRxData (Sock, RxData, TokenRcvdBytes, IsUrg);\r
-\r
- NetbufQueTrim (Sock->RcvBuffer.DataQueue, TokenRcvdBytes);\r
- SIGNAL_TOKEN (&(RcvToken->Token), EFI_SUCCESS);\r
-\r
- return TokenRcvdBytes;\r
-}\r
-\r
-\r
-/**\r
- Process the TCP send data, buffer the tcp txdata and append\r
- the buffer to socket send buffer,then try to send it.\r
-\r
- @param Sock Pointer to the socket.\r
- @param TcpTxData Pointer to the application provided send buffer.\r
-\r
- @retval EFI_SUCCESS The operation is completed successfully.\r
- @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
-\r
-**/\r
-EFI_STATUS\r
-SockProcessTcpSndData (\r
- IN SOCKET *Sock,\r
- IN VOID *TcpTxData\r
- )\r
-{\r
- NET_BUF *SndData;\r
- EFI_STATUS Status;\r
- EFI_TCP4_TRANSMIT_DATA *TxData;\r
-\r
- TxData = (EFI_TCP4_TRANSMIT_DATA *) TcpTxData;\r
-\r
- //\r
- // transform this TxData into a NET_BUFFER\r
- // and insert it into Sock->SndBuffer\r
- //\r
- SndData = NetbufFromExt (\r
- (NET_FRAGMENT *) TxData->FragmentTable,\r
- (UINT32) TxData->FragmentCount,\r
- 0,\r
- 0,\r
- SockFreeFoo,\r
- NULL\r
- );\r
-\r
- if (NULL == SndData) {\r
- DEBUG ((EFI_D_ERROR, "SockKProcessSndData: Failed to"\r
- " call NetBufferFromExt\n"));\r
-\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- NetbufQueAppend (Sock->SndBuffer.DataQueue, SndData);\r
-\r
- //\r
- // notify the low layer protocol to handle this send token\r
- //\r
- if (TxData->Urgent) {\r
- Status = Sock->ProtoHandler (Sock, SOCK_SNDURG, NULL);\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- if (TxData->Push) {\r
- Status = Sock->ProtoHandler (Sock, SOCK_SNDPUSH, NULL);\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- //\r
- // low layer protocol should really handle the sending\r
- // process when catching SOCK_SND request\r
- //\r
- Status = Sock->ProtoHandler (Sock, SOCK_SND, NULL);\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Flush the tokens in the specific token list.\r
-\r
- @param Sock Pointer to the socket.\r
- @param PendingTokenList Pointer to the token list to be flushed.\r
-\r
-**/\r
-VOID\r
-SockFlushPendingToken (\r
- IN SOCKET *Sock,\r
- IN LIST_ENTRY *PendingTokenList\r
- )\r
-{\r
- SOCK_TOKEN *SockToken;\r
- SOCK_COMPLETION_TOKEN *Token;\r
-\r
- ASSERT ((Sock != NULL) && (PendingTokenList != NULL));\r
-\r
- while (!IsListEmpty (PendingTokenList)) {\r
- SockToken = NET_LIST_HEAD (\r
- PendingTokenList,\r
- SOCK_TOKEN,\r
- TokenList\r
- );\r
-\r
- Token = SockToken->Token;\r
- SIGNAL_TOKEN (Token, Sock->SockError);\r
-\r
- RemoveEntryList (&(SockToken->TokenList));\r
- FreePool (SockToken);\r
- }\r
-}\r
-\r
-\r
-/**\r
- Wake up the connection token while the connection is successfully established,\r
- then try to process any pending send token.\r
-\r
- @param Sock Pointer to the socket.\r
-\r
-**/\r
-VOID\r
-SockWakeConnToken (\r
- IN OUT SOCKET *Sock\r
- )\r
-{\r
- ASSERT (Sock->ConnectionToken != NULL);\r
-\r
- SIGNAL_TOKEN (Sock->ConnectionToken, EFI_SUCCESS);\r
- Sock->ConnectionToken = NULL;\r
-\r
- //\r
- // check to see if some pending send token existed?\r
- //\r
- SockProcessSndToken (Sock);\r
- return ;\r
-}\r
-\r
-\r
-/**\r
- Wake up the listen token while the connection is established successfully.\r
-\r
- @param Sock Pointer to the socket.\r
-\r
-**/\r
-VOID\r
-SockWakeListenToken (\r
- IN OUT SOCKET *Sock\r
- )\r
-{\r
- SOCKET *Parent;\r
- SOCK_TOKEN *SockToken;\r
- EFI_TCP4_LISTEN_TOKEN *ListenToken;\r
-\r
- Parent = Sock->Parent;\r
-\r
- ASSERT ((Parent != NULL) && SOCK_IS_LISTENING (Parent) && SOCK_IS_CONNECTED (Sock));\r
-\r
- if (!IsListEmpty (&Parent->ListenTokenList)) {\r
- SockToken = NET_LIST_HEAD (\r
- &Parent->ListenTokenList,\r
- SOCK_TOKEN,\r
- TokenList\r
- );\r
-\r
- ListenToken = (EFI_TCP4_LISTEN_TOKEN *) SockToken->Token;\r
- ListenToken->NewChildHandle = Sock->SockHandle;\r
-\r
- SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);\r
-\r
- RemoveEntryList (&SockToken->TokenList);\r
- FreePool (SockToken);\r
-\r
- RemoveEntryList (&Sock->ConnectionList);\r
-\r
- Parent->ConnCnt--;\r
- DEBUG ((EFI_D_NET, "SockWakeListenToken: accept a socket, now conncnt is %d", Parent->ConnCnt));\r
-\r
- Sock->Parent = NULL;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Wake up the receive token while some data is received.\r
-\r
- @param Sock Pointer to the socket.\r
-\r
-**/\r
-VOID\r
-SockWakeRcvToken (\r
- IN SOCKET *Sock\r
- )\r
-{\r
- UINT32 RcvdBytes;\r
- UINT32 TokenRcvdBytes;\r
- SOCK_TOKEN *SockToken;\r
- SOCK_IO_TOKEN *RcvToken;\r
-\r
- ASSERT (Sock->RcvBuffer.DataQueue != NULL);\r
-\r
- RcvdBytes = (Sock->RcvBuffer.DataQueue)->BufSize;\r
-\r
- ASSERT (RcvdBytes > 0);\r
-\r
- while (RcvdBytes > 0 && !IsListEmpty (&Sock->RcvTokenList)) {\r
-\r
- SockToken = NET_LIST_HEAD (\r
- &Sock->RcvTokenList,\r
- SOCK_TOKEN,\r
- TokenList\r
- );\r
-\r
- RcvToken = (SOCK_IO_TOKEN *) SockToken->Token;\r
- TokenRcvdBytes = SockProcessRcvToken (Sock, RcvToken);\r
-\r
- if (0 == TokenRcvdBytes) {\r
- return ;\r
- }\r
-\r
- RemoveEntryList (&(SockToken->TokenList));\r
- FreePool (SockToken);\r
- RcvdBytes -= TokenRcvdBytes;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Process the send token.\r
-\r
- @param Sock Pointer to the socket.\r
-\r
-**/\r
-VOID\r
-SockProcessSndToken (\r
- IN OUT SOCKET *Sock\r
- )\r
-{\r
- UINT32 FreeSpace;\r
- SOCK_TOKEN *SockToken;\r
- UINT32 DataLen;\r
- SOCK_IO_TOKEN *SndToken;\r
- EFI_TCP4_TRANSMIT_DATA *TxData;\r
- EFI_STATUS Status;\r
-\r
- ASSERT ((Sock != NULL) && (SockStream == Sock->Type));\r
-\r
- FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);\r
-\r
- //\r
- // to determine if process a send token using\r
- // socket layer flow control policy\r
- //\r
- while ((FreeSpace >= Sock->SndBuffer.LowWater) &&\r
- !IsListEmpty (&Sock->SndTokenList)) {\r
-\r
- SockToken = NET_LIST_HEAD (\r
- &(Sock->SndTokenList),\r
- SOCK_TOKEN,\r
- TokenList\r
- );\r
-\r
- //\r
- // process this token\r
- //\r
- RemoveEntryList (&(SockToken->TokenList));\r
- InsertTailList (\r
- &(Sock->ProcessingSndTokenList),\r
- &(SockToken->TokenList)\r
- );\r
-\r
- //\r
- // Proceess it in the light of SockType\r
- //\r
- SndToken = (SOCK_IO_TOKEN *) SockToken->Token;\r
- TxData = SndToken->Packet.TxData;\r
-\r
- DataLen = (UINT32) TxData->DataLength;\r
- Status = SockProcessTcpSndData (Sock, TxData);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto OnError;\r
- }\r
-\r
- if (DataLen >= FreeSpace) {\r
- FreeSpace = 0;\r
-\r
- } else {\r
- FreeSpace -= DataLen;\r
-\r
- }\r
- }\r
-\r
- return ;\r
-\r
-OnError:\r
-\r
- RemoveEntryList (&SockToken->TokenList);\r
- SIGNAL_TOKEN (SockToken->Token, Status);\r
- FreePool (SockToken);\r
-}\r
-\r
-\r
-/**\r
- Create a socket with initial data SockInitData.\r
-\r
- @param SockInitData Pointer to the initial data of the socket.\r
-\r
- @return Pointer to the newly created socket, return NULL when exception occured.\r
-\r
-**/\r
-SOCKET *\r
-SockCreate (\r
- IN SOCK_INIT_DATA *SockInitData\r
- )\r
-{\r
- SOCKET *Sock;\r
- SOCKET *Parent;\r
- EFI_STATUS Status;\r
-\r
- ASSERT ((SockInitData != NULL) && (SockInitData->ProtoHandler != NULL));\r
- ASSERT (SockInitData->Type == SockStream);\r
- ASSERT ((SockInitData->ProtoData != NULL) && (SockInitData->DataSize <= PROTO_RESERVED_LEN));\r
-\r
- Parent = SockInitData->Parent;\r
-\r
- if ((Parent != NULL) && (Parent->ConnCnt == Parent->BackLog)) {\r
- DEBUG (\r
- (EFI_D_ERROR,\r
- "SockCreate: Socket parent has "\r
- "reached its connection limit with %d ConnCnt and %d BackLog\n",\r
- Parent->ConnCnt,\r
- Parent->BackLog)\r
- );\r
-\r
- return NULL;\r
- }\r
-\r
- Sock = AllocateZeroPool (sizeof (SOCKET));\r
- if (NULL == Sock) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockCreate: No resource to create a new socket\n"));\r
- return NULL;\r
- }\r
-\r
- InitializeListHead (&Sock->Link);\r
- InitializeListHead (&Sock->ConnectionList);\r
- InitializeListHead (&Sock->ListenTokenList);\r
- InitializeListHead (&Sock->RcvTokenList);\r
- InitializeListHead (&Sock->SndTokenList);\r
- InitializeListHead (&Sock->ProcessingSndTokenList);\r
-\r
- EfiInitializeLock (&(Sock->Lock), TPL_CALLBACK);\r
-\r
- Sock->SndBuffer.DataQueue = NetbufQueAlloc ();\r
- if (NULL == Sock->SndBuffer.DataQueue) {\r
- DEBUG ((EFI_D_ERROR, "SockCreate: No resource to allocate"\r
- " SndBuffer for new socket\n"));\r
-\r
- goto OnError;\r
- }\r
-\r
- Sock->RcvBuffer.DataQueue = NetbufQueAlloc ();\r
- if (NULL == Sock->RcvBuffer.DataQueue) {\r
- DEBUG ((EFI_D_ERROR, "SockCreate: No resource to allocate "\r
- "RcvBuffer for new socket\n"));\r
-\r
- goto OnError;\r
- }\r
-\r
- Sock->Signature = SOCK_SIGNATURE;\r
-\r
- Sock->Parent = Parent;\r
- Sock->BackLog = SockInitData->BackLog;\r
- Sock->ProtoHandler = SockInitData->ProtoHandler;\r
- Sock->SndBuffer.HighWater = SockInitData->SndBufferSize;\r
- Sock->RcvBuffer.HighWater = SockInitData->RcvBufferSize;\r
- Sock->Type = SockInitData->Type;\r
- Sock->DriverBinding = SockInitData->DriverBinding;\r
- Sock->State = SockInitData->State;\r
- Sock->CreateCallback = SockInitData->CreateCallback;\r
- Sock->DestroyCallback = SockInitData->DestroyCallback;\r
- Sock->Context = SockInitData->Context;\r
-\r
- Sock->SockError = EFI_ABORTED;\r
- Sock->SndBuffer.LowWater = SOCK_BUFF_LOW_WATER;\r
- Sock->RcvBuffer.LowWater = SOCK_BUFF_LOW_WATER;\r
-\r
- //\r
- // Install protocol on Sock->SockHandle\r
- //\r
- CopyMem (\r
- &(Sock->NetProtocol.TcpProtocol),\r
- SockInitData->Protocol,\r
- sizeof (EFI_TCP4_PROTOCOL)\r
- );\r
-\r
- //\r
- // copy the protodata into socket\r
- //\r
- CopyMem (Sock->ProtoReserved, SockInitData->ProtoData, SockInitData->DataSize);\r
-\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Sock->SockHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- &(Sock->NetProtocol.TcpProtocol),\r
- NULL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "SockCreate: Install TCP protocol in "\r
- "socket failed with %r\n", Status));\r
-\r
- goto OnError;\r
- }\r
-\r
- if (Parent != NULL) {\r
- ASSERT (Parent->BackLog > 0);\r
- ASSERT (SOCK_IS_LISTENING (Parent));\r
-\r
- //\r
- // need to add it into Parent->ConnectionList\r
- // if the Parent->ConnCnt < Parent->BackLog\r
- //\r
- Parent->ConnCnt++;\r
-\r
- DEBUG (\r
- (EFI_D_NET,\r
- "SockCreate: Create a new socket and add to parent, now conncnt is %d\n",\r
- Parent->ConnCnt)\r
- );\r
-\r
- InsertTailList (&Parent->ConnectionList, &Sock->ConnectionList);\r
- }\r
-\r
- if (Sock->CreateCallback != NULL) {\r
- Status = Sock->CreateCallback (Sock, Sock->Context);\r
- if (EFI_ERROR (Status)) {\r
- goto OnError;\r
- }\r
- }\r
-\r
- return Sock;\r
-\r
-OnError:\r
-\r
- if (Sock->SockHandle != NULL) {\r
- gBS->UninstallMultipleProtocolInterfaces (\r
- Sock->SockHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- &(Sock->NetProtocol.TcpProtocol),\r
- NULL\r
- );\r
- }\r
-\r
- if (NULL != Sock->SndBuffer.DataQueue) {\r
- NetbufQueFree (Sock->SndBuffer.DataQueue);\r
- }\r
-\r
- if (NULL != Sock->RcvBuffer.DataQueue) {\r
- NetbufQueFree (Sock->RcvBuffer.DataQueue);\r
- }\r
-\r
- FreePool (Sock);\r
-\r
- return NULL;\r
-}\r
-\r
-\r
-/**\r
- Destroy a socket.\r
-\r
- @param Sock Pointer to the socket.\r
-\r
-**/\r
-VOID\r
-SockDestroy (\r
- IN OUT SOCKET *Sock\r
- )\r
-{\r
- ASSERT (SockStream == Sock->Type);\r
-\r
- //\r
- // Flush the completion token buffered\r
- // by sock and rcv, snd buffer\r
- //\r
- if (!SOCK_IS_UNCONFIGURED (Sock)) {\r
-\r
- SockConnFlush (Sock);\r
- SockSetState (Sock, SO_CLOSED);\r
- Sock->ConfigureState = SO_UNCONFIGURED;\r
-\r
- }\r
- //\r
- // Destroy the RcvBuffer Queue and SendBuffer Queue\r
- //\r
- NetbufQueFree (Sock->RcvBuffer.DataQueue);\r
- NetbufQueFree (Sock->SndBuffer.DataQueue);\r
-\r
- //\r
- // Remove it from parent connection list if needed\r
- //\r
- if (Sock->Parent != NULL) {\r
-\r
- RemoveEntryList (&(Sock->ConnectionList));\r
- (Sock->Parent->ConnCnt)--;\r
-\r
- DEBUG (\r
- (EFI_D_NET,\r
- "SockDestroy: Delete a unaccepted socket from parent"\r
- "now conncnt is %d\n",\r
- Sock->Parent->ConnCnt)\r
- );\r
-\r
- Sock->Parent = NULL;\r
- }\r
-\r
- FreePool (Sock);\r
- return ;\r
-}\r
-\r
-\r
-/**\r
- Flush the sndBuffer and rcvBuffer of socket.\r
-\r
- @param Sock Pointer to the socket.\r
-\r
-**/\r
-VOID\r
-SockConnFlush (\r
- IN OUT SOCKET *Sock\r
- )\r
-{\r
- SOCKET *Child;\r
-\r
- ASSERT (Sock != NULL);\r
-\r
- //\r
- // Clear the flag in this socket\r
- //\r
- Sock->Flag = 0;\r
-\r
- //\r
- // Flush the SndBuffer and RcvBuffer of Sock\r
- //\r
- NetbufQueFlush (Sock->SndBuffer.DataQueue);\r
- NetbufQueFlush (Sock->RcvBuffer.DataQueue);\r
-\r
- //\r
- // Signal the pending token\r
- //\r
- if (Sock->ConnectionToken != NULL) {\r
- SIGNAL_TOKEN (Sock->ConnectionToken, Sock->SockError);\r
- Sock->ConnectionToken = NULL;\r
- }\r
-\r
- if (Sock->CloseToken != NULL) {\r
- SIGNAL_TOKEN (Sock->CloseToken, Sock->SockError);\r
- Sock->CloseToken = NULL;\r
- }\r
-\r
- SockFlushPendingToken (Sock, &(Sock->ListenTokenList));\r
- SockFlushPendingToken (Sock, &(Sock->RcvTokenList));\r
- SockFlushPendingToken (Sock, &(Sock->SndTokenList));\r
- SockFlushPendingToken (Sock, &(Sock->ProcessingSndTokenList));\r
-\r
- //\r
- // Destroy the pending connection, if it is a listening socket\r
- //\r
- if (SOCK_IS_LISTENING (Sock)) {\r
- while (!IsListEmpty (&Sock->ConnectionList)) {\r
- Child = NET_LIST_HEAD (\r
- &Sock->ConnectionList,\r
- SOCKET,\r
- ConnectionList\r
- );\r
-\r
- SockDestroyChild (Child);\r
- }\r
-\r
- Sock->ConnCnt = 0;\r
- }\r
-\r
- return ;\r
-}\r
-\r
-\r
-/**\r
- Set the state of the socket.\r
-\r
- @param Sock Pointer to the socket.\r
- @param State The new socket state to be set.\r
-\r
-**/\r
-VOID\r
-SockSetState (\r
- IN OUT SOCKET *Sock,\r
- IN UINT8 State\r
- )\r
-{\r
- Sock->State = State;\r
-}\r
-\r
-\r
-/**\r
- Clone a new socket including its associated protocol control block.\r
-\r
- @param Sock Pointer to the socket to be cloned.\r
-\r
- @return Pointer to the newly cloned socket. If NULL, error condition occurred.\r
-\r
-**/\r
-SOCKET *\r
-SockClone (\r
- IN SOCKET *Sock\r
- )\r
-{\r
- SOCKET *ClonedSock;\r
- SOCK_INIT_DATA InitData;\r
-\r
- InitData.BackLog = Sock->BackLog;\r
- InitData.Parent = Sock;\r
- InitData.State = Sock->State;\r
- InitData.ProtoHandler = Sock->ProtoHandler;\r
- InitData.Type = Sock->Type;\r
- InitData.RcvBufferSize = Sock->RcvBuffer.HighWater;\r
- InitData.SndBufferSize = Sock->SndBuffer.HighWater;\r
- InitData.DriverBinding = Sock->DriverBinding;\r
- InitData.Protocol = &(Sock->NetProtocol);\r
- InitData.CreateCallback = Sock->CreateCallback;\r
- InitData.DestroyCallback = Sock->DestroyCallback;\r
- InitData.Context = Sock->Context;\r
- InitData.ProtoData = Sock->ProtoReserved;\r
- InitData.DataSize = sizeof (Sock->ProtoReserved);\r
-\r
- ClonedSock = SockCreate (&InitData);\r
-\r
- if (NULL == ClonedSock) {\r
- DEBUG ((EFI_D_ERROR, "SockClone: no resource to create a cloned sock\n"));\r
- return NULL;\r
- }\r
-\r
- SockSetState (ClonedSock, SO_CONNECTING);\r
- ClonedSock->ConfigureState = Sock->ConfigureState;\r
-\r
- return ClonedSock;\r
-}\r
-\r
-\r
-/**\r
- Called by the low layer protocol to indicate the socket a connection is\r
- established.\r
-\r
- This function just changes the socket's state to SO_CONNECTED\r
- and signals the token used for connection establishment.\r
-\r
- @param Sock Pointer to the socket associated with the\r
- established connection.\r
-**/\r
-VOID\r
-SockConnEstablished (\r
- IN SOCKET *Sock\r
- )\r
-{\r
-\r
- ASSERT (SO_CONNECTING == Sock->State);\r
-\r
- SockSetState (Sock, SO_CONNECTED);\r
-\r
- if (NULL == Sock->Parent) {\r
- SockWakeConnToken (Sock);\r
- } else {\r
- SockWakeListenToken (Sock);\r
- }\r
-\r
- return ;\r
-}\r
-\r
-\r
-/**\r
- Called by the low layer protocol to indicate the connection is closed.\r
-\r
- This function flushes the socket, sets the state to SO_CLOSED and signals\r
- the close token.\r
-\r
- @param Sock Pointer to the socket associated with the closed\r
- connection.\r
-\r
-**/\r
-VOID\r
-SockConnClosed (\r
- IN OUT SOCKET *Sock\r
- )\r
-{\r
- if (Sock->CloseToken != NULL) {\r
- SIGNAL_TOKEN (Sock->CloseToken, EFI_SUCCESS);\r
- Sock->CloseToken = NULL;\r
- }\r
-\r
- SockConnFlush (Sock);\r
- SockSetState (Sock, SO_CLOSED);\r
-\r
- if (Sock->Parent != NULL) {\r
- SockDestroyChild (Sock);\r
- }\r
-\r
-}\r
-\r
-\r
-/**\r
- Called by low layer protocol to indicate that some data is sent or processed.\r
-\r
- This function trims the sent data in the socket send buffer, signals the data\r
- token if proper.\r
-\r
- @param Sock Pointer to the socket.\r
- @param Count The length of the data processed or sent, in bytes.\r
-\r
-**/\r
-VOID\r
-SockDataSent (\r
- IN SOCKET *Sock,\r
- IN UINT32 Count\r
- )\r
-{\r
- SOCK_TOKEN *SockToken;\r
- SOCK_COMPLETION_TOKEN *SndToken;\r
-\r
- ASSERT (!IsListEmpty (&Sock->ProcessingSndTokenList));\r
- ASSERT (Count <= (Sock->SndBuffer.DataQueue)->BufSize);\r
-\r
- NetbufQueTrim (Sock->SndBuffer.DataQueue, Count);\r
-\r
- //\r
- // To check if we can signal some snd token in this socket\r
- //\r
- while (Count > 0) {\r
- SockToken = NET_LIST_HEAD (\r
- &(Sock->ProcessingSndTokenList),\r
- SOCK_TOKEN,\r
- TokenList\r
- );\r
-\r
- SndToken = SockToken->Token;\r
-\r
- if (SockToken->RemainDataLen <= Count) {\r
-\r
- RemoveEntryList (&(SockToken->TokenList));\r
- SIGNAL_TOKEN (SndToken, EFI_SUCCESS);\r
- Count -= SockToken->RemainDataLen;\r
- FreePool (SockToken);\r
- } else {\r
-\r
- SockToken->RemainDataLen -= Count;\r
- Count = 0;\r
- }\r
- }\r
-\r
- //\r
- // to judge if we can process some send token in\r
- // Sock->SndTokenList, if so process those send token\r
- //\r
- SockProcessSndToken (Sock);\r
- return ;\r
-}\r
-\r
-\r
-/**\r
- Called by the low layer protocol to copy some data in socket send\r
- buffer starting from the specific offset to a buffer provided by\r
- the caller.\r
-\r
- @param Sock Pointer to the socket.\r
- @param Offset The start point of the data to be copied.\r
- @param Len The length of the data to be copied.\r
- @param Dest Pointer to the destination to copy the data.\r
-\r
- @return The data size copied.\r
-\r
-**/\r
-UINT32\r
-SockGetDataToSend (\r
- IN SOCKET *Sock,\r
- IN UINT32 Offset,\r
- IN UINT32 Len,\r
- IN UINT8 *Dest\r
- )\r
-{\r
- ASSERT ((Sock != NULL) && SockStream == Sock->Type);\r
-\r
- return NetbufQueCopy (\r
- Sock->SndBuffer.DataQueue,\r
- Offset,\r
- Len,\r
- Dest\r
- );\r
-}\r
-\r
-\r
-/**\r
- Called by the low layer protocol to deliver received data to socket layer.\r
-\r
- This function will append the data to the socket receive buffer, set ther\r
- urgent data length and then check if any receive token can be signaled.\r
-\r
- @param Sock Pointer to the socket.\r
- @param NetBuffer Pointer to the buffer that contains the received\r
- data.\r
- @param UrgLen The length of the urgent data in the received data.\r
-\r
-**/\r
-VOID\r
-SockDataRcvd (\r
- IN SOCKET *Sock,\r
- IN OUT NET_BUF *NetBuffer,\r
- IN UINT32 UrgLen\r
- )\r
-{\r
- ASSERT ((Sock != NULL) && (Sock->RcvBuffer.DataQueue != NULL) &&\r
- UrgLen <= NetBuffer->TotalSize);\r
-\r
- NET_GET_REF (NetBuffer);\r
-\r
- ((TCP_RSV_DATA *) (NetBuffer->ProtoData))->UrgLen = UrgLen;\r
-\r
- NetbufQueAppend (Sock->RcvBuffer.DataQueue, NetBuffer);\r
-\r
- SockWakeRcvToken (Sock);\r
- return ;\r
-}\r
-\r
-\r
-/**\r
- Get the length of the free space of the specific socket buffer.\r
-\r
- @param Sock Pointer to the socket.\r
- @param Which Flag to indicate which socket buffer to check,\r
- either send buffer or receive buffer.\r
-\r
- @return The length of the free space, in bytes.\r
-\r
-**/\r
-UINT32\r
-SockGetFreeSpace (\r
- IN SOCKET *Sock,\r
- IN UINT32 Which\r
- )\r
-{\r
- UINT32 BufferCC;\r
- SOCK_BUFFER *SockBuffer;\r
-\r
- ASSERT ((Sock != NULL) && ((SOCK_SND_BUF == Which) || (SOCK_RCV_BUF == Which)));\r
-\r
- if (SOCK_SND_BUF == Which) {\r
- SockBuffer = &(Sock->SndBuffer);\r
- } else {\r
- SockBuffer = &(Sock->RcvBuffer);\r
- }\r
-\r
- BufferCC = (SockBuffer->DataQueue)->BufSize;\r
-\r
- if (BufferCC >= SockBuffer->HighWater) {\r
-\r
- return 0;\r
- }\r
-\r
- return SockBuffer->HighWater - BufferCC;\r
-}\r
-\r
-\r
-\r
-/**\r
- Called by the low layer protocol to indicate that there will be no more data\r
- from the communication peer.\r
-\r
- This function set the socket's state to SO_NO_MORE_DATA and signal all queued\r
- IO tokens with the error status EFI_CONNECTION_FIN.\r
-\r
- @param Sock Pointer to the socket.\r
-\r
-**/\r
-VOID\r
-SockNoMoreData (\r
- IN OUT SOCKET *Sock\r
- )\r
-{\r
- EFI_STATUS Err;\r
-\r
- SOCK_NO_MORE_DATA (Sock);\r
-\r
- if (!IsListEmpty (&Sock->RcvTokenList)) {\r
-\r
- ASSERT (0 == GET_RCV_DATASIZE (Sock));\r
-\r
- Err = Sock->SockError;\r
-\r
- SOCK_ERROR (Sock, EFI_CONNECTION_FIN);\r
-\r
- SockFlushPendingToken (Sock, &Sock->RcvTokenList);\r
-\r
- SOCK_ERROR (Sock, Err);\r
-\r
- }\r
-\r
-}\r
-\r
-\r
-/**\r
- Get the first buffer block in the specific socket buffer.\r
-\r
- @param Sockbuf Pointer to the socket buffer.\r
-\r
- @return Pointer to the first buffer in the queue. NULL if the queue is empty.\r
-\r
-**/\r
-NET_BUF *\r
-SockBufFirst (\r
- IN SOCK_BUFFER *Sockbuf\r
- )\r
-{\r
- LIST_ENTRY *NetbufList;\r
-\r
- NetbufList = &(Sockbuf->DataQueue->BufList);\r
-\r
- if (IsListEmpty (NetbufList)) {\r
- return NULL;\r
- }\r
-\r
- return NET_LIST_HEAD (NetbufList, NET_BUF, List);\r
-}\r
-\r
-\r
-/**\r
- Get the next buffer block in the specific socket buffer.\r
-\r
- @param Sockbuf Pointer to the socket buffer.\r
- @param SockEntry Pointer to the buffer block prior to the required\r
- one.\r
-\r
- @return Pointer to the buffer block next to SockEntry. NULL if SockEntry is\r
- the tail or head entry.\r
-\r
-**/\r
-NET_BUF *\r
-SockBufNext (\r
- IN SOCK_BUFFER *Sockbuf,\r
- IN NET_BUF *SockEntry\r
- )\r
-{\r
- LIST_ENTRY *NetbufList;\r
-\r
- NetbufList = &(Sockbuf->DataQueue->BufList);\r
-\r
- if ((SockEntry->List.ForwardLink == NetbufList) ||\r
- (SockEntry->List.BackLink == &SockEntry->List) ||\r
- (SockEntry->List.ForwardLink == &SockEntry->List)) {\r
-\r
- return NULL;\r
- }\r
-\r
- return NET_LIST_USER_STRUCT (SockEntry->List.ForwardLink, NET_BUF, List);\r
-}\r
+++ /dev/null
-/** @file\r
- Socket implementation header file.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#ifndef _SOCK_IMPL_H_\r
-#define _SOCK_IMPL_H_\r
-\r
-#include "Socket.h"\r
-#include "Tcp4Main.h"\r
-\r
-/**\r
- Signal a event with the given status.\r
-\r
- @param Token The token's event is to be signaled.\r
- @param TokenStatus The status to be sent with the event.\r
-\r
-**/\r
-#define SIGNAL_TOKEN(Token, TokenStatus) \\r
- do { \\r
- (Token)->Status = (TokenStatus); \\r
- gBS->SignalEvent ((Token)->Event); \\r
- } while (0)\r
-\r
-\r
-/**\r
- Supporting function for both SockImpl and SockInterface.\r
-\r
- @param Event The Event this notify function registered to, ignored.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-SockFreeFoo (\r
- IN EFI_EVENT Event\r
- );\r
-\r
-/**\r
- Process the TCP send data, buffer the tcp txdata and append\r
- the buffer to socket send buffer,then try to send it.\r
-\r
- @param Sock Pointer to the socket.\r
- @param TcpTxData Pointer to the tcp txdata.\r
-\r
- @retval EFI_SUCCESS The operation is completed successfully.\r
- @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
-\r
-**/\r
-EFI_STATUS\r
-SockProcessTcpSndData (\r
- IN SOCKET *Sock,\r
- IN VOID *TcpTxData\r
- );\r
-\r
-/**\r
- Copy data from socket buffer to application provided receive buffer.\r
-\r
- @param Sock Pointer to the socket.\r
- @param TcpRxData Pointer to the application provided receive buffer.\r
- @param RcvdBytes The maximum length of the data can be copied.\r
- @param IsOOB If TRUE the data is OOB, else the data is normal.\r
-\r
-**/\r
-VOID\r
-SockSetTcpRxData (\r
- IN SOCKET *Sock,\r
- IN VOID *TcpRxData,\r
- IN UINT32 RcvdBytes,\r
- IN BOOLEAN IsOOB\r
- );\r
-\r
-/**\r
- Get received data from the socket layer to the receive token.\r
-\r
- @param Sock Pointer to the socket.\r
- @param RcvToken Pointer to the application provided receive token.\r
-\r
- @return The length of data received in this token.\r
-\r
-**/\r
-UINT32\r
-SockProcessRcvToken (\r
- IN SOCKET *Sock,\r
- IN OUT SOCK_IO_TOKEN *RcvToken\r
- );\r
-\r
-/**\r
- Flush the socket.\r
-\r
- @param Sock Pointer to the socket.\r
-\r
-**/\r
-VOID\r
-SockConnFlush (\r
- IN OUT SOCKET *Sock\r
- );\r
-\r
-/**\r
- Create a socket with initial data SockInitData.\r
-\r
- @param SockInitData Pointer to the initial data of the socket.\r
-\r
- @return Pointer to the newly created socket.\r
-\r
-**/\r
-SOCKET *\r
-SockCreate (\r
- IN SOCK_INIT_DATA *SockInitData\r
- );\r
-\r
-/**\r
- Destroy a socket.\r
-\r
- @param Sock Pointer to the socket.\r
-\r
-**/\r
-VOID\r
-SockDestroy (\r
- IN OUT SOCKET *Sock\r
- );\r
-\r
-#endif\r
+++ /dev/null
-/** @file\r
- Interface function of the Socket.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-\r
-#include "SockImpl.h"\r
-\r
-\r
-/**\r
- Check whether the Event is in the List.\r
-\r
- @param List Pointer to the token list to be searched.\r
- @param Event The event to be checked.\r
-\r
- @retval TRUE The specific Event exists in the List.\r
- @retval FALSE The specific Event is not in the List.\r
-\r
-**/\r
-BOOLEAN\r
-SockTokenExistedInList (\r
- IN LIST_ENTRY *List,\r
- IN EFI_EVENT Event\r
- )\r
-{\r
- LIST_ENTRY *ListEntry;\r
- SOCK_TOKEN *SockToken;\r
-\r
- NET_LIST_FOR_EACH (ListEntry, List) {\r
- SockToken = NET_LIST_USER_STRUCT (\r
- ListEntry,\r
- SOCK_TOKEN,\r
- TokenList\r
- );\r
-\r
- if (Event == SockToken->Token->Event) {\r
- return TRUE;\r
- }\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-\r
-/**\r
- Call SockTokenExistedInList() to check whether the Event is\r
- in the related socket's lists.\r
-\r
- @param Sock Pointer to the instance's socket.\r
- @param Event The event to be checked.\r
-\r
- @retval TRUE The Event exists in related socket's lists.\r
- @retval FALSE The Event is not in related socket's lists.\r
-\r
-**/\r
-BOOLEAN\r
-SockTokenExisted (\r
- IN SOCKET *Sock,\r
- IN EFI_EVENT Event\r
- )\r
-{\r
-\r
- if (SockTokenExistedInList (&Sock->SndTokenList, Event) ||\r
- SockTokenExistedInList (&Sock->ProcessingSndTokenList, Event) ||\r
- SockTokenExistedInList (&Sock->RcvTokenList, Event) ||\r
- SockTokenExistedInList (&Sock->ListenTokenList, Event)) {\r
-\r
- return TRUE;\r
- }\r
-\r
- if ((Sock->ConnectionToken != NULL) &&\r
- (Sock->ConnectionToken->Event == Event)) {\r
-\r
- return TRUE;\r
- }\r
-\r
- if ((Sock->CloseToken != NULL) && (Sock->CloseToken->Event == Event)) {\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-\r
-/**\r
- Buffer a token into the specific list of socket Sock.\r
-\r
- @param Sock Pointer to the instance's socket.\r
- @param List Pointer to the list to store the token.\r
- @param Token Pointer to the token to be buffered.\r
- @param DataLen The data length of the buffer contained in Token.\r
-\r
- @return Pointer to the token that wraps Token. If NULL, error condition occurred.\r
-\r
-**/\r
-SOCK_TOKEN *\r
-SockBufferToken (\r
- IN SOCKET *Sock,\r
- IN LIST_ENTRY *List,\r
- IN VOID *Token,\r
- IN UINT32 DataLen\r
- )\r
-{\r
- SOCK_TOKEN *SockToken;\r
-\r
- SockToken = AllocatePool (sizeof (SOCK_TOKEN));\r
- if (NULL == SockToken) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockBufferIOToken: No Memory "\r
- "to allocate SockToken\n"));\r
-\r
- return NULL;\r
- }\r
-\r
- SockToken->Sock = Sock;\r
- SockToken->Token = (SOCK_COMPLETION_TOKEN *) Token;\r
- SockToken->RemainDataLen = DataLen;\r
- InsertTailList (List, &SockToken->TokenList);\r
-\r
- return SockToken;\r
-}\r
-\r
-\r
-/**\r
- Destroy the socket Sock and its associated protocol control block.\r
-\r
- @param Sock The socket to be destroyed.\r
-\r
- @retval EFI_SUCCESS The socket Sock is destroyed successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
-\r
-**/\r
-EFI_STATUS\r
-SockDestroyChild (\r
- IN SOCKET *Sock\r
- )\r
-{\r
- EFI_STATUS Status;\r
- TCP4_PROTO_DATA *ProtoData;\r
- TCP_CB *Tcb;\r
- VOID *SockProtocol;\r
-\r
- ASSERT ((Sock != NULL) && (Sock->ProtoHandler != NULL));\r
-\r
- if (Sock->InDestroy) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- Sock->InDestroy = TRUE;\r
-\r
- ProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;\r
- Tcb = ProtoData->TcpPcb;\r
-\r
- ASSERT (Tcb != NULL);\r
-\r
- //\r
- // Close the IP protocol.\r
- //\r
- gBS->CloseProtocol (\r
- Tcb->IpInfo->ChildHandle,\r
- &gEfiIp4ProtocolGuid,\r
- ProtoData->TcpService->IpIo->Image,\r
- Sock->SockHandle\r
- );\r
-\r
- if (Sock->DestroyCallback != NULL) {\r
- Sock->DestroyCallback (Sock, Sock->Context);\r
- }\r
-\r
- //\r
- // Retrieve the protocol installed on this sock\r
- //\r
- Status = gBS->OpenProtocol (\r
- Sock->SockHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- &SockProtocol,\r
- Sock->DriverBinding,\r
- Sock->SockHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockDestroyChild: Open protocol installed "\r
- "on socket failed with %r\n", Status));\r
- }\r
-\r
- //\r
- // Uninstall the protocol installed on this sock\r
- // in the light of Sock->SockType\r
- //\r
- gBS->UninstallMultipleProtocolInterfaces (\r
- Sock->SockHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- SockProtocol,\r
- NULL\r
- );\r
-\r
- Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockDestroyChild: Get the lock to "\r
- "access socket failed with %r\n", Status));\r
-\r
- return EFI_ACCESS_DENIED;\r
- }\r
-\r
- //\r
- // force protocol layer to detach the PCB\r
- //\r
- Status = Sock->ProtoHandler (Sock, SOCK_DETACH, NULL);\r
-\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockDestroyChild: Protocol detach socket"\r
- " failed with %r\n", Status));\r
-\r
- Sock->InDestroy = FALSE;\r
- } else if (SOCK_IS_CONFIGURED (Sock)) {\r
-\r
- SockConnFlush (Sock);\r
- SockSetState (Sock, SO_CLOSED);\r
-\r
- Sock->ConfigureState = SO_UNCONFIGURED;\r
- }\r
-\r
- EfiReleaseLock (&(Sock->Lock));\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- SockDestroy (Sock);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Create a socket and its associated protocol control block\r
- with the intial data SockInitData and protocol specific\r
- data ProtoData.\r
-\r
- @param SockInitData Inital data to setting the socket.\r
-\r
- @return Pointer to the newly created socket. If NULL, error condition occured.\r
-\r
-**/\r
-SOCKET *\r
-SockCreateChild (\r
- IN SOCK_INIT_DATA *SockInitData\r
- )\r
-{\r
- SOCKET *Sock;\r
- VOID *SockProtocol;\r
- EFI_STATUS Status;\r
-\r
- //\r
- // create a new socket\r
- //\r
- Sock = SockCreate (SockInitData);\r
- if (NULL == Sock) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockCreateChild: No resource to "\r
- "create a new socket\n"));\r
-\r
- return NULL;\r
- }\r
-\r
- Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockCreateChild: Get the lock to "\r
- "access socket failed with %r\n", Status));\r
-\r
- goto ERROR;\r
- }\r
- //\r
- // inform the protocol layer to attach the socket\r
- // with a new protocol control block\r
- //\r
- Status = Sock->ProtoHandler (Sock, SOCK_ATTACH, NULL);\r
- EfiReleaseLock (&(Sock->Lock));\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockCreateChild: Protocol failed to"\r
- " attach a socket with %r\n", Status));\r
-\r
- goto ERROR;\r
- }\r
-\r
- return Sock;\r
-\r
-ERROR:\r
-\r
- if (Sock->DestroyCallback != NULL) {\r
- Sock->DestroyCallback (Sock, Sock->Context);\r
- }\r
-\r
- gBS->OpenProtocol (\r
- Sock->SockHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- &SockProtocol,\r
- Sock->DriverBinding,\r
- Sock->SockHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- //\r
- // Uninstall the protocol installed on this sock\r
- //\r
- gBS->UninstallMultipleProtocolInterfaces (\r
- Sock->SockHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- SockProtocol,\r
- NULL\r
- );\r
- SockDestroy (Sock);\r
- return NULL;\r
-}\r
-\r
-\r
-/**\r
- Configure the specific socket Sock using configuration data ConfigData.\r
-\r
- @param Sock Pointer to the socket to be configured.\r
- @param ConfigData Pointer to the configuration data.\r
-\r
- @retval EFI_SUCCESS The socket is configured successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the\r
- socket is already configured.\r
-\r
-**/\r
-EFI_STATUS\r
-SockConfigure (\r
- IN SOCKET *Sock,\r
- IN VOID *ConfigData\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockConfigure: Get the access for "\r
- "socket failed with %r", Status));\r
-\r
- return EFI_ACCESS_DENIED;\r
- }\r
-\r
- if (SOCK_IS_CONFIGURED (Sock)) {\r
- Status = EFI_ACCESS_DENIED;\r
- goto OnExit;\r
- }\r
-\r
- ASSERT (Sock->State == SO_CLOSED);\r
-\r
- Status = Sock->ProtoHandler (Sock, SOCK_CONFIGURE, ConfigData);\r
-\r
-OnExit:\r
- EfiReleaseLock (&(Sock->Lock));\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Initiate a connection establishment process.\r
-\r
- @param Sock Pointer to the socket to initiate the initate the\r
- connection.\r
- @param Token Pointer to the token used for the connection\r
- operation.\r
-\r
- @retval EFI_SUCCESS The connection is initialized successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
- socket is closed, or the socket is not configured to\r
- be an active one, or the token is already in one of\r
- this socket's lists.\r
- @retval EFI_NO_MAPPING The IP address configuration operation is not\r
- finished.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
-\r
-**/\r
-EFI_STATUS\r
-SockConnect (\r
- IN SOCKET *Sock,\r
- IN VOID *Token\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_EVENT Event;\r
-\r
- Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockConnect: Get the access for "\r
- "socket failed with %r", Status));\r
-\r
- return EFI_ACCESS_DENIED;\r
- }\r
-\r
- if (SOCK_IS_NO_MAPPING (Sock)) {\r
- Status = EFI_NO_MAPPING;\r
- goto OnExit;\r
- }\r
-\r
- if (SOCK_IS_UNCONFIGURED (Sock)) {\r
-\r
- Status = EFI_NOT_STARTED;\r
- goto OnExit;\r
- }\r
-\r
- if (!SOCK_IS_CLOSED (Sock) || !SOCK_IS_CONFIGURED_ACTIVE (Sock)) {\r
-\r
- Status = EFI_ACCESS_DENIED;\r
- goto OnExit;\r
- }\r
-\r
- Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;\r
-\r
- if (SockTokenExisted (Sock, Event)) {\r
-\r
- Status = EFI_ACCESS_DENIED;\r
- goto OnExit;\r
- }\r
-\r
- Sock->ConnectionToken = (SOCK_COMPLETION_TOKEN *) Token;\r
- SockSetState (Sock, SO_CONNECTING);\r
- Status = Sock->ProtoHandler (Sock, SOCK_CONNECT, NULL);\r
-\r
-OnExit:\r
- EfiReleaseLock (&(Sock->Lock));\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Issue a listen token to get an existed connected network instance\r
- or wait for a connection if there is none.\r
-\r
- @param Sock Pointer to the socket to accept connections.\r
- @param Token The token to accept a connection.\r
-\r
- @retval EFI_SUCCESS Either a connection is accpeted or the Token is\r
- buffered for further acception.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
- socket is closed, or the socket is not configured to\r
- be a passive one, or the token is already in one of\r
- this socket's lists.\r
- @retval EFI_NO_MAPPING The IP address configuration operation is not\r
- finished.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
- @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.\r
-\r
-**/\r
-EFI_STATUS\r
-SockAccept (\r
- IN SOCKET *Sock,\r
- IN VOID *Token\r
- )\r
-{\r
- EFI_TCP4_LISTEN_TOKEN *ListenToken;\r
- LIST_ENTRY *ListEntry;\r
- EFI_STATUS Status;\r
- SOCKET *Socket;\r
- EFI_EVENT Event;\r
-\r
- ASSERT (SockStream == Sock->Type);\r
-\r
- Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockAccept: Get the access for socket"\r
- " failed with %r", Status));\r
-\r
- return EFI_ACCESS_DENIED;\r
- }\r
-\r
- if (SOCK_IS_NO_MAPPING (Sock)) {\r
- Status = EFI_NO_MAPPING;\r
- goto Exit;\r
- }\r
-\r
- if (SOCK_IS_UNCONFIGURED (Sock)) {\r
-\r
- Status = EFI_NOT_STARTED;\r
- goto Exit;\r
- }\r
-\r
- if (!SOCK_IS_LISTENING (Sock)) {\r
-\r
- Status = EFI_ACCESS_DENIED;\r
- goto Exit;\r
- }\r
-\r
- Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;\r
-\r
- if (SockTokenExisted (Sock, Event)) {\r
-\r
- Status = EFI_ACCESS_DENIED;\r
- goto Exit;\r
- }\r
-\r
- ListenToken = (EFI_TCP4_LISTEN_TOKEN *) Token;\r
-\r
- //\r
- // Check if a connection has already in this Sock->ConnectionList\r
- //\r
- NET_LIST_FOR_EACH (ListEntry, &Sock->ConnectionList) {\r
-\r
- Socket = NET_LIST_USER_STRUCT (ListEntry, SOCKET, ConnectionList);\r
-\r
- if (SOCK_IS_CONNECTED (Socket)) {\r
- ListenToken->NewChildHandle = Socket->SockHandle;\r
- SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);\r
-\r
- RemoveEntryList (ListEntry);\r
-\r
- ASSERT (Socket->Parent != NULL);\r
-\r
- Socket->Parent->ConnCnt--;\r
-\r
- DEBUG (\r
- (EFI_D_NET,\r
- "SockAccept: Accept a socket, now conncount is %d",\r
- Socket->Parent->ConnCnt)\r
- );\r
- Socket->Parent = NULL;\r
-\r
- goto Exit;\r
- }\r
- }\r
-\r
- //\r
- // Buffer this token for latter incoming connection request\r
- //\r
- if (NULL == SockBufferToken (Sock, &(Sock->ListenTokenList), Token, 0)) {\r
-\r
- Status = EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
-Exit:\r
- EfiReleaseLock (&(Sock->Lock));\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Issue a token with data to the socket to send out.\r
-\r
- @param Sock Pointer to the socket to process the token with\r
- data.\r
- @param Token The token with data that needs to send out.\r
-\r
- @retval EFI_SUCCESS The token is processed successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
- socket is closed, or the socket is not in a\r
- synchronized state , or the token is already in one\r
- of this socket's lists.\r
- @retval EFI_NO_MAPPING The IP address configuration operation is not\r
- finished.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
- @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.\r
-\r
-**/\r
-EFI_STATUS\r
-SockSend (\r
- IN SOCKET *Sock,\r
- IN VOID *Token\r
- )\r
-{\r
- SOCK_IO_TOKEN *SndToken;\r
- EFI_EVENT Event;\r
- UINT32 FreeSpace;\r
- EFI_TCP4_TRANSMIT_DATA *TxData;\r
- EFI_STATUS Status;\r
- SOCK_TOKEN *SockToken;\r
- UINT32 DataLen;\r
-\r
- ASSERT (SockStream == Sock->Type);\r
-\r
- Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockSend: Get the access for socket"\r
- " failed with %r", Status));\r
-\r
- return EFI_ACCESS_DENIED;\r
- }\r
-\r
- if (SOCK_IS_NO_MAPPING (Sock)) {\r
- Status = EFI_NO_MAPPING;\r
- goto Exit;\r
- }\r
-\r
- SndToken = (SOCK_IO_TOKEN *) Token;\r
- TxData = (EFI_TCP4_TRANSMIT_DATA *) SndToken->Packet.TxData;\r
-\r
- if (SOCK_IS_UNCONFIGURED (Sock)) {\r
- Status = EFI_NOT_STARTED;\r
- goto Exit;\r
- }\r
-\r
- if (!(SOCK_IS_CONNECTING (Sock) || SOCK_IS_CONNECTED (Sock))) {\r
-\r
- Status = EFI_ACCESS_DENIED;\r
- goto Exit;\r
- }\r
-\r
- //\r
- // check if a token is already in the token buffer\r
- //\r
- Event = SndToken->Token.Event;\r
-\r
- if (SockTokenExisted (Sock, Event)) {\r
- Status = EFI_ACCESS_DENIED;\r
- goto Exit;\r
- }\r
-\r
- DataLen = (UINT32) TxData->DataLength;\r
-\r
- //\r
- // process this sending token now or buffer it only?\r
- //\r
- FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);\r
-\r
- if ((FreeSpace < Sock->SndBuffer.LowWater) || !SOCK_IS_CONNECTED (Sock)) {\r
-\r
- SockToken = SockBufferToken (\r
- Sock,\r
- &Sock->SndTokenList,\r
- SndToken,\r
- DataLen\r
- );\r
-\r
- if (NULL == SockToken) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- }\r
- } else {\r
-\r
- SockToken = SockBufferToken (\r
- Sock,\r
- &Sock->ProcessingSndTokenList,\r
- SndToken,\r
- DataLen\r
- );\r
-\r
- if (NULL == SockToken) {\r
- DEBUG ((EFI_D_ERROR, "SockSend: Failed to buffer IO token into"\r
- " socket processing SndToken List\n", Status));\r
-\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Exit;\r
- }\r
-\r
- Status = SockProcessTcpSndData (Sock, TxData);\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "SockSend: Failed to process "\r
- "Snd Data\n", Status));\r
-\r
- RemoveEntryList (&(SockToken->TokenList));\r
- FreePool (SockToken);\r
- }\r
- }\r
-\r
-Exit:\r
- EfiReleaseLock (&(Sock->Lock));\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Issue a token to get data from the socket.\r
-\r
- @param Sock Pointer to the socket to get data from.\r
- @param Token The token to store the received data from the\r
- socket.\r
-\r
- @retval EFI_SUCCESS The token is processed successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
- socket is closed, or the socket is not in a\r
- synchronized state , or the token is already in one\r
- of this socket's lists.\r
- @retval EFI_NO_MAPPING The IP address configuration operation is not\r
- finished.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
- @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.\r
- @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.\r
-\r
-**/\r
-EFI_STATUS\r
-SockRcv (\r
- IN SOCKET *Sock,\r
- IN VOID *Token\r
- )\r
-{\r
- SOCK_IO_TOKEN *RcvToken;\r
- UINT32 RcvdBytes;\r
- EFI_STATUS Status;\r
- EFI_EVENT Event;\r
-\r
- ASSERT (SockStream == Sock->Type);\r
-\r
- Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockRcv: Get the access for socket"\r
- " failed with %r", Status));\r
-\r
- return EFI_ACCESS_DENIED;\r
- }\r
-\r
- if (SOCK_IS_NO_MAPPING (Sock)) {\r
-\r
- Status = EFI_NO_MAPPING;\r
- goto Exit;\r
- }\r
-\r
- if (SOCK_IS_UNCONFIGURED (Sock)) {\r
-\r
- Status = EFI_NOT_STARTED;\r
- goto Exit;\r
- }\r
-\r
- if (!(SOCK_IS_CONNECTED (Sock) || SOCK_IS_CONNECTING (Sock))) {\r
-\r
- Status = EFI_ACCESS_DENIED;\r
- goto Exit;\r
- }\r
-\r
- RcvToken = (SOCK_IO_TOKEN *) Token;\r
-\r
- //\r
- // check if a token is already in the token buffer of this socket\r
- //\r
- Event = RcvToken->Token.Event;\r
- if (SockTokenExisted (Sock, Event)) {\r
- Status = EFI_ACCESS_DENIED;\r
- goto Exit;\r
- }\r
-\r
- RcvToken = (SOCK_IO_TOKEN *) Token;\r
- RcvdBytes = GET_RCV_DATASIZE (Sock);\r
-\r
- //\r
- // check whether an error has happened before\r
- //\r
- if (EFI_ABORTED != Sock->SockError) {\r
-\r
- SIGNAL_TOKEN (&(RcvToken->Token), Sock->SockError);\r
- Sock->SockError = EFI_ABORTED;\r
- goto Exit;\r
- }\r
-\r
- //\r
- // check whether can not receive and there is no any\r
- // data buffered in Sock->RcvBuffer\r
- //\r
- if (SOCK_IS_NO_MORE_DATA (Sock) && (0 == RcvdBytes)) {\r
-\r
- Status = EFI_CONNECTION_FIN;\r
- goto Exit;\r
- }\r
-\r
- if (RcvdBytes != 0) {\r
- SockProcessRcvToken (Sock, RcvToken);\r
-\r
- Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);\r
- } else {\r
-\r
- if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- }\r
- }\r
-\r
-Exit:\r
- EfiReleaseLock (&(Sock->Lock));\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Reset the socket and its associated protocol control block.\r
-\r
- @param Sock Pointer to the socket to be flushed.\r
-\r
- @retval EFI_SUCCESS The socket is flushed successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
-\r
-**/\r
-EFI_STATUS\r
-SockFlush (\r
- IN SOCKET *Sock\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- ASSERT (SockStream == Sock->Type);\r
-\r
- Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockFlush: Get the access for socket"\r
- " failed with %r", Status));\r
-\r
- return EFI_ACCESS_DENIED;\r
- }\r
-\r
- if (!SOCK_IS_CONFIGURED (Sock)) {\r
- goto Exit;\r
- }\r
-\r
- Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "SockFlush: Protocol failed handling"\r
- " SOCK_FLUSH with %r", Status));\r
-\r
- goto Exit;\r
- }\r
-\r
- SOCK_ERROR (Sock, EFI_ABORTED);\r
- SockConnFlush (Sock);\r
- SockSetState (Sock, SO_CLOSED);\r
-\r
- Sock->ConfigureState = SO_UNCONFIGURED;\r
-\r
-Exit:\r
- EfiReleaseLock (&(Sock->Lock));\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Close or abort the socket associated connection.\r
-\r
- @param Sock Pointer to the socket of the connection to close or\r
- abort.\r
- @param Token The token for close operation.\r
- @param OnAbort TRUE for aborting the connection, FALSE to close it.\r
-\r
- @retval EFI_SUCCESS The close or abort operation is initialized\r
- successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
- socket is closed, or the socket is not in a\r
- synchronized state , or the token is already in one\r
- of this socket's lists.\r
- @retval EFI_NO_MAPPING The IP address configuration operation is not\r
- finished.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
-\r
-**/\r
-EFI_STATUS\r
-SockClose (\r
- IN SOCKET *Sock,\r
- IN VOID *Token,\r
- IN BOOLEAN OnAbort\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_EVENT Event;\r
-\r
- ASSERT (SockStream == Sock->Type);\r
-\r
- Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "SockClose: Get the access for socket"\r
- " failed with %r", Status));\r
-\r
- return EFI_ACCESS_DENIED;\r
- }\r
-\r
- if (SOCK_IS_NO_MAPPING (Sock)) {\r
- Status = EFI_NO_MAPPING;\r
- goto Exit;\r
- }\r
-\r
- if (SOCK_IS_UNCONFIGURED (Sock)) {\r
- Status = EFI_NOT_STARTED;\r
- goto Exit;\r
- }\r
-\r
- if (SOCK_IS_DISCONNECTING (Sock)) {\r
- Status = EFI_ACCESS_DENIED;\r
- goto Exit;\r
- }\r
-\r
- Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;\r
-\r
- if (SockTokenExisted (Sock, Event)) {\r
- Status = EFI_ACCESS_DENIED;\r
- goto Exit;\r
- }\r
-\r
- Sock->CloseToken = Token;\r
- SockSetState (Sock, SO_DISCONNECTING);\r
-\r
- if (OnAbort) {\r
- Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);\r
- } else {\r
- Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);\r
- }\r
-\r
-Exit:\r
- EfiReleaseLock (&(Sock->Lock));\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Get the mode data of the low layer protocol.\r
-\r
- @param Sock Pointer to the socket to get mode data from.\r
- @param Mode Pointer to the data to store the low layer mode\r
- information.\r
-\r
- @retval EFI_SUCCESS The mode data is got successfully.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
-\r
-**/\r
-EFI_STATUS\r
-SockGetMode (\r
- IN SOCKET *Sock,\r
- IN OUT VOID *Mode\r
- )\r
-{\r
- return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);\r
-}\r
-\r
-\r
-\r
-\r
-\r
-/**\r
- Add or remove route information in IP route table associated\r
- with this socket.\r
-\r
- @param Sock Pointer to the socket associated with the IP route\r
- table to operate on.\r
- @param RouteInfo Pointer to the route information to be processed.\r
-\r
- @retval EFI_SUCCESS The route table is updated successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
- @retval EFI_NO_MAPPING The IP address configuration operation is not\r
- finished.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
-\r
-**/\r
-EFI_STATUS\r
-SockRoute (\r
- IN SOCKET *Sock,\r
- IN VOID *RouteInfo\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "SockRoute: Get the access for socket"\r
- " failed with %r", Status));\r
-\r
- return EFI_ACCESS_DENIED;\r
- }\r
-\r
- if (SOCK_IS_NO_MAPPING (Sock)) {\r
- Status = EFI_NO_MAPPING;\r
- goto Exit;\r
- }\r
-\r
- if (SOCK_IS_UNCONFIGURED (Sock)) {\r
- Status = EFI_NOT_STARTED;\r
- goto Exit;\r
- }\r
-\r
- Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);\r
-\r
-Exit:\r
- EfiReleaseLock (&(Sock->Lock));\r
- return Status;\r
-}\r
+++ /dev/null
-/** @file\r
- Socket header file.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#ifndef _SOCKET_H_\r
-#define _SOCKET_H_\r
-\r
-#include <Uefi.h>\r
-\r
-#include <Protocol/Ip4.h>\r
-#include <Protocol/Tcp4.h>\r
-#include <Protocol/Udp4.h>\r
-\r
-#include <Library/NetLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiDriverEntryPoint.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/DpcLib.h>\r
-#include <Library/PrintLib.h>\r
-\r
-#define SOCK_SND_BUF 0\r
-#define SOCK_RCV_BUF 1\r
-\r
-#define SOCK_BUFF_LOW_WATER (2 * 1024)\r
-#define SOCK_RCV_BUFF_SIZE (8 * 1024)\r
-#define SOCK_SND_BUFF_SIZE (8 * 1024)\r
-#define SOCK_BACKLOG 5\r
-\r
-#define PROTO_RESERVED_LEN 20\r
-\r
-#define SO_NO_MORE_DATA 0x0001\r
-\r
-//\r
-//\r
-//\r
-// When a socket is created it enters into SO_UNCONFIGURED,\r
-// no actions can be taken on this socket, only after calling\r
-// SockConfigure. The state transition diagram of socket is\r
-// as following:\r
-//\r
-// SO_UNCONFIGURED --- SO_CONFIGURED --- SO_CONNECTING\r
-// ^ | |\r
-// | ---> SO_LISTENING |\r
-// | |\r
-// |------------------SO_DISCONNECTING<-- SO_CONNECTED\r
-//\r
-// A passive socket can only go into SO_LISTENING and\r
-// SO_UNCONFIGURED state. SO_XXXING state is a middle state\r
-// when a socket is undergoing a protocol procedure such\r
-// as requesting a TCP connection.\r
-//\r
-//\r
-//\r
-\r
-///\r
-/// Socket state\r
-///\r
-#define SO_CLOSED 0\r
-#define SO_LISTENING 1\r
-#define SO_CONNECTING 2\r
-#define SO_CONNECTED 3\r
-#define SO_DISCONNECTING 4\r
-\r
-///\r
-/// Socket configure state\r
-///\r
-#define SO_UNCONFIGURED 0\r
-#define SO_CONFIGURED_ACTIVE 1\r
-#define SO_CONFIGURED_PASSIVE 2\r
-#define SO_NO_MAPPING 3\r
-\r
-/**\r
- Set socket SO_NO_MORE_DATA flag.\r
-\r
- @param Sock Pointer to the socket\r
-\r
-**/\r
-#define SOCK_NO_MORE_DATA(Sock) ((Sock)->Flag |= SO_NO_MORE_DATA)\r
-\r
-/**\r
- Check whether the socket is unconfigured.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @retval True The socket is unconfigued\r
- @retval False The socket is not unconfigued\r
-\r
-**/\r
-#define SOCK_IS_UNCONFIGURED(Sock) ((Sock)->ConfigureState == SO_UNCONFIGURED)\r
-\r
-/**\r
- Check whether the socket is configured.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @retval True The socket is configued\r
- @retval False The socket is not configued\r
-\r
-**/\r
-#define SOCK_IS_CONFIGURED(Sock) \\r
- (((Sock)->ConfigureState == SO_CONFIGURED_ACTIVE) || \\r
- ((Sock)->ConfigureState == SO_CONFIGURED_PASSIVE))\r
-\r
-/**\r
- Check whether the socket is configured to active mode.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @retval True The socket is configued to active mode\r
- @retval False The socket is not configued to active mode\r
-\r
-**/\r
-#define SOCK_IS_CONFIGURED_ACTIVE(Sock) \\r
- ((Sock)->ConfigureState == SO_CONFIGURED_ACTIVE)\r
-\r
-/**\r
- Check whether the socket is configured to passive mode.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @retval True The socket is configued to passive mode\r
- @retval False The socket is not configued to passive mode\r
-\r
-**/\r
-#define SOCK_IS_CONNECTED_PASSIVE(Sock) \\r
- ((Sock)->ConfigureState == SO_CONFIGURED_PASSIVE)\r
-\r
-/**\r
- Check whether the socket is mapped.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @retval True The socket is no mapping\r
- @retval False The socket is mapped\r
-\r
-**/\r
-#define SOCK_IS_NO_MAPPING(Sock) \\r
- ((Sock)->ConfigureState == SO_NO_MAPPING)\r
-\r
-/**\r
- Check whether the socket is closed.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @retval True The socket is closed\r
- @retval False The socket is not closed\r
-\r
-**/\r
-#define SOCK_IS_CLOSED(Sock) ((Sock)->State == SO_CLOSED)\r
-\r
-/**\r
- Check whether the socket is listening.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @retval True The socket is listening\r
- @retval False The socket is not listening\r
-\r
-**/\r
-#define SOCK_IS_LISTENING(Sock) ((Sock)->State == SO_LISTENING)\r
-\r
-/**\r
- Check whether the socket is connecting.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @retval True The socket is connecting\r
- @retval False The socket is not connecting\r
-\r
-**/\r
-#define SOCK_IS_CONNECTING(Sock) ((Sock)->State == SO_CONNECTING)\r
-\r
-/**\r
- Check whether the socket has connected.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @retval True The socket has connected\r
- @retval False The socket has not connected\r
-\r
-**/\r
-#define SOCK_IS_CONNECTED(Sock) ((Sock)->State == SO_CONNECTED)\r
-\r
-/**\r
- Check whether the socket is disconnecting.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @retval True The socket is disconnecting\r
- @retval False The socket is not disconnecting\r
-\r
-**/\r
-#define SOCK_IS_DISCONNECTING(Sock) ((Sock)->State == SO_DISCONNECTING)\r
-\r
-/**\r
- Check whether the socket is no more data.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @retval True The socket is no more data\r
- @retval False The socket still has data\r
-\r
-**/\r
-#define SOCK_IS_NO_MORE_DATA(Sock) (0 != ((Sock)->Flag & SO_NO_MORE_DATA))\r
-\r
-/**\r
- Set the size of the receive buffer.\r
-\r
- @param Sock Pointer to the socket\r
- @param Size The size to set\r
-\r
-**/\r
-#define SET_RCV_BUFFSIZE(Sock, Size) ((Sock)->RcvBuffer.HighWater = (Size))\r
-\r
-/**\r
- Get the size of the receive buffer.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @return The receive buffer size\r
-\r
-**/\r
-#define GET_RCV_BUFFSIZE(Sock) ((Sock)->RcvBuffer.HighWater)\r
-\r
-/**\r
- Get the size of the receive data.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @return The received data size\r
-\r
-**/\r
-#define GET_RCV_DATASIZE(Sock) (((Sock)->RcvBuffer.DataQueue)->BufSize)\r
-\r
-/**\r
- Set the size of the send buffer.\r
-\r
- @param Sock Pointer to the socket\r
- @param Size The size to set\r
-\r
-**/\r
-#define SET_SND_BUFFSIZE(Sock, Size) ((Sock)->SndBuffer.HighWater = (Size))\r
-\r
-/**\r
- Get the size of the send buffer.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @return The send buffer size\r
-\r
-**/\r
-#define GET_SND_BUFFSIZE(Sock) ((Sock)->SndBuffer.HighWater)\r
-\r
-/**\r
- Get the size of the send data.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @return The send data size\r
-\r
-**/\r
-#define GET_SND_DATASIZE(Sock) (((Sock)->SndBuffer.DataQueue)->BufSize)\r
-\r
-/**\r
- Set the backlog value of the socket.\r
-\r
- @param Sock Pointer to the socket\r
- @param Value The value to set\r
-\r
-**/\r
-#define SET_BACKLOG(Sock, Value) ((Sock)->BackLog = (Value))\r
-\r
-/**\r
- Get the backlog value of the socket.\r
-\r
- @param Sock Pointer to the socket\r
-\r
- @return The backlog value\r
-\r
-**/\r
-#define GET_BACKLOG(Sock) ((Sock)->BackLog)\r
-\r
-/**\r
- Set the socket with error state.\r
-\r
- @param Sock Pointer to the socket\r
- @param Error The error state\r
-\r
-**/\r
-#define SOCK_ERROR(Sock, Error) ((Sock)->SockError = (Error))\r
-\r
-#define SND_BUF_HDR_LEN(Sock) \\r
- ((SockBufFirst (&((Sock)->SndBuffer)))->TotalSize)\r
-\r
-#define RCV_BUF_HDR_LEN(Sock) \\r
- ((SockBufFirst (&((Sock)->RcvBuffer)))->TotalSize)\r
-\r
-#define SOCK_SIGNATURE SIGNATURE_32 ('S', 'O', 'C', 'K')\r
-\r
-#define SOCK_FROM_THIS(a) CR ((a), SOCKET, NetProtocol, SOCK_SIGNATURE)\r
-\r
-#define SOCK_FROM_TOKEN(Token) (((SOCK_TOKEN *) (Token))->Sock)\r
-\r
-#define PROTO_TOKEN_FORM_SOCK(SockToken, Type) \\r
- ((Type *) (((SOCK_TOKEN *) (SockToken))->Token))\r
-\r
-typedef struct _SOCKET SOCKET;\r
-\r
-///\r
-/// Socket completion token\r
-///\r
-typedef struct _SOCK_COMPLETION_TOKEN {\r
- EFI_EVENT Event; ///< The event to be issued\r
- EFI_STATUS Status; ///< The status to be issued\r
-} SOCK_COMPLETION_TOKEN;\r
-\r
-typedef union {\r
- VOID *RxData;\r
- VOID *TxData;\r
-} SOCK_IO_DATA;\r
-\r
-///\r
-/// The application token with data packet\r
-///\r
-typedef struct _SOCK_IO_TOKEN {\r
- SOCK_COMPLETION_TOKEN Token;\r
- SOCK_IO_DATA Packet;\r
-} SOCK_IO_TOKEN;\r
-\r
-///\r
-/// The request issued from socket layer to protocol layer.\r
-///\r
-#define SOCK_ATTACH 0 ///< Attach current socket to a new PCB\r
-#define SOCK_DETACH 1 ///< Detach current socket from the PCB\r
-#define SOCK_CONFIGURE 2 ///< Configure attached PCB\r
-#define SOCK_FLUSH 3 ///< Flush attached PCB\r
-#define SOCK_SND 4 ///< Need protocol to send something\r
-#define SOCK_SNDPUSH 5 ///< Need protocol to send pushed data\r
-#define SOCK_SNDURG 6 ///< Need protocol to send urgent data\r
-#define SOCK_CONSUMED 7 ///< Application has retrieved data from socket\r
-#define SOCK_CONNECT 8 ///< Need to connect to a peer\r
-#define SOCK_CLOSE 9 ///< Need to close the protocol process\r
-#define SOCK_ABORT 10 ///< Need to reset the protocol process\r
-#define SOCK_POLL 11 ///< Need to poll to the protocol layer\r
-#define SOCK_ROUTE 12 ///< Need to add a route information\r
-#define SOCK_MODE 13 ///< Need to get the mode data of the protocol\r
-#define SOCK_GROUP 14 ///< Need to join a mcast group\r
-\r
-///\r
-/// The socket type.\r
-///\r
-typedef enum {\r
- SockDgram, ///< This socket providing datagram service\r
- SockStream ///< This socket providing stream service\r
-} SOCK_TYPE;\r
-\r
-///\r
-/// The buffer structure of rcvd data and send data used by socket.\r
-///\r
-typedef struct _SOCK_BUFFER {\r
- UINT32 HighWater; ///< The buffersize upper limit of sock_buffer\r
- UINT32 LowWater; ///< The low water mark of sock_buffer\r
- NET_BUF_QUEUE *DataQueue; ///< The queue to buffer data\r
-} SOCK_BUFFER;\r
-\r
-/**\r
- The handler of protocol for request from socket.\r
-\r
- @param Socket The socket issuing the request to protocol\r
- @param Request The request issued by socket\r
- @param RequestData The request related data\r
-\r
- @retval EFI_SUCCESS The socket request is completed successfully.\r
- @retval other The error status returned by the corresponding TCP\r
- layer function.\r
-\r
-**/\r
-typedef\r
-EFI_STATUS\r
-(*SOCK_PROTO_HANDLER) (\r
- IN SOCKET *Socket,\r
- IN UINT8 Request,\r
- IN VOID *RequestData\r
- );\r
-\r
-\r
-//\r
-// Socket provided oprerations for low layer protocol\r
-//\r
-\r
-//\r
-// Socket provided operations for user interface\r
-//\r
-\r
-/**\r
- Set the state of the socket.\r
-\r
- @param Sock Pointer to the socket.\r
- @param State The new socket state to be set.\r
-\r
-**/\r
-VOID\r
-SockSetState (\r
- IN OUT SOCKET *Sock,\r
- IN UINT8 State\r
- );\r
-\r
-/**\r
- Called by the low layer protocol to indicate the socket a connection is\r
- established.\r
-\r
- This function just changes the socket's state to SO_CONNECTED\r
- and signals the token used for connection establishment.\r
-\r
- @param Sock Pointer to the socket associated with the\r
- established connection.\r
-\r
-**/\r
-VOID\r
-SockConnEstablished (\r
- IN SOCKET *Sock\r
- );\r
-\r
-/**\r
- Called by the low layer protocol to indicate the connection is closed.\r
-\r
- This function flushes the socket, sets the state to SO_CLOSED and signals\r
- the close token.\r
-\r
- @param Sock Pointer to the socket associated with the closed\r
- connection.\r
-\r
-**/\r
-VOID\r
-SockConnClosed (\r
- IN OUT SOCKET *Sock\r
- );\r
-\r
-/**\r
- Called by low layer protocol to indicate that some data is sent or processed.\r
-\r
- This function trims the sent data in the socket send buffer, signals the data\r
- token if proper.\r
-\r
- @param Sock Pointer to the socket.\r
- @param Count The length of the data processed or sent, in bytes.\r
-\r
-**/\r
-VOID\r
-SockDataSent (\r
- IN SOCKET *Sock,\r
- IN UINT32 Count\r
- );\r
-\r
-/**\r
- Called by the low layer protocol to copy some data in socket send\r
- buffer starting from the specific offset to a buffer provided by\r
- the caller.\r
-\r
- @param Sock Pointer to the socket.\r
- @param Offset The start point of the data to be copied.\r
- @param Len The length of the data to be copied.\r
- @param Dest Pointer to the destination to copy the data.\r
-\r
- @return The data size copied.\r
-\r
-**/\r
-UINT32\r
-SockGetDataToSend (\r
- IN SOCKET *Sock,\r
- IN UINT32 Offset,\r
- IN UINT32 Len,\r
- IN UINT8 *Dest\r
- );\r
-\r
-/**\r
- Called by the low layer protocol to indicate that there\r
- will be no more data from the communication peer.\r
-\r
- This function set the socket's state to SO_NO_MORE_DATA and\r
- signal all queued IO tokens with the error status EFI_CONNECTION_FIN.\r
-\r
- @param Sock Pointer to the socket.\r
-\r
-**/\r
-VOID\r
-SockNoMoreData (\r
- IN OUT SOCKET *Sock\r
- );\r
-\r
-/**\r
- Called by the low layer protocol to deliver received data to socket layer.\r
-\r
- This function will append the data to the socket receive buffer, set ther\r
- urgent data length and then check if any receive token can be signaled.\r
-\r
- @param Sock Pointer to the socket.\r
- @param NetBuffer Pointer to the buffer that contains the received\r
- data.\r
- @param UrgLen The length of the urgent data in the received data.\r
-\r
-**/\r
-VOID\r
-SockDataRcvd (\r
- IN SOCKET *Sock,\r
- IN OUT NET_BUF *NetBuffer,\r
- IN UINT32 UrgLen\r
- );\r
-\r
-/**\r
- Get the length of the free space of the specific socket buffer.\r
-\r
- @param Sock Pointer to the socket.\r
- @param Which Flag to indicate which socket buffer to check,\r
- either send buffer or receive buffer.\r
-\r
- @return The length of the free space, in bytes.\r
-\r
-**/\r
-UINT32\r
-SockGetFreeSpace (\r
- IN SOCKET *Sock,\r
- IN UINT32 Which\r
- );\r
-\r
-/**\r
- Clone a new socket including its associated protocol control block.\r
-\r
- @param Sock Pointer to the socket to be cloned.\r
-\r
- @return Pointer to the newly cloned socket. If NULL, error condition occurred.\r
-\r
-**/\r
-SOCKET *\r
-SockClone (\r
- IN SOCKET *Sock\r
- );\r
-\r
-\r
-///\r
-/// Proto type of the create callback\r
-///\r
-typedef\r
-EFI_STATUS\r
-(*SOCK_CREATE_CALLBACK) (\r
- IN SOCKET *This,\r
- IN VOID *Context\r
- );\r
-\r
-///\r
-/// Proto type of the destroy callback\r
-///\r
-typedef\r
-VOID\r
-(*SOCK_DESTROY_CALLBACK) (\r
- IN SOCKET *This,\r
- IN VOID *Context\r
- );\r
-\r
-///\r
-/// The initialize data for create a new socket.\r
-///\r
-typedef struct _SOCK_INIT_DATA {\r
- SOCK_TYPE Type;\r
- UINT8 State;\r
-\r
- SOCKET *Parent; ///< The parent of this socket\r
- UINT32 BackLog; ///< The connection limit for listening socket\r
- UINT32 SndBufferSize; ///< The high water mark of send buffer\r
- UINT32 RcvBufferSize; ///< The high water mark of receive buffer\r
- VOID *Protocol; ///< The pointer to protocol function template\r
- ///< wanted to install on socket\r
-\r
- //\r
- // Callbacks after socket is created and before socket is to be destroyed.\r
- //\r
- SOCK_CREATE_CALLBACK CreateCallback; ///< Callback after created\r
- SOCK_DESTROY_CALLBACK DestroyCallback; ///< Callback before destroied\r
- VOID *Context; ///< The context of the callback\r
-\r
- //\r
- // Opaque protocol data.\r
- //\r
- VOID *ProtoData;\r
- UINT32 DataSize;\r
-\r
- SOCK_PROTO_HANDLER ProtoHandler; ///< The handler of protocol for socket request\r
-\r
- EFI_HANDLE DriverBinding; ///< The driver binding handle\r
-} SOCK_INIT_DATA;\r
-\r
-///\r
-/// The union type of TCP and UDP protocol.\r
-///\r
-typedef union _NET_PROTOCOL {\r
- EFI_TCP4_PROTOCOL TcpProtocol; ///< Tcp protocol\r
- EFI_UDP4_PROTOCOL UdpProtocol; ///< Udp protocol\r
-} NET_PROTOCOL;\r
-\r
-///\r
-/// The socket structure representing a network service access point\r
-///\r
-struct _SOCKET {\r
-\r
- //\r
- // Socket description information\r
- //\r
- UINT32 Signature; ///< Signature of the socket\r
- EFI_HANDLE SockHandle; ///< The virtual handle of the socket\r
- EFI_HANDLE DriverBinding; ///< Socket's driver binding protocol\r
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- LIST_ENTRY Link;\r
- UINT8 ConfigureState;\r
- SOCK_TYPE Type;\r
- UINT8 State;\r
- UINT16 Flag;\r
- EFI_LOCK Lock; ///< The lock of socket\r
- SOCK_BUFFER SndBuffer; ///< Send buffer of application's data\r
- SOCK_BUFFER RcvBuffer; ///< Receive buffer of received data\r
- EFI_STATUS SockError; ///< The error returned by low layer protocol\r
- BOOLEAN InDestroy;\r
-\r
- //\r
- // Fields used to manage the connection request\r
- //\r
- UINT32 BackLog; ///< the limit of connection to this socket\r
- UINT32 ConnCnt; ///< the current count of connections to it\r
- SOCKET *Parent; ///< listening parent that accept the connection\r
- LIST_ENTRY ConnectionList; ///< the connections maintained by this socket\r
-\r
- //\r
- // The queue to buffer application's asynchronous token\r
- //\r
- LIST_ENTRY ListenTokenList;\r
- LIST_ENTRY RcvTokenList;\r
- LIST_ENTRY SndTokenList;\r
- LIST_ENTRY ProcessingSndTokenList;\r
-\r
- SOCK_COMPLETION_TOKEN *ConnectionToken; ///< app's token to signal if connected\r
- SOCK_COMPLETION_TOKEN *CloseToken; ///< app's token to signal if closed\r
-\r
- //\r
- // Interface for low level protocol\r
- //\r
- SOCK_PROTO_HANDLER ProtoHandler; ///< The request handler of protocol\r
- UINT8 ProtoReserved[PROTO_RESERVED_LEN]; ///< Data fields reserved for protocol\r
- NET_PROTOCOL NetProtocol; ///< TCP or UDP protocol socket used\r
-\r
- //\r
- // Callbacks after socket is created and before socket is to be destroyed.\r
- //\r
- SOCK_CREATE_CALLBACK CreateCallback; ///< Callback after created\r
- SOCK_DESTROY_CALLBACK DestroyCallback; ///< Callback before destroied\r
- VOID *Context; ///< The context of the callback\r
-};\r
-\r
-///\r
-/// The token structure buffered in socket layer.\r
-///\r
-typedef struct _SOCK_TOKEN {\r
- LIST_ENTRY TokenList; ///< The entry to add in the token list\r
- SOCK_COMPLETION_TOKEN *Token; ///< The application's token\r
- UINT32 RemainDataLen; ///< Unprocessed data length\r
- SOCKET *Sock; ///< The poninter to the socket this token\r
- ///< belongs to\r
-} SOCK_TOKEN;\r
-\r
-///\r
-/// Reserved data to access the NET_BUF delivered by UDP driver.\r
-///\r
-typedef struct _UDP_RSV_DATA {\r
- EFI_TIME TimeStamp;\r
- EFI_UDP4_SESSION_DATA Session;\r
-} UDP_RSV_DATA;\r
-\r
-///\r
-/// Reserved data to access the NET_BUF delivered by TCP driver.\r
-///\r
-typedef struct _TCP_RSV_DATA {\r
- UINT32 UrgLen;\r
-} TCP_RSV_DATA;\r
-\r
-/**\r
- Create a socket and its associated protocol control block\r
- with the intial data SockInitData and protocol specific\r
- data ProtoData.\r
-\r
- @param SockInitData Inital data to setting the socket.\r
-\r
- @return Pointer to the newly created socket. If NULL, error condition occured.\r
-\r
-**/\r
-SOCKET *\r
-SockCreateChild (\r
- IN SOCK_INIT_DATA *SockInitData\r
- );\r
-\r
-/**\r
- Destroy the socket Sock and its associated protocol control block.\r
-\r
- @param Sock The socket to be destroyed.\r
-\r
- @retval EFI_SUCCESS The socket Sock is destroyed successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
-\r
-**/\r
-EFI_STATUS\r
-SockDestroyChild (\r
- IN SOCKET *Sock\r
- );\r
-\r
-/**\r
- Configure the specific socket Sock using configuration data ConfigData.\r
-\r
- @param Sock Pointer to the socket to be configured.\r
- @param ConfigData Pointer to the configuration data.\r
-\r
- @retval EFI_SUCCESS The socket is configured successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the\r
- socket is already configured.\r
-\r
-**/\r
-EFI_STATUS\r
-SockConfigure (\r
- IN SOCKET *Sock,\r
- IN VOID *ConfigData\r
- );\r
-\r
-/**\r
- Initiate a connection establishment process.\r
-\r
- @param Sock Pointer to the socket to initiate the initate the\r
- connection.\r
- @param Token Pointer to the token used for the connection\r
- operation.\r
-\r
- @retval EFI_SUCCESS The connection is initialized successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
- socket is closed, or the socket is not configured to\r
- be an active one, or the token is already in one of\r
- this socket's lists.\r
- @retval EFI_NO_MAPPING The IP address configuration operation is not\r
- finished.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
-\r
-**/\r
-EFI_STATUS\r
-SockConnect (\r
- IN SOCKET *Sock,\r
- IN VOID *Token\r
- );\r
-\r
-/**\r
- Issue a listen token to get an existed connected network instance\r
- or wait for a connection if there is none.\r
-\r
- @param Sock Pointer to the socket to accept connections.\r
- @param Token The token to accept a connection.\r
-\r
- @retval EFI_SUCCESS Either a connection is accpeted or the Token is\r
- buffered for further acception.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
- socket is closed, or the socket is not configured to\r
- be a passive one, or the token is already in one of\r
- this socket's lists.\r
- @retval EFI_NO_MAPPING The IP address configuration operation is not\r
- finished.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
- @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.\r
-\r
-**/\r
-EFI_STATUS\r
-SockAccept (\r
- IN SOCKET *Sock,\r
- IN VOID *Token\r
- );\r
-\r
-/**\r
- Issue a token with data to the socket to send out.\r
-\r
- @param Sock Pointer to the socket to process the token with\r
- data.\r
- @param Token The token with data that needs to send out.\r
-\r
- @retval EFI_SUCCESS The token is processed successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
- socket is closed, or the socket is not in a\r
- synchronized state , or the token is already in one\r
- of this socket's lists.\r
- @retval EFI_NO_MAPPING The IP address configuration operation is not\r
- finished.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
- @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.\r
-\r
-**/\r
-EFI_STATUS\r
-SockSend (\r
- IN SOCKET *Sock,\r
- IN VOID *Token\r
- );\r
-\r
-/**\r
- Issue a token to get data from the socket.\r
-\r
- @param Sock Pointer to the socket to get data from.\r
- @param Token The token to store the received data from the\r
- socket.\r
-\r
- @retval EFI_SUCCESS The token is processed successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
- socket is closed, or the socket is not in a\r
- synchronized state , or the token is already in one\r
- of this socket's lists.\r
- @retval EFI_NO_MAPPING The IP address configuration operation is not\r
- finished.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
- @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.\r
- @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.\r
-\r
-**/\r
-EFI_STATUS\r
-SockRcv (\r
- IN SOCKET *Sock,\r
- IN VOID *Token\r
- );\r
-\r
-/**\r
- Reset the socket and its associated protocol control block.\r
-\r
- @param Sock Pointer to the socket to be flushed.\r
-\r
- @retval EFI_SUCCESS The socket is flushed successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
-\r
-**/\r
-EFI_STATUS\r
-SockFlush (\r
- IN SOCKET *Sock\r
- );\r
-\r
-/**\r
- Close or abort the socket associated connection.\r
-\r
- @param Sock Pointer to the socket of the connection to close or\r
- abort.\r
- @param Token The token for close operation.\r
- @param OnAbort TRUE for aborting the connection, FALSE to close it.\r
-\r
- @retval EFI_SUCCESS The close or abort operation is initialized\r
- successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
- socket is closed, or the socket is not in a\r
- synchronized state , or the token is already in one\r
- of this socket's lists.\r
- @retval EFI_NO_MAPPING The IP address configuration operation is not\r
- finished.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
-\r
-**/\r
-EFI_STATUS\r
-SockClose (\r
- IN SOCKET *Sock,\r
- IN VOID *Token,\r
- IN BOOLEAN OnAbort\r
- );\r
-\r
-/**\r
- Get the mode data of the low layer protocol.\r
-\r
- @param Sock Pointer to the socket to get mode data from.\r
- @param Mode Pointer to the data to store the low layer mode\r
- information.\r
-\r
- @retval EFI_SUCCESS The mode data is got successfully.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
-\r
-**/\r
-EFI_STATUS\r
-SockGetMode (\r
- IN SOCKET *Sock,\r
- IN OUT VOID *Mode\r
- );\r
-\r
-/**\r
- Add or remove route information in IP route table associated\r
- with this socket.\r
-\r
- @param Sock Pointer to the socket associated with the IP route\r
- table to operate on.\r
- @param RouteInfo Pointer to the route information to be processed.\r
-\r
- @retval EFI_SUCCESS The route table is updated successfully.\r
- @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
- @retval EFI_NO_MAPPING The IP address configuration operation is not\r
- finished.\r
- @retval EFI_NOT_STARTED The socket is not configured.\r
-\r
-**/\r
-EFI_STATUS\r
-SockRoute (\r
- IN SOCKET *Sock,\r
- IN VOID *RouteInfo\r
- );\r
-\r
-//\r
-// Supporting function to operate on socket buffer\r
-//\r
-\r
-/**\r
- Get the first buffer block in the specific socket buffer.\r
-\r
- @param Sockbuf Pointer to the socket buffer.\r
-\r
- @return Pointer to the first buffer in the queue. NULL if the queue is empty.\r
-\r
-**/\r
-NET_BUF *\r
-SockBufFirst (\r
- IN SOCK_BUFFER *Sockbuf\r
- );\r
-\r
-/**\r
- Get the next buffer block in the specific socket buffer.\r
-\r
- @param Sockbuf Pointer to the socket buffer.\r
- @param SockEntry Pointer to the buffer block prior to the required\r
- one.\r
-\r
- @return Pointer to the buffer block next to SockEntry. NULL if SockEntry is\r
- the tail or head entry.\r
-\r
-**/\r
-NET_BUF *\r
-SockBufNext (\r
- IN SOCK_BUFFER *Sockbuf,\r
- IN NET_BUF *SockEntry\r
- );\r
-\r
-#endif\r
+++ /dev/null
-/** @file\r
- Tcp request dispatcher implementation.\r
-\r
-(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Tcp4Main.h"\r
-\r
-#define TCP_COMP_VAL(Min, Max, Default, Val) \\r
- ((((Val) <= (Max)) && ((Val) >= (Min))) ? (Val) : (Default))\r
-\r
-/**\r
- Add or remove a route entry in the IP route table associated with this TCP instance.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param RouteInfo Pointer to the route info to be processed.\r
-\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval EFI_NOT_STARTED The driver instance has not been started.\r
- @retval EFI_NO_MAPPING When using the default address, configuration(DHCP,\r
- BOOTP, RARP, etc.) is not finished yet.\r
- @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.\r
- @retval EFI_NOT_FOUND This route is not in the routing table\r
- (when RouteInfo->DeleteRoute is TRUE).\r
- @retval EFI_ACCESS_DENIED The route is already defined in the routing table\r
- (when RouteInfo->DeleteRoute is FALSE).\r
-**/\r
-EFI_STATUS\r
-Tcp4Route (\r
- IN TCP_CB *Tcb,\r
- IN TCP4_ROUTE_INFO *RouteInfo\r
- )\r
-{\r
- EFI_IP4_PROTOCOL *Ip4;\r
-\r
- Ip4 = Tcb->IpInfo->Ip.Ip4;\r
-\r
- ASSERT (Ip4 != NULL);\r
-\r
- return Ip4->Routes (\r
- Ip4,\r
- RouteInfo->DeleteRoute,\r
- RouteInfo->SubnetAddress,\r
- RouteInfo->SubnetMask,\r
- RouteInfo->GatewayAddress\r
- );\r
-\r
-}\r
-\r
-\r
-/**\r
- Get the operational settings of this TCP instance.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Mode Pointer to the buffer to store the operational\r
- settings.\r
-\r
- @retval EFI_SUCCESS The mode data is read.\r
- @retval EFI_NOT_STARTED No configuration data is available because this\r
- instance hasn't been started.\r
-\r
-**/\r
-EFI_STATUS\r
-Tcp4GetMode (\r
- IN TCP_CB *Tcb,\r
- IN OUT TCP4_MODE_DATA *Mode\r
- )\r
-{\r
- SOCKET *Sock;\r
- EFI_TCP4_CONFIG_DATA *ConfigData;\r
- EFI_TCP4_ACCESS_POINT *AccessPoint;\r
- EFI_TCP4_OPTION *Option;\r
- EFI_IP4_PROTOCOL *Ip;\r
-\r
- Sock = Tcb->Sk;\r
-\r
- if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp4ConfigData != NULL)) {\r
- return EFI_NOT_STARTED;\r
- }\r
-\r
- if (Mode->Tcp4State != NULL) {\r
- *(Mode->Tcp4State) = (EFI_TCP4_CONNECTION_STATE) Tcb->State;\r
- }\r
-\r
- if (Mode->Tcp4ConfigData != NULL) {\r
-\r
- ConfigData = Mode->Tcp4ConfigData;\r
- AccessPoint = &(ConfigData->AccessPoint);\r
- Option = ConfigData->ControlOption;\r
-\r
- ConfigData->TypeOfService = Tcb->Tos;\r
- ConfigData->TimeToLive = Tcb->Ttl;\r
-\r
- AccessPoint->UseDefaultAddress = Tcb->UseDefaultAddr;\r
-\r
- IP4_COPY_ADDRESS (&AccessPoint->StationAddress, &Tcb->LocalEnd.Ip);\r
- IP4_COPY_ADDRESS (&AccessPoint->SubnetMask, &Tcb->SubnetMask);\r
- AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port);\r
-\r
- IP4_COPY_ADDRESS (&AccessPoint->RemoteAddress, &Tcb->RemoteEnd.Ip);\r
- AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port);\r
- AccessPoint->ActiveFlag = (BOOLEAN) (Tcb->State != TCP_LISTEN);\r
-\r
- if (Option != NULL) {\r
- Option->ReceiveBufferSize = GET_RCV_BUFFSIZE (Tcb->Sk);\r
- Option->SendBufferSize = GET_SND_BUFFSIZE (Tcb->Sk);\r
- Option->MaxSynBackLog = GET_BACKLOG (Tcb->Sk);\r
-\r
- Option->ConnectionTimeout = Tcb->ConnectTimeout / TCP_TICK_HZ;\r
- Option->DataRetries = Tcb->MaxRexmit;\r
- Option->FinTimeout = Tcb->FinWait2Timeout / TCP_TICK_HZ;\r
- Option->TimeWaitTimeout = Tcb->TimeWaitTimeout / TCP_TICK_HZ;\r
- Option->KeepAliveProbes = Tcb->MaxKeepAlive;\r
- Option->KeepAliveTime = Tcb->KeepAliveIdle / TCP_TICK_HZ;\r
- Option->KeepAliveInterval = Tcb->KeepAlivePeriod / TCP_TICK_HZ;\r
-\r
- Option->EnableNagle = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE));\r
- Option->EnableTimeStamp = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS));\r
- Option->EnableWindowScaling = (BOOLEAN) (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS));\r
-\r
- Option->EnableSelectiveAck = FALSE;\r
- Option->EnablePathMtuDiscovery = FALSE;\r
- }\r
- }\r
-\r
- Ip = Tcb->IpInfo->Ip.Ip4;\r
- ASSERT (Ip != NULL);\r
-\r
- return Ip->GetModeData (Ip, Mode->Ip4ModeData, Mode->MnpConfigData, Mode->SnpModeData);\r
-}\r
-\r
-\r
-/**\r
- If AP->StationPort isn't zero, check whether the access point\r
- is registered, else generate a random station port for this\r
- access point.\r
-\r
- @param AP Pointer to the access point.\r
-\r
- @retval EFI_SUCCESS The check is passed or the port is assigned.\r
- @retval EFI_INVALID_PARAMETER The non-zero station port is already used.\r
- @retval EFI_OUT_OF_RESOURCES No port can be allocated.\r
-\r
-**/\r
-EFI_STATUS\r
-Tcp4Bind (\r
- IN EFI_TCP4_ACCESS_POINT *AP\r
- )\r
-{\r
- BOOLEAN Cycle;\r
-\r
- if (0 != AP->StationPort) {\r
- //\r
- // check if a same endpoint is bound\r
- //\r
- if (TcpFindTcbByPeer (&AP->StationAddress, AP->StationPort)) {\r
-\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- } else {\r
- //\r
- // generate a random port\r
- //\r
- Cycle = FALSE;\r
-\r
- if (TCP4_PORT_USER_RESERVED == mTcp4RandomPort) {\r
- mTcp4RandomPort = TCP4_PORT_KNOWN;\r
- }\r
-\r
- mTcp4RandomPort++;\r
-\r
- while (TcpFindTcbByPeer (&AP->StationAddress, mTcp4RandomPort)) {\r
-\r
- mTcp4RandomPort++;\r
-\r
- if (mTcp4RandomPort <= TCP4_PORT_KNOWN) {\r
-\r
- if (Cycle) {\r
- DEBUG ((EFI_D_ERROR, "Tcp4Bind: no port can be allocated "\r
- "for this pcb\n"));\r
-\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- mTcp4RandomPort = TCP4_PORT_KNOWN + 1;\r
-\r
- Cycle = TRUE;\r
- }\r
-\r
- }\r
-\r
- AP->StationPort = mTcp4RandomPort;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Flush the Tcb add its associated protocols.\r
-\r
- @param Tcb Pointer to the TCP_CB to be flushed.\r
-\r
-**/\r
-VOID\r
-Tcp4FlushPcb (\r
- IN TCP_CB *Tcb\r
- )\r
-{\r
- SOCKET *Sock;\r
-\r
- IpIoConfigIp (Tcb->IpInfo, NULL);\r
-\r
- Sock = Tcb->Sk;\r
-\r
- if (SOCK_IS_CONFIGURED (Sock)) {\r
- RemoveEntryList (&Tcb->List);\r
-\r
- //\r
- // Uninstall the device path protocol.\r
- //\r
- if (Sock->DevicePath != NULL) {\r
- gBS->UninstallProtocolInterface (\r
- Sock->SockHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- Sock->DevicePath\r
- );\r
- FreePool (Sock->DevicePath);\r
- }\r
- }\r
-\r
- NetbufFreeList (&Tcb->SndQue);\r
- NetbufFreeList (&Tcb->RcvQue);\r
- Tcb->State = TCP_CLOSED;\r
-}\r
-\r
-/**\r
- Attach a Pcb to the socket.\r
-\r
- @param Sk Pointer to the socket of this TCP instance.\r
-\r
- @retval EFI_SUCCESS The operation is completed successfully.\r
- @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
-\r
-**/\r
-EFI_STATUS\r
-Tcp4AttachPcb (\r
- IN SOCKET *Sk\r
- )\r
-{\r
- TCP_CB *Tcb;\r
- TCP4_PROTO_DATA *ProtoData;\r
- IP_IO *IpIo;\r
- EFI_STATUS Status;\r
- VOID *Ip;\r
-\r
- Tcb = AllocateZeroPool (sizeof (TCP_CB));\r
-\r
- if (Tcb == NULL) {\r
-\r
- DEBUG ((EFI_D_ERROR, "Tcp4ConfigurePcb: failed to allocate a TCB\n"));\r
-\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;\r
- IpIo = ProtoData->TcpService->IpIo;\r
-\r
- //\r
- // Create an IpInfo for this Tcb.\r
- //\r
- Tcb->IpInfo = IpIoAddIp (IpIo);\r
- if (Tcb->IpInfo == NULL) {\r
-\r
- FreePool (Tcb);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Open the new created IP instance BY_CHILD.\r
- //\r
- Status = gBS->OpenProtocol (\r
- Tcb->IpInfo->ChildHandle,\r
- &gEfiIp4ProtocolGuid,\r
- &Ip,\r
- IpIo->Image,\r
- Sk->SockHandle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- IpIoRemoveIp (IpIo, Tcb->IpInfo);\r
- return Status;\r
- }\r
-\r
- InitializeListHead (&Tcb->List);\r
- InitializeListHead (&Tcb->SndQue);\r
- InitializeListHead (&Tcb->RcvQue);\r
-\r
- Tcb->State = TCP_CLOSED;\r
- Tcb->Sk = Sk;\r
- ProtoData->TcpPcb = Tcb;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Detach the Pcb of the socket.\r
-\r
- @param Sk Pointer to the socket of this TCP instance.\r
-\r
-**/\r
-VOID\r
-Tcp4DetachPcb (\r
- IN SOCKET *Sk\r
- )\r
-{\r
- TCP4_PROTO_DATA *ProtoData;\r
- TCP_CB *Tcb;\r
-\r
- ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;\r
- Tcb = ProtoData->TcpPcb;\r
-\r
- ASSERT (Tcb != NULL);\r
-\r
- Tcp4FlushPcb (Tcb);\r
-\r
- IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);\r
-\r
- FreePool (Tcb);\r
-\r
- ProtoData->TcpPcb = NULL;\r
-}\r
-\r
-\r
-/**\r
- Configure the Pcb using CfgData.\r
-\r
- @param Sk Pointer to the socket of this TCP instance.\r
- @param CfgData Pointer to the TCP configuration data.\r
-\r
- @retval EFI_SUCCESS The operation is completed successfully.\r
- @retval EFI_INVALID_PARAMETER A same access point has been configured in\r
- another TCP instance.\r
- @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.\r
-\r
-**/\r
-EFI_STATUS\r
-Tcp4ConfigurePcb (\r
- IN SOCKET *Sk,\r
- IN EFI_TCP4_CONFIG_DATA *CfgData\r
- )\r
-{\r
- EFI_IP4_CONFIG_DATA IpCfgData;\r
- EFI_STATUS Status;\r
- EFI_TCP4_OPTION *Option;\r
- TCP4_PROTO_DATA *TcpProto;\r
- TCP_CB *Tcb;\r
-\r
- ASSERT ((CfgData != NULL) && (Sk != NULL) && (Sk->SockHandle != NULL));\r
-\r
- TcpProto = (TCP4_PROTO_DATA *) Sk->ProtoReserved;\r
- Tcb = TcpProto->TcpPcb;\r
-\r
- ASSERT (Tcb != NULL);\r
-\r
- //\r
- // Add Ip for send pkt to the peer\r
- //\r
- CopyMem (&IpCfgData, &mIp4IoDefaultIpConfigData, sizeof (IpCfgData));\r
- IpCfgData.DefaultProtocol = EFI_IP_PROTO_TCP;\r
- IpCfgData.UseDefaultAddress = CfgData->AccessPoint.UseDefaultAddress;\r
- IpCfgData.StationAddress = CfgData->AccessPoint.StationAddress;\r
- IpCfgData.SubnetMask = CfgData->AccessPoint.SubnetMask;\r
- IpCfgData.ReceiveTimeout = (UINT32) (-1);\r
-\r
- //\r
- // Configure the IP instance this Tcb consumes.\r
- //\r
- Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);\r
- if (EFI_ERROR (Status)) {\r
- goto OnExit;\r
- }\r
-\r
- //\r
- // Get the default address info if the instance is configured to use default address.\r
- //\r
- if (CfgData->AccessPoint.UseDefaultAddress) {\r
- CfgData->AccessPoint.StationAddress = IpCfgData.StationAddress;\r
- CfgData->AccessPoint.SubnetMask = IpCfgData.SubnetMask;\r
- }\r
-\r
- //\r
- // check if we can bind this endpoint in CfgData\r
- //\r
- Status = Tcp4Bind (&(CfgData->AccessPoint));\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Tcp4ConfigurePcb: Bind endpoint failed "\r
- "with %r\n", Status));\r
-\r
- goto OnExit;\r
- }\r
-\r
- //\r
- // Initalize the operating information in this Tcb\r
- //\r
- ASSERT (Tcb->State == TCP_CLOSED &&\r
- IsListEmpty (&Tcb->SndQue) &&\r
- IsListEmpty (&Tcb->RcvQue));\r
-\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);\r
- Tcb->State = TCP_CLOSED;\r
-\r
- Tcb->SndMss = 536;\r
- Tcb->RcvMss = TcpGetRcvMss (Sk);\r
-\r
- Tcb->SRtt = 0;\r
- Tcb->Rto = 3 * TCP_TICK_HZ;\r
-\r
- Tcb->CWnd = Tcb->SndMss;\r
- Tcb->Ssthresh = 0xffffffff;\r
-\r
- Tcb->CongestState = TCP_CONGEST_OPEN;\r
-\r
- Tcb->KeepAliveIdle = TCP_KEEPALIVE_IDLE_MIN;\r
- Tcb->KeepAlivePeriod = TCP_KEEPALIVE_PERIOD;\r
- Tcb->MaxKeepAlive = TCP_MAX_KEEPALIVE;\r
- Tcb->MaxRexmit = TCP_MAX_LOSS;\r
- Tcb->FinWait2Timeout = TCP_FIN_WAIT2_TIME;\r
- Tcb->TimeWaitTimeout = TCP_TIME_WAIT_TIME;\r
- Tcb->ConnectTimeout = TCP_CONNECT_TIME;\r
-\r
- //\r
- // initialize Tcb in the light of CfgData\r
- //\r
- Tcb->Ttl = CfgData->TimeToLive;\r
- Tcb->Tos = CfgData->TypeOfService;\r
-\r
- Tcb->UseDefaultAddr = CfgData->AccessPoint.UseDefaultAddress;\r
-\r
- CopyMem (&Tcb->LocalEnd.Ip, &CfgData->AccessPoint.StationAddress, sizeof (IP4_ADDR));\r
- Tcb->LocalEnd.Port = HTONS (CfgData->AccessPoint.StationPort);\r
- IP4_COPY_ADDRESS (&Tcb->SubnetMask, &CfgData->AccessPoint.SubnetMask);\r
-\r
- if (CfgData->AccessPoint.ActiveFlag) {\r
- CopyMem (&Tcb->RemoteEnd.Ip, &CfgData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR));\r
- Tcb->RemoteEnd.Port = HTONS (CfgData->AccessPoint.RemotePort);\r
- } else {\r
- Tcb->RemoteEnd.Ip = 0;\r
- Tcb->RemoteEnd.Port = 0;\r
- }\r
-\r
- Option = CfgData->ControlOption;\r
-\r
- if (Option != NULL) {\r
- SET_RCV_BUFFSIZE (\r
- Sk,\r
- (UINT32) (TCP_COMP_VAL (\r
- TCP_RCV_BUF_SIZE_MIN,\r
- TCP_RCV_BUF_SIZE,\r
- TCP_RCV_BUF_SIZE,\r
- Option->ReceiveBufferSize\r
- )\r
- )\r
- );\r
- SET_SND_BUFFSIZE (\r
- Sk,\r
- (UINT32) (TCP_COMP_VAL (\r
- TCP_SND_BUF_SIZE_MIN,\r
- TCP_SND_BUF_SIZE,\r
- TCP_SND_BUF_SIZE,\r
- Option->SendBufferSize\r
- )\r
- )\r
- );\r
-\r
- SET_BACKLOG (\r
- Sk,\r
- (UINT32) (TCP_COMP_VAL (\r
- TCP_BACKLOG_MIN,\r
- TCP_BACKLOG,\r
- TCP_BACKLOG,\r
- Option->MaxSynBackLog\r
- )\r
- )\r
- );\r
-\r
- Tcb->MaxRexmit = (UINT16) TCP_COMP_VAL (\r
- TCP_MAX_LOSS_MIN,\r
- TCP_MAX_LOSS,\r
- TCP_MAX_LOSS,\r
- Option->DataRetries\r
- );\r
- Tcb->FinWait2Timeout = TCP_COMP_VAL (\r
- TCP_FIN_WAIT2_TIME,\r
- TCP_FIN_WAIT2_TIME_MAX,\r
- TCP_FIN_WAIT2_TIME,\r
- (UINT32) (Option->FinTimeout * TCP_TICK_HZ)\r
- );\r
-\r
- if (Option->TimeWaitTimeout != 0) {\r
- Tcb->TimeWaitTimeout = TCP_COMP_VAL (\r
- TCP_TIME_WAIT_TIME,\r
- TCP_TIME_WAIT_TIME_MAX,\r
- TCP_TIME_WAIT_TIME,\r
- (UINT32) (Option->TimeWaitTimeout * TCP_TICK_HZ)\r
- );\r
- } else {\r
- Tcb->TimeWaitTimeout = 0;\r
- }\r
-\r
- if (Option->KeepAliveProbes != 0) {\r
- TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);\r
-\r
- Tcb->MaxKeepAlive = (UINT8) TCP_COMP_VAL (\r
- TCP_MAX_KEEPALIVE_MIN,\r
- TCP_MAX_KEEPALIVE,\r
- TCP_MAX_KEEPALIVE,\r
- Option->KeepAliveProbes\r
- );\r
- Tcb->KeepAliveIdle = TCP_COMP_VAL (\r
- TCP_KEEPALIVE_IDLE_MIN,\r
- TCP_KEEPALIVE_IDLE_MAX,\r
- TCP_KEEPALIVE_IDLE_MIN,\r
- (UINT32) (Option->KeepAliveTime * TCP_TICK_HZ)\r
- );\r
- Tcb->KeepAlivePeriod = TCP_COMP_VAL (\r
- TCP_KEEPALIVE_PERIOD_MIN,\r
- TCP_KEEPALIVE_PERIOD,\r
- TCP_KEEPALIVE_PERIOD,\r
- (UINT32) (Option->KeepAliveInterval * TCP_TICK_HZ)\r
- );\r
- }\r
-\r
- Tcb->ConnectTimeout = TCP_COMP_VAL (\r
- TCP_CONNECT_TIME_MIN,\r
- TCP_CONNECT_TIME,\r
- TCP_CONNECT_TIME,\r
- (UINT32) (Option->ConnectionTimeout * TCP_TICK_HZ)\r
- );\r
-\r
- if (!Option->EnableNagle) {\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);\r
- }\r
-\r
- if (!Option->EnableTimeStamp) {\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);\r
- }\r
-\r
- if (!Option->EnableWindowScaling) {\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);\r
- }\r
- }\r
-\r
- //\r
- // The socket is bound, the <SrcIp, SrcPort, DstIp, DstPort> is\r
- // determined, construct the IP device path and install it.\r
- //\r
- Status = TcpInstallDevicePath (Sk);\r
- if (EFI_ERROR (Status)) {\r
- goto OnExit;\r
- }\r
-\r
- //\r
- // update state of Tcb and socket\r
- //\r
- if (!CfgData->AccessPoint.ActiveFlag) {\r
-\r
- TcpSetState (Tcb, TCP_LISTEN);\r
- SockSetState (Sk, SO_LISTENING);\r
-\r
- Sk->ConfigureState = SO_CONFIGURED_PASSIVE;\r
- } else {\r
-\r
- Sk->ConfigureState = SO_CONFIGURED_ACTIVE;\r
- }\r
-\r
- TcpInsertTcb (Tcb);\r
-\r
-OnExit:\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- The procotol handler provided to the socket layer, used to\r
- dispatch the socket level requests by calling the corresponding\r
- TCP layer functions.\r
-\r
- @param Sock Pointer to the socket of this TCP instance.\r
- @param Request The code of this operation request.\r
- @param Data Pointer to the operation specific data passed in\r
- together with the operation request.\r
-\r
- @retval EFI_SUCCESS The socket request is completed successfully.\r
- @retval other The error status returned by the corresponding TCP\r
- layer function.\r
-\r
-**/\r
-EFI_STATUS\r
-Tcp4Dispatcher (\r
- IN SOCKET *Sock,\r
- IN UINT8 Request,\r
- IN VOID *Data OPTIONAL\r
- )\r
-{\r
- TCP_CB *Tcb;\r
- TCP4_PROTO_DATA *ProtoData;\r
- EFI_IP4_PROTOCOL *Ip;\r
-\r
- ProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;\r
- Tcb = ProtoData->TcpPcb;\r
-\r
- switch (Request) {\r
- case SOCK_POLL:\r
- Ip = ProtoData->TcpService->IpIo->Ip.Ip4;\r
- Ip->Poll (Ip);\r
- break;\r
-\r
- case SOCK_CONSUMED:\r
- //\r
- // After user received data from socket buffer, socket will\r
- // notify TCP using this message to give it a chance to send out\r
- // window update information\r
- //\r
- ASSERT (Tcb != NULL);\r
- TcpOnAppConsume (Tcb);\r
- break;\r
-\r
- case SOCK_SND:\r
-\r
- ASSERT (Tcb != NULL);\r
- TcpOnAppSend (Tcb);\r
- break;\r
-\r
- case SOCK_CLOSE:\r
-\r
- TcpOnAppClose (Tcb);\r
-\r
- break;\r
-\r
- case SOCK_ABORT:\r
-\r
- TcpOnAppAbort (Tcb);\r
-\r
- break;\r
-\r
- case SOCK_SNDPUSH:\r
- Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk);\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);\r
-\r
- break;\r
-\r
- case SOCK_SNDURG:\r
- Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1;\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);\r
-\r
- break;\r
-\r
- case SOCK_CONNECT:\r
-\r
- TcpOnAppConnect (Tcb);\r
-\r
- break;\r
-\r
- case SOCK_ATTACH:\r
-\r
- return Tcp4AttachPcb (Sock);\r
-\r
- case SOCK_FLUSH:\r
-\r
- Tcp4FlushPcb (Tcb);\r
-\r
- break;\r
-\r
- case SOCK_DETACH:\r
-\r
- Tcp4DetachPcb (Sock);\r
-\r
- break;\r
-\r
- case SOCK_CONFIGURE:\r
-\r
- return Tcp4ConfigurePcb (\r
- Sock,\r
- (EFI_TCP4_CONFIG_DATA *) Data\r
- );\r
-\r
- case SOCK_MODE:\r
-\r
- ASSERT ((Data != NULL) && (Tcb != NULL));\r
-\r
- return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data);\r
-\r
- case SOCK_ROUTE:\r
-\r
- ASSERT ((Data != NULL) && (Tcb != NULL));\r
-\r
- return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data);\r
-\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-\r
-}\r
+++ /dev/null
-/** @file\r
- Tcp driver function.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Tcp4Main.h"\r
-\r
-\r
-UINT16 mTcp4RandomPort;\r
-extern EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName;\r
-extern EFI_COMPONENT_NAME2_PROTOCOL gTcp4ComponentName2;\r
-extern EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable;\r
-\r
-TCP4_HEARTBEAT_TIMER mTcp4Timer = {\r
- NULL,\r
- 0\r
-};\r
-\r
-EFI_TCP4_PROTOCOL mTcp4ProtocolTemplate = {\r
- Tcp4GetModeData,\r
- Tcp4Configure,\r
- Tcp4Routes,\r
- Tcp4Connect,\r
- Tcp4Accept,\r
- Tcp4Transmit,\r
- Tcp4Receive,\r
- Tcp4Close,\r
- Tcp4Cancel,\r
- Tcp4Poll\r
-};\r
-\r
-SOCK_INIT_DATA mTcp4DefaultSockData = {\r
- SockStream,\r
- 0,\r
- NULL,\r
- TCP_BACKLOG,\r
- TCP_SND_BUF_SIZE,\r
- TCP_RCV_BUF_SIZE,\r
- &mTcp4ProtocolTemplate,\r
- Tcp4CreateSocketCallback,\r
- Tcp4DestroySocketCallback,\r
- NULL,\r
- NULL,\r
- 0,\r
- Tcp4Dispatcher,\r
- NULL,\r
-};\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL mTcp4DriverBinding = {\r
- Tcp4DriverBindingSupported,\r
- Tcp4DriverBindingStart,\r
- Tcp4DriverBindingStop,\r
- 0xa,\r
- NULL,\r
- NULL\r
-};\r
-\r
-EFI_SERVICE_BINDING_PROTOCOL mTcp4ServiceBinding = {\r
- Tcp4ServiceBindingCreateChild,\r
- Tcp4ServiceBindingDestroyChild\r
-};\r
-\r
-\r
-/**\r
- Create and start the heartbeat timer for TCP driver.\r
-\r
- @retval EFI_SUCCESS The timer is successfully created and started.\r
- @retval other The timer is not created.\r
-\r
-**/\r
-EFI_STATUS\r
-Tcp4CreateTimer (\r
- VOID\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- if (mTcp4Timer.RefCnt == 0) {\r
-\r
- Status = gBS->CreateEvent (\r
- EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- TcpTicking,\r
- NULL,\r
- &mTcp4Timer.TimerEvent\r
- );\r
- if (!EFI_ERROR (Status)) {\r
-\r
- Status = gBS->SetTimer (\r
- mTcp4Timer.TimerEvent,\r
- TimerPeriodic,\r
- (UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ)\r
- );\r
- }\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
-\r
- mTcp4Timer.RefCnt++;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Stop and destroy the heartbeat timer for TCP driver.\r
-\r
-**/\r
-VOID\r
-Tcp4DestroyTimer (\r
- VOID\r
- )\r
-{\r
- ASSERT (mTcp4Timer.RefCnt > 0);\r
-\r
- mTcp4Timer.RefCnt--;\r
-\r
- if (mTcp4Timer.RefCnt > 0) {\r
- return;\r
- }\r
-\r
- gBS->SetTimer (mTcp4Timer.TimerEvent, TimerCancel, 0);\r
- gBS->CloseEvent (mTcp4Timer.TimerEvent);\r
- mTcp4Timer.TimerEvent = NULL;\r
-}\r
-\r
-/**\r
- Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
-\r
- @param[in] Entry The entry to be removed.\r
- @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
-\r
- @retval EFI_SUCCESS The entry has been removed successfully.\r
- @retval Others Fail to remove the entry.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4DestroyChildEntryInHandleBuffer (\r
- IN LIST_ENTRY *Entry,\r
- IN VOID *Context\r
- )\r
-{\r
- SOCKET *Sock;\r
- EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
- UINTN NumberOfChildren;\r
- EFI_HANDLE *ChildHandleBuffer;\r
-\r
- if (Entry == NULL || Context == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Sock = NET_LIST_USER_STRUCT_S (Entry, SOCKET, Link, SOCK_SIGNATURE);\r
- ServiceBinding = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
- NumberOfChildren = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
- ChildHandleBuffer = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
-\r
- if (!NetIsInHandleBuffer (Sock->SockHandle, NumberOfChildren, ChildHandleBuffer)) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- return ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);\r
-}\r
-\r
-/**\r
- The entry point for Tcp4 driver, used to install Tcp4 driver on the ImageHandle.\r
-\r
- @param ImageHandle The firmware allocated handle for this\r
- driver image.\r
- @param SystemTable Pointer to the EFI system table.\r
-\r
- @retval EFI_SUCCESS Driver loaded.\r
- @retval other Driver not loaded.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4DriverEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 Seed;\r
-\r
- //\r
- // Install the TCP4 Driver Binding Protocol\r
- //\r
- Status = EfiLibInstallDriverBindingComponentName2 (\r
- ImageHandle,\r
- SystemTable,\r
- &mTcp4DriverBinding,\r
- ImageHandle,\r
- &gTcp4ComponentName,\r
- &gTcp4ComponentName2\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- //\r
- // Initialize ISS and random port.\r
- //\r
- Seed = NetRandomInitSeed ();\r
- mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;\r
- mTcp4RandomPort = (UINT16) (TCP4_PORT_KNOWN +\r
- (UINT16) (NET_RANDOM(Seed) % TCP4_PORT_KNOWN));\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Tests to see if this driver supports a given controller.\r
-\r
- If a child device is provided, it further tests to see if this driver supports\r
- creating a handle for the specified child device.\r
-\r
- @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
- @param ControllerHandle The handle of the controller to test. This handle\r
- must support a protocol interface that supplies\r
- an I/O abstraction to the driver.\r
- @param RemainingDevicePath A pointer to the remaining portion of a device path.\r
- This parameter is ignored by device drivers, and is optional for bus drivers.\r
-\r
-\r
- @retval EFI_SUCCESS The device specified by ControllerHandle and\r
- RemainingDevicePath is supported by the driver\r
- specified by This.\r
- @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
- RemainingDevicePath is already being managed by\r
- the driver specified by This.\r
- @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
- RemainingDevicePath is already being managed by a\r
- different driver or an application that requires\r
- exclusive access.\r
- @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
- RemainingDevicePath is not supported by the driver\r
- specified by This.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4DriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Test for the Tcp4ServiceBinding Protocol\r
- //\r
- Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiTcp4ServiceBindingProtocolGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- return EFI_ALREADY_STARTED;\r
- }\r
-\r
- //\r
- // Test for the Ip4 Protocol\r
- //\r
- Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiIp4ServiceBindingProtocolGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Start this driver on ControllerHandle.\r
-\r
- The Start() function is designed to be invoked from the EFI boot service\r
- ConnectController(). As a result, much of the error checking on the parameters\r
- to Start() has been moved into this common boot service. It is legal to call\r
- Start() from other locations, but the following calling restrictions must be\r
- followed or the system behavior will not be deterministic.\r
- 1. ControllerHandle must be a valid EFI_HANDLE.\r
- 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally\r
- aligned EFI_DEVICE_PATH_PROTOCOL.\r
- 3. Prior to calling Start(), the Supported() function for the driver specified\r
- by This must have been called with the same calling parameters, and Supported()\r
- must have returned EFI_SUCCESS.\r
-\r
- @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
- @param ControllerHandle The handle of the controller to start. This handle\r
- must support a protocol interface that supplies\r
- an I/O abstraction to the driver.\r
- @param RemainingDevicePath A pointer to the remaining portion of a device path.\r
- This parameter is ignored by device drivers, and is\r
- optional for bus drivers.\r
-\r
- @retval EFI_SUCCESS The device was started.\r
- @retval EFI_ALREADY_STARTED The device could not be started due to a device error.\r
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
- of resources.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4DriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
- )\r
-{\r
- EFI_STATUS Status;\r
- TCP4_SERVICE_DATA *TcpServiceData;\r
- IP_IO_OPEN_DATA OpenData;\r
-\r
- TcpServiceData = AllocateZeroPool (sizeof (TCP4_SERVICE_DATA));\r
-\r
- if (NULL == TcpServiceData) {\r
- DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough"\r
- " resource to create a Tcp Servcie Data\n"));\r
-\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Create a new IP IO to Consume it\r
- //\r
- TcpServiceData->IpIo = IpIoCreate (\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- IP_VERSION_4\r
- );\r
- if (NULL == TcpServiceData->IpIo) {\r
-\r
- DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough"\r
- " resource to create an Ip Io\n"));\r
-\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Configure and start IpIo.\r
- //\r
- ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));\r
-\r
- CopyMem (\r
- &OpenData.IpConfigData.Ip4CfgData,\r
- &mIp4IoDefaultIpConfigData,\r
- sizeof (EFI_IP4_CONFIG_DATA)\r
- );\r
-\r
- OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;\r
-\r
- OpenData.PktRcvdNotify = Tcp4RxCallback;\r
- Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Create the timer event used by TCP driver\r
- //\r
- Status = Tcp4CreateTimer ();\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Create TcpTimer"\r
- " Event failed with %r\n", Status));\r
-\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Install the Tcp4ServiceBinding Protocol on the\r
- // controller handle\r
- //\r
- TcpServiceData->Tcp4ServiceBinding = mTcp4ServiceBinding;\r
-\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &ControllerHandle,\r
- &gEfiTcp4ServiceBindingProtocolGuid,\r
- &TcpServiceData->Tcp4ServiceBinding,\r
- NULL\r
- );\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Install Tcp4 Service Binding"\r
- " Protocol failed for %r\n", Status));\r
-\r
- Tcp4DestroyTimer ();\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Initialize member in TcpServiceData\r
- //\r
- TcpServiceData->ControllerHandle = ControllerHandle;\r
- TcpServiceData->Signature = TCP4_DRIVER_SIGNATURE;\r
- TcpServiceData->DriverBindingHandle = This->DriverBindingHandle;\r
-\r
- InitializeListHead (&TcpServiceData->SocketList);\r
-\r
- return EFI_SUCCESS;\r
-\r
-ON_ERROR:\r
-\r
- if (TcpServiceData->IpIo != NULL) {\r
- IpIoDestroy (TcpServiceData->IpIo);\r
- TcpServiceData->IpIo = NULL;\r
- }\r
-\r
- FreePool (TcpServiceData);\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Stop this driver on ControllerHandle.\r
-\r
- The Stop() function is designed to be invoked from the EFI boot service\r
- DisconnectController(). As a result, much of the error checking on the parameters\r
- to Stop() has been moved into this common boot service. It is legal to call Stop()\r
- from other locations, but the following calling restrictions must be followed\r
- or the system behavior will not be deterministic.\r
- 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call\r
- to this same driver's Start() function.\r
- 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
- EFI_HANDLE. In addition, all of these handles must have been created in this\r
- driver's Start() function, and the Start() function must have called OpenProtocol()\r
- on ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
-\r
- @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
- @param ControllerHandle A handle to the device being stopped. The handle must\r
- support a bus specific I/O protocol for the driver\r
- to use to stop the device.\r
- @param NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
- @param ChildHandleBuffer An array of child handles to be freed. May be NULL if\r
- NumberOfChildren is 0.\r
-\r
- @retval EFI_SUCCESS The device was stopped.\r
- @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4DriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE NicHandle;\r
- EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
- TCP4_SERVICE_DATA *TcpServiceData;\r
- LIST_ENTRY *List;\r
- TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
-\r
- // Find the NicHandle where Tcp4 ServiceBinding Protocol is installed.\r
- //\r
- NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);\r
- if (NicHandle == NULL) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Retrieve the TCP driver Data Structure\r
- //\r
- Status = gBS->OpenProtocol (\r
- NicHandle,\r
- &gEfiTcp4ServiceBindingProtocolGuid,\r
- (VOID **) &ServiceBinding,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStop: Locate Tcp4 Service "\r
- " Binding Protocol failed with %r\n", Status));\r
-\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- TcpServiceData = TCP4_FROM_THIS (ServiceBinding);\r
-\r
- if (NumberOfChildren != 0) {\r
- List = &TcpServiceData->SocketList;\r
- Context.ServiceBinding = ServiceBinding;\r
- Context.NumberOfChildren = NumberOfChildren;\r
- Context.ChildHandleBuffer = ChildHandleBuffer;\r
- Status = NetDestroyLinkList (\r
- List,\r
- Tcp4DestroyChildEntryInHandleBuffer,\r
- &Context,\r
- NULL\r
- );\r
- } else if (IsListEmpty (&TcpServiceData->SocketList)) {\r
- //\r
- // Uninstall TCP servicebinding protocol\r
- //\r
- gBS->UninstallMultipleProtocolInterfaces (\r
- NicHandle,\r
- &gEfiTcp4ServiceBindingProtocolGuid,\r
- ServiceBinding,\r
- NULL\r
- );\r
-\r
- //\r
- // Destroy the IpIO consumed by TCP driver\r
- //\r
- IpIoDestroy (TcpServiceData->IpIo);\r
- TcpServiceData->IpIo = NULL;\r
-\r
- //\r
- // Destroy the heartbeat timer.\r
- //\r
- Tcp4DestroyTimer ();\r
-\r
- if (gTcpControllerNameTable != NULL) {\r
- FreeUnicodeStringTable (gTcpControllerNameTable);\r
- gTcpControllerNameTable = NULL;\r
- }\r
-\r
- //\r
- // Release the TCP service data\r
- //\r
- FreePool (TcpServiceData);\r
-\r
- Status = EFI_SUCCESS;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Open Ip4 and device path protocols for a created socket, and insert it in\r
- socket list.\r
-\r
- @param This Pointer to the socket just created\r
- @param Context Context of the socket\r
-\r
- @retval EFI_SUCCESS This protocol is installed successfully.\r
- @retval other Some error occured.\r
-\r
-**/\r
-EFI_STATUS\r
-Tcp4CreateSocketCallback (\r
- IN SOCKET *This,\r
- IN VOID *Context\r
- )\r
-{\r
- EFI_STATUS Status;\r
- TCP4_SERVICE_DATA *TcpServiceData;\r
- EFI_IP4_PROTOCOL *Ip4;\r
-\r
- TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;\r
-\r
- //\r
- // Open the default Ip4 protocol of IP_IO BY_DRIVER.\r
- //\r
- Status = gBS->OpenProtocol (\r
- TcpServiceData->IpIo->ChildHandle,\r
- &gEfiIp4ProtocolGuid,\r
- (VOID **) &Ip4,\r
- TcpServiceData->DriverBindingHandle,\r
- This->SockHandle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Open the device path on the handle where service binding resides on.\r
- //\r
- Status = gBS->OpenProtocol (\r
- TcpServiceData->ControllerHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &This->ParentDevicePath,\r
- TcpServiceData->DriverBindingHandle,\r
- This->SockHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- gBS->CloseProtocol (\r
- TcpServiceData->IpIo->ChildHandle,\r
- &gEfiIp4ProtocolGuid,\r
- TcpServiceData->DriverBindingHandle,\r
- This->SockHandle\r
- );\r
- } else {\r
- //\r
- // Insert this socket into the SocketList.\r
- //\r
- InsertTailList (&TcpServiceData->SocketList, &This->Link);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Close Ip4 and device path protocols for a socket, and remove it from socket list.\r
-\r
- @param This Pointer to the socket to be removed\r
- @param Context Context of the socket\r
-\r
-**/\r
-VOID\r
-Tcp4DestroySocketCallback (\r
- IN SOCKET *This,\r
- IN VOID *Context\r
- )\r
-{\r
- TCP4_SERVICE_DATA *TcpServiceData;\r
-\r
- TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;\r
-\r
- //\r
- // Remove this node from the list.\r
- //\r
- RemoveEntryList (&This->Link);\r
-\r
- //\r
- // Close the Ip4 protocol.\r
- //\r
- gBS->CloseProtocol (\r
- TcpServiceData->IpIo->ChildHandle,\r
- &gEfiIp4ProtocolGuid,\r
- TcpServiceData->DriverBindingHandle,\r
- This->SockHandle\r
- );\r
-}\r
-\r
-/**\r
- Creates a child handle and installs a protocol.\r
-\r
- The CreateChild() function installs a protocol on ChildHandle. If ChildHandle\r
- is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
- If ChildHandle is not a pointer to NULL, then the protocol installs on the existing\r
- ChildHandle.\r
-\r
- @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
- @param ChildHandle Pointer to the handle of the child to create. If it is NULL, then\r
- a new handle is created. If it is a pointer to an existing UEFI\r
- handle, then the protocol is added to the existing UEFI handle.\r
-\r
- @retval EFI_SUCCES The protocol was added to ChildHandle.\r
- @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
- @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create\r
- the child.\r
- @retval other The child handle was not created.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4ServiceBindingCreateChild (\r
- IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
- IN OUT EFI_HANDLE *ChildHandle\r
- )\r
-{\r
- SOCKET *Sock;\r
- TCP4_SERVICE_DATA *TcpServiceData;\r
- TCP4_PROTO_DATA TcpProto;\r
- EFI_STATUS Status;\r
- EFI_TPL OldTpl;\r
-\r
- if (NULL == This || NULL == ChildHandle) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
- Status = EFI_SUCCESS;\r
- TcpServiceData = TCP4_FROM_THIS (This);\r
- TcpProto.TcpService = TcpServiceData;\r
- TcpProto.TcpPcb = NULL;\r
-\r
- //\r
- // Create a tcp instance with defualt Tcp default\r
- // sock init data and TcpProto\r
- //\r
- mTcp4DefaultSockData.ProtoData = &TcpProto;\r
- mTcp4DefaultSockData.DataSize = sizeof (TCP4_PROTO_DATA);\r
- mTcp4DefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;\r
-\r
- Sock = SockCreateChild (&mTcp4DefaultSockData);\r
- if (NULL == Sock) {\r
- DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingCreateChild: "\r
- "No resource to create a Tcp Child\n"));\r
-\r
- Status = EFI_OUT_OF_RESOURCES;\r
- } else {\r
- *ChildHandle = Sock->SockHandle;\r
- }\r
-\r
- mTcp4DefaultSockData.ProtoData = NULL;\r
-\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Destroys a child handle with a protocol installed on it.\r
-\r
- The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
- that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
- last protocol on ChildHandle, then ChildHandle is destroyed.\r
-\r
- @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
- @param ChildHandle Handle of the child to destroy\r
-\r
- @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
- @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is\r
- being removed.\r
- @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
- @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
- because its services are being used.\r
- @retval other The child handle was not destroyed.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4ServiceBindingDestroyChild (\r
- IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE ChildHandle\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_TCP4_PROTOCOL *Tcp4;\r
- SOCKET *Sock;\r
-\r
- if (NULL == This || NULL == ChildHandle) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // retrieve the Tcp4 protocol from ChildHandle\r
- //\r
- Status = gBS->OpenProtocol (\r
- ChildHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- (VOID **) &Tcp4,\r
- mTcp4DriverBinding.DriverBindingHandle,\r
- ChildHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_UNSUPPORTED;\r
- } else {\r
- //\r
- // destroy this sock and related Tcp protocol control\r
- // block\r
- //\r
- Sock = SOCK_FROM_THIS (Tcp4);\r
-\r
- SockDestroyChild (Sock);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
+++ /dev/null
-/** @file\r
- Tcp driver function header.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#ifndef _TCP4_DRIVER_H_\r
-#define _TCP4_DRIVER_H_\r
-\r
-#include <Protocol/ServiceBinding.h>\r
-#include <Library/IpIoLib.h>\r
-\r
-#define TCP4_DRIVER_SIGNATURE SIGNATURE_32 ('T', 'C', 'P', '4')\r
-\r
-#define TCP4_PORT_KNOWN 1024\r
-#define TCP4_PORT_USER_RESERVED 65535\r
-\r
-#define TCP4_FROM_THIS(a) \\r
- CR ( \\r
- (a), \\r
- TCP4_SERVICE_DATA, \\r
- Tcp4ServiceBinding, \\r
- TCP4_DRIVER_SIGNATURE \\r
- )\r
-\r
-///\r
-/// TCP heartbeat tick timer.\r
-///\r
-typedef struct _TCP4_HEARTBEAT_TIMER {\r
- EFI_EVENT TimerEvent; ///< The event assoiated with the timer\r
- INTN RefCnt; ///< Number of reference\r
-} TCP4_HEARTBEAT_TIMER;\r
-\r
-///\r
-/// TCP service data\r
-///\r
-typedef struct _TCP4_SERVICE_DATA {\r
- UINT32 Signature;\r
- EFI_HANDLE ControllerHandle;\r
- IP_IO *IpIo; // IP Io consumed by TCP4\r
- EFI_SERVICE_BINDING_PROTOCOL Tcp4ServiceBinding;\r
- EFI_HANDLE DriverBindingHandle;\r
- LIST_ENTRY SocketList;\r
-} TCP4_SERVICE_DATA;\r
-\r
-///\r
-/// TCP protocol data\r
-///\r
-typedef struct _TCP4_PROTO_DATA {\r
- TCP4_SERVICE_DATA *TcpService;\r
- TCP_CB *TcpPcb;\r
-} TCP4_PROTO_DATA;\r
-\r
-\r
-/**\r
- Packet receive callback function provided to IP_IO, used to call\r
- the proper function to handle the packet received by IP.\r
-\r
- @param Status Status of the received packet.\r
- @param IcmpErr ICMP error number.\r
- @param NetSession Pointer to the net session of this packet.\r
- @param Pkt Pointer to the recieved packet.\r
- @param Context Pointer to the context configured in IpIoOpen(), not used\r
- now.\r
-\r
- @return None\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Tcp4RxCallback (\r
- IN EFI_STATUS Status,\r
- IN UINT8 IcmpErr,\r
- IN EFI_NET_SESSION_DATA *NetSession,\r
- IN NET_BUF *Pkt,\r
- IN VOID *Context OPTIONAL\r
- );\r
-\r
-/**\r
- Send the segment to IP via IpIo function.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the TCP segment to be sent.\r
- @param Src Source address of the TCP segment.\r
- @param Dest Destination address of the TCP segment.\r
-\r
- @retval 0 The segment was sent out successfully.\r
- @retval -1 The segment was failed to send.\r
-\r
-**/\r
-INTN\r
-TcpSendIpPacket (\r
- IN TCP_CB *Tcb,\r
- IN NET_BUF *Nbuf,\r
- IN UINT32 Src,\r
- IN UINT32 Dest\r
- );\r
-\r
-/**\r
- The procotol handler provided to the socket layer, used to\r
- dispatch the socket level requests by calling the corresponding\r
- TCP layer functions.\r
-\r
- @param Sock Pointer to the socket of this TCP instance.\r
- @param Request The code of this operation request.\r
- @param Data Pointer to the operation specific data passed in\r
- together with the operation request.\r
-\r
- @retval EFI_SUCCESS The socket request is completed successfully.\r
- @retval other The error status returned by the corresponding TCP\r
- layer function.\r
-\r
-**/\r
-EFI_STATUS\r
-Tcp4Dispatcher (\r
- IN SOCKET *Sock,\r
- IN UINT8 Request,\r
- IN VOID *Data OPTIONAL\r
- );\r
-\r
-\r
-/**\r
- The entry point for Tcp4 driver, used to install Tcp4 driver on the ImageHandle.\r
-\r
- @param ImageHandle The firmware allocated handle for this\r
- driver image.\r
- @param SystemTable Pointer to the EFI system table.\r
-\r
- @retval EFI_SUCCESS Driver loaded.\r
- @retval other Driver not loaded.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4DriverEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- );\r
-\r
-\r
-/**\r
- Tests to see if this driver supports a given controller.\r
-\r
- If a child device is provided, it further tests to see if this driver supports\r
- creating a handle for the specified child device.\r
-\r
- @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
- @param ControllerHandle The handle of the controller to test. This handle\r
- must support a protocol interface that supplies\r
- an I/O abstraction to the driver.\r
- @param RemainingDevicePath A pointer to the remaining portion of a device path.\r
- This parameter is ignored by device drivers, and is optional for bus drivers.\r
-\r
-\r
- @retval EFI_SUCCESS The device specified by ControllerHandle and\r
- RemainingDevicePath is supported by the driver\r
- specified by This.\r
- @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
- RemainingDevicePath is already being managed by\r
- the driver specified by This.\r
- @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
- RemainingDevicePath is already being managed by a\r
- different driver or an application that requires\r
- exclusive access.\r
- @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
- RemainingDevicePath is not supported by the driver\r
- specified by This.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4DriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
- );\r
-\r
-/**\r
- Start this driver on ControllerHandle.\r
-\r
- The Start() function is designed to be invoked from the EFI boot service\r
- ConnectController(). As a result, much of the error checking on the parameters\r
- to Start() has been moved into this common boot service. It is legal to call\r
- Start() from other locations, but the following calling restrictions must be\r
- followed or the system behavior will not be deterministic.\r
- 1. ControllerHandle must be a valid EFI_HANDLE.\r
- 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally\r
- aligned EFI_DEVICE_PATH_PROTOCOL.\r
- 3. Prior to calling Start(), the Supported() function for the driver specified\r
- by This must have been called with the same calling parameters, and Supported()\r
- must have returned EFI_SUCCESS.\r
-\r
- @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
- @param ControllerHandle The handle of the controller to start. This handle\r
- must support a protocol interface that supplies\r
- an I/O abstraction to the driver.\r
- @param RemainingDevicePath A pointer to the remaining portion of a device path.\r
- This parameter is ignored by device drivers, and is\r
- optional for bus drivers.\r
-\r
- @retval EFI_SUCCESS The device was started.\r
- @retval EFI_ALREADY_STARTED The device could not be started due to a device error.\r
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
- of resources.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4DriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
- );\r
-\r
-/**\r
- Stop this driver on ControllerHandle.\r
-\r
- The Stop() function is designed to be invoked from the EFI boot service\r
- DisconnectController(). As a result, much of the error checking on the parameters\r
- to Stop() has been moved into this common boot service. It is legal to call Stop()\r
- from other locations, but the following calling restrictions must be followed\r
- or the system behavior will not be deterministic.\r
- 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call\r
- to this same driver's Start() function.\r
- 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
- EFI_HANDLE. In addition, all of these handles must have been created in this\r
- driver's Start() function, and the Start() function must have called OpenProtocol()\r
- on ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
-\r
- @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
- @param ControllerHandle A handle to the device being stopped. The handle must\r
- support a bus specific I/O protocol for the driver\r
- to use to stop the device.\r
- @param NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
- @param ChildHandleBuffer An array of child handles to be freed. May be NULL if\r
- NumberOfChildren is 0.\r
-\r
- @retval EFI_SUCCESS The device was stopped.\r
- @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4DriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- );\r
-\r
-/**\r
- Open Ip4 and device path protocols for a created socket, and insert it in\r
- socket list.\r
-\r
- @param This Pointer to the socket just created\r
- @param Context Context of the socket\r
-\r
- @retval EFI_SUCCESS This protocol is installed successfully.\r
- @retval other Some error occured.\r
-\r
-**/\r
-EFI_STATUS\r
-Tcp4CreateSocketCallback (\r
- IN SOCKET *This,\r
- IN VOID *Context\r
- );\r
-\r
-/**\r
- Close Ip4 and device path protocols for a socket, and remove it from socket list.\r
-\r
- @param This Pointer to the socket to be removed\r
- @param Context Context of the socket\r
-\r
-**/\r
-VOID\r
-Tcp4DestroySocketCallback (\r
- IN SOCKET *This,\r
- IN VOID *Context\r
- );\r
-\r
-/**\r
- Creates a child handle and installs a protocol.\r
-\r
- The CreateChild() function installs a protocol on ChildHandle. If ChildHandle\r
- is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
- If ChildHandle is not a pointer to NULL, then the protocol installs on the existing\r
- ChildHandle.\r
-\r
- @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
- @param ChildHandle Pointer to the handle of the child to create. If it is NULL, then\r
- a new handle is created. If it is a pointer to an existing UEFI\r
- handle, then the protocol is added to the existing UEFI handle.\r
-\r
- @retval EFI_SUCCES The protocol was added to ChildHandle.\r
- @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
- @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create\r
- the child.\r
- @retval other The child handle was not created.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4ServiceBindingCreateChild (\r
- IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
- IN OUT EFI_HANDLE *ChildHandle\r
- );\r
-\r
-/**\r
- Destroys a child handle with a protocol installed on it.\r
-\r
- The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
- that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
- last protocol on ChildHandle, then ChildHandle is destroyed.\r
-\r
- @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
- @param ChildHandle Handle of the child to destroy\r
-\r
- @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
- @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is\r
- being removed.\r
- @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
- @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
- because its services are being used.\r
- @retval other The child handle was not destroyed.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4ServiceBindingDestroyChild (\r
- IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE ChildHandle\r
- );\r
-\r
-#endif\r
+++ /dev/null
-## @file\r
-# This module produces EFI TCPv4 Protocol and EFI TCPv4 Service Binding Protocol.\r
-#\r
-# This module produces EFI TCPv4(Transmission Control Protocol version 4) Protocol\r
-# upon EFI IPv4 Protocol, to provide basic TCPv4 I/O services. This driver only\r
-# supports IPv4 network stack.\r
-#\r
-# Notes:\r
-# 1) This driver can't co-work with the TcpDxe driver in NetworkPkg.\r
-# 2) This driver might have some issues that have been fixed in the TcpDxe driver\r
-# in NetworkPkg.\r
-# 3) This driver supports fewer features than the TcpDxe driver in NetworkPkg (e.g. IPv6,\r
-# TCP Cancel function).\r
-# 4) TcpDxe driver in NetworkPkg is recommended for use instead of this one even though\r
-# both of them can be used.\r
-#\r
-# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
-# This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this distribution. The full text of the license may be found at\r
-# http://opensource.org/licenses/bsd-license.php\r
-#\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#\r
-#\r
-##\r
-\r
-[Defines]\r
- INF_VERSION = 0x00010005\r
- BASE_NAME = Tcp4Dxe\r
- MODULE_UNI_FILE = Tcp4Dxe.uni\r
- FILE_GUID = 6d6963ab-906d-4a65-a7ca-bd40e5d6af4d\r
- MODULE_TYPE = UEFI_DRIVER\r
- VERSION_STRING = 1.0\r
- ENTRY_POINT = Tcp4DriverEntryPoint\r
- UNLOAD_IMAGE = NetLibDefaultUnload\r
-#\r
-# The following information is for reference only and not required by the build tools.\r
-#\r
-# VALID_ARCHITECTURES = IA32 X64 EBC\r
-#\r
-# DRIVER_BINDING = mTcp4DriverBinding\r
-# COMPONENT_NAME = gTcp4ComponentName\r
-# COMPONENT_NAME2 = gTcp4ComponentName2\r
-#\r
-\r
-[Sources]\r
- SockImpl.c\r
- SockInterface.c\r
- Tcp4Proto.h\r
- Tcp4Main.h\r
- SockImpl.h\r
- Tcp4Output.c\r
- Tcp4Timer.c\r
- Tcp4Option.h\r
- Tcp4Dispatcher.c\r
- Tcp4Input.c\r
- Tcp4Misc.c\r
- Tcp4Main.c\r
- Socket.h\r
- ComponentName.c\r
- Tcp4Driver.h\r
- Tcp4Io.c\r
- Tcp4Driver.c\r
- Tcp4Func.h\r
- Tcp4Option.c\r
-\r
-\r
-[Packages]\r
- MdePkg/MdePkg.dec\r
- MdeModulePkg/MdeModulePkg.dec\r
-\r
-[LibraryClasses]\r
- UefiLib\r
- UefiBootServicesTableLib\r
- UefiDriverEntryPoint\r
- UefiRuntimeServicesTableLib\r
- BaseMemoryLib\r
- MemoryAllocationLib\r
- DebugLib\r
- NetLib\r
- IpIoLib\r
- DevicePathLib\r
- DpcLib\r
-\r
-[Protocols]\r
- gEfiTcp4ServiceBindingProtocolGuid ## BY_START\r
- gEfiIp4ServiceBindingProtocolGuid ## TO_START\r
- gEfiTcp4ProtocolGuid ## BY_START\r
- gEfiIp4ProtocolGuid ## TO_START\r
-\r
-[UserExtensions.TianoCore."ExtraFiles"]\r
- Tcp4DxeExtra.uni\r
+++ /dev/null
-// /** @file\r
-// This module produces EFI TCPv4 Protocol and EFI TCPv4 Service Binding Protocol.\r
-//\r
-// This module produces EFI TCPv4(Transmission Control Protocol version 4) Protocol\r
-// upon EFI IPv4 Protocol, to provide basic TCPv4 I/O services.\r
-//\r
-// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
-//\r
-// This program and the accompanying materials\r
-// are licensed and made available under the terms and conditions of the BSD License\r
-// which accompanies this distribution. The full text of the license may be found at\r
-// http://opensource.org/licenses/bsd-license.php\r
-//\r
-// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-//\r
-// **/\r
-\r
-\r
-#string STR_MODULE_ABSTRACT #language en-US "Produces EFI TCPv4 Protocol and EFI TCPv4 Service Binding Protocol"\r
-\r
-#string STR_MODULE_DESCRIPTION #language en-US "This module produces EFI TCPv4(Transmission Control Protocol version 4) Protocol upon EFI IPv4 Protocol to provide basic TCPv4 I/O services."\r
-\r
+++ /dev/null
-// /** @file\r
-// Tcp4Dxe Localized Strings and Content\r
-//\r
-// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>\r
-//\r
-// This program and the accompanying materials\r
-// are licensed and made available under the terms and conditions of the BSD License\r
-// which accompanies this distribution. The full text of the license may be found at\r
-// http://opensource.org/licenses/bsd-license.php\r
-//\r
-// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-//\r
-// **/\r
-\r
-#string STR_PROPERTIES_MODULE_NAME\r
-#language en-US\r
-"TCP v4 DXE Driver"\r
-\r
-\r
+++ /dev/null
-/** @file\r
- Tcp function header file.\r
-\r
-Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#ifndef _TCP4_FUNC_H_\r
-#define _TCP4_FUNC_H_\r
-\r
-//\r
-// Declaration of all the functions in TCP\r
-// protocol. It is intended to keep tcp.h\r
-// clear.\r
-//\r
-\r
-//\r
-// Functions in tcp.c\r
-//\r
-\r
-/**\r
- Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.\r
-\r
- @param Addr Pointer to the IP address needs to match.\r
- @param Port The port number needs to match.\r
-\r
- @return The Tcb which matches the <Addr Port> paire exists or not.\r
-\r
-**/\r
-BOOLEAN\r
-TcpFindTcbByPeer (\r
- IN EFI_IPv4_ADDRESS *Addr,\r
- IN TCP_PORTNO Port\r
- );\r
-\r
-/**\r
- Locate the TCP_CB related to the socket pair.\r
-\r
- @param LocalPort The local port number.\r
- @param LocalIp The local IP address.\r
- @param RemotePort The remote port number.\r
- @param RemoteIp The remote IP address.\r
- @param Syn Whether to search the listen sockets, if TRUE, the\r
- listen sockets are searched.\r
-\r
- @return Pointer to the related TCP_CB, if NULL no match is found.\r
-\r
-**/\r
-TCP_CB *\r
-TcpLocateTcb (\r
- IN TCP_PORTNO LocalPort,\r
- IN UINT32 LocalIp,\r
- IN TCP_PORTNO RemotePort,\r
- IN UINT32 RemoteIp,\r
- IN BOOLEAN Syn\r
- );\r
-\r
-/**\r
- Insert a Tcb into the proper queue.\r
-\r
- @param Tcb Pointer to the TCP_CB to be inserted.\r
-\r
- @retval 0 The Tcb is inserted successfully.\r
- @retval -1 Error condition occurred.\r
-\r
-**/\r
-INTN\r
-TcpInsertTcb (\r
- IN TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Clone a TCP_CB from Tcb.\r
-\r
- @param Tcb Pointer to the TCP_CB to be cloned.\r
-\r
- @return Pointer to the new cloned TCP_CB, if NULL error condition occurred.\r
-\r
-**/\r
-TCP_CB *\r
-TcpCloneTcb (\r
- IN TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Compute an ISS to be used by a new connection.\r
-\r
- @return The result ISS.\r
-\r
-**/\r
-TCP_SEQNO\r
-TcpGetIss (\r
- VOID\r
- );\r
-\r
-/**\r
- Initialize the Tcb local related members.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpInitTcbLocal (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Initialize the peer related members.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seg Pointer to the segment that contains the peer's\r
- intial info.\r
- @param Opt Pointer to the options announced by the peer.\r
-\r
-**/\r
-VOID\r
-TcpInitTcbPeer (\r
- IN OUT TCP_CB *Tcb,\r
- IN TCP_SEG *Seg,\r
- IN TCP_OPTION *Opt\r
- );\r
-\r
-/**\r
- Get the local mss.\r
-\r
- @param Sock Pointer to the socket to get mss\r
-\r
- @return The mss size.\r
-\r
-**/\r
-UINT16\r
-TcpGetRcvMss (\r
- IN SOCKET *Sock\r
- );\r
-\r
-/**\r
- Set the Tcb's state.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param State The state to be set.\r
-\r
-**/\r
-VOID\r
-TcpSetState (\r
- IN OUT TCP_CB *Tcb,\r
- IN UINT8 State\r
- );\r
-\r
-//\r
-// Functions in Tcp4Output.c\r
-//\r
-/**\r
- Send the segment to IP via IpIo function.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the TCP segment to be sent.\r
- @param Src Source address of the TCP segment.\r
- @param Dest Destination address of the TCP segment.\r
-\r
- @retval 0 The segment was sent out successfully.\r
- @retval -1 The segment was failed to send.\r
-\r
-**/\r
-INTN\r
-TcpSendIpPacket (\r
- IN TCP_CB *Tcb,\r
- IN NET_BUF *Nbuf,\r
- IN UINT32 Src,\r
- IN UINT32 Dest\r
- );\r
-\r
-/**\r
- Check whether to send data/SYN/FIN and piggy back an ACK.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Force Whether to ignore the sender's SWS avoidance algorithm and send\r
- out data by force.\r
-\r
- @return The number of bytes sent.\r
-\r
-**/\r
-INTN\r
-TcpToSendData (\r
- IN OUT TCP_CB *Tcb,\r
- IN INTN Force\r
- );\r
-\r
-/**\r
- Check whether to send an ACK or delayed ACK.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpToSendAck (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Send an ACK immediately.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpSendAck (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Send a zero probe segment. It can be used by keepalive and zero window probe.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @retval 0 The zero probe segment was sent out successfully.\r
- @retval other Error condition occurred.\r
-\r
-**/\r
-INTN\r
-TcpSendZeroProbe (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Process the data and FIN flag, check whether to deliver\r
- data to the socket layer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @retval 0 No error occurred to deliver data.\r
- @retval -1 Error condition occurred. Proper response is to reset the\r
- connection.\r
-\r
-**/\r
-INTN\r
-TcpDeliverData (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Send a RESET segment in response to the segment received.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance, may be NULL.\r
- @param Head TCP header of the segment that triggers the reset.\r
- @param Len Length of the segment that triggers the reset.\r
- @param Local Local IP address.\r
- @param Remote Remote peer's IP address.\r
-\r
- @retval 0 A reset is sent or no need to send it.\r
- @retval -1 No reset is sent.\r
-\r
-**/\r
-INTN\r
-TcpSendReset (\r
- IN TCP_CB *Tcb,\r
- IN TCP_HEAD *Head,\r
- IN INT32 Len,\r
- IN UINT32 Local,\r
- IN UINT32 Remote\r
- );\r
-\r
-/**\r
- Compute the sequence space left in the old receive window.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @return The sequence space left in the old receive window.\r
-\r
-**/\r
-UINT32\r
-TcpRcvWinOld (\r
- IN TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Compute the current receive window.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @return The size of the current receive window, in bytes.\r
-\r
-**/\r
-UINT32\r
-TcpRcvWinNow (\r
- IN TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Retransmit the segment from sequence Seq.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seq The sequence number of the segment to be retransmitted.\r
-\r
- @retval 0 Retransmission succeeded.\r
- @retval -1 Error condition occurred.\r
-\r
-**/\r
-INTN\r
-TcpRetransmit (\r
- IN TCP_CB *Tcb,\r
- IN TCP_SEQNO Seq\r
- );\r
-\r
-/**\r
- Compute how much data to send.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Force Whether to ignore the sender's SWS avoidance algorithm and send\r
- out data by force.\r
-\r
- @return The length of the data can be sent, if 0, no data can be sent.\r
-\r
-**/\r
-UINT32\r
-TcpDataToSend (\r
- IN TCP_CB *Tcb,\r
- IN INTN Force\r
- );\r
-\r
-/**\r
- Verify that the segment is in good shape.\r
-\r
- @param Nbuf Buffer that contains the segment to be checked.\r
-\r
- @retval 0 The segment is broken.\r
- @retval 1 The segment is in good shape.\r
-\r
-**/\r
-INTN\r
-TcpVerifySegment (\r
- IN NET_BUF *Nbuf\r
- );\r
-\r
-/**\r
- Verify that all the segments in SndQue are in good shape.\r
-\r
- @param Head Pointer to the head node of the SndQue.\r
-\r
- @retval 0 At least one segment is broken.\r
- @retval 1 All segments in the specific queue are in good shape.\r
-\r
-**/\r
-INTN\r
-TcpCheckSndQue (\r
- IN LIST_ENTRY *Head\r
- );\r
-\r
-/**\r
- Get a segment from the Tcb's SndQue.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seq The sequence number of the segment.\r
- @param Len The maximum length of the segment.\r
-\r
- @return Pointer to the segment, if NULL some error occurred.\r
-\r
-**/\r
-NET_BUF *\r
-TcpGetSegmentSndQue (\r
- IN TCP_CB *Tcb,\r
- IN TCP_SEQNO Seq,\r
- IN UINT32 Len\r
- );\r
-\r
-/**\r
- Get a segment from the Tcb's socket buffer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seq The sequence number of the segment.\r
- @param Len The maximum length of the segment.\r
-\r
- @return Pointer to the segment, if NULL some error occurred.\r
-\r
-**/\r
-NET_BUF *\r
-TcpGetSegmentSock (\r
- IN TCP_CB *Tcb,\r
- IN TCP_SEQNO Seq,\r
- IN UINT32 Len\r
- );\r
-\r
-/**\r
- Get a segment starting from sequence Seq of a maximum\r
- length of Len.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seq The sequence number of the segment.\r
- @param Len The maximum length of the segment.\r
-\r
- @return Pointer to the segment, if NULL some error occurred.\r
-\r
-**/\r
-NET_BUF *\r
-TcpGetSegment (\r
- IN TCP_CB *Tcb,\r
- IN TCP_SEQNO Seq,\r
- IN UINT32 Len\r
- );\r
-\r
-/**\r
- Get the maximum SndNxt.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @return The sequence number of the maximum SndNxt.\r
-\r
-**/\r
-TCP_SEQNO\r
-TcpGetMaxSndNxt (\r
- IN TCP_CB *Tcb\r
- );\r
-\r
-//\r
-// Functions from Tcp4Input.c\r
-//\r
-/**\r
- Process the received ICMP error messages for TCP.\r
-\r
- @param Nbuf Buffer that contains part of the TCP segment without IP header\r
- truncated from the ICMP error packet.\r
- @param IcmpErr The ICMP error code interpreted from ICMP error packet.\r
- @param Src Source address of the ICMP error message.\r
- @param Dst Destination address of the ICMP error message.\r
-\r
-**/\r
-VOID\r
-TcpIcmpInput (\r
- IN NET_BUF *Nbuf,\r
- IN UINT8 IcmpErr,\r
- IN UINT32 Src,\r
- IN UINT32 Dst\r
- );\r
-\r
-/**\r
- Process the received TCP segments.\r
-\r
- @param Nbuf Buffer that contains received TCP segment without IP header.\r
- @param Src Source address of the segment, or the peer's IP address.\r
- @param Dst Destination address of the segment, or the local end's IP\r
- address.\r
-\r
- @retval 0 Segment is processed successfully. It is either accepted or\r
- discarded. But no connection is reset by the segment.\r
- @retval -1 A connection is reset by the segment.\r
-\r
-**/\r
-INTN\r
-TcpInput (\r
- IN NET_BUF *Nbuf,\r
- IN UINT32 Src,\r
- IN UINT32 Dst\r
- );\r
-\r
-/**\r
- Check whether the sequence number of the incoming segment is acceptable.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seg Pointer to the incoming segment.\r
-\r
- @retval 1 The sequence number is acceptable.\r
- @retval 0 The sequence number is not acceptable.\r
-\r
-**/\r
-INTN\r
-TcpSeqAcceptable (\r
- IN TCP_CB *Tcb,\r
- IN TCP_SEG *Seg\r
- );\r
-\r
-/**\r
- NewReno fast recovery, RFC3782.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seg Segment that triggers the fast recovery.\r
-\r
-**/\r
-VOID\r
-TcpFastRecover (\r
- IN OUT TCP_CB *Tcb,\r
- IN TCP_SEG *Seg\r
- );\r
-\r
-/**\r
- NewReno fast loss recovery, RFC3792.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seg Segment that triggers the fast loss recovery.\r
-\r
-**/\r
-VOID\r
-TcpFastLossRecover (\r
- IN OUT TCP_CB *Tcb,\r
- IN TCP_SEG *Seg\r
- );\r
-\r
-/**\r
- Compute the RTT as specified in RFC2988.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Measure Currently measured RTT in heart beats.\r
-\r
-**/\r
-VOID\r
-TcpComputeRtt (\r
- IN OUT TCP_CB *Tcb,\r
- IN UINT32 Measure\r
- );\r
-\r
-/**\r
- Trim off the data outside the tcb's receive window.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the NET_BUF containing the received tcp segment.\r
-\r
-**/\r
-VOID\r
-TcpTrimInWnd (\r
- IN TCP_CB *Tcb,\r
- IN NET_BUF *Nbuf\r
- );\r
-\r
-/**\r
- Store the data into the reassemble queue.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the buffer containing the data to be queued.\r
-\r
-**/\r
-VOID\r
-TcpQueueData (\r
- IN OUT TCP_CB *Tcb,\r
- IN NET_BUF *Nbuf\r
- );\r
-\r
-/**\r
- Ajust the send queue or the retransmit queue.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Ack The acknowledge seuqence number of the received segment.\r
-\r
-**/\r
-VOID\r
-TcpAdjustSndQue (\r
- IN TCP_CB *Tcb,\r
- IN TCP_SEQNO Ack\r
- );\r
-\r
-//\r
-// Functions from Tcp4Misc.c\r
-//\r
-/**\r
- Compute the TCP segment's checksum.\r
-\r
- @param Nbuf Pointer to the buffer that contains the TCP\r
- segment.\r
- @param HeadSum The checksum value of the fixed part of pseudo\r
- header.\r
-\r
- @return The checksum value.\r
-\r
-**/\r
-UINT16\r
-TcpChecksum (\r
- IN NET_BUF *Nbuf,\r
- IN UINT16 HeadSum\r
- );\r
-\r
-/**\r
- Translate the information from the head of the received TCP\r
- segment Nbuf contains and fill it into a TCP_SEG structure.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the buffer contains the TCP segment.\r
-\r
- @return Pointer to the TCP_SEG that contains the translated TCP head information.\r
-\r
-**/\r
-TCP_SEG *\r
-TcpFormatNetbuf (\r
- IN TCP_CB *Tcb,\r
- IN OUT NET_BUF *Nbuf\r
- );\r
-\r
-/**\r
- Initialize an active connection.\r
-\r
- @param Tcb Pointer to the TCP_CB that wants to initiate a\r
- connection.\r
-\r
-**/\r
-VOID\r
-TcpOnAppConnect (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Application has consumed some data, check whether\r
- to send a window updata ack or a delayed ack.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpOnAppConsume (\r
- IN TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Initiate the connection close procedure, called when\r
- applications want to close the connection.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpOnAppClose (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Check whether the application's newly delivered data can be sent out.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @retval 0 Whether the data is sent out or is buffered for\r
- further sending.\r
- @retval -1 The Tcb is not in a state that data is permitted to\r
- be sent out.\r
-\r
-**/\r
-INTN\r
-TcpOnAppSend (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Abort the connection by sending a reset segment, called\r
- when the application wants to abort the connection.\r
-\r
- @param Tcb Pointer to the TCP_CB of the TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpOnAppAbort (\r
- IN TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Reset the connection related with Tcb.\r
-\r
- @param Tcb Pointer to the TCP_CB of the connection to be\r
- reset.\r
-\r
-**/\r
-VOID\r
-TcpResetConnection (\r
- IN TCP_CB *Tcb\r
- );\r
-\r
-//\r
-// Functions in Tcp4Timer.c\r
-//\r
-/**\r
- Close the TCP connection.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpClose (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Heart beat timer handler, queues the DPC at TPL_CALLBACK.\r
-\r
- @param Event Timer event signaled, ignored.\r
- @param Context Context of the timer event, ignored.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-TcpTicking (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- );\r
-\r
-/**\r
- Enable a TCP timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Timer The index of the timer to be enabled.\r
- @param TimeOut The timeout value of this timer.\r
-\r
-**/\r
-VOID\r
-TcpSetTimer (\r
- IN OUT TCP_CB *Tcb,\r
- IN UINT16 Timer,\r
- IN UINT32 TimeOut\r
- );\r
-\r
-/**\r
- Clear one TCP timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Timer The index of the timer to be cleared.\r
-\r
-**/\r
-VOID\r
-TcpClearTimer (\r
- IN OUT TCP_CB *Tcb,\r
- IN UINT16 Timer\r
- );\r
-\r
-/**\r
- Clear all TCP timers.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpClearAllTimer (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Enable the window prober timer and set the timeout value.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpSetProbeTimer (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Enable the keepalive timer and set the timeout value.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpSetKeepaliveTimer (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Backoff the RTO.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpBackoffRto (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Install the device path protocol on the TCP instance.\r
-\r
- @param Sock Pointer to the socket representing the TCP instance.\r
-\r
- @retval EFI_SUCCESS The device path protocol is installed.\r
- @retval other Failed to install the device path protocol.\r
-\r
-**/\r
-EFI_STATUS\r
-TcpInstallDevicePath (\r
- IN SOCKET *Sock\r
- );\r
-\r
-#endif\r
+++ /dev/null
-/** @file\r
- TCP input process routines.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-\r
-#include "Tcp4Main.h"\r
-\r
-\r
-/**\r
- Check whether the sequence number of the incoming segment is acceptable.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seg Pointer to the incoming segment.\r
-\r
- @retval 1 The sequence number is acceptable.\r
- @retval 0 The sequence number is not acceptable.\r
-\r
-**/\r
-INTN\r
-TcpSeqAcceptable (\r
- IN TCP_CB *Tcb,\r
- IN TCP_SEG *Seg\r
- )\r
-{\r
- return (TCP_SEQ_LEQ (Tcb->RcvNxt, Seg->End) &&\r
- TCP_SEQ_LT (Seg->Seq, Tcb->RcvWl2 + Tcb->RcvWnd));\r
-}\r
-\r
-\r
-/**\r
- NewReno fast recovery, RFC3782.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seg Segment that triggers the fast recovery.\r
-\r
-**/\r
-VOID\r
-TcpFastRecover (\r
- IN OUT TCP_CB *Tcb,\r
- IN TCP_SEG *Seg\r
- )\r
-{\r
- UINT32 FlightSize;\r
- UINT32 Acked;\r
-\r
- //\r
- // Step 1: Three duplicate ACKs and not in fast recovery\r
- //\r
- if (Tcb->CongestState != TCP_CONGEST_RECOVER) {\r
-\r
- //\r
- // Step 1A: Invoking fast retransmission.\r
- //\r
- FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);\r
-\r
- Tcb->Ssthresh = MAX (FlightSize >> 1, (UINT32) (2 * Tcb->SndMss));\r
- Tcb->Recover = Tcb->SndNxt;\r
-\r
- Tcb->CongestState = TCP_CONGEST_RECOVER;\r
- TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);\r
-\r
- //\r
- // Step 2: Entering fast retransmission\r
- //\r
- TcpRetransmit (Tcb, Tcb->SndUna);\r
- Tcb->CWnd = Tcb->Ssthresh + 3 * Tcb->SndMss;\r
-\r
- DEBUG ((EFI_D_NET, "TcpFastRecover: enter fast retransmission"\r
- " for TCB %p, recover point is %d\n", Tcb, Tcb->Recover));\r
- return;\r
- }\r
-\r
- //\r
- // During fast recovery, execute Step 3, 4, 5 of RFC3782\r
- //\r
- if (Seg->Ack == Tcb->SndUna) {\r
-\r
- //\r
- // Step 3: Fast Recovery,\r
- // If this is a duplicated ACK, increse Cwnd by SMSS.\r
- //\r
-\r
- // Step 4 is skipped here only to be executed later\r
- // by TcpToSendData\r
- //\r
- Tcb->CWnd += Tcb->SndMss;\r
- DEBUG ((EFI_D_NET, "TcpFastRecover: received another"\r
- " duplicated ACK (%d) for TCB %p\n", Seg->Ack, Tcb));\r
-\r
- } else {\r
-\r
- //\r
- // New data is ACKed, check whether it is a\r
- // full ACK or partial ACK\r
- //\r
- if (TCP_SEQ_GEQ (Seg->Ack, Tcb->Recover)) {\r
-\r
- //\r
- // Step 5 - Full ACK:\r
- // deflate the congestion window, and exit fast recovery\r
- //\r
- FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);\r
-\r
- Tcb->CWnd = MIN (Tcb->Ssthresh, FlightSize + Tcb->SndMss);\r
-\r
- Tcb->CongestState = TCP_CONGEST_OPEN;\r
- DEBUG ((EFI_D_NET, "TcpFastRecover: received a full ACK(%d)"\r
- " for TCB %p, exit fast recovery\n", Seg->Ack, Tcb));\r
-\r
- } else {\r
-\r
- //\r
- // Step 5 - Partial ACK:\r
- // fast retransmit the first unacknowledge field\r
- // , then deflate the CWnd\r
- //\r
- TcpRetransmit (Tcb, Seg->Ack);\r
- Acked = TCP_SUB_SEQ (Seg->Ack, Tcb->SndUna);\r
-\r
- //\r
- // Deflate the CWnd by the amount of new data\r
- // ACKed by SEG.ACK. If more than one SMSS data\r
- // is ACKed, add back SMSS byte to CWnd after\r
- //\r
- if (Acked >= Tcb->SndMss) {\r
- Acked -= Tcb->SndMss;\r
-\r
- }\r
-\r
- Tcb->CWnd -= Acked;\r
-\r
- DEBUG ((EFI_D_NET, "TcpFastRecover: received a partial"\r
- " ACK(%d) for TCB %p\n", Seg->Ack, Tcb));\r
-\r
- }\r
- }\r
-}\r
-\r
-\r
-/**\r
- NewReno fast loss recovery, RFC3792.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seg Segment that triggers the fast loss recovery.\r
-\r
-**/\r
-VOID\r
-TcpFastLossRecover (\r
- IN OUT TCP_CB *Tcb,\r
- IN TCP_SEG *Seg\r
- )\r
-{\r
- if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {\r
-\r
- //\r
- // New data is ACKed, check whether it is a\r
- // full ACK or partial ACK\r
- //\r
- if (TCP_SEQ_GEQ (Seg->Ack, Tcb->LossRecover)) {\r
-\r
- //\r
- // Full ACK: exit the loss recovery.\r
- //\r
- Tcb->LossTimes = 0;\r
- Tcb->CongestState = TCP_CONGEST_OPEN;\r
-\r
- DEBUG ((EFI_D_NET, "TcpFastLossRecover: received a "\r
- "full ACK(%d) for TCB %p\n", Seg->Ack, Tcb));\r
-\r
- } else {\r
-\r
- //\r
- // Partial ACK:\r
- // fast retransmit the first unacknowledge field.\r
- //\r
- TcpRetransmit (Tcb, Seg->Ack);\r
- DEBUG ((EFI_D_NET, "TcpFastLossRecover: received a "\r
- "partial ACK(%d) for TCB %p\n", Seg->Ack, Tcb));\r
- }\r
- }\r
-}\r
-\r
-\r
-/**\r
- Compute the RTT as specified in RFC2988.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Measure Currently measured RTT in heart beats.\r
-\r
-**/\r
-VOID\r
-TcpComputeRtt (\r
- IN OUT TCP_CB *Tcb,\r
- IN UINT32 Measure\r
- )\r
-{\r
- INT32 Var;\r
-\r
- //\r
- // Step 2.3: Compute the RTO for subsequent RTT measurement.\r
- //\r
- if (Tcb->SRtt != 0) {\r
-\r
- Var = Tcb->SRtt - (Measure << TCP_RTT_SHIFT);\r
-\r
- if (Var < 0) {\r
- Var = -Var;\r
- }\r
-\r
- Tcb->RttVar = (3 * Tcb->RttVar + Var) >> 2;\r
- Tcb->SRtt = 7 * (Tcb->SRtt >> 3) + Measure;\r
-\r
- } else {\r
- //\r
- // Step 2.2: compute the first RTT measure\r
- //\r
- Tcb->SRtt = Measure << TCP_RTT_SHIFT;\r
- Tcb->RttVar = Measure << (TCP_RTT_SHIFT - 1);\r
- }\r
-\r
- Tcb->Rto = (Tcb->SRtt + MAX (8, 4 * Tcb->RttVar)) >> TCP_RTT_SHIFT;\r
-\r
- //\r
- // Step 2.4: Limit the RTO to at least 1 second\r
- // Step 2.5: Limit the RTO to a maxium value that\r
- // is at least 60 second\r
- //\r
- if (Tcb->Rto < TCP_RTO_MIN) {\r
- Tcb->Rto = TCP_RTO_MIN;\r
-\r
- } else if (Tcb->Rto > TCP_RTO_MAX) {\r
- Tcb->Rto = TCP_RTO_MAX;\r
-\r
- }\r
-\r
- DEBUG ((EFI_D_NET, "TcpComputeRtt: new RTT for TCB %p"\r
- " computed SRTT: %d RTTVAR: %d RTO: %d\n",\r
- Tcb, Tcb->SRtt, Tcb->RttVar, Tcb->Rto));\r
-\r
-}\r
-\r
-\r
-/**\r
- Trim the data, SYN and FIN to fit into the window defined by Left and Right.\r
-\r
- @param Nbuf Buffer that contains received TCP segment without IP header.\r
- @param Left The sequence number of the window's left edge.\r
- @param Right The sequence number of the window's right edge.\r
-\r
-**/\r
-VOID\r
-TcpTrimSegment (\r
- IN NET_BUF *Nbuf,\r
- IN TCP_SEQNO Left,\r
- IN TCP_SEQNO Right\r
- )\r
-{\r
- TCP_SEG *Seg;\r
- TCP_SEQNO Urg;\r
- UINT32 Drop;\r
-\r
- Seg = TCPSEG_NETBUF (Nbuf);\r
-\r
- //\r
- // If the segment is completely out of window,\r
- // truncate every thing, include SYN and FIN.\r
- //\r
- if (TCP_SEQ_LEQ (Seg->End, Left) || TCP_SEQ_LEQ (Right, Seg->Seq)) {\r
-\r
- TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_SYN);\r
- TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_FIN);\r
-\r
- Seg->Seq = Seg->End;\r
- NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_HEAD);\r
- return;\r
- }\r
-\r
- //\r
- // Adjust the buffer header\r
- //\r
- if (TCP_SEQ_LT (Seg->Seq, Left)) {\r
-\r
- Drop = TCP_SUB_SEQ (Left, Seg->Seq);\r
- Urg = Seg->Seq + Seg->Urg;\r
- Seg->Seq = Left;\r
-\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {\r
- TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_SYN);\r
- Drop--;\r
- }\r
-\r
- //\r
- // Adjust the urgent point\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_URG)) {\r
-\r
- if (TCP_SEQ_LT (Urg, Seg->Seq)) {\r
-\r
- TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_URG);\r
- } else {\r
- Seg->Urg = (UINT16) TCP_SUB_SEQ (Urg, Seg->Seq);\r
- }\r
- }\r
-\r
- if (Drop != 0) {\r
- NetbufTrim (Nbuf, Drop, NET_BUF_HEAD);\r
- }\r
- }\r
-\r
- //\r
- // Adjust the buffer tail\r
- //\r
- if (TCP_SEQ_GT (Seg->End, Right)) {\r
-\r
- Drop = TCP_SUB_SEQ (Seg->End, Right);\r
- Seg->End = Right;\r
-\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {\r
- TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_FIN);\r
- Drop--;\r
- }\r
-\r
- if (Drop != 0) {\r
- NetbufTrim (Nbuf, Drop, NET_BUF_TAIL);\r
- }\r
- }\r
-\r
- ASSERT (TcpVerifySegment (Nbuf) != 0);\r
-}\r
-\r
-\r
-/**\r
- Trim off the data outside the tcb's receive window.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the NET_BUF containing the received tcp segment.\r
-\r
-**/\r
-VOID\r
-TcpTrimInWnd (\r
- IN TCP_CB *Tcb,\r
- IN NET_BUF *Nbuf\r
- )\r
-{\r
- TcpTrimSegment (Nbuf, Tcb->RcvNxt, Tcb->RcvWl2 + Tcb->RcvWnd);\r
-}\r
-\r
-\r
-/**\r
- Process the data and FIN flag, check whether to deliver\r
- data to the socket layer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @retval 0 No error occurred to deliver data.\r
- @retval -1 Error condition occurred. Proper response is to reset the\r
- connection.\r
-\r
-**/\r
-INTN\r
-TcpDeliverData (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- NET_BUF *Nbuf;\r
- TCP_SEQNO Seq;\r
- TCP_SEG *Seg;\r
- UINT32 Urgent;\r
-\r
- ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));\r
-\r
- //\r
- // make sure there is some data queued,\r
- // and TCP is in a proper state\r
- //\r
- if (IsListEmpty (&Tcb->RcvQue) || !TCP_CONNECTED (Tcb->State)) {\r
-\r
- return 0;\r
- }\r
-\r
- //\r
- // Deliver data to the socket layer\r
- //\r
- Entry = Tcb->RcvQue.ForwardLink;\r
- Seq = Tcb->RcvNxt;\r
-\r
- while (Entry != &Tcb->RcvQue) {\r
- Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);\r
- Seg = TCPSEG_NETBUF (Nbuf);\r
-\r
- ASSERT (TcpVerifySegment (Nbuf) != 0);\r
- ASSERT (Nbuf->Tcp == NULL);\r
-\r
- if (TCP_SEQ_GT (Seg->Seq, Seq)) {\r
- break;\r
- }\r
-\r
- Entry = Entry->ForwardLink;\r
- Seq = Seg->End;\r
- Tcb->RcvNxt = Seq;\r
-\r
- RemoveEntryList (&Nbuf->List);\r
-\r
- //\r
- // RFC793 Eighth step: process FIN in sequence\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {\r
-\r
- //\r
- // The peer sends to us junky data after FIN,\r
- // reset the connection.\r
- //\r
- if (!IsListEmpty (&Tcb->RcvQue)) {\r
- DEBUG ((EFI_D_ERROR, "TcpDeliverData: data received after"\r
- " FIN from peer of TCB %p, reset connection\n", Tcb));\r
-\r
- NetbufFree (Nbuf);\r
- return -1;\r
- }\r
-\r
- DEBUG ((EFI_D_NET, "TcpDeliverData: processing FIN "\r
- "from peer of TCB %p\n", Tcb));\r
-\r
- switch (Tcb->State) {\r
- case TCP_SYN_RCVD:\r
- case TCP_ESTABLISHED:\r
-\r
- TcpSetState (Tcb, TCP_CLOSE_WAIT);\r
- break;\r
-\r
- case TCP_FIN_WAIT_1:\r
-\r
- if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {\r
-\r
- TcpSetState (Tcb, TCP_CLOSING);\r
- break;\r
- }\r
-\r
- //\r
- // fall through\r
- //\r
- case TCP_FIN_WAIT_2:\r
-\r
- TcpSetState (Tcb, TCP_TIME_WAIT);\r
- TcpClearAllTimer (Tcb);\r
-\r
- if (Tcb->TimeWaitTimeout != 0) {\r
-\r
- TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);\r
- } else {\r
-\r
- DEBUG ((EFI_D_WARN, "Connection closed immediately "\r
- "because app disables TIME_WAIT timer for %p\n", Tcb));\r
-\r
- TcpSendAck (Tcb);\r
- TcpClose (Tcb);\r
- }\r
- break;\r
-\r
- case TCP_CLOSE_WAIT:\r
- case TCP_CLOSING:\r
- case TCP_LAST_ACK:\r
- case TCP_TIME_WAIT:\r
- //\r
- // The peer sends to us junk FIN byte. Discard\r
- // the buffer then reset the connection\r
- //\r
- NetbufFree (Nbuf);\r
- return -1;\r
- default:\r
- break;\r
- }\r
-\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);\r
-\r
- Seg->End--;\r
- }\r
-\r
- //\r
- // Don't delay the ack if PUSH flag is on.\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_PSH)) {\r
-\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);\r
- }\r
-\r
- if (Nbuf->TotalSize != 0) {\r
- Urgent = 0;\r
-\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG) &&\r
- TCP_SEQ_LEQ (Seg->Seq, Tcb->RcvUp)) {\r
-\r
- if (TCP_SEQ_LEQ (Seg->End, Tcb->RcvUp)) {\r
- Urgent = Nbuf->TotalSize;\r
- } else {\r
- Urgent = TCP_SUB_SEQ (Tcb->RcvUp, Seg->Seq) + 1;\r
- }\r
- }\r
-\r
- SockDataRcvd (Tcb->Sk, Nbuf, Urgent);\r
- }\r
-\r
- if (TCP_FIN_RCVD (Tcb->State)) {\r
-\r
- SockNoMoreData (Tcb->Sk);\r
- }\r
-\r
- NetbufFree (Nbuf);\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-\r
-/**\r
- Store the data into the reassemble queue.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the buffer containing the data to be queued.\r
-\r
-**/\r
-VOID\r
-TcpQueueData (\r
- IN OUT TCP_CB *Tcb,\r
- IN NET_BUF *Nbuf\r
- )\r
-{\r
- TCP_SEG *Seg;\r
- LIST_ENTRY *Head;\r
- LIST_ENTRY *Prev;\r
- LIST_ENTRY *Cur;\r
- NET_BUF *Node;\r
-\r
- ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));\r
-\r
- NET_GET_REF (Nbuf);\r
-\r
- Seg = TCPSEG_NETBUF (Nbuf);\r
- Head = &Tcb->RcvQue;\r
-\r
- //\r
- // Fast path to process normal case. That is,\r
- // no out-of-order segments are received.\r
- //\r
- if (IsListEmpty (Head)) {\r
-\r
- InsertTailList (Head, &Nbuf->List);\r
- return;\r
- }\r
-\r
- //\r
- // Find the point to insert the buffer\r
- //\r
- for (Prev = Head, Cur = Head->ForwardLink;\r
- Cur != Head;\r
- Prev = Cur, Cur = Cur->ForwardLink) {\r
-\r
- Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);\r
-\r
- if (TCP_SEQ_LT (Seg->Seq, TCPSEG_NETBUF (Node)->Seq)) {\r
- break;\r
- }\r
- }\r
-\r
- //\r
- // Check whether the current segment overlaps with the\r
- // previous segment.\r
- //\r
- if (Prev != Head) {\r
- Node = NET_LIST_USER_STRUCT (Prev, NET_BUF, List);\r
-\r
- if (TCP_SEQ_LT (Seg->Seq, TCPSEG_NETBUF (Node)->End)) {\r
-\r
- if (TCP_SEQ_LEQ (Seg->End, TCPSEG_NETBUF (Node)->End)) {\r
-\r
- NetbufFree (Nbuf);\r
- return;\r
- }\r
-\r
- TcpTrimSegment (Nbuf, TCPSEG_NETBUF (Node)->End, Seg->End);\r
- }\r
- }\r
-\r
- InsertHeadList (Prev, &Nbuf->List);\r
-\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);\r
-\r
- //\r
- // Check the segments after the insert point.\r
- //\r
- while (Cur != Head) {\r
- Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);\r
-\r
- if (TCP_SEQ_LEQ (TCPSEG_NETBUF (Node)->End, Seg->End)) {\r
-\r
- Cur = Cur->ForwardLink;\r
-\r
- RemoveEntryList (&Node->List);\r
- NetbufFree (Node);\r
- continue;\r
- }\r
-\r
- if (TCP_SEQ_LT (TCPSEG_NETBUF (Node)->Seq, Seg->End)) {\r
-\r
- if (TCP_SEQ_LEQ (TCPSEG_NETBUF (Node)->Seq, Seg->Seq)) {\r
-\r
- RemoveEntryList (&Nbuf->List);\r
- NetbufFree (Nbuf);\r
- return ;\r
- }\r
-\r
- TcpTrimSegment (Nbuf, Seg->Seq, TCPSEG_NETBUF (Node)->Seq);\r
- break;\r
- }\r
-\r
- Cur = Cur->ForwardLink;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Ajust the send queue or the retransmit queue.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Ack The acknowledge seuqence number of the received segment.\r
-\r
-**/\r
-VOID\r
-TcpAdjustSndQue (\r
- IN TCP_CB *Tcb,\r
- IN TCP_SEQNO Ack\r
- )\r
-{\r
- LIST_ENTRY *Head;\r
- LIST_ENTRY *Cur;\r
- NET_BUF *Node;\r
- TCP_SEG *Seg;\r
-\r
- Head = &Tcb->SndQue;\r
- Cur = Head->ForwardLink;\r
-\r
- while (Cur != Head) {\r
- Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);\r
- Seg = TCPSEG_NETBUF (Node);\r
-\r
- if (TCP_SEQ_GEQ (Seg->Seq, Ack)) {\r
- break;\r
- }\r
-\r
- //\r
- // Remove completely ACKed segments\r
- //\r
- if (TCP_SEQ_LEQ (Seg->End, Ack)) {\r
- Cur = Cur->ForwardLink;\r
-\r
- RemoveEntryList (&Node->List);\r
- NetbufFree (Node);\r
- continue;\r
- }\r
-\r
- TcpTrimSegment (Node, Ack, Seg->End);\r
- break;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Process the received TCP segments.\r
-\r
- @param Nbuf Buffer that contains received TCP segment without IP header.\r
- @param Src Source address of the segment, or the peer's IP address.\r
- @param Dst Destination address of the segment, or the local end's IP\r
- address.\r
-\r
- @retval 0 Segment is processed successfully. It is either accepted or\r
- discarded. But no connection is reset by the segment.\r
- @retval -1 A connection is reset by the segment.\r
-\r
-**/\r
-INTN\r
-TcpInput (\r
- IN NET_BUF *Nbuf,\r
- IN UINT32 Src,\r
- IN UINT32 Dst\r
- )\r
-{\r
- TCP_CB *Tcb;\r
- TCP_CB *Parent;\r
- TCP_OPTION Option;\r
- TCP_HEAD *Head;\r
- INT32 Len;\r
- TCP_SEG *Seg;\r
- TCP_SEQNO Right;\r
- TCP_SEQNO Urg;\r
- INT32 Usable;\r
-\r
- NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
-\r
- Parent = NULL;\r
- Tcb = NULL;\r
-\r
- Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL);\r
- ASSERT (Head != NULL);\r
-\r
- if (Nbuf->TotalSize < sizeof (TCP_HEAD)) {\r
- DEBUG ((EFI_D_NET, "TcpInput: received a malformed packet\n"));\r
- goto DISCARD;\r
- }\r
-\r
- Len = Nbuf->TotalSize - (Head->HeadLen << 2);\r
-\r
- if ((Head->HeadLen < 5) || (Len < 0) ||\r
- (TcpChecksum (Nbuf, NetPseudoHeadChecksum (Src, Dst, 6, 0)) != 0)) {\r
-\r
- DEBUG ((EFI_D_NET, "TcpInput: received a malformed packet\n"));\r
- goto DISCARD;\r
- }\r
-\r
- if (TCP_FLG_ON (Head->Flag, TCP_FLG_SYN)) {\r
- Len++;\r
- }\r
-\r
- if (TCP_FLG_ON (Head->Flag, TCP_FLG_FIN)) {\r
- Len++;\r
- }\r
-\r
- Tcb = TcpLocateTcb (\r
- Head->DstPort,\r
- Dst,\r
- Head->SrcPort,\r
- Src,\r
- (BOOLEAN) TCP_FLG_ON (Head->Flag, TCP_FLG_SYN)\r
- );\r
-\r
- if ((Tcb == NULL) || (Tcb->State == TCP_CLOSED)) {\r
- DEBUG ((EFI_D_NET, "TcpInput: send reset because no TCB found\n"));\r
-\r
- Tcb = NULL;\r
- goto SEND_RESET;\r
- }\r
-\r
- Seg = TcpFormatNetbuf (Tcb, Nbuf);\r
-\r
- //\r
- // RFC1122 recommended reaction to illegal option\r
- // (in fact, an illegal option length) is reset.\r
- //\r
- if (TcpParseOption (Nbuf->Tcp, &Option) == -1) {\r
- DEBUG ((EFI_D_ERROR, "TcpInput: reset the peer because"\r
- " of malformed option for TCB %p\n", Tcb));\r
-\r
- goto SEND_RESET;\r
- }\r
-\r
- //\r
- // From now on, the segment is headless\r
- //\r
- NetbufTrim (Nbuf, (Head->HeadLen << 2), NET_BUF_HEAD);\r
- Nbuf->Tcp = NULL;\r
-\r
- //\r
- // Process the segment in LISTEN state.\r
- //\r
- if (Tcb->State == TCP_LISTEN) {\r
- //\r
- // First step: Check RST\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {\r
- DEBUG ((EFI_D_WARN, "TcpInput: discard a reset segment "\r
- "for TCB %p in listening\n", Tcb));\r
-\r
- goto DISCARD;\r
- }\r
-\r
- //\r
- // Second step: Check ACK.\r
- // Any ACK sent to TCP in LISTEN is reseted.\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {\r
- DEBUG ((EFI_D_WARN, "TcpInput: send reset because of"\r
- " segment with ACK for TCB %p in listening\n", Tcb));\r
-\r
- goto SEND_RESET;\r
- }\r
-\r
- //\r
- // Third step: Check SYN\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {\r
- //\r
- // create a child TCB to handle the data\r
- //\r
- Parent = Tcb;\r
-\r
- Tcb = TcpCloneTcb (Parent);\r
- if (Tcb == NULL) {\r
- DEBUG ((EFI_D_ERROR, "TcpInput: discard a segment because"\r
- " failed to clone a child for TCB %p\n", Tcb));\r
-\r
- goto DISCARD;\r
- }\r
-\r
- DEBUG ((EFI_D_NET, "TcpInput: create a child for TCB %p"\r
- " in listening\n", Tcb));\r
-\r
- //\r
- // init the TCB structure\r
- //\r
- Tcb->LocalEnd.Ip = Dst;\r
- Tcb->LocalEnd.Port = Head->DstPort;\r
- Tcb->RemoteEnd.Ip = Src;\r
- Tcb->RemoteEnd.Port = Head->SrcPort;\r
-\r
- TcpInitTcbLocal (Tcb);\r
- TcpInitTcbPeer (Tcb, Seg, &Option);\r
-\r
- TcpSetState (Tcb, TCP_SYN_RCVD);\r
- TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);\r
- TcpTrimInWnd (Tcb, Nbuf);\r
-\r
- goto StepSix;\r
- }\r
-\r
- goto DISCARD;\r
-\r
- } else if (Tcb->State == TCP_SYN_SENT) {\r
- //\r
- // First step: Check ACK bit\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK) && (Seg->Ack != Tcb->Iss + 1)) {\r
-\r
- DEBUG ((EFI_D_WARN, "TcpInput: send reset because of "\r
- "wrong ACK received for TCB %p in SYN_SENT\n", Tcb));\r
-\r
- goto SEND_RESET;\r
- }\r
-\r
- //\r
- // Second step: Check RST bit\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {\r
-\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {\r
-\r
- DEBUG ((EFI_D_WARN, "TcpInput: connection reset by"\r
- " peer for TCB %p in SYN_SENT\n", Tcb));\r
-\r
- SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);\r
- goto DROP_CONNECTION;\r
- } else {\r
-\r
- DEBUG ((EFI_D_WARN, "TcpInput: discard a reset segment "\r
- "because of no ACK for TCB %p in SYN_SENT\n", Tcb));\r
-\r
- goto DISCARD;\r
- }\r
- }\r
-\r
- //\r
- // Third step: Check security and precedence. Skipped\r
- //\r
-\r
- //\r
- // Fourth step: Check SYN. Pay attention to simultaneous open\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {\r
-\r
- TcpInitTcbPeer (Tcb, Seg, &Option);\r
-\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {\r
-\r
- Tcb->SndUna = Seg->Ack;\r
- }\r
-\r
- TcpClearTimer (Tcb, TCP_TIMER_REXMIT);\r
-\r
- if (TCP_SEQ_GT (Tcb->SndUna, Tcb->Iss)) {\r
-\r
- TcpSetState (Tcb, TCP_ESTABLISHED);\r
-\r
- TcpClearTimer (Tcb, TCP_TIMER_CONNECT);\r
- TcpDeliverData (Tcb);\r
-\r
- if ((Tcb->CongestState == TCP_CONGEST_OPEN) &&\r
- TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {\r
-\r
- TcpComputeRtt (Tcb, Tcb->RttMeasure);\r
- TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);\r
- }\r
-\r
- TcpTrimInWnd (Tcb, Nbuf);\r
-\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);\r
-\r
- DEBUG ((EFI_D_NET, "TcpInput: connection established"\r
- " for TCB %p in SYN_SENT\n", Tcb));\r
-\r
- goto StepSix;\r
- } else {\r
- //\r
- // Received a SYN segment without ACK, simultaneous open.\r
- //\r
- TcpSetState (Tcb, TCP_SYN_RCVD);\r
-\r
- ASSERT (Tcb->SndNxt == Tcb->Iss + 1);\r
- TcpAdjustSndQue (Tcb, Tcb->SndNxt);\r
-\r
- TcpTrimInWnd (Tcb, Nbuf);\r
-\r
- DEBUG ((EFI_D_WARN, "TcpInput: simultaneous open "\r
- "for TCB %p in SYN_SENT\n", Tcb));\r
-\r
- goto StepSix;\r
- }\r
- }\r
-\r
- goto DISCARD;\r
- }\r
-\r
- //\r
- // Process segment in SYN_RCVD or TCP_CONNECTED states\r
- //\r
-\r
- //\r
- // Clear probe timer since the RecvWindow is opened.\r
- //\r
- if (Tcb->ProbeTimerOn && (Seg->Wnd != 0)) {\r
- TcpClearTimer (Tcb, TCP_TIMER_PROBE);\r
- Tcb->ProbeTimerOn = FALSE;\r
- }\r
-\r
- //\r
- // First step: Check whether SEG.SEQ is acceptable\r
- //\r
- if (TcpSeqAcceptable (Tcb, Seg) == 0) {\r
- DEBUG ((EFI_D_WARN, "TcpInput: sequence acceptance"\r
- " test failed for segment of TCB %p\n", Tcb));\r
-\r
- if (!TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {\r
- TcpSendAck (Tcb);\r
- }\r
-\r
- goto DISCARD;\r
- }\r
-\r
- if ((TCP_SEQ_LT (Seg->Seq, Tcb->RcvWl2)) &&\r
- (Tcb->RcvWl2 == Seg->End) &&\r
- !TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN | TCP_FLG_FIN)) {\r
-\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);\r
- }\r
-\r
- //\r
- // Second step: Check the RST\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {\r
-\r
- DEBUG ((EFI_D_WARN, "TcpInput: connection reset for TCB %p\n", Tcb));\r
-\r
- if (Tcb->State == TCP_SYN_RCVD) {\r
-\r
- SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_REFUSED);\r
-\r
- //\r
- // This TCB comes from either a LISTEN TCB,\r
- // or active open TCB with simultanous open.\r
- // Do NOT signal user CONNECTION refused\r
- // if it comes from a LISTEN TCB.\r
- //\r
- } else if ((Tcb->State == TCP_ESTABLISHED) ||\r
- (Tcb->State == TCP_FIN_WAIT_1) ||\r
- (Tcb->State == TCP_FIN_WAIT_2) ||\r
- (Tcb->State == TCP_CLOSE_WAIT)) {\r
-\r
- SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);\r
-\r
- } else {\r
-\r
- }\r
-\r
- goto DROP_CONNECTION;\r
- }\r
-\r
- //\r
- // Trim the data and flags.\r
- //\r
- TcpTrimInWnd (Tcb, Nbuf);\r
-\r
- //\r
- // Third step: Check security and precedence, Ignored\r
- //\r
-\r
- //\r
- // Fourth step: Check the SYN bit.\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {\r
-\r
- DEBUG ((EFI_D_WARN, "TcpInput: connection reset "\r
- "because received extra SYN for TCB %p\n", Tcb));\r
-\r
- SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);\r
- goto RESET_THEN_DROP;\r
- }\r
-\r
- //\r
- // Fifth step: Check the ACK\r
- //\r
- if (!TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {\r
- DEBUG ((EFI_D_WARN, "TcpInput: segment discard because"\r
- " of no ACK for connected TCB %p\n", Tcb));\r
-\r
- goto DISCARD;\r
-\r
- }\r
-\r
- if (Tcb->State == TCP_SYN_RCVD) {\r
-\r
- if (TCP_SEQ_LT (Tcb->SndUna, Seg->Ack) &&\r
- TCP_SEQ_LEQ (Seg->Ack, Tcb->SndNxt)) {\r
-\r
- Tcb->SndWnd = Seg->Wnd;\r
- Tcb->SndWndMax = MAX (Tcb->SndWnd, Tcb->SndWndMax);\r
- Tcb->SndWl1 = Seg->Seq;\r
- Tcb->SndWl2 = Seg->Ack;\r
- TcpSetState (Tcb, TCP_ESTABLISHED);\r
-\r
- TcpClearTimer (Tcb, TCP_TIMER_CONNECT);\r
- TcpDeliverData (Tcb);\r
-\r
- DEBUG ((EFI_D_NET, "TcpInput: connection established "\r
- " for TCB %p in SYN_RCVD\n", Tcb));\r
-\r
- //\r
- // Continue the process as ESTABLISHED state\r
- //\r
- } else {\r
- DEBUG ((EFI_D_WARN, "TcpInput: send reset because of"\r
- " wrong ACK for TCB %p in SYN_RCVD\n", Tcb));\r
-\r
- goto SEND_RESET;\r
- }\r
- }\r
-\r
- if (TCP_SEQ_LT (Seg->Ack, Tcb->SndUna)) {\r
-\r
- DEBUG ((EFI_D_WARN, "TcpInput: ignore the out-of-data"\r
- " ACK for connected TCB %p\n", Tcb));\r
-\r
- goto StepSix;\r
-\r
- } else if (TCP_SEQ_GT (Seg->Ack, Tcb->SndNxt)) {\r
-\r
- DEBUG ((EFI_D_WARN, "TcpInput: discard segment for "\r
- "future ACK for connected TCB %p\n", Tcb));\r
-\r
- TcpSendAck (Tcb);\r
- goto DISCARD;\r
- }\r
-\r
- //\r
- // From now on: SND.UNA <= SEG.ACK <= SND.NXT.\r
- //\r
- if (TCP_FLG_ON (Option.Flag, TCP_OPTION_RCVD_TS)) {\r
- //\r
- // update TsRecent as specified in page 16 RFC1323.\r
- // RcvWl2 equals to the variable "LastAckSent"\r
- // defined there.\r
- //\r
- if (TCP_SEQ_LEQ (Seg->Seq, Tcb->RcvWl2) &&\r
- TCP_SEQ_LT (Tcb->RcvWl2, Seg->End)) {\r
-\r
- Tcb->TsRecent = Option.TSVal;\r
- Tcb->TsRecentAge = mTcpTick;\r
- }\r
-\r
- TcpComputeRtt (Tcb, TCP_SUB_TIME (mTcpTick, Option.TSEcr));\r
-\r
- } else if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {\r
-\r
- ASSERT (Tcb->CongestState == TCP_CONGEST_OPEN);\r
-\r
- TcpComputeRtt (Tcb, Tcb->RttMeasure);\r
- TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);\r
- }\r
-\r
- if (Seg->Ack == Tcb->SndNxt) {\r
-\r
- TcpClearTimer (Tcb, TCP_TIMER_REXMIT);\r
- } else {\r
-\r
- TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);\r
- }\r
-\r
- //\r
- // Count duplicate acks.\r
- //\r
- if ((Seg->Ack == Tcb->SndUna) &&\r
- (Tcb->SndUna != Tcb->SndNxt) &&\r
- (Seg->Wnd == Tcb->SndWnd) &&\r
- (0 == Len)) {\r
-\r
- Tcb->DupAck++;\r
- } else {\r
-\r
- Tcb->DupAck = 0;\r
- }\r
-\r
- //\r
- // Congestion avoidance, fast recovery and fast retransmission.\r
- //\r
- if (((Tcb->CongestState == TCP_CONGEST_OPEN) && (Tcb->DupAck < 3)) ||\r
- (Tcb->CongestState == TCP_CONGEST_LOSS)) {\r
-\r
- if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {\r
-\r
- if (Tcb->CWnd < Tcb->Ssthresh) {\r
-\r
- Tcb->CWnd += Tcb->SndMss;\r
- } else {\r
-\r
- Tcb->CWnd += MAX (Tcb->SndMss * Tcb->SndMss / Tcb->CWnd, 1);\r
- }\r
-\r
- Tcb->CWnd = MIN (Tcb->CWnd, TCP_MAX_WIN << Tcb->SndWndScale);\r
- }\r
-\r
- if (Tcb->CongestState == TCP_CONGEST_LOSS) {\r
- TcpFastLossRecover (Tcb, Seg);\r
- }\r
- } else {\r
-\r
- TcpFastRecover (Tcb, Seg);\r
- }\r
-\r
- if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {\r
-\r
- TcpAdjustSndQue (Tcb, Seg->Ack);\r
- Tcb->SndUna = Seg->Ack;\r
-\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_URG) &&\r
- TCP_SEQ_LT (Tcb->SndUp, Seg->Ack)) {\r
-\r
- TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);\r
- }\r
- }\r
-\r
- //\r
- // Update window info\r
- //\r
- if (TCP_SEQ_LT (Tcb->SndWl1, Seg->Seq) ||\r
- ((Tcb->SndWl1 == Seg->Seq) && TCP_SEQ_LEQ (Tcb->SndWl2, Seg->Ack))) {\r
-\r
- Right = Seg->Ack + Seg->Wnd;\r
-\r
- if (TCP_SEQ_LT (Right, Tcb->SndWl2 + Tcb->SndWnd)) {\r
-\r
- if ((Tcb->SndWl1 == Seg->Seq) &&\r
- (Tcb->SndWl2 == Seg->Ack) &&\r
- (Len == 0)) {\r
-\r
- goto NO_UPDATE;\r
- }\r
-\r
- DEBUG ((EFI_D_WARN, "TcpInput: peer shrinks the"\r
- " window for connected TCB %p\n", Tcb));\r
-\r
- if ((Tcb->CongestState == TCP_CONGEST_RECOVER) &&\r
- (TCP_SEQ_LT (Right, Tcb->Recover))) {\r
-\r
- Tcb->Recover = Right;\r
- }\r
-\r
- if ((Tcb->CongestState == TCP_CONGEST_LOSS) &&\r
- (TCP_SEQ_LT (Right, Tcb->LossRecover))) {\r
-\r
- Tcb->LossRecover = Right;\r
- }\r
-\r
- if (TCP_SEQ_LT (Right, Tcb->SndNxt)) {\r
- //\r
- // Check for Window Retraction in RFC7923 section 2.4.\r
- // The lower n bits of the peer's actual receive window is wiped out if TCP\r
- // window scale is enabled, it will look like the peer is shrinking the window.\r
- // Check whether the SndNxt is out of the advertised receive window by more than\r
- // 2^Rcv.Wind.Shift before moving the SndNxt to the left.\r
- //\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "TcpInput: peer advise negative useable window for connected TCB %p\n",\r
- Tcb)\r
- );\r
- Usable = TCP_SUB_SEQ (Tcb->SndNxt, Right);\r
- if ((Usable >> Tcb->SndWndScale) > 0) {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "TcpInput: SndNxt is out of window by more than window scale for TCB %p\n",\r
- Tcb)\r
- );\r
- Tcb->SndNxt = Right;\r
- }\r
- if (Right == Tcb->SndUna) {\r
-\r
- TcpClearTimer (Tcb, TCP_TIMER_REXMIT);\r
- TcpSetProbeTimer (Tcb);\r
- }\r
- }\r
- }\r
-\r
- Tcb->SndWnd = Seg->Wnd;\r
- Tcb->SndWndMax = MAX (Tcb->SndWnd, Tcb->SndWndMax);\r
- Tcb->SndWl1 = Seg->Seq;\r
- Tcb->SndWl2 = Seg->Ack;\r
- }\r
-\r
-NO_UPDATE:\r
-\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT) &&\r
- (Tcb->SndUna == Tcb->SndNxt)) {\r
-\r
- DEBUG ((EFI_D_NET, "TcpInput: local FIN is ACKed by"\r
- " peer for connected TCB %p\n", Tcb));\r
-\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED);\r
- }\r
-\r
- //\r
- // Transit the state if proper.\r
- //\r
- switch (Tcb->State) {\r
- case TCP_FIN_WAIT_1:\r
-\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {\r
-\r
- TcpSetState (Tcb, TCP_FIN_WAIT_2);\r
-\r
- TcpClearAllTimer (Tcb);\r
- TcpSetTimer (Tcb, TCP_TIMER_FINWAIT2, Tcb->FinWait2Timeout);\r
- }\r
-\r
- case TCP_FIN_WAIT_2:\r
-\r
- break;\r
-\r
- case TCP_CLOSE_WAIT:\r
- break;\r
-\r
- case TCP_CLOSING:\r
-\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {\r
-\r
- TcpSetState (Tcb, TCP_TIME_WAIT);\r
-\r
- TcpClearAllTimer (Tcb);\r
-\r
- if (Tcb->TimeWaitTimeout != 0) {\r
-\r
- TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);\r
- } else {\r
-\r
- DEBUG ((EFI_D_WARN, "Connection closed immediately "\r
- "because app disables TIME_WAIT timer for %p\n", Tcb));\r
-\r
- TcpClose (Tcb);\r
- }\r
- }\r
- break;\r
-\r
- case TCP_LAST_ACK:\r
-\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {\r
-\r
- TcpSetState (Tcb, TCP_CLOSED);\r
- }\r
-\r
- break;\r
-\r
- case TCP_TIME_WAIT:\r
-\r
- TcpSendAck (Tcb);\r
-\r
- if (Tcb->TimeWaitTimeout != 0) {\r
-\r
- TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);\r
- } else {\r
-\r
- DEBUG ((EFI_D_WARN, "Connection closed immediately "\r
- "because app disables TIME_WAIT timer for %p\n", Tcb));\r
-\r
- TcpClose (Tcb);\r
- }\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- //\r
- // Sixth step: Check the URG bit.update the Urg point\r
- // if in TCP_CAN_RECV, otherwise, leave the RcvUp intact.\r
- //\r
-StepSix:\r
-\r
- Tcb->Idle = 0;\r
- TcpSetKeepaliveTimer (Tcb);\r
-\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_URG) &&\r
- !TCP_FIN_RCVD (Tcb->State))\r
- {\r
-\r
- DEBUG ((EFI_D_NET, "TcpInput: received urgent data "\r
- "from peer for connected TCB %p\n", Tcb));\r
-\r
- Urg = Seg->Seq + Seg->Urg;\r
-\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG) &&\r
- TCP_SEQ_GT (Urg, Tcb->RcvUp)) {\r
-\r
- Tcb->RcvUp = Urg;\r
- } else {\r
-\r
- Tcb->RcvUp = Urg;\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG);\r
- }\r
- }\r
-\r
- //\r
- // Seventh step: Process the segment data\r
- //\r
- if (Seg->End != Seg->Seq) {\r
-\r
- if (TCP_FIN_RCVD (Tcb->State)) {\r
-\r
- DEBUG ((EFI_D_WARN, "TcpInput: connection reset because"\r
- " data is lost for connected TCB %p\n", Tcb));\r
-\r
- goto RESET_THEN_DROP;\r
- }\r
-\r
- if (TCP_LOCAL_CLOSED (Tcb->State) && (Nbuf->TotalSize != 0)) {\r
- DEBUG ((EFI_D_WARN, "TcpInput: connection reset because"\r
- " data is lost for connected TCB %p\n", Tcb));\r
-\r
- goto RESET_THEN_DROP;\r
- }\r
-\r
- TcpQueueData (Tcb, Nbuf);\r
- if (TcpDeliverData (Tcb) == -1) {\r
- goto RESET_THEN_DROP;\r
- }\r
-\r
- if (!IsListEmpty (&Tcb->RcvQue)) {\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);\r
- }\r
- }\r
-\r
- //\r
- // Eighth step: check the FIN.\r
- // This step is moved to TcpDeliverData. FIN will be\r
- // processed in sequence there. Check the comments in\r
- // the beginning of the file header for information.\r
- //\r
-\r
- //\r
- // Tcb is a new child of the listening Parent,\r
- // commit it.\r
- //\r
- if (Parent != NULL) {\r
- Tcb->Parent = Parent;\r
- TcpInsertTcb (Tcb);\r
- }\r
-\r
- if ((Tcb->State != TCP_CLOSED) &&\r
- (TcpToSendData (Tcb, 0) == 0) &&\r
- (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW) || (Nbuf->TotalSize != 0))) {\r
-\r
- TcpToSendAck (Tcb);\r
- }\r
-\r
- NetbufFree (Nbuf);\r
- return 0;\r
-\r
-RESET_THEN_DROP:\r
- TcpSendReset (Tcb, Head, Len, Dst, Src);\r
-\r
-DROP_CONNECTION:\r
- ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));\r
-\r
- NetbufFree (Nbuf);\r
- TcpClose (Tcb);\r
-\r
- return -1;\r
-\r
-SEND_RESET:\r
-\r
- TcpSendReset (Tcb, Head, Len, Dst, Src);\r
-\r
-DISCARD:\r
-\r
- //\r
- // Tcb is a child of Parent, and it doesn't survive\r
- //\r
- DEBUG ((EFI_D_WARN, "Tcp4Input: Discard a packet\n"));\r
- NetbufFree (Nbuf);\r
-\r
- if ((Parent != NULL) && (Tcb != NULL)) {\r
-\r
- ASSERT (Tcb->Sk != NULL);\r
- TcpClose (Tcb);\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-\r
-/**\r
- Process the received ICMP error messages for TCP.\r
-\r
- @param Nbuf Buffer that contains part of the TCP segment without IP header\r
- truncated from the ICMP error packet.\r
- @param IcmpErr The ICMP error code interpreted from ICMP error packet.\r
- @param Src Source address of the ICMP error message.\r
- @param Dst Destination address of the ICMP error message.\r
-\r
-**/\r
-VOID\r
-TcpIcmpInput (\r
- IN NET_BUF *Nbuf,\r
- IN UINT8 IcmpErr,\r
- IN UINT32 Src,\r
- IN UINT32 Dst\r
- )\r
-{\r
- TCP_HEAD *Head;\r
- TCP_CB *Tcb;\r
- TCP_SEQNO Seq;\r
- EFI_STATUS IcmpErrStatus;\r
- BOOLEAN IcmpErrIsHard;\r
- BOOLEAN IcmpErrNotify;\r
-\r
- if (Nbuf->TotalSize < sizeof (TCP_HEAD)) {\r
- goto CLEAN_EXIT;\r
- }\r
-\r
- Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL);\r
- ASSERT (Head != NULL);\r
- Tcb = TcpLocateTcb (\r
- Head->DstPort,\r
- Dst,\r
- Head->SrcPort,\r
- Src,\r
- FALSE\r
- );\r
- if (Tcb == NULL || Tcb->State == TCP_CLOSED) {\r
-\r
- goto CLEAN_EXIT;\r
- }\r
-\r
- //\r
- // Validate the sequence number.\r
- //\r
- Seq = NTOHL (Head->Seq);\r
- if (!(TCP_SEQ_LEQ (Tcb->SndUna, Seq) && TCP_SEQ_LT (Seq, Tcb->SndNxt))) {\r
-\r
- goto CLEAN_EXIT;\r
- }\r
-\r
- IcmpErrStatus = IpIoGetIcmpErrStatus (\r
- IcmpErr,\r
- IP_VERSION_4,\r
- &IcmpErrIsHard,\r
- &IcmpErrNotify\r
- );\r
-\r
- if (IcmpErrNotify) {\r
-\r
- SOCK_ERROR (Tcb->Sk, IcmpErrStatus);\r
- }\r
-\r
- if (IcmpErrIsHard) {\r
-\r
- TcpClose (Tcb);\r
- }\r
-\r
-CLEAN_EXIT:\r
- NetbufFree (Nbuf);\r
-}\r
+++ /dev/null
-/** @file\r
- I/O interfaces between TCP and IpIo.\r
-\r
-Copyright (c) 2005 - 2009, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Tcp4Main.h"\r
-\r
-\r
-/**\r
- Packet receive callback function provided to IP_IO, used to call\r
- the proper function to handle the packet received by IP.\r
-\r
- @param Status Status of the received packet.\r
- @param IcmpErr ICMP error number.\r
- @param NetSession Pointer to the net session of this packet.\r
- @param Pkt Pointer to the recieved packet.\r
- @param Context Pointer to the context configured in IpIoOpen(), not used\r
- now.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Tcp4RxCallback (\r
- IN EFI_STATUS Status,\r
- IN UINT8 IcmpErr,\r
- IN EFI_NET_SESSION_DATA *NetSession,\r
- IN NET_BUF *Pkt,\r
- IN VOID *Context OPTIONAL\r
- )\r
-{\r
- if (EFI_SUCCESS == Status) {\r
- TcpInput (Pkt, NetSession->Source.Addr[0], NetSession->Dest.Addr[0]);\r
- } else {\r
- TcpIcmpInput (Pkt, IcmpErr, NetSession->Source.Addr[0], NetSession->Dest.Addr[0]);\r
- }\r
-}\r
-\r
-\r
-/**\r
- Send the segment to IP via IpIo function.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the TCP segment to be sent.\r
- @param Src Source address of the TCP segment.\r
- @param Dest Destination address of the TCP segment.\r
-\r
- @retval 0 The segment was sent out successfully.\r
- @retval -1 The segment was failed to send.\r
-\r
-**/\r
-INTN\r
-TcpSendIpPacket (\r
- IN TCP_CB *Tcb,\r
- IN NET_BUF *Nbuf,\r
- IN UINT32 Src,\r
- IN UINT32 Dest\r
- )\r
-{\r
- EFI_STATUS Status;\r
- IP_IO *IpIo;\r
- IP_IO_OVERRIDE Override;\r
- SOCKET *Sock;\r
- VOID *IpSender;\r
- TCP4_PROTO_DATA *TcpProto;\r
- EFI_IP_ADDRESS Source;\r
- EFI_IP_ADDRESS Destination;\r
-\r
- Source.Addr[0] = Src;\r
- Destination.Addr[0] = Dest;\r
-\r
- if (NULL == Tcb) {\r
-\r
- IpIo = NULL;\r
- IpSender = IpIoFindSender (&IpIo, IP_VERSION_4, &Source);\r
-\r
- if (IpSender == NULL) {\r
- DEBUG ((EFI_D_WARN, "TcpSendIpPacket: No appropriate IpSender.\n"));\r
- return -1;\r
- }\r
- } else {\r
-\r
- Sock = Tcb->Sk;\r
- TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;\r
- IpIo = TcpProto->TcpService->IpIo;\r
- IpSender = Tcb->IpInfo;\r
- }\r
-\r
- Override.Ip4OverrideData.TypeOfService = 0;\r
- Override.Ip4OverrideData.TimeToLive = 255;\r
- Override.Ip4OverrideData.DoNotFragment = FALSE;\r
- Override.Ip4OverrideData.Protocol = EFI_IP_PROTO_TCP;\r
- ZeroMem (&Override.Ip4OverrideData.GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r
- CopyMem (&Override.Ip4OverrideData.SourceAddress, &Src, sizeof (EFI_IPv4_ADDRESS));\r
-\r
- Status = IpIoSend (IpIo, Nbuf, IpSender, NULL, NULL, &Destination, &Override);\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "TcpSendIpPacket: return %r error\n", Status));\r
- return -1;\r
- }\r
-\r
- return 0;\r
-}\r
+++ /dev/null
-/** @file\r
- Implementation of TCP4 protocol services.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-\r
-#include "Tcp4Main.h"\r
-\r
-\r
-/**\r
- Check the integrity of the data buffer.\r
-\r
- @param DataLen The total length of the data buffer.\r
- @param FragmentCount The fragment count of the fragment table.\r
- @param FragmentTable Pointer to the fragment table of the data\r
- buffer.\r
-\r
- @retval EFI_SUCCESS The integrity check is passed.\r
- @retval EFI_INVALID_PARAMETER The integrity check is failed.\r
-\r
-**/\r
-EFI_STATUS\r
-Tcp4ChkDataBuf (\r
- IN UINT32 DataLen,\r
- IN UINT32 FragmentCount,\r
- IN EFI_TCP4_FRAGMENT_DATA *FragmentTable\r
- )\r
-{\r
- UINT32 Index;\r
-\r
- UINT32 Len;\r
-\r
- for (Index = 0, Len = 0; Index < FragmentCount; Index++) {\r
- Len = Len + (UINT32) FragmentTable[Index].FragmentLength;\r
- }\r
-\r
- if (DataLen != Len) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Get the current operational status.\r
-\r
- The GetModeData() function copies the current operational settings of this\r
- EFI TCPv4 Protocol instance into user-supplied buffers. This function can\r
- also be used to retrieve the operational setting of underlying drivers\r
- such as IPv4, MNP, or SNP.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
- @param Tcp4State Pointer to the buffer to receive the current TCP\r
- state.\r
- @param Tcp4ConfigData Pointer to the buffer to receive the current TCP\r
- configuration.\r
- @param Ip4ModeData Pointer to the buffer to receive the current IPv4\r
- configuration data used by the TCPv4 instance.\r
- @param MnpConfigData Pointer to the buffer to receive the current MNP\r
- configuration data indirectly used by the TCPv4\r
- Instance.\r
- @param SnpModeData Pointer to the buffer to receive the current SNP\r
- configuration data indirectly used by the TCPv4\r
- Instance.\r
-\r
- @retval EFI_SUCCESS The mode data was read.\r
- @retval EFI_NOT_STARTED No configuration data is available because this\r
- instance hasn't been started.\r
- @retval EFI_INVALID_PARAMETER This is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4GetModeData (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- OUT EFI_TCP4_CONNECTION_STATE *Tcp4State OPTIONAL,\r
- OUT EFI_TCP4_CONFIG_DATA *Tcp4ConfigData OPTIONAL,\r
- OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL,\r
- OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,\r
- OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL\r
- )\r
-{\r
- TCP4_MODE_DATA TcpMode;\r
- SOCKET *Sock;\r
-\r
- if (NULL == This) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Sock = SOCK_FROM_THIS (This);\r
-\r
- TcpMode.Tcp4State = Tcp4State;\r
- TcpMode.Tcp4ConfigData = Tcp4ConfigData;\r
- TcpMode.Ip4ModeData = Ip4ModeData;\r
- TcpMode.MnpConfigData = MnpConfigData;\r
- TcpMode.SnpModeData = SnpModeData;\r
-\r
- return SockGetMode (Sock, &TcpMode);\r
-}\r
-\r
-\r
-/**\r
- Initialize or brutally reset the operational parameters for\r
- this EFI TCPv4 instance.\r
-\r
- The Configure() function does the following:\r
- * Initialize this EFI TCPv4 instance, i.e., initialize the communication end\r
- setting, specify active open or passive open for an instance.\r
- * Reset this TCPv4 instance brutally, i.e., cancel all pending asynchronous\r
- tokens, flush transmission and receiving buffer directly without informing\r
- the communication peer.\r
- No other TCPv4 Protocol operation can be executed by this instance\r
- until it is configured properly. For an active TCP4 instance, after a proper\r
- configuration it may call Connect() to initiates the three-way handshake.\r
- For a passive TCP4 instance, its state will transit to Tcp4StateListen after\r
- configuration, and Accept() may be called to listen the incoming TCP connection\r
- request. If TcpConfigData is set to NULL, the instance is reset. Resetting\r
- process will be done brutally, the state machine will be set to Tcp4StateClosed\r
- directly, the receive queue and transmit queue will be flushed, and no traffic is\r
- allowed through this instance.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
- @param TcpConfigData Pointer to the configure data to configure the\r
- instance.\r
-\r
- @retval EFI_SUCCESS The operational settings are set, changed, or\r
- reset successfully.\r
- @retval EFI_NO_MAPPING When using a default address, configuration\r
- (through DHCP, BOOTP, RARP, etc.) is not\r
- finished.\r
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_ACCESS_DENIED Configuring TCP instance when it is already\r
- configured.\r
- @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.\r
- @retval EFI_UNSUPPORTED One or more of the control options are not\r
- supported in the implementation.\r
- @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Configure (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_CONFIG_DATA *TcpConfigData OPTIONAL\r
- )\r
-{\r
- EFI_TCP4_OPTION *Option;\r
- SOCKET *Sock;\r
- EFI_STATUS Status;\r
- IP4_ADDR Ip;\r
- IP4_ADDR SubnetMask;\r
-\r
- if (NULL == This) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Tcp protocol related parameter check will be conducted here\r
- //\r
- if (NULL != TcpConfigData) {\r
-\r
- CopyMem (&Ip, &TcpConfigData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR));\r
- if (IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (TcpConfigData->AccessPoint.ActiveFlag &&\r
- (0 == TcpConfigData->AccessPoint.RemotePort || (Ip == 0))) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (!TcpConfigData->AccessPoint.UseDefaultAddress) {\r
-\r
- CopyMem (&Ip, &TcpConfigData->AccessPoint.StationAddress, sizeof (IP4_ADDR));\r
- CopyMem (&SubnetMask, &TcpConfigData->AccessPoint.SubnetMask, sizeof (IP4_ADDR));\r
- if (!IP4_IS_VALID_NETMASK (NTOHL (SubnetMask)) ||\r
- (SubnetMask != 0 && !NetIp4IsUnicast (NTOHL (Ip), NTOHL (SubnetMask)))) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- Option = TcpConfigData->ControlOption;\r
- if ((NULL != Option) &&\r
- (Option->EnableSelectiveAck || Option->EnablePathMtuDiscovery)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- }\r
-\r
- Sock = SOCK_FROM_THIS (This);\r
-\r
- if (NULL == TcpConfigData) {\r
- return SockFlush (Sock);\r
- }\r
-\r
- Status = SockConfigure (Sock, TcpConfigData);\r
-\r
- if (EFI_NO_MAPPING == Status) {\r
- Sock->ConfigureState = SO_NO_MAPPING;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Add or delete routing entries.\r
-\r
- The Routes() function adds or deletes a route from the instance's routing table.\r
- The most specific route is selected by comparing the SubnetAddress with the\r
- destination IP address's arithmetical AND to the SubnetMask.\r
- The default route is added with both SubnetAddress and SubnetMask set to 0.0.0.0.\r
- The default route matches all destination IP addresses if there is no more specific route.\r
- Direct route is added with GatewayAddress set to 0.0.0.0. Packets are sent to\r
- the destination host if its address can be found in the Address Resolution Protocol (ARP)\r
- cache or it is on the local subnet. If the instance is configured to use default\r
- address, a direct route to the local network will be added automatically.\r
- Each TCP instance has its own independent routing table. Instance that uses the\r
- default IP address will have a copy of the EFI_IP4_CONFIG_PROTOCOL's routing table.\r
- The copy will be updated automatically whenever the IP driver reconfigures its\r
- instance. As a result, the previous modification to the instance's local copy\r
- will be lost. The priority of checking the route table is specific with IP\r
- implementation and every IP implementation must comply with RFC 1122.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
- @param DeleteRoute If TRUE, delete the specified route from routing\r
- table; if FALSE, add the specified route to\r
- routing table.\r
- DestinationAddress and SubnetMask are used as\r
- the keywords to search route entry.\r
- @param SubnetAddress The destination network.\r
- @param SubnetMask The subnet mask for the destination network.\r
- @param GatewayAddress The gateway address for this route.\r
- It must be on the same subnet with the station\r
- address unless a direct route is specified.\r
-\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance has not been\r
- configured.\r
- @retval EFI_NO_MAPPING When using a default address, configuration\r
- (through DHCP, BOOTP, RARP, etc.) is not\r
- finished.\r
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to add the\r
- entry to the routing table.\r
- @retval EFI_NOT_FOUND This route is not in the routing table.\r
- @retval EFI_ACCESS_DENIED This route is already in the routing table.\r
- @retval EFI_UNSUPPORTED The TCP driver does not support this operation.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Routes (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN BOOLEAN DeleteRoute,\r
- IN EFI_IPv4_ADDRESS *SubnetAddress,\r
- IN EFI_IPv4_ADDRESS *SubnetMask,\r
- IN EFI_IPv4_ADDRESS *GatewayAddress\r
- )\r
-{\r
- SOCKET *Sock;\r
- TCP4_ROUTE_INFO RouteInfo;\r
-\r
- if (NULL == This) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Sock = SOCK_FROM_THIS (This);\r
-\r
- RouteInfo.DeleteRoute = DeleteRoute;\r
- RouteInfo.SubnetAddress = SubnetAddress;\r
- RouteInfo.SubnetMask = SubnetMask;\r
- RouteInfo.GatewayAddress = GatewayAddress;\r
-\r
- return SockRoute (Sock, &RouteInfo);\r
-}\r
-\r
-\r
-/**\r
- Initiate a nonblocking TCP connection request for an active TCP instance.\r
-\r
- The Connect() function will initiate an active open to the remote peer configured\r
- in current TCP instance if it is configured active. If the connection succeeds\r
- or fails due to any error, the ConnectionToken->CompletionToken.Event will be\r
- signaled and ConnectionToken->CompletionToken.Status will be updated accordingly.\r
- This function can only be called for the TCP instance in Tcp4StateClosed state.\r
- The instance will transfer into Tcp4StateSynSent if the function returns EFI_SUCCESS.\r
- If TCP three way handshake succeeds, its state will become Tcp4StateEstablished,\r
- otherwise, the state will return to Tcp4StateClosed.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance\r
- @param ConnectionToken Pointer to the connection token to return when\r
- the TCP three way handshake finishes.\r
-\r
- @retval EFI_SUCCESS The connection request is successfully initiated\r
- and the state of this TCPv4 instance has\r
- been changed to Tcp4StateSynSent.\r
- @retval EFI_NOT_STARTED This EFI_TCP4_PROTOCOL instance hasn't been\r
- configured.\r
- @retval EFI_ACCESS_DENIED The instance is not configured as an active one\r
- or it is not in Tcp4StateClosed state.\r
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_OUT_OF_RESOURCES The driver can't allocate enough resource to\r
- initiate the active open.\r
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Connect (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken\r
- )\r
-{\r
- SOCKET *Sock;\r
-\r
- if (NULL == This ||\r
- NULL == ConnectionToken ||\r
- NULL == ConnectionToken->CompletionToken.Event) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Sock = SOCK_FROM_THIS (This);\r
-\r
- return SockConnect (Sock, ConnectionToken);\r
-}\r
-\r
-\r
-/**\r
- Listen on the passive instance to accept an incoming connection request.\r
-\r
- The Accept() function initiates an asynchronous accept request to wait for an\r
- incoming connection on the passive TCP instance. If a remote peer successfully\r
- establishes a connection with this instance, a new TCP instance will be created\r
- and its handle will be returned in ListenToken->NewChildHandle. The newly created\r
- instance is configured by inheriting the passive instance's configuration and is\r
- ready for use upon return. The instance is in the Tcp4StateEstablished state.\r
- The ListenToken->CompletionToken.Event will be signaled when a new connection\r
- is accepted, user aborts the listen or connection is reset. This function only\r
- can be called when current TCP instance is in Tcp4StateListen state.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance\r
- @param ListenToken Pointer to the listen token to return when\r
- operation finishes.\r
-\r
- @retval EFI_SUCCESS The listen token has been queued successfully.\r
- @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been\r
- configured.\r
- @retval EFI_ACCESS_DENIED The instatnce is not a passive one or it is not\r
- in Tcp4StateListen state or a same listen token\r
- has already existed in the listen token queue of\r
- this TCP instance.\r
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to finish\r
- the operation.\r
- @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above category error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Accept (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_LISTEN_TOKEN *ListenToken\r
- )\r
-{\r
- SOCKET *Sock;\r
-\r
- if (NULL == This ||\r
- NULL == ListenToken ||\r
- NULL == ListenToken->CompletionToken.Event) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Sock = SOCK_FROM_THIS (This);\r
-\r
- return SockAccept (Sock, ListenToken);\r
-}\r
-\r
-\r
-/**\r
- Queues outgoing data into the transmit queue.\r
-\r
- The Transmit() function queues a sending request to this TCPv4 instance along\r
- with the user data. The status of the token is updated and the event in the token\r
- will be signaled once the data is sent out or some error occurs.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance\r
- @param Token Pointer to the completion token to queue to the\r
- transmit queue\r
-\r
- @retval EFI_SUCCESS The data has been queued for transmission.\r
- @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been\r
- configured.\r
- @retval EFI_NO_MAPPING When using a default address, configuration\r
- (DHCP, BOOTP, RARP, etc.) is not finished yet.\r
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:\r
- * A transmit completion token with the same\r
- Token-> CompletionToken.Event was already in the\r
- transmission queue.\r
- * The current instance is in Tcp4StateClosed state\r
- * The current instance is a passive one and\r
- it is in Tcp4StateListen state.\r
- * User has called Close() to disconnect this\r
- connection.\r
- @retval EFI_NOT_READY The completion token could not be queued because\r
- the transmit queue is full.\r
- @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data because of\r
- resource shortage.\r
- @retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or\r
- address.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Transmit (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_IO_TOKEN *Token\r
- )\r
-{\r
- SOCKET *Sock;\r
- EFI_STATUS Status;\r
-\r
- if (NULL == This ||\r
- NULL == Token ||\r
- NULL == Token->CompletionToken.Event ||\r
- NULL == Token->Packet.TxData ||\r
- 0 == Token->Packet.TxData->FragmentCount ||\r
- 0 == Token->Packet.TxData->DataLength\r
- ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = Tcp4ChkDataBuf (\r
- (UINT32) Token->Packet.TxData->DataLength,\r
- (UINT32) Token->Packet.TxData->FragmentCount,\r
- Token->Packet.TxData->FragmentTable\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Sock = SOCK_FROM_THIS (This);\r
-\r
- return SockSend (Sock, Token);\r
-\r
-}\r
-\r
-\r
-/**\r
- Place an asynchronous receive request into the receiving queue.\r
-\r
- The Receive() function places a completion token into the receive packet queue.\r
- This function is always asynchronous. The caller must allocate the\r
- Token->CompletionToken.Event and the FragmentBuffer used to receive data. He also\r
- must fill the DataLength which represents the whole length of all FragmentBuffer.\r
- When the receive operation completes, the EFI TCPv4 Protocol driver updates the\r
- Token->CompletionToken.Status and Token->Packet.RxData fields and the\r
- Token->CompletionToken.Event is signaled. If got data the data and its length\r
- will be copy into the FragmentTable, in the same time the full length of received\r
- data will be recorded in the DataLength fields. Providing a proper notification\r
- function and context for the event will enable the user to receive the notification\r
- and receiving status. That notification function is guaranteed to not be re-entered.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
- @param Token Pointer to a token that is associated with the\r
- receive data descriptor.\r
-\r
- @retval EFI_SUCCESS The receive completion token was cached.\r
- @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been\r
- configured.\r
- @retval EFI_NO_MAPPING When using a default address, configuration\r
- (DHCP, BOOTP, RARP, etc.) is not finished yet.\r
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued\r
- due to a lack of system resources.\r
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
- The EFI TCPv4 Protocol instance has been reset\r
- to startup defaults.\r
- @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:\r
- * A receive completion token with the same\r
- Token->CompletionToken.Event was already in\r
- the receive queue.\r
- * The current instance is in Tcp4StateClosed state.\r
- * The current instance is a passive one and it\r
- is in Tcp4StateListen state.\r
- * User has called Close() to disconnect this\r
- connection.\r
- @retval EFI_CONNECTION_FIN The communication peer has closed the connection\r
- and there is no any buffered data in the receive\r
- buffer of this instance.\r
- @retval EFI_NOT_READY The receive request could not be queued because\r
- the receive queue is full.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Receive (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_IO_TOKEN *Token\r
- )\r
-{\r
- SOCKET *Sock;\r
- EFI_STATUS Status;\r
-\r
- if (NULL == This ||\r
- NULL == Token ||\r
- NULL == Token->CompletionToken.Event ||\r
- NULL == Token->Packet.RxData ||\r
- 0 == Token->Packet.RxData->FragmentCount ||\r
- 0 == Token->Packet.RxData->DataLength\r
- ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = Tcp4ChkDataBuf (\r
- (UINT32) Token->Packet.RxData->DataLength,\r
- (UINT32) Token->Packet.RxData->FragmentCount,\r
- Token->Packet.RxData->FragmentTable\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Sock = SOCK_FROM_THIS (This);\r
-\r
- return SockRcv (Sock, Token);\r
-\r
-}\r
-\r
-\r
-/**\r
- Disconnecting a TCP connection gracefully or reset a TCP connection.\r
-\r
- Initiate an asynchronous close token to TCP driver. After Close() is called,\r
- any buffered transmission data will be sent by TCP driver and the current\r
- instance will have a graceful close working flow described as RFC 793 if\r
- AbortOnClose is set to FALSE, otherwise, a rest packet will be sent by TCP\r
- driver to fast disconnect this connection. When the close operation completes\r
- successfully the TCP instance is in Tcp4StateClosed state, all pending\r
- asynchronous operation is signaled and any buffers used for TCP network traffic\r
- is flushed.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
- @param CloseToken Pointer to the close token to return when\r
- operation finishes.\r
-\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been\r
- configured.\r
- @retval EFI_ACCESS_DENIED One or more of the following are TRUE:\r
- * Configure() has been called with TcpConfigData\r
- set to NULL and this function has not returned.\r
- * Previous Close() call on this instance has not\r
- finished.\r
- @retval EFI_INVALID_PARAMETER One ore more parameters are invalid.\r
- @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the\r
- operation.\r
- @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above\r
- category error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Close (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_CLOSE_TOKEN *CloseToken\r
- )\r
-{\r
- SOCKET *Sock;\r
-\r
- if (NULL == This ||\r
- NULL == CloseToken ||\r
- NULL == CloseToken->CompletionToken.Event) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Sock = SOCK_FROM_THIS (This);\r
-\r
- return SockClose (Sock, CloseToken, CloseToken->AbortOnClose);\r
-}\r
-\r
-\r
-/**\r
- Abort an asynchronous connection, listen, transmission or receive request.\r
-\r
- The Cancel() function aborts a pending connection, listen, transmit or receive\r
- request. If Token is not NULL and the token is in the connection, listen,\r
- transmission or receive queue when it is being cancelled, its Token->Status\r
- will be set to EFI_ABORTED and then Token->Event will be signaled. If the token\r
- is not in one of the queues, which usually means that the asynchronous operation\r
- has completed, EFI_NOT_FOUND is returned. If Token is NULL all asynchronous token\r
- issued by Connect(), Accept(), Transmit() and Receive()will be aborted.\r
- NOTE: It has not been implemented currently.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
- @param Token Pointer to a token that has been issued by\r
- Connect(), Accept(), Transmit() or Receive(). If\r
- NULL, all pending tokens issued by above four\r
- functions will be aborted.\r
-\r
- @retval EFI_SUCCESS The asynchronous I/O request is aborted and Token->Event\r
- is signaled.\r
- @retval EFI_INVALID_PARAMETER This is NULL.\r
- @retval EFI_NOT_STARTED This instance hasn's been configured.\r
- @retval EFI_NO_MAPPING When using the default address, configuration\r
- (DHCP, BOOTP,RARP, etc.) hasn's finished yet.\r
- @retval EFI_NOT_FOUND The asynchronous I/O request isn's found in the\r
- transmission or receive queue. It has either\r
- completed or wasn's issued by Transmit() and Receive().\r
- @retval EFI_UNSUPPORTED The operation is not supported in current\r
- implementation.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Cancel (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_COMPLETION_TOKEN *Token OPTIONAL\r
- )\r
-{\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-\r
-/**\r
- Poll to receive incoming data and transmit outgoing segments.\r
-\r
- The Poll() function increases the rate that data is moved between the network\r
- and application and can be called when the TCP instance is created successfully.\r
- Its use is optional. In some implementations, the periodical timer in the MNP\r
- driver may not poll the underlying communications device fast enough to avoid\r
- drop packets. Drivers and applications that are experiencing packet loss should\r
- try calling the Poll() function in a high frequency.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
-\r
- @retval EFI_SUCCESS Incoming or outgoing data was processed.\r
- @retval EFI_INVALID_PARAMETER This is NULL.\r
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
- @retval EFI_NOT_READY No incoming or outgoing data was processed.\r
- @retval EFI_TIMEOUT Data was dropped out of the transmission or\r
- receive queue. Consider increasing the polling\r
- rate.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Poll (\r
- IN EFI_TCP4_PROTOCOL *This\r
- )\r
-{\r
- SOCKET *Sock;\r
- EFI_STATUS Status;\r
-\r
- if (NULL == This) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Sock = SOCK_FROM_THIS (This);\r
-\r
- Status = Sock->ProtoHandler (Sock, SOCK_POLL, NULL);\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-/** @file\r
- TCP4 protocol services header file.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#ifndef _TCP4_MAIN_H_\r
-#define _TCP4_MAIN_H_\r
-\r
-#include "Socket.h"\r
-\r
-#include "Tcp4Proto.h"\r
-#include "Tcp4Func.h"\r
-#include "Tcp4Driver.h"\r
-\r
-\r
-extern UINT16 mTcp4RandomPort;\r
-extern CHAR16 *mTcpStateName[];\r
-\r
-//\r
-// Driver Produced Protocol Prototypes\r
-//\r
-\r
-//\r
-// Function prototype for the Tcp4 socket request handler\r
-//\r
-/**\r
- The procotol handler provided to the socket layer, used to\r
- dispatch the socket level requests by calling the corresponding\r
- TCP layer functions.\r
-\r
- @param Sock Pointer to the socket of this TCP instance.\r
- @param Request The code of this operation request.\r
- @param Data Pointer to the operation specific data passed in\r
- together with the operation request.\r
-\r
- @retval EFI_SUCCESS The socket request is completed successfully.\r
- @retval other The error status returned by the corresponding TCP\r
- layer function.\r
-\r
-**/\r
-EFI_STATUS\r
-Tcp4Dispatcher (\r
- IN SOCKET *Sock,\r
- IN UINT8 Request,\r
- IN VOID *Data OPTIONAL\r
- );\r
-\r
-///\r
-/// TCP mode data\r
-///\r
-typedef struct _TCP4_MODE_DATA {\r
- EFI_TCP4_CONNECTION_STATE *Tcp4State;\r
- EFI_TCP4_CONFIG_DATA *Tcp4ConfigData;\r
- EFI_IP4_MODE_DATA *Ip4ModeData;\r
- EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData;\r
- EFI_SIMPLE_NETWORK_MODE *SnpModeData;\r
-} TCP4_MODE_DATA;\r
-\r
-///\r
-/// TCP route infomation data\r
-///\r
-typedef struct _TCP4_ROUTE_INFO {\r
- BOOLEAN DeleteRoute;\r
- EFI_IPv4_ADDRESS *SubnetAddress;\r
- EFI_IPv4_ADDRESS *SubnetMask;\r
- EFI_IPv4_ADDRESS *GatewayAddress;\r
-} TCP4_ROUTE_INFO;\r
-\r
-typedef struct {\r
- EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
- UINTN NumberOfChildren;\r
- EFI_HANDLE *ChildHandleBuffer;\r
-} TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT;\r
-\r
-/**\r
- Get the current operational status of a TCP instance.\r
-\r
- The GetModeData() function copies the current operational settings of this\r
- EFI TCPv4 Protocol instance into user-supplied buffers. This function can\r
- also be used to retrieve the operational setting of underlying drivers\r
- such as IPv4, MNP, or SNP.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
- @param Tcp4State Pointer to the buffer to receive the current TCP\r
- state.\r
- @param Tcp4ConfigData Pointer to the buffer to receive the current TCP\r
- configuration.\r
- @param Ip4ModeData Pointer to the buffer to receive the current IPv4\r
- configuration data used by the TCPv4 instance.\r
- @param MnpConfigData Pointer to the buffer to receive the current MNP\r
- configuration data indirectly used by the TCPv4\r
- Instance.\r
- @param SnpModeData Pointer to the buffer to receive the current SNP\r
- configuration data indirectly used by the TCPv4\r
- Instance.\r
-\r
- @retval EFI_SUCCESS The mode data was read.\r
- @retval EFI_NOT_STARTED No configuration data is available because this\r
- instance hasn't been started.\r
- @retval EFI_INVALID_PARAMETER This is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4GetModeData (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- OUT EFI_TCP4_CONNECTION_STATE *Tcp4State OPTIONAL,\r
- OUT EFI_TCP4_CONFIG_DATA *Tcp4ConfigData OPTIONAL,\r
- OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL,\r
- OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,\r
- OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL\r
- );\r
-\r
-\r
-/**\r
- Initialize or brutally reset the operational parameters for\r
- this EFI TCPv4 instance.\r
-\r
- The Configure() function does the following:\r
- * Initialize this EFI TCPv4 instance, i.e., initialize the communication end\r
- setting, specify active open or passive open for an instance.\r
- * Reset this TCPv4 instance brutally, i.e., cancel all pending asynchronous\r
- tokens, flush transmission and receiving buffer directly without informing\r
- the communication peer.\r
- No other TCPv4 Protocol operation can be executed by this instance\r
- until it is configured properly. For an active TCP4 instance, after a proper\r
- configuration it may call Connect() to initiates the three-way handshake.\r
- For a passive TCP4 instance, its state will transit to Tcp4StateListen after\r
- configuration, and Accept() may be called to listen the incoming TCP connection\r
- request. If TcpConfigData is set to NULL, the instance is reset. Resetting\r
- process will be done brutally, the state machine will be set to Tcp4StateClosed\r
- directly, the receive queue and transmit queue will be flushed, and no traffic is\r
- allowed through this instance.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
- @param TcpConfigData Pointer to the configure data to configure the\r
- instance.\r
-\r
- @retval EFI_SUCCESS The operational settings are set, changed, or\r
- reset successfully.\r
- @retval EFI_NO_MAPPING When using a default address, configuration\r
- (through DHCP, BOOTP, RARP, etc.) is not\r
- finished.\r
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_ACCESS_DENIED Configuring TCP instance when it is already\r
- configured.\r
- @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.\r
- @retval EFI_UNSUPPORTED One or more of the control options are not\r
- supported in the implementation.\r
- @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Configure (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_CONFIG_DATA *TcpConfigData OPTIONAL\r
- );\r
-\r
-/**\r
- Add or delete routing entries.\r
-\r
- The Routes() function adds or deletes a route from the instance's routing table.\r
- The most specific route is selected by comparing the SubnetAddress with the\r
- destination IP address's arithmetical AND to the SubnetMask.\r
- The default route is added with both SubnetAddress and SubnetMask set to 0.0.0.0.\r
- The default route matches all destination IP addresses if there is no more specific route.\r
- Direct route is added with GatewayAddress set to 0.0.0.0. Packets are sent to\r
- the destination host if its address can be found in the Address Resolution Protocol (ARP)\r
- cache or it is on the local subnet. If the instance is configured to use default\r
- address, a direct route to the local network will be added automatically.\r
- Each TCP instance has its own independent routing table. Instance that uses the\r
- default IP address will have a copy of the EFI_IP4_CONFIG_PROTOCOL's routing table.\r
- The copy will be updated automatically whenever the IP driver reconfigures its\r
- instance. As a result, the previous modification to the instance's local copy\r
- will be lost. The priority of checking the route table is specific with IP\r
- implementation and every IP implementation must comply with RFC 1122.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
- @param DeleteRoute If TRUE, delete the specified route from routing\r
- table; if FALSE, add the specified route to\r
- routing table.\r
- DestinationAddress and SubnetMask are used as\r
- the keywords to search route entry.\r
- @param SubnetAddress The destination network.\r
- @param SubnetMask The subnet mask for the destination network.\r
- @param GatewayAddress The gateway address for this route.\r
- It must be on the same subnet with the station\r
- address unless a direct route is specified.\r
-\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance has not been\r
- configured.\r
- @retval EFI_NO_MAPPING When using a default address, configuration\r
- (through DHCP, BOOTP, RARP, etc.) is not\r
- finished.\r
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to add the\r
- entry to the routing table.\r
- @retval EFI_NOT_FOUND This route is not in the routing table.\r
- @retval EFI_ACCESS_DENIED This route is already in the routing table.\r
- @retval EFI_UNSUPPORTED The TCP driver does not support this operation.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Routes (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN BOOLEAN DeleteRoute,\r
- IN EFI_IPv4_ADDRESS *SubnetAddress,\r
- IN EFI_IPv4_ADDRESS *SubnetMask,\r
- IN EFI_IPv4_ADDRESS *GatewayAddress\r
- );\r
-\r
-/**\r
- Initiate a nonblocking TCP connection request for an active TCP instance.\r
-\r
- The Connect() function will initiate an active open to the remote peer configured\r
- in current TCP instance if it is configured active. If the connection succeeds\r
- or fails due to any error, the ConnectionToken->CompletionToken.Event will be\r
- signaled and ConnectionToken->CompletionToken.Status will be updated accordingly.\r
- This function can only be called for the TCP instance in Tcp4StateClosed state.\r
- The instance will transfer into Tcp4StateSynSent if the function returns EFI_SUCCESS.\r
- If TCP three way handshake succeeds, its state will become Tcp4StateEstablished,\r
- otherwise, the state will return to Tcp4StateClosed.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance\r
- @param ConnectionToken Pointer to the connection token to return when\r
- the TCP three way handshake finishes.\r
-\r
- @retval EFI_SUCCESS The connection request is successfully initiated\r
- and the state of this TCPv4 instance has\r
- been changed to Tcp4StateSynSent.\r
- @retval EFI_NOT_STARTED This EFI_TCP4_PROTOCOL instance hasn't been\r
- configured.\r
- @retval EFI_ACCESS_DENIED The instance is not configured as an active one\r
- or it is not in Tcp4StateClosed state.\r
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_OUT_OF_RESOURCES The driver can't allocate enough resource to\r
- initiate the active open.\r
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Connect (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken\r
- );\r
-\r
-/**\r
- Listen on the passive instance to accept an incoming connection request.\r
-\r
- The Accept() function initiates an asynchronous accept request to wait for an\r
- incoming connection on the passive TCP instance. If a remote peer successfully\r
- establishes a connection with this instance, a new TCP instance will be created\r
- and its handle will be returned in ListenToken->NewChildHandle. The newly created\r
- instance is configured by inheriting the passive instance's configuration and is\r
- ready for use upon return. The instance is in the Tcp4StateEstablished state.\r
- The ListenToken->CompletionToken.Event will be signaled when a new connection\r
- is accepted, user aborts the listen or connection is reset. This function only\r
- can be called when current TCP instance is in Tcp4StateListen state.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance\r
- @param ListenToken Pointer to the listen token to return when\r
- operation finishes.\r
-\r
- @retval EFI_SUCCESS The listen token has been queued successfully.\r
- @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been\r
- configured.\r
- @retval EFI_ACCESS_DENIED The instatnce is not a passive one or it is not\r
- in Tcp4StateListen state or a same listen token\r
- has already existed in the listen token queue of\r
- this TCP instance.\r
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to finish\r
- the operation.\r
- @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above category error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Accept (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_LISTEN_TOKEN *ListenToken\r
- );\r
-\r
-/**\r
- Queues outgoing data into the transmit queue.\r
-\r
- The Transmit() function queues a sending request to this TCPv4 instance along\r
- with the user data. The status of the token is updated and the event in the token\r
- will be signaled once the data is sent out or some error occurs.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance\r
- @param Token Pointer to the completion token to queue to the\r
- transmit queue\r
-\r
- @retval EFI_SUCCESS The data has been queued for transmission.\r
- @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been\r
- configured.\r
- @retval EFI_NO_MAPPING When using a default address, configuration\r
- (DHCP, BOOTP, RARP, etc.) is not finished yet.\r
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:\r
- * A transmit completion token with the same\r
- Token-> CompletionToken.Event was already in the\r
- transmission queue.\r
- * The current instance is in Tcp4StateClosed state\r
- * The current instance is a passive one and\r
- it is in Tcp4StateListen state.\r
- * User has called Close() to disconnect this\r
- connection.\r
- @retval EFI_NOT_READY The completion token could not be queued because\r
- the transmit queue is full.\r
- @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data because of\r
- resource shortage.\r
- @retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or\r
- address.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Transmit (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_IO_TOKEN *Token\r
- );\r
-\r
-/**\r
- Place an asynchronous receive request into the receiving queue.\r
-\r
- The Receive() function places a completion token into the receive packet queue.\r
- This function is always asynchronous. The caller must allocate the\r
- Token->CompletionToken.Event and the FragmentBuffer used to receive data. He also\r
- must fill the DataLength which represents the whole length of all FragmentBuffer.\r
- When the receive operation completes, the EFI TCPv4 Protocol driver updates the\r
- Token->CompletionToken.Status and Token->Packet.RxData fields and the\r
- Token->CompletionToken.Event is signaled. If got data the data and its length\r
- will be copy into the FragmentTable, in the same time the full length of received\r
- data will be recorded in the DataLength fields. Providing a proper notification\r
- function and context for the event will enable the user to receive the notification\r
- and receiving status. That notification function is guaranteed to not be re-entered.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
- @param Token Pointer to a token that is associated with the\r
- receive data descriptor.\r
-\r
- @retval EFI_SUCCESS The receive completion token was cached.\r
- @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been\r
- configured.\r
- @retval EFI_NO_MAPPING When using a default address, configuration\r
- (DHCP, BOOTP, RARP, etc.) is not finished yet.\r
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
- @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued\r
- due to a lack of system resources.\r
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
- The EFI TCPv4 Protocol instance has been reset\r
- to startup defaults.\r
- @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:\r
- * A receive completion token with the same\r
- Token->CompletionToken.Event was already in\r
- the receive queue.\r
- * The current instance is in Tcp4StateClosed state.\r
- * The current instance is a passive one and it\r
- is in Tcp4StateListen state.\r
- * User has called Close() to disconnect this\r
- connection.\r
- @retval EFI_CONNECTION_FIN The communication peer has closed the connection\r
- and there is no any buffered data in the receive\r
- buffer of this instance.\r
- @retval EFI_NOT_READY The receive request could not be queued because\r
- the receive queue is full.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Receive (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_IO_TOKEN *Token\r
- );\r
-\r
-/**\r
- Disconnecting a TCP connection gracefully or reset a TCP connection.\r
-\r
- Initiate an asynchronous close token to TCP driver. After Close() is called,\r
- any buffered transmission data will be sent by TCP driver and the current\r
- instance will have a graceful close working flow described as RFC 793 if\r
- AbortOnClose is set to FALSE, otherwise, a rest packet will be sent by TCP\r
- driver to fast disconnect this connection. When the close operation completes\r
- successfully the TCP instance is in Tcp4StateClosed state, all pending\r
- asynchronous operation is signaled and any buffers used for TCP network traffic\r
- is flushed.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
- @param CloseToken Pointer to the close token to return when\r
- operation finishes.\r
-\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been\r
- configured.\r
- @retval EFI_ACCESS_DENIED One or more of the following are TRUE:\r
- * Configure() has been called with TcpConfigData\r
- set to NULL and this function has not returned.\r
- * Previous Close() call on this instance has not\r
- finished.\r
- @retval EFI_INVALID_PARAMETER One ore more parameters are invalid.\r
- @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the\r
- operation.\r
- @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above\r
- category error.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Close (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_CLOSE_TOKEN *CloseToken\r
- );\r
-\r
-/**\r
- Abort an asynchronous connection, listen, transmission or receive request.\r
-\r
- The Cancel() function aborts a pending connection, listen, transmit or receive\r
- request. If Token is not NULL and the token is in the connection, listen,\r
- transmission or receive queue when it is being cancelled, its Token->Status\r
- will be set to EFI_ABORTED and then Token->Event will be signaled. If the token\r
- is not in one of the queues, which usually means that the asynchronous operation\r
- has completed, EFI_NOT_FOUND is returned. If Token is NULL all asynchronous token\r
- issued by Connect(), Accept(), Transmit() and Receive()will be aborted.\r
- NOTE: It has not been implemented currently.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
- @param Token Pointer to a token that has been issued by\r
- Connect(), Accept(), Transmit() or Receive(). If\r
- NULL, all pending tokens issued by above four\r
- functions will be aborted.\r
-\r
- @retval EFI_SUCCESS The asynchronous I/O request is aborted and Token->Event\r
- is signaled.\r
- @retval EFI_INVALID_PARAMETER This is NULL.\r
- @retval EFI_NOT_STARTED This instance hasn's been configured.\r
- @retval EFI_NO_MAPPING When using the default address, configuration\r
- (DHCP, BOOTP,RARP, etc.) hasn's finished yet.\r
- @retval EFI_NOT_FOUND The asynchronous I/O request isn's found in the\r
- transmission or receive queue. It has either\r
- completed or wasn's issued by Transmit() and Receive().\r
- @retval EFI_UNSUPPORTED The operation is not supported in current\r
- implementation.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Cancel (\r
- IN EFI_TCP4_PROTOCOL *This,\r
- IN EFI_TCP4_COMPLETION_TOKEN *Token OPTIONAL\r
- );\r
-\r
-/**\r
- Poll to receive incoming data and transmit outgoing segments.\r
-\r
- The Poll() function increases the rate that data is moved between the network\r
- and application and can be called when the TCP instance is created successfully.\r
- Its use is optional. In some implementations, the periodical timer in the MNP\r
- driver may not poll the underlying communications device fast enough to avoid\r
- drop packets. Drivers and applications that are experiencing packet loss should\r
- try calling the Poll() function in a high frequency.\r
-\r
- @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
-\r
- @retval EFI_SUCCESS Incoming or outgoing data was processed.\r
- @retval EFI_INVALID_PARAMETER This is NULL.\r
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
- @retval EFI_NOT_READY No incoming or outgoing data was processed.\r
- @retval EFI_TIMEOUT Data was dropped out of the transmission or\r
- receive queue. Consider increasing the polling\r
- rate.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Tcp4Poll (\r
- IN EFI_TCP4_PROTOCOL *This\r
- );\r
-\r
-#endif\r
+++ /dev/null
-/** @file\r
- Misc support routines for tcp.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-\r
-#include "Tcp4Main.h"\r
-\r
-#include <Library/DevicePathLib.h>\r
-\r
-LIST_ENTRY mTcpRunQue = {\r
- &mTcpRunQue,\r
- &mTcpRunQue\r
-};\r
-\r
-LIST_ENTRY mTcpListenQue = {\r
- &mTcpListenQue,\r
- &mTcpListenQue\r
-};\r
-\r
-TCP_SEQNO mTcpGlobalIss = 0x4d7e980b;\r
-\r
-CHAR16 *mTcpStateName[] = {\r
- L"TCP_CLOSED",\r
- L"TCP_LISTEN",\r
- L"TCP_SYN_SENT",\r
- L"TCP_SYN_RCVD",\r
- L"TCP_ESTABLISHED",\r
- L"TCP_FIN_WAIT_1",\r
- L"TCP_FIN_WAIT_2",\r
- L"TCP_CLOSING",\r
- L"TCP_TIME_WAIT",\r
- L"TCP_CLOSE_WAIT",\r
- L"TCP_LAST_ACK"\r
-};\r
-\r
-\r
-/**\r
- Initialize the Tcb local related members.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpInitTcbLocal (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- //\r
- // Compute the checksum of the fixed parts of pseudo header\r
- //\r
- Tcb->HeadSum = NetPseudoHeadChecksum (\r
- Tcb->LocalEnd.Ip,\r
- Tcb->RemoteEnd.Ip,\r
- 0x06,\r
- 0\r
- );\r
-\r
- Tcb->Iss = TcpGetIss ();\r
- Tcb->SndUna = Tcb->Iss;\r
- Tcb->SndNxt = Tcb->Iss;\r
-\r
- Tcb->SndWl2 = Tcb->Iss;\r
- Tcb->SndWnd = 536;\r
-\r
- Tcb->RcvWnd = GET_RCV_BUFFSIZE (Tcb->Sk);\r
-\r
- //\r
- // First window size is never scaled\r
- //\r
- Tcb->RcvWndScale = 0;\r
- Tcb->RetxmitSeqMax = 0;\r
-\r
- Tcb->ProbeTimerOn = FALSE;\r
-}\r
-\r
-\r
-/**\r
- Initialize the peer related members.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seg Pointer to the segment that contains the peer's\r
- intial info.\r
- @param Opt Pointer to the options announced by the peer.\r
-\r
-**/\r
-VOID\r
-TcpInitTcbPeer (\r
- IN OUT TCP_CB *Tcb,\r
- IN TCP_SEG *Seg,\r
- IN TCP_OPTION *Opt\r
- )\r
-{\r
- UINT16 RcvMss;\r
-\r
- ASSERT ((Tcb != NULL) && (Seg != NULL) && (Opt != NULL));\r
- ASSERT (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN));\r
-\r
- Tcb->SndWnd = Seg->Wnd;\r
- Tcb->SndWndMax = Tcb->SndWnd;\r
- Tcb->SndWl1 = Seg->Seq;\r
-\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {\r
- Tcb->SndWl2 = Seg->Ack;\r
- } else {\r
- Tcb->SndWl2 = Tcb->Iss + 1;\r
- }\r
-\r
- if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_MSS)) {\r
- Tcb->SndMss = (UINT16) MAX (64, Opt->Mss);\r
-\r
- RcvMss = TcpGetRcvMss (Tcb->Sk);\r
- if (Tcb->SndMss > RcvMss) {\r
- Tcb->SndMss = RcvMss;\r
- }\r
-\r
- } else {\r
- //\r
- // One end doesn't support MSS option, use default.\r
- //\r
- Tcb->RcvMss = 536;\r
- }\r
-\r
- Tcb->CWnd = Tcb->SndMss;\r
-\r
- Tcb->Irs = Seg->Seq;\r
- Tcb->RcvNxt = Tcb->Irs + 1;\r
-\r
- Tcb->RcvWl2 = Tcb->RcvNxt;\r
-\r
- if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_WS) &&\r
- !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS)) {\r
-\r
- Tcb->SndWndScale = Opt->WndScale;\r
-\r
- Tcb->RcvWndScale = TcpComputeScale (Tcb);\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS);\r
-\r
- } else {\r
- //\r
- // One end doesn't support window scale option. use zero.\r
- //\r
- Tcb->RcvWndScale = 0;\r
- }\r
-\r
- if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_TS) &&\r
- !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS)) {\r
-\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_TS);\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS);\r
-\r
- Tcb->TsRecent = Opt->TSVal;\r
-\r
- //\r
- // Compute the effective SndMss per RFC1122\r
- // section 4.2.2.6. If timestamp option is\r
- // enabled, it will always occupy 12 bytes.\r
- //\r
- Tcb->SndMss -= TCP_OPTION_TS_ALIGNED_LEN;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Locate a listen TCB that matchs the Local and Remote.\r
-\r
- @param Local Pointer to the local (IP, Port).\r
- @param Remote Pointer to the remote (IP, Port).\r
-\r
- @return Pointer to the TCP_CB with the least number of wildcard,\r
- if NULL no match is found.\r
-\r
-**/\r
-TCP_CB *\r
-TcpLocateListenTcb (\r
- IN TCP_PEER *Local,\r
- IN TCP_PEER *Remote\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- TCP_CB *Node;\r
- TCP_CB *Match;\r
- INTN Last;\r
- INTN Cur;\r
-\r
- Last = 4;\r
- Match = NULL;\r
-\r
- NET_LIST_FOR_EACH (Entry, &mTcpListenQue) {\r
- Node = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);\r
-\r
- if ((Local->Port != Node->LocalEnd.Port) ||\r
- !TCP_PEER_MATCH (Remote, &Node->RemoteEnd) ||\r
- !TCP_PEER_MATCH (Local, &Node->LocalEnd)) {\r
-\r
- continue;\r
- }\r
-\r
- //\r
- // Compute the number of wildcard\r
- //\r
- Cur = 0;\r
- if (Node->RemoteEnd.Ip == 0) {\r
- Cur++;\r
- }\r
-\r
- if (Node->RemoteEnd.Port == 0) {\r
- Cur++;\r
- }\r
-\r
- if (Node->LocalEnd.Ip == 0) {\r
- Cur++;\r
- }\r
-\r
- if (Cur < Last) {\r
- if (Cur == 0) {\r
- return Node;\r
- }\r
-\r
- Last = Cur;\r
- Match = Node;\r
- }\r
- }\r
-\r
- return Match;\r
-}\r
-\r
-\r
-/**\r
- Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.\r
-\r
- @param Addr Pointer to the IP address needs to match.\r
- @param Port The port number needs to match.\r
-\r
- @return The Tcb which matches the <Addr Port> paire exists or not.\r
-\r
-**/\r
-BOOLEAN\r
-TcpFindTcbByPeer (\r
- IN EFI_IPv4_ADDRESS *Addr,\r
- IN TCP_PORTNO Port\r
- )\r
-{\r
- TCP_PORTNO LocalPort;\r
- LIST_ENTRY *Entry;\r
- TCP_CB *Tcb;\r
-\r
- ASSERT ((Addr != NULL) && (Port != 0));\r
-\r
- LocalPort = HTONS (Port);\r
-\r
- NET_LIST_FOR_EACH (Entry, &mTcpListenQue) {\r
- Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);\r
-\r
- if (EFI_IP4_EQUAL (Addr, &Tcb->LocalEnd.Ip) &&\r
- (LocalPort == Tcb->LocalEnd.Port)) {\r
-\r
- return TRUE;\r
- }\r
- }\r
-\r
- NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {\r
- Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);\r
-\r
- if (EFI_IP4_EQUAL (Addr, &Tcb->LocalEnd.Ip) &&\r
- (LocalPort == Tcb->LocalEnd.Port)) {\r
-\r
- return TRUE;\r
- }\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-\r
-/**\r
- Locate the TCP_CB related to the socket pair.\r
-\r
- @param LocalPort The local port number.\r
- @param LocalIp The local IP address.\r
- @param RemotePort The remote port number.\r
- @param RemoteIp The remote IP address.\r
- @param Syn Whether to search the listen sockets, if TRUE, the\r
- listen sockets are searched.\r
-\r
- @return Pointer to the related TCP_CB, if NULL no match is found.\r
-\r
-**/\r
-TCP_CB *\r
-TcpLocateTcb (\r
- IN TCP_PORTNO LocalPort,\r
- IN UINT32 LocalIp,\r
- IN TCP_PORTNO RemotePort,\r
- IN UINT32 RemoteIp,\r
- IN BOOLEAN Syn\r
- )\r
-{\r
- TCP_PEER Local;\r
- TCP_PEER Remote;\r
- LIST_ENTRY *Entry;\r
- TCP_CB *Tcb;\r
-\r
- Local.Port = LocalPort;\r
- Local.Ip = LocalIp;\r
-\r
- Remote.Port = RemotePort;\r
- Remote.Ip = RemoteIp;\r
-\r
- //\r
- // First check for exact match.\r
- //\r
- NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {\r
- Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);\r
-\r
- if (TCP_PEER_EQUAL (&Remote, &Tcb->RemoteEnd) &&\r
- TCP_PEER_EQUAL (&Local, &Tcb->LocalEnd)) {\r
-\r
- RemoveEntryList (&Tcb->List);\r
- InsertHeadList (&mTcpRunQue, &Tcb->List);\r
-\r
- return Tcb;\r
- }\r
- }\r
-\r
- //\r
- // Only check listen queue when SYN flag is on\r
- //\r
- if (Syn) {\r
- return TcpLocateListenTcb (&Local, &Remote);\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-\r
-/**\r
- Insert a Tcb into the proper queue.\r
-\r
- @param Tcb Pointer to the TCP_CB to be inserted.\r
-\r
- @retval 0 The Tcb is inserted successfully.\r
- @retval -1 Error condition occurred.\r
-\r
-**/\r
-INTN\r
-TcpInsertTcb (\r
- IN TCP_CB *Tcb\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- LIST_ENTRY *Head;\r
- TCP_CB *Node;\r
-\r
- ASSERT (\r
- (Tcb != NULL) &&\r
- ((Tcb->State == TCP_LISTEN) ||\r
- (Tcb->State == TCP_SYN_SENT) ||\r
- (Tcb->State == TCP_SYN_RCVD) ||\r
- (Tcb->State == TCP_CLOSED))\r
- );\r
-\r
- if (Tcb->LocalEnd.Port == 0) {\r
- return -1;\r
- }\r
-\r
- Head = &mTcpRunQue;\r
-\r
- if (Tcb->State == TCP_LISTEN) {\r
- Head = &mTcpListenQue;\r
- }\r
-\r
- //\r
- // Check that Tcb isn't already on the list.\r
- //\r
- NET_LIST_FOR_EACH (Entry, Head) {\r
- Node = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);\r
-\r
- if (TCP_PEER_EQUAL (&Tcb->LocalEnd, &Node->LocalEnd) &&\r
- TCP_PEER_EQUAL (&Tcb->RemoteEnd, &Node->RemoteEnd)) {\r
-\r
- return -1;\r
- }\r
- }\r
-\r
- InsertHeadList (Head, &Tcb->List);\r
-\r
- return 0;\r
-}\r
-\r
-\r
-/**\r
- Clone a TCB_CB from Tcb.\r
-\r
- @param Tcb Pointer to the TCP_CB to be cloned.\r
-\r
- @return Pointer to the new cloned TCP_CB, if NULL error condition occurred.\r
-\r
-**/\r
-TCP_CB *\r
-TcpCloneTcb (\r
- IN TCP_CB *Tcb\r
- )\r
-{\r
- TCP_CB *Clone;\r
-\r
- Clone = AllocatePool (sizeof (TCP_CB));\r
-\r
- if (Clone == NULL) {\r
- return NULL;\r
-\r
- }\r
-\r
- CopyMem (Clone, Tcb, sizeof (TCP_CB));\r
-\r
- //\r
- // Increate the reference count of the shared IpInfo.\r
- //\r
- NET_GET_REF (Tcb->IpInfo);\r
-\r
- InitializeListHead (&Clone->List);\r
- InitializeListHead (&Clone->SndQue);\r
- InitializeListHead (&Clone->RcvQue);\r
-\r
- Clone->Sk = SockClone (Tcb->Sk);\r
- if (Clone->Sk == NULL) {\r
- DEBUG ((EFI_D_ERROR, "TcpCloneTcb: failed to clone a sock\n"));\r
- FreePool (Clone);\r
- return NULL;\r
- }\r
-\r
- ((TCP4_PROTO_DATA *) (Clone->Sk->ProtoReserved))->TcpPcb = Clone;\r
-\r
- return Clone;\r
-}\r
-\r
-\r
-/**\r
- Compute an ISS to be used by a new connection.\r
-\r
- @return The result ISS.\r
-\r
-**/\r
-TCP_SEQNO\r
-TcpGetIss (\r
- VOID\r
- )\r
-{\r
- mTcpGlobalIss += 2048;\r
- return mTcpGlobalIss;\r
-}\r
-\r
-\r
-/**\r
- Get the local mss.\r
-\r
- @param Sock Pointer to the socket to get mss\r
-\r
- @return The mss size.\r
-\r
-**/\r
-UINT16\r
-TcpGetRcvMss (\r
- IN SOCKET *Sock\r
- )\r
-{\r
- EFI_IP4_MODE_DATA Ip4Mode;\r
- TCP4_PROTO_DATA *TcpProto;\r
- EFI_IP4_PROTOCOL *Ip;\r
-\r
- ASSERT (Sock != NULL);\r
-\r
- TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;\r
- Ip = TcpProto->TcpService->IpIo->Ip.Ip4;\r
- ASSERT (Ip != NULL);\r
-\r
- Ip->GetModeData (Ip, &Ip4Mode, NULL, NULL);\r
-\r
- return (UINT16) (Ip4Mode.MaxPacketSize - sizeof (TCP_HEAD));\r
-}\r
-\r
-\r
-/**\r
- Set the Tcb's state.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param State The state to be set.\r
-\r
-**/\r
-VOID\r
-TcpSetState (\r
- IN OUT TCP_CB *Tcb,\r
- IN UINT8 State\r
- )\r
-{\r
- ASSERT (Tcb->State < (sizeof (mTcpStateName) / sizeof (CHAR16 *)));\r
- ASSERT (State < (sizeof (mTcpStateName) / sizeof (CHAR16 *)));\r
-\r
- DEBUG (\r
- (EFI_D_NET,\r
- "Tcb (%p) state %s --> %s\n",\r
- Tcb,\r
- mTcpStateName[Tcb->State],\r
- mTcpStateName[State])\r
- );\r
-\r
- Tcb->State = State;\r
-\r
- switch (State) {\r
- case TCP_ESTABLISHED:\r
-\r
- SockConnEstablished (Tcb->Sk);\r
-\r
- if (Tcb->Parent != NULL) {\r
- //\r
- // A new connection is accepted by a listening socket, install\r
- // the device path.\r
- //\r
- TcpInstallDevicePath (Tcb->Sk);\r
- }\r
-\r
- break;\r
-\r
- case TCP_CLOSED:\r
-\r
- SockConnClosed (Tcb->Sk);\r
-\r
- break;\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Compute the TCP segment's checksum.\r
-\r
- @param Nbuf Pointer to the buffer that contains the TCP\r
- segment.\r
- @param HeadSum The checksum value of the fixed part of pseudo\r
- header.\r
-\r
- @return The checksum value.\r
-\r
-**/\r
-UINT16\r
-TcpChecksum (\r
- IN NET_BUF *Nbuf,\r
- IN UINT16 HeadSum\r
- )\r
-{\r
- UINT16 Checksum;\r
-\r
- Checksum = NetbufChecksum (Nbuf);\r
- Checksum = NetAddChecksum (Checksum, HeadSum);\r
-\r
- Checksum = NetAddChecksum (\r
- Checksum,\r
- HTONS ((UINT16) Nbuf->TotalSize)\r
- );\r
-\r
- return (UINT16) ~Checksum;\r
-}\r
-\r
-/**\r
- Translate the information from the head of the received TCP\r
- segment Nbuf contains and fill it into a TCP_SEG structure.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the buffer contains the TCP segment.\r
-\r
- @return Pointer to the TCP_SEG that contains the translated TCP head information.\r
-\r
-**/\r
-TCP_SEG *\r
-TcpFormatNetbuf (\r
- IN TCP_CB *Tcb,\r
- IN OUT NET_BUF *Nbuf\r
- )\r
-{\r
- TCP_SEG *Seg;\r
- TCP_HEAD *Head;\r
-\r
- Seg = TCPSEG_NETBUF (Nbuf);\r
- Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL);\r
- ASSERT (Head != NULL);\r
- Nbuf->Tcp = Head;\r
-\r
- Seg->Seq = NTOHL (Head->Seq);\r
- Seg->Ack = NTOHL (Head->Ack);\r
- Seg->End = Seg->Seq + (Nbuf->TotalSize - (Head->HeadLen << 2));\r
-\r
- Seg->Urg = NTOHS (Head->Urg);\r
- Seg->Wnd = (NTOHS (Head->Wnd) << Tcb->SndWndScale);\r
- Seg->Flag = Head->Flag;\r
-\r
- //\r
- // SYN and FIN flag occupy one sequence space each.\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {\r
- //\r
- // RFC requires that initial window not be scaled\r
- //\r
- Seg->Wnd = NTOHS (Head->Wnd);\r
- Seg->End++;\r
- }\r
-\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {\r
- Seg->End++;\r
- }\r
-\r
- return Seg;\r
-}\r
-\r
-\r
-/**\r
- Reset the connection related with Tcb.\r
-\r
- @param Tcb Pointer to the TCP_CB of the connection to be\r
- reset.\r
-\r
-**/\r
-VOID\r
-TcpResetConnection (\r
- IN TCP_CB *Tcb\r
- )\r
-{\r
- NET_BUF *Nbuf;\r
- TCP_HEAD *Nhead;\r
-\r
- Nbuf = NetbufAlloc (TCP_MAX_HEAD);\r
-\r
- if (Nbuf == NULL) {\r
- return ;\r
- }\r
-\r
- Nhead = (TCP_HEAD *) NetbufAllocSpace (\r
- Nbuf,\r
- sizeof (TCP_HEAD),\r
- NET_BUF_TAIL\r
- );\r
-\r
- ASSERT (Nhead != NULL);\r
-\r
- Nbuf->Tcp = Nhead;\r
-\r
- Nhead->Flag = TCP_FLG_RST;\r
- Nhead->Seq = HTONL (Tcb->SndNxt);\r
- Nhead->Ack = HTONL (Tcb->RcvNxt);\r
- Nhead->SrcPort = Tcb->LocalEnd.Port;\r
- Nhead->DstPort = Tcb->RemoteEnd.Port;\r
- Nhead->HeadLen = (UINT8) (sizeof (TCP_HEAD) >> 2);\r
- Nhead->Res = 0;\r
- Nhead->Wnd = HTONS (0xFFFF);\r
- Nhead->Checksum = 0;\r
- Nhead->Urg = 0;\r
- Nhead->Checksum = TcpChecksum (Nbuf, Tcb->HeadSum);\r
-\r
- TcpSendIpPacket (Tcb, Nbuf, Tcb->LocalEnd.Ip, Tcb->RemoteEnd.Ip);\r
-\r
- NetbufFree (Nbuf);\r
-}\r
-\r
-\r
-/**\r
- Initialize an active connection.\r
-\r
- @param Tcb Pointer to the TCP_CB that wants to initiate a\r
- connection.\r
-\r
-**/\r
-VOID\r
-TcpOnAppConnect (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- TcpInitTcbLocal (Tcb);\r
- TcpSetState (Tcb, TCP_SYN_SENT);\r
-\r
- TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);\r
- TcpToSendData (Tcb, 1);\r
-}\r
-\r
-\r
-/**\r
- Initiate the connection close procedure, called when\r
- applications want to close the connection.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpOnAppClose (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- ASSERT (Tcb != NULL);\r
-\r
- if (!IsListEmpty (&Tcb->RcvQue) || GET_RCV_DATASIZE (Tcb->Sk) != 0) {\r
-\r
- DEBUG ((EFI_D_WARN, "TcpOnAppClose: connection reset "\r
- "because data is lost for TCB %p\n", Tcb));\r
-\r
- TcpResetConnection (Tcb);\r
- TcpClose (Tcb);\r
- return;\r
- }\r
-\r
- switch (Tcb->State) {\r
- case TCP_CLOSED:\r
- case TCP_LISTEN:\r
- case TCP_SYN_SENT:\r
- TcpSetState (Tcb, TCP_CLOSED);\r
- break;\r
-\r
- case TCP_SYN_RCVD:\r
- case TCP_ESTABLISHED:\r
- TcpSetState (Tcb, TCP_FIN_WAIT_1);\r
- break;\r
-\r
- case TCP_CLOSE_WAIT:\r
- TcpSetState (Tcb, TCP_LAST_ACK);\r
- break;\r
- default:\r
- break;\r
- }\r
-\r
- TcpToSendData (Tcb, 1);\r
-}\r
-\r
-\r
-/**\r
- Check whether the application's newly delivered data can be sent out.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @retval 0 Whether the data is sent out or is buffered for\r
- further sending.\r
- @retval -1 The Tcb is not in a state that data is permitted to\r
- be sent out.\r
-\r
-**/\r
-INTN\r
-TcpOnAppSend (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
-\r
- switch (Tcb->State) {\r
- case TCP_CLOSED:\r
- return -1;\r
-\r
- case TCP_LISTEN:\r
- return -1;\r
-\r
- case TCP_SYN_SENT:\r
- case TCP_SYN_RCVD:\r
- return 0;\r
-\r
- case TCP_ESTABLISHED:\r
- case TCP_CLOSE_WAIT:\r
- TcpToSendData (Tcb, 0);\r
- return 0;\r
-\r
- case TCP_FIN_WAIT_1:\r
- case TCP_FIN_WAIT_2:\r
- case TCP_CLOSING:\r
- case TCP_LAST_ACK:\r
- case TCP_TIME_WAIT:\r
- return -1;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-\r
-/**\r
- Application has consumed some data, check whether\r
- to send a window updata ack or a delayed ack.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpOnAppConsume (\r
- IN TCP_CB *Tcb\r
- )\r
-{\r
- UINT32 TcpOld;\r
-\r
- switch (Tcb->State) {\r
- case TCP_CLOSED:\r
- return;\r
-\r
- case TCP_LISTEN:\r
- return;\r
-\r
- case TCP_SYN_SENT:\r
- case TCP_SYN_RCVD:\r
- return;\r
-\r
- case TCP_ESTABLISHED:\r
- TcpOld = TcpRcvWinOld (Tcb);\r
- if (TcpRcvWinNow (Tcb) > TcpOld) {\r
-\r
- if (TcpOld < Tcb->RcvMss) {\r
-\r
- DEBUG ((EFI_D_NET, "TcpOnAppConsume: send a window"\r
- " update for a window closed Tcb %p\n", Tcb));\r
-\r
- TcpSendAck (Tcb);\r
- } else if (Tcb->DelayedAck == 0) {\r
-\r
- DEBUG ((EFI_D_NET, "TcpOnAppConsume: scheduled a delayed"\r
- " ACK to update window for Tcb %p\n", Tcb));\r
-\r
- Tcb->DelayedAck = 1;\r
- }\r
- }\r
-\r
- break;\r
-\r
- case TCP_CLOSE_WAIT:\r
- return;\r
-\r
- case TCP_FIN_WAIT_1:\r
- case TCP_FIN_WAIT_2:\r
- case TCP_CLOSING:\r
- case TCP_LAST_ACK:\r
- case TCP_TIME_WAIT:\r
- return;\r
-\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Abort the connection by sending a reset segment, called\r
- when the application wants to abort the connection.\r
-\r
- @param Tcb Pointer to the TCP_CB of the TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpOnAppAbort (\r
- IN TCP_CB *Tcb\r
- )\r
-{\r
- DEBUG ((EFI_D_WARN, "TcpOnAppAbort: connection reset "\r
- "issued by application for TCB %p\n", Tcb));\r
-\r
- switch (Tcb->State) {\r
- case TCP_SYN_RCVD:\r
- case TCP_ESTABLISHED:\r
- case TCP_FIN_WAIT_1:\r
- case TCP_FIN_WAIT_2:\r
- case TCP_CLOSE_WAIT:\r
- TcpResetConnection (Tcb);\r
- break;\r
- default:\r
- break;\r
- }\r
-\r
- TcpSetState (Tcb, TCP_CLOSED);\r
-}\r
-\r
-/**\r
- Install the device path protocol on the TCP instance.\r
-\r
- @param Sock Pointer to the socket representing the TCP instance.\r
-\r
- @retval EFI_SUCCESS The device path protocol is installed.\r
- @retval other Failed to install the device path protocol.\r
-\r
-**/\r
-EFI_STATUS\r
-TcpInstallDevicePath (\r
- IN SOCKET *Sock\r
- )\r
-{\r
- TCP4_PROTO_DATA *TcpProto;\r
- TCP4_SERVICE_DATA *TcpService;\r
- TCP_CB *Tcb;\r
- IPv4_DEVICE_PATH Ip4DPathNode;\r
- EFI_STATUS Status;\r
- TCP_PORTNO LocalPort;\r
- TCP_PORTNO RemotePort;\r
-\r
- TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;\r
- TcpService = TcpProto->TcpService;\r
- Tcb = TcpProto->TcpPcb;\r
-\r
- LocalPort = NTOHS (Tcb->LocalEnd.Port);\r
- RemotePort = NTOHS (Tcb->RemoteEnd.Port);\r
- NetLibCreateIPv4DPathNode (\r
- &Ip4DPathNode,\r
- TcpService->ControllerHandle,\r
- Tcb->LocalEnd.Ip,\r
- LocalPort,\r
- Tcb->RemoteEnd.Ip,\r
- RemotePort,\r
- EFI_IP_PROTO_TCP,\r
- Tcb->UseDefaultAddr\r
- );\r
-\r
- IP4_COPY_ADDRESS (&Ip4DPathNode.SubnetMask, &Tcb->SubnetMask);\r
-\r
- Sock->DevicePath = AppendDevicePathNode (\r
- Sock->ParentDevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *) &Ip4DPathNode\r
- );\r
- if (Sock->DevicePath == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Status = gBS->InstallProtocolInterface (\r
- &Sock->SockHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- Sock->DevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (Sock->DevicePath);\r
- }\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-/** @file\r
- Routines to process TCP option.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Tcp4Main.h"\r
-\r
-/**\r
- Get a UINT16 value from buffer.\r
-\r
- @param Buf Pointer to input buffer.\r
-\r
- @return The UINT16 value get from buffer.\r
-\r
-**/\r
-UINT16\r
-TcpGetUint16 (\r
- IN UINT8 *Buf\r
- )\r
-{\r
- UINT16 Value;\r
- CopyMem (&Value, Buf, sizeof (UINT16));\r
- return NTOHS (Value);\r
-}\r
-\r
-/**\r
- Get a UINT32 value from buffer.\r
-\r
- @param Buf Pointer to input buffer.\r
-\r
- @return The UINT32 value get from buffer.\r
-\r
-**/\r
-UINT32\r
-TcpGetUint32 (\r
- IN UINT8 *Buf\r
- )\r
-{\r
- UINT32 Value;\r
- CopyMem (&Value, Buf, sizeof (UINT32));\r
- return NTOHL (Value);\r
-}\r
-\r
-/**\r
- Put a UINT32 value in buffer.\r
-\r
- @param Buf Pointer to the buffer.\r
- @param Data The UINT32 Date to put in buffer\r
-\r
-**/\r
-VOID\r
-TcpPutUint32 (\r
- OUT UINT8 *Buf,\r
- IN UINT32 Data\r
- )\r
-{\r
- Data = HTONL (Data);\r
- CopyMem (Buf, &Data, sizeof (UINT32));\r
-}\r
-\r
-\r
-/**\r
- Compute the window scale value according to the given buffer size.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @return The scale value.\r
-\r
-**/\r
-UINT8\r
-TcpComputeScale (\r
- IN TCP_CB *Tcb\r
- )\r
-{\r
- UINT8 Scale;\r
- UINT32 BufSize;\r
-\r
- ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));\r
-\r
- BufSize = GET_RCV_BUFFSIZE (Tcb->Sk);\r
-\r
- Scale = 0;\r
- while ((Scale < TCP_OPTION_MAX_WS) &&\r
- ((UINT32) (TCP_OPTION_MAX_WIN << Scale) < BufSize)) {\r
-\r
- Scale++;\r
- }\r
-\r
- return Scale;\r
-}\r
-\r
-\r
-/**\r
- Build the TCP option in three-way handshake.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the buffer to store the options.\r
-\r
- @return The total length of the TCP option field.\r
-\r
-**/\r
-UINT16\r
-TcpSynBuildOption (\r
- IN TCP_CB *Tcb,\r
- IN NET_BUF *Nbuf\r
- )\r
-{\r
- UINT8 *Data;\r
- UINT16 Len;\r
-\r
- ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));\r
-\r
- Len = 0;\r
-\r
- //\r
- // Add timestamp option if not disabled by application\r
- // and it is the first SYN segment or the peer has sent\r
- // us its timestamp.\r
- //\r
- if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS) &&\r
- (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||\r
- TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS))) {\r
-\r
- Data = NetbufAllocSpace (\r
- Nbuf,\r
- TCP_OPTION_TS_ALIGNED_LEN,\r
- NET_BUF_HEAD\r
- );\r
-\r
- ASSERT (Data != NULL);\r
- Len += TCP_OPTION_TS_ALIGNED_LEN;\r
-\r
- TcpPutUint32 (Data, TCP_OPTION_TS_FAST);\r
- TcpPutUint32 (Data + 4, mTcpTick);\r
- TcpPutUint32 (Data + 8, 0);\r
- }\r
-\r
- //\r
- // Build window scale option, only when are configured\r
- // to send WS option, and either we are doing active\r
- // open or we have received WS option from peer.\r
- //\r
- if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS) &&\r
- (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||\r
- TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS))) {\r
-\r
- Data = NetbufAllocSpace (\r
- Nbuf,\r
- TCP_OPTION_WS_ALIGNED_LEN,\r
- NET_BUF_HEAD\r
- );\r
-\r
- ASSERT (Data != NULL);\r
-\r
- Len += TCP_OPTION_WS_ALIGNED_LEN;\r
- TcpPutUint32 (Data, TCP_OPTION_WS_FAST | TcpComputeScale (Tcb));\r
- }\r
-\r
- //\r
- // Build MSS option\r
- //\r
- Data = NetbufAllocSpace (Nbuf, TCP_OPTION_MSS_LEN, 1);\r
- ASSERT (Data != NULL);\r
-\r
- Len += TCP_OPTION_MSS_LEN;\r
- TcpPutUint32 (Data, TCP_OPTION_MSS_FAST | Tcb->RcvMss);\r
-\r
- return Len;\r
-}\r
-\r
-\r
-/**\r
- Build the TCP option in synchronized states.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the buffer to store the options.\r
-\r
- @return The total length of the TCP option field.\r
-\r
-**/\r
-UINT16\r
-TcpBuildOption (\r
- IN TCP_CB *Tcb,\r
- IN NET_BUF *Nbuf\r
- )\r
-{\r
- UINT8 *Data;\r
- UINT16 Len;\r
-\r
- ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));\r
- Len = 0;\r
-\r
- //\r
- // Build Timestamp option\r
- //\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_TS) &&\r
- !TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_RST)) {\r
-\r
- Data = NetbufAllocSpace (\r
- Nbuf,\r
- TCP_OPTION_TS_ALIGNED_LEN,\r
- NET_BUF_HEAD\r
- );\r
-\r
- ASSERT (Data != NULL);\r
- Len += TCP_OPTION_TS_ALIGNED_LEN;\r
-\r
- TcpPutUint32 (Data, TCP_OPTION_TS_FAST);\r
- TcpPutUint32 (Data + 4, mTcpTick);\r
- TcpPutUint32 (Data + 8, Tcb->TsRecent);\r
- }\r
-\r
- return Len;\r
-}\r
-\r
-\r
-/**\r
- Parse the supported options.\r
-\r
- @param Tcp Pointer to the TCP_CB of this TCP instance.\r
- @param Option Pointer to the TCP_OPTION used to store the successfully pasrsed\r
- options.\r
-\r
- @retval 0 The options are successfully pasrsed.\r
- @retval -1 Ilegal option was found.\r
-\r
-**/\r
-INTN\r
-TcpParseOption (\r
- IN TCP_HEAD *Tcp,\r
- IN OUT TCP_OPTION *Option\r
- )\r
-{\r
- UINT8 *Head;\r
- UINT8 TotalLen;\r
- UINT8 Cur;\r
- UINT8 Type;\r
- UINT8 Len;\r
-\r
- ASSERT ((Tcp != NULL) && (Option != NULL));\r
-\r
- Option->Flag = 0;\r
-\r
- TotalLen = (UINT8) ((Tcp->HeadLen << 2) - sizeof (TCP_HEAD));\r
- if (TotalLen <= 0) {\r
- return 0;\r
- }\r
-\r
- Head = (UINT8 *) (Tcp + 1);\r
-\r
- //\r
- // Fast process of timestamp option\r
- //\r
- if ((TotalLen == TCP_OPTION_TS_ALIGNED_LEN) &&\r
- (TcpGetUint32 (Head) == TCP_OPTION_TS_FAST)) {\r
-\r
- Option->TSVal = TcpGetUint32 (Head + 4);\r
- Option->TSEcr = TcpGetUint32 (Head + 8);\r
- Option->Flag = TCP_OPTION_RCVD_TS;\r
-\r
- return 0;\r
- }\r
-\r
- //\r
- // Slow path to process the options.\r
- //\r
- Cur = 0;\r
-\r
- while (Cur < TotalLen) {\r
- Type = Head[Cur];\r
-\r
- switch (Type) {\r
- case TCP_OPTION_MSS:\r
- Len = Head[Cur + 1];\r
-\r
- if ((Len != TCP_OPTION_MSS_LEN) ||\r
- (TotalLen - Cur < TCP_OPTION_MSS_LEN)) {\r
-\r
- return -1;\r
- }\r
-\r
- Option->Mss = TcpGetUint16 (&Head[Cur + 2]);\r
- TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_MSS);\r
-\r
- Cur += TCP_OPTION_MSS_LEN;\r
- break;\r
-\r
- case TCP_OPTION_WS:\r
- Len = Head[Cur + 1];\r
-\r
- if ((Len != TCP_OPTION_WS_LEN) ||\r
- (TotalLen - Cur < TCP_OPTION_WS_LEN)) {\r
-\r
- return -1;\r
- }\r
-\r
- Option->WndScale = (UINT8) MIN (14, Head[Cur + 2]);\r
- TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_WS);\r
-\r
- Cur += TCP_OPTION_WS_LEN;\r
- break;\r
-\r
- case TCP_OPTION_TS:\r
- Len = Head[Cur + 1];\r
-\r
- if ((Len != TCP_OPTION_TS_LEN) ||\r
- (TotalLen - Cur < TCP_OPTION_TS_LEN)) {\r
-\r
- return -1;\r
- }\r
-\r
- Option->TSVal = TcpGetUint32 (&Head[Cur + 2]);\r
- Option->TSEcr = TcpGetUint32 (&Head[Cur + 6]);\r
- TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_TS);\r
-\r
- Cur += TCP_OPTION_TS_LEN;\r
- break;\r
-\r
- case TCP_OPTION_NOP:\r
- Cur++;\r
- break;\r
-\r
- case TCP_OPTION_EOP:\r
- Cur = TotalLen;\r
- break;\r
-\r
- default:\r
- Len = Head[Cur + 1];\r
-\r
- if ((TotalLen - Cur) < Len || Len < 2) {\r
- return -1;\r
- }\r
-\r
- Cur = (UINT8) (Cur + Len);\r
- break;\r
- }\r
-\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-\r
+++ /dev/null
-/** @file\r
- Tcp option's routine header file.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#ifndef _TCP4_OPTION_H_\r
-#define _TCP4_OPTION_H_\r
-\r
-///\r
-/// The structure to store the parse option value.\r
-/// ParseOption only parse the options, don't process them.\r
-///\r
-typedef struct _TCP_OPTION {\r
- UINT8 Flag; ///< Flag such as TCP_OPTION_RCVD_MSS\r
- UINT8 WndScale; ///< The WndScale received\r
- UINT16 Mss; ///< The Mss received\r
- UINT32 TSVal; ///< The TSVal field in a timestamp option\r
- UINT32 TSEcr; ///< The TSEcr field in a timestamp option\r
-} TCP_OPTION;\r
-\r
-//\r
-// supported TCP option type and their length\r
-//\r
-#define TCP_OPTION_EOP 0 ///< End Of oPtion\r
-#define TCP_OPTION_NOP 1 ///< No-Option.\r
-#define TCP_OPTION_MSS 2 ///< Maximum Segment Size\r
-#define TCP_OPTION_WS 3 ///< Window scale\r
-#define TCP_OPTION_TS 8 ///< Timestamp\r
-#define TCP_OPTION_MSS_LEN 4 ///< Length of MSS option\r
-#define TCP_OPTION_WS_LEN 3 ///< Length of window scale option\r
-#define TCP_OPTION_TS_LEN 10 ///< Length of timestamp option\r
-#define TCP_OPTION_WS_ALIGNED_LEN 4 ///< Length of window scale option, aligned\r
-#define TCP_OPTION_TS_ALIGNED_LEN 12 ///< Length of timestamp option, aligned\r
-\r
-//\r
-// recommend format of timestamp window scale\r
-// option for fast process.\r
-//\r
-#define TCP_OPTION_TS_FAST ((TCP_OPTION_NOP << 24) | \\r
- (TCP_OPTION_NOP << 16) | \\r
- (TCP_OPTION_TS << 8) | \\r
- (TCP_OPTION_TS_LEN))\r
-\r
-#define TCP_OPTION_WS_FAST ((TCP_OPTION_NOP << 24) | \\r
- (TCP_OPTION_WS << 16) | \\r
- (TCP_OPTION_WS_LEN << 8))\r
-\r
-#define TCP_OPTION_MSS_FAST ((TCP_OPTION_MSS << 24) | (TCP_OPTION_MSS_LEN << 16))\r
-\r
-//\r
-// Other misc definations\r
-//\r
-#define TCP_OPTION_RCVD_MSS 0x01\r
-#define TCP_OPTION_RCVD_WS 0x02\r
-#define TCP_OPTION_RCVD_TS 0x04\r
-#define TCP_OPTION_MAX_WS 14 ///< Maxium window scale value\r
-#define TCP_OPTION_MAX_WIN 0xffff ///< Max window size in TCP header\r
-\r
-\r
-/**\r
- Compute the window scale value according to the given buffer size.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @return The scale value.\r
-\r
-**/\r
-UINT8\r
-TcpComputeScale (\r
- IN TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Build the TCP option in three-way handshake.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the buffer to store the options.\r
-\r
- @return The total length of the TCP option field.\r
-\r
-**/\r
-UINT16\r
-TcpSynBuildOption (\r
- IN TCP_CB *Tcb,\r
- IN NET_BUF *Nbuf\r
- );\r
-\r
-/**\r
- Build the TCP option in synchronized states.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the buffer to store the options.\r
-\r
- @return The total length of the TCP option field.\r
-\r
-**/\r
-UINT16\r
-TcpBuildOption (\r
- IN TCP_CB *Tcb,\r
- IN NET_BUF *Nbuf\r
- );\r
-\r
-/**\r
- Parse the supported options.\r
-\r
- @param Tcp Pointer to the TCP_CB of this TCP instance.\r
- @param Option Pointer to the TCP_OPTION used to store the successfully pasrsed\r
- options.\r
-\r
- @retval 0 The options are successfully pasrsed.\r
- @retval -1 Ilegal option was found.\r
-\r
-**/\r
-INTN\r
-TcpParseOption (\r
- IN TCP_HEAD *Tcp,\r
- IN OUT TCP_OPTION *Option\r
- );\r
-\r
-\r
-#endif\r
+++ /dev/null
-/** @file\r
- TCP output process routines.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Tcp4Main.h"\r
-\r
-UINT8 mTcpOutFlag[] = {\r
- 0, // TCP_CLOSED\r
- 0, // TCP_LISTEN\r
- TCP_FLG_SYN, // TCP_SYN_SENT\r
- TCP_FLG_SYN | TCP_FLG_ACK, // TCP_SYN_RCVD\r
- TCP_FLG_ACK, // TCP_ESTABLISHED\r
- TCP_FLG_FIN | TCP_FLG_ACK, // TCP_FIN_WAIT_1\r
- TCP_FLG_ACK, // TCP_FIN_WAIT_2\r
- TCP_FLG_ACK | TCP_FLG_FIN, // TCP_CLOSING\r
- TCP_FLG_ACK, // TCP_TIME_WAIT\r
- TCP_FLG_ACK, // TCP_CLOSE_WAIT\r
- TCP_FLG_FIN | TCP_FLG_ACK // TCP_LAST_ACK\r
-};\r
-\r
-\r
-/**\r
- Compute the sequence space left in the old receive window.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @return The sequence space left in the old receive window.\r
-\r
-**/\r
-UINT32\r
-TcpRcvWinOld (\r
- IN TCP_CB *Tcb\r
- )\r
-{\r
- UINT32 OldWin;\r
-\r
- OldWin = 0;\r
-\r
- if (TCP_SEQ_GT (Tcb->RcvWl2 + Tcb->RcvWnd, Tcb->RcvNxt)) {\r
-\r
- OldWin = TCP_SUB_SEQ (\r
- Tcb->RcvWl2 + Tcb->RcvWnd,\r
- Tcb->RcvNxt\r
- );\r
- }\r
-\r
- return OldWin;\r
-}\r
-\r
-\r
-/**\r
- Compute the current receive window.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @return The size of the current receive window, in bytes.\r
-\r
-**/\r
-UINT32\r
-TcpRcvWinNow (\r
- IN TCP_CB *Tcb\r
- )\r
-{\r
- SOCKET *Sk;\r
- UINT32 Win;\r
- UINT32 Increase;\r
- UINT32 OldWin;\r
-\r
- Sk = Tcb->Sk;\r
- ASSERT (Sk != NULL);\r
-\r
- OldWin = TcpRcvWinOld (Tcb);\r
-\r
- Win = SockGetFreeSpace (Sk, SOCK_RCV_BUF);\r
-\r
- Increase = 0;\r
- if (Win > OldWin) {\r
- Increase = Win - OldWin;\r
- }\r
-\r
- //\r
- // Receiver's SWS: don't advertise a bigger window\r
- // unless it can be increased by at least one Mss or\r
- // half of the receive buffer.\r
- //\r
- if ((Increase > Tcb->SndMss) ||\r
- (2 * Increase >= GET_RCV_BUFFSIZE (Sk))) {\r
-\r
- return Win;\r
- }\r
-\r
- return OldWin;\r
-}\r
-\r
-\r
-/**\r
- Compute the value to fill in the window size field of the outgoing segment.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Syn The flag to indicate whether the outgoing segment is a SYN\r
- segment.\r
-\r
- @return The value of the local receive window size used to fill the outing segment.\r
-\r
-**/\r
-UINT16\r
-TcpComputeWnd (\r
- IN OUT TCP_CB *Tcb,\r
- IN BOOLEAN Syn\r
- )\r
-{\r
- UINT32 Wnd;\r
-\r
- //\r
- // RFC requires that initial window not be scaled\r
- //\r
- if (Syn) {\r
-\r
- Wnd = GET_RCV_BUFFSIZE (Tcb->Sk);\r
- } else {\r
-\r
- Wnd = TcpRcvWinNow (Tcb);\r
-\r
- Tcb->RcvWnd = Wnd;\r
- }\r
-\r
- Wnd = MIN (Wnd >> Tcb->RcvWndScale, 0xffff);\r
- return NTOHS ((UINT16) Wnd);\r
-}\r
-\r
-\r
-/**\r
- Get the maximum SndNxt.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @return The sequence number of the maximum SndNxt.\r
-\r
-**/\r
-TCP_SEQNO\r
-TcpGetMaxSndNxt (\r
- IN TCP_CB *Tcb\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- NET_BUF *Nbuf;\r
-\r
- if (IsListEmpty (&Tcb->SndQue)) {\r
- return Tcb->SndNxt;\r
- }\r
-\r
- Entry = Tcb->SndQue.BackLink;\r
- Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);\r
-\r
- ASSERT (TCP_SEQ_GEQ (TCPSEG_NETBUF (Nbuf)->End, Tcb->SndNxt));\r
- return TCPSEG_NETBUF (Nbuf)->End;\r
-}\r
-\r
-\r
-/**\r
- Compute how much data to send.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Force Whether to ignore the sender's SWS avoidance algorithm and send\r
- out data by force.\r
-\r
- @return The length of the data can be sent, if 0, no data can be sent.\r
-\r
-**/\r
-UINT32\r
-TcpDataToSend (\r
- IN TCP_CB *Tcb,\r
- IN INTN Force\r
- )\r
-{\r
- SOCKET *Sk;\r
- UINT32 Win;\r
- UINT32 Len;\r
- UINT32 Left;\r
- UINT32 Limit;\r
-\r
- Sk = Tcb->Sk;\r
- ASSERT (Sk != NULL);\r
-\r
- //\r
- // TCP should NOT send data beyond the send window\r
- // and congestion window. The right edge of send\r
- // window is defined as SND.WL2 + SND.WND. The right\r
- // edge of congestion window is defined as SND.UNA +\r
- // CWND.\r
- //\r
- Win = 0;\r
- Limit = Tcb->SndWl2 + Tcb->SndWnd;\r
-\r
- if (TCP_SEQ_GT (Limit, Tcb->SndUna + Tcb->CWnd)) {\r
-\r
- Limit = Tcb->SndUna + Tcb->CWnd;\r
- }\r
-\r
- if (TCP_SEQ_GT (Limit, Tcb->SndNxt)) {\r
- Win = TCP_SUB_SEQ (Limit, Tcb->SndNxt);\r
- }\r
-\r
- //\r
- // The data to send contains two parts: the data on the\r
- // socket send queue, and the data on the TCB's send\r
- // buffer. The later can be non-zero if the peer shrinks\r
- // its advertised window.\r
- //\r
- Left = GET_SND_DATASIZE (Sk) +\r
- TCP_SUB_SEQ (TcpGetMaxSndNxt (Tcb), Tcb->SndNxt);\r
-\r
- Len = MIN (Win, Left);\r
-\r
- if (Len > Tcb->SndMss) {\r
- Len = Tcb->SndMss;\r
- }\r
-\r
- if ((Force != 0)|| (Len == 0 && Left == 0)) {\r
- return Len;\r
- }\r
-\r
- if (Len == 0 && Left != 0) {\r
- goto SetPersistTimer;\r
- }\r
-\r
- //\r
- // Sender's SWS avoidance: Don't send a small segment unless\r
- // a)A full-sized segment can be sent,\r
- // b)at least one-half of the maximum sized windows that\r
- // the other end has ever advertised.\r
- // c)It can send everything it has and either it isn't\r
- // expecting an ACK or the Nagle algorithm is disabled.\r
- //\r
- if ((Len == Tcb->SndMss) || (2 * Len >= Tcb->SndWndMax)) {\r
-\r
- return Len;\r
- }\r
-\r
- if ((Len == Left) &&\r
- ((Tcb->SndNxt == Tcb->SndUna) ||\r
- TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE))) {\r
-\r
- return Len;\r
- }\r
-\r
- //\r
- // RFC1122 suggests to set a timer when SWSA forbids TCP\r
- // sending more data, and combine it with probe timer.\r
- //\r
-SetPersistTimer:\r
- if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT)) {\r
-\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "TcpDataToSend: enter persistent state for TCB %p\n",\r
- Tcb)\r
- );\r
-\r
- if (!Tcb->ProbeTimerOn) {\r
- TcpSetProbeTimer (Tcb);\r
- }\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-\r
-/**\r
- Build the TCP header of the TCP segment and transmit the segment by IP.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Nbuf Pointer to the buffer containing the segment to be sent out.\r
-\r
- @retval 0 The segment is sent out successfully.\r
- @retval other Error condition occurred.\r
-\r
-**/\r
-INTN\r
-TcpTransmitSegment (\r
- IN OUT TCP_CB *Tcb,\r
- IN NET_BUF *Nbuf\r
- )\r
-{\r
- UINT16 Len;\r
- TCP_HEAD *Head;\r
- TCP_SEG *Seg;\r
- BOOLEAN Syn;\r
- UINT32 DataLen;\r
-\r
- ASSERT ((Nbuf != NULL) && (Nbuf->Tcp == NULL) && (TcpVerifySegment (Nbuf) != 0));\r
-\r
- DataLen = Nbuf->TotalSize;\r
-\r
- Seg = TCPSEG_NETBUF (Nbuf);\r
- Syn = TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN);\r
-\r
- if (Syn) {\r
-\r
- Len = TcpSynBuildOption (Tcb, Nbuf);\r
- } else {\r
-\r
- Len = TcpBuildOption (Tcb, Nbuf);\r
- }\r
-\r
- ASSERT ((Len % 4 == 0) && (Len <= 40));\r
-\r
- Len += sizeof (TCP_HEAD);\r
-\r
- Head = (TCP_HEAD *) NetbufAllocSpace (\r
- Nbuf,\r
- sizeof (TCP_HEAD),\r
- NET_BUF_HEAD\r
- );\r
-\r
- ASSERT (Head != NULL);\r
-\r
- Nbuf->Tcp = Head;\r
-\r
- Head->SrcPort = Tcb->LocalEnd.Port;\r
- Head->DstPort = Tcb->RemoteEnd.Port;\r
- Head->Seq = NTOHL (Seg->Seq);\r
- Head->Ack = NTOHL (Tcb->RcvNxt);\r
- Head->HeadLen = (UINT8) (Len >> 2);\r
- Head->Res = 0;\r
- Head->Wnd = TcpComputeWnd (Tcb, Syn);\r
- Head->Checksum = 0;\r
-\r
- //\r
- // Check whether to set the PSH flag.\r
- //\r
- TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_PSH);\r
-\r
- if (DataLen != 0) {\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_PSH) &&\r
- TCP_SEQ_BETWEEN (Seg->Seq, Tcb->SndPsh, Seg->End)) {\r
-\r
- TCP_SET_FLG (Seg->Flag, TCP_FLG_PSH);\r
- TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);\r
-\r
- } else if ((Seg->End == Tcb->SndNxt) &&\r
- (GET_SND_DATASIZE (Tcb->Sk) == 0)) {\r
-\r
- TCP_SET_FLG (Seg->Flag, TCP_FLG_PSH);\r
- }\r
- }\r
-\r
- //\r
- // Check whether to set the URG flag and the urgent pointer.\r
- //\r
- TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_URG);\r
-\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_URG) &&\r
- TCP_SEQ_LEQ (Seg->Seq, Tcb->SndUp)) {\r
-\r
- TCP_SET_FLG (Seg->Flag, TCP_FLG_URG);\r
-\r
- if (TCP_SEQ_LT (Tcb->SndUp, Seg->End)) {\r
-\r
- Seg->Urg = (UINT16) TCP_SUB_SEQ (Tcb->SndUp, Seg->Seq);\r
- } else {\r
-\r
- Seg->Urg = (UINT16) MIN (\r
- TCP_SUB_SEQ (Tcb->SndUp,\r
- Seg->Seq),\r
- 0xffff\r
- );\r
- }\r
- }\r
-\r
- Head->Flag = Seg->Flag;\r
- Head->Urg = NTOHS (Seg->Urg);\r
- Head->Checksum = TcpChecksum (Nbuf, Tcb->HeadSum);\r
-\r
- //\r
- // update the TCP session's control information\r
- //\r
- Tcb->RcvWl2 = Tcb->RcvNxt;\r
- if (Syn) {\r
- Tcb->RcvWnd = NTOHS (Head->Wnd);\r
- }\r
-\r
- //\r
- // clear delayedack flag\r
- //\r
- Tcb->DelayedAck = 0;\r
-\r
- return TcpSendIpPacket (Tcb, Nbuf, Tcb->LocalEnd.Ip, Tcb->RemoteEnd.Ip);\r
-}\r
-\r
-\r
-/**\r
- Get a segment from the Tcb's SndQue.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seq The sequence number of the segment.\r
- @param Len The maximum length of the segment.\r
-\r
- @return Pointer to the segment, if NULL some error occurred.\r
-\r
-**/\r
-NET_BUF *\r
-TcpGetSegmentSndQue (\r
- IN TCP_CB *Tcb,\r
- IN TCP_SEQNO Seq,\r
- IN UINT32 Len\r
- )\r
-{\r
- LIST_ENTRY *Head;\r
- LIST_ENTRY *Cur;\r
- NET_BUF *Node;\r
- TCP_SEG *Seg;\r
- NET_BUF *Nbuf;\r
- TCP_SEQNO End;\r
- UINT8 *Data;\r
- UINT8 Flag;\r
- INT32 Offset;\r
- INT32 CopyLen;\r
-\r
- ASSERT ((Tcb != NULL) && TCP_SEQ_LEQ (Seq, Tcb->SndNxt) && (Len > 0));\r
-\r
- //\r
- // Find the segment that contains the Seq.\r
- //\r
- Head = &Tcb->SndQue;\r
-\r
- Node = NULL;\r
- Seg = NULL;\r
-\r
- NET_LIST_FOR_EACH (Cur, Head) {\r
- Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);\r
- Seg = TCPSEG_NETBUF (Node);\r
-\r
- if (TCP_SEQ_LT (Seq, Seg->End) && TCP_SEQ_LEQ (Seg->Seq, Seq)) {\r
-\r
- break;\r
- }\r
- }\r
-\r
- ASSERT (Cur != Head);\r
- ASSERT (Node != NULL);\r
- ASSERT (Seg != NULL);\r
-\r
- //\r
- // Return the buffer if it can be returned without\r
- // adjustment:\r
- //\r
- if ((Seg->Seq == Seq) &&\r
- TCP_SEQ_LEQ (Seg->End, Seg->Seq + Len) &&\r
- !NET_BUF_SHARED (Node)) {\r
-\r
- NET_GET_REF (Node);\r
- return Node;\r
- }\r
-\r
- //\r
- // Create a new buffer and copy data there.\r
- //\r
- Nbuf = NetbufAlloc (Len + TCP_MAX_HEAD);\r
-\r
- if (Nbuf == NULL) {\r
- return NULL;\r
- }\r
-\r
- NetbufReserve (Nbuf, TCP_MAX_HEAD);\r
-\r
- Flag = Seg->Flag;\r
- End = Seg->End;\r
-\r
- if (TCP_SEQ_LT (Seq + Len, Seg->End)) {\r
- End = Seq + Len;\r
- }\r
-\r
- CopyLen = TCP_SUB_SEQ (End, Seq);\r
- Offset = TCP_SUB_SEQ (Seq, Seg->Seq);\r
-\r
- //\r
- // If SYN is set and out of the range, clear the flag.\r
- // Because the sequence of the first byte is SEG.SEQ+1,\r
- // adjust Offset by -1. If SYN is in the range, copy\r
- // one byte less.\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {\r
-\r
- if (TCP_SEQ_LT (Seg->Seq, Seq)) {\r
-\r
- TCP_CLEAR_FLG (Flag, TCP_FLG_SYN);\r
- Offset--;\r
- } else {\r
-\r
- CopyLen--;\r
- }\r
- }\r
-\r
- //\r
- // If FIN is set and in the range, copy one byte less,\r
- // and if it is out of the range, clear the flag.\r
- //\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {\r
-\r
- if (Seg->End == End) {\r
-\r
- CopyLen--;\r
- } else {\r
-\r
- TCP_CLEAR_FLG (Flag, TCP_FLG_FIN);\r
- }\r
- }\r
-\r
- ASSERT (CopyLen >= 0);\r
-\r
- //\r
- // copy data to the segment\r
- //\r
- if (CopyLen != 0) {\r
- Data = NetbufAllocSpace (Nbuf, CopyLen, NET_BUF_TAIL);\r
- ASSERT (Data != NULL);\r
-\r
- if ((INT32) NetbufCopy (Node, Offset, CopyLen, Data) != CopyLen) {\r
- goto OnError;\r
- }\r
- }\r
-\r
- CopyMem (TCPSEG_NETBUF (Nbuf), Seg, sizeof (TCP_SEG));\r
-\r
- TCPSEG_NETBUF (Nbuf)->Seq = Seq;\r
- TCPSEG_NETBUF (Nbuf)->End = End;\r
- TCPSEG_NETBUF (Nbuf)->Flag = Flag;\r
-\r
- return Nbuf;\r
-\r
-OnError:\r
- NetbufFree (Nbuf);\r
- return NULL;\r
-}\r
-\r
-\r
-/**\r
- Get a segment from the Tcb's socket buffer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seq The sequence number of the segment.\r
- @param Len The maximum length of the segment.\r
-\r
- @return Pointer to the segment, if NULL some error occurred.\r
-\r
-**/\r
-NET_BUF *\r
-TcpGetSegmentSock (\r
- IN TCP_CB *Tcb,\r
- IN TCP_SEQNO Seq,\r
- IN UINT32 Len\r
- )\r
-{\r
- NET_BUF *Nbuf;\r
- UINT8 *Data;\r
- UINT32 DataGet;\r
-\r
- ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));\r
-\r
- Nbuf = NetbufAlloc (Len + TCP_MAX_HEAD);\r
-\r
- if (Nbuf == NULL) {\r
- DEBUG ((EFI_D_ERROR, "TcpGetSegmentSock: failed to allocate "\r
- "a netbuf for TCB %p\n",Tcb));\r
-\r
- return NULL;\r
- }\r
-\r
- NetbufReserve (Nbuf, TCP_MAX_HEAD);\r
-\r
- DataGet = 0;\r
-\r
- if (Len != 0) {\r
- //\r
- // copy data to the segment.\r
- //\r
- Data = NetbufAllocSpace (Nbuf, Len, NET_BUF_TAIL);\r
- ASSERT (Data != NULL);\r
-\r
- DataGet = SockGetDataToSend (Tcb->Sk, 0, Len, Data);\r
- }\r
-\r
- NET_GET_REF (Nbuf);\r
-\r
- TCPSEG_NETBUF (Nbuf)->Seq = Seq;\r
- TCPSEG_NETBUF (Nbuf)->End = Seq + Len;\r
-\r
- InsertTailList (&(Tcb->SndQue), &(Nbuf->List));\r
-\r
- if (DataGet != 0) {\r
-\r
- SockDataSent (Tcb->Sk, DataGet);\r
- }\r
-\r
- return Nbuf;\r
-}\r
-\r
-\r
-/**\r
- Get a segment starting from sequence Seq of a maximum\r
- length of Len.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seq The sequence number of the segment.\r
- @param Len The maximum length of the segment.\r
-\r
- @return Pointer to the segment, if NULL some error occurred.\r
-\r
-**/\r
-NET_BUF *\r
-TcpGetSegment (\r
- IN TCP_CB *Tcb,\r
- IN TCP_SEQNO Seq,\r
- IN UINT32 Len\r
- )\r
-{\r
- NET_BUF *Nbuf;\r
-\r
- ASSERT (Tcb != NULL);\r
-\r
- //\r
- // Compare the SndNxt with the max sequence number sent.\r
- //\r
- if ((Len != 0) && TCP_SEQ_LT (Seq, TcpGetMaxSndNxt (Tcb))) {\r
-\r
- Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len);\r
- } else {\r
-\r
- Nbuf = TcpGetSegmentSock (Tcb, Seq, Len);\r
- }\r
-\r
- ASSERT (TcpVerifySegment (Nbuf) != 0);\r
- return Nbuf;\r
-}\r
-\r
-\r
-/**\r
- Retransmit the segment from sequence Seq.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Seq The sequence number of the segment to be retransmitted.\r
-\r
- @retval 0 Retransmission succeeded.\r
- @retval -1 Error condition occurred.\r
-\r
-**/\r
-INTN\r
-TcpRetransmit (\r
- IN TCP_CB *Tcb,\r
- IN TCP_SEQNO Seq\r
- )\r
-{\r
- NET_BUF *Nbuf;\r
- UINT32 Len;\r
-\r
- //\r
- // Compute the maxium length of retransmission. It is\r
- // limited by three factors:\r
- // 1. Less than SndMss\r
- // 2. must in the current send window\r
- // 3. will not change the boundaries of queued segments.\r
- //\r
-\r
- //\r
- // Handle the Window Retraction if TCP window scale is enabled according to RFC7323:\r
- // On first retransmission, or if the sequence number is out of\r
- // window by less than 2^Rcv.Wind.Shift, then do normal\r
- // retransmission(s) without regard to the receiver window as long\r
- // as the original segment was in window when it was sent.\r
- //\r
- if ((Tcb->SndWndScale != 0) &&\r
- (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax) || TCP_SEQ_BETWEEN (Tcb->SndWl2 + Tcb->SndWnd, Seq, Tcb->SndWl2 + Tcb->SndWnd + (1 << Tcb->SndWndScale)))) {\r
- Len = TCP_SUB_SEQ (Tcb->SndNxt, Seq);\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "TcpRetransmit: retransmission without regard to the receiver window for TCB %p\n",\r
- Tcb)\r
- );\r
-\r
- } else if (TCP_SEQ_GEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq)) {\r
- Len = TCP_SUB_SEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq);\r
-\r
- } else {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "TcpRetransmit: retransmission cancelled because send window too small for TCB %p\n",\r
- Tcb)\r
- );\r
-\r
- return 0;\r
- }\r
-\r
- Len = MIN (Len, Tcb->SndMss);\r
-\r
- Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len);\r
- if (Nbuf == NULL) {\r
- return -1;\r
- }\r
-\r
- ASSERT (TcpVerifySegment (Nbuf) != 0);\r
-\r
- if (TcpTransmitSegment (Tcb, Nbuf) != 0) {\r
- goto OnError;\r
- }\r
-\r
- if (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax)) {\r
- Tcb->RetxmitSeqMax = Seq;\r
- }\r
-\r
- //\r
- // The retransmitted buffer may be on the SndQue,\r
- // trim TCP head because all the buffer on SndQue\r
- // are headless.\r
- //\r
- ASSERT (Nbuf->Tcp != NULL);\r
- NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);\r
- Nbuf->Tcp = NULL;\r
-\r
- NetbufFree (Nbuf);\r
- return 0;\r
-\r
-OnError:\r
- if (Nbuf != NULL) {\r
- NetbufFree (Nbuf);\r
- }\r
-\r
- return -1;\r
-}\r
-\r
-\r
-/**\r
- Check whether to send data/SYN/FIN and piggy back an ACK.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Force Whether to ignore the sender's SWS avoidance algorithm and send\r
- out data by force.\r
-\r
- @return The number of bytes sent.\r
-\r
-**/\r
-INTN\r
-TcpToSendData (\r
- IN OUT TCP_CB *Tcb,\r
- IN INTN Force\r
- )\r
-{\r
- UINT32 Len;\r
- INTN Sent;\r
- UINT8 Flag;\r
- NET_BUF *Nbuf;\r
- TCP_SEG *Seg;\r
- TCP_SEQNO Seq;\r
- TCP_SEQNO End;\r
-\r
- ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL) && (Tcb->State != TCP_LISTEN));\r
-\r
- Sent = 0;\r
-\r
- if ((Tcb->State == TCP_CLOSED) ||\r
- TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT)) {\r
-\r
- return 0;\r
- }\r
-\r
-SEND_AGAIN:\r
- //\r
- // compute how much data can be sent\r
- //\r
- Len = TcpDataToSend (Tcb, Force);\r
- Seq = Tcb->SndNxt;\r
-\r
- ASSERT ((Tcb->State) < (ARRAY_SIZE (mTcpOutFlag)));\r
- Flag = mTcpOutFlag[Tcb->State];\r
-\r
- if ((Flag & TCP_FLG_SYN) != 0) {\r
-\r
- Seq = Tcb->Iss;\r
- Len = 0;\r
- }\r
-\r
- //\r
- // only send a segment without data if SYN or\r
- // FIN is set.\r
- //\r
- if ((Len == 0) &&\r
- ((Flag & (TCP_FLG_SYN | TCP_FLG_FIN)) == 0)) {\r
- return Sent;\r
- }\r
-\r
- Nbuf = TcpGetSegment (Tcb, Seq, Len);\r
-\r
- if (Nbuf == NULL) {\r
- DEBUG (\r
- (EFI_D_ERROR,\r
- "TcpToSendData: failed to get a segment for TCB %p\n",\r
- Tcb)\r
- );\r
-\r
- goto OnError;\r
- }\r
-\r
- Seg = TCPSEG_NETBUF (Nbuf);\r
-\r
- //\r
- // Set the TcpSeg in Nbuf.\r
- //\r
- Len = Nbuf->TotalSize;\r
- End = Seq + Len;\r
- if (TCP_FLG_ON (Flag, TCP_FLG_SYN)) {\r
- End++;\r
- }\r
-\r
- if ((Flag & TCP_FLG_FIN) != 0) {\r
- //\r
- // Send FIN if all data is sent, and FIN is\r
- // in the window\r
- //\r
- if ((TcpGetMaxSndNxt (Tcb) == Tcb->SndNxt) &&\r
- (GET_SND_DATASIZE (Tcb->Sk) == 0) &&\r
- TCP_SEQ_LT (End + 1, Tcb->SndWnd + Tcb->SndWl2)) {\r
-\r
- DEBUG (\r
- (EFI_D_NET,\r
- "TcpToSendData: send FIN "\r
- "to peer for TCB %p in state %s\n",\r
- Tcb,\r
- mTcpStateName[Tcb->State])\r
- );\r
-\r
- End++;\r
- } else {\r
- TCP_CLEAR_FLG (Flag, TCP_FLG_FIN);\r
- }\r
- }\r
-\r
- Seg->Seq = Seq;\r
- Seg->End = End;\r
- Seg->Flag = Flag;\r
-\r
- ASSERT (TcpVerifySegment (Nbuf) != 0);\r
- ASSERT (TcpCheckSndQue (&Tcb->SndQue) != 0);\r
-\r
- //\r
- // don't send an empty segment here.\r
- //\r
- if (Seg->End == Seg->Seq) {\r
- DEBUG ((EFI_D_WARN, "TcpToSendData: created a empty"\r
- " segment for TCB %p, free it now\n", Tcb));\r
-\r
- NetbufFree (Nbuf);\r
- return Sent;\r
- }\r
-\r
- if (TcpTransmitSegment (Tcb, Nbuf) != 0) {\r
- NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);\r
- Nbuf->Tcp = NULL;\r
-\r
- if ((Flag & TCP_FLG_FIN) != 0) {\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT);\r
- }\r
-\r
- goto OnError;\r
- }\r
-\r
- Sent += TCP_SUB_SEQ (End, Seq);\r
-\r
- //\r
- // All the buffer in the SndQue is headless\r
- //\r
- ASSERT (Nbuf->Tcp != NULL);\r
-\r
- NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);\r
- Nbuf->Tcp = NULL;\r
-\r
- NetbufFree (Nbuf);\r
-\r
- //\r
- // update status in TCB\r
- //\r
- Tcb->DelayedAck = 0;\r
-\r
- if ((Flag & TCP_FLG_FIN) != 0) {\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT);\r
- }\r
-\r
- if (TCP_SEQ_GT (End, Tcb->SndNxt)) {\r
- Tcb->SndNxt = End;\r
- }\r
-\r
- if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT)) {\r
- TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);\r
- }\r
-\r
- //\r
- // Enable RTT measurement only if not in retransmit.\r
- // Karn's algorithm reqires not to update RTT when in loss.\r
- //\r
- if ((Tcb->CongestState == TCP_CONGEST_OPEN) &&\r
- !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {\r
-\r
- DEBUG ((EFI_D_NET, "TcpToSendData: set RTT measure "\r
- "sequence %d for TCB %p\n", Seq, Tcb));\r
-\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);\r
- Tcb->RttSeq = Seq;\r
- Tcb->RttMeasure = 0;\r
- }\r
-\r
- if (Len == Tcb->SndMss) {\r
- goto SEND_AGAIN;\r
- }\r
-\r
- return Sent;\r
-\r
-OnError:\r
- if (Nbuf != NULL) {\r
- NetbufFree (Nbuf);\r
- }\r
-\r
- return Sent;\r
-}\r
-\r
-\r
-/**\r
- Send an ACK immediately.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpSendAck (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- NET_BUF *Nbuf;\r
- TCP_SEG *Seg;\r
-\r
- Nbuf = NetbufAlloc (TCP_MAX_HEAD);\r
-\r
- if (Nbuf == NULL) {\r
- return;\r
- }\r
-\r
- NetbufReserve (Nbuf, TCP_MAX_HEAD);\r
-\r
- Seg = TCPSEG_NETBUF (Nbuf);\r
- Seg->Seq = Tcb->SndNxt;\r
- Seg->End = Tcb->SndNxt;\r
- Seg->Flag = TCP_FLG_ACK;\r
-\r
- if (TcpTransmitSegment (Tcb, Nbuf) == 0) {\r
- TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);\r
- Tcb->DelayedAck = 0;\r
- }\r
-\r
- NetbufFree (Nbuf);\r
-}\r
-\r
-\r
-/**\r
- Send a zero probe segment. It can be used by keepalive and zero window probe.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
- @retval 0 The zero probe segment was sent out successfully.\r
- @retval other Error condition occurred.\r
-\r
-**/\r
-INTN\r
-TcpSendZeroProbe (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- NET_BUF *Nbuf;\r
- TCP_SEG *Seg;\r
- INTN Result;\r
-\r
- Nbuf = NetbufAlloc (TCP_MAX_HEAD);\r
-\r
- if (Nbuf == NULL) {\r
- return -1;\r
- }\r
-\r
- NetbufReserve (Nbuf, TCP_MAX_HEAD);\r
-\r
- //\r
- // SndNxt-1 is out of window. The peer should respond\r
- // with an ACK.\r
- //\r
- Seg = TCPSEG_NETBUF (Nbuf);\r
- Seg->Seq = Tcb->SndNxt - 1;\r
- Seg->End = Tcb->SndNxt - 1;\r
- Seg->Flag = TCP_FLG_ACK;\r
-\r
- Result = TcpTransmitSegment (Tcb, Nbuf);\r
- NetbufFree (Nbuf);\r
-\r
- return Result;\r
-}\r
-\r
-\r
-/**\r
- Check whether to send an ACK or delayed ACK.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpToSendAck (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- UINT32 TcpNow;\r
-\r
- TcpNow = TcpRcvWinNow (Tcb);\r
- //\r
- // Generally, TCP should send a delayed ACK unless:\r
- // 1. ACK at least every other FULL sized segment received,\r
- // 2. Packets received out of order\r
- // 3. Receiving window is open\r
- //\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW) ||\r
- (Tcb->DelayedAck >= 1) ||\r
- (TcpNow > TcpRcvWinOld (Tcb))) {\r
- TcpSendAck (Tcb);\r
- return;\r
- }\r
-\r
- DEBUG ((EFI_D_NET, "TcpToSendAck: scheduled a delayed"\r
- " ACK for TCB %p\n", Tcb));\r
-\r
- //\r
- // schedule a delayed ACK\r
- //\r
- Tcb->DelayedAck++;\r
-}\r
-\r
-\r
-/**\r
- Send a RESET segment in response to the segment received.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance, may be NULL.\r
- @param Head TCP header of the segment that triggers the reset.\r
- @param Len Length of the segment that triggers the reset.\r
- @param Local Local IP address.\r
- @param Remote Remote peer's IP address.\r
-\r
- @retval 0 A reset is sent or no need to send it.\r
- @retval -1 No reset is sent.\r
-\r
-**/\r
-INTN\r
-TcpSendReset (\r
- IN TCP_CB *Tcb,\r
- IN TCP_HEAD *Head,\r
- IN INT32 Len,\r
- IN UINT32 Local,\r
- IN UINT32 Remote\r
- )\r
-{\r
- NET_BUF *Nbuf;\r
- TCP_HEAD *Nhead;\r
- UINT16 HeadSum;\r
-\r
- //\r
- // Don't respond to a Reset with reset\r
- //\r
- if ((Head->Flag & TCP_FLG_RST) != 0) {\r
- return 0;\r
- }\r
-\r
- Nbuf = NetbufAlloc (TCP_MAX_HEAD);\r
-\r
- if (Nbuf == NULL) {\r
- return -1;\r
- }\r
-\r
- Nhead = (TCP_HEAD *) NetbufAllocSpace (\r
- Nbuf,\r
- sizeof (TCP_HEAD),\r
- NET_BUF_TAIL\r
- );\r
-\r
- ASSERT (Nhead != NULL);\r
-\r
- Nbuf->Tcp = Nhead;\r
- Nhead->Flag = TCP_FLG_RST;\r
-\r
- //\r
- // Derive Seq/ACK from the segment if no TCB\r
- // associated with it, otherwise from the Tcb\r
- //\r
- if (Tcb == NULL) {\r
-\r
- if (TCP_FLG_ON (Head->Flag, TCP_FLG_ACK)) {\r
- Nhead->Seq = Head->Ack;\r
- Nhead->Ack = 0;\r
- } else {\r
- Nhead->Seq = 0;\r
- TCP_SET_FLG (Nhead->Flag, TCP_FLG_ACK);\r
- Nhead->Ack = HTONL (NTOHL (Head->Seq) + Len);\r
- }\r
- } else {\r
-\r
- Nhead->Seq = HTONL (Tcb->SndNxt);\r
- Nhead->Ack = HTONL (Tcb->RcvNxt);\r
- TCP_SET_FLG (Nhead->Flag, TCP_FLG_ACK);\r
- }\r
-\r
- Nhead->SrcPort = Head->DstPort;\r
- Nhead->DstPort = Head->SrcPort;\r
- Nhead->HeadLen = (UINT8) (sizeof (TCP_HEAD) >> 2);\r
- Nhead->Res = 0;\r
- Nhead->Wnd = HTONS (0xFFFF);\r
- Nhead->Checksum = 0;\r
- Nhead->Urg = 0;\r
-\r
- HeadSum = NetPseudoHeadChecksum (Local, Remote, 6, 0);\r
- Nhead->Checksum = TcpChecksum (Nbuf, HeadSum);\r
-\r
- TcpSendIpPacket (Tcb, Nbuf, Local, Remote);\r
-\r
- NetbufFree (Nbuf);\r
- return 0;\r
-}\r
-\r
-\r
-/**\r
- Verify that the segment is in good shape.\r
-\r
- @param Nbuf Buffer that contains the segment to be checked.\r
-\r
- @retval 0 The segment is broken.\r
- @retval 1 The segment is in good shape.\r
-\r
-**/\r
-INTN\r
-TcpVerifySegment (\r
- IN NET_BUF *Nbuf\r
- )\r
-{\r
- TCP_HEAD *Head;\r
- TCP_SEG *Seg;\r
- UINT32 Len;\r
-\r
- if (Nbuf == NULL) {\r
- return 1;\r
- }\r
-\r
- NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);\r
-\r
- Seg = TCPSEG_NETBUF (Nbuf);\r
- Len = Nbuf->TotalSize;\r
- Head = Nbuf->Tcp;\r
-\r
- if (Head != NULL) {\r
- if (Head->Flag != Seg->Flag) {\r
- return 0;\r
- }\r
-\r
- Len -= (Head->HeadLen << 2);\r
- }\r
-\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {\r
- Len++;\r
- }\r
-\r
- if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {\r
- Len++;\r
- }\r
-\r
- if (Seg->Seq + Len != Seg->End) {\r
- return 0;\r
- }\r
-\r
- return 1;\r
-}\r
-\r
-\r
-/**\r
- Verify that all the segments in SndQue are in good shape.\r
-\r
- @param Head Pointer to the head node of the SndQue.\r
-\r
- @retval 0 At least one segment is broken.\r
- @retval 1 All segments in the specific queue are in good shape.\r
-\r
-**/\r
-INTN\r
-TcpCheckSndQue (\r
- IN LIST_ENTRY *Head\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- NET_BUF *Nbuf;\r
- TCP_SEQNO Seq;\r
-\r
- if (IsListEmpty (Head)) {\r
- return 1;\r
- }\r
- //\r
- // Initialize the Seq\r
- //\r
- Entry = Head->ForwardLink;\r
- Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);\r
- Seq = TCPSEG_NETBUF (Nbuf)->Seq;\r
-\r
- NET_LIST_FOR_EACH (Entry, Head) {\r
- Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);\r
-\r
- if (TcpVerifySegment (Nbuf) == 0) {\r
- return 0;\r
- }\r
-\r
- //\r
- // All the node in the SndQue should has:\r
- // SEG.SEQ = LAST_SEG.END\r
- //\r
- if (Seq != TCPSEG_NETBUF (Nbuf)->Seq) {\r
- return 0;\r
- }\r
-\r
- Seq = TCPSEG_NETBUF (Nbuf)->End;\r
- }\r
-\r
- return 1;\r
-}\r
+++ /dev/null
-/** @file\r
- Tcp Protocol header file.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#ifndef _TCP4_PROTO_H_\r
-#define _TCP4_PROTO_H_\r
-\r
-typedef struct _TCP_CB TCP_CB;\r
-\r
-#include "Tcp4Driver.h"\r
-#include "Socket.h"\r
-#include "Tcp4Option.h"\r
-\r
-\r
-\r
-///\r
-/// Tcp states, Don't change their order, it is used as\r
-/// index to mTcpOutFlag and other macros\r
-///\r
-#define TCP_CLOSED 0\r
-#define TCP_LISTEN 1\r
-#define TCP_SYN_SENT 2\r
-#define TCP_SYN_RCVD 3\r
-#define TCP_ESTABLISHED 4\r
-#define TCP_FIN_WAIT_1 5\r
-#define TCP_FIN_WAIT_2 6\r
-#define TCP_CLOSING 7\r
-#define TCP_TIME_WAIT 8\r
-#define TCP_CLOSE_WAIT 9\r
-#define TCP_LAST_ACK 10\r
-\r
-\r
-///\r
-/// Flags in the TCP header\r
-///\r
-#define TCP_FLG_FIN 0x01\r
-#define TCP_FLG_SYN 0x02\r
-#define TCP_FLG_RST 0x04\r
-#define TCP_FLG_PSH 0x08\r
-#define TCP_FLG_ACK 0x10\r
-#define TCP_FLG_URG 0x20\r
-\r
- //\r
- // mask for all the flags\r
- //\r
-#define TCP_FLG_FLAG 0x3F\r
-\r
-\r
-#define TCP_CONNECT_REFUSED (-1) ///< TCP error status\r
-#define TCP_CONNECT_RESET (-2) ///< TCP error status\r
-#define TCP_CONNECT_CLOSED (-3) ///< TCP error status\r
-\r
-//\r
-// Current congestion status as suggested by RFC3782.\r
-//\r
-#define TCP_CONGEST_RECOVER 1 ///< During the NewReno fast recovery\r
-#define TCP_CONGEST_LOSS 2 ///< Retxmit because of retxmit time out\r
-#define TCP_CONGEST_OPEN 3 ///< TCP is opening its congestion window\r
-\r
-//\r
-// TCP control flags\r
-//\r
-#define TCP_CTRL_NO_NAGLE 0x0001 ///< Disable Nagle algorithm\r
-#define TCP_CTRL_NO_KEEPALIVE 0x0002 ///< Disable keepalive timer\r
-#define TCP_CTRL_NO_WS 0x0004 ///< Disable window scale option\r
-#define TCP_CTRL_RCVD_WS 0x0008 ///< Received a wnd scale option in syn\r
-#define TCP_CTRL_NO_TS 0x0010 ///< Disable Timestamp option\r
-#define TCP_CTRL_RCVD_TS 0x0020 ///< Received a Timestamp option in syn\r
-#define TCP_CTRL_SND_TS 0x0040 ///< Send Timestamp option to remote\r
-#define TCP_CTRL_SND_URG 0x0080 ///< In urgent send mode\r
-#define TCP_CTRL_RCVD_URG 0x0100 ///< In urgent receive mode\r
-#define TCP_CTRL_SND_PSH 0x0200 ///< In PUSH send mode\r
-#define TCP_CTRL_FIN_SENT 0x0400 ///< FIN is sent\r
-#define TCP_CTRL_FIN_ACKED 0x0800 ///< FIN is ACKed.\r
-#define TCP_CTRL_TIMER_ON 0x1000 ///< At least one of the timer is on\r
-#define TCP_CTRL_RTT_ON 0x2000 ///< The RTT measurement is on\r
-#define TCP_CTRL_ACK_NOW 0x4000 ///< Send the ACK now, don't delay\r
-\r
-//\r
-// Timer related values\r
-//\r
-#define TCP_TIMER_CONNECT 0 ///< Connection establishment timer\r
-#define TCP_TIMER_REXMIT 1 ///< Retransmit timer\r
-#define TCP_TIMER_PROBE 2 ///< Window probe timer\r
-#define TCP_TIMER_KEEPALIVE 3 ///< Keepalive timer\r
-#define TCP_TIMER_FINWAIT2 4 ///< FIN_WAIT_2 timer\r
-#define TCP_TIMER_2MSL 5 ///< TIME_WAIT tiemr\r
-#define TCP_TIMER_NUMBER 6 ///< The total number of TCP timer.\r
-#define TCP_TICK 200 ///< Every TCP tick is 200ms\r
-#define TCP_TICK_HZ 5 ///< The frequence of TCP tick\r
-#define TCP_RTT_SHIFT 3 ///< SRTT & RTTVAR scaled by 8\r
-#define TCP_RTO_MIN TCP_TICK_HZ ///< The minium value of RTO\r
-#define TCP_RTO_MAX (TCP_TICK_HZ * 60) ///< The maxium value of RTO\r
-#define TCP_FOLD_RTT 4 ///< Timeout threshod to fold RTT\r
-\r
-//\r
-// Default values for some timers\r
-//\r
-#define TCP_MAX_LOSS 12 ///< Default max times to retxmit\r
-#define TCP_KEEPALIVE_IDLE_MIN (TCP_TICK_HZ * 60 * 60 * 2) ///< First keep alive\r
-#define TCP_KEEPALIVE_PERIOD (TCP_TICK_HZ * 60)\r
-#define TCP_MAX_KEEPALIVE 8\r
-#define TCP_FIN_WAIT2_TIME (2 * TCP_TICK_HZ)\r
-#define TCP_TIME_WAIT_TIME (2 * TCP_TICK_HZ)\r
-#define TCP_PAWS_24DAY (24 * 24 * 60 * 60 * TCP_TICK_HZ)\r
-#define TCP_CONNECT_TIME (75 * TCP_TICK_HZ)\r
-\r
-//\r
-// The header space to be reserved before TCP data to accomodate :\r
-// 60byte IP head + 60byte TCP head + link layer head\r
-//\r
-#define TCP_MAX_HEAD 192\r
-\r
-//\r
-// Value ranges for some control option\r
-//\r
-#define TCP_RCV_BUF_SIZE (2 * 1024 * 1024)\r
-#define TCP_RCV_BUF_SIZE_MIN (8 * 1024)\r
-#define TCP_SND_BUF_SIZE (2 * 1024 * 1024)\r
-#define TCP_SND_BUF_SIZE_MIN (8 * 1024)\r
-#define TCP_BACKLOG 10\r
-#define TCP_BACKLOG_MIN 5\r
-#define TCP_MAX_LOSS_MIN 6\r
-#define TCP_CONNECT_TIME_MIN (60 * TCP_TICK_HZ)\r
-#define TCP_MAX_KEEPALIVE_MIN 4\r
-#define TCP_KEEPALIVE_IDLE_MAX (TCP_TICK_HZ * 60 * 60 * 4)\r
-#define TCP_KEEPALIVE_PERIOD_MIN (TCP_TICK_HZ * 30)\r
-#define TCP_FIN_WAIT2_TIME_MAX (4 * TCP_TICK_HZ)\r
-#define TCP_TIME_WAIT_TIME_MAX (60 * TCP_TICK_HZ)\r
-\r
-///\r
-/// TCP segmentation data\r
-///\r
-typedef struct _TCP_SEG {\r
- TCP_SEQNO Seq; ///< Starting sequence number\r
- TCP_SEQNO End; ///< The sequence of the last byte + 1, include SYN/FIN. End-Seq = SEG.LEN\r
- TCP_SEQNO Ack; ///< ACK field in the segment\r
- UINT8 Flag; ///< TCP header flags\r
- UINT16 Urg; ///< Valid if URG flag is set.\r
- UINT32 Wnd; ///< TCP window size field\r
-} TCP_SEG;\r
-\r
-///\r
-/// Network endpoint, IP+Port structure\r
-///\r
-typedef struct _TCP_PEER {\r
- UINT32 Ip; ///< IP address, network byte order\r
- TCP_PORTNO Port; ///< Port number, network byte order\r
-} TCP_PEER;\r
-\r
-///\r
-/// TCP control block, it includes various states\r
-///\r
-struct _TCP_CB {\r
- LIST_ENTRY List; ///< Back and forward link entry\r
- TCP_CB *Parent; ///< The parent TCP_CB structure\r
-\r
- SOCKET *Sk; ///< The socket it controled.\r
- TCP_PEER LocalEnd; ///< Local endpoint\r
- TCP_PEER RemoteEnd;///< Remote endpoint\r
-\r
- LIST_ENTRY SndQue; ///< Retxmission queue\r
- LIST_ENTRY RcvQue; ///< Reassemble queue\r
- UINT32 CtrlFlag; ///< Control flags, such as NO_NAGLE\r
- INT32 Error; ///< Soft error status, such as TCP_CONNECT_RESET\r
-\r
- //\r
- // RFC793 and RFC1122 defined variables\r
- //\r
- UINT8 State; ///< TCP state, such as SYN_SENT, LISTEN\r
- UINT8 DelayedAck; ///< Number of delayed ACKs\r
- UINT16 HeadSum; ///< Checksum of the fixed parts of pesudo\r
- ///< header: Src IP, Dst IP, 0, Protocol,\r
- ///< not include the TCP length.\r
-\r
- TCP_SEQNO Iss; ///< Initial Sending Sequence\r
- TCP_SEQNO SndUna; ///< First unacknowledged data\r
- TCP_SEQNO SndNxt; ///< Next data sequence to send.\r
- TCP_SEQNO SndPsh; ///< Send PUSH point\r
- TCP_SEQNO SndUp; ///< Send urgent point\r
- UINT32 SndWnd; ///< Window advertised by the remote peer\r
- UINT32 SndWndMax; ///< Max send window advertised by the peer\r
- TCP_SEQNO SndWl1; ///< Seq number used for last window update\r
- TCP_SEQNO SndWl2; ///< Ack no of last window update\r
- UINT16 SndMss; ///< Max send segment size\r
- TCP_SEQNO RcvNxt; ///< Next sequence no to receive\r
- UINT32 RcvWnd; ///< Window advertised by the local peer\r
- TCP_SEQNO RcvWl2; ///< The RcvNxt (or ACK) of last window update.\r
- ///< It is necessary because of delayed ACK\r
-\r
- TCP_SEQNO RcvUp; ///< Urgent point;\r
- TCP_SEQNO Irs; ///< Initial Receiving Sequence\r
- UINT16 RcvMss; ///< Max receive segment size\r
- UINT16 EnabledTimer; ///< Which timer is currently enabled\r
- UINT32 Timer[TCP_TIMER_NUMBER]; ///< When the timer will expire\r
- INT32 NextExpire; ///< Count down offset for the nearest timer\r
- UINT32 Idle; ///< How long the connection is in idle\r
- UINT32 ProbeTime; ///< The time out value for current window prober\r
- BOOLEAN ProbeTimerOn;///< If TRUE, the probe time is on.\r
-\r
- //\r
- // RFC1323 defined variables, about window scale,\r
- // timestamp and PAWS\r
- //\r
- UINT8 SndWndScale; ///< Wndscale received from the peer\r
- UINT8 RcvWndScale; ///< Wndscale used to scale local buffer\r
- UINT32 TsRecent; ///< TsRecent to echo to the remote peer\r
- UINT32 TsRecentAge; ///< When this TsRecent is updated\r
-\r
- //\r
- // RFC2988 defined variables. about RTT measurement\r
- //\r
- TCP_SEQNO RttSeq; ///< The seq of measured segment now\r
- UINT32 RttMeasure; ///< Currently measured RTT in heart beats\r
- UINT32 SRtt; ///< Smoothed RTT, scaled by 8\r
- UINT32 RttVar; ///< RTT variance, scaled by 8\r
- UINT32 Rto; ///< Current RTO, not scaled\r
-\r
- //\r
- // RFC2581, and 3782 variables.\r
- // Congestion control + NewReno fast recovery.\r
- //\r
- UINT32 CWnd; ///< Sender's congestion window\r
- UINT32 Ssthresh; ///< Slow start threshold.\r
- TCP_SEQNO Recover; ///< Recover point for NewReno\r
- UINT16 DupAck; ///< Number of duplicate ACKs\r
- UINT8 CongestState; ///< The current congestion state(RFC3782)\r
- UINT8 LossTimes; ///< Number of retxmit timeouts in a row\r
- TCP_SEQNO LossRecover; ///< Recover point for retxmit\r
-\r
- //\r
- // configuration parameters, for EFI_TCP4_PROTOCOL specification\r
- //\r
- UINT32 KeepAliveIdle; ///< Idle time before sending first probe\r
- UINT32 KeepAlivePeriod; ///< Interval for subsequent keep alive probe\r
- UINT8 MaxKeepAlive; ///< Maxium keep alive probe times.\r
- UINT8 KeepAliveProbes; ///< The number of keep alive probe.\r
- UINT16 MaxRexmit; ///< The maxium number of retxmit before abort\r
- UINT32 FinWait2Timeout; ///< The FIN_WAIT_2 time out\r
- UINT32 TimeWaitTimeout; ///< The TIME_WAIT time out\r
- UINT32 ConnectTimeout; ///< The connect establishment time out\r
-\r
- //\r
- // RFC7323\r
- // Addressing Window Retraction for TCP Window Scale Option.\r
- //\r
- TCP_SEQNO RetxmitSeqMax; ///< Max Seq number in previous retransmission.\r
-\r
- //\r
- // configuration for tcp provided by user\r
- //\r
- BOOLEAN UseDefaultAddr;\r
- UINT8 Tos;\r
- UINT8 Ttl;\r
- EFI_IPv4_ADDRESS SubnetMask;\r
-\r
- IP_IO_IP_INFO *IpInfo; ///<pointer reference to Ip used to send pkt\r
-};\r
-\r
-extern LIST_ENTRY mTcpRunQue;\r
-extern LIST_ENTRY mTcpListenQue;\r
-extern TCP_SEQNO mTcpGlobalIss;\r
-extern UINT32 mTcpTick;\r
-\r
-///\r
-/// TCP_CONNECTED: both ends have synchronized their ISN.\r
-///\r
-#define TCP_CONNECTED(state) ((state) > TCP_SYN_RCVD)\r
-\r
-#define TCP_FIN_RCVD(State) \\r
- (((State) == TCP_CLOSE_WAIT) || \\r
- ((State) == TCP_LAST_ACK) || \\r
- ((State) == TCP_CLOSING) || \\r
- ((State) == TCP_TIME_WAIT))\r
-\r
-#define TCP_LOCAL_CLOSED(State) \\r
- (((State) == TCP_FIN_WAIT_1) || \\r
- ((State) == TCP_FIN_WAIT_2) || \\r
- ((State) == TCP_CLOSING) || \\r
- ((State) == TCP_TIME_WAIT) || \\r
- ((State) == TCP_LAST_ACK))\r
-\r
-//\r
-// Get the TCP_SEG point from a net buffer's ProtoData\r
-//\r
-#define TCPSEG_NETBUF(NBuf) ((TCP_SEG *) ((NBuf)->ProtoData))\r
-\r
-//\r
-// macros to compare sequence no\r
-//\r
-#define TCP_SEQ_LT(SeqA, SeqB) ((INT32) ((SeqA) - (SeqB)) < 0)\r
-#define TCP_SEQ_LEQ(SeqA, SeqB) ((INT32) ((SeqA) - (SeqB)) <= 0)\r
-#define TCP_SEQ_GT(SeqA, SeqB) ((INT32) ((SeqB) - (SeqA)) < 0)\r
-#define TCP_SEQ_GEQ(SeqA, SeqB) ((INT32) ((SeqB) - (SeqA)) <= 0)\r
-\r
-//\r
-// TCP_SEQ_BETWEEN return whether b <= m <= e\r
-//\r
-#define TCP_SEQ_BETWEEN(b, m, e) ((e) - (b) >= (m) - (b))\r
-\r
-//\r
-// TCP_SUB_SEQ returns Seq1 - Seq2. Make sure Seq1 >= Seq2\r
-//\r
-#define TCP_SUB_SEQ(Seq1, Seq2) ((UINT32) ((Seq1) - (Seq2)))\r
-\r
-//\r
-// Check whether Flag is on\r
-//\r
-#define TCP_FLG_ON(Value, Flag) ((BOOLEAN) (((Value) & (Flag)) != 0))\r
-\r
-//\r
-// Set and Clear operation on a Flag\r
-//\r
-#define TCP_SET_FLG(Value, Flag) ((Value) |= (Flag))\r
-#define TCP_CLEAR_FLG(Value, Flag) ((Value) &= ~(Flag))\r
-\r
-//\r
-// Test whether two peers are equal\r
-//\r
-#define TCP_PEER_EQUAL(Pa, Pb) \\r
- (((Pa)->Ip == (Pb)->Ip) && ((Pa)->Port == (Pb)->Port))\r
-\r
-//\r
-// Test whether Pa matches Pb, or Pa is more specific\r
-// than pb. Zero means wildcard.\r
-//\r
-#define TCP_PEER_MATCH(Pa, Pb) \\r
- ((((Pb)->Ip == 0) || ((Pb)->Ip == (Pa)->Ip)) && \\r
- (((Pb)->Port == 0) || ((Pb)->Port == (Pa)->Port)))\r
-\r
-#define TCP_TIMER_ON(Flag, Timer) ((Flag) & (1 << (Timer)))\r
-#define TCP_SET_TIMER(Flag, Timer) ((Flag) = (UINT16) ((Flag) | (1 << (Timer))))\r
-#define TCP_CLEAR_TIMER(Flag, Timer) ((Flag) = (UINT16) ((Flag) & (~(1 << (Timer)))))\r
-\r
-#define TCP_TIME_LT(Ta, Tb) ((INT32) ((Ta) - (Tb)) < 0)\r
-#define TCP_TIME_LEQ(Ta, Tb) ((INT32) ((Ta) - (Tb)) <= 0)\r
-#define TCP_SUB_TIME(Ta, Tb) ((UINT32) ((Ta) - (Tb)))\r
-\r
-#define TCP_MAX_WIN 0xFFFFU\r
-\r
-typedef\r
-VOID\r
-(*TCP_TIMER_HANDLER) (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-#endif\r
+++ /dev/null
-/** @file\r
- TCP timer related functions.\r
-\r
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php<BR>\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Tcp4Main.h"\r
-\r
-UINT32 mTcpTick = 1000;\r
-\r
-/**\r
- Connect timeout handler.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpConnectTimeout (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Timeout handler for TCP retransmission timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpRexmitTimeout (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Timeout handler for window probe timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpProbeTimeout (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Timeout handler for keepalive timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpKeepaliveTimeout (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Timeout handler for FIN_WAIT_2 timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpFinwait2Timeout (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-/**\r
- Timeout handler for 2MSL timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-Tcp2MSLTimeout (\r
- IN OUT TCP_CB *Tcb\r
- );\r
-\r
-TCP_TIMER_HANDLER mTcpTimerHandler[TCP_TIMER_NUMBER] = {\r
- TcpConnectTimeout,\r
- TcpRexmitTimeout,\r
- TcpProbeTimeout,\r
- TcpKeepaliveTimeout,\r
- TcpFinwait2Timeout,\r
- Tcp2MSLTimeout,\r
-};\r
-\r
-/**\r
- Close the TCP connection.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpClose (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- NetbufFreeList (&Tcb->SndQue);\r
- NetbufFreeList (&Tcb->RcvQue);\r
-\r
- TcpSetState (Tcb, TCP_CLOSED);\r
-}\r
-\r
-\r
-/**\r
- Connect timeout handler.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpConnectTimeout (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- if (!TCP_CONNECTED (Tcb->State)) {\r
- DEBUG ((EFI_D_ERROR, "TcpConnectTimeout: connection closed "\r
- "because conenction timer timeout for TCB %p\n", Tcb));\r
-\r
- if (EFI_ABORTED == Tcb->Sk->SockError) {\r
- SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);\r
- }\r
-\r
- if (TCP_SYN_RCVD == Tcb->State) {\r
- DEBUG ((EFI_D_WARN, "TcpConnectTimeout: send reset because "\r
- "connection timer timeout for TCB %p\n", Tcb));\r
-\r
- TcpResetConnection (Tcb);\r
-\r
- }\r
-\r
- TcpClose (Tcb);\r
- }\r
-}\r
-\r
-\r
-/**\r
- Timeout handler for TCP retransmission timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpRexmitTimeout (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- UINT32 FlightSize;\r
-\r
- DEBUG ((EFI_D_WARN, "TcpRexmitTimeout: transmission "\r
- "timeout for TCB %p\n", Tcb));\r
-\r
- //\r
- // Set the congestion window. FlightSize is the\r
- // amount of data that has been sent but not\r
- // yet ACKed.\r
- //\r
- FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);\r
- Tcb->Ssthresh = MAX ((UINT32) (2 * Tcb->SndMss), FlightSize / 2);\r
-\r
- Tcb->CWnd = Tcb->SndMss;\r
- Tcb->LossRecover = Tcb->SndNxt;\r
-\r
- Tcb->LossTimes++;\r
- if ((Tcb->LossTimes > Tcb->MaxRexmit) &&\r
- !TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_CONNECT)) {\r
-\r
- DEBUG ((EFI_D_ERROR, "TcpRexmitTimeout: connection closed "\r
- "because too many timeouts for TCB %p\n", Tcb));\r
-\r
- if (EFI_ABORTED == Tcb->Sk->SockError) {\r
- SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);\r
- }\r
-\r
- TcpClose (Tcb);\r
- return ;\r
- }\r
-\r
- TcpBackoffRto (Tcb);\r
- TcpRetransmit (Tcb, Tcb->SndUna);\r
- TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);\r
-\r
- Tcb->CongestState = TCP_CONGEST_LOSS;\r
- TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);\r
-}\r
-\r
-\r
-/**\r
- Timeout handler for window probe timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpProbeTimeout (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- //\r
- // This is the timer for sender's SWSA. RFC1122 requires\r
- // a timer set for sender's SWSA, and suggest combine it\r
- // with window probe timer. If data is sent, don't set\r
- // the probe timer, since retransmit timer is on.\r
- //\r
- if ((TcpDataToSend (Tcb, 1) != 0) && (TcpToSendData (Tcb, 1) > 0)) {\r
-\r
- ASSERT (TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT) != 0);\r
- Tcb->ProbeTimerOn = FALSE;\r
- return ;\r
- }\r
-\r
- TcpSendZeroProbe (Tcb);\r
- TcpSetProbeTimer (Tcb);\r
-}\r
-\r
-\r
-/**\r
- Timeout handler for keepalive timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpKeepaliveTimeout (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- Tcb->KeepAliveProbes++;\r
-\r
- //\r
- // Too many Keep-alive probes, drop the connection\r
- //\r
- if (Tcb->KeepAliveProbes > Tcb->MaxKeepAlive) {\r
-\r
- if (EFI_ABORTED == Tcb->Sk->SockError) {\r
- SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);\r
- }\r
-\r
- TcpClose (Tcb);\r
- return ;\r
- }\r
-\r
- TcpSendZeroProbe (Tcb);\r
- TcpSetKeepaliveTimer (Tcb);\r
-}\r
-\r
-\r
-/**\r
- Timeout handler for FIN_WAIT_2 timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpFinwait2Timeout (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- DEBUG ((EFI_D_WARN, "TcpFinwait2Timeout: connection closed "\r
- "because FIN_WAIT2 timer timeouts for TCB %p\n", Tcb));\r
-\r
- TcpClose (Tcb);\r
-}\r
-\r
-\r
-/**\r
- Timeout handler for 2MSL timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-Tcp2MSLTimeout (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- DEBUG ((EFI_D_WARN, "Tcp2MSLTimeout: connection closed "\r
- "because TIME_WAIT timer timeouts for TCB %p\n", Tcb));\r
-\r
- TcpClose (Tcb);\r
-}\r
-\r
-\r
-/**\r
- Update the timer status and the next expire time according to the timers\r
- to expire in a specific future time slot.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpUpdateTimer (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- UINT16 Index;\r
-\r
- //\r
- // Don't use a too large value to init NextExpire\r
- // since mTcpTick wraps around as sequence no does.\r
- //\r
- Tcb->NextExpire = 65535;\r
- TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON);\r
-\r
- for (Index = 0; Index < TCP_TIMER_NUMBER; Index++) {\r
-\r
- if (TCP_TIMER_ON (Tcb->EnabledTimer, Index) &&\r
- TCP_TIME_LT (Tcb->Timer[Index], mTcpTick + Tcb->NextExpire)) {\r
-\r
- Tcb->NextExpire = TCP_SUB_TIME (Tcb->Timer[Index], mTcpTick);\r
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON);\r
- }\r
- }\r
-}\r
-\r
-\r
-/**\r
- Enable a TCP timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Timer The index of the timer to be enabled.\r
- @param TimeOut The timeout value of this timer.\r
-\r
-**/\r
-VOID\r
-TcpSetTimer (\r
- IN OUT TCP_CB *Tcb,\r
- IN UINT16 Timer,\r
- IN UINT32 TimeOut\r
- )\r
-{\r
- TCP_SET_TIMER (Tcb->EnabledTimer, Timer);\r
- Tcb->Timer[Timer] = mTcpTick + TimeOut;\r
-\r
- TcpUpdateTimer (Tcb);\r
-}\r
-\r
-\r
-/**\r
- Clear one TCP timer.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
- @param Timer The index of the timer to be cleared.\r
-\r
-**/\r
-VOID\r
-TcpClearTimer (\r
- IN OUT TCP_CB *Tcb,\r
- IN UINT16 Timer\r
- )\r
-{\r
- TCP_CLEAR_TIMER (Tcb->EnabledTimer, Timer);\r
- TcpUpdateTimer (Tcb);\r
-}\r
-\r
-\r
-/**\r
- Clear all TCP timers.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpClearAllTimer (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- Tcb->EnabledTimer = 0;\r
- TcpUpdateTimer (Tcb);\r
-}\r
-\r
-\r
-/**\r
- Enable the window prober timer and set the timeout value.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpSetProbeTimer (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- if (!Tcb->ProbeTimerOn) {\r
- Tcb->ProbeTime = Tcb->Rto;\r
- Tcb->ProbeTimerOn = TRUE;\r
-\r
- } else {\r
- Tcb->ProbeTime <<= 1;\r
- }\r
-\r
- if (Tcb->ProbeTime < TCP_RTO_MIN) {\r
-\r
- Tcb->ProbeTime = TCP_RTO_MIN;\r
- } else if (Tcb->ProbeTime > TCP_RTO_MAX) {\r
-\r
- Tcb->ProbeTime = TCP_RTO_MAX;\r
- }\r
-\r
- TcpSetTimer (Tcb, TCP_TIMER_PROBE, Tcb->ProbeTime);\r
-}\r
-\r
-\r
-/**\r
- Enable the keepalive timer and set the timeout value.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpSetKeepaliveTimer (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE)) {\r
- return ;\r
-\r
- }\r
-\r
- //\r
- // Set the timer to KeepAliveIdle if either\r
- // 1. the keepalive timer is off\r
- // 2. The keepalive timer is on, but the idle\r
- // is less than KeepAliveIdle, that means the\r
- // connection is alive since our last probe.\r
- //\r
- if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_KEEPALIVE) ||\r
- (Tcb->Idle < Tcb->KeepAliveIdle)) {\r
-\r
- TcpSetTimer (Tcb, TCP_TIMER_KEEPALIVE, Tcb->KeepAliveIdle);\r
- Tcb->KeepAliveProbes = 0;\r
-\r
- } else {\r
-\r
- TcpSetTimer (Tcb, TCP_TIMER_KEEPALIVE, Tcb->KeepAlivePeriod);\r
- }\r
-}\r
-\r
-\r
-/**\r
- Backoff the RTO.\r
-\r
- @param Tcb Pointer to the TCP_CB of this TCP instance.\r
-\r
-**/\r
-VOID\r
-TcpBackoffRto (\r
- IN OUT TCP_CB *Tcb\r
- )\r
-{\r
- //\r
- // Fold the RTT estimate if too many times, the estimate\r
- // may be wrong, fold it. So the next time a valid\r
- // measurement is sampled, we can start fresh.\r
- //\r
- if ((Tcb->LossTimes >= TCP_FOLD_RTT) && (Tcb->SRtt != 0)) {\r
- Tcb->RttVar += Tcb->SRtt >> 2;\r
- Tcb->SRtt = 0;\r
- }\r
-\r
- Tcb->Rto <<= 1;\r
-\r
- if (Tcb->Rto < TCP_RTO_MIN) {\r
-\r
- Tcb->Rto = TCP_RTO_MIN;\r
- } else if (Tcb->Rto > TCP_RTO_MAX) {\r
-\r
- Tcb->Rto = TCP_RTO_MAX;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Heart beat timer handler.\r
-\r
- @param Context Context of the timer event, ignored.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-TcpTickingDpc (\r
- IN VOID *Context\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- LIST_ENTRY *Next;\r
- TCP_CB *Tcb;\r
- INT16 Index;\r
-\r
- mTcpTick++;\r
- mTcpGlobalIss += 100;\r
-\r
- //\r
- // Don't use LIST_FOR_EACH, which isn't delete safe.\r
- //\r
- for (Entry = mTcpRunQue.ForwardLink; Entry != &mTcpRunQue; Entry = Next) {\r
-\r
- Next = Entry->ForwardLink;\r
-\r
- Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);\r
-\r
- if (Tcb->State == TCP_CLOSED) {\r
- continue;\r
- }\r
- //\r
- // The connection is doing RTT measurement.\r
- //\r
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {\r
- Tcb->RttMeasure++;\r
- }\r
-\r
- Tcb->Idle++;\r
-\r
- if (Tcb->DelayedAck != 0) {\r
- TcpSendAck (Tcb);\r
- }\r
-\r
- //\r
- // No timer is active or no timer expired\r
- //\r
- if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON) ||\r
- ((--Tcb->NextExpire) > 0)) {\r
-\r
- continue;\r
- }\r
-\r
- //\r
- // Call the timeout handler for each expired timer.\r
- //\r
- for (Index = 0; Index < TCP_TIMER_NUMBER; Index++) {\r
-\r
- if (TCP_TIMER_ON (Tcb->EnabledTimer, Index) &&\r
- TCP_TIME_LEQ (Tcb->Timer[Index], mTcpTick)) {\r
- //\r
- // disable the timer before calling the handler\r
- // in case the handler enables it again.\r
- //\r
- TCP_CLEAR_TIMER (Tcb->EnabledTimer, Index);\r
- mTcpTimerHandler[Index](Tcb);\r
-\r
- //\r
- // The Tcb may have been deleted by the timer, or\r
- // no other timer is set.\r
- //\r
- if ((Next->BackLink != Entry) ||\r
- (Tcb->EnabledTimer == 0)) {\r
- break;\r
- }\r
- }\r
- }\r
-\r
- //\r
- // If the Tcb still exist or some timer is set, update the timer\r
- //\r
- if (Index == TCP_TIMER_NUMBER) {\r
- TcpUpdateTimer (Tcb);\r
- }\r
- }\r
-}\r
-\r
-/**\r
- Heart beat timer handler, queues the DPC at TPL_CALLBACK.\r
-\r
- @param Event Timer event signaled, ignored.\r
- @param Context Context of the timer event, ignored.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-TcpTicking (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- QueueDpc (TPL_CALLBACK, TcpTickingDpc, Context);\r
-}\r
-\r