2 Miscellaneous routines for HttpDxe driver.
4 Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "HttpDriver.h"
13 The common notify function used in HTTP driver.
15 @param[in] Event The event signaled.
16 @param[in] Context The context.
26 if ((Event
== NULL
) || (Context
== NULL
)) {
30 *((BOOLEAN
*)Context
) = TRUE
;
34 The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().
36 @param[in] Context The context.
41 HttpTcpTransmitNotifyDpc (
45 HTTP_TOKEN_WRAP
*Wrap
;
46 HTTP_PROTOCOL
*HttpInstance
;
48 if (Context
== NULL
) {
52 Wrap
= (HTTP_TOKEN_WRAP
*)Context
;
53 HttpInstance
= Wrap
->HttpInstance
;
55 if (!HttpInstance
->LocalAddressIsIPv6
) {
56 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Tx4Token
.CompletionToken
.Status
;
57 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
62 if (Wrap
->TcpWrap
.Tx4Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
63 FreePool (Wrap
->TcpWrap
.Tx4Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
);
66 if (Wrap
->TcpWrap
.Tx4Token
.CompletionToken
.Event
!= NULL
) {
67 gBS
->CloseEvent (Wrap
->TcpWrap
.Tx4Token
.CompletionToken
.Event
);
70 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Status
;
71 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
76 if (Wrap
->TcpWrap
.Tx6Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
77 FreePool (Wrap
->TcpWrap
.Tx6Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
);
80 if (Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Event
!= NULL
) {
81 gBS
->CloseEvent (Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Event
);
85 Wrap
->TcpWrap
.IsTxDone
= TRUE
;
88 // Check pending TxTokens and sent out.
90 NetMapIterate (&Wrap
->HttpInstance
->TxTokens
, HttpTcpTransmit
, NULL
);
94 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.
96 @param Event The receive event delivered to TCP for transmit.
97 @param Context Context for the callback.
102 HttpTcpTransmitNotify (
108 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
110 QueueDpc (TPL_CALLBACK
, HttpTcpTransmitNotifyDpc
, Context
);
114 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().
116 @param[in] Context The context.
121 HttpTcpReceiveNotifyDpc (
125 HTTP_TOKEN_WRAP
*Wrap
;
129 HTTP_PROTOCOL
*HttpInstance
;
132 if (Context
== NULL
) {
136 Wrap
= (HTTP_TOKEN_WRAP
*)Context
;
137 HttpInstance
= Wrap
->HttpInstance
;
138 UsingIpv6
= HttpInstance
->LocalAddressIsIPv6
;
141 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
142 Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
= NULL
;
144 if (EFI_ERROR (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
)) {
145 DEBUG ((DEBUG_ERROR
, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
));
146 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
147 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
149 Item
= NetMapFindKey (&HttpInstance
->RxTokens
, Wrap
->HttpToken
);
151 NetMapRemoveItem (&HttpInstance
->RxTokens
, Item
, NULL
);
160 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
161 Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
= NULL
;
163 if (EFI_ERROR (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
)) {
164 DEBUG ((DEBUG_ERROR
, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
));
165 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
166 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
168 Item
= NetMapFindKey (&HttpInstance
->RxTokens
, Wrap
->HttpToken
);
170 NetMapRemoveItem (&HttpInstance
->RxTokens
, Item
, NULL
);
181 // Check whether we receive a complete HTTP message.
183 ASSERT (HttpInstance
->MsgParser
!= NULL
);
185 Length
= (UINTN
)Wrap
->TcpWrap
.Rx6Data
.FragmentTable
[0].FragmentLength
;
187 Length
= (UINTN
)Wrap
->TcpWrap
.Rx4Data
.FragmentTable
[0].FragmentLength
;
191 // Record the CallbackData data.
193 HttpInstance
->CallbackData
.Wrap
= (VOID
*)Wrap
;
194 HttpInstance
->CallbackData
.ParseData
= Wrap
->HttpToken
->Message
->Body
;
195 HttpInstance
->CallbackData
.ParseDataLength
= Length
;
198 // Parse Body with CallbackData data.
200 Status
= HttpParseMessageBody (
201 HttpInstance
->MsgParser
,
203 Wrap
->HttpToken
->Message
->Body
205 if (EFI_ERROR (Status
)) {
209 if (HttpIsMessageComplete (HttpInstance
->MsgParser
)) {
211 // Free the MsgParse since we already have a full HTTP message.
213 HttpFreeMsgParser (HttpInstance
->MsgParser
);
214 HttpInstance
->MsgParser
= NULL
;
217 Wrap
->HttpToken
->Message
->BodyLength
= Length
;
218 ASSERT (HttpInstance
->CacheBody
== NULL
);
220 // We receive part of header of next HTTP msg.
222 if (HttpInstance
->NextMsg
!= NULL
) {
223 Wrap
->HttpToken
->Message
->BodyLength
= HttpInstance
->NextMsg
-
224 (CHAR8
*)Wrap
->HttpToken
->Message
->Body
;
225 HttpInstance
->CacheLen
= Length
- Wrap
->HttpToken
->Message
->BodyLength
;
226 if (HttpInstance
->CacheLen
!= 0) {
227 HttpInstance
->CacheBody
= AllocateZeroPool (HttpInstance
->CacheLen
);
228 if (HttpInstance
->CacheBody
== NULL
) {
232 CopyMem (HttpInstance
->CacheBody
, HttpInstance
->NextMsg
, HttpInstance
->CacheLen
);
233 HttpInstance
->NextMsg
= HttpInstance
->CacheBody
;
234 HttpInstance
->CacheOffset
= 0;
238 Item
= NetMapFindKey (&Wrap
->HttpInstance
->RxTokens
, Wrap
->HttpToken
);
240 NetMapRemoveItem (&Wrap
->HttpInstance
->RxTokens
, Item
, NULL
);
243 Wrap
->TcpWrap
.IsRxDone
= TRUE
;
245 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
247 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
250 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
253 // Check pending RxTokens and receive the HTTP message.
255 NetMapIterate (&Wrap
->HttpInstance
->RxTokens
, HttpTcpReceive
, NULL
);
262 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.
264 @param Event The receive event delivered to TCP for receive.
265 @param Context Context for the callback.
270 HttpTcpReceiveNotify (
276 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
278 QueueDpc (TPL_CALLBACK
, HttpTcpReceiveNotifyDpc
, Context
);
282 Create events for the TCP connection token and TCP close token.
284 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
286 @retval EFI_SUCCESS The events are created successfully.
287 @retval others Other error as indicated.
291 HttpCreateTcpConnCloseEvent (
292 IN HTTP_PROTOCOL
*HttpInstance
297 if (!HttpInstance
->LocalAddressIsIPv6
) {
299 // Create events for various asynchronous operations.
301 Status
= gBS
->CreateEvent (
305 &HttpInstance
->IsTcp4ConnDone
,
306 &HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
308 if (EFI_ERROR (Status
)) {
313 // Initialize Tcp4CloseToken
315 Status
= gBS
->CreateEvent (
319 &HttpInstance
->IsTcp4CloseDone
,
320 &HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
322 if (EFI_ERROR (Status
)) {
327 // Create events for various asynchronous operations.
329 Status
= gBS
->CreateEvent (
333 &HttpInstance
->IsTcp6ConnDone
,
334 &HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
336 if (EFI_ERROR (Status
)) {
341 // Initialize Tcp6CloseToken
343 Status
= gBS
->CreateEvent (
347 &HttpInstance
->IsTcp6CloseDone
,
348 &HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
350 if (EFI_ERROR (Status
)) {
361 HttpCloseTcpConnCloseEvent (HttpInstance
);
367 Close events in the TCP connection token and TCP close token.
369 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
373 HttpCloseTcpConnCloseEvent (
374 IN HTTP_PROTOCOL
*HttpInstance
377 ASSERT (HttpInstance
!= NULL
);
379 if (HttpInstance
->LocalAddressIsIPv6
) {
380 if (NULL
!= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
) {
381 gBS
->CloseEvent (HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
);
382 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
= NULL
;
385 if (NULL
!= HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
) {
386 gBS
->CloseEvent (HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
);
387 HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
= NULL
;
390 if (NULL
!= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
) {
391 gBS
->CloseEvent (HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
);
392 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
= NULL
;
395 if (NULL
!= HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
) {
396 gBS
->CloseEvent (HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
);
397 HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
403 Create event for the TCP transmit token.
405 @param[in] Wrap Point to HTTP token's wrap data.
407 @retval EFI_SUCCESS The events is created successfully.
408 @retval others Other error as indicated.
412 HttpCreateTcpTxEvent (
413 IN HTTP_TOKEN_WRAP
*Wrap
417 HTTP_PROTOCOL
*HttpInstance
;
418 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
420 HttpInstance
= Wrap
->HttpInstance
;
421 TcpWrap
= &Wrap
->TcpWrap
;
423 if (!HttpInstance
->LocalAddressIsIPv6
) {
424 Status
= gBS
->CreateEvent (
427 HttpTcpTransmitNotify
,
429 &TcpWrap
->Tx4Token
.CompletionToken
.Event
431 if (EFI_ERROR (Status
)) {
435 TcpWrap
->Tx4Data
.Push
= TRUE
;
436 TcpWrap
->Tx4Data
.Urgent
= FALSE
;
437 TcpWrap
->Tx4Data
.FragmentCount
= 1;
438 TcpWrap
->Tx4Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx4Data
;
439 TcpWrap
->Tx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
441 Status
= gBS
->CreateEvent (
444 HttpTcpTransmitNotify
,
446 &TcpWrap
->Tx6Token
.CompletionToken
.Event
448 if (EFI_ERROR (Status
)) {
452 TcpWrap
->Tx6Data
.Push
= TRUE
;
453 TcpWrap
->Tx6Data
.Urgent
= FALSE
;
454 TcpWrap
->Tx6Data
.FragmentCount
= 1;
455 TcpWrap
->Tx6Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx6Data
;
456 TcpWrap
->Tx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
463 Create event for the TCP receive token which is used to receive HTTP header.
465 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
467 @retval EFI_SUCCESS The events is created successfully.
468 @retval others Other error as indicated.
472 HttpCreateTcpRxEventForHeader (
473 IN HTTP_PROTOCOL
*HttpInstance
478 if (!HttpInstance
->LocalAddressIsIPv6
) {
479 Status
= gBS
->CreateEvent (
483 &HttpInstance
->IsRxDone
,
484 &HttpInstance
->Rx4Token
.CompletionToken
.Event
486 if (EFI_ERROR (Status
)) {
490 HttpInstance
->Rx4Data
.FragmentCount
= 1;
491 HttpInstance
->Rx4Token
.Packet
.RxData
= &HttpInstance
->Rx4Data
;
492 HttpInstance
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
494 Status
= gBS
->CreateEvent (
498 &HttpInstance
->IsRxDone
,
499 &HttpInstance
->Rx6Token
.CompletionToken
.Event
501 if (EFI_ERROR (Status
)) {
505 HttpInstance
->Rx6Data
.FragmentCount
= 1;
506 HttpInstance
->Rx6Token
.Packet
.RxData
= &HttpInstance
->Rx6Data
;
507 HttpInstance
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
514 Create event for the TCP receive token which is used to receive HTTP body.
516 @param[in] Wrap Point to HTTP token's wrap data.
518 @retval EFI_SUCCESS The events is created successfully.
519 @retval others Other error as indicated.
523 HttpCreateTcpRxEvent (
524 IN HTTP_TOKEN_WRAP
*Wrap
528 HTTP_PROTOCOL
*HttpInstance
;
529 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
531 HttpInstance
= Wrap
->HttpInstance
;
532 TcpWrap
= &Wrap
->TcpWrap
;
533 if (!HttpInstance
->LocalAddressIsIPv6
) {
534 Status
= gBS
->CreateEvent (
537 HttpTcpReceiveNotify
,
539 &TcpWrap
->Rx4Token
.CompletionToken
.Event
541 if (EFI_ERROR (Status
)) {
545 TcpWrap
->Rx4Data
.FragmentCount
= 1;
546 TcpWrap
->Rx4Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx4Data
;
547 TcpWrap
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
549 Status
= gBS
->CreateEvent (
552 HttpTcpReceiveNotify
,
554 &TcpWrap
->Rx6Token
.CompletionToken
.Event
556 if (EFI_ERROR (Status
)) {
560 TcpWrap
->Rx6Data
.FragmentCount
= 1;
561 TcpWrap
->Rx6Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx6Data
;
562 TcpWrap
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
569 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.
571 @param[in] Wrap Pointer to HTTP token's wrap data.
575 HttpCloseTcpRxEvent (
576 IN HTTP_TOKEN_WRAP
*Wrap
579 HTTP_PROTOCOL
*HttpInstance
;
581 ASSERT (Wrap
!= NULL
);
582 HttpInstance
= Wrap
->HttpInstance
;
584 if (HttpInstance
->LocalAddressIsIPv6
) {
585 if (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
!= NULL
) {
586 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
589 if (HttpInstance
->Rx6Token
.CompletionToken
.Event
!= NULL
) {
590 gBS
->CloseEvent (HttpInstance
->Rx6Token
.CompletionToken
.Event
);
591 HttpInstance
->Rx6Token
.CompletionToken
.Event
= NULL
;
594 if (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
!= NULL
) {
595 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
598 if (HttpInstance
->Rx4Token
.CompletionToken
.Event
!= NULL
) {
599 gBS
->CloseEvent (HttpInstance
->Rx4Token
.CompletionToken
.Event
);
600 HttpInstance
->Rx4Token
.CompletionToken
.Event
= NULL
;
606 Initialize the HTTP_PROTOCOL structure to the unconfigured state.
608 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
609 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.
611 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
612 @retval Others Other error as indicated.
617 IN OUT HTTP_PROTOCOL
*HttpInstance
,
625 ASSERT (HttpInstance
!= NULL
);
626 UsingIpv6
= IpVersion
;
630 // Create TCP4 child.
632 Status
= NetLibCreateServiceChild (
633 HttpInstance
->Service
->ControllerHandle
,
634 HttpInstance
->Service
->Ip4DriverBindingHandle
,
635 &gEfiTcp4ServiceBindingProtocolGuid
,
636 &HttpInstance
->Tcp4ChildHandle
639 if (EFI_ERROR (Status
)) {
643 Status
= gBS
->OpenProtocol (
644 HttpInstance
->Tcp4ChildHandle
,
645 &gEfiTcp4ProtocolGuid
,
647 HttpInstance
->Service
->Ip4DriverBindingHandle
,
648 HttpInstance
->Service
->ControllerHandle
,
649 EFI_OPEN_PROTOCOL_BY_DRIVER
652 if (EFI_ERROR (Status
)) {
656 Status
= gBS
->OpenProtocol (
657 HttpInstance
->Tcp4ChildHandle
,
658 &gEfiTcp4ProtocolGuid
,
659 (VOID
**)&HttpInstance
->Tcp4
,
660 HttpInstance
->Service
->Ip4DriverBindingHandle
,
661 HttpInstance
->Handle
,
662 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
664 if (EFI_ERROR (Status
)) {
668 Status
= gBS
->OpenProtocol (
669 HttpInstance
->Service
->Tcp4ChildHandle
,
670 &gEfiTcp4ProtocolGuid
,
672 HttpInstance
->Service
->Ip4DriverBindingHandle
,
673 HttpInstance
->Handle
,
674 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
676 if (EFI_ERROR (Status
)) {
681 // Create TCP6 Child.
683 Status
= NetLibCreateServiceChild (
684 HttpInstance
->Service
->ControllerHandle
,
685 HttpInstance
->Service
->Ip6DriverBindingHandle
,
686 &gEfiTcp6ServiceBindingProtocolGuid
,
687 &HttpInstance
->Tcp6ChildHandle
690 if (EFI_ERROR (Status
)) {
694 Status
= gBS
->OpenProtocol (
695 HttpInstance
->Tcp6ChildHandle
,
696 &gEfiTcp6ProtocolGuid
,
698 HttpInstance
->Service
->Ip6DriverBindingHandle
,
699 HttpInstance
->Service
->ControllerHandle
,
700 EFI_OPEN_PROTOCOL_BY_DRIVER
703 if (EFI_ERROR (Status
)) {
707 Status
= gBS
->OpenProtocol (
708 HttpInstance
->Tcp6ChildHandle
,
709 &gEfiTcp6ProtocolGuid
,
710 (VOID
**)&HttpInstance
->Tcp6
,
711 HttpInstance
->Service
->Ip6DriverBindingHandle
,
712 HttpInstance
->Handle
,
713 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
716 if (EFI_ERROR (Status
)) {
720 Status
= gBS
->OpenProtocol (
721 HttpInstance
->Service
->Tcp6ChildHandle
,
722 &gEfiTcp6ProtocolGuid
,
724 HttpInstance
->Service
->Ip6DriverBindingHandle
,
725 HttpInstance
->Handle
,
726 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
729 if (EFI_ERROR (Status
)) {
734 HttpInstance
->Url
= AllocateZeroPool (HTTP_URL_BUFFER_LEN
);
735 if (HttpInstance
->Url
== NULL
) {
736 Status
= EFI_OUT_OF_RESOURCES
;
744 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
746 HttpInstance
->Tcp4ChildHandle
,
747 &gEfiTcp4ProtocolGuid
,
748 HttpInstance
->Service
->Ip4DriverBindingHandle
,
749 HttpInstance
->Service
->ControllerHandle
753 HttpInstance
->Tcp4ChildHandle
,
754 &gEfiTcp4ProtocolGuid
,
755 HttpInstance
->Service
->Ip4DriverBindingHandle
,
759 NetLibDestroyServiceChild (
760 HttpInstance
->Service
->ControllerHandle
,
761 HttpInstance
->Service
->Ip4DriverBindingHandle
,
762 &gEfiTcp4ServiceBindingProtocolGuid
,
763 HttpInstance
->Tcp4ChildHandle
767 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
769 HttpInstance
->Service
->Tcp4ChildHandle
,
770 &gEfiTcp4ProtocolGuid
,
771 HttpInstance
->Service
->Ip4DriverBindingHandle
,
776 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
778 HttpInstance
->Tcp6ChildHandle
,
779 &gEfiTcp6ProtocolGuid
,
780 HttpInstance
->Service
->Ip6DriverBindingHandle
,
781 HttpInstance
->Service
->ControllerHandle
785 HttpInstance
->Tcp6ChildHandle
,
786 &gEfiTcp6ProtocolGuid
,
787 HttpInstance
->Service
->Ip6DriverBindingHandle
,
791 NetLibDestroyServiceChild (
792 HttpInstance
->Service
->ControllerHandle
,
793 HttpInstance
->Service
->Ip6DriverBindingHandle
,
794 &gEfiTcp6ServiceBindingProtocolGuid
,
795 HttpInstance
->Tcp6ChildHandle
799 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
801 HttpInstance
->Service
->Tcp6ChildHandle
,
802 &gEfiTcp6ProtocolGuid
,
803 HttpInstance
->Service
->Ip6DriverBindingHandle
,
808 return EFI_UNSUPPORTED
;
812 Clean up the HTTP child, release all the resources used by it.
814 @param[in] HttpInstance The HTTP child to clean up.
819 IN HTTP_PROTOCOL
*HttpInstance
822 HttpCloseConnection (HttpInstance
);
824 HttpCloseTcpConnCloseEvent (HttpInstance
);
826 if (HttpInstance
->TimeoutEvent
!= NULL
) {
827 gBS
->CloseEvent (HttpInstance
->TimeoutEvent
);
828 HttpInstance
->TimeoutEvent
= NULL
;
831 if (HttpInstance
->CacheBody
!= NULL
) {
832 FreePool (HttpInstance
->CacheBody
);
833 HttpInstance
->CacheBody
= NULL
;
834 HttpInstance
->NextMsg
= NULL
;
837 if (HttpInstance
->RemoteHost
!= NULL
) {
838 FreePool (HttpInstance
->RemoteHost
);
839 HttpInstance
->RemoteHost
= NULL
;
842 if (HttpInstance
->MsgParser
!= NULL
) {
843 HttpFreeMsgParser (HttpInstance
->MsgParser
);
844 HttpInstance
->MsgParser
= NULL
;
847 if (HttpInstance
->Url
!= NULL
) {
848 FreePool (HttpInstance
->Url
);
849 HttpInstance
->Url
= NULL
;
852 NetMapClean (&HttpInstance
->TxTokens
);
853 NetMapClean (&HttpInstance
->RxTokens
);
855 if ((HttpInstance
->TlsSb
!= NULL
) && (HttpInstance
->TlsChildHandle
!= NULL
)) {
857 // Destroy the TLS instance.
859 HttpInstance
->TlsSb
->DestroyChild (HttpInstance
->TlsSb
, HttpInstance
->TlsChildHandle
);
860 HttpInstance
->TlsChildHandle
= NULL
;
863 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
865 HttpInstance
->Tcp4ChildHandle
,
866 &gEfiTcp4ProtocolGuid
,
867 HttpInstance
->Service
->Ip4DriverBindingHandle
,
868 HttpInstance
->Service
->ControllerHandle
872 HttpInstance
->Tcp4ChildHandle
,
873 &gEfiTcp4ProtocolGuid
,
874 HttpInstance
->Service
->Ip4DriverBindingHandle
,
878 NetLibDestroyServiceChild (
879 HttpInstance
->Service
->ControllerHandle
,
880 HttpInstance
->Service
->Ip4DriverBindingHandle
,
881 &gEfiTcp4ServiceBindingProtocolGuid
,
882 HttpInstance
->Tcp4ChildHandle
886 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
888 HttpInstance
->Service
->Tcp4ChildHandle
,
889 &gEfiTcp4ProtocolGuid
,
890 HttpInstance
->Service
->Ip4DriverBindingHandle
,
895 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
897 HttpInstance
->Tcp6ChildHandle
,
898 &gEfiTcp6ProtocolGuid
,
899 HttpInstance
->Service
->Ip6DriverBindingHandle
,
900 HttpInstance
->Service
->ControllerHandle
904 HttpInstance
->Tcp6ChildHandle
,
905 &gEfiTcp6ProtocolGuid
,
906 HttpInstance
->Service
->Ip6DriverBindingHandle
,
910 NetLibDestroyServiceChild (
911 HttpInstance
->Service
->ControllerHandle
,
912 HttpInstance
->Service
->Ip6DriverBindingHandle
,
913 &gEfiTcp6ServiceBindingProtocolGuid
,
914 HttpInstance
->Tcp6ChildHandle
918 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
920 HttpInstance
->Service
->Tcp6ChildHandle
,
921 &gEfiTcp6ProtocolGuid
,
922 HttpInstance
->Service
->Ip6DriverBindingHandle
,
927 TlsCloseTxRxEvent (HttpInstance
);
931 Establish TCP connection with HTTP server.
933 @param[in] HttpInstance The HTTP instance private data.
935 @retval EFI_SUCCESS The TCP connection is established.
936 @retval Others Other error as indicated.
940 HttpCreateConnection (
941 IN HTTP_PROTOCOL
*HttpInstance
947 // Connect to Http server
949 if (!HttpInstance
->LocalAddressIsIPv6
) {
950 HttpInstance
->IsTcp4ConnDone
= FALSE
;
951 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
952 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4ConnToken
);
953 HttpNotify (HttpEventConnectTcp
, Status
);
954 if (EFI_ERROR (Status
)) {
955 DEBUG ((DEBUG_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
959 while (!HttpInstance
->IsTcp4ConnDone
) {
960 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
963 Status
= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
;
965 HttpInstance
->IsTcp6ConnDone
= FALSE
;
966 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
967 Status
= HttpInstance
->Tcp6
->Connect (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6ConnToken
);
968 HttpNotify (HttpEventConnectTcp
, Status
);
969 if (EFI_ERROR (Status
)) {
970 DEBUG ((DEBUG_ERROR
, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status
));
974 while (!HttpInstance
->IsTcp6ConnDone
) {
975 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
978 Status
= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
;
981 if (!EFI_ERROR (Status
)) {
982 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
989 Close existing TCP connection.
991 @param[in] HttpInstance The HTTP instance private data.
993 @retval EFI_SUCCESS The TCP connection is closed.
994 @retval Others Other error as indicated.
998 HttpCloseConnection (
999 IN HTTP_PROTOCOL
*HttpInstance
1004 if (HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) {
1005 if (HttpInstance
->LocalAddressIsIPv6
) {
1006 HttpInstance
->Tcp6CloseToken
.AbortOnClose
= TRUE
;
1007 HttpInstance
->IsTcp6CloseDone
= FALSE
;
1008 Status
= HttpInstance
->Tcp6
->Close (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6CloseToken
);
1009 if (EFI_ERROR (Status
)) {
1013 while (!HttpInstance
->IsTcp6CloseDone
) {
1014 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
1017 HttpInstance
->Tcp4CloseToken
.AbortOnClose
= TRUE
;
1018 HttpInstance
->IsTcp4CloseDone
= FALSE
;
1019 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4CloseToken
);
1020 if (EFI_ERROR (Status
)) {
1024 while (!HttpInstance
->IsTcp4CloseDone
) {
1025 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
1030 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
1035 Configure TCP4 protocol child.
1037 @param[in] HttpInstance The HTTP instance private data.
1038 @param[in] Wrap The HTTP token's wrap data.
1040 @retval EFI_SUCCESS The TCP4 protocol child is configured.
1041 @retval Others Other error as indicated.
1046 IN HTTP_PROTOCOL
*HttpInstance
,
1047 IN HTTP_TOKEN_WRAP
*Wrap
1051 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
1052 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
1053 EFI_TCP4_OPTION
*Tcp4Option
;
1055 ASSERT (HttpInstance
!= NULL
);
1057 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
1058 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
1060 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
1061 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
1062 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
1064 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
1065 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
1066 if (!Tcp4AP
->UseDefaultAddress
) {
1067 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
1068 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
1071 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
1072 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
1073 Tcp4AP
->ActiveFlag
= TRUE
;
1074 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
1076 Tcp4Option
= Tcp4CfgData
->ControlOption
;
1077 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1078 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1079 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1080 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1081 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
1082 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1083 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1084 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1085 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1086 Tcp4Option
->EnableNagle
= TRUE
;
1087 Tcp4CfgData
->ControlOption
= Tcp4Option
;
1089 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
1090 if (EFI_ERROR (Status
)) {
1091 DEBUG ((DEBUG_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
1095 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1096 if (EFI_ERROR (Status
)) {
1100 Status
= HttpCreateTcpTxEvent (Wrap
);
1101 if (EFI_ERROR (Status
)) {
1105 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1111 Configure TCP6 protocol child.
1113 @param[in] HttpInstance The HTTP instance private data.
1114 @param[in] Wrap The HTTP token's wrap data.
1116 @retval EFI_SUCCESS The TCP6 protocol child is configured.
1117 @retval Others Other error as indicated.
1122 IN HTTP_PROTOCOL
*HttpInstance
,
1123 IN HTTP_TOKEN_WRAP
*Wrap
1127 EFI_TCP6_CONFIG_DATA
*Tcp6CfgData
;
1128 EFI_TCP6_ACCESS_POINT
*Tcp6Ap
;
1129 EFI_TCP6_OPTION
*Tcp6Option
;
1131 ASSERT (HttpInstance
!= NULL
);
1133 Tcp6CfgData
= &HttpInstance
->Tcp6CfgData
;
1134 ZeroMem (Tcp6CfgData
, sizeof (EFI_TCP6_CONFIG_DATA
));
1136 Tcp6CfgData
->TrafficClass
= 0;
1137 Tcp6CfgData
->HopLimit
= 255;
1138 Tcp6CfgData
->ControlOption
= &HttpInstance
->Tcp6Option
;
1140 Tcp6Ap
= &Tcp6CfgData
->AccessPoint
;
1141 Tcp6Ap
->ActiveFlag
= TRUE
;
1142 Tcp6Ap
->StationPort
= HttpInstance
->Ipv6Node
.LocalPort
;
1143 Tcp6Ap
->RemotePort
= HttpInstance
->RemotePort
;
1144 IP6_COPY_ADDRESS (&Tcp6Ap
->StationAddress
, &HttpInstance
->Ipv6Node
.LocalAddress
);
1145 IP6_COPY_ADDRESS (&Tcp6Ap
->RemoteAddress
, &HttpInstance
->RemoteIpv6Addr
);
1147 Tcp6Option
= Tcp6CfgData
->ControlOption
;
1148 Tcp6Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1149 Tcp6Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1150 Tcp6Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1151 Tcp6Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1152 Tcp6Option
->DataRetries
= HTTP_DATA_RETRIES
;
1153 Tcp6Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1154 Tcp6Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1155 Tcp6Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1156 Tcp6Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1157 Tcp6Option
->EnableNagle
= TRUE
;
1159 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, Tcp6CfgData
);
1160 if (EFI_ERROR (Status
)) {
1161 DEBUG ((DEBUG_ERROR
, "HttpConfigureTcp6 - %r\n", Status
));
1165 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1166 if (EFI_ERROR (Status
)) {
1170 Status
= HttpCreateTcpTxEvent (Wrap
);
1171 if (EFI_ERROR (Status
)) {
1175 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1181 Check existing TCP connection, if in error state, recover TCP4 connection. Then,
1182 connect one TLS session if required.
1184 @param[in] HttpInstance The HTTP instance private data.
1186 @retval EFI_SUCCESS The TCP connection is established.
1187 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1188 @retval Others Other error as indicated.
1193 IN HTTP_PROTOCOL
*HttpInstance
1197 EFI_TCP4_CONNECTION_STATE Tcp4State
;
1199 if ((HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
) || (HttpInstance
->Tcp4
== NULL
)) {
1200 return EFI_NOT_READY
;
1203 Status
= HttpInstance
->Tcp4
->GetModeData (
1211 if (EFI_ERROR (Status
)) {
1212 DEBUG ((DEBUG_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
1216 if (Tcp4State
== Tcp4StateEstablished
) {
1218 } else if (Tcp4State
> Tcp4StateEstablished
) {
1219 HttpCloseConnection (HttpInstance
);
1222 Status
= HttpCreateConnection (HttpInstance
);
1223 if (EFI_ERROR (Status
)) {
1224 DEBUG ((DEBUG_ERROR
, "Tcp4 Connection fail - %x\n", Status
));
1229 // Tls session connection.
1231 if (HttpInstance
->UseHttps
) {
1232 if (HttpInstance
->TimeoutEvent
== NULL
) {
1234 // Create TimeoutEvent for TLS connection.
1236 Status
= gBS
->CreateEvent (
1241 &HttpInstance
->TimeoutEvent
1243 if (EFI_ERROR (Status
)) {
1244 TlsCloseTxRxEvent (HttpInstance
);
1250 // Start the timer, and wait Timeout seconds for connection.
1252 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1253 if (EFI_ERROR (Status
)) {
1254 TlsCloseTxRxEvent (HttpInstance
);
1258 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1259 HttpNotify (HttpEventTlsConnectSession
, Status
);
1261 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1263 if (EFI_ERROR (Status
)) {
1264 TlsCloseTxRxEvent (HttpInstance
);
1273 Check existing TCP connection, if in error state, recover TCP6 connection. Then,
1274 connect one TLS session if required.
1276 @param[in] HttpInstance The HTTP instance private data.
1278 @retval EFI_SUCCESS The TCP connection is established.
1279 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1280 @retval Others Other error as indicated.
1285 IN HTTP_PROTOCOL
*HttpInstance
1289 EFI_TCP6_CONNECTION_STATE Tcp6State
;
1291 if ((HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
) || (HttpInstance
->Tcp6
== NULL
)) {
1292 return EFI_NOT_READY
;
1295 Status
= HttpInstance
->Tcp6
->GetModeData (
1304 if (EFI_ERROR (Status
)) {
1305 DEBUG ((DEBUG_ERROR
, "Tcp6 GetModeData fail - %x\n", Status
));
1309 if (Tcp6State
== Tcp6StateEstablished
) {
1311 } else if (Tcp6State
> Tcp6StateEstablished
) {
1312 HttpCloseConnection (HttpInstance
);
1315 Status
= HttpCreateConnection (HttpInstance
);
1316 if (EFI_ERROR (Status
)) {
1317 DEBUG ((DEBUG_ERROR
, "Tcp6 Connection fail - %x\n", Status
));
1322 // Tls session connection.
1324 if (HttpInstance
->UseHttps
) {
1325 if (HttpInstance
->TimeoutEvent
== NULL
) {
1327 // Create TimeoutEvent for TLS connection.
1329 Status
= gBS
->CreateEvent (
1334 &HttpInstance
->TimeoutEvent
1336 if (EFI_ERROR (Status
)) {
1337 TlsCloseTxRxEvent (HttpInstance
);
1343 // Start the timer, and wait Timeout seconds for connection.
1345 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1346 if (EFI_ERROR (Status
)) {
1347 TlsCloseTxRxEvent (HttpInstance
);
1351 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1352 HttpNotify (HttpEventTlsConnectSession
, Status
);
1354 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1356 if (EFI_ERROR (Status
)) {
1357 TlsCloseTxRxEvent (HttpInstance
);
1366 Initialize Http session.
1368 @param[in] HttpInstance The HTTP instance private data.
1369 @param[in] Wrap The HTTP token's wrap data.
1370 @param[in] Configure The Flag indicates whether need to initialize session.
1371 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session.
1373 @retval EFI_SUCCESS The initialization of session is done.
1374 @retval Others Other error as indicated.
1379 IN HTTP_PROTOCOL
*HttpInstance
,
1380 IN HTTP_TOKEN_WRAP
*Wrap
,
1381 IN BOOLEAN Configure
,
1382 IN BOOLEAN TlsConfigure
1387 ASSERT (HttpInstance
!= NULL
);
1390 // Configure Tls session.
1393 Status
= TlsConfigureSession (HttpInstance
);
1394 if (EFI_ERROR (Status
)) {
1399 if (!HttpInstance
->LocalAddressIsIPv6
) {
1401 // Configure TCP instance.
1404 Status
= HttpConfigureTcp4 (HttpInstance
, Wrap
);
1405 if (EFI_ERROR (Status
)) {
1413 Status
= HttpConnectTcp4 (HttpInstance
);
1414 if (EFI_ERROR (Status
)) {
1419 // Configure TCP instance.
1422 Status
= HttpConfigureTcp6 (HttpInstance
, Wrap
);
1423 if (EFI_ERROR (Status
)) {
1431 Status
= HttpConnectTcp6 (HttpInstance
);
1432 if (EFI_ERROR (Status
)) {
1441 Send the HTTP or HTTPS message through TCP4 or TCP6.
1443 @param[in] HttpInstance The HTTP instance private data.
1444 @param[in] Wrap The HTTP token's wrap data.
1445 @param[in] TxString Buffer containing the HTTP message string.
1446 @param[in] TxStringLen Length of the HTTP message string in bytes.
1448 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1449 @retval Others Other error as indicated.
1454 IN HTTP_PROTOCOL
*HttpInstance
,
1455 IN HTTP_TOKEN_WRAP
*Wrap
,
1457 IN UINTN TxStringLen
1461 EFI_TCP4_IO_TOKEN
*Tx4Token
;
1462 EFI_TCP4_PROTOCOL
*Tcp4
;
1463 EFI_TCP6_IO_TOKEN
*Tx6Token
;
1464 EFI_TCP6_PROTOCOL
*Tcp6
;
1467 NET_FRAGMENT TempFragment
;
1468 NET_FRAGMENT Fragment
;
1472 Status
= EFI_SUCCESS
;
1475 TempFragment
.Len
= 0;
1476 TempFragment
.Bulk
= NULL
;
1478 Fragment
.Bulk
= NULL
;
1483 // Need to encrypt data.
1485 if (HttpInstance
->UseHttps
) {
1487 // Allocate enough buffer for each TLS plaintext records.
1489 TlsRecord
= AllocateZeroPool (TLS_RECORD_HEADER_LENGTH
+ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
);
1490 if (TlsRecord
== NULL
) {
1491 Status
= EFI_OUT_OF_RESOURCES
;
1496 // Allocate enough buffer for all TLS ciphertext records.
1498 RecordCount
= TxStringLen
/ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
+ 1;
1499 Fragment
.Bulk
= AllocateZeroPool (RecordCount
* (TLS_RECORD_HEADER_LENGTH
+ TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH
));
1500 if (Fragment
.Bulk
== NULL
) {
1501 Status
= EFI_OUT_OF_RESOURCES
;
1506 // Encrypt each TLS plaintext records.
1508 RemainingLen
= TxStringLen
;
1509 while (RemainingLen
!= 0) {
1510 PayloadSize
= (UINT16
)MIN (TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
, RemainingLen
);
1512 ((TLS_RECORD_HEADER
*)TlsRecord
)->ContentType
= TlsContentTypeApplicationData
;
1513 ((TLS_RECORD_HEADER
*)TlsRecord
)->Version
.Major
= HttpInstance
->TlsConfigData
.Version
.Major
;
1514 ((TLS_RECORD_HEADER
*)TlsRecord
)->Version
.Minor
= HttpInstance
->TlsConfigData
.Version
.Minor
;
1515 ((TLS_RECORD_HEADER
*)TlsRecord
)->Length
= PayloadSize
;
1517 CopyMem (TlsRecord
+ TLS_RECORD_HEADER_LENGTH
, TxString
+ (TxStringLen
- RemainingLen
), PayloadSize
);
1519 Status
= TlsProcessMessage (
1522 TLS_RECORD_HEADER_LENGTH
+ PayloadSize
,
1526 if (EFI_ERROR (Status
)) {
1531 // Record the processed/encrypted Packet.
1533 CopyMem (Fragment
.Bulk
+ Fragment
.Len
, TempFragment
.Bulk
, TempFragment
.Len
);
1534 Fragment
.Len
+= TempFragment
.Len
;
1536 FreePool (TempFragment
.Bulk
);
1537 TempFragment
.Len
= 0;
1538 TempFragment
.Bulk
= NULL
;
1540 RemainingLen
-= (UINTN
)PayloadSize
;
1541 ZeroMem (TlsRecord
, TLS_RECORD_HEADER_LENGTH
+ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
);
1544 FreePool (TlsRecord
);
1548 if (!HttpInstance
->LocalAddressIsIPv6
) {
1549 Tcp4
= HttpInstance
->Tcp4
;
1550 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1552 if (HttpInstance
->UseHttps
) {
1553 Tx4Token
->Packet
.TxData
->DataLength
= Fragment
.Len
;
1554 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= Fragment
.Len
;
1555 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)Fragment
.Bulk
;
1557 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
)TxStringLen
;
1558 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
)TxStringLen
;
1559 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)TxString
;
1562 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1564 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1565 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1566 if (EFI_ERROR (Status
)) {
1567 DEBUG ((DEBUG_ERROR
, "Transmit failed: %r\n", Status
));
1571 Tcp6
= HttpInstance
->Tcp6
;
1572 Tx6Token
= &Wrap
->TcpWrap
.Tx6Token
;
1574 if (HttpInstance
->UseHttps
) {
1575 Tx6Token
->Packet
.TxData
->DataLength
= Fragment
.Len
;
1576 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= Fragment
.Len
;
1577 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)Fragment
.Bulk
;
1579 Tx6Token
->Packet
.TxData
->DataLength
= (UINT32
)TxStringLen
;
1580 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
)TxStringLen
;
1581 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)TxString
;
1584 Tx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1586 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1587 Status
= Tcp6
->Transmit (Tcp6
, Tx6Token
);
1588 if (EFI_ERROR (Status
)) {
1589 DEBUG ((DEBUG_ERROR
, "Transmit failed: %r\n", Status
));
1598 if (HttpInstance
->UseHttps
) {
1599 if (TlsRecord
!= NULL
) {
1600 FreePool (TlsRecord
);
1604 if (Fragment
.Bulk
!= NULL
) {
1605 FreePool (Fragment
.Bulk
);
1606 Fragment
.Bulk
= NULL
;
1614 Check whether the user's token or event has already
1615 been enqueue on HTTP Tx or Rx Token list.
1617 @param[in] Map The container of either user's transmit or receive
1619 @param[in] Item Current item to check against.
1620 @param[in] Context The Token to check against.
1622 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1623 @retval EFI_SUCCESS The current item isn't the same token/event as the
1631 IN NET_MAP_ITEM
*Item
,
1635 EFI_HTTP_TOKEN
*Token
;
1636 EFI_HTTP_TOKEN
*TokenInItem
;
1638 Token
= (EFI_HTTP_TOKEN
*)Context
;
1639 TokenInItem
= (EFI_HTTP_TOKEN
*)Item
->Key
;
1641 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
1642 return EFI_ACCESS_DENIED
;
1649 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1651 @param[in] Map The container of Tx4Token or Tx6Token.
1652 @param[in] Item Current item to check against.
1653 @param[in] Context The Token to check against.
1655 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1656 @retval EFI_SUCCESS The HTTP message has been sent out.
1663 IN NET_MAP_ITEM
*Item
,
1667 HTTP_TOKEN_WRAP
*ValueInItem
;
1669 ValueInItem
= (HTTP_TOKEN_WRAP
*)Item
->Value
;
1671 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
1672 return EFI_NOT_READY
;
1679 Transmit the HTTP or HTTPS message by processing the associated HTTP token.
1681 @param[in] Map The container of Tx4Token or Tx6Token.
1682 @param[in] Item Current item to check against.
1683 @param[in] Context The Token to check against.
1685 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1686 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1694 IN NET_MAP_ITEM
*Item
,
1698 HTTP_TOKEN_WRAP
*ValueInItem
;
1703 UINTN RequestMsgSize
;
1707 ValueInItem
= (HTTP_TOKEN_WRAP
*)Item
->Value
;
1708 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1713 // Parse the URI of the remote host.
1715 UrlSize
= StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1;
1716 Url
= AllocatePool (UrlSize
);
1718 return EFI_OUT_OF_RESOURCES
;
1721 UnicodeStrToAsciiStrS (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
, UrlSize
);
1724 // Create request message.
1726 Status
= HttpGenRequestMessage (
1727 ValueInItem
->HttpToken
->Message
,
1734 if (EFI_ERROR (Status
) || (NULL
== RequestMsg
)) {
1738 ASSERT (RequestMsg
!= NULL
);
1741 // Transmit the request message.
1743 Status
= HttpTransmitTcp (
1744 ValueInItem
->HttpInstance
,
1746 (UINT8
*)RequestMsg
,
1749 FreePool (RequestMsg
);
1754 Receive the HTTP response by processing the associated HTTP token.
1756 @param[in] Map The container of Rx4Token or Rx6Token.
1757 @param[in] Item Current item to check against.
1758 @param[in] Context The Token to check against.
1760 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1762 @retval Others Other error as indicated.
1769 IN NET_MAP_ITEM
*Item
,
1774 // Process the queued HTTP response.
1776 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*)Item
->Value
);
1780 Receive the HTTP header by processing the associated HTTP token.
1782 @param[in] HttpInstance The HTTP instance private data.
1783 @param[in, out] SizeofHeaders The HTTP header length.
1784 @param[in, out] BufferSize The size of buffer to cache the header message.
1785 @param[in] Timeout The time to wait for receiving the header packet.
1787 @retval EFI_SUCCESS The HTTP header is received.
1788 @retval Others Other errors as indicated.
1792 HttpTcpReceiveHeader (
1793 IN HTTP_PROTOCOL
*HttpInstance
,
1794 IN OUT UINTN
*SizeofHeaders
,
1795 IN OUT UINTN
*BufferSize
,
1796 IN EFI_EVENT Timeout
1800 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1801 EFI_TCP4_PROTOCOL
*Tcp4
;
1802 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1803 EFI_TCP6_PROTOCOL
*Tcp6
;
1804 CHAR8
**EndofHeader
;
1805 CHAR8
**HttpHeaders
;
1807 NET_FRAGMENT Fragment
;
1809 ASSERT (HttpInstance
!= NULL
);
1811 EndofHeader
= HttpInstance
->EndofHeader
;
1812 HttpHeaders
= HttpInstance
->HttpHeaders
;
1813 Tcp4
= HttpInstance
->Tcp4
;
1814 Tcp6
= HttpInstance
->Tcp6
;
1819 Fragment
.Bulk
= NULL
;
1821 if (HttpInstance
->LocalAddressIsIPv6
) {
1822 ASSERT (Tcp6
!= NULL
);
1824 ASSERT (Tcp4
!= NULL
);
1827 if (!HttpInstance
->UseHttps
) {
1828 Status
= HttpCreateTcpRxEventForHeader (HttpInstance
);
1829 if (EFI_ERROR (Status
)) {
1834 if (!HttpInstance
->LocalAddressIsIPv6
) {
1835 if (!HttpInstance
->UseHttps
) {
1836 Rx4Token
= &HttpInstance
->Rx4Token
;
1837 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1838 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1839 Status
= EFI_OUT_OF_RESOURCES
;
1845 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1847 while (*EndofHeader
== NULL
) {
1848 if (!HttpInstance
->UseHttps
) {
1849 HttpInstance
->IsRxDone
= FALSE
;
1850 Rx4Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1851 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1852 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1853 if (EFI_ERROR (Status
)) {
1854 DEBUG ((DEBUG_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1858 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1862 if (!HttpInstance
->IsRxDone
) {
1864 // Cancel the Token before close its Event.
1866 Tcp4
->Cancel (HttpInstance
->Tcp4
, &Rx4Token
->CompletionToken
);
1867 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1868 Rx4Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1871 Status
= Rx4Token
->CompletionToken
.Status
;
1872 if (EFI_ERROR (Status
)) {
1876 Fragment
.Len
= Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1877 Fragment
.Bulk
= (UINT8
*)Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
1879 if (Fragment
.Bulk
!= NULL
) {
1880 FreePool (Fragment
.Bulk
);
1881 Fragment
.Bulk
= NULL
;
1884 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
1885 if (EFI_ERROR (Status
)) {
1886 DEBUG ((DEBUG_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1892 // Append the response string along with a Null-terminator.
1894 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
1895 Buffer
= AllocatePool (*BufferSize
+ 1);
1896 if (Buffer
== NULL
) {
1897 Status
= EFI_OUT_OF_RESOURCES
;
1901 if (*HttpHeaders
!= NULL
) {
1902 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
1903 FreePool (*HttpHeaders
);
1907 Buffer
+ *SizeofHeaders
,
1911 *(Buffer
+ *BufferSize
) = '\0';
1912 *HttpHeaders
= Buffer
;
1913 *SizeofHeaders
= *BufferSize
;
1916 // Check whether we received end of HTTP headers.
1918 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1924 if ((Rx4Token
!= NULL
) && (Rx4Token
->Packet
.RxData
!= NULL
) && (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
)) {
1925 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1926 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1927 Fragment
.Bulk
= NULL
;
1930 if (Fragment
.Bulk
!= NULL
) {
1931 FreePool (Fragment
.Bulk
);
1932 Fragment
.Bulk
= NULL
;
1935 if (!HttpInstance
->UseHttps
) {
1936 Rx6Token
= &HttpInstance
->Rx6Token
;
1937 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1938 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1939 Status
= EFI_OUT_OF_RESOURCES
;
1945 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1947 while (*EndofHeader
== NULL
) {
1948 if (!HttpInstance
->UseHttps
) {
1949 HttpInstance
->IsRxDone
= FALSE
;
1950 Rx6Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1951 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1952 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1953 if (EFI_ERROR (Status
)) {
1954 DEBUG ((DEBUG_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1958 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1962 if (!HttpInstance
->IsRxDone
) {
1964 // Cancel the Token before close its Event.
1966 Tcp6
->Cancel (HttpInstance
->Tcp6
, &Rx6Token
->CompletionToken
);
1967 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1968 Rx6Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1971 Status
= Rx6Token
->CompletionToken
.Status
;
1972 if (EFI_ERROR (Status
)) {
1976 Fragment
.Len
= Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1977 Fragment
.Bulk
= (UINT8
*)Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
1979 if (Fragment
.Bulk
!= NULL
) {
1980 FreePool (Fragment
.Bulk
);
1981 Fragment
.Bulk
= NULL
;
1984 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
1985 if (EFI_ERROR (Status
)) {
1986 DEBUG ((DEBUG_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1992 // Append the response string along with a Null-terminator.
1994 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
1995 Buffer
= AllocatePool (*BufferSize
+ 1);
1996 if (Buffer
== NULL
) {
1997 Status
= EFI_OUT_OF_RESOURCES
;
2001 if (*HttpHeaders
!= NULL
) {
2002 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
2003 FreePool (*HttpHeaders
);
2007 Buffer
+ *SizeofHeaders
,
2011 *(Buffer
+ *BufferSize
) = '\0';
2012 *HttpHeaders
= Buffer
;
2013 *SizeofHeaders
= *BufferSize
;
2016 // Check whether we received end of HTTP headers.
2018 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
2024 if ((Rx6Token
!= NULL
) && (Rx6Token
->Packet
.RxData
!= NULL
) && (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
)) {
2025 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2026 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2027 Fragment
.Bulk
= NULL
;
2030 if (Fragment
.Bulk
!= NULL
) {
2031 FreePool (Fragment
.Bulk
);
2032 Fragment
.Bulk
= NULL
;
2037 // Skip the CRLF after the HTTP headers.
2039 *EndofHeader
= *EndofHeader
+ AsciiStrLen (HTTP_END_OF_HDR_STR
);
2041 *SizeofHeaders
= *EndofHeader
- *HttpHeaders
;
2047 Receive the HTTP body by processing the associated HTTP token.
2049 @param[in] Wrap The HTTP token's wrap data.
2050 @param[in] HttpMsg The HTTP message data.
2052 @retval EFI_SUCCESS The HTTP body is received.
2053 @retval Others Other error as indicated.
2057 HttpTcpReceiveBody (
2058 IN HTTP_TOKEN_WRAP
*Wrap
,
2059 IN EFI_HTTP_MESSAGE
*HttpMsg
2063 HTTP_PROTOCOL
*HttpInstance
;
2064 EFI_TCP6_PROTOCOL
*Tcp6
;
2065 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2066 EFI_TCP4_PROTOCOL
*Tcp4
;
2067 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2069 HttpInstance
= Wrap
->HttpInstance
;
2070 Tcp4
= HttpInstance
->Tcp4
;
2071 Tcp6
= HttpInstance
->Tcp6
;
2075 if (HttpInstance
->LocalAddressIsIPv6
) {
2076 ASSERT (Tcp6
!= NULL
);
2078 ASSERT (Tcp4
!= NULL
);
2081 if (HttpInstance
->LocalAddressIsIPv6
) {
2082 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2083 Rx6Token
->Packet
.RxData
->DataLength
= (UINT32
)MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2084 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
)MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2085 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)HttpMsg
->Body
;
2086 Rx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2088 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
2089 if (EFI_ERROR (Status
)) {
2090 DEBUG ((DEBUG_ERROR
, "Tcp6 receive failed: %r\n", Status
));
2094 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2095 Rx4Token
->Packet
.RxData
->DataLength
= (UINT32
)MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2096 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
)MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2097 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)HttpMsg
->Body
;
2099 Rx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2100 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
2101 if (EFI_ERROR (Status
)) {
2102 DEBUG ((DEBUG_ERROR
, "Tcp4 receive failed: %r\n", Status
));
2111 Clean up Tcp Tokens while the Tcp transmission error occurs.
2113 @param[in] Wrap Pointer to HTTP token's wrap data.
2117 HttpTcpTokenCleanup (
2118 IN HTTP_TOKEN_WRAP
*Wrap
2121 HTTP_PROTOCOL
*HttpInstance
;
2122 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2123 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2125 ASSERT (Wrap
!= NULL
);
2126 HttpInstance
= Wrap
->HttpInstance
;
2130 if (HttpInstance
->LocalAddressIsIPv6
) {
2131 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2133 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2134 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2135 Rx6Token
->CompletionToken
.Event
= NULL
;
2140 Rx6Token
= &HttpInstance
->Rx6Token
;
2142 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2143 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2144 Rx6Token
->CompletionToken
.Event
= NULL
;
2147 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2148 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2149 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2152 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2154 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2155 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2156 Rx4Token
->CompletionToken
.Event
= NULL
;
2161 Rx4Token
= &HttpInstance
->Rx4Token
;
2163 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2164 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2165 Rx4Token
->CompletionToken
.Event
= NULL
;
2168 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2169 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2170 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2176 Send Events via EDKII_HTTP_CALLBACK_PROTOCOL.
2178 @param[in] Event The event that occurs in the current state.
2179 @param[in] EventStatus The Status of Event, EFI_SUCCESS or other errors.
2184 IN EDKII_HTTP_CALLBACK_EVENT Event
,
2185 IN EFI_STATUS EventStatus
2189 EFI_HANDLE
*Handles
;
2193 EDKII_HTTP_CALLBACK_PROTOCOL
*HttpCallback
;
2195 DEBUG ((DEBUG_INFO
, "HttpNotify: Event - %d, EventStatus - %r\n", Event
, EventStatus
));
2199 Status
= gBS
->LocateHandleBuffer (
2201 &gEdkiiHttpCallbackProtocolGuid
,
2206 if (Status
== EFI_SUCCESS
) {
2207 for (Index
= 0; Index
< HandleCount
; Index
++) {
2208 Handle
= Handles
[Index
];
2209 Status
= gBS
->HandleProtocol (
2211 &gEdkiiHttpCallbackProtocolGuid
,
2212 (VOID
**)&HttpCallback
2214 if (Status
== EFI_SUCCESS
) {
2215 DEBUG ((DEBUG_INFO
, "HttpNotify: Notifying %p\n", HttpCallback
));
2216 HttpCallback
->Callback (