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
);
160 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
162 if (EFI_ERROR (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
)) {
163 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
164 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
171 // Check whether we receive a complete HTTP message.
173 ASSERT (HttpInstance
->MsgParser
!= NULL
);
175 Length
= (UINTN
) Wrap
->TcpWrap
.Rx6Data
.FragmentTable
[0].FragmentLength
;
177 Length
= (UINTN
) Wrap
->TcpWrap
.Rx4Data
.FragmentTable
[0].FragmentLength
;
180 Status
= HttpParseMessageBody (
181 HttpInstance
->MsgParser
,
183 Wrap
->HttpToken
->Message
->Body
185 if (EFI_ERROR (Status
)) {
189 if (HttpIsMessageComplete (HttpInstance
->MsgParser
)) {
191 // Free the MsgParse since we already have a full HTTP message.
193 HttpFreeMsgParser (HttpInstance
->MsgParser
);
194 HttpInstance
->MsgParser
= NULL
;
197 Wrap
->HttpToken
->Message
->BodyLength
= Length
;
198 ASSERT (HttpInstance
->CacheBody
== NULL
);
200 // We receive part of header of next HTTP msg.
202 if (HttpInstance
->NextMsg
!= NULL
) {
203 Wrap
->HttpToken
->Message
->BodyLength
= HttpInstance
->NextMsg
-
204 (CHAR8
*) Wrap
->HttpToken
->Message
->Body
;
205 HttpInstance
->CacheLen
= Length
- Wrap
->HttpToken
->Message
->BodyLength
;
206 if (HttpInstance
->CacheLen
!= 0) {
207 HttpInstance
->CacheBody
= AllocateZeroPool (HttpInstance
->CacheLen
);
208 if (HttpInstance
->CacheBody
== NULL
) {
211 CopyMem (HttpInstance
->CacheBody
, HttpInstance
->NextMsg
, HttpInstance
->CacheLen
);
212 HttpInstance
->NextMsg
= HttpInstance
->CacheBody
;
213 HttpInstance
->CacheOffset
= 0;
217 Item
= NetMapFindKey (&Wrap
->HttpInstance
->RxTokens
, Wrap
->HttpToken
);
219 NetMapRemoveItem (&Wrap
->HttpInstance
->RxTokens
, Item
, NULL
);
223 Wrap
->TcpWrap
.IsRxDone
= TRUE
;
225 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
227 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
231 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
234 // Check pending RxTokens and receive the HTTP message.
236 NetMapIterate (&Wrap
->HttpInstance
->RxTokens
, HttpTcpReceive
, NULL
);
242 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.
244 @param Event The receive event delivered to TCP for receive.
245 @param Context Context for the callback.
250 HttpTcpReceiveNotify (
256 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
258 QueueDpc (TPL_CALLBACK
, HttpTcpReceiveNotifyDpc
, Context
);
262 Create events for the TCP connection token and TCP close token.
264 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
266 @retval EFI_SUCCESS The events are created successfully.
267 @retval others Other error as indicated.
271 HttpCreateTcpConnCloseEvent (
272 IN HTTP_PROTOCOL
*HttpInstance
277 if (!HttpInstance
->LocalAddressIsIPv6
) {
279 // Create events for variuos asynchronous operations.
281 Status
= gBS
->CreateEvent (
285 &HttpInstance
->IsTcp4ConnDone
,
286 &HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
288 if (EFI_ERROR (Status
)) {
293 // Initialize Tcp4CloseToken
295 Status
= gBS
->CreateEvent (
299 &HttpInstance
->IsTcp4CloseDone
,
300 &HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
302 if (EFI_ERROR (Status
)) {
308 // Create events for variuos asynchronous operations.
310 Status
= gBS
->CreateEvent (
314 &HttpInstance
->IsTcp6ConnDone
,
315 &HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
317 if (EFI_ERROR (Status
)) {
322 // Initialize Tcp6CloseToken
324 Status
= gBS
->CreateEvent (
328 &HttpInstance
->IsTcp6CloseDone
,
329 &HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
331 if (EFI_ERROR (Status
)) {
342 HttpCloseTcpConnCloseEvent (HttpInstance
);
349 Close events in the TCP connection token and TCP close token.
351 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
355 HttpCloseTcpConnCloseEvent (
356 IN HTTP_PROTOCOL
*HttpInstance
359 ASSERT (HttpInstance
!= NULL
);
361 if (HttpInstance
->LocalAddressIsIPv6
) {
362 if (NULL
!= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
) {
363 gBS
->CloseEvent (HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
);
364 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
= NULL
;
367 if (NULL
!= HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
) {
368 gBS
->CloseEvent(HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
);
369 HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
= NULL
;
373 if (NULL
!= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
) {
374 gBS
->CloseEvent (HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
);
375 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
= NULL
;
378 if (NULL
!= HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
) {
379 gBS
->CloseEvent(HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
);
380 HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
387 Create event for the TCP transmit token.
389 @param[in] Wrap Point to HTTP token's wrap data.
391 @retval EFI_SUCCESS The events is created successfully.
392 @retval others Other error as indicated.
396 HttpCreateTcpTxEvent (
397 IN HTTP_TOKEN_WRAP
*Wrap
401 HTTP_PROTOCOL
*HttpInstance
;
402 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
404 HttpInstance
= Wrap
->HttpInstance
;
405 TcpWrap
= &Wrap
->TcpWrap
;
407 if (!HttpInstance
->LocalAddressIsIPv6
) {
408 Status
= gBS
->CreateEvent (
411 HttpTcpTransmitNotify
,
413 &TcpWrap
->Tx4Token
.CompletionToken
.Event
415 if (EFI_ERROR (Status
)) {
419 TcpWrap
->Tx4Data
.Push
= TRUE
;
420 TcpWrap
->Tx4Data
.Urgent
= FALSE
;
421 TcpWrap
->Tx4Data
.FragmentCount
= 1;
422 TcpWrap
->Tx4Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx4Data
;
423 TcpWrap
->Tx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
426 Status
= gBS
->CreateEvent (
429 HttpTcpTransmitNotify
,
431 &TcpWrap
->Tx6Token
.CompletionToken
.Event
433 if (EFI_ERROR (Status
)) {
437 TcpWrap
->Tx6Data
.Push
= TRUE
;
438 TcpWrap
->Tx6Data
.Urgent
= FALSE
;
439 TcpWrap
->Tx6Data
.FragmentCount
= 1;
440 TcpWrap
->Tx6Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx6Data
;
441 TcpWrap
->Tx6Token
.CompletionToken
.Status
=EFI_NOT_READY
;
450 Create event for the TCP receive token which is used to receive HTTP header.
452 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
454 @retval EFI_SUCCESS The events is created successfully.
455 @retval others Other error as indicated.
459 HttpCreateTcpRxEventForHeader (
460 IN HTTP_PROTOCOL
*HttpInstance
465 if (!HttpInstance
->LocalAddressIsIPv6
) {
466 Status
= gBS
->CreateEvent (
470 &HttpInstance
->IsRxDone
,
471 &HttpInstance
->Rx4Token
.CompletionToken
.Event
473 if (EFI_ERROR (Status
)) {
477 HttpInstance
->Rx4Data
.FragmentCount
= 1;
478 HttpInstance
->Rx4Token
.Packet
.RxData
= &HttpInstance
->Rx4Data
;
479 HttpInstance
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
482 Status
= gBS
->CreateEvent (
486 &HttpInstance
->IsRxDone
,
487 &HttpInstance
->Rx6Token
.CompletionToken
.Event
489 if (EFI_ERROR (Status
)) {
493 HttpInstance
->Rx6Data
.FragmentCount
=1;
494 HttpInstance
->Rx6Token
.Packet
.RxData
= &HttpInstance
->Rx6Data
;
495 HttpInstance
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
504 Create event for the TCP receive token which is used to receive HTTP body.
506 @param[in] Wrap Point to HTTP token's wrap data.
508 @retval EFI_SUCCESS The events is created successfully.
509 @retval others Other error as indicated.
513 HttpCreateTcpRxEvent (
514 IN HTTP_TOKEN_WRAP
*Wrap
518 HTTP_PROTOCOL
*HttpInstance
;
519 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
521 HttpInstance
= Wrap
->HttpInstance
;
522 TcpWrap
= &Wrap
->TcpWrap
;
523 if (!HttpInstance
->LocalAddressIsIPv6
) {
524 Status
= gBS
->CreateEvent (
527 HttpTcpReceiveNotify
,
529 &TcpWrap
->Rx4Token
.CompletionToken
.Event
531 if (EFI_ERROR (Status
)) {
535 TcpWrap
->Rx4Data
.FragmentCount
= 1;
536 TcpWrap
->Rx4Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx4Data
;
537 TcpWrap
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
540 Status
= gBS
->CreateEvent (
543 HttpTcpReceiveNotify
,
545 &TcpWrap
->Rx6Token
.CompletionToken
.Event
547 if (EFI_ERROR (Status
)) {
551 TcpWrap
->Rx6Data
.FragmentCount
= 1;
552 TcpWrap
->Rx6Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx6Data
;
553 TcpWrap
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
560 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.
562 @param[in] Wrap Pointer to HTTP token's wrap data.
566 HttpCloseTcpRxEvent (
567 IN HTTP_TOKEN_WRAP
*Wrap
570 HTTP_PROTOCOL
*HttpInstance
;
572 ASSERT (Wrap
!= NULL
);
573 HttpInstance
= Wrap
->HttpInstance
;
575 if (HttpInstance
->LocalAddressIsIPv6
) {
576 if (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
!= NULL
) {
577 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
580 if (HttpInstance
->Rx6Token
.CompletionToken
.Event
!= NULL
) {
581 gBS
->CloseEvent (HttpInstance
->Rx6Token
.CompletionToken
.Event
);
582 HttpInstance
->Rx6Token
.CompletionToken
.Event
= NULL
;
585 if (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
!= NULL
) {
586 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
589 if (HttpInstance
->Rx4Token
.CompletionToken
.Event
!= NULL
) {
590 gBS
->CloseEvent (HttpInstance
->Rx4Token
.CompletionToken
.Event
);
591 HttpInstance
->Rx4Token
.CompletionToken
.Event
= NULL
;
597 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.
599 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
600 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.
602 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
603 @retval Others Other error as indicated.
608 IN OUT HTTP_PROTOCOL
*HttpInstance
,
616 ASSERT (HttpInstance
!= NULL
);
617 UsingIpv6
= IpVersion
;
621 // Create TCP4 child.
623 Status
= NetLibCreateServiceChild (
624 HttpInstance
->Service
->ControllerHandle
,
625 HttpInstance
->Service
->ImageHandle
,
626 &gEfiTcp4ServiceBindingProtocolGuid
,
627 &HttpInstance
->Tcp4ChildHandle
630 if (EFI_ERROR (Status
)) {
634 Status
= gBS
->OpenProtocol (
635 HttpInstance
->Tcp4ChildHandle
,
636 &gEfiTcp4ProtocolGuid
,
637 (VOID
**) &Interface
,
638 HttpInstance
->Service
->ImageHandle
,
639 HttpInstance
->Service
->ControllerHandle
,
640 EFI_OPEN_PROTOCOL_BY_DRIVER
643 if (EFI_ERROR (Status
)) {
647 Status
= gBS
->OpenProtocol (
648 HttpInstance
->Tcp4ChildHandle
,
649 &gEfiTcp4ProtocolGuid
,
650 (VOID
**) &HttpInstance
->Tcp4
,
651 HttpInstance
->Service
->ImageHandle
,
652 HttpInstance
->Handle
,
653 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
655 if (EFI_ERROR(Status
)) {
659 Status
= gBS
->OpenProtocol (
660 HttpInstance
->Service
->Tcp4ChildHandle
,
661 &gEfiTcp4ProtocolGuid
,
662 (VOID
**) &Interface
,
663 HttpInstance
->Service
->ImageHandle
,
664 HttpInstance
->Handle
,
665 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
667 if (EFI_ERROR(Status
)) {
672 // Create TCP6 Child.
674 Status
= NetLibCreateServiceChild (
675 HttpInstance
->Service
->ControllerHandle
,
676 HttpInstance
->Service
->ImageHandle
,
677 &gEfiTcp6ServiceBindingProtocolGuid
,
678 &HttpInstance
->Tcp6ChildHandle
681 if (EFI_ERROR (Status
)) {
685 Status
= gBS
->OpenProtocol (
686 HttpInstance
->Tcp6ChildHandle
,
687 &gEfiTcp6ProtocolGuid
,
688 (VOID
**) &Interface
,
689 HttpInstance
->Service
->ImageHandle
,
690 HttpInstance
->Service
->ControllerHandle
,
691 EFI_OPEN_PROTOCOL_BY_DRIVER
694 if (EFI_ERROR (Status
)) {
698 Status
= gBS
->OpenProtocol (
699 HttpInstance
->Tcp6ChildHandle
,
700 &gEfiTcp6ProtocolGuid
,
701 (VOID
**) &HttpInstance
->Tcp6
,
702 HttpInstance
->Service
->ImageHandle
,
703 HttpInstance
->Handle
,
704 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
707 if (EFI_ERROR(Status
)) {
711 Status
= gBS
->OpenProtocol (
712 HttpInstance
->Service
->Tcp6ChildHandle
,
713 &gEfiTcp6ProtocolGuid
,
714 (VOID
**) &Interface
,
715 HttpInstance
->Service
->ImageHandle
,
716 HttpInstance
->Handle
,
717 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
720 if (EFI_ERROR(Status
)) {
725 HttpInstance
->Url
= AllocateZeroPool (HTTP_URL_BUFFER_LEN
);
726 if (HttpInstance
->Url
== NULL
) {
727 Status
= EFI_OUT_OF_RESOURCES
;
735 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
737 HttpInstance
->Tcp4ChildHandle
,
738 &gEfiTcp4ProtocolGuid
,
739 HttpInstance
->Service
->ImageHandle
,
740 HttpInstance
->Service
->ControllerHandle
744 HttpInstance
->Tcp4ChildHandle
,
745 &gEfiTcp4ProtocolGuid
,
746 HttpInstance
->Service
->ImageHandle
,
750 NetLibDestroyServiceChild (
751 HttpInstance
->Service
->ControllerHandle
,
752 HttpInstance
->Service
->ImageHandle
,
753 &gEfiTcp4ServiceBindingProtocolGuid
,
754 HttpInstance
->Tcp4ChildHandle
758 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
760 HttpInstance
->Service
->Tcp4ChildHandle
,
761 &gEfiTcp4ProtocolGuid
,
762 HttpInstance
->Service
->ImageHandle
,
767 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
769 HttpInstance
->Tcp6ChildHandle
,
770 &gEfiTcp6ProtocolGuid
,
771 HttpInstance
->Service
->ImageHandle
,
772 HttpInstance
->Service
->ControllerHandle
776 HttpInstance
->Tcp6ChildHandle
,
777 &gEfiTcp6ProtocolGuid
,
778 HttpInstance
->Service
->ImageHandle
,
782 NetLibDestroyServiceChild (
783 HttpInstance
->Service
->ControllerHandle
,
784 HttpInstance
->Service
->ImageHandle
,
785 &gEfiTcp6ServiceBindingProtocolGuid
,
786 HttpInstance
->Tcp6ChildHandle
790 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
792 HttpInstance
->Service
->Tcp6ChildHandle
,
793 &gEfiTcp6ProtocolGuid
,
794 HttpInstance
->Service
->ImageHandle
,
799 return EFI_UNSUPPORTED
;
804 Clean up the HTTP child, release all the resources used by it.
806 @param[in] HttpInstance The HTTP child to clean up.
811 IN HTTP_PROTOCOL
*HttpInstance
814 HttpCloseConnection (HttpInstance
);
816 HttpCloseTcpConnCloseEvent (HttpInstance
);
818 if (HttpInstance
->CacheBody
!= NULL
) {
819 FreePool (HttpInstance
->CacheBody
);
820 HttpInstance
->CacheBody
= NULL
;
821 HttpInstance
->NextMsg
= NULL
;
824 if (HttpInstance
->RemoteHost
!= NULL
) {
825 FreePool (HttpInstance
->RemoteHost
);
826 HttpInstance
->RemoteHost
= NULL
;
829 if (HttpInstance
->MsgParser
!= NULL
) {
830 HttpFreeMsgParser (HttpInstance
->MsgParser
);
831 HttpInstance
->MsgParser
= NULL
;
834 if (HttpInstance
->Url
!= NULL
) {
835 FreePool (HttpInstance
->Url
);
836 HttpInstance
->Url
= NULL
;
839 NetMapClean (&HttpInstance
->TxTokens
);
840 NetMapClean (&HttpInstance
->RxTokens
);
842 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
844 HttpInstance
->Tcp4ChildHandle
,
845 &gEfiTcp4ProtocolGuid
,
846 HttpInstance
->Service
->ImageHandle
,
847 HttpInstance
->Service
->ControllerHandle
851 HttpInstance
->Tcp4ChildHandle
,
852 &gEfiTcp4ProtocolGuid
,
853 HttpInstance
->Service
->ImageHandle
,
857 NetLibDestroyServiceChild (
858 HttpInstance
->Service
->ControllerHandle
,
859 HttpInstance
->Service
->ImageHandle
,
860 &gEfiTcp4ServiceBindingProtocolGuid
,
861 HttpInstance
->Tcp4ChildHandle
865 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
867 HttpInstance
->Service
->Tcp4ChildHandle
,
868 &gEfiTcp4ProtocolGuid
,
869 HttpInstance
->Service
->ImageHandle
,
874 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
876 HttpInstance
->Tcp6ChildHandle
,
877 &gEfiTcp6ProtocolGuid
,
878 HttpInstance
->Service
->ImageHandle
,
879 HttpInstance
->Service
->ControllerHandle
883 HttpInstance
->Tcp6ChildHandle
,
884 &gEfiTcp6ProtocolGuid
,
885 HttpInstance
->Service
->ImageHandle
,
889 NetLibDestroyServiceChild (
890 HttpInstance
->Service
->ControllerHandle
,
891 HttpInstance
->Service
->ImageHandle
,
892 &gEfiTcp6ServiceBindingProtocolGuid
,
893 HttpInstance
->Tcp6ChildHandle
897 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
899 HttpInstance
->Service
->Tcp6ChildHandle
,
900 &gEfiTcp6ProtocolGuid
,
901 HttpInstance
->Service
->ImageHandle
,
909 Establish TCP connection with HTTP server.
911 @param[in] HttpInstance The HTTP instance private data.
913 @retval EFI_SUCCESS The TCP connection is established.
914 @retval Others Other error as indicated.
918 HttpCreateConnection (
919 IN HTTP_PROTOCOL
*HttpInstance
925 // Connect to Http server
927 if (!HttpInstance
->LocalAddressIsIPv6
) {
928 HttpInstance
->IsTcp4ConnDone
= FALSE
;
929 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
930 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4ConnToken
);
931 if (EFI_ERROR (Status
)) {
932 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
936 while (!HttpInstance
->IsTcp4ConnDone
) {
937 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
940 Status
= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
;
943 HttpInstance
->IsTcp6ConnDone
= FALSE
;
944 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
945 Status
= HttpInstance
->Tcp6
->Connect (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6ConnToken
);
946 if (EFI_ERROR (Status
)) {
947 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status
));
951 while(!HttpInstance
->IsTcp6ConnDone
) {
952 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
955 Status
= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
;
958 if (!EFI_ERROR (Status
)) {
959 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
966 Close existing TCP connection.
968 @param[in] HttpInstance The HTTP instance private data.
970 @retval EFI_SUCCESS The TCP connection is closed.
971 @retval Others Other error as indicated.
975 HttpCloseConnection (
976 IN HTTP_PROTOCOL
*HttpInstance
981 if (HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) {
983 if (HttpInstance
->LocalAddressIsIPv6
) {
984 HttpInstance
->Tcp6CloseToken
.AbortOnClose
= TRUE
;
985 HttpInstance
->IsTcp6CloseDone
= FALSE
;
986 Status
= HttpInstance
->Tcp6
->Close (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6CloseToken
);
987 if (EFI_ERROR (Status
)) {
991 while (!HttpInstance
->IsTcp6CloseDone
) {
992 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
996 HttpInstance
->Tcp4CloseToken
.AbortOnClose
= TRUE
;
997 HttpInstance
->IsTcp4CloseDone
= FALSE
;
998 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4CloseToken
);
999 if (EFI_ERROR (Status
)) {
1003 while (!HttpInstance
->IsTcp4CloseDone
) {
1004 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
1010 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
1015 Configure TCP4 protocol child.
1017 @param[in] HttpInstance The HTTP instance private data.
1018 @param[in] Wrap The HTTP token's wrap data.
1020 @retval EFI_SUCCESS The TCP4 protocol child is configured.
1021 @retval Others Other error as indicated.
1026 IN HTTP_PROTOCOL
*HttpInstance
,
1027 IN HTTP_TOKEN_WRAP
*Wrap
1031 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
1032 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
1033 EFI_TCP4_OPTION
*Tcp4Option
;
1035 ASSERT (HttpInstance
!= NULL
);
1038 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
1039 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
1041 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
1042 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
1043 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
1045 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
1046 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
1047 if (!Tcp4AP
->UseDefaultAddress
) {
1048 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
1049 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
1052 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
1053 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
1054 Tcp4AP
->ActiveFlag
= TRUE
;
1055 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
1057 Tcp4Option
= Tcp4CfgData
->ControlOption
;
1058 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1059 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1060 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1061 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1062 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
1063 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1064 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1065 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1066 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1067 Tcp4Option
->EnableNagle
= TRUE
;
1068 Tcp4CfgData
->ControlOption
= Tcp4Option
;
1070 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
1071 if (EFI_ERROR (Status
)) {
1072 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
1076 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1077 if (EFI_ERROR (Status
)) {
1081 Status
= HttpCreateTcpTxEvent (Wrap
);
1082 if (EFI_ERROR (Status
)) {
1086 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1092 Configure TCP6 protocol child.
1094 @param[in] HttpInstance The HTTP instance private data.
1095 @param[in] Wrap The HTTP token's wrap data.
1097 @retval EFI_SUCCESS The TCP6 protocol child is configured.
1098 @retval Others Other error as indicated.
1103 IN HTTP_PROTOCOL
*HttpInstance
,
1104 IN HTTP_TOKEN_WRAP
*Wrap
1108 EFI_TCP6_CONFIG_DATA
*Tcp6CfgData
;
1109 EFI_TCP6_ACCESS_POINT
*Tcp6Ap
;
1110 EFI_TCP6_OPTION
*Tcp6Option
;
1112 ASSERT (HttpInstance
!= NULL
);
1114 Tcp6CfgData
= &HttpInstance
->Tcp6CfgData
;
1115 ZeroMem (Tcp6CfgData
, sizeof (EFI_TCP6_CONFIG_DATA
));
1117 Tcp6CfgData
->TrafficClass
= 0;
1118 Tcp6CfgData
->HopLimit
= 255;
1119 Tcp6CfgData
->ControlOption
= &HttpInstance
->Tcp6Option
;
1121 Tcp6Ap
= &Tcp6CfgData
->AccessPoint
;
1122 Tcp6Ap
->ActiveFlag
= TRUE
;
1123 Tcp6Ap
->StationPort
= HttpInstance
->Ipv6Node
.LocalPort
;
1124 Tcp6Ap
->RemotePort
= HttpInstance
->RemotePort
;
1125 IP6_COPY_ADDRESS (&Tcp6Ap
->StationAddress
, &HttpInstance
->Ipv6Node
.LocalAddress
);
1126 IP6_COPY_ADDRESS (&Tcp6Ap
->RemoteAddress
, &HttpInstance
->RemoteIpv6Addr
);
1128 Tcp6Option
= Tcp6CfgData
->ControlOption
;
1129 Tcp6Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1130 Tcp6Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1131 Tcp6Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1132 Tcp6Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1133 Tcp6Option
->DataRetries
= HTTP_DATA_RETRIES
;
1134 Tcp6Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1135 Tcp6Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1136 Tcp6Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1137 Tcp6Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1138 Tcp6Option
->EnableNagle
= TRUE
;
1140 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, Tcp6CfgData
);
1141 if (EFI_ERROR (Status
)) {
1142 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp6 - %r\n", Status
));
1146 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1147 if (EFI_ERROR (Status
)) {
1151 Status
= HttpCreateTcpTxEvent (Wrap
);
1152 if (EFI_ERROR (Status
)) {
1156 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1163 Check existing TCP connection, if in error state, recover TCP4 connection.
1165 @param[in] HttpInstance The HTTP instance private data.
1167 @retval EFI_SUCCESS The TCP connection is established.
1168 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1169 @retval Others Other error as indicated.
1174 IN HTTP_PROTOCOL
*HttpInstance
1178 EFI_TCP4_CONNECTION_STATE Tcp4State
;
1181 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp4
== NULL
) {
1182 return EFI_NOT_READY
;
1185 Status
= HttpInstance
->Tcp4
->GetModeData(
1193 if (EFI_ERROR(Status
)){
1194 DEBUG ((EFI_D_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
1198 if (Tcp4State
== Tcp4StateEstablished
) {
1200 } else if (Tcp4State
> Tcp4StateEstablished
) {
1201 HttpCloseConnection(HttpInstance
);
1204 return HttpCreateConnection (HttpInstance
);
1208 Check existing TCP connection, if in error state, recover TCP6 connection.
1210 @param[in] HttpInstance The HTTP instance private data.
1212 @retval EFI_SUCCESS The TCP connection is established.
1213 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1214 @retval Others Other error as indicated.
1219 IN HTTP_PROTOCOL
*HttpInstance
1223 EFI_TCP6_CONNECTION_STATE Tcp6State
;
1225 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp6
== NULL
) {
1226 return EFI_NOT_READY
;
1229 Status
= HttpInstance
->Tcp6
->GetModeData (
1238 if (EFI_ERROR(Status
)){
1239 DEBUG ((EFI_D_ERROR
, "Tcp6 GetModeData fail - %x\n", Status
));
1243 if (Tcp6State
== Tcp6StateEstablished
) {
1245 } else if (Tcp6State
> Tcp6StateEstablished
) {
1246 HttpCloseConnection(HttpInstance
);
1249 return HttpCreateConnection (HttpInstance
);
1253 Initialize TCP related data.
1255 @param[in] HttpInstance The HTTP instance private data.
1256 @param[in] Wrap The HTTP token's wrap data.
1257 @param[in] Configure The Flag indicates whether the first time to initialize Tcp.
1259 @retval EFI_SUCCESS The initialization of TCP instance is done.
1260 @retval Others Other error as indicated.
1265 IN HTTP_PROTOCOL
*HttpInstance
,
1266 IN HTTP_TOKEN_WRAP
*Wrap
,
1267 IN BOOLEAN Configure
1271 ASSERT (HttpInstance
!= NULL
);
1273 if (!HttpInstance
->LocalAddressIsIPv6
) {
1275 // Configure TCP instance.
1278 Status
= HttpConfigureTcp4 (HttpInstance
, Wrap
);
1279 if (EFI_ERROR (Status
)) {
1287 Status
= HttpConnectTcp4 (HttpInstance
);
1288 if (EFI_ERROR (Status
)) {
1293 // Configure TCP instance.
1296 Status
= HttpConfigureTcp6 (HttpInstance
, Wrap
);
1297 if (EFI_ERROR (Status
)) {
1305 Status
= HttpConnectTcp6 (HttpInstance
);
1306 if (EFI_ERROR (Status
)) {
1316 Send the HTTP message through TCP4 or TCP6.
1318 @param[in] HttpInstance The HTTP instance private data.
1319 @param[in] Wrap The HTTP token's wrap data.
1320 @param[in] TxString Buffer containing the HTTP message string.
1321 @param[in] TxStringLen Length of the HTTP message string in bytes.
1323 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1324 @retval Others Other error as indicated.
1329 IN HTTP_PROTOCOL
*HttpInstance
,
1330 IN HTTP_TOKEN_WRAP
*Wrap
,
1332 IN UINTN TxStringLen
1336 EFI_TCP4_IO_TOKEN
*Tx4Token
;
1337 EFI_TCP4_PROTOCOL
*Tcp4
;
1338 EFI_TCP6_IO_TOKEN
*Tx6Token
;
1339 EFI_TCP6_PROTOCOL
*Tcp6
;
1341 if (!HttpInstance
->LocalAddressIsIPv6
) {
1342 Tcp4
= HttpInstance
->Tcp4
;
1343 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1345 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1346 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1347 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1348 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1350 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1351 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1352 if (EFI_ERROR (Status
)) {
1353 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1358 Tcp6
= HttpInstance
->Tcp6
;
1359 Tx6Token
= &Wrap
->TcpWrap
.Tx6Token
;
1361 Tx6Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1362 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1363 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1364 Tx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1366 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1367 Status
= Tcp6
->Transmit (Tcp6
, Tx6Token
);
1368 if (EFI_ERROR (Status
)) {
1369 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1379 Check whether the user's token or event has already
1380 been enqueue on HTTP Tx or Rx Token list.
1382 @param[in] Map The container of either user's transmit or receive
1384 @param[in] Item Current item to check against.
1385 @param[in] Context The Token to check againist.
1387 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1388 @retval EFI_SUCCESS The current item isn't the same token/event as the
1396 IN NET_MAP_ITEM
*Item
,
1400 EFI_HTTP_TOKEN
*Token
;
1401 EFI_HTTP_TOKEN
*TokenInItem
;
1403 Token
= (EFI_HTTP_TOKEN
*) Context
;
1404 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
1406 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
1407 return EFI_ACCESS_DENIED
;
1414 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1416 @param[in] Map The container of Tx4Token or Tx6Token.
1417 @param[in] Item Current item to check against.
1418 @param[in] Context The Token to check againist.
1420 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1421 @retval EFI_SUCCESS The HTTP message has been sent out.
1428 IN NET_MAP_ITEM
*Item
,
1432 HTTP_TOKEN_WRAP
*ValueInItem
;
1434 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1436 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
1437 return EFI_NOT_READY
;
1444 Transmit the HTTP mssage by processing the associated HTTP token.
1446 @param[in] Map The container of Tx4Token or Tx6Token.
1447 @param[in] Item Current item to check against.
1448 @param[in] Context The Token to check againist.
1450 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1451 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1459 IN NET_MAP_ITEM
*Item
,
1463 HTTP_TOKEN_WRAP
*ValueInItem
;
1468 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1469 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1474 // Parse the URI of the remote host.
1476 Url
= AllocatePool (StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1);
1478 return EFI_OUT_OF_RESOURCES
;
1481 UnicodeStrToAsciiStr (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
);
1484 // Create request message.
1486 Status
= HttpGenRequestString (
1487 ValueInItem
->HttpToken
->Message
,
1493 if (EFI_ERROR (Status
)){
1498 // Transmit the request message.
1500 Status
= HttpTransmitTcp (
1501 ValueInItem
->HttpInstance
,
1503 (UINT8
*) RequestStr
,
1504 AsciiStrLen (RequestStr
)
1506 FreePool (RequestStr
);
1511 Receive the HTTP response by processing the associated HTTP token.
1513 @param[in] Map The container of Rx4Token or Rx6Token.
1514 @param[in] Item Current item to check against.
1515 @param[in] Context The Token to check againist.
1517 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1519 @retval Others Other error as indicated.
1526 IN NET_MAP_ITEM
*Item
,
1531 // Process the queued HTTP response.
1533 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1537 Receive the HTTP header by processing the associated HTTP token.
1539 @param[in] HttpInstance The HTTP instance private data.
1540 @param[in, out] SizeofHeaders The HTTP header length.
1541 @param[in, out] BufferSize The size of buffer to cacahe the header message.
1543 @retval EFI_SUCCESS The HTTP header is received.
1544 @retval Others Other errors as indicated.
1548 HttpTcpReceiveHeader (
1549 IN HTTP_PROTOCOL
*HttpInstance
,
1550 IN OUT UINTN
*SizeofHeaders
,
1551 IN OUT UINTN
*BufferSize
1555 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1556 EFI_TCP4_PROTOCOL
*Tcp4
;
1557 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1558 EFI_TCP6_PROTOCOL
*Tcp6
;
1559 CHAR8
**EndofHeader
;
1560 CHAR8
**HttpHeaders
;
1563 ASSERT (HttpInstance
!= NULL
);
1565 EndofHeader
= HttpInstance
->EndofHeader
;
1566 HttpHeaders
= HttpInstance
->HttpHeaders
;
1567 Tcp4
= HttpInstance
->Tcp4
;
1568 Tcp6
= HttpInstance
->Tcp6
;
1573 if (HttpInstance
->LocalAddressIsIPv6
) {
1574 ASSERT (Tcp6
!= NULL
);
1576 ASSERT (Tcp4
!= NULL
);
1579 if (!HttpInstance
->LocalAddressIsIPv6
) {
1580 Rx4Token
= &HttpInstance
->Rx4Token
;
1581 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1582 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1583 Status
= EFI_OUT_OF_RESOURCES
;
1588 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1590 while (*EndofHeader
== NULL
) {
1591 HttpInstance
->IsRxDone
= FALSE
;
1592 Rx4Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1593 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1594 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1595 if (EFI_ERROR (Status
)) {
1596 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1600 while (!HttpInstance
->IsRxDone
) {
1604 Status
= Rx4Token
->CompletionToken
.Status
;
1605 if (EFI_ERROR (Status
)) {
1610 // Append the response string.
1612 *BufferSize
= (*SizeofHeaders
) + Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1613 Buffer
= AllocateZeroPool (*BufferSize
);
1614 if (Buffer
== NULL
) {
1615 Status
= EFI_OUT_OF_RESOURCES
;
1619 if (*HttpHeaders
!= NULL
) {
1620 CopyMem (Buffer
, *HttpHeaders
, (*SizeofHeaders
));
1621 FreePool (*HttpHeaders
);
1625 Buffer
+ (*SizeofHeaders
),
1626 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
,
1627 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
1629 *HttpHeaders
= Buffer
;
1630 *SizeofHeaders
= *BufferSize
;
1633 // Check whether we received end of HTTP headers.
1635 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1637 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1638 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1641 Rx6Token
= &HttpInstance
->Rx6Token
;
1642 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1643 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1644 Status
= EFI_OUT_OF_RESOURCES
;
1649 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1651 while (*EndofHeader
== NULL
) {
1652 HttpInstance
->IsRxDone
= FALSE
;
1653 Rx6Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1654 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1655 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1656 if (EFI_ERROR (Status
)) {
1657 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1661 while (!HttpInstance
->IsRxDone
) {
1665 Status
= Rx6Token
->CompletionToken
.Status
;
1666 if (EFI_ERROR (Status
)) {
1671 // Append the response string.
1673 *BufferSize
= (*SizeofHeaders
) + Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1674 Buffer
= AllocateZeroPool (*BufferSize
);
1675 if (Buffer
== NULL
) {
1676 Status
= EFI_OUT_OF_RESOURCES
;
1680 if (*HttpHeaders
!= NULL
) {
1681 CopyMem (Buffer
, *HttpHeaders
, (*SizeofHeaders
));
1682 FreePool (*HttpHeaders
);
1686 Buffer
+ (*SizeofHeaders
),
1687 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
,
1688 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
1690 *HttpHeaders
= Buffer
;
1691 *SizeofHeaders
= *BufferSize
;
1694 // Check whether we received end of HTTP headers.
1696 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1699 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1700 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1704 // Skip the CRLF after the HTTP headers.
1706 *EndofHeader
= *EndofHeader
+ AsciiStrLen (HTTP_END_OF_HDR_STR
);
1712 Receive the HTTP body by processing the associated HTTP token.
1714 @param[in] Wrap The HTTP token's wrap data.
1715 @param[in] HttpMsg The HTTP message data.
1717 @retval EFI_SUCCESS The HTTP body is received.
1718 @retval Others Other error as indicated.
1722 HttpTcpReceiveBody (
1723 IN HTTP_TOKEN_WRAP
*Wrap
,
1724 IN EFI_HTTP_MESSAGE
*HttpMsg
1728 HTTP_PROTOCOL
*HttpInstance
;
1729 EFI_TCP6_PROTOCOL
*Tcp6
;
1730 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1731 EFI_TCP4_PROTOCOL
*Tcp4
;
1732 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1734 HttpInstance
= Wrap
->HttpInstance
;
1735 Tcp4
= HttpInstance
->Tcp4
;
1736 Tcp6
= HttpInstance
->Tcp6
;
1741 if (HttpInstance
->LocalAddressIsIPv6
) {
1742 ASSERT (Tcp6
!= NULL
);
1744 ASSERT (Tcp4
!= NULL
);
1747 if (HttpInstance
->LocalAddressIsIPv6
) {
1748 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
1749 Rx6Token
->Packet
.RxData
->DataLength
= (UINT32
) HttpMsg
->BodyLength
;
1750 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) HttpMsg
->BodyLength
;
1751 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
1752 Rx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1754 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1755 if (EFI_ERROR (Status
)) {
1756 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1761 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
1762 Rx4Token
->Packet
.RxData
->DataLength
= (UINT32
) HttpMsg
->BodyLength
;
1763 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) HttpMsg
->BodyLength
;
1764 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
1766 Rx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1767 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1768 if (EFI_ERROR (Status
)) {
1769 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1779 Clean up Tcp Tokens while the Tcp transmission error occurs.
1781 @param[in] Wrap Pointer to HTTP token's wrap data.
1785 HttpTcpTokenCleanup (
1786 IN HTTP_TOKEN_WRAP
*Wrap
1789 HTTP_PROTOCOL
*HttpInstance
;
1790 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1791 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1793 ASSERT (Wrap
!= NULL
);
1794 HttpInstance
= Wrap
->HttpInstance
;
1798 if (HttpInstance
->LocalAddressIsIPv6
) {
1799 if (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
!= NULL
) {
1800 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
1803 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
1804 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1805 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1806 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1810 if (HttpInstance
->Rx6Token
.CompletionToken
.Event
!= NULL
) {
1811 gBS
->CloseEvent (HttpInstance
->Rx6Token
.CompletionToken
.Event
);
1812 HttpInstance
->Rx6Token
.CompletionToken
.Event
= NULL
;
1815 Rx6Token
= &HttpInstance
->Rx6Token
;
1816 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1817 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1818 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1822 if (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
!= NULL
) {
1823 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
1825 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
1826 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1827 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1828 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1832 if (HttpInstance
->Rx4Token
.CompletionToken
.Event
!= NULL
) {
1833 gBS
->CloseEvent (HttpInstance
->Rx4Token
.CompletionToken
.Event
);
1834 HttpInstance
->Rx4Token
.CompletionToken
.Event
= NULL
;
1837 Rx4Token
= &HttpInstance
->Rx4Token
;
1838 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1839 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1840 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;