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 if ((HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) ||
1172 (HttpInstance
->State
== HTTP_STATE_TCP_CLOSED
))
1174 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, NULL
);
1175 if (EFI_ERROR (Status
)) {
1176 DEBUG ((DEBUG_ERROR
, "HttpConfigureTcp6(NULL) - %r\n", Status
));
1180 HttpInstance
->State
= HTTP_STATE_TCP_UNCONFIGED
;
1183 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, Tcp6CfgData
);
1184 if (EFI_ERROR (Status
)) {
1185 DEBUG ((DEBUG_ERROR
, "HttpConfigureTcp6 - %r\n", Status
));
1189 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1190 if (EFI_ERROR (Status
)) {
1194 Status
= HttpCreateTcpTxEvent (Wrap
);
1195 if (EFI_ERROR (Status
)) {
1199 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1205 Check existing TCP connection, if in error state, recover TCP4 connection. Then,
1206 connect one TLS session if required.
1208 @param[in] HttpInstance The HTTP instance private data.
1210 @retval EFI_SUCCESS The TCP connection is established.
1211 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1212 @retval Others Other error as indicated.
1217 IN HTTP_PROTOCOL
*HttpInstance
1221 EFI_TCP4_CONNECTION_STATE Tcp4State
;
1223 if ((HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
) || (HttpInstance
->Tcp4
== NULL
)) {
1224 return EFI_NOT_READY
;
1227 Status
= HttpInstance
->Tcp4
->GetModeData (
1235 if (EFI_ERROR (Status
)) {
1236 DEBUG ((DEBUG_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
1240 if (Tcp4State
== Tcp4StateEstablished
) {
1242 } else if (Tcp4State
> Tcp4StateEstablished
) {
1243 HttpCloseConnection (HttpInstance
);
1246 Status
= HttpCreateConnection (HttpInstance
);
1247 if (EFI_ERROR (Status
)) {
1248 DEBUG ((DEBUG_ERROR
, "Tcp4 Connection fail - %x\n", Status
));
1253 // Tls session connection.
1255 if (HttpInstance
->UseHttps
) {
1256 if (HttpInstance
->TimeoutEvent
== NULL
) {
1258 // Create TimeoutEvent for TLS connection.
1260 Status
= gBS
->CreateEvent (
1265 &HttpInstance
->TimeoutEvent
1267 if (EFI_ERROR (Status
)) {
1268 TlsCloseTxRxEvent (HttpInstance
);
1274 // Start the timer, and wait Timeout seconds for connection.
1276 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1277 if (EFI_ERROR (Status
)) {
1278 TlsCloseTxRxEvent (HttpInstance
);
1282 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1283 HttpNotify (HttpEventTlsConnectSession
, Status
);
1285 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1287 if (EFI_ERROR (Status
)) {
1288 TlsCloseTxRxEvent (HttpInstance
);
1297 Check existing TCP connection, if in error state, recover TCP6 connection. Then,
1298 connect one TLS session if required.
1300 @param[in] HttpInstance The HTTP instance private data.
1302 @retval EFI_SUCCESS The TCP connection is established.
1303 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1304 @retval Others Other error as indicated.
1309 IN HTTP_PROTOCOL
*HttpInstance
1313 EFI_TCP6_CONNECTION_STATE Tcp6State
;
1315 if ((HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
) || (HttpInstance
->Tcp6
== NULL
)) {
1316 return EFI_NOT_READY
;
1319 Status
= HttpInstance
->Tcp6
->GetModeData (
1328 if (EFI_ERROR (Status
)) {
1329 DEBUG ((DEBUG_ERROR
, "Tcp6 GetModeData fail - %x\n", Status
));
1333 if (Tcp6State
== Tcp6StateEstablished
) {
1335 } else if (Tcp6State
> Tcp6StateEstablished
) {
1336 HttpCloseConnection (HttpInstance
);
1339 Status
= HttpCreateConnection (HttpInstance
);
1340 if (EFI_ERROR (Status
)) {
1341 DEBUG ((DEBUG_ERROR
, "Tcp6 Connection fail - %x\n", Status
));
1346 // Tls session connection.
1348 if (HttpInstance
->UseHttps
) {
1349 if (HttpInstance
->TimeoutEvent
== NULL
) {
1351 // Create TimeoutEvent for TLS connection.
1353 Status
= gBS
->CreateEvent (
1358 &HttpInstance
->TimeoutEvent
1360 if (EFI_ERROR (Status
)) {
1361 TlsCloseTxRxEvent (HttpInstance
);
1367 // Start the timer, and wait Timeout seconds for connection.
1369 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1370 if (EFI_ERROR (Status
)) {
1371 TlsCloseTxRxEvent (HttpInstance
);
1375 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1376 HttpNotify (HttpEventTlsConnectSession
, Status
);
1378 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1380 if (EFI_ERROR (Status
)) {
1381 TlsCloseTxRxEvent (HttpInstance
);
1390 Initialize Http session.
1392 @param[in] HttpInstance The HTTP instance private data.
1393 @param[in] Wrap The HTTP token's wrap data.
1394 @param[in] Configure The Flag indicates whether need to initialize session.
1395 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session.
1397 @retval EFI_SUCCESS The initialization of session is done.
1398 @retval Others Other error as indicated.
1403 IN HTTP_PROTOCOL
*HttpInstance
,
1404 IN HTTP_TOKEN_WRAP
*Wrap
,
1405 IN BOOLEAN Configure
,
1406 IN BOOLEAN TlsConfigure
1411 ASSERT (HttpInstance
!= NULL
);
1414 // Configure Tls session.
1417 Status
= TlsConfigureSession (HttpInstance
);
1418 if (EFI_ERROR (Status
)) {
1423 if (!HttpInstance
->LocalAddressIsIPv6
) {
1425 // Configure TCP instance.
1428 Status
= HttpConfigureTcp4 (HttpInstance
, Wrap
);
1429 if (EFI_ERROR (Status
)) {
1437 Status
= HttpConnectTcp4 (HttpInstance
);
1438 if (EFI_ERROR (Status
)) {
1443 // Configure TCP instance.
1446 Status
= HttpConfigureTcp6 (HttpInstance
, Wrap
);
1447 if (EFI_ERROR (Status
)) {
1455 Status
= HttpConnectTcp6 (HttpInstance
);
1456 if (EFI_ERROR (Status
)) {
1465 Send the HTTP or HTTPS message through TCP4 or TCP6.
1467 @param[in] HttpInstance The HTTP instance private data.
1468 @param[in] Wrap The HTTP token's wrap data.
1469 @param[in] TxString Buffer containing the HTTP message string.
1470 @param[in] TxStringLen Length of the HTTP message string in bytes.
1472 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1473 @retval Others Other error as indicated.
1478 IN HTTP_PROTOCOL
*HttpInstance
,
1479 IN HTTP_TOKEN_WRAP
*Wrap
,
1481 IN UINTN TxStringLen
1485 EFI_TCP4_IO_TOKEN
*Tx4Token
;
1486 EFI_TCP4_PROTOCOL
*Tcp4
;
1487 EFI_TCP6_IO_TOKEN
*Tx6Token
;
1488 EFI_TCP6_PROTOCOL
*Tcp6
;
1491 NET_FRAGMENT TempFragment
;
1492 NET_FRAGMENT Fragment
;
1496 Status
= EFI_SUCCESS
;
1499 TempFragment
.Len
= 0;
1500 TempFragment
.Bulk
= NULL
;
1502 Fragment
.Bulk
= NULL
;
1507 // Need to encrypt data.
1509 if (HttpInstance
->UseHttps
) {
1511 // Allocate enough buffer for each TLS plaintext records.
1513 TlsRecord
= AllocateZeroPool (TLS_RECORD_HEADER_LENGTH
+ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
);
1514 if (TlsRecord
== NULL
) {
1515 Status
= EFI_OUT_OF_RESOURCES
;
1520 // Allocate enough buffer for all TLS ciphertext records.
1522 RecordCount
= TxStringLen
/ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
+ 1;
1523 Fragment
.Bulk
= AllocateZeroPool (RecordCount
* (TLS_RECORD_HEADER_LENGTH
+ TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH
));
1524 if (Fragment
.Bulk
== NULL
) {
1525 Status
= EFI_OUT_OF_RESOURCES
;
1530 // Encrypt each TLS plaintext records.
1532 RemainingLen
= TxStringLen
;
1533 while (RemainingLen
!= 0) {
1534 PayloadSize
= (UINT16
)MIN (TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
, RemainingLen
);
1536 ((TLS_RECORD_HEADER
*)TlsRecord
)->ContentType
= TlsContentTypeApplicationData
;
1537 ((TLS_RECORD_HEADER
*)TlsRecord
)->Version
.Major
= HttpInstance
->TlsConfigData
.Version
.Major
;
1538 ((TLS_RECORD_HEADER
*)TlsRecord
)->Version
.Minor
= HttpInstance
->TlsConfigData
.Version
.Minor
;
1539 ((TLS_RECORD_HEADER
*)TlsRecord
)->Length
= PayloadSize
;
1541 CopyMem (TlsRecord
+ TLS_RECORD_HEADER_LENGTH
, TxString
+ (TxStringLen
- RemainingLen
), PayloadSize
);
1543 Status
= TlsProcessMessage (
1546 TLS_RECORD_HEADER_LENGTH
+ PayloadSize
,
1550 if (EFI_ERROR (Status
)) {
1555 // Record the processed/encrypted Packet.
1557 CopyMem (Fragment
.Bulk
+ Fragment
.Len
, TempFragment
.Bulk
, TempFragment
.Len
);
1558 Fragment
.Len
+= TempFragment
.Len
;
1560 FreePool (TempFragment
.Bulk
);
1561 TempFragment
.Len
= 0;
1562 TempFragment
.Bulk
= NULL
;
1564 RemainingLen
-= (UINTN
)PayloadSize
;
1565 ZeroMem (TlsRecord
, TLS_RECORD_HEADER_LENGTH
+ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
);
1568 FreePool (TlsRecord
);
1572 if (!HttpInstance
->LocalAddressIsIPv6
) {
1573 Tcp4
= HttpInstance
->Tcp4
;
1574 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1576 if (HttpInstance
->UseHttps
) {
1577 Tx4Token
->Packet
.TxData
->DataLength
= Fragment
.Len
;
1578 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= Fragment
.Len
;
1579 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)Fragment
.Bulk
;
1581 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
)TxStringLen
;
1582 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
)TxStringLen
;
1583 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*)TxString
;
1586 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1588 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1589 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1590 if (EFI_ERROR (Status
)) {
1591 DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_ERROR
, "Tcp4 receive failed: %r\n", Status
));
2135 Clean up Tcp Tokens while the Tcp transmission error occurs.
2137 @param[in] Wrap Pointer to HTTP token's wrap data.
2141 HttpTcpTokenCleanup (
2142 IN HTTP_TOKEN_WRAP
*Wrap
2145 HTTP_PROTOCOL
*HttpInstance
;
2146 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2147 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2149 ASSERT (Wrap
!= NULL
);
2150 HttpInstance
= Wrap
->HttpInstance
;
2154 if (HttpInstance
->LocalAddressIsIPv6
) {
2155 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2157 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2158 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2159 Rx6Token
->CompletionToken
.Event
= NULL
;
2164 Rx6Token
= &HttpInstance
->Rx6Token
;
2166 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2167 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2168 Rx6Token
->CompletionToken
.Event
= NULL
;
2171 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2172 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2173 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2176 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2178 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2179 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2180 Rx4Token
->CompletionToken
.Event
= NULL
;
2185 Rx4Token
= &HttpInstance
->Rx4Token
;
2187 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2188 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2189 Rx4Token
->CompletionToken
.Event
= NULL
;
2192 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2193 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2194 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2200 Send Events via EDKII_HTTP_CALLBACK_PROTOCOL.
2202 @param[in] Event The event that occurs in the current state.
2203 @param[in] EventStatus The Status of Event, EFI_SUCCESS or other errors.
2208 IN EDKII_HTTP_CALLBACK_EVENT Event
,
2209 IN EFI_STATUS EventStatus
2213 EFI_HANDLE
*Handles
;
2217 EDKII_HTTP_CALLBACK_PROTOCOL
*HttpCallback
;
2219 DEBUG ((DEBUG_INFO
, "HttpNotify: Event - %d, EventStatus - %r\n", Event
, EventStatus
));
2223 Status
= gBS
->LocateHandleBuffer (
2225 &gEdkiiHttpCallbackProtocolGuid
,
2230 if (Status
== EFI_SUCCESS
) {
2231 for (Index
= 0; Index
< HandleCount
; Index
++) {
2232 Handle
= Handles
[Index
];
2233 Status
= gBS
->HandleProtocol (
2235 &gEdkiiHttpCallbackProtocolGuid
,
2236 (VOID
**)&HttpCallback
2238 if (Status
== EFI_SUCCESS
) {
2239 DEBUG ((DEBUG_INFO
, "HttpNotify: Notifying %p\n", HttpCallback
));
2240 HttpCallback
->Callback (