summaryrefslogtreecommitdiff
path: root/NetworkPkg/HttpDxe
diff options
context:
space:
mode:
authorZhang Lubo <lubo.zhang@intel.com>2015-11-09 03:30:42 +0000
committerluobozhang <luobozhang@Edk2>2015-11-09 03:30:42 +0000
commitb659408b933f40765960e877de3e1f8ceaab52cb (patch)
tree0a54cf99a62f599e230acdc7277fa3784fafa13f /NetworkPkg/HttpDxe
parentd1c275c651099c7f187885412b7751327b86ca38 (diff)
downloadedk2-platforms-b659408b933f40765960e877de3e1f8ceaab52cb.tar.xz
NetworkPkg:Enable Http Boot over Ipv6 stack
Add new features to support Http boot over ipv6 stack. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Zhang Lubo <lubo.zhang@intel.com> Reviewed-by: Fu Siyuan <siyuan.fu@intel.com> Reviewed-by: Ye Ting <ting.ye@intel.com> Reviewed-by: Wu Jiaxin <jiaxin.wu@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18743 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'NetworkPkg/HttpDxe')
-rw-r--r--NetworkPkg/HttpDxe/HttpDns.c207
-rw-r--r--NetworkPkg/HttpDxe/HttpDns.h20
-rw-r--r--NetworkPkg/HttpDxe/HttpDriver.c806
-rw-r--r--NetworkPkg/HttpDxe/HttpDriver.h143
-rw-r--r--NetworkPkg/HttpDxe/HttpDxe.inf5
-rw-r--r--NetworkPkg/HttpDxe/HttpDxe.unibin1822 -> 1854 bytes
-rw-r--r--NetworkPkg/HttpDxe/HttpImpl.c374
-rw-r--r--NetworkPkg/HttpDxe/HttpProto.c1253
-rw-r--r--NetworkPkg/HttpDxe/HttpProto.h193
9 files changed, 2312 insertions, 689 deletions
diff --git a/NetworkPkg/HttpDxe/HttpDns.c b/NetworkPkg/HttpDxe/HttpDns.c
index daebc173b5..0f5fe18072 100644
--- a/NetworkPkg/HttpDxe/HttpDns.c
+++ b/NetworkPkg/HttpDxe/HttpDns.c
@@ -194,11 +194,11 @@ Exit:
Dns4->Configure (Dns4, NULL);
gBS->CloseProtocol (
- Dns4Handle,
- &gEfiDns4ProtocolGuid,
- Service->ImageHandle,
- Service->ControllerHandle
- );
+ Dns4Handle,
+ &gEfiDns4ProtocolGuid,
+ Service->ImageHandle,
+ Service->ControllerHandle
+ );
}
if (Dns4Handle != NULL) {
@@ -216,3 +216,200 @@ Exit:
return Status;
}
+
+/**
+ Retrieve the host address using the EFI_DNS6_PROTOCOL.
+
+ @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.
+ @param[in] HostName Pointer to buffer containing hostname.
+ @param[out] IpAddress On output, pointer to buffer containing IPv6 address.
+
+ @retval EFI_SUCCESS Operation succeeded.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
+ @retval EFI_DEVICE_ERROR An unexpected network error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpDns6 (
+ IN HTTP_PROTOCOL *HttpInstance,
+ IN CHAR16 *HostName,
+ OUT EFI_IPv6_ADDRESS *IpAddress
+ )
+{
+ EFI_STATUS Status;
+ HTTP_SERVICE *Service;
+ EFI_DNS6_PROTOCOL *Dns6;
+ EFI_DNS6_CONFIG_DATA Dns6ConfigData;
+ EFI_DNS6_COMPLETION_TOKEN Token;
+ EFI_HANDLE Dns6Handle;
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
+ EFI_IPv6_ADDRESS *DnsServerList;
+ UINTN DnsServerListCount;
+ UINTN DataSize;
+ BOOLEAN IsDone;
+
+
+ Service = HttpInstance->Service;
+ ASSERT (Service != NULL);
+
+ DnsServerList = NULL;
+ DnsServerListCount = 0;
+ Dns6 = NULL;
+ Dns6Handle = NULL;
+ ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));
+
+ //
+ // Get DNS server list from EFI IPv6 Configuration protocol.
+ //
+ Status = gBS->HandleProtocol (Service->ControllerHandle, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Get the required size.
+ //
+ DataSize = 0;
+ Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ DnsServerList = AllocatePool (DataSize);
+ if (DnsServerList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);
+ if (EFI_ERROR (Status)) {
+ FreePool (DnsServerList);
+ DnsServerList = NULL;
+ } else {
+ DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
+ }
+ }
+ }
+
+ //
+ // Create a DNSv6 child instance and get the protocol.
+ //
+ Status = NetLibCreateServiceChild (
+ Service->ControllerHandle,
+ Service->ImageHandle,
+ &gEfiDns6ServiceBindingProtocolGuid,
+ &Dns6Handle
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Status = gBS->OpenProtocol (
+ Dns6Handle,
+ &gEfiDns6ProtocolGuid,
+ (VOID **) &Dns6,
+ Service->ImageHandle,
+ Service->ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Configure DNS6 instance for the DNS server address and protocol.
+ //
+ ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));
+ Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;
+ Dns6ConfigData.DnsServerList = DnsServerList;
+ Dns6ConfigData.EnableDnsCache = TRUE;
+ Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;
+ IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp, &HttpInstance->Ipv6Node.LocalAddress);
+ Status = Dns6->Configure (
+ Dns6,
+ &Dns6ConfigData
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Token.Status = EFI_NOT_READY;
+ IsDone = FALSE;
+ //
+ // Create event to set the IsDone flag when name resolution is finished.
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpCommonNotify,
+ &IsDone,
+ &Token.Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Start asynchronous name resolution.
+ //
+ Status = Dns6->HostNameToIp (Dns6, HostName, &Token);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ while (!IsDone) {
+ Dns6->Poll (Dns6);
+ }
+
+ //
+ // Name resolution is done, check result.
+ //
+ Status = Token.Status;
+ if (!EFI_ERROR (Status)) {
+ if (Token.RspData.H2AData == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ //
+ // We just return the first IPv6 address from DNS protocol.
+ //
+ IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
+ Status = EFI_SUCCESS;
+ }
+
+Exit:
+
+ if (Token.Event != NULL) {
+ gBS->CloseEvent (Token.Event);
+ }
+ if (Token.RspData.H2AData != NULL) {
+ if (Token.RspData.H2AData->IpList != NULL) {
+ FreePool (Token.RspData.H2AData->IpList);
+ }
+ FreePool (Token.RspData.H2AData);
+ }
+
+ if (Dns6 != NULL) {
+ Dns6->Configure (Dns6, NULL);
+
+ gBS->CloseProtocol (
+ Dns6Handle,
+ &gEfiDns6ProtocolGuid,
+ Service->ImageHandle,
+ Service->ControllerHandle
+ );
+ }
+
+ if (Dns6Handle != NULL) {
+ NetLibDestroyServiceChild (
+ Service->ControllerHandle,
+ Service->ImageHandle,
+ &gEfiDns6ServiceBindingProtocolGuid,
+ Dns6Handle
+ );
+ }
+
+ if (DnsServerList != NULL) {
+ FreePool (DnsServerList);
+ }
+
+ return Status;
+}
diff --git a/NetworkPkg/HttpDxe/HttpDns.h b/NetworkPkg/HttpDxe/HttpDns.h
index 0fb418635c..fa0c8f4a99 100644
--- a/NetworkPkg/HttpDxe/HttpDns.h
+++ b/NetworkPkg/HttpDxe/HttpDns.h
@@ -35,4 +35,24 @@ HttpDns4 (
OUT EFI_IPv4_ADDRESS *IpAddress
);
+/**
+ Retrieve the host address using the EFI_DNS6_PROTOCOL.
+
+ @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.
+ @param[in] HostName Pointer to buffer containing hostname.
+ @param[out] IpAddress On output, pointer to buffer containing IPv6 address.
+
+ @retval EFI_SUCCESS Operation succeeded.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
+ @retval EFI_DEVICE_ERROR An unexpected network error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpDns6 (
+ IN HTTP_PROTOCOL *HttpInstance,
+ IN CHAR16 *HostName,
+ OUT EFI_IPv6_ADDRESS *IpAddress
+ );
+
#endif \ No newline at end of file
diff --git a/NetworkPkg/HttpDxe/HttpDriver.c b/NetworkPkg/HttpDxe/HttpDriver.c
index bd1d04e78c..2518f4e707 100644
--- a/NetworkPkg/HttpDxe/HttpDriver.c
+++ b/NetworkPkg/HttpDxe/HttpDriver.c
@@ -20,15 +20,25 @@ EFI_HTTP_UTILITIES_PROTOCOL *mHttpUtilities = NULL;
///
/// Driver Binding Protocol instance
///
-EFI_DRIVER_BINDING_PROTOCOL gHttpDxeDriverBinding = {
- HttpDxeDriverBindingSupported,
- HttpDxeDriverBindingStart,
- HttpDxeDriverBindingStop,
+EFI_DRIVER_BINDING_PROTOCOL gHttpDxeIp4DriverBinding = {
+ HttpDxeIp4DriverBindingSupported,
+ HttpDxeIp4DriverBindingStart,
+ HttpDxeIp4DriverBindingStop,
HTTP_DRIVER_VERSION,
NULL,
NULL
};
+EFI_DRIVER_BINDING_PROTOCOL gHttpDxeIp6DriverBinding = {
+ HttpDxeIp6DriverBindingSupported,
+ HttpDxeIp6DriverBindingStart,
+ HttpDxeIp6DriverBindingStop,
+ HTTP_DRIVER_VERSION,
+ NULL,
+ NULL
+};
+
+
/**
Create a HTTP driver service binding private instance.
@@ -73,33 +83,59 @@ HttpCreateService (
/**
Release all the resource used the HTTP service binding instance.
- @param HttpService The HTTP private instance.
-
+ @param[in] HttpService The HTTP private instance.
+ @param[in] UsingIpv6 Indicate use TCP4 protocol or TCP6 protocol.
+ if TRUE, use Tcp6 protocol.
+ if FALSE, use Tcp4 protocl.
**/
VOID
HttpCleanService (
- IN HTTP_SERVICE *HttpService
+ IN HTTP_SERVICE *HttpService,
+ IN BOOLEAN UsingIpv6
)
-{
+{
+
if (HttpService == NULL) {
return ;
}
-
- if (HttpService->TcpChildHandle != NULL) {
- gBS->CloseProtocol (
- HttpService->TcpChildHandle,
- &gEfiTcp4ProtocolGuid,
- HttpService->ImageHandle,
- HttpService->ControllerHandle
- );
-
- NetLibDestroyServiceChild (
- HttpService->ControllerHandle,
- HttpService->ImageHandle,
- &gEfiTcp4ServiceBindingProtocolGuid,
- HttpService->TcpChildHandle
- );
+ if (!UsingIpv6) {
+ if (HttpService->Tcp4ChildHandle != NULL) {
+ gBS->CloseProtocol (
+ HttpService->Tcp4ChildHandle,
+ &gEfiTcp4ProtocolGuid,
+ HttpService->ImageHandle,
+ HttpService->ControllerHandle
+ );
+
+ NetLibDestroyServiceChild (
+ HttpService->ControllerHandle,
+ HttpService->ImageHandle,
+ &gEfiTcp4ServiceBindingProtocolGuid,
+ HttpService->Tcp4ChildHandle
+ );
+
+ HttpService->Tcp4ChildHandle = NULL;
+ }
+ } else {
+ if (HttpService->Tcp6ChildHandle != NULL) {
+ gBS->CloseProtocol (
+ HttpService->Tcp6ChildHandle,
+ &gEfiTcp6ProtocolGuid,
+ HttpService->ImageHandle,
+ HttpService->ControllerHandle
+ );
+
+ NetLibDestroyServiceChild (
+ HttpService->ControllerHandle,
+ HttpService->ImageHandle,
+ &gEfiTcp6ServiceBindingProtocolGuid,
+ HttpService->Tcp6ChildHandle
+ );
+
+ HttpService->Tcp6ChildHandle = NULL;
+ }
}
+
}
/**
@@ -107,7 +143,7 @@ HttpCleanService (
in the system.
@param[in] Event Not used.
- @param[in] Context The pointer to the IP4 config2 instance data.
+ @param[in] Context The pointer to the IP4 config2 instance data or IP6 Config instance data.
**/
VOID
@@ -122,7 +158,7 @@ HttpUtilitiesInstalledCallback (
NULL,
(VOID **) &mHttpUtilities
);
-
+
//
// Close the event if Http utilities protocol is loacted.
//
@@ -150,6 +186,7 @@ HttpDxeDriverEntryPoint (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
+ EFI_STATUS Status;
VOID *Registration;
gBS->LocateProtocol (
@@ -174,14 +211,39 @@ HttpDxeDriverEntryPoint (
//
// Install UEFI Driver Model protocol(s).
//
- return EfiLibInstallDriverBindingComponentName2 (
- ImageHandle,
- SystemTable,
- &gHttpDxeDriverBinding,
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gHttpDxeIp4DriverBinding,
+ ImageHandle,
+ &gHttpDxeComponentName,
+ &gHttpDxeComponentName2
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gHttpDxeIp6DriverBinding,
+ NULL,
+ &gHttpDxeComponentName,
+ &gHttpDxeComponentName2
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gHttpDxeIp4DriverBinding,
+ &gEfiComponentName2ProtocolGuid,
+ &gHttpDxeComponentName2,
+ &gEfiComponentNameProtocolGuid,
&gHttpDxeComponentName,
- &gHttpDxeComponentName2
+ NULL
);
+ }
+ return Status;
}
/**
@@ -224,6 +286,309 @@ HttpDestroyChildEntryInHandleBuffer (
}
/**
+ Test to see if this driver supports ControllerHandle. This is the worker function for
+ HttpDxeIp4(6)DriverBindingSupported.
+
+ @param[in] This The pointer to the driver binding protocol.
+ @param[in] ControllerHandle The handle of device to be tested.
+ @param[in] RemainingDevicePath Optional parameter used to pick a specific child
+ device to be started.
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpDxeSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
+ IN UINT8 IpVersion
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID *TcpServiceBindingProtocolGuid;
+
+ if (IpVersion == IP_VERSION_4) {
+ TcpServiceBindingProtocolGuid = &gEfiTcp4ServiceBindingProtocolGuid;
+ } else {
+ TcpServiceBindingProtocolGuid = &gEfiTcp6ServiceBindingProtocolGuid;
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ TcpServiceBindingProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Start this driver on ControllerHandle. This is the worker function for
+ HttpDxeIp4(6)DriverBindingStart.
+
+ @param[in] This The pointer to the driver binding protocol.
+ @param[in] ControllerHandle The handle of device to be started.
+ @param[in] RemainingDevicePath Optional parameter used to pick a specific child
+ device to be started.
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
+
+
+ @retval EFI_SUCCESS This driver is installed to ControllerHandle.
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpDxeStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
+ IN UINT8 IpVersion
+ )
+{
+ EFI_STATUS Status;
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ HTTP_SERVICE *HttpService;
+ VOID *Interface;
+ BOOLEAN UsingIpv6;
+
+ UsingIpv6 = FALSE;
+
+ //
+ // Test for the Http service binding protocol
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ (VOID **) &ServiceBinding,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ HttpService = HTTP_SERVICE_FROM_PROTOCOL (ServiceBinding);
+ } else {
+ Status = HttpCreateService (ControllerHandle, This->DriverBindingHandle, &HttpService);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ASSERT (HttpService != NULL);
+
+ //
+ // Install the HttpServiceBinding Protocol onto Controller
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ControllerHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ &HttpService->ServiceBinding,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ }
+
+ if (IpVersion == IP_VERSION_4) {
+
+ if (HttpService->Tcp4ChildHandle == NULL) {
+ //
+ // Create a TCP4 child instance, but do not configure it. This will establish the parent-child relationship.
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ This->DriverBindingHandle,
+ &gEfiTcp4ServiceBindingProtocolGuid,
+ &HttpService->Tcp4ChildHandle
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Status = gBS->OpenProtocol (
+ HttpService->Tcp4ChildHandle,
+ &gEfiTcp4ProtocolGuid,
+ &Interface,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ } else {
+ return EFI_ALREADY_STARTED;
+ }
+
+ } else {
+ UsingIpv6 = TRUE;
+
+ if (HttpService->Tcp6ChildHandle == NULL) {
+ //
+ // Create a TCP6 child instance, but do not configure it. This will establish the parent-child relationship.
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ This->DriverBindingHandle,
+ &gEfiTcp6ServiceBindingProtocolGuid,
+ &HttpService->Tcp6ChildHandle
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Status = gBS->OpenProtocol (
+ HttpService->Tcp6ChildHandle,
+ &gEfiTcp6ProtocolGuid,
+ &Interface,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ } else {
+ return EFI_ALREADY_STARTED;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+
+ if (HttpService != NULL) {
+ HttpCleanService (HttpService, UsingIpv6);
+ if (HttpService->Tcp4ChildHandle == NULL && HttpService->Tcp6ChildHandle == NULL) {
+ FreePool (HttpService);
+ }
+ }
+
+ return Status;
+
+
+}
+
+/**
+ Stop this driver on ControllerHandle. This is the worker function for
+ HttpDxeIp4(6)DriverBindingStop.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] ControllerHandle Handle of device to stop driver on.
+ @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
+ children is zero stop the entire bus driver.
+ @param[in] ChildHandleBuffer List of Child Handles to Stop.
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
+
+ @retval EFI_SUCCESS This driver was removed ControllerHandle.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval Others This driver was not removed from this device
+
+**/
+EFI_STATUS
+EFIAPI
+HttpDxeStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer,
+ IN UINT8 IpVersion
+ )
+{
+ EFI_HANDLE NicHandle;
+ EFI_STATUS Status;
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ HTTP_SERVICE *HttpService;
+ LIST_ENTRY *List;
+ HTTP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
+ BOOLEAN UsingIpv6;
+
+ //
+ // HTTP driver opens TCP4(6) child, So, Controller is a TCP4(6)
+ // child handle. Locate the Nic handle first. Then get the
+ // HTTP private data back.
+ //
+ if (IpVersion == IP_VERSION_4) {
+ UsingIpv6 = FALSE;
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiTcp4ProtocolGuid);
+ } else {
+ UsingIpv6 = TRUE;
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiTcp6ProtocolGuid);
+ }
+
+ if (NicHandle == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = gBS->OpenProtocol (
+ NicHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ (VOID **) &ServiceBinding,
+ This->DriverBindingHandle,
+ NicHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ HttpService = HTTP_SERVICE_FROM_PROTOCOL (ServiceBinding);
+
+ if (NumberOfChildren != 0) {
+ //
+ // Destroy the HTTP child instance in ChildHandleBuffer.
+ //
+ List = &HttpService->ChildrenList;
+ Context.ServiceBinding = ServiceBinding;
+ Context.NumberOfChildren = NumberOfChildren;
+ Context.ChildHandleBuffer = ChildHandleBuffer;
+ Status = NetDestroyLinkList (
+ List,
+ HttpDestroyChildEntryInHandleBuffer,
+ &Context,
+ NULL
+ );
+ } else {
+
+ HttpCleanService (HttpService, UsingIpv6);
+
+ if (HttpService->Tcp4ChildHandle == NULL && HttpService->Tcp6ChildHandle == NULL) {
+ gBS->UninstallProtocolInterface (
+ NicHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ ServiceBinding
+ );
+ FreePool (HttpService);
+ }
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ return Status;
+
+}
+
+/**
Tests to see if this driver supports a given controller. If a child device is provided,
it further tests to see if this driver supports creating a handle for the specified child device.
@@ -267,41 +632,18 @@ HttpDestroyChildEntryInHandleBuffer (
**/
EFI_STATUS
EFIAPI
-HttpDxeDriverBindingSupported (
+HttpDxeIp4DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
- EFI_STATUS Status;
-
- //
- // Test for the HttpServiceBinding protocol.
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiHttpServiceBindingProtocolGuid,
- NULL,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- return EFI_ALREADY_STARTED;
- }
-
- //
- // Test for the Tcp4 Protocol
- //
- return gBS->OpenProtocol (
- ControllerHandle,
- &gEfiTcp4ServiceBindingProtocolGuid,
- NULL,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
-
+ return HttpDxeSupported (
+ This,
+ ControllerHandle,
+ RemainingDevicePath,
+ IP_VERSION_4
+ );
}
/**
@@ -342,90 +684,173 @@ HttpDxeDriverBindingSupported (
**/
EFI_STATUS
EFIAPI
-HttpDxeDriverBindingStart (
+HttpDxeIp4DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
- EFI_STATUS Status;
- HTTP_SERVICE *HttpService;
- VOID *Interface;
+ return HttpDxeStart (
+ This,
+ ControllerHandle,
+ RemainingDevicePath,
+ IP_VERSION_4
+ );
+}
+
+/**
+ Stops a device controller or a bus controller.
- //
- // Test for the Http service binding protocol
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiHttpServiceBindingProtocolGuid,
- NULL,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
- if (Status == EFI_SUCCESS) {
- return EFI_ALREADY_STARTED;
- }
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
- Status = HttpCreateService (ControllerHandle, This->DriverBindingHandle, &HttpService);
- if (EFI_ERROR (Status)) {
- return Status;
- }
+**/
+EFI_STATUS
+EFIAPI
+HttpDxeIp4DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ return HttpDxeStop (
+ This,
+ ControllerHandle,
+ NumberOfChildren,
+ ChildHandleBuffer,
+ IP_VERSION_4
+ );
+}
- ASSERT (HttpService != NULL);
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
- //
- // Create a TCP child instance, but do not configure it. This will establish the parent-child relationship.
- //
- Status = NetLibCreateServiceChild (
- ControllerHandle,
- This->DriverBindingHandle,
- &gEfiTcp4ServiceBindingProtocolGuid,
- &HttpService->TcpChildHandle
- );
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
- Status = gBS->OpenProtocol (
- HttpService->TcpChildHandle,
- &gEfiTcp4ProtocolGuid,
- &Interface,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
-
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+HttpDxeIp6DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ return HttpDxeSupported (
+ This,
+ ControllerHandle,
+ RemainingDevicePath,
+ IP_VERSION_6
+ );
- //
- // Install the HttpServiceBinding Protocol onto Controller
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &ControllerHandle,
- &gEfiHttpServiceBindingProtocolGuid,
- &HttpService->ServiceBinding,
- NULL
- );
+}
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
+/**
+ Starts a device controller or a bus controller.
- return EFI_SUCCESS;
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
-ON_ERROR:
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
- if (HttpService != NULL) {
- HttpCleanService (HttpService);
- FreePool (HttpService);
- }
-
- return Status;
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_ALREADY_STARTED This device is already running on ControllerHandle.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpDxeIp6DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ return HttpDxeStart (
+ This,
+ ControllerHandle,
+ RemainingDevicePath,
+ IP_VERSION_6
+ );
}
/**
@@ -456,78 +881,21 @@ ON_ERROR:
**/
EFI_STATUS
EFIAPI
-HttpDxeDriverBindingStop (
+HttpDxeIp6DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
)
{
- EFI_HANDLE NicHandle;
- EFI_STATUS Status;
- EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
- HTTP_SERVICE *HttpService;
- LIST_ENTRY *List;
- HTTP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
-
- //
- // HTTP driver opens TCP child, So, Controller is a TCP
- // child handle. Locate the Nic handle first. Then get the
- // HTTP private data back.
- //
- NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiTcp4ProtocolGuid);
- if (NicHandle == NULL) {
- return EFI_SUCCESS;
- }
-
- Status = gBS->OpenProtocol (
- NicHandle,
- &gEfiHttpServiceBindingProtocolGuid,
- (VOID **) &ServiceBinding,
- This->DriverBindingHandle,
- NicHandle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
-
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- HttpService = HTTP_SERVICE_FROM_PROTOCOL (ServiceBinding);
-
- if (!IsListEmpty (&HttpService->ChildrenList)) {
- //
- // Destroy the HTTP child instance in ChildHandleBuffer.
- //
- List = &HttpService->ChildrenList;
- Context.ServiceBinding = ServiceBinding;
- Context.NumberOfChildren = NumberOfChildren;
- Context.ChildHandleBuffer = ChildHandleBuffer;
- Status = NetDestroyLinkList (
- List,
- HttpDestroyChildEntryInHandleBuffer,
- &Context,
- NULL
- );
- }
-
- if (NumberOfChildren == 0 && IsListEmpty (&HttpService->ChildrenList)) {
- gBS->UninstallProtocolInterface (
- NicHandle,
- &gEfiHttpServiceBindingProtocolGuid,
- ServiceBinding
+ return HttpDxeStop (
+ This,
+ ControllerHandle,
+ NumberOfChildren,
+ ChildHandleBuffer,
+ IP_VERSION_6
);
-
- HttpCleanService (HttpService);
-
- FreePool (HttpService);
-
- Status = EFI_SUCCESS;
- }
-
- return Status;
}
-
/**
Creates a child handle and installs a protocol.
@@ -557,7 +925,6 @@ HttpServiceBindingCreateChild (
HTTP_SERVICE *HttpService;
HTTP_PROTOCOL *HttpInstance;
EFI_STATUS Status;
- VOID *Interface;
EFI_TPL OldTpl;
if ((This == NULL) || (ChildHandle == NULL)) {
@@ -569,6 +936,12 @@ HttpServiceBindingCreateChild (
if (HttpInstance == NULL) {
return EFI_OUT_OF_RESOURCES;
}
+
+ HttpInstance->Signature = HTTP_PROTOCOL_SIGNATURE;
+ HttpInstance->Service = HttpService;
+ CopyMem (&HttpInstance->Http, &mEfiHttpTemplate, sizeof (HttpInstance->Http));
+ NetMapInit (&HttpInstance->TxTokens);
+ NetMapInit (&HttpInstance->RxTokens);
//
// Install HTTP protocol onto ChildHandle
@@ -584,27 +957,7 @@ HttpServiceBindingCreateChild (
goto ON_ERROR;
}
- HttpInstance->Handle = *ChildHandle;
-
- Status = HttpInitProtocol (HttpService, HttpInstance);
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
-
- //
- // Open the default Tcp4 protocol by child.
- //
- Status = gBS->OpenProtocol (
- HttpService->TcpChildHandle,
- &gEfiTcp4ProtocolGuid,
- (VOID **) &Interface,
- gHttpDxeDriverBinding.DriverBindingHandle,
- HttpInstance->Handle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
+ HttpInstance->Handle = *ChildHandle;
//
// Add it to the HTTP service's child list.
@@ -619,8 +972,9 @@ HttpServiceBindingCreateChild (
return EFI_SUCCESS;
ON_ERROR:
-
- HttpCleanProtocol (HttpInstance);
+
+ NetMapClean (&HttpInstance->TxTokens);
+ NetMapClean (&HttpInstance->RxTokens);
FreePool (HttpInstance);
return Status;
@@ -664,8 +1018,8 @@ HttpServiceBindingDestroyChild (
ChildHandle,
&gEfiHttpProtocolGuid,
(VOID **) &Http,
- gHttpDxeDriverBinding.DriverBindingHandle,
- ChildHandle,
+ NULL,
+ NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
@@ -681,16 +1035,6 @@ HttpServiceBindingDestroyChild (
return EFI_SUCCESS;
}
- //
- // Close the Tcp4 protocol.
- //
- gBS->CloseProtocol (
- HttpService->TcpChildHandle,
- &gEfiTcp4ProtocolGuid,
- gHttpDxeDriverBinding.DriverBindingHandle,
- ChildHandle
- );
-
HttpInstance->InDestroy = TRUE;
//
@@ -706,11 +1050,11 @@ HttpServiceBindingDestroyChild (
HttpInstance->InDestroy = FALSE;
return Status;
}
-
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
-
+
HttpCleanProtocol (HttpInstance);
-
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
RemoveEntryList (&HttpInstance->Link);
HttpService->ChildrenNumber--;
diff --git a/NetworkPkg/HttpDxe/HttpDriver.h b/NetworkPkg/HttpDxe/HttpDriver.h
index eea8d5169e..8fda6b2be4 100644
--- a/NetworkPkg/HttpDxe/HttpDriver.h
+++ b/NetworkPkg/HttpDxe/HttpDriver.h
@@ -43,8 +43,12 @@
//
#include <Protocol/HttpUtilities.h>
#include <Protocol/Tcp4.h>
+#include <Protocol/Tcp6.h>
#include <Protocol/Dns4.h>
+#include <Protocol/Dns6.h>
#include <Protocol/Ip4Config2.h>
+#include <Protocol/Ip6Config.h>
+
//
// Produced Protocols
@@ -59,7 +63,9 @@
//
// Protocol instances
//
-extern EFI_DRIVER_BINDING_PROTOCOL gHttpDxeDriverBinding;
+extern EFI_DRIVER_BINDING_PROTOCOL gHttpDxeIp4DriverBinding;
+extern EFI_DRIVER_BINDING_PROTOCOL gHttpDxeIp6DriverBinding;
+
extern EFI_COMPONENT_NAME2_PROTOCOL gHttpDxeComponentName2;
extern EFI_COMPONENT_NAME_PROTOCOL gHttpDxeComponentName;
@@ -123,7 +129,7 @@ typedef struct {
**/
EFI_STATUS
EFIAPI
-HttpDxeDriverBindingSupported (
+HttpDxeIp4DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
@@ -166,7 +172,7 @@ HttpDxeDriverBindingSupported (
**/
EFI_STATUS
EFIAPI
-HttpDxeDriverBindingStart (
+HttpDxeIp4DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
@@ -200,7 +206,7 @@ HttpDxeDriverBindingStart (
**/
EFI_STATUS
EFIAPI
-HttpDxeDriverBindingStop (
+HttpDxeIp4DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
@@ -208,6 +214,135 @@ HttpDxeDriverBindingStop (
);
/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+HttpDxeIp6DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_ALREADY_STARTED This device is already running on ControllerHandle.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpDxeIp6DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+HttpDxeIp6DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ );
+
+/**
Creates a child handle and installs a protocol.
The CreateChild() function installs a protocol on ChildHandle.
diff --git a/NetworkPkg/HttpDxe/HttpDxe.inf b/NetworkPkg/HttpDxe/HttpDxe.inf
index 0d3bd00cf7..bf2cbee5f7 100644
--- a/NetworkPkg/HttpDxe/HttpDxe.inf
+++ b/NetworkPkg/HttpDxe/HttpDxe.inf
@@ -56,9 +56,14 @@
gEfiHttpUtilitiesProtocolGuid ## CONSUMES
gEfiTcp4ServiceBindingProtocolGuid ## TO_START
gEfiTcp4ProtocolGuid ## TO_START
+ gEfiTcp6ServiceBindingProtocolGuid ## TO_START
+ gEfiTcp6ProtocolGuid ## TO_START
gEfiDns4ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES
gEfiDns4ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiDns6ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiDns6ProtocolGuid ## SOMETIMES_CONSUMES
gEfiIp4Config2ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiIp6ConfigProtocolGuid ## SOMETIMES_CONSUMES
[UserExtensions.TianoCore."ExtraFiles"]
HttpDxeExtra.uni \ No newline at end of file
diff --git a/NetworkPkg/HttpDxe/HttpDxe.uni b/NetworkPkg/HttpDxe/HttpDxe.uni
index f9c2ac812e..d6792dd41e 100644
--- a/NetworkPkg/HttpDxe/HttpDxe.uni
+++ b/NetworkPkg/HttpDxe/HttpDxe.uni
Binary files differ
diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c
index f1e3e53411..c527da0872 100644
--- a/NetworkPkg/HttpDxe/HttpImpl.c
+++ b/NetworkPkg/HttpDxe/HttpImpl.c
@@ -51,6 +51,8 @@ EfiHttpGetModeData (
)
{
HTTP_PROTOCOL *HttpInstance;
+ EFI_HTTPv4_ACCESS_POINT *Http4AccessPoint;
+ EFI_HTTPv6_ACCESS_POINT *Http6AccessPoint;
if ((This == NULL) || (HttpConfigData == NULL)) {
return EFI_INVALID_PARAMETER;
@@ -58,24 +60,32 @@ EfiHttpGetModeData (
HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
ASSERT (HttpInstance != NULL);
-
+
if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {
return EFI_NOT_STARTED;
}
- if (HttpConfigData->AccessPoint.IPv4Node == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
HttpConfigData->HttpVersion = HttpInstance->HttpVersion;
HttpConfigData->TimeOutMillisec = HttpInstance->TimeOutMillisec;
HttpConfigData->LocalAddressIsIPv6 = HttpInstance->LocalAddressIsIPv6;
- CopyMem (
- HttpConfigData->AccessPoint.IPv4Node,
- &HttpInstance->IPv4Node,
- sizeof (HttpInstance->IPv4Node)
+ if (HttpInstance->LocalAddressIsIPv6) {
+ Http6AccessPoint = AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT));
+ CopyMem (
+ Http6AccessPoint,
+ &HttpInstance->Ipv6Node,
+ sizeof (HttpInstance->Ipv6Node)
);
+ HttpConfigData->AccessPoint.IPv6Node = Http6AccessPoint;
+ } else {
+ Http4AccessPoint = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT));
+ CopyMem (
+ Http4AccessPoint,
+ &HttpInstance->IPv4Node,
+ sizeof (HttpInstance->IPv4Node)
+ );
+ HttpConfigData->AccessPoint.IPv4Node = Http4AccessPoint;
+ }
return EFI_SUCCESS;
}
@@ -120,8 +130,13 @@ EfiHttpConfigure (
{
HTTP_PROTOCOL *HttpInstance;
EFI_STATUS Status;
-
- if (This == NULL) {
+
+ //
+ // Check input parameters.
+ //
+ if (This == NULL ||
+ (HttpConfigData != NULL && ((HttpConfigData->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv6Node == NULL) ||
+ (!HttpConfigData->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv4Node == NULL)))) {
return EFI_INVALID_PARAMETER;
}
@@ -129,18 +144,7 @@ EfiHttpConfigure (
ASSERT (HttpInstance != NULL && HttpInstance->Service != NULL);
if (HttpConfigData != NULL) {
- //
- // Check input parameters.
- //
- if (HttpConfigData->LocalAddressIsIPv6) {
- if (HttpConfigData->AccessPoint.IPv6Node == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- } else {
- if (HttpConfigData->AccessPoint.IPv4Node == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- }
+
//
// Now configure this HTTP instance.
//
@@ -151,33 +155,38 @@ EfiHttpConfigure (
HttpInstance->HttpVersion = HttpConfigData->HttpVersion;
HttpInstance->TimeOutMillisec = HttpConfigData->TimeOutMillisec;
HttpInstance->LocalAddressIsIPv6 = HttpConfigData->LocalAddressIsIPv6;
-
- if (HttpConfigData->LocalAddressIsIPv6) {
- return EFI_UNSUPPORTED;
+
+ if (HttpConfigData->LocalAddressIsIPv6) {
+ CopyMem (
+ &HttpInstance->Ipv6Node,
+ HttpConfigData->AccessPoint.IPv6Node,
+ sizeof (HttpInstance->Ipv6Node)
+ );
} else {
CopyMem (
&HttpInstance->IPv4Node,
HttpConfigData->AccessPoint.IPv4Node,
sizeof (HttpInstance->IPv4Node)
);
-
- HttpInstance->State = HTTP_STATE_HTTP_CONFIGED;
- return EFI_SUCCESS;
}
+ //
+ // Creat Tcp child
+ //
+ Status = HttpInitProtocol (HttpInstance, HttpInstance->LocalAddressIsIPv6);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ HttpInstance->State = HTTP_STATE_HTTP_CONFIGED;
+ return EFI_SUCCESS;
} else {
- if (HttpInstance->LocalAddressIsIPv6) {
- return EFI_UNSUPPORTED;
- } else {
- HttpCleanProtocol (HttpInstance);
- Status = HttpInitProtocol (HttpInstance->Service, HttpInstance);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- HttpInstance->State = HTTP_STATE_UNCONFIGED;
- return EFI_SUCCESS;
- }
+ //
+ // Reset all the resources related to HttpInsance.
+ //
+ HttpCleanProtocol (HttpInstance);
+ HttpInstance->State = HTTP_STATE_UNCONFIGED;
+ return EFI_SUCCESS;
}
}
@@ -264,10 +273,6 @@ EfiHttpRequest (
return EFI_NOT_STARTED;
}
- if (HttpInstance->LocalAddressIsIPv6) {
- return EFI_UNSUPPORTED;
- }
-
//
// Check whether the token already existed.
//
@@ -291,7 +296,8 @@ EfiHttpRequest (
}
FreePool (HttpInstance->Url);
HttpInstance->Url = Url;
- }
+ }
+
UnicodeStrToAsciiStr (Request->Url, Url);
UrlParser = NULL;
@@ -340,7 +346,7 @@ EfiHttpRequest (
Wrap->HttpToken = Token;
Wrap->HttpInstance = HttpInstance;
- Status = HttpCreateTcp4TxEvent (Wrap);
+ Status = HttpCreateTcpTxEvent (Wrap);
if (EFI_ERROR (Status)) {
goto Error1;
}
@@ -379,24 +385,35 @@ EfiHttpRequest (
if (Configure) {
//
- // Parse Url for IPv4 address, if failed, perform DNS resolution.
+ // Parse Url for IPv4 or IPv6 address, if failed, perform DNS resolution.
//
- Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);
+ if (!HttpInstance->LocalAddressIsIPv6) {
+ Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);
+ } else {
+ Status = NetLibAsciiStrToIp6 (HostName, &HttpInstance->RemoteIpv6Addr);
+ }
+
if (EFI_ERROR (Status)) {
- HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (UINT16));
+ HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (CHAR16));
if (HostNameStr == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error1;
}
-
+
AsciiStrToUnicodeStr (HostName, HostNameStr);
- Status = HttpDns4 (HttpInstance, HostNameStr, &HttpInstance->RemoteAddr);
+ if (!HttpInstance->LocalAddressIsIPv6) {
+ Status = HttpDns4 (HttpInstance, HostNameStr, &HttpInstance->RemoteAddr);
+ } else {
+ Status = HttpDns6 (HttpInstance, HostNameStr, &HttpInstance->RemoteIpv6Addr);
+ }
+
FreePool (HostNameStr);
if (EFI_ERROR (Status)) {
goto Error1;
}
}
+
//
// Save the RemotePort and RemoteHost.
//
@@ -410,7 +427,7 @@ EfiHttpRequest (
//
// The request URL is different from previous calls to Request(), close existing TCP instance.
//
- ASSERT (HttpInstance->Tcp4 != NULL);
+ ASSERT (HttpInstance->Tcp4 != NULL &&HttpInstance->Tcp6 != NULL);
HttpCloseConnection (HttpInstance);
EfiHttpCancel (This, NULL);
}
@@ -429,25 +446,16 @@ EfiHttpRequest (
Wrap->TcpWrap.Method = Request->Method;
if (Configure) {
- //
- // Configure TCP instance.
- //
- Status = HttpConfigureTcp4 (HttpInstance, Wrap);
- if (EFI_ERROR (Status)) {
- goto Error1;
- }
- //
- // Connect TCP.
- //
- Status = HttpConnectTcp4 (HttpInstance);
+ Status = HttpInitTcp (HttpInstance, Wrap);
if (EFI_ERROR (Status)) {
goto Error2;
}
+
} else {
//
// For the new HTTP token, create TX TCP token events.
//
- Status = HttpCreateTcp4TxEvent (Wrap);
+ Status = HttpCreateTcpTxEvent (Wrap);
if (EFI_ERROR (Status)) {
goto Error1;
}
@@ -488,7 +496,7 @@ EfiHttpRequest (
//
// Transmit the request message.
//
- Status = HttpTransmitTcp4 (
+ Status = HttpTransmitTcp (
HttpInstance,
Wrap,
(UINT8*) RequestStr,
@@ -499,11 +507,11 @@ EfiHttpRequest (
}
DispatchDpc ();
-
+
if (HostName != NULL) {
FreePool (HostName);
}
-
+
return EFI_SUCCESS;
Error5:
@@ -517,15 +525,19 @@ Error4:
Error3:
HttpCloseConnection (HttpInstance);
-
Error2:
- HttpCloseTcp4ConnCloseEvent (HttpInstance);
- if (NULL != Wrap->TcpWrap.TxToken.CompletionToken.Event) {
- gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event);
- Wrap->TcpWrap.TxToken.CompletionToken.Event = NULL;
+ HttpCloseTcpConnCloseEvent (HttpInstance);
+ if (NULL != Wrap->TcpWrap.Tx4Token.CompletionToken.Event) {
+ gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);
+ Wrap->TcpWrap.Tx4Token.CompletionToken.Event = NULL;
+ }
+ if (NULL != Wrap->TcpWrap.Tx6Token.CompletionToken.Event) {
+ gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);
+ Wrap->TcpWrap.Tx6Token.CompletionToken.Event = NULL;
}
Error1:
+
if (HostName != NULL) {
FreePool (HostName);
}
@@ -541,7 +553,7 @@ Error1:
}
/**
- Cancel a TxToken or RxToken.
+ Cancel a user's Token.
@param[in] Map The HTTP instance's token queue.
@param[in] Item Object container for one HTTP token and token's wrap.
@@ -562,6 +574,7 @@ HttpCancelTokens (
EFI_HTTP_TOKEN *Token;
HTTP_TOKEN_WRAP *Wrap;
+ HTTP_PROTOCOL *HttpInstance;
Token = (EFI_HTTP_TOKEN *) Context;
@@ -575,24 +588,41 @@ HttpCancelTokens (
Wrap = (HTTP_TOKEN_WRAP *) Item->Value;
ASSERT (Wrap != NULL);
+ HttpInstance = Wrap->HttpInstance;
//
// Free resources.
//
NetMapRemoveItem (Map, Item, NULL);
- if (Wrap->TcpWrap.TxToken.CompletionToken.Event != NULL) {
- gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event);
- }
+ if (!HttpInstance->LocalAddressIsIPv6) {
+ if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);
+ }
+
+ if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);
+ }
+
+ if (Wrap->TcpWrap.Rx4Token.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
+ FreePool (Wrap->TcpWrap.Rx4Token.Packet.RxData->FragmentTable[0].FragmentBuffer);
+ }
- if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);
- }
+ } else {
+ if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);
+ }
+
+ if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);
+ }
- if (Wrap->TcpWrap.RxToken.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
- FreePool (Wrap->TcpWrap.RxToken.Packet.RxData->FragmentTable[0].FragmentBuffer);
+ if (Wrap->TcpWrap.Rx6Token.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
+ FreePool (Wrap->TcpWrap.Rx6Token.Packet.RxData->FragmentTable[0].FragmentBuffer);
+ }
}
+
FreePool (Wrap);
//
@@ -747,7 +777,7 @@ HttpBodyParserCallback (
Wrap->HttpInstance->NextMsg = Data;
//
- // Free TxToken since already received corrsponding HTTP response.
+ // Free Tx4Token or Tx6Token since already received corrsponding HTTP response.
//
FreePool (Wrap);
@@ -761,7 +791,7 @@ HttpBodyParserCallback (
@retval EFI_SUCCESS Allocation succeeded.
@retval EFI_OUT_OF_RESOURCES Failed to complete the opration due to lack of resources.
- @retval EFI_NOT_READY Can't find a corresponding TxToken or
+ @retval EFI_NOT_READY Can't find a corresponding Tx4Token/Tx6Token or
the EFI_HTTP_UTILITIES_PROTOCOL is not available.
**/
@@ -772,12 +802,9 @@ HttpResponseWorker (
{
EFI_STATUS Status;
EFI_HTTP_MESSAGE *HttpMsg;
- EFI_TCP4_IO_TOKEN *RxToken;
- EFI_TCP4_PROTOCOL *Tcp4;
CHAR8 *EndofHeader;
CHAR8 *HttpHeaders;
UINTN SizeofHeaders;
- CHAR8 *Buffer;
UINTN BufferSize;
UINTN StatusCode;
CHAR8 *Tmp;
@@ -796,23 +823,21 @@ HttpResponseWorker (
HttpInstance = Wrap->HttpInstance;
Token = Wrap->HttpToken;
-
HttpMsg = Token->Message;
- Tcp4 = HttpInstance->Tcp4;
- ASSERT (Tcp4 != NULL);
- HttpMsg->Headers = NULL;
- HttpHeaders = NULL;
- SizeofHeaders = 0;
- Buffer = NULL;
- BufferSize = 0;
- EndofHeader = NULL;
+ HttpInstance->EndofHeader = NULL;
+ HttpInstance->HttpHeaders = NULL;
+ HttpMsg->Headers = NULL;
+ HttpHeaders = NULL;
+ SizeofHeaders = 0;
+ BufferSize = 0;
+ EndofHeader = NULL;
if (HttpMsg->Data.Response != NULL) {
//
// Need receive the HTTP headers, prepare buffer.
//
- Status = HttpCreateTcp4RxEventForHeader (HttpInstance);
+ Status = HttpCreateTcpRxEventForHeader (HttpInstance);
if (EFI_ERROR (Status)) {
goto Error;
}
@@ -843,70 +868,15 @@ HttpResponseWorker (
// Check whether we cached the whole HTTP headers.
//
EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR);
- }
-
- RxToken = &HttpInstance->RxToken;
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);
- if (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- //
- // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
- //
- while (EndofHeader == NULL) {
- HttpInstance->IsRxDone = FALSE;
- RxToken->Packet.RxData->DataLength = DEF_BUF_LEN;
- RxToken->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;
- Status = Tcp4->Receive (Tcp4, RxToken);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));
- goto Error;
- }
-
- while (!HttpInstance->IsRxDone) {
- Tcp4->Poll (Tcp4);
- }
-
- Status = RxToken->CompletionToken.Status;
- if (EFI_ERROR (Status)) {
- goto Error;
- }
-
- //
- // Append the response string.
- //
- BufferSize = SizeofHeaders + RxToken->Packet.RxData->FragmentTable[0].FragmentLength;
- Buffer = AllocateZeroPool (BufferSize);
- if (Buffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
-
- if (HttpHeaders != NULL) {
- CopyMem (Buffer, HttpHeaders, SizeofHeaders);
- FreePool (HttpHeaders);
- }
-
- CopyMem (
- Buffer + SizeofHeaders,
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer,
- RxToken->Packet.RxData->FragmentTable[0].FragmentLength
- );
- HttpHeaders = Buffer;
- SizeofHeaders = BufferSize;
+ }
- //
- // Check whether we received end of HTTP headers.
- //
- EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR);
- };
+ HttpInstance->EndofHeader = &EndofHeader;
+ HttpInstance->HttpHeaders = &HttpHeaders;
- //
- // Skip the CRLF after the HTTP headers.
- //
- EndofHeader = EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);
+ Status = HttpTcpReceiveHeader (HttpInstance, &SizeofHeaders, &BufferSize);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
//
// Cache the part of body.
@@ -927,9 +897,6 @@ HttpResponseWorker (
HttpInstance->CacheLen = BodyLen;
}
- FreePool (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer);
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
-
//
// Search for Status Code.
//
@@ -997,7 +964,7 @@ HttpResponseWorker (
}
//
- // The first TxToken not transmitted yet, insert back and return error.
+ // The first Tx Token not transmitted yet, insert back and return error.
//
if (!ValueInItem->TcpWrap.IsTxDone) {
goto Error2;
@@ -1108,16 +1075,8 @@ HttpResponseWorker (
//
// We still need receive more data when there is no cache data and MsgParser is not NULL;
//
- RxToken = &Wrap->TcpWrap.RxToken;
-
- RxToken->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;
- RxToken->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;
-
- RxToken->CompletionToken.Status = EFI_NOT_READY;
- Status = Tcp4->Receive (Tcp4, RxToken);
+ Status = HttpTcpReceiveBody (Wrap, HttpMsg);
if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));
goto Error;
}
@@ -1130,18 +1089,7 @@ Exit:
}
Token->Status = Status;
gBS->SignalEvent (Token->Event);
-
- if (Wrap != NULL) {
- if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);
- }
- }
-
- if (HttpInstance->RxToken.CompletionToken.Event != NULL) {
- gBS->CloseEvent (HttpInstance->RxToken.CompletionToken.Event);
- HttpInstance->RxToken.CompletionToken.Event = NULL;
- }
-
+ HttpCloseTcpRxEvent (Wrap);
FreePool (Wrap);
return Status;
@@ -1149,28 +1097,7 @@ Error2:
NetMapInsertHead (&HttpInstance->TxTokens, ValueInItem->HttpToken, ValueInItem);
Error:
- if (Wrap != NULL) {
- if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);
- }
- RxToken = &Wrap->TcpWrap.RxToken;
- if (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
- FreePool (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer);
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
- }
- FreePool (Wrap);
- }
-
- if (HttpInstance->RxToken.CompletionToken.Event != NULL) {
- gBS->CloseEvent (HttpInstance->RxToken.CompletionToken.Event);
- HttpInstance->RxToken.CompletionToken.Event = NULL;
- }
-
- RxToken = &HttpInstance->RxToken;
- if (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
- FreePool (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer);
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
- }
+ HttpTcpTokenCleanup (Wrap);
if (HttpHeaders != NULL) {
FreePool (HttpHeaders);
@@ -1268,10 +1195,6 @@ EfiHttpResponse (
return EFI_NOT_STARTED;
}
- if (HttpInstance->LocalAddressIsIPv6) {
- return EFI_UNSUPPORTED;
- }
-
//
// Check whether the token already existed.
//
@@ -1287,7 +1210,7 @@ EfiHttpResponse (
Wrap->HttpInstance = HttpInstance;
Wrap->HttpToken = Token;
- Status = HttpCreateTcp4RxEvent (Wrap);
+ Status = HttpCreateTcpRxEvent (Wrap);
if (EFI_ERROR (Status)) {
goto Error;
}
@@ -1308,8 +1231,12 @@ EfiHttpResponse (
Error:
if (Wrap != NULL) {
- if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);
+ if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);
+ }
+
+ if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);
}
FreePool (Wrap);
}
@@ -1343,8 +1270,8 @@ EfiHttpPoll (
IN EFI_HTTP_PROTOCOL *This
)
{
- HTTP_PROTOCOL *HttpInstance;
EFI_STATUS Status;
+ HTTP_PROTOCOL *HttpInstance;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
@@ -1353,17 +1280,18 @@ EfiHttpPoll (
HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
ASSERT (HttpInstance != NULL);
- if (HttpInstance->LocalAddressIsIPv6) {
- return EFI_UNSUPPORTED;
- }
-
- if (HttpInstance->Tcp4 == NULL || HttpInstance->State != HTTP_STATE_TCP_CONNECTED) {
+ if (HttpInstance->State != HTTP_STATE_TCP_CONNECTED || (HttpInstance->Tcp4 == NULL &&
+ HttpInstance->Tcp6 == NULL)) {
return EFI_NOT_STARTED;
}
-
- Status = HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
-
+
+ if (HttpInstance->LocalAddressIsIPv6) {
+ Status = HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);
+ } else {
+ Status = HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
+ }
+
DispatchDpc ();
-
+
return Status;
}
diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c
index 57ea207389..39837a3c82 100644
--- a/NetworkPkg/HttpDxe/HttpProto.c
+++ b/NetworkPkg/HttpDxe/HttpProto.c
@@ -37,7 +37,7 @@ HttpCommonNotify (
}
/**
- The notify function associated with TxToken for Tcp4->Transmit().
+ The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().
@param[in] Context The context.
@@ -49,25 +49,46 @@ HttpTcpTransmitNotifyDpc (
)
{
HTTP_TOKEN_WRAP *Wrap;
+ HTTP_PROTOCOL *HttpInstance;
if (Context == NULL) {
return ;
}
+
+ Wrap = (HTTP_TOKEN_WRAP *) Context;
+ HttpInstance = Wrap->HttpInstance;
+
+ if (!HttpInstance->LocalAddressIsIPv6) {
+ Wrap->HttpToken->Status = Wrap->TcpWrap.Tx4Token.CompletionToken.Status;
+ gBS->SignalEvent (Wrap->HttpToken->Event);
+
+ //
+ // Free resources.
+ //
+ if (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {
+ FreePool (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer);
+ }
- Wrap = (HTTP_TOKEN_WRAP *) Context;
- Wrap->HttpToken->Status = Wrap->TcpWrap.TxToken.CompletionToken.Status;
- gBS->SignalEvent (Wrap->HttpToken->Event);
+ if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);
+ }
+
+ } else {
+ Wrap->HttpToken->Status = Wrap->TcpWrap.Tx6Token.CompletionToken.Status;
+ gBS->SignalEvent (Wrap->HttpToken->Event);
+
+ //
+ // Free resources.
+ //
+ if (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {
+ FreePool (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer);
+ }
- //
- // Free resources.
- //
- if (Wrap->TcpWrap.TxToken.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {
- FreePool (Wrap->TcpWrap.TxToken.Packet.TxData->FragmentTable[0].FragmentBuffer);
+ if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);
+ }
}
- if (Wrap->TcpWrap.TxToken.CompletionToken.Event != NULL) {
- gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event);
- }
Wrap->TcpWrap.IsTxDone = TRUE;
@@ -98,9 +119,8 @@ HttpTcpTransmitNotify (
QueueDpc (TPL_CALLBACK, HttpTcpTransmitNotifyDpc, Context);
}
-
/**
- The notify function associated with RxToken for Tcp4->Receive ().
+ The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().
@param[in] Context The context.
@@ -116,25 +136,41 @@ HttpTcpReceiveNotifyDpc (
UINTN Length;
EFI_STATUS Status;
HTTP_PROTOCOL *HttpInstance;
+ BOOLEAN UsingIpv6;
if (Context == NULL) {
return ;
}
Wrap = (HTTP_TOKEN_WRAP *) Context;
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);
- if (EFI_ERROR (Wrap->TcpWrap.RxToken.CompletionToken.Status)) {
- return ;
- }
-
HttpInstance = Wrap->HttpInstance;
+ UsingIpv6 = HttpInstance->LocalAddressIsIPv6;
+
+ if (UsingIpv6) {
+ gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);
+
+ if (EFI_ERROR (Wrap->TcpWrap.Rx6Token.CompletionToken.Status)) {
+ return ;
+ }
+
+ } else {
+ gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);
+
+ if (EFI_ERROR (Wrap->TcpWrap.Rx4Token.CompletionToken.Status)) {
+ return ;
+ }
+ }
//
// Check whether we receive a complete HTTP message.
//
ASSERT (HttpInstance->MsgParser != NULL);
+ if (UsingIpv6) {
+ Length = (UINTN) Wrap->TcpWrap.Rx6Data.FragmentTable[0].FragmentLength;
+ } else {
+ Length = (UINTN) Wrap->TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;
+ }
- Length = (UINTN) Wrap->TcpWrap.RxData.FragmentTable[0].FragmentLength;
Status = HttpParseMessageBody (
HttpInstance->MsgParser,
Length,
@@ -179,7 +215,12 @@ HttpTcpReceiveNotifyDpc (
Wrap->TcpWrap.IsRxDone = TRUE;
- Wrap->HttpToken->Status = Wrap->TcpWrap.RxToken.CompletionToken.Status;
+ if (UsingIpv6) {
+ Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;
+ } else {
+ Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;
+ }
+
gBS->SignalEvent (Wrap->HttpToken->Event);
@@ -211,9 +252,8 @@ HttpTcpReceiveNotify (
QueueDpc (TPL_CALLBACK, HttpTcpReceiveNotifyDpc, Context);
}
-
/**
- Create events for the TCP4 connection token and TCP4 close token.
+ Create events for the TCP connection token and TCP close token.
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
@@ -222,11 +262,13 @@ HttpTcpReceiveNotify (
**/
EFI_STATUS
-HttpCreateTcp4ConnCloseEvent (
+HttpCreateTcpConnCloseEvent (
IN HTTP_PROTOCOL *HttpInstance
)
{
EFI_STATUS Status;
+
+ if (!HttpInstance->LocalAddressIsIPv6) {
//
// Create events for variuos asynchronous operations.
//
@@ -234,66 +276,109 @@ HttpCreateTcp4ConnCloseEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
HttpCommonNotify,
- &HttpInstance->IsConnDone,
- &HttpInstance->ConnToken.CompletionToken.Event
+ &HttpInstance->IsTcp4ConnDone,
+ &HttpInstance->Tcp4ConnToken.CompletionToken.Event
);
if (EFI_ERROR (Status)) {
goto ERROR;
}
//
- // Initialize CloseToken
+ // Initialize Tcp4CloseToken
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpCommonNotify,
+ &HttpInstance->IsTcp4CloseDone,
+ &HttpInstance->Tcp4CloseToken.CompletionToken.Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR;
+ }
+
+ } else {
+ //
+ // Create events for variuos asynchronous operations.
//
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
HttpCommonNotify,
- &HttpInstance->IsCloseDone,
- &HttpInstance->CloseToken.CompletionToken.Event
+ &HttpInstance->IsTcp6ConnDone,
+ &HttpInstance->Tcp6ConnToken.CompletionToken.Event
);
if (EFI_ERROR (Status)) {
goto ERROR;
}
-
+ //
+ // Initialize Tcp6CloseToken
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpCommonNotify,
+ &HttpInstance->IsTcp6CloseDone,
+ &HttpInstance->Tcp6CloseToken.CompletionToken.Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR;
+ }
+ }
+
return EFI_SUCCESS;
ERROR:
//
// Error handling
//
- HttpCloseTcp4ConnCloseEvent (HttpInstance);
+ HttpCloseTcpConnCloseEvent (HttpInstance);
return Status;
}
/**
- Close events in the TCP4 connection token and TCP4 close token.
+ Close events in the TCP connection token and TCP close token.
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
**/
VOID
-HttpCloseTcp4ConnCloseEvent (
+HttpCloseTcpConnCloseEvent (
IN HTTP_PROTOCOL *HttpInstance
)
{
ASSERT (HttpInstance != NULL);
- if (NULL != HttpInstance->ConnToken.CompletionToken.Event) {
- gBS->CloseEvent (HttpInstance->ConnToken.CompletionToken.Event);
- HttpInstance->ConnToken.CompletionToken.Event = NULL;
- }
+ if (HttpInstance->LocalAddressIsIPv6) {
+ if (NULL != HttpInstance->Tcp6ConnToken.CompletionToken.Event) {
+ gBS->CloseEvent (HttpInstance->Tcp6ConnToken.CompletionToken.Event);
+ HttpInstance->Tcp6ConnToken.CompletionToken.Event = NULL;
+ }
- if (NULL != HttpInstance->CloseToken.CompletionToken.Event) {
- gBS->CloseEvent(HttpInstance->CloseToken.CompletionToken.Event);
- HttpInstance->CloseToken.CompletionToken.Event = NULL;
- }
+ if (NULL != HttpInstance->Tcp6CloseToken.CompletionToken.Event) {
+ gBS->CloseEvent(HttpInstance->Tcp6CloseToken.CompletionToken.Event);
+ HttpInstance->Tcp6CloseToken.CompletionToken.Event = NULL;
+ }
+
+ } else {
+ if (NULL != HttpInstance->Tcp4ConnToken.CompletionToken.Event) {
+ gBS->CloseEvent (HttpInstance->Tcp4ConnToken.CompletionToken.Event);
+ HttpInstance->Tcp4ConnToken.CompletionToken.Event = NULL;
+ }
+
+ if (NULL != HttpInstance->Tcp4CloseToken.CompletionToken.Event) {
+ gBS->CloseEvent(HttpInstance->Tcp4CloseToken.CompletionToken.Event);
+ HttpInstance->Tcp4CloseToken.CompletionToken.Event = NULL;
+ }
+ }
+
}
/**
- Create event for the TCP4 transmit token.
+ Create event for the TCP transmit token.
@param[in] Wrap Point to HTTP token's wrap data.
@@ -302,37 +387,61 @@ HttpCloseTcp4ConnCloseEvent (
**/
EFI_STATUS
-HttpCreateTcp4TxEvent (
+HttpCreateTcpTxEvent (
IN HTTP_TOKEN_WRAP *Wrap
)
{
EFI_STATUS Status;
+ HTTP_PROTOCOL *HttpInstance;
HTTP_TCP_TOKEN_WRAP *TcpWrap;
+ HttpInstance = Wrap->HttpInstance;
TcpWrap = &Wrap->TcpWrap;
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- HttpTcpTransmitNotify,
- Wrap,
- &TcpWrap->TxToken.CompletionToken.Event
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ if (!HttpInstance->LocalAddressIsIPv6) {
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpTcpTransmitNotify,
+ Wrap,
+ &TcpWrap->Tx4Token.CompletionToken.Event
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TcpWrap->Tx4Data.Push = TRUE;
+ TcpWrap->Tx4Data.Urgent = FALSE;
+ TcpWrap->Tx4Data.FragmentCount = 1;
+ TcpWrap->Tx4Token.Packet.TxData = &Wrap->TcpWrap.Tx4Data;
+ TcpWrap->Tx4Token.CompletionToken.Status = EFI_NOT_READY;
- TcpWrap->TxData.Push = TRUE;
- TcpWrap->TxData.Urgent = FALSE;
- TcpWrap->TxData.FragmentCount = 1;
- TcpWrap->TxToken.Packet.TxData = &Wrap->TcpWrap.TxData;
- TcpWrap->TxToken.CompletionToken.Status = EFI_NOT_READY;
+ } else {
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpTcpTransmitNotify,
+ Wrap,
+ &TcpWrap->Tx6Token.CompletionToken.Event
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ TcpWrap->Tx6Data.Push = TRUE;
+ TcpWrap->Tx6Data.Urgent = FALSE;
+ TcpWrap->Tx6Data.FragmentCount = 1;
+ TcpWrap->Tx6Token.Packet.TxData = &Wrap->TcpWrap.Tx6Data;
+ TcpWrap->Tx6Token.CompletionToken.Status =EFI_NOT_READY;
+
+
+ }
+
return EFI_SUCCESS;
}
/**
- Create event for the TCP4 receive token which is used to receive HTTP header.
+ Create event for the TCP receive token which is used to receive HTTP header.
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
@@ -341,33 +450,52 @@ HttpCreateTcp4TxEvent (
**/
EFI_STATUS
-HttpCreateTcp4RxEventForHeader (
+HttpCreateTcpRxEventForHeader (
IN HTTP_PROTOCOL *HttpInstance
)
{
EFI_STATUS Status;
+ if (!HttpInstance->LocalAddressIsIPv6) {
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpCommonNotify,
+ &HttpInstance->IsRxDone,
+ &HttpInstance->Rx4Token.CompletionToken.Event
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ HttpInstance->Rx4Data.FragmentCount = 1;
+ HttpInstance->Rx4Token.Packet.RxData = &HttpInstance->Rx4Data;
+ HttpInstance->Rx4Token.CompletionToken.Status = EFI_NOT_READY;
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- HttpCommonNotify,
- &HttpInstance->IsRxDone,
- &HttpInstance->RxToken.CompletionToken.Event
- );
- if (EFI_ERROR (Status)) {
- return Status;
+ } else {
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpCommonNotify,
+ &HttpInstance->IsRxDone,
+ &HttpInstance->Rx6Token.CompletionToken.Event
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ HttpInstance->Rx6Data.FragmentCount =1;
+ HttpInstance->Rx6Token.Packet.RxData = &HttpInstance->Rx6Data;
+ HttpInstance->Rx6Token.CompletionToken.Status = EFI_NOT_READY;
+
}
- HttpInstance->RxData.FragmentCount = 1;
- HttpInstance->RxToken.Packet.RxData = &HttpInstance->RxData;
- HttpInstance->RxToken.CompletionToken.Status = EFI_NOT_READY;
return EFI_SUCCESS;
}
/**
- Create event for the TCP4 receive token which is used to receive HTTP body.
+ Create event for the TCP receive token which is used to receive HTTP body.
@param[in] Wrap Point to HTTP token's wrap data.
@@ -376,38 +504,101 @@ HttpCreateTcp4RxEventForHeader (
**/
EFI_STATUS
-HttpCreateTcp4RxEvent (
+HttpCreateTcpRxEvent (
IN HTTP_TOKEN_WRAP *Wrap
)
{
EFI_STATUS Status;
+ HTTP_PROTOCOL *HttpInstance;
HTTP_TCP_TOKEN_WRAP *TcpWrap;
+ HttpInstance = Wrap->HttpInstance;
TcpWrap = &Wrap->TcpWrap;
+ if (!HttpInstance->LocalAddressIsIPv6) {
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpTcpReceiveNotify,
+ Wrap,
+ &TcpWrap->Rx4Token.CompletionToken.Event
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TcpWrap->Rx4Data.FragmentCount = 1;
+ TcpWrap->Rx4Token.Packet.RxData = &Wrap->TcpWrap.Rx4Data;
+ TcpWrap->Rx4Token.CompletionToken.Status = EFI_NOT_READY;
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- HttpTcpReceiveNotify,
- Wrap,
- &TcpWrap->RxToken.CompletionToken.Event
- );
- if (EFI_ERROR (Status)) {
- return Status;
+ } else {
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpTcpReceiveNotify,
+ Wrap,
+ &TcpWrap->Rx6Token.CompletionToken.Event
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TcpWrap->Rx6Data.FragmentCount = 1;
+ TcpWrap->Rx6Token.Packet.RxData = &Wrap->TcpWrap.Rx6Data;
+ TcpWrap->Rx6Token.CompletionToken.Status = EFI_NOT_READY;
}
+
+ return EFI_SUCCESS;
+}
- TcpWrap->RxData.FragmentCount = 1;
- TcpWrap->RxToken.Packet.RxData = &Wrap->TcpWrap.RxData;
- TcpWrap->RxToken.CompletionToken.Status = EFI_NOT_READY;
+/**
+ Close Events for Tcp Receive Tokens for HTTP body and HTTP header.
- return EFI_SUCCESS;
+ @param[in] Wrap Pointer to HTTP token's wrap data.
+
+**/
+VOID
+HttpCloseTcpRxEvent (
+ IN HTTP_TOKEN_WRAP *Wrap
+ )
+{
+ HTTP_PROTOCOL *HttpInstance;
+ EFI_TCP4_IO_TOKEN *Rx4Token;
+ EFI_TCP6_IO_TOKEN *Rx6Token;
+
+ HttpInstance = Wrap->HttpInstance;
+ Rx4Token = NULL;
+ Rx6Token = NULL;
+
+ if (HttpInstance->LocalAddressIsIPv6) {
+ if (Wrap != NULL) {
+ if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);
+ }
+ }
+
+ if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);
+ HttpInstance->Rx6Token.CompletionToken.Event = NULL;
+ }
+ } else {
+ if (Wrap != NULL) {
+ if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);
+ }
+ }
+
+ if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);
+ HttpInstance->Rx4Token.CompletionToken.Event = NULL;
+ }
+ }
}
/**
Intiialize the HTTP_PROTOCOL structure to the unconfigured state.
- @param[in] HttpSb The HTTP service private instance.
@param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
+ @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.
@retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
@retval Others Other error as indicated.
@@ -415,95 +606,198 @@ HttpCreateTcp4RxEvent (
**/
EFI_STATUS
HttpInitProtocol (
- IN HTTP_SERVICE *HttpSb,
- IN OUT HTTP_PROTOCOL *HttpInstance
+ IN OUT HTTP_PROTOCOL *HttpInstance,
+ IN BOOLEAN IpVersion
)
{
EFI_STATUS Status;
VOID *Interface;
+ BOOLEAN UsingIpv6;
+
+ ASSERT (HttpInstance != NULL);
+ UsingIpv6 = IpVersion;
+
+ if (!UsingIpv6) {
+ //
+ // Create TCP4 child.
+ //
+ Status = NetLibCreateServiceChild (
+ HttpInstance->Service->ControllerHandle,
+ HttpInstance->Service->ImageHandle,
+ &gEfiTcp4ServiceBindingProtocolGuid,
+ &HttpInstance->Tcp4ChildHandle
+ );
- ASSERT ((HttpSb != NULL) && (HttpInstance != NULL));
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
- HttpInstance->Signature = HTTP_PROTOCOL_SIGNATURE;
- CopyMem (&HttpInstance->Http, &mEfiHttpTemplate, sizeof (HttpInstance->Http));
- HttpInstance->Service = HttpSb;
+ Status = gBS->OpenProtocol (
+ HttpInstance->Tcp4ChildHandle,
+ &gEfiTcp4ProtocolGuid,
+ (VOID **) &Interface,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Service->ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
- //
- // Create TCP child.
- //
- Status = NetLibCreateServiceChild (
- HttpInstance->Service->ControllerHandle,
- HttpInstance->Service->ImageHandle,
- &gEfiTcp4ServiceBindingProtocolGuid,
- &HttpInstance->TcpChildHandle
- );
+ Status = gBS->OpenProtocol (
+ HttpInstance->Tcp4ChildHandle,
+ &gEfiTcp4ProtocolGuid,
+ (VOID **) &HttpInstance->Tcp4,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR(Status)) {
+ goto ON_ERROR;
+ }
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
+ Status = gBS->OpenProtocol (
+ HttpInstance->Service->Tcp4ChildHandle,
+ &gEfiTcp4ProtocolGuid,
+ (VOID **) &Interface,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR(Status)) {
+ goto ON_ERROR;
+ }
+ } else {
+ //
+ // Create TCP6 Child.
+ //
+ Status = NetLibCreateServiceChild (
+ HttpInstance->Service->ControllerHandle,
+ HttpInstance->Service->ImageHandle,
+ &gEfiTcp6ServiceBindingProtocolGuid,
+ &HttpInstance->Tcp6ChildHandle
+ );
- Status = gBS->OpenProtocol (
- HttpInstance->TcpChildHandle,
- &gEfiTcp4ProtocolGuid,
- (VOID **) &Interface,
- HttpInstance->Service->ImageHandle,
- HttpInstance->Service->ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
-
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
- Status = gBS->OpenProtocol (
- HttpInstance->TcpChildHandle,
- &gEfiTcp4ProtocolGuid,
- (VOID **) &HttpInstance->Tcp4,
- HttpInstance->Service->ImageHandle,
- HttpInstance->Handle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- if (EFI_ERROR(Status)) {
- goto ON_ERROR;
- }
+ Status = gBS->OpenProtocol (
+ HttpInstance->Tcp6ChildHandle,
+ &gEfiTcp6ProtocolGuid,
+ (VOID **) &Interface,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Service->ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ Status = gBS->OpenProtocol (
+ HttpInstance->Tcp6ChildHandle,
+ &gEfiTcp6ProtocolGuid,
+ (VOID **) &HttpInstance->Tcp6,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ if (EFI_ERROR(Status)) {
+ goto ON_ERROR;
+ }
+
+ Status = gBS->OpenProtocol (
+ HttpInstance->Service->Tcp6ChildHandle,
+ &gEfiTcp6ProtocolGuid,
+ (VOID **) &Interface,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ if (EFI_ERROR(Status)) {
+ goto ON_ERROR;
+ }
+ }
+
HttpInstance->Url = AllocateZeroPool (HTTP_URL_BUFFER_LEN);
if (HttpInstance->Url == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
}
- NetMapInit (&HttpInstance->TxTokens);
- NetMapInit (&HttpInstance->RxTokens);
-
return EFI_SUCCESS;
ON_ERROR:
- if (HttpInstance->TcpChildHandle != NULL) {
+ if (HttpInstance->Tcp4ChildHandle != NULL) {
gBS->CloseProtocol (
- HttpInstance->TcpChildHandle,
+ HttpInstance->Tcp4ChildHandle,
&gEfiTcp4ProtocolGuid,
HttpInstance->Service->ImageHandle,
HttpInstance->Service->ControllerHandle
);
gBS->CloseProtocol (
- HttpInstance->TcpChildHandle,
+ HttpInstance->Tcp4ChildHandle,
&gEfiTcp4ProtocolGuid,
HttpInstance->Service->ImageHandle,
HttpInstance->Handle
- );
+ );
NetLibDestroyServiceChild (
HttpInstance->Service->ControllerHandle,
HttpInstance->Service->ImageHandle,
&gEfiTcp4ServiceBindingProtocolGuid,
- HttpInstance->TcpChildHandle
+ HttpInstance->Tcp4ChildHandle
);
}
+
+ if (HttpInstance->Service->Tcp4ChildHandle != NULL) {
+ gBS->CloseProtocol (
+ HttpInstance->Service->Tcp4ChildHandle,
+ &gEfiTcp4ProtocolGuid,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Handle
+ );
+ }
+
+ if (HttpInstance->Tcp6ChildHandle != NULL) {
+ gBS->CloseProtocol (
+ HttpInstance->Tcp6ChildHandle,
+ &gEfiTcp6ProtocolGuid,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Service->ControllerHandle
+ );
- return Status;
+ gBS->CloseProtocol (
+ HttpInstance->Tcp6ChildHandle,
+ &gEfiTcp6ProtocolGuid,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Handle
+ );
+
+ NetLibDestroyServiceChild (
+ HttpInstance->Service->ControllerHandle,
+ HttpInstance->Service->ImageHandle,
+ &gEfiTcp6ServiceBindingProtocolGuid,
+ HttpInstance->Tcp6ChildHandle
+ );
+ }
+
+ if (HttpInstance->Service->Tcp6ChildHandle != NULL) {
+ gBS->CloseProtocol (
+ HttpInstance->Service->Tcp6ChildHandle,
+ &gEfiTcp6ProtocolGuid,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Handle
+ );
+ }
+
+ return EFI_UNSUPPORTED;
}
@@ -520,7 +814,7 @@ HttpCleanProtocol (
{
HttpCloseConnection (HttpInstance);
- HttpCloseTcp4ConnCloseEvent (HttpInstance);
+ HttpCloseTcpConnCloseEvent (HttpInstance);
if (HttpInstance->CacheBody != NULL) {
FreePool (HttpInstance->CacheBody);
@@ -537,25 +831,25 @@ HttpCleanProtocol (
HttpFreeMsgParser (HttpInstance->MsgParser);
HttpInstance->MsgParser = NULL;
}
-
+
if (HttpInstance->Url != NULL) {
FreePool (HttpInstance->Url);
HttpInstance->Url = NULL;
}
-
+
NetMapClean (&HttpInstance->TxTokens);
NetMapClean (&HttpInstance->RxTokens);
- if (HttpInstance->TcpChildHandle != NULL) {
+ if (HttpInstance->Tcp4ChildHandle != NULL) {
gBS->CloseProtocol (
- HttpInstance->TcpChildHandle,
+ HttpInstance->Tcp4ChildHandle,
&gEfiTcp4ProtocolGuid,
HttpInstance->Service->ImageHandle,
HttpInstance->Service->ControllerHandle
);
gBS->CloseProtocol (
- HttpInstance->TcpChildHandle,
+ HttpInstance->Tcp4ChildHandle,
&gEfiTcp4ProtocolGuid,
HttpInstance->Service->ImageHandle,
HttpInstance->Handle
@@ -565,9 +859,51 @@ HttpCleanProtocol (
HttpInstance->Service->ControllerHandle,
HttpInstance->Service->ImageHandle,
&gEfiTcp4ServiceBindingProtocolGuid,
- HttpInstance->TcpChildHandle
+ HttpInstance->Tcp4ChildHandle
);
}
+
+ if (HttpInstance->Service->Tcp4ChildHandle != NULL) {
+ gBS->CloseProtocol (
+ HttpInstance->Service->Tcp4ChildHandle,
+ &gEfiTcp4ProtocolGuid,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Handle
+ );
+ }
+
+ if (HttpInstance->Tcp6ChildHandle != NULL) {
+ gBS->CloseProtocol (
+ HttpInstance->Tcp6ChildHandle,
+ &gEfiTcp6ProtocolGuid,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Service->ControllerHandle
+ );
+
+ gBS->CloseProtocol (
+ HttpInstance->Tcp6ChildHandle,
+ &gEfiTcp6ProtocolGuid,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Handle
+ );
+
+ NetLibDestroyServiceChild (
+ HttpInstance->Service->ControllerHandle,
+ HttpInstance->Service->ImageHandle,
+ &gEfiTcp6ServiceBindingProtocolGuid,
+ HttpInstance->Tcp6ChildHandle
+ );
+ }
+
+ if (HttpInstance->Service->Tcp6ChildHandle != NULL) {
+ gBS->CloseProtocol (
+ HttpInstance->Service->Tcp6ChildHandle,
+ &gEfiTcp6ProtocolGuid,
+ HttpInstance->Service->ImageHandle,
+ HttpInstance->Handle
+ );
+ }
+
}
/**
@@ -587,26 +923,39 @@ HttpCreateConnection (
EFI_STATUS Status;
//
- // Create events for variuos asynchronous operations.
- //
- HttpInstance->IsConnDone = FALSE;
-
- //
// Connect to Http server
//
- HttpInstance->ConnToken.CompletionToken.Status = EFI_NOT_READY;
- Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->ConnToken);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));
- return Status;
- }
-
- while (!HttpInstance->IsConnDone) {
- HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
- }
+ if (!HttpInstance->LocalAddressIsIPv6) {
+ HttpInstance->IsTcp4ConnDone = FALSE;
+ HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY;
+ Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));
+ return Status;
+ }
+
+ while (!HttpInstance->IsTcp4ConnDone) {
+ HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
+ }
+
+ Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;
+
+ } else {
+ HttpInstance->IsTcp6ConnDone = FALSE;
+ HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY;
+ Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status));
+ return Status;
+ }
- Status = HttpInstance->ConnToken.CompletionToken.Status;
+ while(!HttpInstance->IsTcp6ConnDone) {
+ HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);
+ }
+ Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status;
+ }
+
if (!EFI_ERROR (Status)) {
HttpInstance->State = HTTP_STATE_TCP_CONNECTED;
}
@@ -631,17 +980,32 @@ HttpCloseConnection (
EFI_STATUS Status;
if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {
- HttpInstance->CloseToken.AbortOnClose = TRUE;
- HttpInstance->IsCloseDone = FALSE;
-
- Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->CloseToken);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- while (!HttpInstance->IsCloseDone) {
- HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
+ if (HttpInstance->LocalAddressIsIPv6) {
+ HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE;
+ HttpInstance->IsTcp6CloseDone = FALSE;
+ Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (!HttpInstance->IsTcp6CloseDone) {
+ HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);
+ }
+
+ } else {
+ HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE;
+ HttpInstance->IsTcp4CloseDone = FALSE;
+ Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (!HttpInstance->IsTcp4CloseDone) {
+ HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
+ }
}
+
}
HttpInstance->State = HTTP_STATE_TCP_CLOSED;
@@ -710,12 +1074,82 @@ HttpConfigureTcp4 (
return Status;
}
- Status = HttpCreateTcp4ConnCloseEvent (HttpInstance);
+ Status = HttpCreateTcpConnCloseEvent (HttpInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = HttpCreateTcpTxEvent (Wrap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ HttpInstance->State = HTTP_STATE_TCP_CONFIGED;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Configure TCP6 protocol child.
+
+ @param[in] HttpInstance The HTTP instance private data.
+ @param[in] Wrap The HTTP token's wrap data.
+
+ @retval EFI_SUCCESS The TCP6 protocol child is configured.
+ @retval Others Other error as indicated.
+
+**/
+EFI_STATUS
+HttpConfigureTcp6 (
+ IN HTTP_PROTOCOL *HttpInstance,
+ IN HTTP_TOKEN_WRAP *Wrap
+ )
+{
+ EFI_STATUS Status;
+ EFI_TCP6_CONFIG_DATA *Tcp6CfgData;
+ EFI_TCP6_ACCESS_POINT *Tcp6Ap;
+ EFI_TCP6_OPTION *Tcp6Option;
+
+ ASSERT (HttpInstance != NULL);
+
+ Tcp6CfgData = &HttpInstance->Tcp6CfgData;
+ ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA));
+
+ Tcp6CfgData->TrafficClass = 0;
+ Tcp6CfgData->HopLimit = 255;
+ Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option;
+
+ Tcp6Ap = &Tcp6CfgData->AccessPoint;
+ Tcp6Ap->ActiveFlag = TRUE;
+ Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort;
+ Tcp6Ap->RemotePort = HttpInstance->RemotePort;
+ IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress);
+ IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress , &HttpInstance->RemoteIpv6Addr);
+
+ Tcp6Option = Tcp6CfgData->ControlOption;
+ Tcp6Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;
+ Tcp6Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;
+ Tcp6Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;
+ Tcp6Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;
+ Tcp6Option->DataRetries = HTTP_DATA_RETRIES;
+ Tcp6Option->FinTimeout = HTTP_FIN_TIMEOUT;
+ Tcp6Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;
+ Tcp6Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;
+ Tcp6Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;
+ Tcp6Option->EnableNagle = TRUE;
+
+ Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "HttpConfigureTcp6 - %r\n", Status));
+ return Status;
+ }
+
+ Status = HttpCreateTcpConnCloseEvent (HttpInstance);
if (EFI_ERROR (Status)) {
return Status;
}
- Status = HttpCreateTcp4TxEvent (Wrap);
+ Status = HttpCreateTcpTxEvent (Wrap);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -723,10 +1157,11 @@ HttpConfigureTcp4 (
HttpInstance->State = HTTP_STATE_TCP_CONFIGED;
return EFI_SUCCESS;
+
}
/**
- Check existing TCP connection, if in error state, receover TCP4 connection.
+ Check existing TCP connection, if in error state, recover TCP4 connection.
@param[in] HttpInstance The HTTP instance private data.
@@ -769,7 +1204,105 @@ HttpConnectTcp4 (
}
/**
- Send the HTTP message through TCP4.
+ Check existing TCP connection, if in error state, recover TCP6 connection.
+
+ @param[in] HttpInstance The HTTP instance private data.
+
+ @retval EFI_SUCCESS The TCP connection is established.
+ @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
+ @retval Others Other error as indicated.
+
+**/
+EFI_STATUS
+HttpConnectTcp6 (
+ IN HTTP_PROTOCOL *HttpInstance
+ )
+{
+ EFI_STATUS Status;
+ EFI_TCP6_CONNECTION_STATE Tcp6State;
+
+ if (HttpInstance->State != HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = HttpInstance->Tcp6->GetModeData (
+ HttpInstance->Tcp6,
+ &Tcp6State,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ );
+
+ if (EFI_ERROR(Status)){
+ DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status));
+ return Status;
+ }
+
+ if (Tcp6State > Tcp6StateEstablished) {
+ HttpCloseConnection (HttpInstance);
+ }
+
+ return HttpCreateConnection (HttpInstance);
+}
+
+/**
+ Initialize TCP related data.
+
+ @param[in] HttpInstance The HTTP instance private data.
+ @param[in] Wrap The HTTP token's wrap data.
+
+ @retval EFI_SUCCESS The initialization of TCP instance is done.
+ @retval Others Other error as indicated.
+
+**/
+EFI_STATUS
+HttpInitTcp (
+ IN HTTP_PROTOCOL *HttpInstance,
+ IN HTTP_TOKEN_WRAP *Wrap
+ )
+{
+ EFI_STATUS Status;
+ ASSERT (HttpInstance != NULL);
+
+ if (!HttpInstance->LocalAddressIsIPv6) {
+ //
+ // Configure TCP instance.
+ //
+ Status = HttpConfigureTcp4 (HttpInstance, Wrap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Connect TCP.
+ //
+ Status = HttpConnectTcp4 (HttpInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+ //
+ // Configure TCP instance.
+ //
+ Status = HttpConfigureTcp6 (HttpInstance, Wrap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Connect TCP.
+ //
+ Status = HttpConnectTcp6 (HttpInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Send the HTTP message through TCP4 or TCP6.
@param[in] HttpInstance The HTTP instance private data.
@param[in] Wrap The HTTP token's wrap data.
@@ -781,7 +1314,7 @@ HttpConnectTcp4 (
**/
EFI_STATUS
-HttpTransmitTcp4 (
+HttpTransmitTcp (
IN HTTP_PROTOCOL *HttpInstance,
IN HTTP_TOKEN_WRAP *Wrap,
IN UINT8 *TxString,
@@ -789,23 +1322,44 @@ HttpTransmitTcp4 (
)
{
EFI_STATUS Status;
- EFI_TCP4_IO_TOKEN *TxToken;
+ EFI_TCP4_IO_TOKEN *Tx4Token;
EFI_TCP4_PROTOCOL *Tcp4;
+ EFI_TCP6_IO_TOKEN *Tx6Token;
+ EFI_TCP6_PROTOCOL *Tcp6;
- Tcp4 = HttpInstance->Tcp4;
- TxToken = &Wrap->TcpWrap.TxToken;
+ if (!HttpInstance->LocalAddressIsIPv6) {
+ Tcp4 = HttpInstance->Tcp4;
+ Tx4Token = &Wrap->TcpWrap.Tx4Token;
+
+ Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;
+ Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;
+ Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;
+ Tx4Token->CompletionToken.Status = EFI_NOT_READY;
+
+ Wrap->TcpWrap.IsTxDone = FALSE;
+ Status = Tcp4->Transmit (Tcp4, Tx4Token);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));
+ return Status;
+ }
- TxToken->Packet.TxData->DataLength = (UINT32) TxStringLen;
- TxToken->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;
- TxToken->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;
- TxToken->CompletionToken.Status = EFI_NOT_READY;
+ } else {
+ Tcp6 = HttpInstance->Tcp6;
+ Tx6Token = &Wrap->TcpWrap.Tx6Token;
- Wrap->TcpWrap.IsTxDone = FALSE;
- Status = Tcp4->Transmit (Tcp4, TxToken);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));
- return Status;
+ Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;
+ Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;
+ Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;
+ Tx6Token->CompletionToken.Status = EFI_NOT_READY;
+
+ Wrap->TcpWrap.IsTxDone = FALSE;
+ Status = Tcp6->Transmit (Tcp6, Tx6Token);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));
+ return Status;
+ }
}
+
return Status;
}
@@ -913,7 +1467,7 @@ HttpMappingToStatusCode (
/**
Check whether the user's token or event has already
- been enqueue on HTTP TxToken or RxToken list.
+ been enqueue on HTTP Tx or Rx Token list.
@param[in] Map The container of either user's transmit or receive
token.
@@ -947,9 +1501,9 @@ HttpTokenExist (
}
/**
- Check whether the HTTP message associated with TxToken is already sent out.
+ Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
- @param[in] Map The container of TxToken.
+ @param[in] Map The container of Tx4Token or Tx6Token.
@param[in] Item Current item to check against.
@param[in] Context The Token to check againist.
@@ -979,7 +1533,7 @@ HttpTcpNotReady (
/**
Transmit the HTTP mssage by processing the associated HTTP token.
- @param[in] Map The container of TxToken.
+ @param[in] Map The container of Tx4Token or Tx6Token.
@param[in] Item Current item to check against.
@param[in] Context The Token to check againist.
@@ -1032,7 +1586,7 @@ HttpTcpTransmit (
//
// Transmit the request message.
//
- Status = HttpTransmitTcp4 (
+ Status = HttpTransmitTcp (
ValueInItem->HttpInstance,
ValueInItem,
(UINT8*) RequestStr,
@@ -1045,7 +1599,7 @@ HttpTcpTransmit (
/**
Receive the HTTP response by processing the associated HTTP token.
- @param[in] Map The container of RxToken.
+ @param[in] Map The container of Rx4Token or Rx6Token.
@param[in] Item Current item to check against.
@param[in] Context The Token to check againist.
@@ -1069,6 +1623,319 @@ HttpTcpReceive (
}
/**
+ Receive the HTTP header by processing the associated HTTP token.
+
+ @param[in] HttpInstance The HTTP instance private data.
+ @param[in, out] SizeofHeaders The HTTP header length.
+ @param[in, out] BufferSize The size of buffer to cacahe the header message.
+
+ @retval EFI_SUCCESS The HTTP header is received.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpTcpReceiveHeader (
+ IN HTTP_PROTOCOL *HttpInstance,
+ IN OUT UINTN *SizeofHeaders,
+ IN OUT UINTN *BufferSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_TCP4_IO_TOKEN *Rx4Token;
+ EFI_TCP4_PROTOCOL *Tcp4;
+ EFI_TCP6_IO_TOKEN *Rx6Token;
+ EFI_TCP6_PROTOCOL *Tcp6;
+ CHAR8 **EndofHeader;
+ CHAR8 **HttpHeaders;
+ CHAR8 *Buffer;
+
+ ASSERT (HttpInstance != NULL);
+
+ EndofHeader = HttpInstance->EndofHeader;
+ HttpHeaders = HttpInstance->HttpHeaders;
+ Tcp4 = HttpInstance->Tcp4;
+ Tcp6 = HttpInstance->Tcp6;
+ Buffer = NULL;
+ Rx4Token = NULL;
+ Rx6Token = NULL;
+
+ if (HttpInstance->LocalAddressIsIPv6) {
+ ASSERT (Tcp6 != NULL);
+ } else {
+ ASSERT (Tcp4 != NULL);
+ }
+
+ if (!HttpInstance->LocalAddressIsIPv6) {
+ Rx4Token = &HttpInstance->Rx4Token;
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);
+ if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+
+ //
+ // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
+ //
+ while (*EndofHeader == NULL) {
+ HttpInstance->IsRxDone = FALSE;
+ Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;
+ Status = Tcp4->Receive (Tcp4, Rx4Token);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));
+ return Status;
+ }
+
+ while (!HttpInstance->IsRxDone) {
+ Tcp4->Poll (Tcp4);
+ }
+
+ Status = Rx4Token->CompletionToken.Status;
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Append the response string.
+ //
+ *BufferSize = (*SizeofHeaders) + Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;
+ Buffer = AllocateZeroPool (*BufferSize);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+
+ if (*HttpHeaders != NULL) {
+ CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));
+ FreePool (*HttpHeaders);
+ }
+
+ CopyMem (
+ Buffer + (*SizeofHeaders),
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer,
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength
+ );
+ *HttpHeaders = Buffer;
+ *SizeofHeaders = *BufferSize;
+
+ //
+ // Check whether we received end of HTTP headers.
+ //
+ *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);
+ }
+ FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
+
+ } else {
+ Rx6Token = &HttpInstance->Rx6Token;
+ Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);
+ if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+
+ //
+ // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
+ //
+ while (*EndofHeader == NULL) {
+ HttpInstance->IsRxDone = FALSE;
+ Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;
+ Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;
+ Status = Tcp6->Receive (Tcp6, Rx6Token);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));
+ return Status;
+ }
+
+ while (!HttpInstance->IsRxDone) {
+ Tcp6->Poll (Tcp6);
+ }
+
+ Status = Rx6Token->CompletionToken.Status;
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Append the response string.
+ //
+ *BufferSize = (*SizeofHeaders) + Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;
+ Buffer = AllocateZeroPool (*BufferSize);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+
+ if (*HttpHeaders != NULL) {
+ CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));
+ FreePool (*HttpHeaders);
+ }
+
+ CopyMem (
+ Buffer + (*SizeofHeaders),
+ Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer,
+ Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength
+ );
+ *HttpHeaders = Buffer;
+ *SizeofHeaders = *BufferSize;
+
+ //
+ // Check whether we received end of HTTP headers.
+ //
+ *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);
+
+ }
+ FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);
+ Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
+ }
+
+ //
+ // Skip the CRLF after the HTTP headers.
+ //
+ *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Receive the HTTP body by processing the associated HTTP token.
+
+ @param[in] Wrap The HTTP token's wrap data.
+ @param[in] HttpMsg The HTTP message data.
+
+ @retval EFI_SUCCESS The HTTP body is received.
+ @retval Others Other error as indicated.
+
+**/
+EFI_STATUS
+HttpTcpReceiveBody (
+ IN HTTP_TOKEN_WRAP *Wrap,
+ IN EFI_HTTP_MESSAGE *HttpMsg
+ )
+{
+ EFI_STATUS Status;
+ HTTP_PROTOCOL *HttpInstance;
+ EFI_TCP6_PROTOCOL *Tcp6;
+ EFI_TCP6_IO_TOKEN *Rx6Token;
+ EFI_TCP4_PROTOCOL *Tcp4;
+ EFI_TCP4_IO_TOKEN *Rx4Token;
+
+ HttpInstance = Wrap->HttpInstance;
+ Tcp4 = HttpInstance->Tcp4;
+ Tcp6 = HttpInstance->Tcp6;
+ Rx4Token = NULL;
+ Rx6Token = NULL;
+
+
+ if (HttpInstance->LocalAddressIsIPv6) {
+ ASSERT (Tcp6 != NULL);
+ } else {
+ ASSERT (Tcp4 != NULL);
+ }
+
+ if (HttpInstance->LocalAddressIsIPv6) {
+ Rx6Token = &Wrap->TcpWrap.Rx6Token;
+ Rx6Token ->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;
+ Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;
+ Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;
+ Rx6Token->CompletionToken.Status = EFI_NOT_READY;
+
+ Status = Tcp6->Receive (Tcp6, Rx6Token);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));
+ return Status;
+ }
+
+ } else {
+ Rx4Token = &Wrap->TcpWrap.Rx4Token;
+ Rx4Token->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;
+
+ Rx4Token->CompletionToken.Status = EFI_NOT_READY;
+ Status = Tcp4->Receive (Tcp4, Rx4Token);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Clean up Tcp Tokens while the Tcp transmission error occurs.
+
+ @param[in] Wrap Pointer to HTTP token's wrap data.
+
+**/
+VOID
+HttpTcpTokenCleanup (
+ IN HTTP_TOKEN_WRAP *Wrap
+ )
+{
+ HTTP_PROTOCOL *HttpInstance;
+ EFI_TCP4_IO_TOKEN *Rx4Token;
+ EFI_TCP6_IO_TOKEN *Rx6Token;
+
+ HttpInstance = Wrap->HttpInstance;
+ Rx4Token = NULL;
+ Rx6Token = NULL;
+
+ if (HttpInstance->LocalAddressIsIPv6) {
+ if (Wrap != NULL) {
+ if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);
+ }
+
+ Rx6Token = &Wrap->TcpWrap.Rx6Token;
+ if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
+ FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);
+ Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
+ }
+ FreePool (Wrap);
+ }
+
+ if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);
+ HttpInstance->Rx6Token.CompletionToken.Event = NULL;
+ }
+
+ Rx6Token = &HttpInstance->Rx6Token;
+ if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
+ FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);
+ Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
+ }
+
+ } else {
+ if (Wrap != NULL) {
+ if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);
+ }
+ Rx4Token = &Wrap->TcpWrap.Rx4Token;
+ if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
+ FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
+ }
+ FreePool (Wrap);
+ }
+
+ if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {
+ gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);
+ HttpInstance->Rx4Token.CompletionToken.Event = NULL;
+ }
+
+ Rx4Token = &HttpInstance->Rx4Token;
+ if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
+ FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
+ }
+ }
+
+}
+
+/**
Generate HTTP request string.
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
diff --git a/NetworkPkg/HttpDxe/HttpProto.h b/NetworkPkg/HttpDxe/HttpProto.h
index c37b80c8ec..a15e0a87be 100644
--- a/NetworkPkg/HttpDxe/HttpProto.h
+++ b/NetworkPkg/HttpDxe/HttpProto.h
@@ -27,6 +27,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
HTTP_SERVICE_SIGNATURE \
)
+
//
// The state of HTTP protocol. It starts from UNCONFIGED.
//
@@ -58,18 +59,23 @@ typedef struct _HTTP_SERVICE {
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
EFI_HANDLE ImageHandle;
EFI_HANDLE ControllerHandle;
+ EFI_HANDLE Tcp4ChildHandle;
+ EFI_HANDLE Tcp6ChildHandle;
LIST_ENTRY ChildrenList;
UINTN ChildrenNumber;
- EFI_HANDLE TcpChildHandle;
INTN State;
} HTTP_SERVICE;
typedef struct {
- EFI_TCP4_IO_TOKEN TxToken;
- EFI_TCP4_TRANSMIT_DATA TxData;
+ EFI_TCP4_IO_TOKEN Tx4Token;
+ EFI_TCP4_TRANSMIT_DATA Tx4Data;
+ EFI_TCP6_IO_TOKEN Tx6Token;
+ EFI_TCP6_TRANSMIT_DATA Tx6Data;
+ EFI_TCP4_IO_TOKEN Rx4Token;
+ EFI_TCP4_RECEIVE_DATA Rx4Data;
+ EFI_TCP6_IO_TOKEN Rx6Token;
+ EFI_TCP6_RECEIVE_DATA Rx6Data;
BOOLEAN IsTxDone;
- EFI_TCP4_IO_TOKEN RxToken;
- EFI_TCP4_RECEIVE_DATA RxData;
BOOLEAN IsRxDone;
UINTN BodyLen;
EFI_HTTP_METHOD Method;
@@ -84,26 +90,43 @@ typedef struct _HTTP_PROTOCOL {
BOOLEAN InDestroy;
INTN State;
- EFI_HANDLE TcpChildHandle;
+ EFI_HANDLE Tcp4ChildHandle;
EFI_TCP4_PROTOCOL *Tcp4;
EFI_TCP4_CONFIG_DATA Tcp4CfgData;
EFI_TCP4_OPTION Tcp4Option;
- EFI_TCP4_CONNECTION_TOKEN ConnToken;
- BOOLEAN IsConnDone;
- EFI_TCP4_CLOSE_TOKEN CloseToken;
- BOOLEAN IsCloseDone;
-
+ EFI_TCP4_CONNECTION_TOKEN Tcp4ConnToken;
+ BOOLEAN IsTcp4ConnDone;
+ EFI_TCP4_CLOSE_TOKEN Tcp4CloseToken;
+ BOOLEAN IsTcp4CloseDone;
CHAR8 *RemoteHost;
UINT16 RemotePort;
EFI_IPv4_ADDRESS RemoteAddr;
+
+ EFI_HANDLE Tcp6ChildHandle;
+ EFI_TCP6_PROTOCOL *Tcp6;
+ EFI_TCP6_CONFIG_DATA Tcp6CfgData;
+ EFI_TCP6_OPTION Tcp6Option;
+
+ EFI_TCP6_CONNECTION_TOKEN Tcp6ConnToken;
+ BOOLEAN IsTcp6ConnDone;
+ EFI_TCP6_CLOSE_TOKEN Tcp6CloseToken;
+ BOOLEAN IsTcp6CloseDone;
+ EFI_IPv6_ADDRESS RemoteIpv6Addr;
+
+
+
//
- // RxToken used for receiving HTTP header.
+ // Rx4Token or Rx6Token used for receiving HTTP header.
//
- EFI_TCP4_IO_TOKEN RxToken;
- EFI_TCP4_RECEIVE_DATA RxData;
+ EFI_TCP4_IO_TOKEN Rx4Token;
+ EFI_TCP4_RECEIVE_DATA Rx4Data;
+ EFI_TCP6_IO_TOKEN Rx6Token;
+ EFI_TCP6_RECEIVE_DATA Rx6Data;
BOOLEAN IsRxDone;
+ CHAR8 **EndofHeader;
+ CHAR8 **HttpHeaders;
CHAR8 *CacheBody;
CHAR8 *NextMsg;
UINTN CacheLen;
@@ -119,6 +142,7 @@ typedef struct _HTTP_PROTOCOL {
BOOLEAN LocalAddressIsIPv6;
EFI_HTTPv4_ACCESS_POINT IPv4Node;
+ EFI_HTTPv6_ACCESS_POINT Ipv6Node;
NET_MAP TxTokens;
NET_MAP RxTokens;
@@ -158,7 +182,7 @@ HttpCommonNotify (
);
/**
- Create events for the TCP4 connection token and TCP4 close token.
+ Create events for the TCP connection token and TCP close token.
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
@@ -167,23 +191,23 @@ HttpCommonNotify (
**/
EFI_STATUS
-HttpCreateTcp4ConnCloseEvent (
+HttpCreateTcpConnCloseEvent (
IN HTTP_PROTOCOL *HttpInstance
);
/**
- Close events in the TCP4 connection token and TCP4 close token.
+ Close events in the TCP connection token and TCP close token.
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
**/
VOID
-HttpCloseTcp4ConnCloseEvent (
+HttpCloseTcpConnCloseEvent (
IN HTTP_PROTOCOL *HttpInstance
);
/**
- Create event for the TCP4 transmit token.
+ Create event for the TCP transmit token.
@param[in] Wrap Point to HTTP token's wrap data.
@@ -192,12 +216,12 @@ HttpCloseTcp4ConnCloseEvent (
**/
EFI_STATUS
-HttpCreateTcp4TxEvent (
+HttpCreateTcpTxEvent (
IN HTTP_TOKEN_WRAP *Wrap
);
/**
- Create event for the TCP4 receive token which is used to receive HTTP header.
+ Create event for the TCP receive token which is used to receive HTTP header.
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
@@ -206,12 +230,12 @@ HttpCreateTcp4TxEvent (
**/
EFI_STATUS
-HttpCreateTcp4RxEventForHeader (
+HttpCreateTcpRxEventForHeader (
IN HTTP_PROTOCOL *HttpInstance
);
/**
- Create event for the TCP4 receive token which is used to receive HTTP body.
+ Create event for the TCP receive token which is used to receive HTTP body.
@param[in] Wrap Point to HTTP token's wrap data.
@@ -220,15 +244,26 @@ HttpCreateTcp4RxEventForHeader (
**/
EFI_STATUS
-HttpCreateTcp4RxEvent (
+HttpCreateTcpRxEvent (
IN HTTP_TOKEN_WRAP *Wrap
);
/**
+ Close Events for Tcp Receive Tokens for HTTP body and HTTP header.
+
+ @param[in] Wrap Pointer to HTTP token's wrap data.
+
+**/
+VOID
+HttpCloseTcpRxEvent (
+ IN HTTP_TOKEN_WRAP *Wrap
+ );
+
+/**
Intiialize the HTTP_PROTOCOL structure to the unconfigured state.
- @param[in] HttpSb The HTTP service private instance.
@param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
+ @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.
@retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
@retval Others Other error as indicated.
@@ -236,8 +271,8 @@ HttpCreateTcp4RxEvent (
**/
EFI_STATUS
HttpInitProtocol (
- IN HTTP_SERVICE *HttpSb,
- IN OUT HTTP_PROTOCOL *HttpInstance
+ IN OUT HTTP_PROTOCOL *HttpInstance,
+ IN BOOLEAN IpVersion
);
/**
@@ -296,6 +331,22 @@ HttpConfigureTcp4 (
);
/**
+ Configure TCP6 protocol child.
+
+ @param[in] HttpInstance The HTTP instance private data.
+ @param[in] Wrap The HTTP token's wrap data.
+
+ @retval EFI_SUCCESS The TCP6 protocol child is configured.
+ @retval Others Other error as indicated.
+
+**/
+EFI_STATUS
+HttpConfigureTcp6 (
+ IN HTTP_PROTOCOL *HttpInstance,
+ IN HTTP_TOKEN_WRAP *Wrap
+ );
+
+/**
Check existing TCP connection, if in error state, receover TCP4 connection.
@param[in] HttpInstance The HTTP instance private data.
@@ -311,7 +362,22 @@ HttpConnectTcp4 (
);
/**
- Send the HTTP message through TCP4.
+ Check existing TCP connection, if in error state, recover TCP6 connection.
+
+ @param[in] HttpInstance The HTTP instance private data.
+
+ @retval EFI_SUCCESS The TCP connection is established.
+ @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
+ @retval Others Other error as indicated.
+
+**/
+EFI_STATUS
+HttpConnectTcp6 (
+ IN HTTP_PROTOCOL *HttpInstance
+ );
+
+/**
+ Send the HTTP message through TCP4 or TCP6.
@param[in] HttpInstance The HTTP instance private data.
@param[in] Wrap The HTTP token's wrap data.
@@ -323,7 +389,7 @@ HttpConnectTcp4 (
**/
EFI_STATUS
-HttpTransmitTcp4 (
+HttpTransmitTcp (
IN HTTP_PROTOCOL *HttpInstance,
IN HTTP_TOKEN_WRAP *Wrap,
IN UINT8 *TxString,
@@ -346,7 +412,7 @@ HttpMappingToStatusCode (
/**
Check whether the user's token or event has already
- been enqueue on HTTP TxToken or RxToken list.
+ been enqueue on HTTP Tx or Rx Token list.
@param[in] Map The container of either user's transmit or receive
token.
@@ -367,7 +433,7 @@ HttpTokenExist (
);
/**
- Check whether the HTTP message associated with TxToken is already sent out.
+ Check whether the HTTP message associated with TxToken or Tx6Token is already sent out.
@param[in] Map The container of TxToken.
@param[in] Item Current item to check against.
@@ -386,9 +452,25 @@ HttpTcpNotReady (
);
/**
+ Initialize TCP related data.
+
+ @param[in] HttpInstance The HTTP instance private data.
+ @param[in] Wrap The HTTP token's wrap data.
+
+ @retval EFI_SUCCESS The initialization of TCP instance is done.
+ @retval Others Other error as indicated.
+
+**/
+EFI_STATUS
+HttpInitTcp (
+ IN HTTP_PROTOCOL *HttpInstance,
+ IN HTTP_TOKEN_WRAP *Wrap
+ );
+
+/**
Transmit the HTTP mssage by processing the associated HTTP token.
- @param[in] Map The container of TxToken.
+ @param[in] Map The container of TxToken or Tx6Token.
@param[in] Item Current item to check against.
@param[in] Context The Token to check againist.
@@ -408,7 +490,7 @@ HttpTcpTransmit (
/**
Receive the HTTP response by processing the associated HTTP token.
- @param[in] Map The container of RxToken.
+ @param[in] Map The container of Rx4Token or Rx6Token.
@param[in] Item Current item to check against.
@param[in] Context The Token to check againist.
@@ -426,6 +508,51 @@ HttpTcpReceive (
);
/**
+ Receive the HTTP header by processing the associated HTTP token.
+
+ @param[in] HttpInstance The HTTP instance private data.
+ @param[in, out] SizeofHeaders The HTTP header length.
+ @param[in, out] BufferSize The size of buffer to cacahe the header message.
+
+ @retval EFI_SUCCESS The HTTP header is received.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpTcpReceiveHeader (
+ IN HTTP_PROTOCOL *HttpInstance,
+ IN OUT UINTN *SizeofHeaders,
+ IN OUT UINTN *BufferSize
+ );
+
+/**
+ Receive the HTTP body by processing the associated HTTP token.
+
+ @param[in] Wrap The HTTP token's wrap data.
+ @param[in] HttpMsg The HTTP message data.
+
+ @retval EFI_SUCCESS The HTTP body is received.
+ @retval Others Other error as indicated.
+
+**/
+EFI_STATUS
+HttpTcpReceiveBody (
+ IN HTTP_TOKEN_WRAP *Wrap,
+ IN EFI_HTTP_MESSAGE *HttpMsg
+ );
+
+/**
+ Clean up Tcp Tokens while the Tcp transmission error occurs.
+
+ @param[in] Wrap Pointer to HTTP token's wrap data.
+
+**/
+VOID
+HttpTcpTokenCleanup (
+ IN HTTP_TOKEN_WRAP *Wrap
+ );
+
+/**
Generate HTTP request string.
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.