diff options
author | Jiaxin Wu <jiaxin.wu@intel.com> | 2016-04-26 16:46:33 +0800 |
---|---|---|
committer | Jiaxin Wu <jiaxin.wu@intel.com> | 2016-04-28 16:27:42 +0800 |
commit | b347a22aecbfac9aac47831fee9a30aa810d6d0b (patch) | |
tree | 59b07a700a7a76fb6e55f28da1d1bf51410aa1be /NetworkPkg/HttpDxe | |
parent | 467d5f6b30bcd2bb73bfaafc31118944d95ec28e (diff) | |
download | edk2-b347a22aecbfac9aac47831fee9a30aa810d6d0b.tar.gz edk2-b347a22aecbfac9aac47831fee9a30aa810d6d0b.tar.bz2 edk2-b347a22aecbfac9aac47831fee9a30aa810d6d0b.zip |
NetworkPkg: Avoid the indefinite wait case in HttpDxe
Need the timer check to avoid the indefinite wait case
in HttpDxe driver
A.HTTP receive Header process in HttpTcpReceiveHeader();
B.HTTP receive Body process in HttpTcpReceiveBody();
Cc: Hegde Nagaraj P <nagaraj-p.hegde@hpe.com>
Cc: El-Haj-Mahmoud Samer <samer.el-haj-mahmoud@hpe.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
Reviewed-by: Hegde Nagaraj P <nagaraj-p.hegde@hpe.com>
Reviewed-by: Fu Siyuan <siyuan.fu@intel.com>
Diffstat (limited to 'NetworkPkg/HttpDxe')
-rw-r--r-- | NetworkPkg/HttpDxe/HttpImpl.c | 60 | ||||
-rw-r--r-- | NetworkPkg/HttpDxe/HttpProto.c | 59 | ||||
-rw-r--r-- | NetworkPkg/HttpDxe/HttpProto.h | 15 |
3 files changed, 117 insertions, 17 deletions
diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c index 553b79cca0..7a236f40e0 100644 --- a/NetworkPkg/HttpDxe/HttpImpl.c +++ b/NetworkPkg/HttpDxe/HttpImpl.c @@ -176,6 +176,7 @@ EfiHttpConfigure ( sizeof (HttpInstance->IPv4Node)
);
}
+
//
// Creat Tcp child
//
@@ -897,7 +898,35 @@ HttpResponseWorker ( HttpInstance->EndofHeader = &EndofHeader;
HttpInstance->HttpHeaders = &HttpHeaders;
- Status = HttpTcpReceiveHeader (HttpInstance, &SizeofHeaders, &BufferSize);
+
+ if (HttpInstance->TimeoutEvent == NULL) {
+ //
+ // Create TimeoutEvent for response
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ TPL_CALLBACK,
+ NULL,
+ NULL,
+ &HttpInstance->TimeoutEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ }
+
+ //
+ // Start the timer, and wait Timeout seconds to receive the header packet.
+ //
+ Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_RESPONSE_TIMEOUT * TICKS_PER_SECOND);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ Status = HttpTcpReceiveHeader (HttpInstance, &SizeofHeaders, &BufferSize, HttpInstance->TimeoutEvent);
+
+ gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);
+
if (EFI_ERROR (Status)) {
goto Error;
}
@@ -1098,10 +1127,37 @@ HttpResponseWorker ( ASSERT (HttpInstance->MsgParser != NULL);
+ if (HttpInstance->TimeoutEvent == NULL) {
+ //
+ // Create TimeoutEvent for response
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ TPL_CALLBACK,
+ NULL,
+ NULL,
+ &HttpInstance->TimeoutEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ }
+
+ //
+ // Start the timer, and wait Timeout seconds to receive the body packet.
+ //
+ Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_RESPONSE_TIMEOUT * TICKS_PER_SECOND);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
//
// We still need receive more data when there is no cache data and MsgParser is not NULL;
//
- Status = HttpTcpReceiveBody (Wrap, HttpMsg);
+ Status = HttpTcpReceiveBody (Wrap, HttpMsg, HttpInstance->TimeoutEvent);
+
+ gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);
+
if (EFI_ERROR (Status)) {
goto Error;
}
diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c index 9b3c774ae2..06f3bb6860 100644 --- a/NetworkPkg/HttpDxe/HttpProto.c +++ b/NetworkPkg/HttpDxe/HttpProto.c @@ -815,6 +815,11 @@ HttpCleanProtocol ( HttpCloseTcpConnCloseEvent (HttpInstance);
+ if (HttpInstance->TimeoutEvent != NULL) {
+ gBS->CloseEvent (HttpInstance->TimeoutEvent);
+ HttpInstance->TimeoutEvent = NULL;
+ }
+
if (HttpInstance->CacheBody != NULL) {
FreePool (HttpInstance->CacheBody);
HttpInstance->CacheBody = NULL;
@@ -1541,6 +1546,7 @@ HttpTcpReceive ( @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.
+ @param[in] Timeout The time to wait for receiving the header packet.
@retval EFI_SUCCESS The HTTP header is received.
@retval Others Other errors as indicated.
@@ -1550,7 +1556,8 @@ EFI_STATUS HttpTcpReceiveHeader (
IN HTTP_PROTOCOL *HttpInstance,
IN OUT UINTN *SizeofHeaders,
- IN OUT UINTN *BufferSize
+ IN OUT UINTN *BufferSize,
+ IN EFI_EVENT Timeout
)
{
EFI_STATUS Status;
@@ -1599,9 +1606,14 @@ HttpTcpReceiveHeader ( return Status;
}
- while (!HttpInstance->IsRxDone) {
- Tcp4->Poll (Tcp4);
- }
+ while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
+ Tcp4->Poll (Tcp4);
+ }
+
+ if (!HttpInstance->IsRxDone) {
+ gBS->CloseEvent (Rx4Token->CompletionToken.Event);
+ Rx4Token->CompletionToken.Status = EFI_TIMEOUT;
+ }
Status = Rx4Token->CompletionToken.Status;
if (EFI_ERROR (Status)) {
@@ -1660,9 +1672,14 @@ HttpTcpReceiveHeader ( return Status;
}
- while (!HttpInstance->IsRxDone) {
- Tcp6->Poll (Tcp6);
- }
+ while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
+ Tcp6->Poll (Tcp6);
+ }
+
+ if (!HttpInstance->IsRxDone) {
+ gBS->CloseEvent (Rx6Token->CompletionToken.Event);
+ Rx6Token->CompletionToken.Status = EFI_TIMEOUT;
+ }
Status = Rx6Token->CompletionToken.Status;
if (EFI_ERROR (Status)) {
@@ -1715,6 +1732,7 @@ HttpTcpReceiveHeader ( @param[in] Wrap The HTTP token's wrap data.
@param[in] HttpMsg The HTTP message data.
+ @param[in] Timeout The time to wait for receiving the body packet.
@retval EFI_SUCCESS The HTTP body is received.
@retval Others Other error as indicated.
@@ -1723,7 +1741,8 @@ HttpTcpReceiveHeader ( EFI_STATUS
HttpTcpReceiveBody (
IN HTTP_TOKEN_WRAP *Wrap,
- IN EFI_HTTP_MESSAGE *HttpMsg
+ IN EFI_HTTP_MESSAGE *HttpMsg,
+ IN EFI_EVENT Timeout
)
{
EFI_STATUS Status;
@@ -1738,7 +1757,6 @@ HttpTcpReceiveBody ( Tcp6 = HttpInstance->Tcp6;
Rx4Token = NULL;
Rx6Token = NULL;
-
if (HttpInstance->LocalAddressIsIPv6) {
ASSERT (Tcp6 != NULL);
@@ -1758,7 +1776,17 @@ HttpTcpReceiveBody ( DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));
return Status;
}
-
+
+ while (!Wrap->TcpWrap.IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
+ Tcp6->Poll (Tcp6);
+ }
+
+ if (!Wrap->TcpWrap.IsRxDone) {
+ gBS->CloseEvent (Rx6Token->CompletionToken.Event);
+ Rx6Token->CompletionToken.Status = EFI_TIMEOUT;
+ Wrap->HttpToken->Status = Rx6Token->CompletionToken.Status;
+ gBS->SignalEvent (Wrap->HttpToken->Event);
+ }
} else {
Rx4Token = &Wrap->TcpWrap.Rx4Token;
Rx4Token->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;
@@ -1771,6 +1799,17 @@ HttpTcpReceiveBody ( DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));
return Status;
}
+
+ while (!Wrap->TcpWrap.IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
+ Tcp4->Poll (Tcp4);
+ }
+
+ if (!Wrap->TcpWrap.IsRxDone) {
+ gBS->CloseEvent (Rx4Token->CompletionToken.Event);
+ Rx4Token->CompletionToken.Status = EFI_TIMEOUT;
+ Wrap->HttpToken->Status = Rx4Token->CompletionToken.Status;
+ gBS->SignalEvent (Wrap->HttpToken->Event);
+ }
}
return EFI_SUCCESS;
diff --git a/NetworkPkg/HttpDxe/HttpProto.h b/NetworkPkg/HttpDxe/HttpProto.h index 7b4b343b2a..8b47fe00f6 100644 --- a/NetworkPkg/HttpDxe/HttpProto.h +++ b/NetworkPkg/HttpDxe/HttpProto.h @@ -47,6 +47,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #define HTTP_BUFFER_SIZE_DEAULT 65535
#define HTTP_MAX_SYN_BACK_LOG 5
#define HTTP_CONNECTION_TIMEOUT 60
+#define HTTP_RESPONSE_TIMEOUT 5
#define HTTP_DATA_RETRIES 12
#define HTTP_FIN_TIMEOUT 2
#define HTTP_KEEP_ALIVE_PROBES 6
@@ -93,6 +94,8 @@ typedef struct _HTTP_PROTOCOL { UINTN StatusCode;
+ EFI_EVENT TimeoutEvent;
+
EFI_HANDLE Tcp4ChildHandle;
EFI_TCP4_PROTOCOL *Tcp4;
EFI_TCP4_CONFIG_DATA Tcp4CfgData;
@@ -116,9 +119,7 @@ typedef struct _HTTP_PROTOCOL { EFI_TCP6_CLOSE_TOKEN Tcp6CloseToken;
BOOLEAN IsTcp6CloseDone;
EFI_IPv6_ADDRESS RemoteIpv6Addr;
-
-
-
+
//
// Rx4Token or Rx6Token used for receiving HTTP header.
//
@@ -504,6 +505,7 @@ HttpTcpReceive ( @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.
+ @param[in] Timeout The time to wait for receiving the header packet.
@retval EFI_SUCCESS The HTTP header is received.
@retval Others Other errors as indicated.
@@ -513,7 +515,8 @@ EFI_STATUS HttpTcpReceiveHeader (
IN HTTP_PROTOCOL *HttpInstance,
IN OUT UINTN *SizeofHeaders,
- IN OUT UINTN *BufferSize
+ IN OUT UINTN *BufferSize,
+ IN EFI_EVENT Timeout
);
/**
@@ -521,6 +524,7 @@ HttpTcpReceiveHeader ( @param[in] Wrap The HTTP token's wrap data.
@param[in] HttpMsg The HTTP message data.
+ @param[in] Timeout The time to wait for receiving the body packet.
@retval EFI_SUCCESS The HTTP body is received.
@retval Others Other error as indicated.
@@ -529,7 +533,8 @@ HttpTcpReceiveHeader ( EFI_STATUS
HttpTcpReceiveBody (
IN HTTP_TOKEN_WRAP *Wrap,
- IN EFI_HTTP_MESSAGE *HttpMsg
+ IN EFI_HTTP_MESSAGE *HttpMsg,
+ IN EFI_EVENT Timeout
);
/**
|