X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=NetworkPkg%2FHttpDxe%2FHttpProto.c;h=d7fe271168fe29b41eb9dbb154fdf2719371b510;hp=06f3bb686061c8c62310fe99dc07c8b07dfd31cf;hb=328141fcbe6a50e57175e2edd67a7acb2e9b6ab3;hpb=b347a22aecbfac9aac47831fee9a30aa810d6d0b diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c index 06f3bb6860..d7fe271168 100644 --- a/NetworkPkg/HttpDxe/HttpProto.c +++ b/NetworkPkg/HttpDxe/HttpProto.c @@ -1,7 +1,7 @@ /** @file Miscellaneous routines for HttpDxe driver. -Copyright (c) 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
(C) Copyright 2016 Hewlett Packard Enterprise Development LP
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -148,21 +148,41 @@ HttpTcpReceiveNotifyDpc ( if (UsingIpv6) { gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event); + Wrap->TcpWrap.Rx6Token.CompletionToken.Event = NULL; if (EFI_ERROR (Wrap->TcpWrap.Rx6Token.CompletionToken.Status)) { + DEBUG ((EFI_D_ERROR, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap->TcpWrap.Rx6Token.CompletionToken.Status)); Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status; gBS->SignalEvent (Wrap->HttpToken->Event); + + Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken); + if (Item != NULL) { + NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL); + } + FreePool (Wrap); + Wrap = NULL; + return ; } } else { gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event); + Wrap->TcpWrap.Rx4Token.CompletionToken.Event = NULL; if (EFI_ERROR (Wrap->TcpWrap.Rx4Token.CompletionToken.Status)) { + DEBUG ((EFI_D_ERROR, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap->TcpWrap.Rx4Token.CompletionToken.Status)); Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status; gBS->SignalEvent (Wrap->HttpToken->Event); + + Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken); + if (Item != NULL) { + NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL); + } + FreePool (Wrap); + Wrap = NULL; + return ; } } @@ -234,8 +254,9 @@ HttpTcpReceiveNotifyDpc ( // Check pending RxTokens and receive the HTTP message. // NetMapIterate (&Wrap->HttpInstance->RxTokens, HttpTcpReceive, NULL); - + FreePool (Wrap); + Wrap = NULL; } /** @@ -412,15 +433,15 @@ HttpCreateTcpTxEvent ( 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; + 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; } else { Status = gBS->CreateEvent ( @@ -440,7 +461,6 @@ HttpCreateTcpTxEvent ( TcpWrap->Tx6Token.Packet.TxData = &Wrap->TcpWrap.Tx6Data; TcpWrap->Tx6Token.CompletionToken.Status =EFI_NOT_READY; - } return EFI_SUCCESS; @@ -622,7 +642,7 @@ HttpInitProtocol ( // Status = NetLibCreateServiceChild ( HttpInstance->Service->ControllerHandle, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip4DriverBindingHandle, &gEfiTcp4ServiceBindingProtocolGuid, &HttpInstance->Tcp4ChildHandle ); @@ -635,7 +655,7 @@ HttpInitProtocol ( HttpInstance->Tcp4ChildHandle, &gEfiTcp4ProtocolGuid, (VOID **) &Interface, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip4DriverBindingHandle, HttpInstance->Service->ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); @@ -648,7 +668,7 @@ HttpInitProtocol ( HttpInstance->Tcp4ChildHandle, &gEfiTcp4ProtocolGuid, (VOID **) &HttpInstance->Tcp4, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip4DriverBindingHandle, HttpInstance->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); @@ -660,7 +680,7 @@ HttpInitProtocol ( HttpInstance->Service->Tcp4ChildHandle, &gEfiTcp4ProtocolGuid, (VOID **) &Interface, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip4DriverBindingHandle, HttpInstance->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); @@ -673,7 +693,7 @@ HttpInitProtocol ( // Status = NetLibCreateServiceChild ( HttpInstance->Service->ControllerHandle, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip6DriverBindingHandle, &gEfiTcp6ServiceBindingProtocolGuid, &HttpInstance->Tcp6ChildHandle ); @@ -686,7 +706,7 @@ HttpInitProtocol ( HttpInstance->Tcp6ChildHandle, &gEfiTcp6ProtocolGuid, (VOID **) &Interface, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip6DriverBindingHandle, HttpInstance->Service->ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); @@ -699,7 +719,7 @@ HttpInitProtocol ( HttpInstance->Tcp6ChildHandle, &gEfiTcp6ProtocolGuid, (VOID **) &HttpInstance->Tcp6, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip6DriverBindingHandle, HttpInstance->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); @@ -712,7 +732,7 @@ HttpInitProtocol ( HttpInstance->Service->Tcp6ChildHandle, &gEfiTcp6ProtocolGuid, (VOID **) &Interface, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip6DriverBindingHandle, HttpInstance->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); @@ -736,20 +756,20 @@ ON_ERROR: gBS->CloseProtocol ( HttpInstance->Tcp4ChildHandle, &gEfiTcp4ProtocolGuid, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip4DriverBindingHandle, HttpInstance->Service->ControllerHandle ); gBS->CloseProtocol ( HttpInstance->Tcp4ChildHandle, &gEfiTcp4ProtocolGuid, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip4DriverBindingHandle, HttpInstance->Handle ); NetLibDestroyServiceChild ( HttpInstance->Service->ControllerHandle, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip4DriverBindingHandle, &gEfiTcp4ServiceBindingProtocolGuid, HttpInstance->Tcp4ChildHandle ); @@ -759,7 +779,7 @@ ON_ERROR: gBS->CloseProtocol ( HttpInstance->Service->Tcp4ChildHandle, &gEfiTcp4ProtocolGuid, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip4DriverBindingHandle, HttpInstance->Handle ); } @@ -768,20 +788,20 @@ ON_ERROR: gBS->CloseProtocol ( HttpInstance->Tcp6ChildHandle, &gEfiTcp6ProtocolGuid, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip6DriverBindingHandle, HttpInstance->Service->ControllerHandle ); gBS->CloseProtocol ( HttpInstance->Tcp6ChildHandle, &gEfiTcp6ProtocolGuid, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip6DriverBindingHandle, HttpInstance->Handle ); NetLibDestroyServiceChild ( HttpInstance->Service->ControllerHandle, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip6DriverBindingHandle, &gEfiTcp6ServiceBindingProtocolGuid, HttpInstance->Tcp6ChildHandle ); @@ -791,7 +811,7 @@ ON_ERROR: gBS->CloseProtocol ( HttpInstance->Service->Tcp6ChildHandle, &gEfiTcp6ProtocolGuid, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip6DriverBindingHandle, HttpInstance->Handle ); } @@ -844,24 +864,31 @@ HttpCleanProtocol ( NetMapClean (&HttpInstance->TxTokens); NetMapClean (&HttpInstance->RxTokens); + if (HttpInstance->TlsSb != NULL && HttpInstance->TlsChildHandle != NULL) { + // + // Destroy the TLS instance. + // + HttpInstance->TlsSb->DestroyChild (HttpInstance->TlsSb, HttpInstance->TlsChildHandle); + } + if (HttpInstance->Tcp4ChildHandle != NULL) { gBS->CloseProtocol ( HttpInstance->Tcp4ChildHandle, &gEfiTcp4ProtocolGuid, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip4DriverBindingHandle, HttpInstance->Service->ControllerHandle ); gBS->CloseProtocol ( HttpInstance->Tcp4ChildHandle, &gEfiTcp4ProtocolGuid, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip4DriverBindingHandle, HttpInstance->Handle ); NetLibDestroyServiceChild ( HttpInstance->Service->ControllerHandle, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip4DriverBindingHandle, &gEfiTcp4ServiceBindingProtocolGuid, HttpInstance->Tcp4ChildHandle ); @@ -871,7 +898,7 @@ HttpCleanProtocol ( gBS->CloseProtocol ( HttpInstance->Service->Tcp4ChildHandle, &gEfiTcp4ProtocolGuid, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip4DriverBindingHandle, HttpInstance->Handle ); } @@ -880,20 +907,20 @@ HttpCleanProtocol ( gBS->CloseProtocol ( HttpInstance->Tcp6ChildHandle, &gEfiTcp6ProtocolGuid, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip6DriverBindingHandle, HttpInstance->Service->ControllerHandle ); gBS->CloseProtocol ( HttpInstance->Tcp6ChildHandle, &gEfiTcp6ProtocolGuid, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip6DriverBindingHandle, HttpInstance->Handle ); NetLibDestroyServiceChild ( HttpInstance->Service->ControllerHandle, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip6DriverBindingHandle, &gEfiTcp6ServiceBindingProtocolGuid, HttpInstance->Tcp6ChildHandle ); @@ -903,11 +930,12 @@ HttpCleanProtocol ( gBS->CloseProtocol ( HttpInstance->Service->Tcp6ChildHandle, &gEfiTcp6ProtocolGuid, - HttpInstance->Service->ImageHandle, + HttpInstance->Service->Ip6DriverBindingHandle, HttpInstance->Handle ); } - + + TlsCloseTxRxEvent (HttpInstance); } /** @@ -1165,7 +1193,8 @@ HttpConfigureTcp6 ( } /** - Check existing TCP connection, if in error state, recover TCP4 connection. + Check existing TCP connection, if in error state, recover TCP4 connection. Then, + connect one TLS session if required. @param[in] HttpInstance The HTTP instance private data. @@ -1206,11 +1235,58 @@ HttpConnectTcp4 ( HttpCloseConnection(HttpInstance); } - return HttpCreateConnection (HttpInstance); + Status = HttpCreateConnection (HttpInstance); + if (EFI_ERROR(Status)){ + DEBUG ((EFI_D_ERROR, "Tcp4 Connection fail - %x\n", Status)); + return Status; + } + + // + // Tls session connection. + // + if (HttpInstance->UseHttps) { + if (HttpInstance->TimeoutEvent == NULL) { + // + // Create TimeoutEvent for TLS connection. + // + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &HttpInstance->TimeoutEvent + ); + if (EFI_ERROR (Status)) { + TlsCloseTxRxEvent (HttpInstance); + return Status; + } + } + + // + // Start the timer, and wait Timeout seconds for connection. + // + Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND); + if (EFI_ERROR (Status)) { + TlsCloseTxRxEvent (HttpInstance); + return Status; + } + + Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent); + + gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0); + + if (EFI_ERROR (Status)) { + TlsCloseTxRxEvent (HttpInstance); + return Status; + } + } + + return Status; } /** - Check existing TCP connection, if in error state, recover TCP6 connection. + Check existing TCP connection, if in error state, recover TCP6 connection. Then, + connect one TLS session if required. @param[in] HttpInstance The HTTP instance private data. @@ -1251,30 +1327,88 @@ HttpConnectTcp6 ( HttpCloseConnection(HttpInstance); } - return HttpCreateConnection (HttpInstance); + Status = HttpCreateConnection (HttpInstance); + if (EFI_ERROR(Status)){ + DEBUG ((EFI_D_ERROR, "Tcp6 Connection fail - %x\n", Status)); + return Status; + } + + // + // Tls session connection. + // + if (HttpInstance->UseHttps) { + if (HttpInstance->TimeoutEvent == NULL) { + // + // Create TimeoutEvent for TLS connection. + // + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &HttpInstance->TimeoutEvent + ); + if (EFI_ERROR (Status)) { + TlsCloseTxRxEvent (HttpInstance); + return Status; + } + } + + // + // Start the timer, and wait Timeout seconds for connection. + // + Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND); + if (EFI_ERROR (Status)) { + TlsCloseTxRxEvent (HttpInstance); + return Status; + } + + Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent); + + gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0); + + if (EFI_ERROR (Status)) { + TlsCloseTxRxEvent (HttpInstance); + return Status; + } + } + + return Status; } /** - Initialize TCP related data. + Initialize Http session. @param[in] HttpInstance The HTTP instance private data. @param[in] Wrap The HTTP token's wrap data. - @param[in] Configure The Flag indicates whether the first time to initialize Tcp. + @param[in] Configure The Flag indicates whether need to initialize session. + @param[in] TlsConfigure The Flag indicates whether it's the new Tls session. - @retval EFI_SUCCESS The initialization of TCP instance is done. + @retval EFI_SUCCESS The initialization of session is done. @retval Others Other error as indicated. **/ EFI_STATUS -HttpInitTcp ( +HttpInitSession ( IN HTTP_PROTOCOL *HttpInstance, IN HTTP_TOKEN_WRAP *Wrap, - IN BOOLEAN Configure + IN BOOLEAN Configure, + IN BOOLEAN TlsConfigure ) { EFI_STATUS Status; ASSERT (HttpInstance != NULL); + // + // Configure Tls session. + // + if (TlsConfigure) { + Status = TlsConfigureSession (HttpInstance); + if (EFI_ERROR (Status)) { + return Status; + } + } + if (!HttpInstance->LocalAddressIsIPv6) { // // Configure TCP instance. @@ -1318,7 +1452,7 @@ HttpInitTcp ( } /** - Send the HTTP message through TCP4 or TCP6. + Send the HTTP or HTTPS message through TCP4 or TCP6. @param[in] HttpInstance The HTTP instance private data. @param[in] Wrap The HTTP token's wrap data. @@ -1342,14 +1476,66 @@ HttpTransmitTcp ( EFI_TCP4_PROTOCOL *Tcp4; EFI_TCP6_IO_TOKEN *Tx6Token; EFI_TCP6_PROTOCOL *Tcp6; + UINT8 *Buffer; + UINTN BufferSize; + NET_FRAGMENT TempFragment; + + Status = EFI_SUCCESS; + Buffer = NULL; + TempFragment.Len = 0; + TempFragment.Bulk = NULL; + + // + // Need to encrypt data. + // + if (HttpInstance->UseHttps) { + // + // Build BufferOut data + // + BufferSize = sizeof (TLS_RECORD_HEADER) + TxStringLen; + Buffer = AllocateZeroPool (BufferSize); + if (Buffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + return Status; + } + ((TLS_RECORD_HEADER *) Buffer)->ContentType = TlsContentTypeApplicationData; + ((TLS_RECORD_HEADER *) Buffer)->Version.Major = HttpInstance->TlsConfigData.Version.Major; + ((TLS_RECORD_HEADER *) Buffer)->Version.Minor = HttpInstance->TlsConfigData.Version.Minor; + ((TLS_RECORD_HEADER *) Buffer)->Length = (UINT16) (TxStringLen); + CopyMem (Buffer + sizeof (TLS_RECORD_HEADER), TxString, TxStringLen); + + // + // Encrypt Packet. + // + Status = TlsProcessMessage ( + HttpInstance, + Buffer, + BufferSize, + EfiTlsEncrypt, + &TempFragment + ); + + FreePool (Buffer); + + if (EFI_ERROR (Status)) { + return Status; + } + } - if (!HttpInstance->LocalAddressIsIPv6) { + if (!HttpInstance->LocalAddressIsIPv6) { Tcp4 = HttpInstance->Tcp4; Tx4Token = &Wrap->TcpWrap.Tx4Token; + + if (HttpInstance->UseHttps) { + Tx4Token->Packet.TxData->DataLength = TempFragment.Len; + Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = TempFragment.Len; + Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TempFragment.Bulk; + } else { + Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen; + Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen; + Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString; + } - 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; @@ -1362,10 +1548,17 @@ HttpTransmitTcp ( } else { Tcp6 = HttpInstance->Tcp6; Tx6Token = &Wrap->TcpWrap.Tx6Token; - - Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen; - Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen; - Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString; + + if (HttpInstance->UseHttps) { + Tx6Token->Packet.TxData->DataLength = TempFragment.Len; + Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = TempFragment.Len; + Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TempFragment.Bulk; + } else { + 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; @@ -1376,7 +1569,6 @@ HttpTransmitTcp ( } } - return Status; } @@ -1446,7 +1638,7 @@ HttpTcpNotReady ( } /** - Transmit the HTTP mssage by processing the associated HTTP token. + Transmit the HTTP or HTTPS mssage by processing the associated HTTP token. @param[in] Map The container of Tx4Token or Tx6Token. @param[in] Item Current item to check against. @@ -1469,8 +1661,11 @@ HttpTcpTransmit ( EFI_STATUS Status; CHAR8 *RequestMsg; CHAR8 *Url; + UINTN UrlSize; UINTN RequestMsgSize; + RequestMsg = NULL; + ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value; if (ValueInItem->TcpWrap.IsTxDone) { return EFI_SUCCESS; @@ -1479,12 +1674,13 @@ HttpTcpTransmit ( // // Parse the URI of the remote host. // - Url = AllocatePool (StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1); + UrlSize = StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1; + Url = AllocatePool (UrlSize); if (Url == NULL) { return EFI_OUT_OF_RESOURCES; } - UnicodeStrToAsciiStr (ValueInItem->HttpToken->Message->Data.Request->Url, Url); + UnicodeStrToAsciiStrS (ValueInItem->HttpToken->Message->Data.Request->Url, Url, UrlSize); // // Create request message. @@ -1497,10 +1693,12 @@ HttpTcpTransmit ( ); FreePool (Url); - if (EFI_ERROR (Status)){ + if (EFI_ERROR (Status) || NULL == RequestMsg){ return Status; } + ASSERT (RequestMsg != NULL); + // // Transmit the request message. // @@ -1568,6 +1766,7 @@ HttpTcpReceiveHeader ( CHAR8 **EndofHeader; CHAR8 **HttpHeaders; CHAR8 *Buffer; + NET_FRAGMENT Fragment; ASSERT (HttpInstance != NULL); @@ -1578,6 +1777,8 @@ HttpTcpReceiveHeader ( Buffer = NULL; Rx4Token = NULL; Rx6Token = NULL; + Fragment.Len = 0; + Fragment.Bulk = NULL; if (HttpInstance->LocalAddressIsIPv6) { ASSERT (Tcp6 != NULL); @@ -1585,144 +1786,219 @@ HttpTcpReceiveHeader ( 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; + if (!HttpInstance->UseHttps) { + Status = HttpCreateTcpRxEventForHeader (HttpInstance); + if (EFI_ERROR (Status)) { return Status; } + } + + if (!HttpInstance->LocalAddressIsIPv6) { + if (!HttpInstance->UseHttps) { + 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 && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) { - Tcp4->Poll (Tcp4); + while (*EndofHeader == NULL) { + if (!HttpInstance->UseHttps) { + 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 && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) { + Tcp4->Poll (Tcp4); + } + + if (!HttpInstance->IsRxDone) { + // + // Cancle the Token before close its Event. + // + Tcp4->Cancel (HttpInstance->Tcp4, &Rx4Token->CompletionToken); + gBS->CloseEvent (Rx4Token->CompletionToken.Event); + Rx4Token->CompletionToken.Status = EFI_TIMEOUT; + } + + Status = Rx4Token->CompletionToken.Status; + if (EFI_ERROR (Status)) { + return Status; + } + + Fragment.Len = Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength; + Fragment.Bulk = (UINT8 *) Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer; + } else { + if (Fragment.Bulk != NULL) { + FreePool (Fragment.Bulk); + Fragment.Bulk = NULL; + } + + Status = HttpsReceive (HttpInstance, &Fragment, Timeout); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status)); + return Status; + } } - if (!HttpInstance->IsRxDone) { - gBS->CloseEvent (Rx4Token->CompletionToken.Event); - Rx4Token->CompletionToken.Status = EFI_TIMEOUT; - } - - Status = Rx4Token->CompletionToken.Status; - if (EFI_ERROR (Status)) { - return Status; - } - // // Append the response string. // - *BufferSize = (*SizeofHeaders) + Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength; + *BufferSize = *SizeofHeaders + Fragment.Len; Buffer = AllocateZeroPool (*BufferSize); if (Buffer == NULL) { Status = EFI_OUT_OF_RESOURCES; return Status; } - + if (*HttpHeaders != NULL) { - CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders)); + CopyMem (Buffer, *HttpHeaders, *SizeofHeaders); FreePool (*HttpHeaders); } - + CopyMem ( - Buffer + (*SizeofHeaders), - Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer, - Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength + Buffer + *SizeofHeaders, + Fragment.Bulk, + Fragment.Len ); - *HttpHeaders = Buffer; - *SizeofHeaders = *BufferSize; - + *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; + *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); + }; + // + // Free the buffer. + // + if (Rx4Token != NULL && Rx4Token->Packet.RxData != NULL && Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) { + FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer); + Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; + Fragment.Bulk = NULL; + } + + if (Fragment.Bulk != NULL) { + FreePool (Fragment.Bulk); + Fragment.Bulk = 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; + if (!HttpInstance->UseHttps) { + 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 && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) { - Tcp6->Poll (Tcp6); + while (*EndofHeader == NULL) { + if (!HttpInstance->UseHttps) { + 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 && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) { + Tcp6->Poll (Tcp6); + } + + if (!HttpInstance->IsRxDone) { + // + // Cancle the Token before close its Event. + // + Tcp6->Cancel (HttpInstance->Tcp6, &Rx6Token->CompletionToken); + gBS->CloseEvent (Rx6Token->CompletionToken.Event); + Rx6Token->CompletionToken.Status = EFI_TIMEOUT; + } + + Status = Rx6Token->CompletionToken.Status; + if (EFI_ERROR (Status)) { + return Status; + } + + Fragment.Len = Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength; + Fragment.Bulk = (UINT8 *) Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer; + } else { + if (Fragment.Bulk != NULL) { + FreePool (Fragment.Bulk); + Fragment.Bulk = NULL; + } + + Status = HttpsReceive (HttpInstance, &Fragment, Timeout); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status)); + return Status; + } } - if (!HttpInstance->IsRxDone) { - gBS->CloseEvent (Rx6Token->CompletionToken.Event); - Rx6Token->CompletionToken.Status = EFI_TIMEOUT; - } - - Status = Rx6Token->CompletionToken.Status; - if (EFI_ERROR (Status)) { - return Status; - } - // // Append the response string. // - *BufferSize = (*SizeofHeaders) + Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength; + *BufferSize = *SizeofHeaders + Fragment.Len; Buffer = AllocateZeroPool (*BufferSize); if (Buffer == NULL) { Status = EFI_OUT_OF_RESOURCES; return Status; } - + if (*HttpHeaders != NULL) { - CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders)); + CopyMem (Buffer, *HttpHeaders, *SizeofHeaders); FreePool (*HttpHeaders); } - + CopyMem ( - Buffer + (*SizeofHeaders), - Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer, - Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength + Buffer + *SizeofHeaders, + Fragment.Bulk, + Fragment.Len ); - *HttpHeaders = Buffer; - *SizeofHeaders = *BufferSize; - + *HttpHeaders = Buffer; + *SizeofHeaders = *BufferSize; + // // Check whether we received end of HTTP headers. // - *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); - + *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); + }; + + // + // Free the buffer. + // + if (Rx6Token != NULL && Rx6Token->Packet.RxData != NULL && Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) { + FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer); + Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; + Fragment.Bulk = NULL; + } + + if (Fragment.Bulk != NULL) { + FreePool (Fragment.Bulk); + Fragment.Bulk = NULL; } - 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); + *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR); + + *SizeofHeaders = *EndofHeader - *HttpHeaders; return EFI_SUCCESS; } @@ -1732,7 +2008,6 @@ 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. @@ -1741,8 +2016,7 @@ HttpTcpReceiveHeader ( EFI_STATUS HttpTcpReceiveBody ( IN HTTP_TOKEN_WRAP *Wrap, - IN EFI_HTTP_MESSAGE *HttpMsg, - IN EFI_EVENT Timeout + IN EFI_HTTP_MESSAGE *HttpMsg ) { EFI_STATUS Status; @@ -1766,8 +2040,8 @@ HttpTcpReceiveBody ( 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->DataLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength); + Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength); Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body; Rx6Token->CompletionToken.Status = EFI_NOT_READY; @@ -1776,21 +2050,10 @@ 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; - Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength; + Rx4Token->Packet.RxData->DataLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength); + Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength); Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body; Rx4Token->CompletionToken.Status = EFI_NOT_READY; @@ -1799,17 +2062,6 @@ 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; @@ -1837,45 +2089,45 @@ HttpTcpTokenCleanup ( Rx6Token = NULL; if (HttpInstance->LocalAddressIsIPv6) { - 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; + + if (Rx6Token->CompletionToken.Event != NULL) { + gBS->CloseEvent (Rx6Token->CompletionToken.Event); + Rx6Token->CompletionToken.Event = NULL; } - FreePool (Wrap); - if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) { - gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event); - HttpInstance->Rx6Token.CompletionToken.Event = NULL; - } + FreePool (Wrap); Rx6Token = &HttpInstance->Rx6Token; + + if (Rx6Token->CompletionToken.Event != NULL) { + gBS->CloseEvent (Rx6Token->CompletionToken.Event); + Rx6Token->CompletionToken.Event = NULL; + } + 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->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; + + if (Rx4Token->CompletionToken.Event != NULL) { + gBS->CloseEvent (Rx4Token->CompletionToken.Event); + Rx4Token->CompletionToken.Event = 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->CompletionToken.Event != NULL) { + gBS->CloseEvent (Rx4Token->CompletionToken.Event); + 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;