2 Miscellaneous routines for HttpDxe driver.
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HttpDriver.h"
19 The common notify function used in HTTP driver.
21 @param[in] Event The event signaled.
22 @param[in] Context The context.
32 if ((Event
== NULL
) || (Context
== NULL
)) {
36 *((BOOLEAN
*) Context
) = TRUE
;
40 The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().
42 @param[in] Context The context.
47 HttpTcpTransmitNotifyDpc (
51 HTTP_TOKEN_WRAP
*Wrap
;
52 HTTP_PROTOCOL
*HttpInstance
;
54 if (Context
== NULL
) {
58 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
59 HttpInstance
= Wrap
->HttpInstance
;
61 if (!HttpInstance
->LocalAddressIsIPv6
) {
62 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Tx4Token
.CompletionToken
.Status
;
63 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
68 if (Wrap
->TcpWrap
.Tx4Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
69 FreePool (Wrap
->TcpWrap
.Tx4Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
);
72 if (Wrap
->TcpWrap
.Tx4Token
.CompletionToken
.Event
!= NULL
) {
73 gBS
->CloseEvent (Wrap
->TcpWrap
.Tx4Token
.CompletionToken
.Event
);
77 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Status
;
78 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
83 if (Wrap
->TcpWrap
.Tx6Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
84 FreePool (Wrap
->TcpWrap
.Tx6Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
);
87 if (Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Event
!= NULL
) {
88 gBS
->CloseEvent (Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Event
);
93 Wrap
->TcpWrap
.IsTxDone
= TRUE
;
96 // Check pending TxTokens and sent out.
98 NetMapIterate (&Wrap
->HttpInstance
->TxTokens
, HttpTcpTransmit
, NULL
);
103 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.
105 @param Event The receive event delivered to TCP for transmit.
106 @param Context Context for the callback.
111 HttpTcpTransmitNotify (
117 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
119 QueueDpc (TPL_CALLBACK
, HttpTcpTransmitNotifyDpc
, Context
);
123 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().
125 @param[in] Context The context.
130 HttpTcpReceiveNotifyDpc (
134 HTTP_TOKEN_WRAP
*Wrap
;
138 HTTP_PROTOCOL
*HttpInstance
;
141 if (Context
== NULL
) {
145 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
146 HttpInstance
= Wrap
->HttpInstance
;
147 UsingIpv6
= HttpInstance
->LocalAddressIsIPv6
;
150 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
152 if (EFI_ERROR (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
)) {
153 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
154 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
159 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
161 if (EFI_ERROR (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
)) {
162 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
163 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
169 // Check whether we receive a complete HTTP message.
171 ASSERT (HttpInstance
->MsgParser
!= NULL
);
173 Length
= (UINTN
) Wrap
->TcpWrap
.Rx6Data
.FragmentTable
[0].FragmentLength
;
175 Length
= (UINTN
) Wrap
->TcpWrap
.Rx4Data
.FragmentTable
[0].FragmentLength
;
178 Status
= HttpParseMessageBody (
179 HttpInstance
->MsgParser
,
181 Wrap
->HttpToken
->Message
->Body
183 if (EFI_ERROR (Status
)) {
187 if (HttpIsMessageComplete (HttpInstance
->MsgParser
)) {
189 // Free the MsgParse since we already have a full HTTP message.
191 HttpFreeMsgParser (HttpInstance
->MsgParser
);
192 HttpInstance
->MsgParser
= NULL
;
195 Wrap
->HttpToken
->Message
->BodyLength
= Length
;
196 ASSERT (HttpInstance
->CacheBody
== NULL
);
198 // We receive part of header of next HTTP msg.
200 if (HttpInstance
->NextMsg
!= NULL
) {
201 Wrap
->HttpToken
->Message
->BodyLength
= HttpInstance
->NextMsg
-
202 (CHAR8
*) Wrap
->HttpToken
->Message
->Body
;
203 HttpInstance
->CacheLen
= Length
- Wrap
->HttpToken
->Message
->BodyLength
;
204 if (HttpInstance
->CacheLen
!= 0) {
205 HttpInstance
->CacheBody
= AllocateZeroPool (HttpInstance
->CacheLen
);
206 if (HttpInstance
->CacheBody
== NULL
) {
209 CopyMem (HttpInstance
->CacheBody
, HttpInstance
->NextMsg
, HttpInstance
->CacheLen
);
210 HttpInstance
->NextMsg
= HttpInstance
->CacheBody
;
211 HttpInstance
->CacheOffset
= 0;
215 Item
= NetMapFindKey (&Wrap
->HttpInstance
->RxTokens
, Wrap
->HttpToken
);
217 NetMapRemoveItem (&Wrap
->HttpInstance
->RxTokens
, Item
, NULL
);
221 Wrap
->TcpWrap
.IsRxDone
= TRUE
;
223 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
225 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
229 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
232 // Check pending RxTokens and receive the HTTP message.
234 NetMapIterate (&Wrap
->HttpInstance
->RxTokens
, HttpTcpReceive
, NULL
);
238 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.
240 @param Event The receive event delivered to TCP for receive.
241 @param Context Context for the callback.
246 HttpTcpReceiveNotify (
252 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
254 QueueDpc (TPL_CALLBACK
, HttpTcpReceiveNotifyDpc
, Context
);
258 Create events for the TCP connection token and TCP close token.
260 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
262 @retval EFI_SUCCESS The events are created successfully.
263 @retval others Other error as indicated.
267 HttpCreateTcpConnCloseEvent (
268 IN HTTP_PROTOCOL
*HttpInstance
273 if (!HttpInstance
->LocalAddressIsIPv6
) {
275 // Create events for variuos asynchronous operations.
277 Status
= gBS
->CreateEvent (
281 &HttpInstance
->IsTcp4ConnDone
,
282 &HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
284 if (EFI_ERROR (Status
)) {
289 // Initialize Tcp4CloseToken
291 Status
= gBS
->CreateEvent (
295 &HttpInstance
->IsTcp4CloseDone
,
296 &HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
298 if (EFI_ERROR (Status
)) {
304 // Create events for variuos asynchronous operations.
306 Status
= gBS
->CreateEvent (
310 &HttpInstance
->IsTcp6ConnDone
,
311 &HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
313 if (EFI_ERROR (Status
)) {
318 // Initialize Tcp6CloseToken
320 Status
= gBS
->CreateEvent (
324 &HttpInstance
->IsTcp6CloseDone
,
325 &HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
327 if (EFI_ERROR (Status
)) {
338 HttpCloseTcpConnCloseEvent (HttpInstance
);
345 Close events in the TCP connection token and TCP close token.
347 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
351 HttpCloseTcpConnCloseEvent (
352 IN HTTP_PROTOCOL
*HttpInstance
355 ASSERT (HttpInstance
!= NULL
);
357 if (HttpInstance
->LocalAddressIsIPv6
) {
358 if (NULL
!= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
) {
359 gBS
->CloseEvent (HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
);
360 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
= NULL
;
363 if (NULL
!= HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
) {
364 gBS
->CloseEvent(HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
);
365 HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
= NULL
;
369 if (NULL
!= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
) {
370 gBS
->CloseEvent (HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
);
371 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
= NULL
;
374 if (NULL
!= HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
) {
375 gBS
->CloseEvent(HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
);
376 HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
383 Create event for the TCP transmit token.
385 @param[in] Wrap Point to HTTP token's wrap data.
387 @retval EFI_SUCCESS The events is created successfully.
388 @retval others Other error as indicated.
392 HttpCreateTcpTxEvent (
393 IN HTTP_TOKEN_WRAP
*Wrap
397 HTTP_PROTOCOL
*HttpInstance
;
398 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
400 HttpInstance
= Wrap
->HttpInstance
;
401 TcpWrap
= &Wrap
->TcpWrap
;
403 if (!HttpInstance
->LocalAddressIsIPv6
) {
404 Status
= gBS
->CreateEvent (
407 HttpTcpTransmitNotify
,
409 &TcpWrap
->Tx4Token
.CompletionToken
.Event
411 if (EFI_ERROR (Status
)) {
415 TcpWrap
->Tx4Data
.Push
= TRUE
;
416 TcpWrap
->Tx4Data
.Urgent
= FALSE
;
417 TcpWrap
->Tx4Data
.FragmentCount
= 1;
418 TcpWrap
->Tx4Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx4Data
;
419 TcpWrap
->Tx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
422 Status
= gBS
->CreateEvent (
425 HttpTcpTransmitNotify
,
427 &TcpWrap
->Tx6Token
.CompletionToken
.Event
429 if (EFI_ERROR (Status
)) {
433 TcpWrap
->Tx6Data
.Push
= TRUE
;
434 TcpWrap
->Tx6Data
.Urgent
= FALSE
;
435 TcpWrap
->Tx6Data
.FragmentCount
= 1;
436 TcpWrap
->Tx6Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx6Data
;
437 TcpWrap
->Tx6Token
.CompletionToken
.Status
=EFI_NOT_READY
;
446 Create event for the TCP receive token which is used to receive HTTP header.
448 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
450 @retval EFI_SUCCESS The events is created successfully.
451 @retval others Other error as indicated.
455 HttpCreateTcpRxEventForHeader (
456 IN HTTP_PROTOCOL
*HttpInstance
461 if (!HttpInstance
->LocalAddressIsIPv6
) {
462 Status
= gBS
->CreateEvent (
466 &HttpInstance
->IsRxDone
,
467 &HttpInstance
->Rx4Token
.CompletionToken
.Event
469 if (EFI_ERROR (Status
)) {
473 HttpInstance
->Rx4Data
.FragmentCount
= 1;
474 HttpInstance
->Rx4Token
.Packet
.RxData
= &HttpInstance
->Rx4Data
;
475 HttpInstance
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
478 Status
= gBS
->CreateEvent (
482 &HttpInstance
->IsRxDone
,
483 &HttpInstance
->Rx6Token
.CompletionToken
.Event
485 if (EFI_ERROR (Status
)) {
489 HttpInstance
->Rx6Data
.FragmentCount
=1;
490 HttpInstance
->Rx6Token
.Packet
.RxData
= &HttpInstance
->Rx6Data
;
491 HttpInstance
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
500 Create event for the TCP receive token which is used to receive HTTP body.
502 @param[in] Wrap Point to HTTP token's wrap data.
504 @retval EFI_SUCCESS The events is created successfully.
505 @retval others Other error as indicated.
509 HttpCreateTcpRxEvent (
510 IN HTTP_TOKEN_WRAP
*Wrap
514 HTTP_PROTOCOL
*HttpInstance
;
515 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
517 HttpInstance
= Wrap
->HttpInstance
;
518 TcpWrap
= &Wrap
->TcpWrap
;
519 if (!HttpInstance
->LocalAddressIsIPv6
) {
520 Status
= gBS
->CreateEvent (
523 HttpTcpReceiveNotify
,
525 &TcpWrap
->Rx4Token
.CompletionToken
.Event
527 if (EFI_ERROR (Status
)) {
531 TcpWrap
->Rx4Data
.FragmentCount
= 1;
532 TcpWrap
->Rx4Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx4Data
;
533 TcpWrap
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
536 Status
= gBS
->CreateEvent (
539 HttpTcpReceiveNotify
,
541 &TcpWrap
->Rx6Token
.CompletionToken
.Event
543 if (EFI_ERROR (Status
)) {
547 TcpWrap
->Rx6Data
.FragmentCount
= 1;
548 TcpWrap
->Rx6Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx6Data
;
549 TcpWrap
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
556 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.
558 @param[in] Wrap Pointer to HTTP token's wrap data.
562 HttpCloseTcpRxEvent (
563 IN HTTP_TOKEN_WRAP
*Wrap
566 HTTP_PROTOCOL
*HttpInstance
;
568 ASSERT (Wrap
!= NULL
);
569 HttpInstance
= Wrap
->HttpInstance
;
571 if (HttpInstance
->LocalAddressIsIPv6
) {
572 if (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
!= NULL
) {
573 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
576 if (HttpInstance
->Rx6Token
.CompletionToken
.Event
!= NULL
) {
577 gBS
->CloseEvent (HttpInstance
->Rx6Token
.CompletionToken
.Event
);
578 HttpInstance
->Rx6Token
.CompletionToken
.Event
= NULL
;
581 if (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
!= NULL
) {
582 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
585 if (HttpInstance
->Rx4Token
.CompletionToken
.Event
!= NULL
) {
586 gBS
->CloseEvent (HttpInstance
->Rx4Token
.CompletionToken
.Event
);
587 HttpInstance
->Rx4Token
.CompletionToken
.Event
= NULL
;
593 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.
595 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
596 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.
598 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
599 @retval Others Other error as indicated.
604 IN OUT HTTP_PROTOCOL
*HttpInstance
,
612 ASSERT (HttpInstance
!= NULL
);
613 UsingIpv6
= IpVersion
;
617 // Create TCP4 child.
619 Status
= NetLibCreateServiceChild (
620 HttpInstance
->Service
->ControllerHandle
,
621 HttpInstance
->Service
->ImageHandle
,
622 &gEfiTcp4ServiceBindingProtocolGuid
,
623 &HttpInstance
->Tcp4ChildHandle
626 if (EFI_ERROR (Status
)) {
630 Status
= gBS
->OpenProtocol (
631 HttpInstance
->Tcp4ChildHandle
,
632 &gEfiTcp4ProtocolGuid
,
633 (VOID
**) &Interface
,
634 HttpInstance
->Service
->ImageHandle
,
635 HttpInstance
->Service
->ControllerHandle
,
636 EFI_OPEN_PROTOCOL_BY_DRIVER
639 if (EFI_ERROR (Status
)) {
643 Status
= gBS
->OpenProtocol (
644 HttpInstance
->Tcp4ChildHandle
,
645 &gEfiTcp4ProtocolGuid
,
646 (VOID
**) &HttpInstance
->Tcp4
,
647 HttpInstance
->Service
->ImageHandle
,
648 HttpInstance
->Handle
,
649 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
651 if (EFI_ERROR(Status
)) {
655 Status
= gBS
->OpenProtocol (
656 HttpInstance
->Service
->Tcp4ChildHandle
,
657 &gEfiTcp4ProtocolGuid
,
658 (VOID
**) &Interface
,
659 HttpInstance
->Service
->ImageHandle
,
660 HttpInstance
->Handle
,
661 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
663 if (EFI_ERROR(Status
)) {
668 // Create TCP6 Child.
670 Status
= NetLibCreateServiceChild (
671 HttpInstance
->Service
->ControllerHandle
,
672 HttpInstance
->Service
->ImageHandle
,
673 &gEfiTcp6ServiceBindingProtocolGuid
,
674 &HttpInstance
->Tcp6ChildHandle
677 if (EFI_ERROR (Status
)) {
681 Status
= gBS
->OpenProtocol (
682 HttpInstance
->Tcp6ChildHandle
,
683 &gEfiTcp6ProtocolGuid
,
684 (VOID
**) &Interface
,
685 HttpInstance
->Service
->ImageHandle
,
686 HttpInstance
->Service
->ControllerHandle
,
687 EFI_OPEN_PROTOCOL_BY_DRIVER
690 if (EFI_ERROR (Status
)) {
694 Status
= gBS
->OpenProtocol (
695 HttpInstance
->Tcp6ChildHandle
,
696 &gEfiTcp6ProtocolGuid
,
697 (VOID
**) &HttpInstance
->Tcp6
,
698 HttpInstance
->Service
->ImageHandle
,
699 HttpInstance
->Handle
,
700 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
703 if (EFI_ERROR(Status
)) {
707 Status
= gBS
->OpenProtocol (
708 HttpInstance
->Service
->Tcp6ChildHandle
,
709 &gEfiTcp6ProtocolGuid
,
710 (VOID
**) &Interface
,
711 HttpInstance
->Service
->ImageHandle
,
712 HttpInstance
->Handle
,
713 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
716 if (EFI_ERROR(Status
)) {
721 HttpInstance
->Url
= AllocateZeroPool (HTTP_URL_BUFFER_LEN
);
722 if (HttpInstance
->Url
== NULL
) {
723 Status
= EFI_OUT_OF_RESOURCES
;
731 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
733 HttpInstance
->Tcp4ChildHandle
,
734 &gEfiTcp4ProtocolGuid
,
735 HttpInstance
->Service
->ImageHandle
,
736 HttpInstance
->Service
->ControllerHandle
740 HttpInstance
->Tcp4ChildHandle
,
741 &gEfiTcp4ProtocolGuid
,
742 HttpInstance
->Service
->ImageHandle
,
746 NetLibDestroyServiceChild (
747 HttpInstance
->Service
->ControllerHandle
,
748 HttpInstance
->Service
->ImageHandle
,
749 &gEfiTcp4ServiceBindingProtocolGuid
,
750 HttpInstance
->Tcp4ChildHandle
754 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
756 HttpInstance
->Service
->Tcp4ChildHandle
,
757 &gEfiTcp4ProtocolGuid
,
758 HttpInstance
->Service
->ImageHandle
,
763 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
765 HttpInstance
->Tcp6ChildHandle
,
766 &gEfiTcp6ProtocolGuid
,
767 HttpInstance
->Service
->ImageHandle
,
768 HttpInstance
->Service
->ControllerHandle
772 HttpInstance
->Tcp6ChildHandle
,
773 &gEfiTcp6ProtocolGuid
,
774 HttpInstance
->Service
->ImageHandle
,
778 NetLibDestroyServiceChild (
779 HttpInstance
->Service
->ControllerHandle
,
780 HttpInstance
->Service
->ImageHandle
,
781 &gEfiTcp6ServiceBindingProtocolGuid
,
782 HttpInstance
->Tcp6ChildHandle
786 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
788 HttpInstance
->Service
->Tcp6ChildHandle
,
789 &gEfiTcp6ProtocolGuid
,
790 HttpInstance
->Service
->ImageHandle
,
795 return EFI_UNSUPPORTED
;
800 Clean up the HTTP child, release all the resources used by it.
802 @param[in] HttpInstance The HTTP child to clean up.
807 IN HTTP_PROTOCOL
*HttpInstance
810 HttpCloseConnection (HttpInstance
);
812 HttpCloseTcpConnCloseEvent (HttpInstance
);
814 if (HttpInstance
->TimeoutEvent
!= NULL
) {
815 gBS
->CloseEvent (HttpInstance
->TimeoutEvent
);
816 HttpInstance
->TimeoutEvent
= NULL
;
819 if (HttpInstance
->CacheBody
!= NULL
) {
820 FreePool (HttpInstance
->CacheBody
);
821 HttpInstance
->CacheBody
= NULL
;
822 HttpInstance
->NextMsg
= NULL
;
825 if (HttpInstance
->RemoteHost
!= NULL
) {
826 FreePool (HttpInstance
->RemoteHost
);
827 HttpInstance
->RemoteHost
= NULL
;
830 if (HttpInstance
->MsgParser
!= NULL
) {
831 HttpFreeMsgParser (HttpInstance
->MsgParser
);
832 HttpInstance
->MsgParser
= NULL
;
835 if (HttpInstance
->Url
!= NULL
) {
836 FreePool (HttpInstance
->Url
);
837 HttpInstance
->Url
= NULL
;
840 NetMapClean (&HttpInstance
->TxTokens
);
841 NetMapClean (&HttpInstance
->RxTokens
);
843 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
845 HttpInstance
->Tcp4ChildHandle
,
846 &gEfiTcp4ProtocolGuid
,
847 HttpInstance
->Service
->ImageHandle
,
848 HttpInstance
->Service
->ControllerHandle
852 HttpInstance
->Tcp4ChildHandle
,
853 &gEfiTcp4ProtocolGuid
,
854 HttpInstance
->Service
->ImageHandle
,
858 NetLibDestroyServiceChild (
859 HttpInstance
->Service
->ControllerHandle
,
860 HttpInstance
->Service
->ImageHandle
,
861 &gEfiTcp4ServiceBindingProtocolGuid
,
862 HttpInstance
->Tcp4ChildHandle
866 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
868 HttpInstance
->Service
->Tcp4ChildHandle
,
869 &gEfiTcp4ProtocolGuid
,
870 HttpInstance
->Service
->ImageHandle
,
875 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
877 HttpInstance
->Tcp6ChildHandle
,
878 &gEfiTcp6ProtocolGuid
,
879 HttpInstance
->Service
->ImageHandle
,
880 HttpInstance
->Service
->ControllerHandle
884 HttpInstance
->Tcp6ChildHandle
,
885 &gEfiTcp6ProtocolGuid
,
886 HttpInstance
->Service
->ImageHandle
,
890 NetLibDestroyServiceChild (
891 HttpInstance
->Service
->ControllerHandle
,
892 HttpInstance
->Service
->ImageHandle
,
893 &gEfiTcp6ServiceBindingProtocolGuid
,
894 HttpInstance
->Tcp6ChildHandle
898 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
900 HttpInstance
->Service
->Tcp6ChildHandle
,
901 &gEfiTcp6ProtocolGuid
,
902 HttpInstance
->Service
->ImageHandle
,
910 Establish TCP connection with HTTP server.
912 @param[in] HttpInstance The HTTP instance private data.
914 @retval EFI_SUCCESS The TCP connection is established.
915 @retval Others Other error as indicated.
919 HttpCreateConnection (
920 IN HTTP_PROTOCOL
*HttpInstance
926 // Connect to Http server
928 if (!HttpInstance
->LocalAddressIsIPv6
) {
929 HttpInstance
->IsTcp4ConnDone
= FALSE
;
930 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
931 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4ConnToken
);
932 if (EFI_ERROR (Status
)) {
933 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
937 while (!HttpInstance
->IsTcp4ConnDone
) {
938 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
941 Status
= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
;
944 HttpInstance
->IsTcp6ConnDone
= FALSE
;
945 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
946 Status
= HttpInstance
->Tcp6
->Connect (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6ConnToken
);
947 if (EFI_ERROR (Status
)) {
948 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status
));
952 while(!HttpInstance
->IsTcp6ConnDone
) {
953 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
956 Status
= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
;
959 if (!EFI_ERROR (Status
)) {
960 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
967 Close existing TCP connection.
969 @param[in] HttpInstance The HTTP instance private data.
971 @retval EFI_SUCCESS The TCP connection is closed.
972 @retval Others Other error as indicated.
976 HttpCloseConnection (
977 IN HTTP_PROTOCOL
*HttpInstance
982 if (HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) {
984 if (HttpInstance
->LocalAddressIsIPv6
) {
985 HttpInstance
->Tcp6CloseToken
.AbortOnClose
= TRUE
;
986 HttpInstance
->IsTcp6CloseDone
= FALSE
;
987 Status
= HttpInstance
->Tcp6
->Close (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6CloseToken
);
988 if (EFI_ERROR (Status
)) {
992 while (!HttpInstance
->IsTcp6CloseDone
) {
993 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
997 HttpInstance
->Tcp4CloseToken
.AbortOnClose
= TRUE
;
998 HttpInstance
->IsTcp4CloseDone
= FALSE
;
999 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4CloseToken
);
1000 if (EFI_ERROR (Status
)) {
1004 while (!HttpInstance
->IsTcp4CloseDone
) {
1005 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
1011 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
1016 Configure TCP4 protocol child.
1018 @param[in] HttpInstance The HTTP instance private data.
1019 @param[in] Wrap The HTTP token's wrap data.
1021 @retval EFI_SUCCESS The TCP4 protocol child is configured.
1022 @retval Others Other error as indicated.
1027 IN HTTP_PROTOCOL
*HttpInstance
,
1028 IN HTTP_TOKEN_WRAP
*Wrap
1032 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
1033 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
1034 EFI_TCP4_OPTION
*Tcp4Option
;
1036 ASSERT (HttpInstance
!= NULL
);
1039 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
1040 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
1042 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
1043 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
1044 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
1046 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
1047 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
1048 if (!Tcp4AP
->UseDefaultAddress
) {
1049 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
1050 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
1053 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
1054 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
1055 Tcp4AP
->ActiveFlag
= TRUE
;
1056 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
1058 Tcp4Option
= Tcp4CfgData
->ControlOption
;
1059 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1060 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1061 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1062 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1063 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
1064 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1065 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1066 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1067 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1068 Tcp4Option
->EnableNagle
= TRUE
;
1069 Tcp4CfgData
->ControlOption
= Tcp4Option
;
1071 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
1072 if (EFI_ERROR (Status
)) {
1073 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
1077 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1078 if (EFI_ERROR (Status
)) {
1082 Status
= HttpCreateTcpTxEvent (Wrap
);
1083 if (EFI_ERROR (Status
)) {
1087 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1093 Configure TCP6 protocol child.
1095 @param[in] HttpInstance The HTTP instance private data.
1096 @param[in] Wrap The HTTP token's wrap data.
1098 @retval EFI_SUCCESS The TCP6 protocol child is configured.
1099 @retval Others Other error as indicated.
1104 IN HTTP_PROTOCOL
*HttpInstance
,
1105 IN HTTP_TOKEN_WRAP
*Wrap
1109 EFI_TCP6_CONFIG_DATA
*Tcp6CfgData
;
1110 EFI_TCP6_ACCESS_POINT
*Tcp6Ap
;
1111 EFI_TCP6_OPTION
*Tcp6Option
;
1113 ASSERT (HttpInstance
!= NULL
);
1115 Tcp6CfgData
= &HttpInstance
->Tcp6CfgData
;
1116 ZeroMem (Tcp6CfgData
, sizeof (EFI_TCP6_CONFIG_DATA
));
1118 Tcp6CfgData
->TrafficClass
= 0;
1119 Tcp6CfgData
->HopLimit
= 255;
1120 Tcp6CfgData
->ControlOption
= &HttpInstance
->Tcp6Option
;
1122 Tcp6Ap
= &Tcp6CfgData
->AccessPoint
;
1123 Tcp6Ap
->ActiveFlag
= TRUE
;
1124 Tcp6Ap
->StationPort
= HttpInstance
->Ipv6Node
.LocalPort
;
1125 Tcp6Ap
->RemotePort
= HttpInstance
->RemotePort
;
1126 IP6_COPY_ADDRESS (&Tcp6Ap
->StationAddress
, &HttpInstance
->Ipv6Node
.LocalAddress
);
1127 IP6_COPY_ADDRESS (&Tcp6Ap
->RemoteAddress
, &HttpInstance
->RemoteIpv6Addr
);
1129 Tcp6Option
= Tcp6CfgData
->ControlOption
;
1130 Tcp6Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1131 Tcp6Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1132 Tcp6Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1133 Tcp6Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1134 Tcp6Option
->DataRetries
= HTTP_DATA_RETRIES
;
1135 Tcp6Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1136 Tcp6Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1137 Tcp6Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1138 Tcp6Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1139 Tcp6Option
->EnableNagle
= TRUE
;
1141 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, Tcp6CfgData
);
1142 if (EFI_ERROR (Status
)) {
1143 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp6 - %r\n", Status
));
1147 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1148 if (EFI_ERROR (Status
)) {
1152 Status
= HttpCreateTcpTxEvent (Wrap
);
1153 if (EFI_ERROR (Status
)) {
1157 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1164 Check existing TCP connection, if in error state, recover TCP4 connection.
1166 @param[in] HttpInstance The HTTP instance private data.
1168 @retval EFI_SUCCESS The TCP connection is established.
1169 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1170 @retval Others Other error as indicated.
1175 IN HTTP_PROTOCOL
*HttpInstance
1179 EFI_TCP4_CONNECTION_STATE Tcp4State
;
1182 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp4
== NULL
) {
1183 return EFI_NOT_READY
;
1186 Status
= HttpInstance
->Tcp4
->GetModeData(
1194 if (EFI_ERROR(Status
)){
1195 DEBUG ((EFI_D_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
1199 if (Tcp4State
== Tcp4StateEstablished
) {
1201 } else if (Tcp4State
> Tcp4StateEstablished
) {
1202 HttpCloseConnection(HttpInstance
);
1205 return HttpCreateConnection (HttpInstance
);
1209 Check existing TCP connection, if in error state, recover TCP6 connection.
1211 @param[in] HttpInstance The HTTP instance private data.
1213 @retval EFI_SUCCESS The TCP connection is established.
1214 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1215 @retval Others Other error as indicated.
1220 IN HTTP_PROTOCOL
*HttpInstance
1224 EFI_TCP6_CONNECTION_STATE Tcp6State
;
1226 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp6
== NULL
) {
1227 return EFI_NOT_READY
;
1230 Status
= HttpInstance
->Tcp6
->GetModeData (
1239 if (EFI_ERROR(Status
)){
1240 DEBUG ((EFI_D_ERROR
, "Tcp6 GetModeData fail - %x\n", Status
));
1244 if (Tcp6State
== Tcp6StateEstablished
) {
1246 } else if (Tcp6State
> Tcp6StateEstablished
) {
1247 HttpCloseConnection(HttpInstance
);
1250 return HttpCreateConnection (HttpInstance
);
1254 Initialize TCP related data.
1256 @param[in] HttpInstance The HTTP instance private data.
1257 @param[in] Wrap The HTTP token's wrap data.
1258 @param[in] Configure The Flag indicates whether the first time to initialize Tcp.
1260 @retval EFI_SUCCESS The initialization of TCP instance is done.
1261 @retval Others Other error as indicated.
1266 IN HTTP_PROTOCOL
*HttpInstance
,
1267 IN HTTP_TOKEN_WRAP
*Wrap
,
1268 IN BOOLEAN Configure
1272 ASSERT (HttpInstance
!= NULL
);
1274 if (!HttpInstance
->LocalAddressIsIPv6
) {
1276 // Configure TCP instance.
1279 Status
= HttpConfigureTcp4 (HttpInstance
, Wrap
);
1280 if (EFI_ERROR (Status
)) {
1288 Status
= HttpConnectTcp4 (HttpInstance
);
1289 if (EFI_ERROR (Status
)) {
1294 // Configure TCP instance.
1297 Status
= HttpConfigureTcp6 (HttpInstance
, Wrap
);
1298 if (EFI_ERROR (Status
)) {
1306 Status
= HttpConnectTcp6 (HttpInstance
);
1307 if (EFI_ERROR (Status
)) {
1317 Send the HTTP message through TCP4 or TCP6.
1319 @param[in] HttpInstance The HTTP instance private data.
1320 @param[in] Wrap The HTTP token's wrap data.
1321 @param[in] TxString Buffer containing the HTTP message string.
1322 @param[in] TxStringLen Length of the HTTP message string in bytes.
1324 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1325 @retval Others Other error as indicated.
1330 IN HTTP_PROTOCOL
*HttpInstance
,
1331 IN HTTP_TOKEN_WRAP
*Wrap
,
1333 IN UINTN TxStringLen
1337 EFI_TCP4_IO_TOKEN
*Tx4Token
;
1338 EFI_TCP4_PROTOCOL
*Tcp4
;
1339 EFI_TCP6_IO_TOKEN
*Tx6Token
;
1340 EFI_TCP6_PROTOCOL
*Tcp6
;
1342 if (!HttpInstance
->LocalAddressIsIPv6
) {
1343 Tcp4
= HttpInstance
->Tcp4
;
1344 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1346 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1347 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1348 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1349 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1351 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1352 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1353 if (EFI_ERROR (Status
)) {
1354 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1359 Tcp6
= HttpInstance
->Tcp6
;
1360 Tx6Token
= &Wrap
->TcpWrap
.Tx6Token
;
1362 Tx6Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1363 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1364 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1365 Tx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1367 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1368 Status
= Tcp6
->Transmit (Tcp6
, Tx6Token
);
1369 if (EFI_ERROR (Status
)) {
1370 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1380 Check whether the user's token or event has already
1381 been enqueue on HTTP Tx or Rx Token list.
1383 @param[in] Map The container of either user's transmit or receive
1385 @param[in] Item Current item to check against.
1386 @param[in] Context The Token to check againist.
1388 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1389 @retval EFI_SUCCESS The current item isn't the same token/event as the
1397 IN NET_MAP_ITEM
*Item
,
1401 EFI_HTTP_TOKEN
*Token
;
1402 EFI_HTTP_TOKEN
*TokenInItem
;
1404 Token
= (EFI_HTTP_TOKEN
*) Context
;
1405 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
1407 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
1408 return EFI_ACCESS_DENIED
;
1415 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1417 @param[in] Map The container of Tx4Token or Tx6Token.
1418 @param[in] Item Current item to check against.
1419 @param[in] Context The Token to check againist.
1421 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1422 @retval EFI_SUCCESS The HTTP message has been sent out.
1429 IN NET_MAP_ITEM
*Item
,
1433 HTTP_TOKEN_WRAP
*ValueInItem
;
1435 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1437 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
1438 return EFI_NOT_READY
;
1445 Transmit the HTTP mssage by processing the associated HTTP token.
1447 @param[in] Map The container of Tx4Token or Tx6Token.
1448 @param[in] Item Current item to check against.
1449 @param[in] Context The Token to check againist.
1451 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1452 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1460 IN NET_MAP_ITEM
*Item
,
1464 HTTP_TOKEN_WRAP
*ValueInItem
;
1468 UINTN RequestMsgSize
;
1470 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1471 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1476 // Parse the URI of the remote host.
1478 Url
= AllocatePool (StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1);
1480 return EFI_OUT_OF_RESOURCES
;
1483 UnicodeStrToAsciiStr (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
);
1486 // Create request message.
1488 Status
= HttpGenRequestMessage (
1489 ValueInItem
->HttpToken
->Message
,
1496 if (EFI_ERROR (Status
)){
1501 // Transmit the request message.
1503 Status
= HttpTransmitTcp (
1504 ValueInItem
->HttpInstance
,
1506 (UINT8
*) RequestMsg
,
1509 FreePool (RequestMsg
);
1514 Receive the HTTP response by processing the associated HTTP token.
1516 @param[in] Map The container of Rx4Token or Rx6Token.
1517 @param[in] Item Current item to check against.
1518 @param[in] Context The Token to check againist.
1520 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1522 @retval Others Other error as indicated.
1529 IN NET_MAP_ITEM
*Item
,
1534 // Process the queued HTTP response.
1536 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1540 Receive the HTTP header by processing the associated HTTP token.
1542 @param[in] HttpInstance The HTTP instance private data.
1543 @param[in, out] SizeofHeaders The HTTP header length.
1544 @param[in, out] BufferSize The size of buffer to cacahe the header message.
1545 @param[in] Timeout The time to wait for receiving the header packet.
1547 @retval EFI_SUCCESS The HTTP header is received.
1548 @retval Others Other errors as indicated.
1552 HttpTcpReceiveHeader (
1553 IN HTTP_PROTOCOL
*HttpInstance
,
1554 IN OUT UINTN
*SizeofHeaders
,
1555 IN OUT UINTN
*BufferSize
,
1556 IN EFI_EVENT Timeout
1560 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1561 EFI_TCP4_PROTOCOL
*Tcp4
;
1562 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1563 EFI_TCP6_PROTOCOL
*Tcp6
;
1564 CHAR8
**EndofHeader
;
1565 CHAR8
**HttpHeaders
;
1568 ASSERT (HttpInstance
!= NULL
);
1570 EndofHeader
= HttpInstance
->EndofHeader
;
1571 HttpHeaders
= HttpInstance
->HttpHeaders
;
1572 Tcp4
= HttpInstance
->Tcp4
;
1573 Tcp6
= HttpInstance
->Tcp6
;
1578 if (HttpInstance
->LocalAddressIsIPv6
) {
1579 ASSERT (Tcp6
!= NULL
);
1581 ASSERT (Tcp4
!= NULL
);
1584 if (!HttpInstance
->LocalAddressIsIPv6
) {
1585 Rx4Token
= &HttpInstance
->Rx4Token
;
1586 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1587 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1588 Status
= EFI_OUT_OF_RESOURCES
;
1593 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1595 while (*EndofHeader
== NULL
) {
1596 HttpInstance
->IsRxDone
= FALSE
;
1597 Rx4Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1598 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1599 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1600 if (EFI_ERROR (Status
)) {
1601 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1605 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1609 if (!HttpInstance
->IsRxDone
) {
1610 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1611 Rx4Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1614 Status
= Rx4Token
->CompletionToken
.Status
;
1615 if (EFI_ERROR (Status
)) {
1620 // Append the response string.
1622 *BufferSize
= (*SizeofHeaders
) + Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1623 Buffer
= AllocateZeroPool (*BufferSize
);
1624 if (Buffer
== NULL
) {
1625 Status
= EFI_OUT_OF_RESOURCES
;
1629 if (*HttpHeaders
!= NULL
) {
1630 CopyMem (Buffer
, *HttpHeaders
, (*SizeofHeaders
));
1631 FreePool (*HttpHeaders
);
1635 Buffer
+ (*SizeofHeaders
),
1636 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
,
1637 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
1639 *HttpHeaders
= Buffer
;
1640 *SizeofHeaders
= *BufferSize
;
1643 // Check whether we received end of HTTP headers.
1645 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1647 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1648 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1651 Rx6Token
= &HttpInstance
->Rx6Token
;
1652 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1653 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1654 Status
= EFI_OUT_OF_RESOURCES
;
1659 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1661 while (*EndofHeader
== NULL
) {
1662 HttpInstance
->IsRxDone
= FALSE
;
1663 Rx6Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1664 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1665 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1666 if (EFI_ERROR (Status
)) {
1667 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1671 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1675 if (!HttpInstance
->IsRxDone
) {
1676 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1677 Rx6Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1680 Status
= Rx6Token
->CompletionToken
.Status
;
1681 if (EFI_ERROR (Status
)) {
1686 // Append the response string.
1688 *BufferSize
= (*SizeofHeaders
) + Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1689 Buffer
= AllocateZeroPool (*BufferSize
);
1690 if (Buffer
== NULL
) {
1691 Status
= EFI_OUT_OF_RESOURCES
;
1695 if (*HttpHeaders
!= NULL
) {
1696 CopyMem (Buffer
, *HttpHeaders
, (*SizeofHeaders
));
1697 FreePool (*HttpHeaders
);
1701 Buffer
+ (*SizeofHeaders
),
1702 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
,
1703 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
1705 *HttpHeaders
= Buffer
;
1706 *SizeofHeaders
= *BufferSize
;
1709 // Check whether we received end of HTTP headers.
1711 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1714 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1715 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1719 // Skip the CRLF after the HTTP headers.
1721 *EndofHeader
= *EndofHeader
+ AsciiStrLen (HTTP_END_OF_HDR_STR
);
1727 Receive the HTTP body by processing the associated HTTP token.
1729 @param[in] Wrap The HTTP token's wrap data.
1730 @param[in] HttpMsg The HTTP message data.
1731 @param[in] Timeout The time to wait for receiving the body packet.
1733 @retval EFI_SUCCESS The HTTP body is received.
1734 @retval Others Other error as indicated.
1738 HttpTcpReceiveBody (
1739 IN HTTP_TOKEN_WRAP
*Wrap
,
1740 IN EFI_HTTP_MESSAGE
*HttpMsg
,
1741 IN EFI_EVENT Timeout
1745 HTTP_PROTOCOL
*HttpInstance
;
1746 EFI_TCP6_PROTOCOL
*Tcp6
;
1747 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1748 EFI_TCP4_PROTOCOL
*Tcp4
;
1749 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1751 HttpInstance
= Wrap
->HttpInstance
;
1752 Tcp4
= HttpInstance
->Tcp4
;
1753 Tcp6
= HttpInstance
->Tcp6
;
1757 if (HttpInstance
->LocalAddressIsIPv6
) {
1758 ASSERT (Tcp6
!= NULL
);
1760 ASSERT (Tcp4
!= NULL
);
1763 if (HttpInstance
->LocalAddressIsIPv6
) {
1764 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
1765 Rx6Token
->Packet
.RxData
->DataLength
= (UINT32
) HttpMsg
->BodyLength
;
1766 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) HttpMsg
->BodyLength
;
1767 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
1768 Rx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1770 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1771 if (EFI_ERROR (Status
)) {
1772 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1776 while (!Wrap
->TcpWrap
.IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1780 if (!Wrap
->TcpWrap
.IsRxDone
) {
1781 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1782 Rx6Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1783 Wrap
->HttpToken
->Status
= Rx6Token
->CompletionToken
.Status
;
1784 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
1787 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
1788 Rx4Token
->Packet
.RxData
->DataLength
= (UINT32
) HttpMsg
->BodyLength
;
1789 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) HttpMsg
->BodyLength
;
1790 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
1792 Rx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1793 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1794 if (EFI_ERROR (Status
)) {
1795 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1799 while (!Wrap
->TcpWrap
.IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1803 if (!Wrap
->TcpWrap
.IsRxDone
) {
1804 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1805 Rx4Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1806 Wrap
->HttpToken
->Status
= Rx4Token
->CompletionToken
.Status
;
1807 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
1816 Clean up Tcp Tokens while the Tcp transmission error occurs.
1818 @param[in] Wrap Pointer to HTTP token's wrap data.
1822 HttpTcpTokenCleanup (
1823 IN HTTP_TOKEN_WRAP
*Wrap
1826 HTTP_PROTOCOL
*HttpInstance
;
1827 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1828 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1830 ASSERT (Wrap
!= NULL
);
1831 HttpInstance
= Wrap
->HttpInstance
;
1835 if (HttpInstance
->LocalAddressIsIPv6
) {
1836 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
1838 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
1839 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1840 Rx6Token
->CompletionToken
.Event
= NULL
;
1845 Rx6Token
= &HttpInstance
->Rx6Token
;
1847 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
1848 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1849 Rx6Token
->CompletionToken
.Event
= NULL
;
1852 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1853 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1854 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1858 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
1860 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
1861 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1862 Rx4Token
->CompletionToken
.Event
= NULL
;
1867 Rx4Token
= &HttpInstance
->Rx4Token
;
1869 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
1870 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1871 Rx4Token
->CompletionToken
.Event
= NULL
;
1875 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1876 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1877 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;