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
);
71 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Status
;
72 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
77 if (Wrap
->TcpWrap
.Tx6Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
78 FreePool (Wrap
->TcpWrap
.Tx6Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
);
81 if (Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Event
!= NULL
) {
82 gBS
->CloseEvent (Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Event
);
87 Wrap
->TcpWrap
.IsTxDone
= TRUE
;
90 // Check pending TxTokens and sent out.
92 NetMapIterate (&Wrap
->HttpInstance
->TxTokens
, HttpTcpTransmit
, NULL
);
97 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.
99 @param Event The receive event delivered to TCP for transmit.
100 @param Context Context for the callback.
105 HttpTcpTransmitNotify (
111 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
113 QueueDpc (TPL_CALLBACK
, HttpTcpTransmitNotifyDpc
, Context
);
117 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().
119 @param[in] Context The context.
124 HttpTcpReceiveNotifyDpc (
128 HTTP_TOKEN_WRAP
*Wrap
;
132 HTTP_PROTOCOL
*HttpInstance
;
135 if (Context
== NULL
) {
139 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
140 HttpInstance
= Wrap
->HttpInstance
;
141 UsingIpv6
= HttpInstance
->LocalAddressIsIPv6
;
144 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
145 Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
= NULL
;
147 if (EFI_ERROR (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
)) {
148 DEBUG ((EFI_D_ERROR
, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
));
149 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
150 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
152 Item
= NetMapFindKey (&HttpInstance
->RxTokens
, Wrap
->HttpToken
);
154 NetMapRemoveItem (&HttpInstance
->RxTokens
, Item
, NULL
);
164 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
165 Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
= NULL
;
167 if (EFI_ERROR (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
)) {
168 DEBUG ((EFI_D_ERROR
, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
));
169 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
170 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
172 Item
= NetMapFindKey (&HttpInstance
->RxTokens
, Wrap
->HttpToken
);
174 NetMapRemoveItem (&HttpInstance
->RxTokens
, Item
, NULL
);
185 // Check whether we receive a complete HTTP message.
187 ASSERT (HttpInstance
->MsgParser
!= NULL
);
189 Length
= (UINTN
) Wrap
->TcpWrap
.Rx6Data
.FragmentTable
[0].FragmentLength
;
191 Length
= (UINTN
) Wrap
->TcpWrap
.Rx4Data
.FragmentTable
[0].FragmentLength
;
195 // Record the CallbackData data.
197 HttpInstance
->CallbackData
.Wrap
= (VOID
*) Wrap
;
198 HttpInstance
->CallbackData
.ParseData
= Wrap
->HttpToken
->Message
->Body
;
199 HttpInstance
->CallbackData
.ParseDataLength
= Length
;
202 // Parse Body with CallbackData data.
204 Status
= HttpParseMessageBody (
205 HttpInstance
->MsgParser
,
207 Wrap
->HttpToken
->Message
->Body
209 if (EFI_ERROR (Status
)) {
213 if (HttpIsMessageComplete (HttpInstance
->MsgParser
)) {
215 // Free the MsgParse since we already have a full HTTP message.
217 HttpFreeMsgParser (HttpInstance
->MsgParser
);
218 HttpInstance
->MsgParser
= NULL
;
221 Wrap
->HttpToken
->Message
->BodyLength
= Length
;
222 ASSERT (HttpInstance
->CacheBody
== NULL
);
224 // We receive part of header of next HTTP msg.
226 if (HttpInstance
->NextMsg
!= NULL
) {
227 Wrap
->HttpToken
->Message
->BodyLength
= HttpInstance
->NextMsg
-
228 (CHAR8
*) Wrap
->HttpToken
->Message
->Body
;
229 HttpInstance
->CacheLen
= Length
- Wrap
->HttpToken
->Message
->BodyLength
;
230 if (HttpInstance
->CacheLen
!= 0) {
231 HttpInstance
->CacheBody
= AllocateZeroPool (HttpInstance
->CacheLen
);
232 if (HttpInstance
->CacheBody
== NULL
) {
235 CopyMem (HttpInstance
->CacheBody
, HttpInstance
->NextMsg
, HttpInstance
->CacheLen
);
236 HttpInstance
->NextMsg
= HttpInstance
->CacheBody
;
237 HttpInstance
->CacheOffset
= 0;
241 Item
= NetMapFindKey (&Wrap
->HttpInstance
->RxTokens
, Wrap
->HttpToken
);
243 NetMapRemoveItem (&Wrap
->HttpInstance
->RxTokens
, Item
, NULL
);
247 Wrap
->TcpWrap
.IsRxDone
= TRUE
;
249 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
251 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
255 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
258 // Check pending RxTokens and receive the HTTP message.
260 NetMapIterate (&Wrap
->HttpInstance
->RxTokens
, HttpTcpReceive
, NULL
);
267 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.
269 @param Event The receive event delivered to TCP for receive.
270 @param Context Context for the callback.
275 HttpTcpReceiveNotify (
281 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
283 QueueDpc (TPL_CALLBACK
, HttpTcpReceiveNotifyDpc
, Context
);
287 Create events for the TCP connection token and TCP close token.
289 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
291 @retval EFI_SUCCESS The events are created successfully.
292 @retval others Other error as indicated.
296 HttpCreateTcpConnCloseEvent (
297 IN HTTP_PROTOCOL
*HttpInstance
302 if (!HttpInstance
->LocalAddressIsIPv6
) {
304 // Create events for various asynchronous operations.
306 Status
= gBS
->CreateEvent (
310 &HttpInstance
->IsTcp4ConnDone
,
311 &HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
313 if (EFI_ERROR (Status
)) {
318 // Initialize Tcp4CloseToken
320 Status
= gBS
->CreateEvent (
324 &HttpInstance
->IsTcp4CloseDone
,
325 &HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
327 if (EFI_ERROR (Status
)) {
333 // Create events for various asynchronous operations.
335 Status
= gBS
->CreateEvent (
339 &HttpInstance
->IsTcp6ConnDone
,
340 &HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
342 if (EFI_ERROR (Status
)) {
347 // Initialize Tcp6CloseToken
349 Status
= gBS
->CreateEvent (
353 &HttpInstance
->IsTcp6CloseDone
,
354 &HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
356 if (EFI_ERROR (Status
)) {
367 HttpCloseTcpConnCloseEvent (HttpInstance
);
374 Close events in the TCP connection token and TCP close token.
376 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
380 HttpCloseTcpConnCloseEvent (
381 IN HTTP_PROTOCOL
*HttpInstance
384 ASSERT (HttpInstance
!= NULL
);
386 if (HttpInstance
->LocalAddressIsIPv6
) {
387 if (NULL
!= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
) {
388 gBS
->CloseEvent (HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
);
389 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
= NULL
;
392 if (NULL
!= HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
) {
393 gBS
->CloseEvent(HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
);
394 HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
= NULL
;
398 if (NULL
!= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
) {
399 gBS
->CloseEvent (HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
);
400 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
= NULL
;
403 if (NULL
!= HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
) {
404 gBS
->CloseEvent(HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
);
405 HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
412 Create event for the TCP transmit token.
414 @param[in] Wrap Point to HTTP token's wrap data.
416 @retval EFI_SUCCESS The events is created successfully.
417 @retval others Other error as indicated.
421 HttpCreateTcpTxEvent (
422 IN HTTP_TOKEN_WRAP
*Wrap
426 HTTP_PROTOCOL
*HttpInstance
;
427 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
429 HttpInstance
= Wrap
->HttpInstance
;
430 TcpWrap
= &Wrap
->TcpWrap
;
432 if (!HttpInstance
->LocalAddressIsIPv6
) {
433 Status
= gBS
->CreateEvent (
436 HttpTcpTransmitNotify
,
438 &TcpWrap
->Tx4Token
.CompletionToken
.Event
440 if (EFI_ERROR (Status
)) {
444 TcpWrap
->Tx4Data
.Push
= TRUE
;
445 TcpWrap
->Tx4Data
.Urgent
= FALSE
;
446 TcpWrap
->Tx4Data
.FragmentCount
= 1;
447 TcpWrap
->Tx4Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx4Data
;
448 TcpWrap
->Tx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
451 Status
= gBS
->CreateEvent (
454 HttpTcpTransmitNotify
,
456 &TcpWrap
->Tx6Token
.CompletionToken
.Event
458 if (EFI_ERROR (Status
)) {
462 TcpWrap
->Tx6Data
.Push
= TRUE
;
463 TcpWrap
->Tx6Data
.Urgent
= FALSE
;
464 TcpWrap
->Tx6Data
.FragmentCount
= 1;
465 TcpWrap
->Tx6Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx6Data
;
466 TcpWrap
->Tx6Token
.CompletionToken
.Status
=EFI_NOT_READY
;
474 Create event for the TCP receive token which is used to receive HTTP header.
476 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
478 @retval EFI_SUCCESS The events is created successfully.
479 @retval others Other error as indicated.
483 HttpCreateTcpRxEventForHeader (
484 IN HTTP_PROTOCOL
*HttpInstance
489 if (!HttpInstance
->LocalAddressIsIPv6
) {
490 Status
= gBS
->CreateEvent (
494 &HttpInstance
->IsRxDone
,
495 &HttpInstance
->Rx4Token
.CompletionToken
.Event
497 if (EFI_ERROR (Status
)) {
501 HttpInstance
->Rx4Data
.FragmentCount
= 1;
502 HttpInstance
->Rx4Token
.Packet
.RxData
= &HttpInstance
->Rx4Data
;
503 HttpInstance
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
506 Status
= gBS
->CreateEvent (
510 &HttpInstance
->IsRxDone
,
511 &HttpInstance
->Rx6Token
.CompletionToken
.Event
513 if (EFI_ERROR (Status
)) {
517 HttpInstance
->Rx6Data
.FragmentCount
=1;
518 HttpInstance
->Rx6Token
.Packet
.RxData
= &HttpInstance
->Rx6Data
;
519 HttpInstance
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
528 Create event for the TCP receive token which is used to receive HTTP body.
530 @param[in] Wrap Point to HTTP token's wrap data.
532 @retval EFI_SUCCESS The events is created successfully.
533 @retval others Other error as indicated.
537 HttpCreateTcpRxEvent (
538 IN HTTP_TOKEN_WRAP
*Wrap
542 HTTP_PROTOCOL
*HttpInstance
;
543 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
545 HttpInstance
= Wrap
->HttpInstance
;
546 TcpWrap
= &Wrap
->TcpWrap
;
547 if (!HttpInstance
->LocalAddressIsIPv6
) {
548 Status
= gBS
->CreateEvent (
551 HttpTcpReceiveNotify
,
553 &TcpWrap
->Rx4Token
.CompletionToken
.Event
555 if (EFI_ERROR (Status
)) {
559 TcpWrap
->Rx4Data
.FragmentCount
= 1;
560 TcpWrap
->Rx4Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx4Data
;
561 TcpWrap
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
564 Status
= gBS
->CreateEvent (
567 HttpTcpReceiveNotify
,
569 &TcpWrap
->Rx6Token
.CompletionToken
.Event
571 if (EFI_ERROR (Status
)) {
575 TcpWrap
->Rx6Data
.FragmentCount
= 1;
576 TcpWrap
->Rx6Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx6Data
;
577 TcpWrap
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
584 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.
586 @param[in] Wrap Pointer to HTTP token's wrap data.
590 HttpCloseTcpRxEvent (
591 IN HTTP_TOKEN_WRAP
*Wrap
594 HTTP_PROTOCOL
*HttpInstance
;
596 ASSERT (Wrap
!= NULL
);
597 HttpInstance
= Wrap
->HttpInstance
;
599 if (HttpInstance
->LocalAddressIsIPv6
) {
600 if (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
!= NULL
) {
601 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
604 if (HttpInstance
->Rx6Token
.CompletionToken
.Event
!= NULL
) {
605 gBS
->CloseEvent (HttpInstance
->Rx6Token
.CompletionToken
.Event
);
606 HttpInstance
->Rx6Token
.CompletionToken
.Event
= NULL
;
609 if (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
!= NULL
) {
610 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
613 if (HttpInstance
->Rx4Token
.CompletionToken
.Event
!= NULL
) {
614 gBS
->CloseEvent (HttpInstance
->Rx4Token
.CompletionToken
.Event
);
615 HttpInstance
->Rx4Token
.CompletionToken
.Event
= NULL
;
621 Initialize the HTTP_PROTOCOL structure to the unconfigured state.
623 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
624 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.
626 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
627 @retval Others Other error as indicated.
632 IN OUT HTTP_PROTOCOL
*HttpInstance
,
640 ASSERT (HttpInstance
!= NULL
);
641 UsingIpv6
= IpVersion
;
645 // Create TCP4 child.
647 Status
= NetLibCreateServiceChild (
648 HttpInstance
->Service
->ControllerHandle
,
649 HttpInstance
->Service
->Ip4DriverBindingHandle
,
650 &gEfiTcp4ServiceBindingProtocolGuid
,
651 &HttpInstance
->Tcp4ChildHandle
654 if (EFI_ERROR (Status
)) {
658 Status
= gBS
->OpenProtocol (
659 HttpInstance
->Tcp4ChildHandle
,
660 &gEfiTcp4ProtocolGuid
,
661 (VOID
**) &Interface
,
662 HttpInstance
->Service
->Ip4DriverBindingHandle
,
663 HttpInstance
->Service
->ControllerHandle
,
664 EFI_OPEN_PROTOCOL_BY_DRIVER
667 if (EFI_ERROR (Status
)) {
671 Status
= gBS
->OpenProtocol (
672 HttpInstance
->Tcp4ChildHandle
,
673 &gEfiTcp4ProtocolGuid
,
674 (VOID
**) &HttpInstance
->Tcp4
,
675 HttpInstance
->Service
->Ip4DriverBindingHandle
,
676 HttpInstance
->Handle
,
677 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
679 if (EFI_ERROR(Status
)) {
683 Status
= gBS
->OpenProtocol (
684 HttpInstance
->Service
->Tcp4ChildHandle
,
685 &gEfiTcp4ProtocolGuid
,
686 (VOID
**) &Interface
,
687 HttpInstance
->Service
->Ip4DriverBindingHandle
,
688 HttpInstance
->Handle
,
689 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
691 if (EFI_ERROR(Status
)) {
696 // Create TCP6 Child.
698 Status
= NetLibCreateServiceChild (
699 HttpInstance
->Service
->ControllerHandle
,
700 HttpInstance
->Service
->Ip6DriverBindingHandle
,
701 &gEfiTcp6ServiceBindingProtocolGuid
,
702 &HttpInstance
->Tcp6ChildHandle
705 if (EFI_ERROR (Status
)) {
709 Status
= gBS
->OpenProtocol (
710 HttpInstance
->Tcp6ChildHandle
,
711 &gEfiTcp6ProtocolGuid
,
712 (VOID
**) &Interface
,
713 HttpInstance
->Service
->Ip6DriverBindingHandle
,
714 HttpInstance
->Service
->ControllerHandle
,
715 EFI_OPEN_PROTOCOL_BY_DRIVER
718 if (EFI_ERROR (Status
)) {
722 Status
= gBS
->OpenProtocol (
723 HttpInstance
->Tcp6ChildHandle
,
724 &gEfiTcp6ProtocolGuid
,
725 (VOID
**) &HttpInstance
->Tcp6
,
726 HttpInstance
->Service
->Ip6DriverBindingHandle
,
727 HttpInstance
->Handle
,
728 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
731 if (EFI_ERROR(Status
)) {
735 Status
= gBS
->OpenProtocol (
736 HttpInstance
->Service
->Tcp6ChildHandle
,
737 &gEfiTcp6ProtocolGuid
,
738 (VOID
**) &Interface
,
739 HttpInstance
->Service
->Ip6DriverBindingHandle
,
740 HttpInstance
->Handle
,
741 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
744 if (EFI_ERROR(Status
)) {
749 HttpInstance
->Url
= AllocateZeroPool (HTTP_URL_BUFFER_LEN
);
750 if (HttpInstance
->Url
== NULL
) {
751 Status
= EFI_OUT_OF_RESOURCES
;
759 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
761 HttpInstance
->Tcp4ChildHandle
,
762 &gEfiTcp4ProtocolGuid
,
763 HttpInstance
->Service
->Ip4DriverBindingHandle
,
764 HttpInstance
->Service
->ControllerHandle
768 HttpInstance
->Tcp4ChildHandle
,
769 &gEfiTcp4ProtocolGuid
,
770 HttpInstance
->Service
->Ip4DriverBindingHandle
,
774 NetLibDestroyServiceChild (
775 HttpInstance
->Service
->ControllerHandle
,
776 HttpInstance
->Service
->Ip4DriverBindingHandle
,
777 &gEfiTcp4ServiceBindingProtocolGuid
,
778 HttpInstance
->Tcp4ChildHandle
782 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
784 HttpInstance
->Service
->Tcp4ChildHandle
,
785 &gEfiTcp4ProtocolGuid
,
786 HttpInstance
->Service
->Ip4DriverBindingHandle
,
791 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
793 HttpInstance
->Tcp6ChildHandle
,
794 &gEfiTcp6ProtocolGuid
,
795 HttpInstance
->Service
->Ip6DriverBindingHandle
,
796 HttpInstance
->Service
->ControllerHandle
800 HttpInstance
->Tcp6ChildHandle
,
801 &gEfiTcp6ProtocolGuid
,
802 HttpInstance
->Service
->Ip6DriverBindingHandle
,
806 NetLibDestroyServiceChild (
807 HttpInstance
->Service
->ControllerHandle
,
808 HttpInstance
->Service
->Ip6DriverBindingHandle
,
809 &gEfiTcp6ServiceBindingProtocolGuid
,
810 HttpInstance
->Tcp6ChildHandle
814 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
816 HttpInstance
->Service
->Tcp6ChildHandle
,
817 &gEfiTcp6ProtocolGuid
,
818 HttpInstance
->Service
->Ip6DriverBindingHandle
,
823 return EFI_UNSUPPORTED
;
828 Clean up the HTTP child, release all the resources used by it.
830 @param[in] HttpInstance The HTTP child to clean up.
835 IN HTTP_PROTOCOL
*HttpInstance
838 HttpCloseConnection (HttpInstance
);
840 HttpCloseTcpConnCloseEvent (HttpInstance
);
842 if (HttpInstance
->TimeoutEvent
!= NULL
) {
843 gBS
->CloseEvent (HttpInstance
->TimeoutEvent
);
844 HttpInstance
->TimeoutEvent
= NULL
;
847 if (HttpInstance
->CacheBody
!= NULL
) {
848 FreePool (HttpInstance
->CacheBody
);
849 HttpInstance
->CacheBody
= NULL
;
850 HttpInstance
->NextMsg
= NULL
;
853 if (HttpInstance
->RemoteHost
!= NULL
) {
854 FreePool (HttpInstance
->RemoteHost
);
855 HttpInstance
->RemoteHost
= NULL
;
858 if (HttpInstance
->MsgParser
!= NULL
) {
859 HttpFreeMsgParser (HttpInstance
->MsgParser
);
860 HttpInstance
->MsgParser
= NULL
;
863 if (HttpInstance
->Url
!= NULL
) {
864 FreePool (HttpInstance
->Url
);
865 HttpInstance
->Url
= NULL
;
868 NetMapClean (&HttpInstance
->TxTokens
);
869 NetMapClean (&HttpInstance
->RxTokens
);
871 if (HttpInstance
->TlsSb
!= NULL
&& HttpInstance
->TlsChildHandle
!= NULL
) {
873 // Destroy the TLS instance.
875 HttpInstance
->TlsSb
->DestroyChild (HttpInstance
->TlsSb
, HttpInstance
->TlsChildHandle
);
876 HttpInstance
->TlsChildHandle
= NULL
;
879 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
881 HttpInstance
->Tcp4ChildHandle
,
882 &gEfiTcp4ProtocolGuid
,
883 HttpInstance
->Service
->Ip4DriverBindingHandle
,
884 HttpInstance
->Service
->ControllerHandle
888 HttpInstance
->Tcp4ChildHandle
,
889 &gEfiTcp4ProtocolGuid
,
890 HttpInstance
->Service
->Ip4DriverBindingHandle
,
894 NetLibDestroyServiceChild (
895 HttpInstance
->Service
->ControllerHandle
,
896 HttpInstance
->Service
->Ip4DriverBindingHandle
,
897 &gEfiTcp4ServiceBindingProtocolGuid
,
898 HttpInstance
->Tcp4ChildHandle
902 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
904 HttpInstance
->Service
->Tcp4ChildHandle
,
905 &gEfiTcp4ProtocolGuid
,
906 HttpInstance
->Service
->Ip4DriverBindingHandle
,
911 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
913 HttpInstance
->Tcp6ChildHandle
,
914 &gEfiTcp6ProtocolGuid
,
915 HttpInstance
->Service
->Ip6DriverBindingHandle
,
916 HttpInstance
->Service
->ControllerHandle
920 HttpInstance
->Tcp6ChildHandle
,
921 &gEfiTcp6ProtocolGuid
,
922 HttpInstance
->Service
->Ip6DriverBindingHandle
,
926 NetLibDestroyServiceChild (
927 HttpInstance
->Service
->ControllerHandle
,
928 HttpInstance
->Service
->Ip6DriverBindingHandle
,
929 &gEfiTcp6ServiceBindingProtocolGuid
,
930 HttpInstance
->Tcp6ChildHandle
934 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
936 HttpInstance
->Service
->Tcp6ChildHandle
,
937 &gEfiTcp6ProtocolGuid
,
938 HttpInstance
->Service
->Ip6DriverBindingHandle
,
943 TlsCloseTxRxEvent (HttpInstance
);
947 Establish TCP connection with HTTP server.
949 @param[in] HttpInstance The HTTP instance private data.
951 @retval EFI_SUCCESS The TCP connection is established.
952 @retval Others Other error as indicated.
956 HttpCreateConnection (
957 IN HTTP_PROTOCOL
*HttpInstance
963 // Connect to Http server
965 if (!HttpInstance
->LocalAddressIsIPv6
) {
966 HttpInstance
->IsTcp4ConnDone
= FALSE
;
967 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
968 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4ConnToken
);
969 HttpNotify (HttpEventConnectTcp
, Status
);
970 if (EFI_ERROR (Status
)) {
971 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
975 while (!HttpInstance
->IsTcp4ConnDone
) {
976 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
979 Status
= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
;
982 HttpInstance
->IsTcp6ConnDone
= FALSE
;
983 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
984 Status
= HttpInstance
->Tcp6
->Connect (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6ConnToken
);
985 HttpNotify (HttpEventConnectTcp
, Status
);
986 if (EFI_ERROR (Status
)) {
987 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status
));
991 while(!HttpInstance
->IsTcp6ConnDone
) {
992 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
995 Status
= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
;
998 if (!EFI_ERROR (Status
)) {
999 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
1006 Close existing TCP connection.
1008 @param[in] HttpInstance The HTTP instance private data.
1010 @retval EFI_SUCCESS The TCP connection is closed.
1011 @retval Others Other error as indicated.
1015 HttpCloseConnection (
1016 IN HTTP_PROTOCOL
*HttpInstance
1021 if (HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) {
1023 if (HttpInstance
->LocalAddressIsIPv6
) {
1024 HttpInstance
->Tcp6CloseToken
.AbortOnClose
= TRUE
;
1025 HttpInstance
->IsTcp6CloseDone
= FALSE
;
1026 Status
= HttpInstance
->Tcp6
->Close (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6CloseToken
);
1027 if (EFI_ERROR (Status
)) {
1031 while (!HttpInstance
->IsTcp6CloseDone
) {
1032 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
1036 HttpInstance
->Tcp4CloseToken
.AbortOnClose
= TRUE
;
1037 HttpInstance
->IsTcp4CloseDone
= FALSE
;
1038 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4CloseToken
);
1039 if (EFI_ERROR (Status
)) {
1043 while (!HttpInstance
->IsTcp4CloseDone
) {
1044 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
1050 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
1055 Configure TCP4 protocol child.
1057 @param[in] HttpInstance The HTTP instance private data.
1058 @param[in] Wrap The HTTP token's wrap data.
1060 @retval EFI_SUCCESS The TCP4 protocol child is configured.
1061 @retval Others Other error as indicated.
1066 IN HTTP_PROTOCOL
*HttpInstance
,
1067 IN HTTP_TOKEN_WRAP
*Wrap
1071 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
1072 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
1073 EFI_TCP4_OPTION
*Tcp4Option
;
1075 ASSERT (HttpInstance
!= NULL
);
1078 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
1079 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
1081 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
1082 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
1083 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
1085 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
1086 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
1087 if (!Tcp4AP
->UseDefaultAddress
) {
1088 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
1089 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
1092 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
1093 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
1094 Tcp4AP
->ActiveFlag
= TRUE
;
1095 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
1097 Tcp4Option
= Tcp4CfgData
->ControlOption
;
1098 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1099 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1100 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1101 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1102 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
1103 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1104 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1105 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1106 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1107 Tcp4Option
->EnableNagle
= TRUE
;
1108 Tcp4CfgData
->ControlOption
= Tcp4Option
;
1110 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
1111 if (EFI_ERROR (Status
)) {
1112 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
1116 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1117 if (EFI_ERROR (Status
)) {
1121 Status
= HttpCreateTcpTxEvent (Wrap
);
1122 if (EFI_ERROR (Status
)) {
1126 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1132 Configure TCP6 protocol child.
1134 @param[in] HttpInstance The HTTP instance private data.
1135 @param[in] Wrap The HTTP token's wrap data.
1137 @retval EFI_SUCCESS The TCP6 protocol child is configured.
1138 @retval Others Other error as indicated.
1143 IN HTTP_PROTOCOL
*HttpInstance
,
1144 IN HTTP_TOKEN_WRAP
*Wrap
1148 EFI_TCP6_CONFIG_DATA
*Tcp6CfgData
;
1149 EFI_TCP6_ACCESS_POINT
*Tcp6Ap
;
1150 EFI_TCP6_OPTION
*Tcp6Option
;
1152 ASSERT (HttpInstance
!= NULL
);
1154 Tcp6CfgData
= &HttpInstance
->Tcp6CfgData
;
1155 ZeroMem (Tcp6CfgData
, sizeof (EFI_TCP6_CONFIG_DATA
));
1157 Tcp6CfgData
->TrafficClass
= 0;
1158 Tcp6CfgData
->HopLimit
= 255;
1159 Tcp6CfgData
->ControlOption
= &HttpInstance
->Tcp6Option
;
1161 Tcp6Ap
= &Tcp6CfgData
->AccessPoint
;
1162 Tcp6Ap
->ActiveFlag
= TRUE
;
1163 Tcp6Ap
->StationPort
= HttpInstance
->Ipv6Node
.LocalPort
;
1164 Tcp6Ap
->RemotePort
= HttpInstance
->RemotePort
;
1165 IP6_COPY_ADDRESS (&Tcp6Ap
->StationAddress
, &HttpInstance
->Ipv6Node
.LocalAddress
);
1166 IP6_COPY_ADDRESS (&Tcp6Ap
->RemoteAddress
, &HttpInstance
->RemoteIpv6Addr
);
1168 Tcp6Option
= Tcp6CfgData
->ControlOption
;
1169 Tcp6Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1170 Tcp6Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1171 Tcp6Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1172 Tcp6Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1173 Tcp6Option
->DataRetries
= HTTP_DATA_RETRIES
;
1174 Tcp6Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1175 Tcp6Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1176 Tcp6Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1177 Tcp6Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1178 Tcp6Option
->EnableNagle
= TRUE
;
1180 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, Tcp6CfgData
);
1181 if (EFI_ERROR (Status
)) {
1182 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp6 - %r\n", Status
));
1186 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1187 if (EFI_ERROR (Status
)) {
1191 Status
= HttpCreateTcpTxEvent (Wrap
);
1192 if (EFI_ERROR (Status
)) {
1196 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1203 Check existing TCP connection, if in error state, recover TCP4 connection. Then,
1204 connect one TLS session if required.
1206 @param[in] HttpInstance The HTTP instance private data.
1208 @retval EFI_SUCCESS The TCP connection is established.
1209 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1210 @retval Others Other error as indicated.
1215 IN HTTP_PROTOCOL
*HttpInstance
1219 EFI_TCP4_CONNECTION_STATE Tcp4State
;
1222 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp4
== NULL
) {
1223 return EFI_NOT_READY
;
1226 Status
= HttpInstance
->Tcp4
->GetModeData(
1234 if (EFI_ERROR(Status
)){
1235 DEBUG ((EFI_D_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
1239 if (Tcp4State
== Tcp4StateEstablished
) {
1241 } else if (Tcp4State
> Tcp4StateEstablished
) {
1242 HttpCloseConnection(HttpInstance
);
1245 Status
= HttpCreateConnection (HttpInstance
);
1246 if (EFI_ERROR(Status
)){
1247 DEBUG ((EFI_D_ERROR
, "Tcp4 Connection fail - %x\n", Status
));
1252 // Tls session connection.
1254 if (HttpInstance
->UseHttps
) {
1255 if (HttpInstance
->TimeoutEvent
== NULL
) {
1257 // Create TimeoutEvent for TLS connection.
1259 Status
= gBS
->CreateEvent (
1264 &HttpInstance
->TimeoutEvent
1266 if (EFI_ERROR (Status
)) {
1267 TlsCloseTxRxEvent (HttpInstance
);
1273 // Start the timer, and wait Timeout seconds for connection.
1275 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1276 if (EFI_ERROR (Status
)) {
1277 TlsCloseTxRxEvent (HttpInstance
);
1281 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1282 HttpNotify (HttpEventTlsConnectSession
, Status
);
1284 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1286 if (EFI_ERROR (Status
)) {
1287 TlsCloseTxRxEvent (HttpInstance
);
1296 Check existing TCP connection, if in error state, recover TCP6 connection. Then,
1297 connect one TLS session if required.
1299 @param[in] HttpInstance The HTTP instance private data.
1301 @retval EFI_SUCCESS The TCP connection is established.
1302 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1303 @retval Others Other error as indicated.
1308 IN HTTP_PROTOCOL
*HttpInstance
1312 EFI_TCP6_CONNECTION_STATE Tcp6State
;
1314 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp6
== NULL
) {
1315 return EFI_NOT_READY
;
1318 Status
= HttpInstance
->Tcp6
->GetModeData (
1327 if (EFI_ERROR(Status
)){
1328 DEBUG ((EFI_D_ERROR
, "Tcp6 GetModeData fail - %x\n", Status
));
1332 if (Tcp6State
== Tcp6StateEstablished
) {
1334 } else if (Tcp6State
> Tcp6StateEstablished
) {
1335 HttpCloseConnection(HttpInstance
);
1338 Status
= HttpCreateConnection (HttpInstance
);
1339 if (EFI_ERROR(Status
)){
1340 DEBUG ((EFI_D_ERROR
, "Tcp6 Connection fail - %x\n", Status
));
1345 // Tls session connection.
1347 if (HttpInstance
->UseHttps
) {
1348 if (HttpInstance
->TimeoutEvent
== NULL
) {
1350 // Create TimeoutEvent for TLS connection.
1352 Status
= gBS
->CreateEvent (
1357 &HttpInstance
->TimeoutEvent
1359 if (EFI_ERROR (Status
)) {
1360 TlsCloseTxRxEvent (HttpInstance
);
1366 // Start the timer, and wait Timeout seconds for connection.
1368 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1369 if (EFI_ERROR (Status
)) {
1370 TlsCloseTxRxEvent (HttpInstance
);
1374 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1375 HttpNotify (HttpEventTlsConnectSession
, Status
);
1377 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1379 if (EFI_ERROR (Status
)) {
1380 TlsCloseTxRxEvent (HttpInstance
);
1389 Initialize Http session.
1391 @param[in] HttpInstance The HTTP instance private data.
1392 @param[in] Wrap The HTTP token's wrap data.
1393 @param[in] Configure The Flag indicates whether need to initialize session.
1394 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session.
1396 @retval EFI_SUCCESS The initialization of session is done.
1397 @retval Others Other error as indicated.
1402 IN HTTP_PROTOCOL
*HttpInstance
,
1403 IN HTTP_TOKEN_WRAP
*Wrap
,
1404 IN BOOLEAN Configure
,
1405 IN BOOLEAN TlsConfigure
1409 ASSERT (HttpInstance
!= NULL
);
1412 // Configure Tls session.
1415 Status
= TlsConfigureSession (HttpInstance
);
1416 if (EFI_ERROR (Status
)) {
1421 if (!HttpInstance
->LocalAddressIsIPv6
) {
1423 // Configure TCP instance.
1426 Status
= HttpConfigureTcp4 (HttpInstance
, Wrap
);
1427 if (EFI_ERROR (Status
)) {
1435 Status
= HttpConnectTcp4 (HttpInstance
);
1436 if (EFI_ERROR (Status
)) {
1441 // Configure TCP instance.
1444 Status
= HttpConfigureTcp6 (HttpInstance
, Wrap
);
1445 if (EFI_ERROR (Status
)) {
1453 Status
= HttpConnectTcp6 (HttpInstance
);
1454 if (EFI_ERROR (Status
)) {
1464 Send the HTTP or HTTPS message through TCP4 or TCP6.
1466 @param[in] HttpInstance The HTTP instance private data.
1467 @param[in] Wrap The HTTP token's wrap data.
1468 @param[in] TxString Buffer containing the HTTP message string.
1469 @param[in] TxStringLen Length of the HTTP message string in bytes.
1471 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1472 @retval Others Other error as indicated.
1477 IN HTTP_PROTOCOL
*HttpInstance
,
1478 IN HTTP_TOKEN_WRAP
*Wrap
,
1480 IN UINTN TxStringLen
1484 EFI_TCP4_IO_TOKEN
*Tx4Token
;
1485 EFI_TCP4_PROTOCOL
*Tcp4
;
1486 EFI_TCP6_IO_TOKEN
*Tx6Token
;
1487 EFI_TCP6_PROTOCOL
*Tcp6
;
1490 NET_FRAGMENT TempFragment
;
1491 NET_FRAGMENT Fragment
;
1495 Status
= EFI_SUCCESS
;
1498 TempFragment
.Len
= 0;
1499 TempFragment
.Bulk
= NULL
;
1501 Fragment
.Bulk
= NULL
;
1506 // Need to encrypt data.
1508 if (HttpInstance
->UseHttps
) {
1510 // Allocate enough buffer for each TLS plaintext records.
1512 TlsRecord
= AllocateZeroPool (TLS_RECORD_HEADER_LENGTH
+ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
);
1513 if (TlsRecord
== NULL
) {
1514 Status
= EFI_OUT_OF_RESOURCES
;
1519 // Allocate enough buffer for all TLS ciphertext records.
1521 RecordCount
= TxStringLen
/ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
+ 1;
1522 Fragment
.Bulk
= AllocateZeroPool (RecordCount
* (TLS_RECORD_HEADER_LENGTH
+ TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH
));
1523 if (Fragment
.Bulk
== NULL
) {
1524 Status
= EFI_OUT_OF_RESOURCES
;
1529 // Encrypt each TLS plaintext records.
1531 RemainingLen
= TxStringLen
;
1532 while (RemainingLen
!= 0) {
1533 PayloadSize
= (UINT16
) MIN (TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
, RemainingLen
);
1535 ((TLS_RECORD_HEADER
*) TlsRecord
)->ContentType
= TlsContentTypeApplicationData
;
1536 ((TLS_RECORD_HEADER
*) TlsRecord
)->Version
.Major
= HttpInstance
->TlsConfigData
.Version
.Major
;
1537 ((TLS_RECORD_HEADER
*) TlsRecord
)->Version
.Minor
= HttpInstance
->TlsConfigData
.Version
.Minor
;
1538 ((TLS_RECORD_HEADER
*) TlsRecord
)->Length
= PayloadSize
;
1540 CopyMem (TlsRecord
+ TLS_RECORD_HEADER_LENGTH
, TxString
+ (TxStringLen
- RemainingLen
), PayloadSize
);
1542 Status
= TlsProcessMessage (
1545 TLS_RECORD_HEADER_LENGTH
+ PayloadSize
,
1549 if (EFI_ERROR (Status
)) {
1554 // Record the processed/encrypted Packet.
1556 CopyMem (Fragment
.Bulk
+ Fragment
.Len
, TempFragment
.Bulk
, TempFragment
.Len
);
1557 Fragment
.Len
+= TempFragment
.Len
;
1559 FreePool (TempFragment
.Bulk
);
1560 TempFragment
.Len
= 0;
1561 TempFragment
.Bulk
= NULL
;
1563 RemainingLen
-= (UINTN
) PayloadSize
;
1564 ZeroMem (TlsRecord
, TLS_RECORD_HEADER_LENGTH
+ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
);
1567 FreePool (TlsRecord
);
1571 if (!HttpInstance
->LocalAddressIsIPv6
) {
1572 Tcp4
= HttpInstance
->Tcp4
;
1573 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1575 if (HttpInstance
->UseHttps
) {
1576 Tx4Token
->Packet
.TxData
->DataLength
= Fragment
.Len
;
1577 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= Fragment
.Len
;
1578 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) Fragment
.Bulk
;
1580 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1581 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1582 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1585 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1587 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1588 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1589 if (EFI_ERROR (Status
)) {
1590 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1595 Tcp6
= HttpInstance
->Tcp6
;
1596 Tx6Token
= &Wrap
->TcpWrap
.Tx6Token
;
1598 if (HttpInstance
->UseHttps
) {
1599 Tx6Token
->Packet
.TxData
->DataLength
= Fragment
.Len
;
1600 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= Fragment
.Len
;
1601 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) Fragment
.Bulk
;
1603 Tx6Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1604 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1605 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1608 Tx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1610 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1611 Status
= Tcp6
->Transmit (Tcp6
, Tx6Token
);
1612 if (EFI_ERROR (Status
)) {
1613 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1622 if (HttpInstance
->UseHttps
) {
1623 if (TlsRecord
!= NULL
) {
1624 FreePool (TlsRecord
);
1628 if (Fragment
.Bulk
!= NULL
) {
1629 FreePool (Fragment
.Bulk
);
1630 Fragment
.Bulk
= NULL
;
1638 Check whether the user's token or event has already
1639 been enqueue on HTTP Tx or Rx Token list.
1641 @param[in] Map The container of either user's transmit or receive
1643 @param[in] Item Current item to check against.
1644 @param[in] Context The Token to check against.
1646 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1647 @retval EFI_SUCCESS The current item isn't the same token/event as the
1655 IN NET_MAP_ITEM
*Item
,
1659 EFI_HTTP_TOKEN
*Token
;
1660 EFI_HTTP_TOKEN
*TokenInItem
;
1662 Token
= (EFI_HTTP_TOKEN
*) Context
;
1663 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
1665 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
1666 return EFI_ACCESS_DENIED
;
1673 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1675 @param[in] Map The container of Tx4Token or Tx6Token.
1676 @param[in] Item Current item to check against.
1677 @param[in] Context The Token to check against.
1679 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1680 @retval EFI_SUCCESS The HTTP message has been sent out.
1687 IN NET_MAP_ITEM
*Item
,
1691 HTTP_TOKEN_WRAP
*ValueInItem
;
1693 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1695 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
1696 return EFI_NOT_READY
;
1703 Transmit the HTTP or HTTPS message by processing the associated HTTP token.
1705 @param[in] Map The container of Tx4Token or Tx6Token.
1706 @param[in] Item Current item to check against.
1707 @param[in] Context The Token to check against.
1709 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1710 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1718 IN NET_MAP_ITEM
*Item
,
1722 HTTP_TOKEN_WRAP
*ValueInItem
;
1727 UINTN RequestMsgSize
;
1731 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1732 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1737 // Parse the URI of the remote host.
1739 UrlSize
= StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1;
1740 Url
= AllocatePool (UrlSize
);
1742 return EFI_OUT_OF_RESOURCES
;
1745 UnicodeStrToAsciiStrS (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
, UrlSize
);
1748 // Create request message.
1750 Status
= HttpGenRequestMessage (
1751 ValueInItem
->HttpToken
->Message
,
1758 if (EFI_ERROR (Status
) || NULL
== RequestMsg
){
1762 ASSERT (RequestMsg
!= NULL
);
1765 // Transmit the request message.
1767 Status
= HttpTransmitTcp (
1768 ValueInItem
->HttpInstance
,
1770 (UINT8
*) RequestMsg
,
1773 FreePool (RequestMsg
);
1778 Receive the HTTP response by processing the associated HTTP token.
1780 @param[in] Map The container of Rx4Token or Rx6Token.
1781 @param[in] Item Current item to check against.
1782 @param[in] Context The Token to check against.
1784 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1786 @retval Others Other error as indicated.
1793 IN NET_MAP_ITEM
*Item
,
1798 // Process the queued HTTP response.
1800 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1804 Receive the HTTP header by processing the associated HTTP token.
1806 @param[in] HttpInstance The HTTP instance private data.
1807 @param[in, out] SizeofHeaders The HTTP header length.
1808 @param[in, out] BufferSize The size of buffer to cache the header message.
1809 @param[in] Timeout The time to wait for receiving the header packet.
1811 @retval EFI_SUCCESS The HTTP header is received.
1812 @retval Others Other errors as indicated.
1816 HttpTcpReceiveHeader (
1817 IN HTTP_PROTOCOL
*HttpInstance
,
1818 IN OUT UINTN
*SizeofHeaders
,
1819 IN OUT UINTN
*BufferSize
,
1820 IN EFI_EVENT Timeout
1824 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1825 EFI_TCP4_PROTOCOL
*Tcp4
;
1826 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1827 EFI_TCP6_PROTOCOL
*Tcp6
;
1828 CHAR8
**EndofHeader
;
1829 CHAR8
**HttpHeaders
;
1831 NET_FRAGMENT Fragment
;
1833 ASSERT (HttpInstance
!= NULL
);
1835 EndofHeader
= HttpInstance
->EndofHeader
;
1836 HttpHeaders
= HttpInstance
->HttpHeaders
;
1837 Tcp4
= HttpInstance
->Tcp4
;
1838 Tcp6
= HttpInstance
->Tcp6
;
1843 Fragment
.Bulk
= NULL
;
1845 if (HttpInstance
->LocalAddressIsIPv6
) {
1846 ASSERT (Tcp6
!= NULL
);
1848 ASSERT (Tcp4
!= NULL
);
1851 if (!HttpInstance
->UseHttps
) {
1852 Status
= HttpCreateTcpRxEventForHeader (HttpInstance
);
1853 if (EFI_ERROR (Status
)) {
1858 if (!HttpInstance
->LocalAddressIsIPv6
) {
1859 if (!HttpInstance
->UseHttps
) {
1860 Rx4Token
= &HttpInstance
->Rx4Token
;
1861 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1862 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1863 Status
= EFI_OUT_OF_RESOURCES
;
1869 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1871 while (*EndofHeader
== NULL
) {
1872 if (!HttpInstance
->UseHttps
) {
1873 HttpInstance
->IsRxDone
= FALSE
;
1874 Rx4Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1875 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1876 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1877 if (EFI_ERROR (Status
)) {
1878 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1882 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1886 if (!HttpInstance
->IsRxDone
) {
1888 // Cancel the Token before close its Event.
1890 Tcp4
->Cancel (HttpInstance
->Tcp4
, &Rx4Token
->CompletionToken
);
1891 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1892 Rx4Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1895 Status
= Rx4Token
->CompletionToken
.Status
;
1896 if (EFI_ERROR (Status
)) {
1900 Fragment
.Len
= Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1901 Fragment
.Bulk
= (UINT8
*) Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
1903 if (Fragment
.Bulk
!= NULL
) {
1904 FreePool (Fragment
.Bulk
);
1905 Fragment
.Bulk
= NULL
;
1908 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
1909 if (EFI_ERROR (Status
)) {
1910 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1916 // Append the response string along with a Null-terminator.
1918 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
1919 Buffer
= AllocatePool (*BufferSize
+ 1);
1920 if (Buffer
== NULL
) {
1921 Status
= EFI_OUT_OF_RESOURCES
;
1925 if (*HttpHeaders
!= NULL
) {
1926 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
1927 FreePool (*HttpHeaders
);
1931 Buffer
+ *SizeofHeaders
,
1935 *(Buffer
+ *BufferSize
) = '\0';
1936 *HttpHeaders
= Buffer
;
1937 *SizeofHeaders
= *BufferSize
;
1940 // Check whether we received end of HTTP headers.
1942 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1948 if (Rx4Token
!= NULL
&& Rx4Token
->Packet
.RxData
!= NULL
&& Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1949 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1950 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1951 Fragment
.Bulk
= NULL
;
1954 if (Fragment
.Bulk
!= NULL
) {
1955 FreePool (Fragment
.Bulk
);
1956 Fragment
.Bulk
= NULL
;
1959 if (!HttpInstance
->UseHttps
) {
1960 Rx6Token
= &HttpInstance
->Rx6Token
;
1961 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1962 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1963 Status
= EFI_OUT_OF_RESOURCES
;
1969 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1971 while (*EndofHeader
== NULL
) {
1972 if (!HttpInstance
->UseHttps
) {
1973 HttpInstance
->IsRxDone
= FALSE
;
1974 Rx6Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1975 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1976 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1977 if (EFI_ERROR (Status
)) {
1978 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1982 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1986 if (!HttpInstance
->IsRxDone
) {
1988 // Cancel the Token before close its Event.
1990 Tcp6
->Cancel (HttpInstance
->Tcp6
, &Rx6Token
->CompletionToken
);
1991 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1992 Rx6Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1995 Status
= Rx6Token
->CompletionToken
.Status
;
1996 if (EFI_ERROR (Status
)) {
2000 Fragment
.Len
= Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
2001 Fragment
.Bulk
= (UINT8
*) Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
2003 if (Fragment
.Bulk
!= NULL
) {
2004 FreePool (Fragment
.Bulk
);
2005 Fragment
.Bulk
= NULL
;
2008 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
2009 if (EFI_ERROR (Status
)) {
2010 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
2016 // Append the response string along with a Null-terminator.
2018 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
2019 Buffer
= AllocatePool (*BufferSize
+ 1);
2020 if (Buffer
== NULL
) {
2021 Status
= EFI_OUT_OF_RESOURCES
;
2025 if (*HttpHeaders
!= NULL
) {
2026 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
2027 FreePool (*HttpHeaders
);
2031 Buffer
+ *SizeofHeaders
,
2035 *(Buffer
+ *BufferSize
) = '\0';
2036 *HttpHeaders
= Buffer
;
2037 *SizeofHeaders
= *BufferSize
;
2040 // Check whether we received end of HTTP headers.
2042 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
2048 if (Rx6Token
!= NULL
&& Rx6Token
->Packet
.RxData
!= NULL
&& Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2049 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2050 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2051 Fragment
.Bulk
= NULL
;
2054 if (Fragment
.Bulk
!= NULL
) {
2055 FreePool (Fragment
.Bulk
);
2056 Fragment
.Bulk
= NULL
;
2061 // Skip the CRLF after the HTTP headers.
2063 *EndofHeader
= *EndofHeader
+ AsciiStrLen (HTTP_END_OF_HDR_STR
);
2065 *SizeofHeaders
= *EndofHeader
- *HttpHeaders
;
2071 Receive the HTTP body by processing the associated HTTP token.
2073 @param[in] Wrap The HTTP token's wrap data.
2074 @param[in] HttpMsg The HTTP message data.
2076 @retval EFI_SUCCESS The HTTP body is received.
2077 @retval Others Other error as indicated.
2081 HttpTcpReceiveBody (
2082 IN HTTP_TOKEN_WRAP
*Wrap
,
2083 IN EFI_HTTP_MESSAGE
*HttpMsg
2087 HTTP_PROTOCOL
*HttpInstance
;
2088 EFI_TCP6_PROTOCOL
*Tcp6
;
2089 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2090 EFI_TCP4_PROTOCOL
*Tcp4
;
2091 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2093 HttpInstance
= Wrap
->HttpInstance
;
2094 Tcp4
= HttpInstance
->Tcp4
;
2095 Tcp6
= HttpInstance
->Tcp6
;
2099 if (HttpInstance
->LocalAddressIsIPv6
) {
2100 ASSERT (Tcp6
!= NULL
);
2102 ASSERT (Tcp4
!= NULL
);
2105 if (HttpInstance
->LocalAddressIsIPv6
) {
2106 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2107 Rx6Token
->Packet
.RxData
->DataLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2108 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2109 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
2110 Rx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2112 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
2113 if (EFI_ERROR (Status
)) {
2114 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
2118 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2119 Rx4Token
->Packet
.RxData
->DataLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2120 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2121 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
2123 Rx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2124 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
2125 if (EFI_ERROR (Status
)) {
2126 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
2136 Clean up Tcp Tokens while the Tcp transmission error occurs.
2138 @param[in] Wrap Pointer to HTTP token's wrap data.
2142 HttpTcpTokenCleanup (
2143 IN HTTP_TOKEN_WRAP
*Wrap
2146 HTTP_PROTOCOL
*HttpInstance
;
2147 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2148 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2150 ASSERT (Wrap
!= NULL
);
2151 HttpInstance
= Wrap
->HttpInstance
;
2155 if (HttpInstance
->LocalAddressIsIPv6
) {
2156 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2158 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2159 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2160 Rx6Token
->CompletionToken
.Event
= NULL
;
2165 Rx6Token
= &HttpInstance
->Rx6Token
;
2167 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2168 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2169 Rx6Token
->CompletionToken
.Event
= NULL
;
2172 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2173 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2174 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2178 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2180 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2181 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2182 Rx4Token
->CompletionToken
.Event
= NULL
;
2187 Rx4Token
= &HttpInstance
->Rx4Token
;
2189 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2190 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2191 Rx4Token
->CompletionToken
.Event
= NULL
;
2195 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2196 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2197 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2204 Send Events via EDKII_HTTP_CALLBACK_PROTOCOL.
2206 @param[in] Event The event that occurs in the current state.
2207 @param[in] EventStatus The Status of Event, EFI_SUCCESS or other errors.
2212 IN EDKII_HTTP_CALLBACK_EVENT Event
,
2213 IN EFI_STATUS EventStatus
2217 EFI_HANDLE
*Handles
;
2221 EDKII_HTTP_CALLBACK_PROTOCOL
*HttpCallback
;
2223 DEBUG ((DEBUG_INFO
, "HttpNotify: Event - %d, EventStatus - %r\n", Event
, EventStatus
));
2227 Status
= gBS
->LocateHandleBuffer (
2229 &gEdkiiHttpCallbackProtocolGuid
,
2234 if (Status
== EFI_SUCCESS
) {
2235 for (Index
= 0; Index
< HandleCount
; Index
++) {
2236 Handle
= Handles
[Index
];
2237 Status
= gBS
->HandleProtocol (
2239 &gEdkiiHttpCallbackProtocolGuid
,
2240 (VOID
**) &HttpCallback
2242 if (Status
== EFI_SUCCESS
) {
2243 DEBUG ((DEBUG_INFO
, "HttpNotify: Notifying %p\n", HttpCallback
));
2244 HttpCallback
->Callback (