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
,
931 TlsCloseTxRxEvent (HttpInstance
);
935 Establish TCP connection with HTTP server.
937 @param[in] HttpInstance The HTTP instance private data.
939 @retval EFI_SUCCESS The TCP connection is established.
940 @retval Others Other error as indicated.
944 HttpCreateConnection (
945 IN HTTP_PROTOCOL
*HttpInstance
951 // Connect to Http server
953 if (!HttpInstance
->LocalAddressIsIPv6
) {
954 HttpInstance
->IsTcp4ConnDone
= FALSE
;
955 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
956 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4ConnToken
);
957 if (EFI_ERROR (Status
)) {
958 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
962 while (!HttpInstance
->IsTcp4ConnDone
) {
963 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
966 Status
= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
;
969 HttpInstance
->IsTcp6ConnDone
= FALSE
;
970 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
971 Status
= HttpInstance
->Tcp6
->Connect (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6ConnToken
);
972 if (EFI_ERROR (Status
)) {
973 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status
));
977 while(!HttpInstance
->IsTcp6ConnDone
) {
978 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
981 Status
= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
;
984 if (!EFI_ERROR (Status
)) {
985 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
992 Close existing TCP connection.
994 @param[in] HttpInstance The HTTP instance private data.
996 @retval EFI_SUCCESS The TCP connection is closed.
997 @retval Others Other error as indicated.
1001 HttpCloseConnection (
1002 IN HTTP_PROTOCOL
*HttpInstance
1007 if (HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) {
1009 if (HttpInstance
->LocalAddressIsIPv6
) {
1010 HttpInstance
->Tcp6CloseToken
.AbortOnClose
= TRUE
;
1011 HttpInstance
->IsTcp6CloseDone
= FALSE
;
1012 Status
= HttpInstance
->Tcp6
->Close (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6CloseToken
);
1013 if (EFI_ERROR (Status
)) {
1017 while (!HttpInstance
->IsTcp6CloseDone
) {
1018 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
1022 HttpInstance
->Tcp4CloseToken
.AbortOnClose
= TRUE
;
1023 HttpInstance
->IsTcp4CloseDone
= FALSE
;
1024 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4CloseToken
);
1025 if (EFI_ERROR (Status
)) {
1029 while (!HttpInstance
->IsTcp4CloseDone
) {
1030 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
1036 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
1041 Configure TCP4 protocol child.
1043 @param[in] HttpInstance The HTTP instance private data.
1044 @param[in] Wrap The HTTP token's wrap data.
1046 @retval EFI_SUCCESS The TCP4 protocol child is configured.
1047 @retval Others Other error as indicated.
1052 IN HTTP_PROTOCOL
*HttpInstance
,
1053 IN HTTP_TOKEN_WRAP
*Wrap
1057 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
1058 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
1059 EFI_TCP4_OPTION
*Tcp4Option
;
1061 ASSERT (HttpInstance
!= NULL
);
1064 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
1065 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
1067 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
1068 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
1069 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
1071 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
1072 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
1073 if (!Tcp4AP
->UseDefaultAddress
) {
1074 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
1075 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
1078 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
1079 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
1080 Tcp4AP
->ActiveFlag
= TRUE
;
1081 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
1083 Tcp4Option
= Tcp4CfgData
->ControlOption
;
1084 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1085 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1086 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1087 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1088 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
1089 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1090 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1091 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1092 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1093 Tcp4Option
->EnableNagle
= TRUE
;
1094 Tcp4CfgData
->ControlOption
= Tcp4Option
;
1096 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
1097 if (EFI_ERROR (Status
)) {
1098 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
1102 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1103 if (EFI_ERROR (Status
)) {
1107 Status
= HttpCreateTcpTxEvent (Wrap
);
1108 if (EFI_ERROR (Status
)) {
1112 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1118 Configure TCP6 protocol child.
1120 @param[in] HttpInstance The HTTP instance private data.
1121 @param[in] Wrap The HTTP token's wrap data.
1123 @retval EFI_SUCCESS The TCP6 protocol child is configured.
1124 @retval Others Other error as indicated.
1129 IN HTTP_PROTOCOL
*HttpInstance
,
1130 IN HTTP_TOKEN_WRAP
*Wrap
1134 EFI_TCP6_CONFIG_DATA
*Tcp6CfgData
;
1135 EFI_TCP6_ACCESS_POINT
*Tcp6Ap
;
1136 EFI_TCP6_OPTION
*Tcp6Option
;
1138 ASSERT (HttpInstance
!= NULL
);
1140 Tcp6CfgData
= &HttpInstance
->Tcp6CfgData
;
1141 ZeroMem (Tcp6CfgData
, sizeof (EFI_TCP6_CONFIG_DATA
));
1143 Tcp6CfgData
->TrafficClass
= 0;
1144 Tcp6CfgData
->HopLimit
= 255;
1145 Tcp6CfgData
->ControlOption
= &HttpInstance
->Tcp6Option
;
1147 Tcp6Ap
= &Tcp6CfgData
->AccessPoint
;
1148 Tcp6Ap
->ActiveFlag
= TRUE
;
1149 Tcp6Ap
->StationPort
= HttpInstance
->Ipv6Node
.LocalPort
;
1150 Tcp6Ap
->RemotePort
= HttpInstance
->RemotePort
;
1151 IP6_COPY_ADDRESS (&Tcp6Ap
->StationAddress
, &HttpInstance
->Ipv6Node
.LocalAddress
);
1152 IP6_COPY_ADDRESS (&Tcp6Ap
->RemoteAddress
, &HttpInstance
->RemoteIpv6Addr
);
1154 Tcp6Option
= Tcp6CfgData
->ControlOption
;
1155 Tcp6Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1156 Tcp6Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1157 Tcp6Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1158 Tcp6Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1159 Tcp6Option
->DataRetries
= HTTP_DATA_RETRIES
;
1160 Tcp6Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1161 Tcp6Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1162 Tcp6Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1163 Tcp6Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1164 Tcp6Option
->EnableNagle
= TRUE
;
1166 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, Tcp6CfgData
);
1167 if (EFI_ERROR (Status
)) {
1168 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp6 - %r\n", Status
));
1172 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1173 if (EFI_ERROR (Status
)) {
1177 Status
= HttpCreateTcpTxEvent (Wrap
);
1178 if (EFI_ERROR (Status
)) {
1182 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1189 Check existing TCP connection, if in error state, recover TCP4 connection. Then,
1190 connect one TLS session if required.
1192 @param[in] HttpInstance The HTTP instance private data.
1194 @retval EFI_SUCCESS The TCP connection is established.
1195 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1196 @retval Others Other error as indicated.
1201 IN HTTP_PROTOCOL
*HttpInstance
1205 EFI_TCP4_CONNECTION_STATE Tcp4State
;
1208 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp4
== NULL
) {
1209 return EFI_NOT_READY
;
1212 Status
= HttpInstance
->Tcp4
->GetModeData(
1220 if (EFI_ERROR(Status
)){
1221 DEBUG ((EFI_D_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
1225 if (Tcp4State
== Tcp4StateEstablished
) {
1227 } else if (Tcp4State
> Tcp4StateEstablished
) {
1228 HttpCloseConnection(HttpInstance
);
1231 Status
= HttpCreateConnection (HttpInstance
);
1232 if (EFI_ERROR(Status
)){
1233 DEBUG ((EFI_D_ERROR
, "Tcp4 Connection fail - %x\n", Status
));
1238 // Tls session connection.
1240 if (HttpInstance
->UseHttps
) {
1241 if (HttpInstance
->TimeoutEvent
== NULL
) {
1243 // Create TimeoutEvent for TLS connection.
1245 Status
= gBS
->CreateEvent (
1250 &HttpInstance
->TimeoutEvent
1252 if (EFI_ERROR (Status
)) {
1253 TlsCloseTxRxEvent (HttpInstance
);
1259 // Start the timer, and wait Timeout seconds for connection.
1261 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1262 if (EFI_ERROR (Status
)) {
1263 TlsCloseTxRxEvent (HttpInstance
);
1267 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1269 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1271 if (EFI_ERROR (Status
)) {
1272 TlsCloseTxRxEvent (HttpInstance
);
1281 Check existing TCP connection, if in error state, recover TCP6 connection. Then,
1282 connect one TLS session if required.
1284 @param[in] HttpInstance The HTTP instance private data.
1286 @retval EFI_SUCCESS The TCP connection is established.
1287 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1288 @retval Others Other error as indicated.
1293 IN HTTP_PROTOCOL
*HttpInstance
1297 EFI_TCP6_CONNECTION_STATE Tcp6State
;
1299 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp6
== NULL
) {
1300 return EFI_NOT_READY
;
1303 Status
= HttpInstance
->Tcp6
->GetModeData (
1312 if (EFI_ERROR(Status
)){
1313 DEBUG ((EFI_D_ERROR
, "Tcp6 GetModeData fail - %x\n", Status
));
1317 if (Tcp6State
== Tcp6StateEstablished
) {
1319 } else if (Tcp6State
> Tcp6StateEstablished
) {
1320 HttpCloseConnection(HttpInstance
);
1323 Status
= HttpCreateConnection (HttpInstance
);
1324 if (EFI_ERROR(Status
)){
1325 DEBUG ((EFI_D_ERROR
, "Tcp6 Connection fail - %x\n", Status
));
1330 // Tls session connection.
1332 if (HttpInstance
->UseHttps
) {
1333 if (HttpInstance
->TimeoutEvent
== NULL
) {
1335 // Create TimeoutEvent for TLS connection.
1337 Status
= gBS
->CreateEvent (
1342 &HttpInstance
->TimeoutEvent
1344 if (EFI_ERROR (Status
)) {
1345 TlsCloseTxRxEvent (HttpInstance
);
1351 // Start the timer, and wait Timeout seconds for connection.
1353 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1354 if (EFI_ERROR (Status
)) {
1355 TlsCloseTxRxEvent (HttpInstance
);
1359 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1361 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1363 if (EFI_ERROR (Status
)) {
1364 TlsCloseTxRxEvent (HttpInstance
);
1373 Initialize Http session.
1375 @param[in] HttpInstance The HTTP instance private data.
1376 @param[in] Wrap The HTTP token's wrap data.
1377 @param[in] Configure The Flag indicates whether need to initialize session.
1378 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session.
1380 @retval EFI_SUCCESS The initialization of session is done.
1381 @retval Others Other error as indicated.
1386 IN HTTP_PROTOCOL
*HttpInstance
,
1387 IN HTTP_TOKEN_WRAP
*Wrap
,
1388 IN BOOLEAN Configure
,
1389 IN BOOLEAN TlsConfigure
1393 ASSERT (HttpInstance
!= NULL
);
1396 // Configure Tls session.
1399 Status
= TlsConfigureSession (HttpInstance
);
1400 if (EFI_ERROR (Status
)) {
1405 if (!HttpInstance
->LocalAddressIsIPv6
) {
1407 // Configure TCP instance.
1410 Status
= HttpConfigureTcp4 (HttpInstance
, Wrap
);
1411 if (EFI_ERROR (Status
)) {
1419 Status
= HttpConnectTcp4 (HttpInstance
);
1420 if (EFI_ERROR (Status
)) {
1425 // Configure TCP instance.
1428 Status
= HttpConfigureTcp6 (HttpInstance
, Wrap
);
1429 if (EFI_ERROR (Status
)) {
1437 Status
= HttpConnectTcp6 (HttpInstance
);
1438 if (EFI_ERROR (Status
)) {
1448 Send the HTTP or HTTPS message through TCP4 or TCP6.
1450 @param[in] HttpInstance The HTTP instance private data.
1451 @param[in] Wrap The HTTP token's wrap data.
1452 @param[in] TxString Buffer containing the HTTP message string.
1453 @param[in] TxStringLen Length of the HTTP message string in bytes.
1455 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1456 @retval Others Other error as indicated.
1461 IN HTTP_PROTOCOL
*HttpInstance
,
1462 IN HTTP_TOKEN_WRAP
*Wrap
,
1464 IN UINTN TxStringLen
1468 EFI_TCP4_IO_TOKEN
*Tx4Token
;
1469 EFI_TCP4_PROTOCOL
*Tcp4
;
1470 EFI_TCP6_IO_TOKEN
*Tx6Token
;
1471 EFI_TCP6_PROTOCOL
*Tcp6
;
1474 NET_FRAGMENT TempFragment
;
1476 Status
= EFI_SUCCESS
;
1480 // Need to encrypt data.
1482 if (HttpInstance
->UseHttps
) {
1484 // Build BufferOut data
1486 BufferSize
= sizeof (TLS_RECORD_HEADER
) + TxStringLen
;
1487 Buffer
= AllocateZeroPool (BufferSize
);
1488 if (Buffer
== NULL
) {
1489 Status
= EFI_OUT_OF_RESOURCES
;
1492 ((TLS_RECORD_HEADER
*) Buffer
)->ContentType
= TLS_CONTENT_TYPE_APPLICATION_DATA
;
1493 ((TLS_RECORD_HEADER
*) Buffer
)->Version
.Major
= HttpInstance
->TlsConfigData
.Version
.Major
;
1494 ((TLS_RECORD_HEADER
*) Buffer
)->Version
.Minor
= HttpInstance
->TlsConfigData
.Version
.Minor
;
1495 ((TLS_RECORD_HEADER
*) Buffer
)->Length
= (UINT16
) (TxStringLen
);
1496 CopyMem (Buffer
+ sizeof (TLS_RECORD_HEADER
), TxString
, TxStringLen
);
1501 Status
= TlsProcessMessage (
1511 if (EFI_ERROR (Status
)) {
1516 if (!HttpInstance
->LocalAddressIsIPv6
) {
1517 Tcp4
= HttpInstance
->Tcp4
;
1518 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1520 if (HttpInstance
->UseHttps
) {
1521 Tx4Token
->Packet
.TxData
->DataLength
= TempFragment
.Len
;
1522 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= TempFragment
.Len
;
1523 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TempFragment
.Bulk
;
1525 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1526 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1527 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1530 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1532 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1533 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1534 if (EFI_ERROR (Status
)) {
1535 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1540 Tcp6
= HttpInstance
->Tcp6
;
1541 Tx6Token
= &Wrap
->TcpWrap
.Tx6Token
;
1543 if (HttpInstance
->UseHttps
) {
1544 Tx6Token
->Packet
.TxData
->DataLength
= TempFragment
.Len
;
1545 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= TempFragment
.Len
;
1546 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TempFragment
.Bulk
;
1548 Tx6Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1549 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1550 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1553 Tx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1555 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1556 Status
= Tcp6
->Transmit (Tcp6
, Tx6Token
);
1557 if (EFI_ERROR (Status
)) {
1558 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1567 Check whether the user's token or event has already
1568 been enqueue on HTTP Tx or Rx Token list.
1570 @param[in] Map The container of either user's transmit or receive
1572 @param[in] Item Current item to check against.
1573 @param[in] Context The Token to check againist.
1575 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1576 @retval EFI_SUCCESS The current item isn't the same token/event as the
1584 IN NET_MAP_ITEM
*Item
,
1588 EFI_HTTP_TOKEN
*Token
;
1589 EFI_HTTP_TOKEN
*TokenInItem
;
1591 Token
= (EFI_HTTP_TOKEN
*) Context
;
1592 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
1594 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
1595 return EFI_ACCESS_DENIED
;
1602 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1604 @param[in] Map The container of Tx4Token or Tx6Token.
1605 @param[in] Item Current item to check against.
1606 @param[in] Context The Token to check againist.
1608 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1609 @retval EFI_SUCCESS The HTTP message has been sent out.
1616 IN NET_MAP_ITEM
*Item
,
1620 HTTP_TOKEN_WRAP
*ValueInItem
;
1622 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1624 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
1625 return EFI_NOT_READY
;
1632 Transmit the HTTP or HTTPS mssage by processing the associated HTTP token.
1634 @param[in] Map The container of Tx4Token or Tx6Token.
1635 @param[in] Item Current item to check against.
1636 @param[in] Context The Token to check againist.
1638 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1639 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1647 IN NET_MAP_ITEM
*Item
,
1651 HTTP_TOKEN_WRAP
*ValueInItem
;
1656 UINTN RequestMsgSize
;
1660 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1661 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1666 // Parse the URI of the remote host.
1668 UrlSize
= StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1;
1669 Url
= AllocatePool (UrlSize
);
1671 return EFI_OUT_OF_RESOURCES
;
1674 UnicodeStrToAsciiStrS (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
, UrlSize
);
1677 // Create request message.
1679 Status
= HttpGenRequestMessage (
1680 ValueInItem
->HttpToken
->Message
,
1687 if (EFI_ERROR (Status
) || NULL
== RequestMsg
){
1691 ASSERT (RequestMsg
!= NULL
);
1694 // Transmit the request message.
1696 Status
= HttpTransmitTcp (
1697 ValueInItem
->HttpInstance
,
1699 (UINT8
*) RequestMsg
,
1702 FreePool (RequestMsg
);
1707 Receive the HTTP response by processing the associated HTTP token.
1709 @param[in] Map The container of Rx4Token or Rx6Token.
1710 @param[in] Item Current item to check against.
1711 @param[in] Context The Token to check againist.
1713 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1715 @retval Others Other error as indicated.
1722 IN NET_MAP_ITEM
*Item
,
1727 // Process the queued HTTP response.
1729 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1733 Receive the HTTP header by processing the associated HTTP token.
1735 @param[in] HttpInstance The HTTP instance private data.
1736 @param[in, out] SizeofHeaders The HTTP header length.
1737 @param[in, out] BufferSize The size of buffer to cacahe the header message.
1738 @param[in] Timeout The time to wait for receiving the header packet.
1740 @retval EFI_SUCCESS The HTTP header is received.
1741 @retval Others Other errors as indicated.
1745 HttpTcpReceiveHeader (
1746 IN HTTP_PROTOCOL
*HttpInstance
,
1747 IN OUT UINTN
*SizeofHeaders
,
1748 IN OUT UINTN
*BufferSize
,
1749 IN EFI_EVENT Timeout
1753 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1754 EFI_TCP4_PROTOCOL
*Tcp4
;
1755 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1756 EFI_TCP6_PROTOCOL
*Tcp6
;
1757 CHAR8
**EndofHeader
;
1758 CHAR8
**HttpHeaders
;
1760 NET_FRAGMENT Fragment
;
1762 ASSERT (HttpInstance
!= NULL
);
1764 EndofHeader
= HttpInstance
->EndofHeader
;
1765 HttpHeaders
= HttpInstance
->HttpHeaders
;
1766 Tcp4
= HttpInstance
->Tcp4
;
1767 Tcp6
= HttpInstance
->Tcp6
;
1772 Fragment
.Bulk
= NULL
;
1774 if (HttpInstance
->LocalAddressIsIPv6
) {
1775 ASSERT (Tcp6
!= NULL
);
1777 ASSERT (Tcp4
!= NULL
);
1780 if (!HttpInstance
->UseHttps
) {
1781 Status
= HttpCreateTcpRxEventForHeader (HttpInstance
);
1782 if (EFI_ERROR (Status
)) {
1787 if (!HttpInstance
->LocalAddressIsIPv6
) {
1788 if (!HttpInstance
->UseHttps
) {
1789 Rx4Token
= &HttpInstance
->Rx4Token
;
1790 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1791 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1792 Status
= EFI_OUT_OF_RESOURCES
;
1798 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1800 while (*EndofHeader
== NULL
) {
1801 if (!HttpInstance
->UseHttps
) {
1802 HttpInstance
->IsRxDone
= FALSE
;
1803 Rx4Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1804 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1805 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1806 if (EFI_ERROR (Status
)) {
1807 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1811 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1815 if (!HttpInstance
->IsRxDone
) {
1817 // Cancle the Token before close its Event.
1819 Tcp4
->Cancel (HttpInstance
->Tcp4
, &Rx4Token
->CompletionToken
);
1820 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1821 Rx4Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1824 Status
= Rx4Token
->CompletionToken
.Status
;
1825 if (EFI_ERROR (Status
)) {
1829 Fragment
.Len
= Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1830 Fragment
.Bulk
= (UINT8
*) Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
1832 if (Fragment
.Bulk
!= NULL
) {
1833 FreePool (Fragment
.Bulk
);
1834 Fragment
.Bulk
= NULL
;
1837 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
1838 if (EFI_ERROR (Status
)) {
1839 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1845 // Append the response string.
1847 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
1848 Buffer
= AllocateZeroPool (*BufferSize
);
1849 if (Buffer
== NULL
) {
1850 Status
= EFI_OUT_OF_RESOURCES
;
1854 if (*HttpHeaders
!= NULL
) {
1855 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
1856 FreePool (*HttpHeaders
);
1860 Buffer
+ *SizeofHeaders
,
1864 *HttpHeaders
= Buffer
;
1865 *SizeofHeaders
= *BufferSize
;
1868 // Check whether we received end of HTTP headers.
1870 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1876 if (Rx4Token
!= NULL
&& Rx4Token
->Packet
.RxData
!= NULL
&& Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1877 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1878 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1879 Fragment
.Bulk
= NULL
;
1882 if (Fragment
.Bulk
!= NULL
) {
1883 FreePool (Fragment
.Bulk
);
1884 Fragment
.Bulk
= NULL
;
1887 if (!HttpInstance
->UseHttps
) {
1888 Rx6Token
= &HttpInstance
->Rx6Token
;
1889 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1890 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1891 Status
= EFI_OUT_OF_RESOURCES
;
1897 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1899 while (*EndofHeader
== NULL
) {
1900 if (!HttpInstance
->UseHttps
) {
1901 HttpInstance
->IsRxDone
= FALSE
;
1902 Rx6Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1903 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1904 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1905 if (EFI_ERROR (Status
)) {
1906 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1910 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1914 if (!HttpInstance
->IsRxDone
) {
1916 // Cancle the Token before close its Event.
1918 Tcp6
->Cancel (HttpInstance
->Tcp6
, &Rx6Token
->CompletionToken
);
1919 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1920 Rx6Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1923 Status
= Rx6Token
->CompletionToken
.Status
;
1924 if (EFI_ERROR (Status
)) {
1928 Fragment
.Len
= Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1929 Fragment
.Bulk
= (UINT8
*) Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
1931 if (Fragment
.Bulk
!= NULL
) {
1932 FreePool (Fragment
.Bulk
);
1933 Fragment
.Bulk
= NULL
;
1936 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
1937 if (EFI_ERROR (Status
)) {
1938 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1944 // Append the response string.
1946 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
1947 Buffer
= AllocateZeroPool (*BufferSize
);
1948 if (Buffer
== NULL
) {
1949 Status
= EFI_OUT_OF_RESOURCES
;
1953 if (*HttpHeaders
!= NULL
) {
1954 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
1955 FreePool (*HttpHeaders
);
1959 Buffer
+ *SizeofHeaders
,
1963 *HttpHeaders
= Buffer
;
1964 *SizeofHeaders
= *BufferSize
;
1967 // Check whether we received end of HTTP headers.
1969 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1975 if (Rx6Token
!= NULL
&& Rx6Token
->Packet
.RxData
!= NULL
&& Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1976 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1977 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1978 Fragment
.Bulk
= NULL
;
1981 if (Fragment
.Bulk
!= NULL
) {
1982 FreePool (Fragment
.Bulk
);
1983 Fragment
.Bulk
= NULL
;
1988 // Skip the CRLF after the HTTP headers.
1990 *EndofHeader
= *EndofHeader
+ AsciiStrLen (HTTP_END_OF_HDR_STR
);
1996 Receive the HTTP body by processing the associated HTTP token.
1998 @param[in] Wrap The HTTP token's wrap data.
1999 @param[in] HttpMsg The HTTP message data.
2001 @retval EFI_SUCCESS The HTTP body is received.
2002 @retval Others Other error as indicated.
2006 HttpTcpReceiveBody (
2007 IN HTTP_TOKEN_WRAP
*Wrap
,
2008 IN EFI_HTTP_MESSAGE
*HttpMsg
2012 HTTP_PROTOCOL
*HttpInstance
;
2013 EFI_TCP6_PROTOCOL
*Tcp6
;
2014 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2015 EFI_TCP4_PROTOCOL
*Tcp4
;
2016 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2018 HttpInstance
= Wrap
->HttpInstance
;
2019 Tcp4
= HttpInstance
->Tcp4
;
2020 Tcp6
= HttpInstance
->Tcp6
;
2024 if (HttpInstance
->LocalAddressIsIPv6
) {
2025 ASSERT (Tcp6
!= NULL
);
2027 ASSERT (Tcp4
!= NULL
);
2030 if (HttpInstance
->LocalAddressIsIPv6
) {
2031 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2032 Rx6Token
->Packet
.RxData
->DataLength
= (UINT32
) HttpMsg
->BodyLength
;
2033 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) HttpMsg
->BodyLength
;
2034 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
2035 Rx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2037 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
2038 if (EFI_ERROR (Status
)) {
2039 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
2043 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2044 Rx4Token
->Packet
.RxData
->DataLength
= (UINT32
) HttpMsg
->BodyLength
;
2045 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) HttpMsg
->BodyLength
;
2046 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
2048 Rx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2049 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
2050 if (EFI_ERROR (Status
)) {
2051 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
2061 Clean up Tcp Tokens while the Tcp transmission error occurs.
2063 @param[in] Wrap Pointer to HTTP token's wrap data.
2067 HttpTcpTokenCleanup (
2068 IN HTTP_TOKEN_WRAP
*Wrap
2071 HTTP_PROTOCOL
*HttpInstance
;
2072 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2073 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2075 ASSERT (Wrap
!= NULL
);
2076 HttpInstance
= Wrap
->HttpInstance
;
2080 if (HttpInstance
->LocalAddressIsIPv6
) {
2081 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2083 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2084 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2085 Rx6Token
->CompletionToken
.Event
= NULL
;
2090 Rx6Token
= &HttpInstance
->Rx6Token
;
2092 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2093 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2094 Rx6Token
->CompletionToken
.Event
= NULL
;
2097 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2098 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2099 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2103 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2105 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2106 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2107 Rx4Token
->CompletionToken
.Event
= NULL
;
2112 Rx4Token
= &HttpInstance
->Rx4Token
;
2114 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2115 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2116 Rx4Token
->CompletionToken
.Event
= NULL
;
2120 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2121 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2122 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;