diff options
author | Zhang Lubo <lubo.zhang@intel.com> | 2015-11-18 08:36:42 +0000 |
---|---|---|
committer | vanjeff <vanjeff@Edk2> | 2015-11-18 08:36:42 +0000 |
commit | 0e772049c65ad249b70808b456fc7f8ad694b275 (patch) | |
tree | a49069a7b7b707ff5b00397dfdd435696eea095f /NetworkPkg/HttpDxe/HttpProto.c | |
parent | ba82c72fc4d4f9230d3bf5d0a69b14e44d5105cf (diff) | |
download | edk2-platforms-0e772049c65ad249b70808b456fc7f8ad694b275.tar.xz |
NetworkPkg:Enable Http Boot over Ipv6 stack
Add new features to support Http boot over ipv6 stack.
(Sync patch r18743 from main trunk.)
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/branches/UDK2015@18874 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'NetworkPkg/HttpDxe/HttpProto.c')
-rw-r--r-- | NetworkPkg/HttpDxe/HttpProto.c | 1249 |
1 files changed, 1056 insertions, 193 deletions
diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c index 13d5748378..c4ffef2bc2 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,7 +387,7 @@ HttpCloseTcp4ConnCloseEvent ( **/
EFI_STATUS
-HttpCreateTcp4TxEvent (
+HttpCreateTcpTxEvent (
IN HTTP_TOKEN_WRAP *Wrap
)
{
@@ -313,28 +398,50 @@ HttpCreateTcp4TxEvent ( 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.
@@ -343,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.
@@ -378,7 +504,7 @@ HttpCreateTcp4RxEventForHeader ( **/
EFI_STATUS
-HttpCreateTcp4RxEvent (
+HttpCreateTcpRxEvent (
IN HTTP_TOKEN_WRAP *Wrap
)
{
@@ -388,30 +514,91 @@ HttpCreateTcp4RxEvent ( 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.
@@ -419,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
+ );
+
+ 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 Status;
+ return EFI_UNSUPPORTED;
}
@@ -524,7 +814,7 @@ HttpCleanProtocol ( {
HttpCloseConnection (HttpInstance);
- HttpCloseTcp4ConnCloseEvent (HttpInstance);
+ HttpCloseTcpConnCloseEvent (HttpInstance);
if (HttpInstance->CacheBody != NULL) {
FreePool (HttpInstance->CacheBody);
@@ -541,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
@@ -569,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
+ );
+ }
+
}
/**
@@ -591,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;
}
@@ -635,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;
@@ -716,12 +1076,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;
}
@@ -729,10 +1159,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.
@@ -775,7 +1206,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.
@@ -787,7 +1316,7 @@ HttpConnectTcp4 ( **/
EFI_STATUS
-HttpTransmitTcp4 (
+HttpTransmitTcp (
IN HTTP_PROTOCOL *HttpInstance,
IN HTTP_TOKEN_WRAP *Wrap,
IN UINT8 *TxString,
@@ -795,23 +1324,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;
}
@@ -919,7 +1469,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.
@@ -953,9 +1503,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.
@@ -985,7 +1535,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.
@@ -1038,7 +1588,7 @@ HttpTcpTransmit ( //
// Transmit the request message.
//
- Status = HttpTransmitTcp4 (
+ Status = HttpTransmitTcp (
ValueInItem->HttpInstance,
ValueInItem,
(UINT8*) RequestStr,
@@ -1051,7 +1601,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.
@@ -1075,6 +1625,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.
|