2 Miscellaneous routines for HttpDxe driver.
4 Copyright (c) 2015 - 2016, 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
);
151 Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
= NULL
;
153 if (EFI_ERROR (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
)) {
154 DEBUG ((EFI_D_ERROR
, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
));
155 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
156 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
158 Item
= NetMapFindKey (&HttpInstance
->RxTokens
, Wrap
->HttpToken
);
160 NetMapRemoveItem (&HttpInstance
->RxTokens
, Item
, NULL
);
170 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
171 Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
= NULL
;
173 if (EFI_ERROR (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
)) {
174 DEBUG ((EFI_D_ERROR
, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
));
175 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
176 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
178 Item
= NetMapFindKey (&HttpInstance
->RxTokens
, Wrap
->HttpToken
);
180 NetMapRemoveItem (&HttpInstance
->RxTokens
, Item
, NULL
);
191 // Check whether we receive a complete HTTP message.
193 ASSERT (HttpInstance
->MsgParser
!= NULL
);
195 Length
= (UINTN
) Wrap
->TcpWrap
.Rx6Data
.FragmentTable
[0].FragmentLength
;
197 Length
= (UINTN
) Wrap
->TcpWrap
.Rx4Data
.FragmentTable
[0].FragmentLength
;
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
) {
231 CopyMem (HttpInstance
->CacheBody
, HttpInstance
->NextMsg
, HttpInstance
->CacheLen
);
232 HttpInstance
->NextMsg
= HttpInstance
->CacheBody
;
233 HttpInstance
->CacheOffset
= 0;
237 Item
= NetMapFindKey (&Wrap
->HttpInstance
->RxTokens
, Wrap
->HttpToken
);
239 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
;
251 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
254 // Check pending RxTokens and receive the HTTP message.
256 NetMapIterate (&Wrap
->HttpInstance
->RxTokens
, HttpTcpReceive
, NULL
);
263 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.
265 @param Event The receive event delivered to TCP for receive.
266 @param Context Context for the callback.
271 HttpTcpReceiveNotify (
277 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
279 QueueDpc (TPL_CALLBACK
, HttpTcpReceiveNotifyDpc
, Context
);
283 Create events for the TCP connection token and TCP close token.
285 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
287 @retval EFI_SUCCESS The events are created successfully.
288 @retval others Other error as indicated.
292 HttpCreateTcpConnCloseEvent (
293 IN HTTP_PROTOCOL
*HttpInstance
298 if (!HttpInstance
->LocalAddressIsIPv6
) {
300 // Create events for variuos asynchronous operations.
302 Status
= gBS
->CreateEvent (
306 &HttpInstance
->IsTcp4ConnDone
,
307 &HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
309 if (EFI_ERROR (Status
)) {
314 // Initialize Tcp4CloseToken
316 Status
= gBS
->CreateEvent (
320 &HttpInstance
->IsTcp4CloseDone
,
321 &HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
323 if (EFI_ERROR (Status
)) {
329 // Create events for variuos asynchronous operations.
331 Status
= gBS
->CreateEvent (
335 &HttpInstance
->IsTcp6ConnDone
,
336 &HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
338 if (EFI_ERROR (Status
)) {
343 // Initialize Tcp6CloseToken
345 Status
= gBS
->CreateEvent (
349 &HttpInstance
->IsTcp6CloseDone
,
350 &HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
352 if (EFI_ERROR (Status
)) {
363 HttpCloseTcpConnCloseEvent (HttpInstance
);
370 Close events in the TCP connection token and TCP close token.
372 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
376 HttpCloseTcpConnCloseEvent (
377 IN HTTP_PROTOCOL
*HttpInstance
380 ASSERT (HttpInstance
!= NULL
);
382 if (HttpInstance
->LocalAddressIsIPv6
) {
383 if (NULL
!= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
) {
384 gBS
->CloseEvent (HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
);
385 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
= NULL
;
388 if (NULL
!= HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
) {
389 gBS
->CloseEvent(HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
);
390 HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
= NULL
;
394 if (NULL
!= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
) {
395 gBS
->CloseEvent (HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
);
396 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
= NULL
;
399 if (NULL
!= HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
) {
400 gBS
->CloseEvent(HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
);
401 HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
408 Create event for the TCP transmit token.
410 @param[in] Wrap Point to HTTP token's wrap data.
412 @retval EFI_SUCCESS The events is created successfully.
413 @retval others Other error as indicated.
417 HttpCreateTcpTxEvent (
418 IN HTTP_TOKEN_WRAP
*Wrap
422 HTTP_PROTOCOL
*HttpInstance
;
423 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
425 HttpInstance
= Wrap
->HttpInstance
;
426 TcpWrap
= &Wrap
->TcpWrap
;
428 if (!HttpInstance
->LocalAddressIsIPv6
) {
429 Status
= gBS
->CreateEvent (
432 HttpTcpTransmitNotify
,
434 &TcpWrap
->Tx4Token
.CompletionToken
.Event
436 if (EFI_ERROR (Status
)) {
440 TcpWrap
->Tx4Data
.Push
= TRUE
;
441 TcpWrap
->Tx4Data
.Urgent
= FALSE
;
442 TcpWrap
->Tx4Data
.FragmentCount
= 1;
443 TcpWrap
->Tx4Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx4Data
;
444 TcpWrap
->Tx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
447 Status
= gBS
->CreateEvent (
450 HttpTcpTransmitNotify
,
452 &TcpWrap
->Tx6Token
.CompletionToken
.Event
454 if (EFI_ERROR (Status
)) {
458 TcpWrap
->Tx6Data
.Push
= TRUE
;
459 TcpWrap
->Tx6Data
.Urgent
= FALSE
;
460 TcpWrap
->Tx6Data
.FragmentCount
= 1;
461 TcpWrap
->Tx6Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx6Data
;
462 TcpWrap
->Tx6Token
.CompletionToken
.Status
=EFI_NOT_READY
;
470 Create event for the TCP receive token which is used to receive HTTP header.
472 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
474 @retval EFI_SUCCESS The events is created successfully.
475 @retval others Other error as indicated.
479 HttpCreateTcpRxEventForHeader (
480 IN HTTP_PROTOCOL
*HttpInstance
485 if (!HttpInstance
->LocalAddressIsIPv6
) {
486 Status
= gBS
->CreateEvent (
490 &HttpInstance
->IsRxDone
,
491 &HttpInstance
->Rx4Token
.CompletionToken
.Event
493 if (EFI_ERROR (Status
)) {
497 HttpInstance
->Rx4Data
.FragmentCount
= 1;
498 HttpInstance
->Rx4Token
.Packet
.RxData
= &HttpInstance
->Rx4Data
;
499 HttpInstance
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
502 Status
= gBS
->CreateEvent (
506 &HttpInstance
->IsRxDone
,
507 &HttpInstance
->Rx6Token
.CompletionToken
.Event
509 if (EFI_ERROR (Status
)) {
513 HttpInstance
->Rx6Data
.FragmentCount
=1;
514 HttpInstance
->Rx6Token
.Packet
.RxData
= &HttpInstance
->Rx6Data
;
515 HttpInstance
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
524 Create event for the TCP receive token which is used to receive HTTP body.
526 @param[in] Wrap Point to HTTP token's wrap data.
528 @retval EFI_SUCCESS The events is created successfully.
529 @retval others Other error as indicated.
533 HttpCreateTcpRxEvent (
534 IN HTTP_TOKEN_WRAP
*Wrap
538 HTTP_PROTOCOL
*HttpInstance
;
539 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
541 HttpInstance
= Wrap
->HttpInstance
;
542 TcpWrap
= &Wrap
->TcpWrap
;
543 if (!HttpInstance
->LocalAddressIsIPv6
) {
544 Status
= gBS
->CreateEvent (
547 HttpTcpReceiveNotify
,
549 &TcpWrap
->Rx4Token
.CompletionToken
.Event
551 if (EFI_ERROR (Status
)) {
555 TcpWrap
->Rx4Data
.FragmentCount
= 1;
556 TcpWrap
->Rx4Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx4Data
;
557 TcpWrap
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
560 Status
= gBS
->CreateEvent (
563 HttpTcpReceiveNotify
,
565 &TcpWrap
->Rx6Token
.CompletionToken
.Event
567 if (EFI_ERROR (Status
)) {
571 TcpWrap
->Rx6Data
.FragmentCount
= 1;
572 TcpWrap
->Rx6Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx6Data
;
573 TcpWrap
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
580 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.
582 @param[in] Wrap Pointer to HTTP token's wrap data.
586 HttpCloseTcpRxEvent (
587 IN HTTP_TOKEN_WRAP
*Wrap
590 HTTP_PROTOCOL
*HttpInstance
;
592 ASSERT (Wrap
!= NULL
);
593 HttpInstance
= Wrap
->HttpInstance
;
595 if (HttpInstance
->LocalAddressIsIPv6
) {
596 if (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
!= NULL
) {
597 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
600 if (HttpInstance
->Rx6Token
.CompletionToken
.Event
!= NULL
) {
601 gBS
->CloseEvent (HttpInstance
->Rx6Token
.CompletionToken
.Event
);
602 HttpInstance
->Rx6Token
.CompletionToken
.Event
= NULL
;
605 if (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
!= NULL
) {
606 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
609 if (HttpInstance
->Rx4Token
.CompletionToken
.Event
!= NULL
) {
610 gBS
->CloseEvent (HttpInstance
->Rx4Token
.CompletionToken
.Event
);
611 HttpInstance
->Rx4Token
.CompletionToken
.Event
= NULL
;
617 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.
619 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
620 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.
622 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
623 @retval Others Other error as indicated.
628 IN OUT HTTP_PROTOCOL
*HttpInstance
,
636 ASSERT (HttpInstance
!= NULL
);
637 UsingIpv6
= IpVersion
;
641 // Create TCP4 child.
643 Status
= NetLibCreateServiceChild (
644 HttpInstance
->Service
->ControllerHandle
,
645 HttpInstance
->Service
->ImageHandle
,
646 &gEfiTcp4ServiceBindingProtocolGuid
,
647 &HttpInstance
->Tcp4ChildHandle
650 if (EFI_ERROR (Status
)) {
654 Status
= gBS
->OpenProtocol (
655 HttpInstance
->Tcp4ChildHandle
,
656 &gEfiTcp4ProtocolGuid
,
657 (VOID
**) &Interface
,
658 HttpInstance
->Service
->ImageHandle
,
659 HttpInstance
->Service
->ControllerHandle
,
660 EFI_OPEN_PROTOCOL_BY_DRIVER
663 if (EFI_ERROR (Status
)) {
667 Status
= gBS
->OpenProtocol (
668 HttpInstance
->Tcp4ChildHandle
,
669 &gEfiTcp4ProtocolGuid
,
670 (VOID
**) &HttpInstance
->Tcp4
,
671 HttpInstance
->Service
->ImageHandle
,
672 HttpInstance
->Handle
,
673 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
675 if (EFI_ERROR(Status
)) {
679 Status
= gBS
->OpenProtocol (
680 HttpInstance
->Service
->Tcp4ChildHandle
,
681 &gEfiTcp4ProtocolGuid
,
682 (VOID
**) &Interface
,
683 HttpInstance
->Service
->ImageHandle
,
684 HttpInstance
->Handle
,
685 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
687 if (EFI_ERROR(Status
)) {
692 // Create TCP6 Child.
694 Status
= NetLibCreateServiceChild (
695 HttpInstance
->Service
->ControllerHandle
,
696 HttpInstance
->Service
->ImageHandle
,
697 &gEfiTcp6ServiceBindingProtocolGuid
,
698 &HttpInstance
->Tcp6ChildHandle
701 if (EFI_ERROR (Status
)) {
705 Status
= gBS
->OpenProtocol (
706 HttpInstance
->Tcp6ChildHandle
,
707 &gEfiTcp6ProtocolGuid
,
708 (VOID
**) &Interface
,
709 HttpInstance
->Service
->ImageHandle
,
710 HttpInstance
->Service
->ControllerHandle
,
711 EFI_OPEN_PROTOCOL_BY_DRIVER
714 if (EFI_ERROR (Status
)) {
718 Status
= gBS
->OpenProtocol (
719 HttpInstance
->Tcp6ChildHandle
,
720 &gEfiTcp6ProtocolGuid
,
721 (VOID
**) &HttpInstance
->Tcp6
,
722 HttpInstance
->Service
->ImageHandle
,
723 HttpInstance
->Handle
,
724 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
727 if (EFI_ERROR(Status
)) {
731 Status
= gBS
->OpenProtocol (
732 HttpInstance
->Service
->Tcp6ChildHandle
,
733 &gEfiTcp6ProtocolGuid
,
734 (VOID
**) &Interface
,
735 HttpInstance
->Service
->ImageHandle
,
736 HttpInstance
->Handle
,
737 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
740 if (EFI_ERROR(Status
)) {
745 HttpInstance
->Url
= AllocateZeroPool (HTTP_URL_BUFFER_LEN
);
746 if (HttpInstance
->Url
== NULL
) {
747 Status
= EFI_OUT_OF_RESOURCES
;
755 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
757 HttpInstance
->Tcp4ChildHandle
,
758 &gEfiTcp4ProtocolGuid
,
759 HttpInstance
->Service
->ImageHandle
,
760 HttpInstance
->Service
->ControllerHandle
764 HttpInstance
->Tcp4ChildHandle
,
765 &gEfiTcp4ProtocolGuid
,
766 HttpInstance
->Service
->ImageHandle
,
770 NetLibDestroyServiceChild (
771 HttpInstance
->Service
->ControllerHandle
,
772 HttpInstance
->Service
->ImageHandle
,
773 &gEfiTcp4ServiceBindingProtocolGuid
,
774 HttpInstance
->Tcp4ChildHandle
778 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
780 HttpInstance
->Service
->Tcp4ChildHandle
,
781 &gEfiTcp4ProtocolGuid
,
782 HttpInstance
->Service
->ImageHandle
,
787 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
789 HttpInstance
->Tcp6ChildHandle
,
790 &gEfiTcp6ProtocolGuid
,
791 HttpInstance
->Service
->ImageHandle
,
792 HttpInstance
->Service
->ControllerHandle
796 HttpInstance
->Tcp6ChildHandle
,
797 &gEfiTcp6ProtocolGuid
,
798 HttpInstance
->Service
->ImageHandle
,
802 NetLibDestroyServiceChild (
803 HttpInstance
->Service
->ControllerHandle
,
804 HttpInstance
->Service
->ImageHandle
,
805 &gEfiTcp6ServiceBindingProtocolGuid
,
806 HttpInstance
->Tcp6ChildHandle
810 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
812 HttpInstance
->Service
->Tcp6ChildHandle
,
813 &gEfiTcp6ProtocolGuid
,
814 HttpInstance
->Service
->ImageHandle
,
819 return EFI_UNSUPPORTED
;
824 Clean up the HTTP child, release all the resources used by it.
826 @param[in] HttpInstance The HTTP child to clean up.
831 IN HTTP_PROTOCOL
*HttpInstance
834 HttpCloseConnection (HttpInstance
);
836 HttpCloseTcpConnCloseEvent (HttpInstance
);
838 if (HttpInstance
->TimeoutEvent
!= NULL
) {
839 gBS
->CloseEvent (HttpInstance
->TimeoutEvent
);
840 HttpInstance
->TimeoutEvent
= NULL
;
843 if (HttpInstance
->CacheBody
!= NULL
) {
844 FreePool (HttpInstance
->CacheBody
);
845 HttpInstance
->CacheBody
= NULL
;
846 HttpInstance
->NextMsg
= NULL
;
849 if (HttpInstance
->RemoteHost
!= NULL
) {
850 FreePool (HttpInstance
->RemoteHost
);
851 HttpInstance
->RemoteHost
= NULL
;
854 if (HttpInstance
->MsgParser
!= NULL
) {
855 HttpFreeMsgParser (HttpInstance
->MsgParser
);
856 HttpInstance
->MsgParser
= NULL
;
859 if (HttpInstance
->Url
!= NULL
) {
860 FreePool (HttpInstance
->Url
);
861 HttpInstance
->Url
= NULL
;
864 NetMapClean (&HttpInstance
->TxTokens
);
865 NetMapClean (&HttpInstance
->RxTokens
);
867 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
869 HttpInstance
->Tcp4ChildHandle
,
870 &gEfiTcp4ProtocolGuid
,
871 HttpInstance
->Service
->ImageHandle
,
872 HttpInstance
->Service
->ControllerHandle
876 HttpInstance
->Tcp4ChildHandle
,
877 &gEfiTcp4ProtocolGuid
,
878 HttpInstance
->Service
->ImageHandle
,
882 NetLibDestroyServiceChild (
883 HttpInstance
->Service
->ControllerHandle
,
884 HttpInstance
->Service
->ImageHandle
,
885 &gEfiTcp4ServiceBindingProtocolGuid
,
886 HttpInstance
->Tcp4ChildHandle
890 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
892 HttpInstance
->Service
->Tcp4ChildHandle
,
893 &gEfiTcp4ProtocolGuid
,
894 HttpInstance
->Service
->ImageHandle
,
899 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
901 HttpInstance
->Tcp6ChildHandle
,
902 &gEfiTcp6ProtocolGuid
,
903 HttpInstance
->Service
->ImageHandle
,
904 HttpInstance
->Service
->ControllerHandle
908 HttpInstance
->Tcp6ChildHandle
,
909 &gEfiTcp6ProtocolGuid
,
910 HttpInstance
->Service
->ImageHandle
,
914 NetLibDestroyServiceChild (
915 HttpInstance
->Service
->ControllerHandle
,
916 HttpInstance
->Service
->ImageHandle
,
917 &gEfiTcp6ServiceBindingProtocolGuid
,
918 HttpInstance
->Tcp6ChildHandle
922 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
924 HttpInstance
->Service
->Tcp6ChildHandle
,
925 &gEfiTcp6ProtocolGuid
,
926 HttpInstance
->Service
->ImageHandle
,
934 Establish TCP connection with HTTP server.
936 @param[in] HttpInstance The HTTP instance private data.
938 @retval EFI_SUCCESS The TCP connection is established.
939 @retval Others Other error as indicated.
943 HttpCreateConnection (
944 IN HTTP_PROTOCOL
*HttpInstance
950 // Connect to Http server
952 if (!HttpInstance
->LocalAddressIsIPv6
) {
953 HttpInstance
->IsTcp4ConnDone
= FALSE
;
954 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
955 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4ConnToken
);
956 if (EFI_ERROR (Status
)) {
957 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
961 while (!HttpInstance
->IsTcp4ConnDone
) {
962 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
965 Status
= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
;
968 HttpInstance
->IsTcp6ConnDone
= FALSE
;
969 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
970 Status
= HttpInstance
->Tcp6
->Connect (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6ConnToken
);
971 if (EFI_ERROR (Status
)) {
972 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status
));
976 while(!HttpInstance
->IsTcp6ConnDone
) {
977 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
980 Status
= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
;
983 if (!EFI_ERROR (Status
)) {
984 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
991 Close existing TCP connection.
993 @param[in] HttpInstance The HTTP instance private data.
995 @retval EFI_SUCCESS The TCP connection is closed.
996 @retval Others Other error as indicated.
1000 HttpCloseConnection (
1001 IN HTTP_PROTOCOL
*HttpInstance
1006 if (HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) {
1008 if (HttpInstance
->LocalAddressIsIPv6
) {
1009 HttpInstance
->Tcp6CloseToken
.AbortOnClose
= TRUE
;
1010 HttpInstance
->IsTcp6CloseDone
= FALSE
;
1011 Status
= HttpInstance
->Tcp6
->Close (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6CloseToken
);
1012 if (EFI_ERROR (Status
)) {
1016 while (!HttpInstance
->IsTcp6CloseDone
) {
1017 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
1021 HttpInstance
->Tcp4CloseToken
.AbortOnClose
= TRUE
;
1022 HttpInstance
->IsTcp4CloseDone
= FALSE
;
1023 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4CloseToken
);
1024 if (EFI_ERROR (Status
)) {
1028 while (!HttpInstance
->IsTcp4CloseDone
) {
1029 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
1035 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
1040 Configure TCP4 protocol child.
1042 @param[in] HttpInstance The HTTP instance private data.
1043 @param[in] Wrap The HTTP token's wrap data.
1045 @retval EFI_SUCCESS The TCP4 protocol child is configured.
1046 @retval Others Other error as indicated.
1051 IN HTTP_PROTOCOL
*HttpInstance
,
1052 IN HTTP_TOKEN_WRAP
*Wrap
1056 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
1057 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
1058 EFI_TCP4_OPTION
*Tcp4Option
;
1060 ASSERT (HttpInstance
!= NULL
);
1063 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
1064 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
1066 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
1067 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
1068 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
1070 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
1071 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
1072 if (!Tcp4AP
->UseDefaultAddress
) {
1073 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
1074 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
1077 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
1078 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
1079 Tcp4AP
->ActiveFlag
= TRUE
;
1080 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
1082 Tcp4Option
= Tcp4CfgData
->ControlOption
;
1083 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1084 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1085 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1086 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1087 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
1088 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1089 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1090 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1091 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1092 Tcp4Option
->EnableNagle
= TRUE
;
1093 Tcp4CfgData
->ControlOption
= Tcp4Option
;
1095 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
1096 if (EFI_ERROR (Status
)) {
1097 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
1101 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1102 if (EFI_ERROR (Status
)) {
1106 Status
= HttpCreateTcpTxEvent (Wrap
);
1107 if (EFI_ERROR (Status
)) {
1111 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1117 Configure TCP6 protocol child.
1119 @param[in] HttpInstance The HTTP instance private data.
1120 @param[in] Wrap The HTTP token's wrap data.
1122 @retval EFI_SUCCESS The TCP6 protocol child is configured.
1123 @retval Others Other error as indicated.
1128 IN HTTP_PROTOCOL
*HttpInstance
,
1129 IN HTTP_TOKEN_WRAP
*Wrap
1133 EFI_TCP6_CONFIG_DATA
*Tcp6CfgData
;
1134 EFI_TCP6_ACCESS_POINT
*Tcp6Ap
;
1135 EFI_TCP6_OPTION
*Tcp6Option
;
1137 ASSERT (HttpInstance
!= NULL
);
1139 Tcp6CfgData
= &HttpInstance
->Tcp6CfgData
;
1140 ZeroMem (Tcp6CfgData
, sizeof (EFI_TCP6_CONFIG_DATA
));
1142 Tcp6CfgData
->TrafficClass
= 0;
1143 Tcp6CfgData
->HopLimit
= 255;
1144 Tcp6CfgData
->ControlOption
= &HttpInstance
->Tcp6Option
;
1146 Tcp6Ap
= &Tcp6CfgData
->AccessPoint
;
1147 Tcp6Ap
->ActiveFlag
= TRUE
;
1148 Tcp6Ap
->StationPort
= HttpInstance
->Ipv6Node
.LocalPort
;
1149 Tcp6Ap
->RemotePort
= HttpInstance
->RemotePort
;
1150 IP6_COPY_ADDRESS (&Tcp6Ap
->StationAddress
, &HttpInstance
->Ipv6Node
.LocalAddress
);
1151 IP6_COPY_ADDRESS (&Tcp6Ap
->RemoteAddress
, &HttpInstance
->RemoteIpv6Addr
);
1153 Tcp6Option
= Tcp6CfgData
->ControlOption
;
1154 Tcp6Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1155 Tcp6Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1156 Tcp6Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1157 Tcp6Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1158 Tcp6Option
->DataRetries
= HTTP_DATA_RETRIES
;
1159 Tcp6Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1160 Tcp6Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1161 Tcp6Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1162 Tcp6Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1163 Tcp6Option
->EnableNagle
= TRUE
;
1165 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, Tcp6CfgData
);
1166 if (EFI_ERROR (Status
)) {
1167 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp6 - %r\n", Status
));
1171 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1172 if (EFI_ERROR (Status
)) {
1176 Status
= HttpCreateTcpTxEvent (Wrap
);
1177 if (EFI_ERROR (Status
)) {
1181 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1188 Check existing TCP connection, if in error state, recover TCP4 connection.
1190 @param[in] HttpInstance The HTTP instance private data.
1192 @retval EFI_SUCCESS The TCP connection is established.
1193 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1194 @retval Others Other error as indicated.
1199 IN HTTP_PROTOCOL
*HttpInstance
1203 EFI_TCP4_CONNECTION_STATE Tcp4State
;
1206 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp4
== NULL
) {
1207 return EFI_NOT_READY
;
1210 Status
= HttpInstance
->Tcp4
->GetModeData(
1218 if (EFI_ERROR(Status
)){
1219 DEBUG ((EFI_D_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
1223 if (Tcp4State
== Tcp4StateEstablished
) {
1225 } else if (Tcp4State
> Tcp4StateEstablished
) {
1226 HttpCloseConnection(HttpInstance
);
1229 return HttpCreateConnection (HttpInstance
);
1233 Check existing TCP connection, if in error state, recover TCP6 connection.
1235 @param[in] HttpInstance The HTTP instance private data.
1237 @retval EFI_SUCCESS The TCP connection is established.
1238 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1239 @retval Others Other error as indicated.
1244 IN HTTP_PROTOCOL
*HttpInstance
1248 EFI_TCP6_CONNECTION_STATE Tcp6State
;
1250 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp6
== NULL
) {
1251 return EFI_NOT_READY
;
1254 Status
= HttpInstance
->Tcp6
->GetModeData (
1263 if (EFI_ERROR(Status
)){
1264 DEBUG ((EFI_D_ERROR
, "Tcp6 GetModeData fail - %x\n", Status
));
1268 if (Tcp6State
== Tcp6StateEstablished
) {
1270 } else if (Tcp6State
> Tcp6StateEstablished
) {
1271 HttpCloseConnection(HttpInstance
);
1274 return HttpCreateConnection (HttpInstance
);
1278 Initialize TCP related data.
1280 @param[in] HttpInstance The HTTP instance private data.
1281 @param[in] Wrap The HTTP token's wrap data.
1282 @param[in] Configure The Flag indicates whether the first time to initialize Tcp.
1284 @retval EFI_SUCCESS The initialization of TCP instance is done.
1285 @retval Others Other error as indicated.
1290 IN HTTP_PROTOCOL
*HttpInstance
,
1291 IN HTTP_TOKEN_WRAP
*Wrap
,
1292 IN BOOLEAN Configure
1296 ASSERT (HttpInstance
!= NULL
);
1298 if (!HttpInstance
->LocalAddressIsIPv6
) {
1300 // Configure TCP instance.
1303 Status
= HttpConfigureTcp4 (HttpInstance
, Wrap
);
1304 if (EFI_ERROR (Status
)) {
1312 Status
= HttpConnectTcp4 (HttpInstance
);
1313 if (EFI_ERROR (Status
)) {
1318 // Configure TCP instance.
1321 Status
= HttpConfigureTcp6 (HttpInstance
, Wrap
);
1322 if (EFI_ERROR (Status
)) {
1330 Status
= HttpConnectTcp6 (HttpInstance
);
1331 if (EFI_ERROR (Status
)) {
1341 Send the HTTP message through TCP4 or TCP6.
1343 @param[in] HttpInstance The HTTP instance private data.
1344 @param[in] Wrap The HTTP token's wrap data.
1345 @param[in] TxString Buffer containing the HTTP message string.
1346 @param[in] TxStringLen Length of the HTTP message string in bytes.
1348 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1349 @retval Others Other error as indicated.
1354 IN HTTP_PROTOCOL
*HttpInstance
,
1355 IN HTTP_TOKEN_WRAP
*Wrap
,
1357 IN UINTN TxStringLen
1361 EFI_TCP4_IO_TOKEN
*Tx4Token
;
1362 EFI_TCP4_PROTOCOL
*Tcp4
;
1363 EFI_TCP6_IO_TOKEN
*Tx6Token
;
1364 EFI_TCP6_PROTOCOL
*Tcp6
;
1366 if (!HttpInstance
->LocalAddressIsIPv6
) {
1367 Tcp4
= HttpInstance
->Tcp4
;
1368 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1370 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1371 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1372 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1373 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1375 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1376 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1377 if (EFI_ERROR (Status
)) {
1378 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1383 Tcp6
= HttpInstance
->Tcp6
;
1384 Tx6Token
= &Wrap
->TcpWrap
.Tx6Token
;
1386 Tx6Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1387 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1388 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1389 Tx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1391 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1392 Status
= Tcp6
->Transmit (Tcp6
, Tx6Token
);
1393 if (EFI_ERROR (Status
)) {
1394 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1404 Check whether the user's token or event has already
1405 been enqueue on HTTP Tx or Rx Token list.
1407 @param[in] Map The container of either user's transmit or receive
1409 @param[in] Item Current item to check against.
1410 @param[in] Context The Token to check againist.
1412 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1413 @retval EFI_SUCCESS The current item isn't the same token/event as the
1421 IN NET_MAP_ITEM
*Item
,
1425 EFI_HTTP_TOKEN
*Token
;
1426 EFI_HTTP_TOKEN
*TokenInItem
;
1428 Token
= (EFI_HTTP_TOKEN
*) Context
;
1429 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
1431 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
1432 return EFI_ACCESS_DENIED
;
1439 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1441 @param[in] Map The container of Tx4Token or Tx6Token.
1442 @param[in] Item Current item to check against.
1443 @param[in] Context The Token to check againist.
1445 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1446 @retval EFI_SUCCESS The HTTP message has been sent out.
1453 IN NET_MAP_ITEM
*Item
,
1457 HTTP_TOKEN_WRAP
*ValueInItem
;
1459 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1461 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
1462 return EFI_NOT_READY
;
1469 Transmit the HTTP mssage by processing the associated HTTP token.
1471 @param[in] Map The container of Tx4Token or Tx6Token.
1472 @param[in] Item Current item to check against.
1473 @param[in] Context The Token to check againist.
1475 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1476 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1484 IN NET_MAP_ITEM
*Item
,
1488 HTTP_TOKEN_WRAP
*ValueInItem
;
1493 UINTN RequestMsgSize
;
1495 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1496 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1501 // Parse the URI of the remote host.
1503 UrlSize
= StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1;
1504 Url
= AllocatePool (UrlSize
);
1506 return EFI_OUT_OF_RESOURCES
;
1509 UnicodeStrToAsciiStrS (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
, UrlSize
);
1512 // Create request message.
1514 Status
= HttpGenRequestMessage (
1515 ValueInItem
->HttpToken
->Message
,
1522 if (EFI_ERROR (Status
)){
1527 // Transmit the request message.
1529 Status
= HttpTransmitTcp (
1530 ValueInItem
->HttpInstance
,
1532 (UINT8
*) RequestMsg
,
1535 FreePool (RequestMsg
);
1540 Receive the HTTP response by processing the associated HTTP token.
1542 @param[in] Map The container of Rx4Token or Rx6Token.
1543 @param[in] Item Current item to check against.
1544 @param[in] Context The Token to check againist.
1546 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1548 @retval Others Other error as indicated.
1555 IN NET_MAP_ITEM
*Item
,
1560 // Process the queued HTTP response.
1562 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1566 Receive the HTTP header by processing the associated HTTP token.
1568 @param[in] HttpInstance The HTTP instance private data.
1569 @param[in, out] SizeofHeaders The HTTP header length.
1570 @param[in, out] BufferSize The size of buffer to cacahe the header message.
1571 @param[in] Timeout The time to wait for receiving the header packet.
1573 @retval EFI_SUCCESS The HTTP header is received.
1574 @retval Others Other errors as indicated.
1578 HttpTcpReceiveHeader (
1579 IN HTTP_PROTOCOL
*HttpInstance
,
1580 IN OUT UINTN
*SizeofHeaders
,
1581 IN OUT UINTN
*BufferSize
,
1582 IN EFI_EVENT Timeout
1586 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1587 EFI_TCP4_PROTOCOL
*Tcp4
;
1588 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1589 EFI_TCP6_PROTOCOL
*Tcp6
;
1590 CHAR8
**EndofHeader
;
1591 CHAR8
**HttpHeaders
;
1594 ASSERT (HttpInstance
!= NULL
);
1596 EndofHeader
= HttpInstance
->EndofHeader
;
1597 HttpHeaders
= HttpInstance
->HttpHeaders
;
1598 Tcp4
= HttpInstance
->Tcp4
;
1599 Tcp6
= HttpInstance
->Tcp6
;
1604 if (HttpInstance
->LocalAddressIsIPv6
) {
1605 ASSERT (Tcp6
!= NULL
);
1607 ASSERT (Tcp4
!= NULL
);
1610 if (!HttpInstance
->LocalAddressIsIPv6
) {
1611 Rx4Token
= &HttpInstance
->Rx4Token
;
1612 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1613 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1614 Status
= EFI_OUT_OF_RESOURCES
;
1619 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1621 while (*EndofHeader
== NULL
) {
1622 HttpInstance
->IsRxDone
= FALSE
;
1623 Rx4Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1624 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1625 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1626 if (EFI_ERROR (Status
)) {
1627 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1631 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1635 if (!HttpInstance
->IsRxDone
) {
1637 // Cancle the Token before close its Event.
1639 Tcp4
->Cancel (HttpInstance
->Tcp4
, &Rx4Token
->CompletionToken
);
1640 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1641 Rx4Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1644 Status
= Rx4Token
->CompletionToken
.Status
;
1645 if (EFI_ERROR (Status
)) {
1650 // Append the response string.
1652 *BufferSize
= (*SizeofHeaders
) + Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1653 Buffer
= AllocateZeroPool (*BufferSize
);
1654 if (Buffer
== NULL
) {
1655 Status
= EFI_OUT_OF_RESOURCES
;
1659 if (*HttpHeaders
!= NULL
) {
1660 CopyMem (Buffer
, *HttpHeaders
, (*SizeofHeaders
));
1661 FreePool (*HttpHeaders
);
1665 Buffer
+ (*SizeofHeaders
),
1666 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
,
1667 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
1669 *HttpHeaders
= Buffer
;
1670 *SizeofHeaders
= *BufferSize
;
1673 // Check whether we received end of HTTP headers.
1675 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1677 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1678 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1681 Rx6Token
= &HttpInstance
->Rx6Token
;
1682 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1683 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1684 Status
= EFI_OUT_OF_RESOURCES
;
1689 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1691 while (*EndofHeader
== NULL
) {
1692 HttpInstance
->IsRxDone
= FALSE
;
1693 Rx6Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1694 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1695 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1696 if (EFI_ERROR (Status
)) {
1697 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1701 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1705 if (!HttpInstance
->IsRxDone
) {
1707 // Cancle the Token before close its Event.
1709 Tcp6
->Cancel (HttpInstance
->Tcp6
, &Rx6Token
->CompletionToken
);
1710 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1711 Rx6Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1714 Status
= Rx6Token
->CompletionToken
.Status
;
1715 if (EFI_ERROR (Status
)) {
1720 // Append the response string.
1722 *BufferSize
= (*SizeofHeaders
) + Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1723 Buffer
= AllocateZeroPool (*BufferSize
);
1724 if (Buffer
== NULL
) {
1725 Status
= EFI_OUT_OF_RESOURCES
;
1729 if (*HttpHeaders
!= NULL
) {
1730 CopyMem (Buffer
, *HttpHeaders
, (*SizeofHeaders
));
1731 FreePool (*HttpHeaders
);
1735 Buffer
+ (*SizeofHeaders
),
1736 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
,
1737 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
1739 *HttpHeaders
= Buffer
;
1740 *SizeofHeaders
= *BufferSize
;
1743 // Check whether we received end of HTTP headers.
1745 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1748 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1749 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1753 // Skip the CRLF after the HTTP headers.
1755 *EndofHeader
= *EndofHeader
+ AsciiStrLen (HTTP_END_OF_HDR_STR
);
1761 Receive the HTTP body by processing the associated HTTP token.
1763 @param[in] Wrap The HTTP token's wrap data.
1764 @param[in] HttpMsg The HTTP message data.
1766 @retval EFI_SUCCESS The HTTP body is received.
1767 @retval Others Other error as indicated.
1771 HttpTcpReceiveBody (
1772 IN HTTP_TOKEN_WRAP
*Wrap
,
1773 IN EFI_HTTP_MESSAGE
*HttpMsg
1777 HTTP_PROTOCOL
*HttpInstance
;
1778 EFI_TCP6_PROTOCOL
*Tcp6
;
1779 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1780 EFI_TCP4_PROTOCOL
*Tcp4
;
1781 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1783 HttpInstance
= Wrap
->HttpInstance
;
1784 Tcp4
= HttpInstance
->Tcp4
;
1785 Tcp6
= HttpInstance
->Tcp6
;
1789 if (HttpInstance
->LocalAddressIsIPv6
) {
1790 ASSERT (Tcp6
!= NULL
);
1792 ASSERT (Tcp4
!= NULL
);
1795 if (HttpInstance
->LocalAddressIsIPv6
) {
1796 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
1797 Rx6Token
->Packet
.RxData
->DataLength
= (UINT32
) HttpMsg
->BodyLength
;
1798 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) HttpMsg
->BodyLength
;
1799 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
1800 Rx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1802 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1803 if (EFI_ERROR (Status
)) {
1804 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1808 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
1809 Rx4Token
->Packet
.RxData
->DataLength
= (UINT32
) HttpMsg
->BodyLength
;
1810 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) HttpMsg
->BodyLength
;
1811 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
1813 Rx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1814 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1815 if (EFI_ERROR (Status
)) {
1816 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1826 Clean up Tcp Tokens while the Tcp transmission error occurs.
1828 @param[in] Wrap Pointer to HTTP token's wrap data.
1832 HttpTcpTokenCleanup (
1833 IN HTTP_TOKEN_WRAP
*Wrap
1836 HTTP_PROTOCOL
*HttpInstance
;
1837 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1838 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1840 ASSERT (Wrap
!= NULL
);
1841 HttpInstance
= Wrap
->HttpInstance
;
1845 if (HttpInstance
->LocalAddressIsIPv6
) {
1846 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
1848 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
1849 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1850 Rx6Token
->CompletionToken
.Event
= NULL
;
1855 Rx6Token
= &HttpInstance
->Rx6Token
;
1857 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
1858 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1859 Rx6Token
->CompletionToken
.Event
= NULL
;
1862 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1863 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1864 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1868 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
1870 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
1871 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1872 Rx4Token
->CompletionToken
.Event
= NULL
;
1877 Rx4Token
= &HttpInstance
->Rx4Token
;
1879 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
1880 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1881 Rx4Token
->CompletionToken
.Event
= NULL
;
1885 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1886 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1887 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;