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 if ((HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) ||
1090 (HttpInstance
->State
== HTTP_STATE_TCP_CLOSED
))
1092 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, NULL
);
1093 if (EFI_ERROR (Status
)) {
1094 DEBUG ((DEBUG_ERROR
, "HttpConfigureTcp4(NULL) - %r\n", Status
));
1098 HttpInstance
->State
= HTTP_STATE_TCP_UNCONFIGED
;
1101 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
1102 if (EFI_ERROR (Status
)) {
1103 DEBUG ((DEBUG_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
1107 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1108 if (EFI_ERROR (Status
)) {
1112 Status
= HttpCreateTcpTxEvent (Wrap
);
1113 if (EFI_ERROR (Status
)) {
1117 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1123 Configure TCP6 protocol child.
1125 @param[in] HttpInstance The HTTP instance private data.
1126 @param[in] Wrap The HTTP token's wrap data.
1128 @retval EFI_SUCCESS The TCP6 protocol child is configured.
1129 @retval Others Other error as indicated.
1134 IN HTTP_PROTOCOL
*HttpInstance
,
1135 IN HTTP_TOKEN_WRAP
*Wrap
1139 EFI_TCP6_CONFIG_DATA
*Tcp6CfgData
;
1140 EFI_TCP6_ACCESS_POINT
*Tcp6Ap
;
1141 EFI_TCP6_OPTION
*Tcp6Option
;
1143 ASSERT (HttpInstance
!= NULL
);
1145 Tcp6CfgData
= &HttpInstance
->Tcp6CfgData
;
1146 ZeroMem (Tcp6CfgData
, sizeof (EFI_TCP6_CONFIG_DATA
));
1148 Tcp6CfgData
->TrafficClass
= 0;
1149 Tcp6CfgData
->HopLimit
= 255;
1150 Tcp6CfgData
->ControlOption
= &HttpInstance
->Tcp6Option
;
1152 Tcp6Ap
= &Tcp6CfgData
->AccessPoint
;
1153 Tcp6Ap
->ActiveFlag
= TRUE
;
1154 Tcp6Ap
->StationPort
= HttpInstance
->Ipv6Node
.LocalPort
;
1155 Tcp6Ap
->RemotePort
= HttpInstance
->RemotePort
;
1156 IP6_COPY_ADDRESS (&Tcp6Ap
->StationAddress
, &HttpInstance
->Ipv6Node
.LocalAddress
);
1157 IP6_COPY_ADDRESS (&Tcp6Ap
->RemoteAddress
, &HttpInstance
->RemoteIpv6Addr
);
1159 Tcp6Option
= Tcp6CfgData
->ControlOption
;
1160 Tcp6Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1161 Tcp6Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1162 Tcp6Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1163 Tcp6Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1164 Tcp6Option
->DataRetries
= HTTP_DATA_RETRIES
;
1165 Tcp6Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1166 Tcp6Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1167 Tcp6Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1168 Tcp6Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1169 Tcp6Option
->EnableNagle
= TRUE
;
1171 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, Tcp6CfgData
);
1172 if (EFI_ERROR (Status
)) {
1173 DEBUG ((DEBUG_ERROR
, "HttpConfigureTcp6 - %r\n", Status
));
1177 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1178 if (EFI_ERROR (Status
)) {
1182 Status
= HttpCreateTcpTxEvent (Wrap
);
1183 if (EFI_ERROR (Status
)) {
1187 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1193 Check existing TCP connection, if in error state, recover TCP4 connection. Then,
1194 connect one TLS session if required.
1196 @param[in] HttpInstance The HTTP instance private data.
1198 @retval EFI_SUCCESS The TCP connection is established.
1199 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1200 @retval Others Other error as indicated.
1205 IN HTTP_PROTOCOL
*HttpInstance
1209 EFI_TCP4_CONNECTION_STATE Tcp4State
;
1211 if ((HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
) || (HttpInstance
->Tcp4
== NULL
)) {
1212 return EFI_NOT_READY
;
1215 Status
= HttpInstance
->Tcp4
->GetModeData (
1223 if (EFI_ERROR (Status
)) {
1224 DEBUG ((DEBUG_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
1228 if (Tcp4State
== Tcp4StateEstablished
) {
1230 } else if (Tcp4State
> Tcp4StateEstablished
) {
1231 HttpCloseConnection (HttpInstance
);
1234 Status
= HttpCreateConnection (HttpInstance
);
1235 if (EFI_ERROR (Status
)) {
1236 DEBUG ((DEBUG_ERROR
, "Tcp4 Connection fail - %x\n", Status
));
1241 // Tls session connection.
1243 if (HttpInstance
->UseHttps
) {
1244 if (HttpInstance
->TimeoutEvent
== NULL
) {
1246 // Create TimeoutEvent for TLS connection.
1248 Status
= gBS
->CreateEvent (
1253 &HttpInstance
->TimeoutEvent
1255 if (EFI_ERROR (Status
)) {
1256 TlsCloseTxRxEvent (HttpInstance
);
1262 // Start the timer, and wait Timeout seconds for connection.
1264 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1265 if (EFI_ERROR (Status
)) {
1266 TlsCloseTxRxEvent (HttpInstance
);
1270 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1271 HttpNotify (HttpEventTlsConnectSession
, Status
);
1273 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1275 if (EFI_ERROR (Status
)) {
1276 TlsCloseTxRxEvent (HttpInstance
);
1285 Check existing TCP connection, if in error state, recover TCP6 connection. Then,
1286 connect one TLS session if required.
1288 @param[in] HttpInstance The HTTP instance private data.
1290 @retval EFI_SUCCESS The TCP connection is established.
1291 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1292 @retval Others Other error as indicated.
1297 IN HTTP_PROTOCOL
*HttpInstance
1301 EFI_TCP6_CONNECTION_STATE Tcp6State
;
1303 if ((HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
) || (HttpInstance
->Tcp6
== NULL
)) {
1304 return EFI_NOT_READY
;
1307 Status
= HttpInstance
->Tcp6
->GetModeData (
1316 if (EFI_ERROR (Status
)) {
1317 DEBUG ((DEBUG_ERROR
, "Tcp6 GetModeData fail - %x\n", Status
));
1321 if (Tcp6State
== Tcp6StateEstablished
) {
1323 } else if (Tcp6State
> Tcp6StateEstablished
) {
1324 HttpCloseConnection (HttpInstance
);
1327 Status
= HttpCreateConnection (HttpInstance
);
1328 if (EFI_ERROR (Status
)) {
1329 DEBUG ((DEBUG_ERROR
, "Tcp6 Connection fail - %x\n", Status
));
1334 // Tls session connection.
1336 if (HttpInstance
->UseHttps
) {
1337 if (HttpInstance
->TimeoutEvent
== NULL
) {
1339 // Create TimeoutEvent for TLS connection.
1341 Status
= gBS
->CreateEvent (
1346 &HttpInstance
->TimeoutEvent
1348 if (EFI_ERROR (Status
)) {
1349 TlsCloseTxRxEvent (HttpInstance
);
1355 // Start the timer, and wait Timeout seconds for connection.
1357 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1358 if (EFI_ERROR (Status
)) {
1359 TlsCloseTxRxEvent (HttpInstance
);
1363 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1364 HttpNotify (HttpEventTlsConnectSession
, Status
);
1366 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1368 if (EFI_ERROR (Status
)) {
1369 TlsCloseTxRxEvent (HttpInstance
);
1378 Initialize Http session.
1380 @param[in] HttpInstance The HTTP instance private data.
1381 @param[in] Wrap The HTTP token's wrap data.
1382 @param[in] Configure The Flag indicates whether need to initialize session.
1383 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session.
1385 @retval EFI_SUCCESS The initialization of session is done.
1386 @retval Others Other error as indicated.
1391 IN HTTP_PROTOCOL
*HttpInstance
,
1392 IN HTTP_TOKEN_WRAP
*Wrap
,
1393 IN BOOLEAN Configure
,
1394 IN BOOLEAN TlsConfigure
1399 ASSERT (HttpInstance
!= NULL
);
1402 // Configure Tls session.
1405 Status
= TlsConfigureSession (HttpInstance
);
1406 if (EFI_ERROR (Status
)) {
1411 if (!HttpInstance
->LocalAddressIsIPv6
) {
1413 // Configure TCP instance.
1416 Status
= HttpConfigureTcp4 (HttpInstance
, Wrap
);
1417 if (EFI_ERROR (Status
)) {
1425 Status
= HttpConnectTcp4 (HttpInstance
);
1426 if (EFI_ERROR (Status
)) {
1431 // Configure TCP instance.
1434 Status
= HttpConfigureTcp6 (HttpInstance
, Wrap
);
1435 if (EFI_ERROR (Status
)) {
1443 Status
= HttpConnectTcp6 (HttpInstance
);
1444 if (EFI_ERROR (Status
)) {
1453 Send the HTTP or HTTPS message through TCP4 or TCP6.
1455 @param[in] HttpInstance The HTTP instance private data.
1456 @param[in] Wrap The HTTP token's wrap data.
1457 @param[in] TxString Buffer containing the HTTP message string.
1458 @param[in] TxStringLen Length of the HTTP message string in bytes.
1460 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1461 @retval Others Other error as indicated.
1466 IN HTTP_PROTOCOL
*HttpInstance
,
1467 IN HTTP_TOKEN_WRAP
*Wrap
,
1469 IN UINTN TxStringLen
1473 EFI_TCP4_IO_TOKEN
*Tx4Token
;
1474 EFI_TCP4_PROTOCOL
*Tcp4
;
1475 EFI_TCP6_IO_TOKEN
*Tx6Token
;
1476 EFI_TCP6_PROTOCOL
*Tcp6
;
1479 NET_FRAGMENT TempFragment
;
1480 NET_FRAGMENT Fragment
;
1484 Status
= EFI_SUCCESS
;
1487 TempFragment
.Len
= 0;
1488 TempFragment
.Bulk
= NULL
;
1490 Fragment
.Bulk
= NULL
;
1495 // Need to encrypt data.
1497 if (HttpInstance
->UseHttps
) {
1499 // Allocate enough buffer for each TLS plaintext records.
1501 TlsRecord
= AllocateZeroPool (TLS_RECORD_HEADER_LENGTH
+ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
);
1502 if (TlsRecord
== NULL
) {
1503 Status
= EFI_OUT_OF_RESOURCES
;
1508 // Allocate enough buffer for all TLS ciphertext records.
1510 RecordCount
= TxStringLen
/ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
+ 1;
1511 Fragment
.Bulk
= AllocateZeroPool (RecordCount
* (TLS_RECORD_HEADER_LENGTH
+ TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH
));
1512 if (Fragment
.Bulk
== NULL
) {
1513 Status
= EFI_OUT_OF_RESOURCES
;
1518 // Encrypt each TLS plaintext records.
1520 RemainingLen
= TxStringLen
;
1521 while (RemainingLen
!= 0) {
1522 PayloadSize
= (UINT16
)MIN (TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
, RemainingLen
);
1524 ((TLS_RECORD_HEADER
*)TlsRecord
)->ContentType
= TlsContentTypeApplicationData
;
1525 ((TLS_RECORD_HEADER
*)TlsRecord
)->Version
.Major
= HttpInstance
->TlsConfigData
.Version
.Major
;
1526 ((TLS_RECORD_HEADER
*)TlsRecord
)->Version
.Minor
= HttpInstance
->TlsConfigData
.Version
.Minor
;
1527 ((TLS_RECORD_HEADER
*)TlsRecord
)->Length
= PayloadSize
;
1529 CopyMem (TlsRecord
+ TLS_RECORD_HEADER_LENGTH
, TxString
+ (TxStringLen
- RemainingLen
), PayloadSize
);
1531 Status
= TlsProcessMessage (
1534 TLS_RECORD_HEADER_LENGTH
+ PayloadSize
,
1538 if (EFI_ERROR (Status
)) {
1543 // Record the processed/encrypted Packet.
1545 CopyMem (Fragment
.Bulk
+ Fragment
.Len
, TempFragment
.Bulk
, TempFragment
.Len
);
1546 Fragment
.Len
+= TempFragment
.Len
;
1548 FreePool (TempFragment
.Bulk
);
1549 TempFragment
.Len
= 0;
1550 TempFragment
.Bulk
= NULL
;
1552 RemainingLen
-= (UINTN
)PayloadSize
;
1553 ZeroMem (TlsRecord
, TLS_RECORD_HEADER_LENGTH
+ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
);
1556 FreePool (TlsRecord
);
1560 if (!HttpInstance
->LocalAddressIsIPv6
) {
1561 Tcp4
= HttpInstance
->Tcp4
;
1562 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1564 if (HttpInstance
->UseHttps
) {
1565 Tx4Token
->Packet
.TxData
->DataLength
= Fragment
.Len
;
1566 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= Fragment
.Len
;
1567 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)Fragment
.Bulk
;
1569 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
)TxStringLen
;
1570 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
)TxStringLen
;
1571 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)TxString
;
1574 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1576 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1577 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1578 if (EFI_ERROR (Status
)) {
1579 DEBUG ((DEBUG_ERROR
, "Transmit failed: %r\n", Status
));
1583 Tcp6
= HttpInstance
->Tcp6
;
1584 Tx6Token
= &Wrap
->TcpWrap
.Tx6Token
;
1586 if (HttpInstance
->UseHttps
) {
1587 Tx6Token
->Packet
.TxData
->DataLength
= Fragment
.Len
;
1588 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= Fragment
.Len
;
1589 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)Fragment
.Bulk
;
1591 Tx6Token
->Packet
.TxData
->DataLength
= (UINT32
)TxStringLen
;
1592 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
)TxStringLen
;
1593 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)TxString
;
1596 Tx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1598 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1599 Status
= Tcp6
->Transmit (Tcp6
, Tx6Token
);
1600 if (EFI_ERROR (Status
)) {
1601 DEBUG ((DEBUG_ERROR
, "Transmit failed: %r\n", Status
));
1610 if (HttpInstance
->UseHttps
) {
1611 if (TlsRecord
!= NULL
) {
1612 FreePool (TlsRecord
);
1616 if (Fragment
.Bulk
!= NULL
) {
1617 FreePool (Fragment
.Bulk
);
1618 Fragment
.Bulk
= NULL
;
1626 Check whether the user's token or event has already
1627 been enqueue on HTTP Tx or Rx Token list.
1629 @param[in] Map The container of either user's transmit or receive
1631 @param[in] Item Current item to check against.
1632 @param[in] Context The Token to check against.
1634 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1635 @retval EFI_SUCCESS The current item isn't the same token/event as the
1643 IN NET_MAP_ITEM
*Item
,
1647 EFI_HTTP_TOKEN
*Token
;
1648 EFI_HTTP_TOKEN
*TokenInItem
;
1650 Token
= (EFI_HTTP_TOKEN
*)Context
;
1651 TokenInItem
= (EFI_HTTP_TOKEN
*)Item
->Key
;
1653 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
1654 return EFI_ACCESS_DENIED
;
1661 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1663 @param[in] Map The container of Tx4Token or Tx6Token.
1664 @param[in] Item Current item to check against.
1665 @param[in] Context The Token to check against.
1667 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1668 @retval EFI_SUCCESS The HTTP message has been sent out.
1675 IN NET_MAP_ITEM
*Item
,
1679 HTTP_TOKEN_WRAP
*ValueInItem
;
1681 ValueInItem
= (HTTP_TOKEN_WRAP
*)Item
->Value
;
1683 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
1684 return EFI_NOT_READY
;
1691 Transmit the HTTP or HTTPS message by processing the associated HTTP token.
1693 @param[in] Map The container of Tx4Token or Tx6Token.
1694 @param[in] Item Current item to check against.
1695 @param[in] Context The Token to check against.
1697 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1698 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1706 IN NET_MAP_ITEM
*Item
,
1710 HTTP_TOKEN_WRAP
*ValueInItem
;
1715 UINTN RequestMsgSize
;
1719 ValueInItem
= (HTTP_TOKEN_WRAP
*)Item
->Value
;
1720 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1725 // Parse the URI of the remote host.
1727 UrlSize
= StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1;
1728 Url
= AllocatePool (UrlSize
);
1730 return EFI_OUT_OF_RESOURCES
;
1733 UnicodeStrToAsciiStrS (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
, UrlSize
);
1736 // Create request message.
1738 Status
= HttpGenRequestMessage (
1739 ValueInItem
->HttpToken
->Message
,
1746 if (EFI_ERROR (Status
) || (NULL
== RequestMsg
)) {
1750 ASSERT (RequestMsg
!= NULL
);
1753 // Transmit the request message.
1755 Status
= HttpTransmitTcp (
1756 ValueInItem
->HttpInstance
,
1758 (UINT8
*)RequestMsg
,
1761 FreePool (RequestMsg
);
1766 Receive the HTTP response by processing the associated HTTP token.
1768 @param[in] Map The container of Rx4Token or Rx6Token.
1769 @param[in] Item Current item to check against.
1770 @param[in] Context The Token to check against.
1772 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1774 @retval Others Other error as indicated.
1781 IN NET_MAP_ITEM
*Item
,
1786 // Process the queued HTTP response.
1788 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*)Item
->Value
);
1792 Receive the HTTP header by processing the associated HTTP token.
1794 @param[in] HttpInstance The HTTP instance private data.
1795 @param[in, out] SizeofHeaders The HTTP header length.
1796 @param[in, out] BufferSize The size of buffer to cache the header message.
1797 @param[in] Timeout The time to wait for receiving the header packet.
1799 @retval EFI_SUCCESS The HTTP header is received.
1800 @retval Others Other errors as indicated.
1804 HttpTcpReceiveHeader (
1805 IN HTTP_PROTOCOL
*HttpInstance
,
1806 IN OUT UINTN
*SizeofHeaders
,
1807 IN OUT UINTN
*BufferSize
,
1808 IN EFI_EVENT Timeout
1812 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1813 EFI_TCP4_PROTOCOL
*Tcp4
;
1814 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1815 EFI_TCP6_PROTOCOL
*Tcp6
;
1816 CHAR8
**EndofHeader
;
1817 CHAR8
**HttpHeaders
;
1819 NET_FRAGMENT Fragment
;
1821 ASSERT (HttpInstance
!= NULL
);
1823 EndofHeader
= HttpInstance
->EndofHeader
;
1824 HttpHeaders
= HttpInstance
->HttpHeaders
;
1825 Tcp4
= HttpInstance
->Tcp4
;
1826 Tcp6
= HttpInstance
->Tcp6
;
1831 Fragment
.Bulk
= NULL
;
1833 if (HttpInstance
->LocalAddressIsIPv6
) {
1834 ASSERT (Tcp6
!= NULL
);
1836 ASSERT (Tcp4
!= NULL
);
1839 if (!HttpInstance
->UseHttps
) {
1840 Status
= HttpCreateTcpRxEventForHeader (HttpInstance
);
1841 if (EFI_ERROR (Status
)) {
1846 if (!HttpInstance
->LocalAddressIsIPv6
) {
1847 if (!HttpInstance
->UseHttps
) {
1848 Rx4Token
= &HttpInstance
->Rx4Token
;
1849 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1850 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1851 Status
= EFI_OUT_OF_RESOURCES
;
1857 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1859 while (*EndofHeader
== NULL
) {
1860 if (!HttpInstance
->UseHttps
) {
1861 HttpInstance
->IsRxDone
= FALSE
;
1862 Rx4Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1863 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1864 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1865 if (EFI_ERROR (Status
)) {
1866 DEBUG ((DEBUG_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1870 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1874 if (!HttpInstance
->IsRxDone
) {
1876 // Cancel the Token before close its Event.
1878 Tcp4
->Cancel (HttpInstance
->Tcp4
, &Rx4Token
->CompletionToken
);
1879 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1880 Rx4Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1883 Status
= Rx4Token
->CompletionToken
.Status
;
1884 if (EFI_ERROR (Status
)) {
1888 Fragment
.Len
= Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1889 Fragment
.Bulk
= (UINT8
*)Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
1891 if (Fragment
.Bulk
!= NULL
) {
1892 FreePool (Fragment
.Bulk
);
1893 Fragment
.Bulk
= NULL
;
1896 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
1897 if (EFI_ERROR (Status
)) {
1898 DEBUG ((DEBUG_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1904 // Append the response string along with a Null-terminator.
1906 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
1907 Buffer
= AllocatePool (*BufferSize
+ 1);
1908 if (Buffer
== NULL
) {
1909 Status
= EFI_OUT_OF_RESOURCES
;
1913 if (*HttpHeaders
!= NULL
) {
1914 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
1915 FreePool (*HttpHeaders
);
1919 Buffer
+ *SizeofHeaders
,
1923 *(Buffer
+ *BufferSize
) = '\0';
1924 *HttpHeaders
= Buffer
;
1925 *SizeofHeaders
= *BufferSize
;
1928 // Check whether we received end of HTTP headers.
1930 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1936 if ((Rx4Token
!= NULL
) && (Rx4Token
->Packet
.RxData
!= NULL
) && (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
)) {
1937 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1938 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1939 Fragment
.Bulk
= NULL
;
1942 if (Fragment
.Bulk
!= NULL
) {
1943 FreePool (Fragment
.Bulk
);
1944 Fragment
.Bulk
= NULL
;
1947 if (!HttpInstance
->UseHttps
) {
1948 Rx6Token
= &HttpInstance
->Rx6Token
;
1949 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1950 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1951 Status
= EFI_OUT_OF_RESOURCES
;
1957 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1959 while (*EndofHeader
== NULL
) {
1960 if (!HttpInstance
->UseHttps
) {
1961 HttpInstance
->IsRxDone
= FALSE
;
1962 Rx6Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1963 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1964 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1965 if (EFI_ERROR (Status
)) {
1966 DEBUG ((DEBUG_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1970 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1974 if (!HttpInstance
->IsRxDone
) {
1976 // Cancel the Token before close its Event.
1978 Tcp6
->Cancel (HttpInstance
->Tcp6
, &Rx6Token
->CompletionToken
);
1979 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1980 Rx6Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1983 Status
= Rx6Token
->CompletionToken
.Status
;
1984 if (EFI_ERROR (Status
)) {
1988 Fragment
.Len
= Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1989 Fragment
.Bulk
= (UINT8
*)Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
1991 if (Fragment
.Bulk
!= NULL
) {
1992 FreePool (Fragment
.Bulk
);
1993 Fragment
.Bulk
= NULL
;
1996 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
1997 if (EFI_ERROR (Status
)) {
1998 DEBUG ((DEBUG_ERROR
, "Tcp6 receive failed: %r\n", Status
));
2004 // Append the response string along with a Null-terminator.
2006 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
2007 Buffer
= AllocatePool (*BufferSize
+ 1);
2008 if (Buffer
== NULL
) {
2009 Status
= EFI_OUT_OF_RESOURCES
;
2013 if (*HttpHeaders
!= NULL
) {
2014 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
2015 FreePool (*HttpHeaders
);
2019 Buffer
+ *SizeofHeaders
,
2023 *(Buffer
+ *BufferSize
) = '\0';
2024 *HttpHeaders
= Buffer
;
2025 *SizeofHeaders
= *BufferSize
;
2028 // Check whether we received end of HTTP headers.
2030 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
2036 if ((Rx6Token
!= NULL
) && (Rx6Token
->Packet
.RxData
!= NULL
) && (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
)) {
2037 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2038 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2039 Fragment
.Bulk
= NULL
;
2042 if (Fragment
.Bulk
!= NULL
) {
2043 FreePool (Fragment
.Bulk
);
2044 Fragment
.Bulk
= NULL
;
2049 // Skip the CRLF after the HTTP headers.
2051 *EndofHeader
= *EndofHeader
+ AsciiStrLen (HTTP_END_OF_HDR_STR
);
2053 *SizeofHeaders
= *EndofHeader
- *HttpHeaders
;
2059 Receive the HTTP body by processing the associated HTTP token.
2061 @param[in] Wrap The HTTP token's wrap data.
2062 @param[in] HttpMsg The HTTP message data.
2064 @retval EFI_SUCCESS The HTTP body is received.
2065 @retval Others Other error as indicated.
2069 HttpTcpReceiveBody (
2070 IN HTTP_TOKEN_WRAP
*Wrap
,
2071 IN EFI_HTTP_MESSAGE
*HttpMsg
2075 HTTP_PROTOCOL
*HttpInstance
;
2076 EFI_TCP6_PROTOCOL
*Tcp6
;
2077 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2078 EFI_TCP4_PROTOCOL
*Tcp4
;
2079 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2081 HttpInstance
= Wrap
->HttpInstance
;
2082 Tcp4
= HttpInstance
->Tcp4
;
2083 Tcp6
= HttpInstance
->Tcp6
;
2087 if (HttpInstance
->LocalAddressIsIPv6
) {
2088 ASSERT (Tcp6
!= NULL
);
2090 ASSERT (Tcp4
!= NULL
);
2093 if (HttpInstance
->LocalAddressIsIPv6
) {
2094 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2095 Rx6Token
->Packet
.RxData
->DataLength
= (UINT32
)MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2096 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
)MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2097 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)HttpMsg
->Body
;
2098 Rx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2100 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
2101 if (EFI_ERROR (Status
)) {
2102 DEBUG ((DEBUG_ERROR
, "Tcp6 receive failed: %r\n", Status
));
2106 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2107 Rx4Token
->Packet
.RxData
->DataLength
= (UINT32
)MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2108 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
)MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2109 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)HttpMsg
->Body
;
2111 Rx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2112 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
2113 if (EFI_ERROR (Status
)) {
2114 DEBUG ((DEBUG_ERROR
, "Tcp4 receive failed: %r\n", Status
));
2123 Clean up Tcp Tokens while the Tcp transmission error occurs.
2125 @param[in] Wrap Pointer to HTTP token's wrap data.
2129 HttpTcpTokenCleanup (
2130 IN HTTP_TOKEN_WRAP
*Wrap
2133 HTTP_PROTOCOL
*HttpInstance
;
2134 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2135 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2137 ASSERT (Wrap
!= NULL
);
2138 HttpInstance
= Wrap
->HttpInstance
;
2142 if (HttpInstance
->LocalAddressIsIPv6
) {
2143 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2145 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2146 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2147 Rx6Token
->CompletionToken
.Event
= NULL
;
2152 Rx6Token
= &HttpInstance
->Rx6Token
;
2154 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2155 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2156 Rx6Token
->CompletionToken
.Event
= NULL
;
2159 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2160 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2161 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2164 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2166 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2167 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2168 Rx4Token
->CompletionToken
.Event
= NULL
;
2173 Rx4Token
= &HttpInstance
->Rx4Token
;
2175 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2176 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2177 Rx4Token
->CompletionToken
.Event
= NULL
;
2180 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2181 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2182 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2188 Send Events via EDKII_HTTP_CALLBACK_PROTOCOL.
2190 @param[in] Event The event that occurs in the current state.
2191 @param[in] EventStatus The Status of Event, EFI_SUCCESS or other errors.
2196 IN EDKII_HTTP_CALLBACK_EVENT Event
,
2197 IN EFI_STATUS EventStatus
2201 EFI_HANDLE
*Handles
;
2205 EDKII_HTTP_CALLBACK_PROTOCOL
*HttpCallback
;
2207 DEBUG ((DEBUG_INFO
, "HttpNotify: Event - %d, EventStatus - %r\n", Event
, EventStatus
));
2211 Status
= gBS
->LocateHandleBuffer (
2213 &gEdkiiHttpCallbackProtocolGuid
,
2218 if (Status
== EFI_SUCCESS
) {
2219 for (Index
= 0; Index
< HandleCount
; Index
++) {
2220 Handle
= Handles
[Index
];
2221 Status
= gBS
->HandleProtocol (
2223 &gEdkiiHttpCallbackProtocolGuid
,
2224 (VOID
**)&HttpCallback
2226 if (Status
== EFI_SUCCESS
) {
2227 DEBUG ((DEBUG_INFO
, "HttpNotify: Notifying %p\n", HttpCallback
));
2228 HttpCallback
->Callback (