2 Miscellaneous routines for HttpDxe driver.
4 Copyright (c) 2015 - 2017, 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
->Ip4DriverBindingHandle
,
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
->Ip4DriverBindingHandle
,
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
->Ip4DriverBindingHandle
,
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
->Ip4DriverBindingHandle
,
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
->Ip6DriverBindingHandle
,
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
->Ip6DriverBindingHandle
,
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
->Ip6DriverBindingHandle
,
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
->Ip6DriverBindingHandle
,
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
->Ip4DriverBindingHandle
,
760 HttpInstance
->Service
->ControllerHandle
764 HttpInstance
->Tcp4ChildHandle
,
765 &gEfiTcp4ProtocolGuid
,
766 HttpInstance
->Service
->Ip4DriverBindingHandle
,
770 NetLibDestroyServiceChild (
771 HttpInstance
->Service
->ControllerHandle
,
772 HttpInstance
->Service
->Ip4DriverBindingHandle
,
773 &gEfiTcp4ServiceBindingProtocolGuid
,
774 HttpInstance
->Tcp4ChildHandle
778 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
780 HttpInstance
->Service
->Tcp4ChildHandle
,
781 &gEfiTcp4ProtocolGuid
,
782 HttpInstance
->Service
->Ip4DriverBindingHandle
,
787 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
789 HttpInstance
->Tcp6ChildHandle
,
790 &gEfiTcp6ProtocolGuid
,
791 HttpInstance
->Service
->Ip6DriverBindingHandle
,
792 HttpInstance
->Service
->ControllerHandle
796 HttpInstance
->Tcp6ChildHandle
,
797 &gEfiTcp6ProtocolGuid
,
798 HttpInstance
->Service
->Ip6DriverBindingHandle
,
802 NetLibDestroyServiceChild (
803 HttpInstance
->Service
->ControllerHandle
,
804 HttpInstance
->Service
->Ip6DriverBindingHandle
,
805 &gEfiTcp6ServiceBindingProtocolGuid
,
806 HttpInstance
->Tcp6ChildHandle
810 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
812 HttpInstance
->Service
->Tcp6ChildHandle
,
813 &gEfiTcp6ProtocolGuid
,
814 HttpInstance
->Service
->Ip6DriverBindingHandle
,
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
->TlsSb
!= NULL
&& HttpInstance
->TlsChildHandle
!= NULL
) {
869 // Destroy the TLS instance.
871 HttpInstance
->TlsSb
->DestroyChild (HttpInstance
->TlsSb
, HttpInstance
->TlsChildHandle
);
874 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
876 HttpInstance
->Tcp4ChildHandle
,
877 &gEfiTcp4ProtocolGuid
,
878 HttpInstance
->Service
->Ip4DriverBindingHandle
,
879 HttpInstance
->Service
->ControllerHandle
883 HttpInstance
->Tcp4ChildHandle
,
884 &gEfiTcp4ProtocolGuid
,
885 HttpInstance
->Service
->Ip4DriverBindingHandle
,
889 NetLibDestroyServiceChild (
890 HttpInstance
->Service
->ControllerHandle
,
891 HttpInstance
->Service
->Ip4DriverBindingHandle
,
892 &gEfiTcp4ServiceBindingProtocolGuid
,
893 HttpInstance
->Tcp4ChildHandle
897 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
899 HttpInstance
->Service
->Tcp4ChildHandle
,
900 &gEfiTcp4ProtocolGuid
,
901 HttpInstance
->Service
->Ip4DriverBindingHandle
,
906 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
908 HttpInstance
->Tcp6ChildHandle
,
909 &gEfiTcp6ProtocolGuid
,
910 HttpInstance
->Service
->Ip6DriverBindingHandle
,
911 HttpInstance
->Service
->ControllerHandle
915 HttpInstance
->Tcp6ChildHandle
,
916 &gEfiTcp6ProtocolGuid
,
917 HttpInstance
->Service
->Ip6DriverBindingHandle
,
921 NetLibDestroyServiceChild (
922 HttpInstance
->Service
->ControllerHandle
,
923 HttpInstance
->Service
->Ip6DriverBindingHandle
,
924 &gEfiTcp6ServiceBindingProtocolGuid
,
925 HttpInstance
->Tcp6ChildHandle
929 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
931 HttpInstance
->Service
->Tcp6ChildHandle
,
932 &gEfiTcp6ProtocolGuid
,
933 HttpInstance
->Service
->Ip6DriverBindingHandle
,
938 TlsCloseTxRxEvent (HttpInstance
);
942 Establish TCP connection with HTTP server.
944 @param[in] HttpInstance The HTTP instance private data.
946 @retval EFI_SUCCESS The TCP connection is established.
947 @retval Others Other error as indicated.
951 HttpCreateConnection (
952 IN HTTP_PROTOCOL
*HttpInstance
958 // Connect to Http server
960 if (!HttpInstance
->LocalAddressIsIPv6
) {
961 HttpInstance
->IsTcp4ConnDone
= FALSE
;
962 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
963 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4ConnToken
);
964 if (EFI_ERROR (Status
)) {
965 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
969 while (!HttpInstance
->IsTcp4ConnDone
) {
970 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
973 Status
= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
;
976 HttpInstance
->IsTcp6ConnDone
= FALSE
;
977 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
978 Status
= HttpInstance
->Tcp6
->Connect (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6ConnToken
);
979 if (EFI_ERROR (Status
)) {
980 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status
));
984 while(!HttpInstance
->IsTcp6ConnDone
) {
985 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
988 Status
= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
;
991 if (!EFI_ERROR (Status
)) {
992 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
999 Close existing TCP connection.
1001 @param[in] HttpInstance The HTTP instance private data.
1003 @retval EFI_SUCCESS The TCP connection is closed.
1004 @retval Others Other error as indicated.
1008 HttpCloseConnection (
1009 IN HTTP_PROTOCOL
*HttpInstance
1014 if (HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) {
1016 if (HttpInstance
->LocalAddressIsIPv6
) {
1017 HttpInstance
->Tcp6CloseToken
.AbortOnClose
= TRUE
;
1018 HttpInstance
->IsTcp6CloseDone
= FALSE
;
1019 Status
= HttpInstance
->Tcp6
->Close (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6CloseToken
);
1020 if (EFI_ERROR (Status
)) {
1024 while (!HttpInstance
->IsTcp6CloseDone
) {
1025 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
1029 HttpInstance
->Tcp4CloseToken
.AbortOnClose
= TRUE
;
1030 HttpInstance
->IsTcp4CloseDone
= FALSE
;
1031 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4CloseToken
);
1032 if (EFI_ERROR (Status
)) {
1036 while (!HttpInstance
->IsTcp4CloseDone
) {
1037 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
1043 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
1048 Configure TCP4 protocol child.
1050 @param[in] HttpInstance The HTTP instance private data.
1051 @param[in] Wrap The HTTP token's wrap data.
1053 @retval EFI_SUCCESS The TCP4 protocol child is configured.
1054 @retval Others Other error as indicated.
1059 IN HTTP_PROTOCOL
*HttpInstance
,
1060 IN HTTP_TOKEN_WRAP
*Wrap
1064 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
1065 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
1066 EFI_TCP4_OPTION
*Tcp4Option
;
1068 ASSERT (HttpInstance
!= NULL
);
1071 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
1072 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
1074 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
1075 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
1076 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
1078 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
1079 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
1080 if (!Tcp4AP
->UseDefaultAddress
) {
1081 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
1082 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
1085 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
1086 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
1087 Tcp4AP
->ActiveFlag
= TRUE
;
1088 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
1090 Tcp4Option
= Tcp4CfgData
->ControlOption
;
1091 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1092 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1093 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1094 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1095 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
1096 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1097 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1098 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1099 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1100 Tcp4Option
->EnableNagle
= TRUE
;
1101 Tcp4CfgData
->ControlOption
= Tcp4Option
;
1103 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
1104 if (EFI_ERROR (Status
)) {
1105 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
1109 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1110 if (EFI_ERROR (Status
)) {
1114 Status
= HttpCreateTcpTxEvent (Wrap
);
1115 if (EFI_ERROR (Status
)) {
1119 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1125 Configure TCP6 protocol child.
1127 @param[in] HttpInstance The HTTP instance private data.
1128 @param[in] Wrap The HTTP token's wrap data.
1130 @retval EFI_SUCCESS The TCP6 protocol child is configured.
1131 @retval Others Other error as indicated.
1136 IN HTTP_PROTOCOL
*HttpInstance
,
1137 IN HTTP_TOKEN_WRAP
*Wrap
1141 EFI_TCP6_CONFIG_DATA
*Tcp6CfgData
;
1142 EFI_TCP6_ACCESS_POINT
*Tcp6Ap
;
1143 EFI_TCP6_OPTION
*Tcp6Option
;
1145 ASSERT (HttpInstance
!= NULL
);
1147 Tcp6CfgData
= &HttpInstance
->Tcp6CfgData
;
1148 ZeroMem (Tcp6CfgData
, sizeof (EFI_TCP6_CONFIG_DATA
));
1150 Tcp6CfgData
->TrafficClass
= 0;
1151 Tcp6CfgData
->HopLimit
= 255;
1152 Tcp6CfgData
->ControlOption
= &HttpInstance
->Tcp6Option
;
1154 Tcp6Ap
= &Tcp6CfgData
->AccessPoint
;
1155 Tcp6Ap
->ActiveFlag
= TRUE
;
1156 Tcp6Ap
->StationPort
= HttpInstance
->Ipv6Node
.LocalPort
;
1157 Tcp6Ap
->RemotePort
= HttpInstance
->RemotePort
;
1158 IP6_COPY_ADDRESS (&Tcp6Ap
->StationAddress
, &HttpInstance
->Ipv6Node
.LocalAddress
);
1159 IP6_COPY_ADDRESS (&Tcp6Ap
->RemoteAddress
, &HttpInstance
->RemoteIpv6Addr
);
1161 Tcp6Option
= Tcp6CfgData
->ControlOption
;
1162 Tcp6Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1163 Tcp6Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1164 Tcp6Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1165 Tcp6Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1166 Tcp6Option
->DataRetries
= HTTP_DATA_RETRIES
;
1167 Tcp6Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1168 Tcp6Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1169 Tcp6Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1170 Tcp6Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1171 Tcp6Option
->EnableNagle
= TRUE
;
1173 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, Tcp6CfgData
);
1174 if (EFI_ERROR (Status
)) {
1175 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp6 - %r\n", Status
));
1179 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1180 if (EFI_ERROR (Status
)) {
1184 Status
= HttpCreateTcpTxEvent (Wrap
);
1185 if (EFI_ERROR (Status
)) {
1189 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1196 Check existing TCP connection, if in error state, recover TCP4 connection. Then,
1197 connect one TLS session if required.
1199 @param[in] HttpInstance The HTTP instance private data.
1201 @retval EFI_SUCCESS The TCP connection is established.
1202 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1203 @retval Others Other error as indicated.
1208 IN HTTP_PROTOCOL
*HttpInstance
1212 EFI_TCP4_CONNECTION_STATE Tcp4State
;
1215 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp4
== NULL
) {
1216 return EFI_NOT_READY
;
1219 Status
= HttpInstance
->Tcp4
->GetModeData(
1227 if (EFI_ERROR(Status
)){
1228 DEBUG ((EFI_D_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
1232 if (Tcp4State
== Tcp4StateEstablished
) {
1234 } else if (Tcp4State
> Tcp4StateEstablished
) {
1235 HttpCloseConnection(HttpInstance
);
1238 Status
= HttpCreateConnection (HttpInstance
);
1239 if (EFI_ERROR(Status
)){
1240 DEBUG ((EFI_D_ERROR
, "Tcp4 Connection fail - %x\n", Status
));
1245 // Tls session connection.
1247 if (HttpInstance
->UseHttps
) {
1248 if (HttpInstance
->TimeoutEvent
== NULL
) {
1250 // Create TimeoutEvent for TLS connection.
1252 Status
= gBS
->CreateEvent (
1257 &HttpInstance
->TimeoutEvent
1259 if (EFI_ERROR (Status
)) {
1260 TlsCloseTxRxEvent (HttpInstance
);
1266 // Start the timer, and wait Timeout seconds for connection.
1268 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1269 if (EFI_ERROR (Status
)) {
1270 TlsCloseTxRxEvent (HttpInstance
);
1274 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1276 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1278 if (EFI_ERROR (Status
)) {
1279 TlsCloseTxRxEvent (HttpInstance
);
1288 Check existing TCP connection, if in error state, recover TCP6 connection. Then,
1289 connect one TLS session if required.
1291 @param[in] HttpInstance The HTTP instance private data.
1293 @retval EFI_SUCCESS The TCP connection is established.
1294 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1295 @retval Others Other error as indicated.
1300 IN HTTP_PROTOCOL
*HttpInstance
1304 EFI_TCP6_CONNECTION_STATE Tcp6State
;
1306 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp6
== NULL
) {
1307 return EFI_NOT_READY
;
1310 Status
= HttpInstance
->Tcp6
->GetModeData (
1319 if (EFI_ERROR(Status
)){
1320 DEBUG ((EFI_D_ERROR
, "Tcp6 GetModeData fail - %x\n", Status
));
1324 if (Tcp6State
== Tcp6StateEstablished
) {
1326 } else if (Tcp6State
> Tcp6StateEstablished
) {
1327 HttpCloseConnection(HttpInstance
);
1330 Status
= HttpCreateConnection (HttpInstance
);
1331 if (EFI_ERROR(Status
)){
1332 DEBUG ((EFI_D_ERROR
, "Tcp6 Connection fail - %x\n", Status
));
1337 // Tls session connection.
1339 if (HttpInstance
->UseHttps
) {
1340 if (HttpInstance
->TimeoutEvent
== NULL
) {
1342 // Create TimeoutEvent for TLS connection.
1344 Status
= gBS
->CreateEvent (
1349 &HttpInstance
->TimeoutEvent
1351 if (EFI_ERROR (Status
)) {
1352 TlsCloseTxRxEvent (HttpInstance
);
1358 // Start the timer, and wait Timeout seconds for connection.
1360 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1361 if (EFI_ERROR (Status
)) {
1362 TlsCloseTxRxEvent (HttpInstance
);
1366 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1368 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1370 if (EFI_ERROR (Status
)) {
1371 TlsCloseTxRxEvent (HttpInstance
);
1380 Initialize Http session.
1382 @param[in] HttpInstance The HTTP instance private data.
1383 @param[in] Wrap The HTTP token's wrap data.
1384 @param[in] Configure The Flag indicates whether need to initialize session.
1385 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session.
1387 @retval EFI_SUCCESS The initialization of session is done.
1388 @retval Others Other error as indicated.
1393 IN HTTP_PROTOCOL
*HttpInstance
,
1394 IN HTTP_TOKEN_WRAP
*Wrap
,
1395 IN BOOLEAN Configure
,
1396 IN BOOLEAN TlsConfigure
1400 ASSERT (HttpInstance
!= NULL
);
1403 // Configure Tls session.
1406 Status
= TlsConfigureSession (HttpInstance
);
1407 if (EFI_ERROR (Status
)) {
1412 if (!HttpInstance
->LocalAddressIsIPv6
) {
1414 // Configure TCP instance.
1417 Status
= HttpConfigureTcp4 (HttpInstance
, Wrap
);
1418 if (EFI_ERROR (Status
)) {
1426 Status
= HttpConnectTcp4 (HttpInstance
);
1427 if (EFI_ERROR (Status
)) {
1432 // Configure TCP instance.
1435 Status
= HttpConfigureTcp6 (HttpInstance
, Wrap
);
1436 if (EFI_ERROR (Status
)) {
1444 Status
= HttpConnectTcp6 (HttpInstance
);
1445 if (EFI_ERROR (Status
)) {
1455 Send the HTTP or HTTPS message through TCP4 or TCP6.
1457 @param[in] HttpInstance The HTTP instance private data.
1458 @param[in] Wrap The HTTP token's wrap data.
1459 @param[in] TxString Buffer containing the HTTP message string.
1460 @param[in] TxStringLen Length of the HTTP message string in bytes.
1462 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1463 @retval Others Other error as indicated.
1468 IN HTTP_PROTOCOL
*HttpInstance
,
1469 IN HTTP_TOKEN_WRAP
*Wrap
,
1471 IN UINTN TxStringLen
1475 EFI_TCP4_IO_TOKEN
*Tx4Token
;
1476 EFI_TCP4_PROTOCOL
*Tcp4
;
1477 EFI_TCP6_IO_TOKEN
*Tx6Token
;
1478 EFI_TCP6_PROTOCOL
*Tcp6
;
1481 NET_FRAGMENT TempFragment
;
1483 Status
= EFI_SUCCESS
;
1485 TempFragment
.Len
= 0;
1486 TempFragment
.Bulk
= NULL
;
1489 // Need to encrypt data.
1491 if (HttpInstance
->UseHttps
) {
1493 // Build BufferOut data
1495 BufferSize
= sizeof (TLS_RECORD_HEADER
) + TxStringLen
;
1496 Buffer
= AllocateZeroPool (BufferSize
);
1497 if (Buffer
== NULL
) {
1498 Status
= EFI_OUT_OF_RESOURCES
;
1501 ((TLS_RECORD_HEADER
*) Buffer
)->ContentType
= TlsContentTypeApplicationData
;
1502 ((TLS_RECORD_HEADER
*) Buffer
)->Version
.Major
= HttpInstance
->TlsConfigData
.Version
.Major
;
1503 ((TLS_RECORD_HEADER
*) Buffer
)->Version
.Minor
= HttpInstance
->TlsConfigData
.Version
.Minor
;
1504 ((TLS_RECORD_HEADER
*) Buffer
)->Length
= (UINT16
) (TxStringLen
);
1505 CopyMem (Buffer
+ sizeof (TLS_RECORD_HEADER
), TxString
, TxStringLen
);
1510 Status
= TlsProcessMessage (
1520 if (EFI_ERROR (Status
)) {
1525 if (!HttpInstance
->LocalAddressIsIPv6
) {
1526 Tcp4
= HttpInstance
->Tcp4
;
1527 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1529 if (HttpInstance
->UseHttps
) {
1530 Tx4Token
->Packet
.TxData
->DataLength
= TempFragment
.Len
;
1531 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= TempFragment
.Len
;
1532 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TempFragment
.Bulk
;
1534 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1535 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1536 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1539 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1541 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1542 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1543 if (EFI_ERROR (Status
)) {
1544 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1549 Tcp6
= HttpInstance
->Tcp6
;
1550 Tx6Token
= &Wrap
->TcpWrap
.Tx6Token
;
1552 if (HttpInstance
->UseHttps
) {
1553 Tx6Token
->Packet
.TxData
->DataLength
= TempFragment
.Len
;
1554 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= TempFragment
.Len
;
1555 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TempFragment
.Bulk
;
1557 Tx6Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1558 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1559 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1562 Tx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1564 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1565 Status
= Tcp6
->Transmit (Tcp6
, Tx6Token
);
1566 if (EFI_ERROR (Status
)) {
1567 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1576 Check whether the user's token or event has already
1577 been enqueue on HTTP Tx or Rx Token list.
1579 @param[in] Map The container of either user's transmit or receive
1581 @param[in] Item Current item to check against.
1582 @param[in] Context The Token to check againist.
1584 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1585 @retval EFI_SUCCESS The current item isn't the same token/event as the
1593 IN NET_MAP_ITEM
*Item
,
1597 EFI_HTTP_TOKEN
*Token
;
1598 EFI_HTTP_TOKEN
*TokenInItem
;
1600 Token
= (EFI_HTTP_TOKEN
*) Context
;
1601 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
1603 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
1604 return EFI_ACCESS_DENIED
;
1611 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1613 @param[in] Map The container of Tx4Token or Tx6Token.
1614 @param[in] Item Current item to check against.
1615 @param[in] Context The Token to check againist.
1617 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1618 @retval EFI_SUCCESS The HTTP message has been sent out.
1625 IN NET_MAP_ITEM
*Item
,
1629 HTTP_TOKEN_WRAP
*ValueInItem
;
1631 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1633 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
1634 return EFI_NOT_READY
;
1641 Transmit the HTTP or HTTPS mssage by processing the associated HTTP token.
1643 @param[in] Map The container of Tx4Token or Tx6Token.
1644 @param[in] Item Current item to check against.
1645 @param[in] Context The Token to check againist.
1647 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1648 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1656 IN NET_MAP_ITEM
*Item
,
1660 HTTP_TOKEN_WRAP
*ValueInItem
;
1665 UINTN RequestMsgSize
;
1669 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1670 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1675 // Parse the URI of the remote host.
1677 UrlSize
= StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1;
1678 Url
= AllocatePool (UrlSize
);
1680 return EFI_OUT_OF_RESOURCES
;
1683 UnicodeStrToAsciiStrS (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
, UrlSize
);
1686 // Create request message.
1688 Status
= HttpGenRequestMessage (
1689 ValueInItem
->HttpToken
->Message
,
1696 if (EFI_ERROR (Status
) || NULL
== RequestMsg
){
1700 ASSERT (RequestMsg
!= NULL
);
1703 // Transmit the request message.
1705 Status
= HttpTransmitTcp (
1706 ValueInItem
->HttpInstance
,
1708 (UINT8
*) RequestMsg
,
1711 FreePool (RequestMsg
);
1716 Receive the HTTP response by processing the associated HTTP token.
1718 @param[in] Map The container of Rx4Token or Rx6Token.
1719 @param[in] Item Current item to check against.
1720 @param[in] Context The Token to check againist.
1722 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1724 @retval Others Other error as indicated.
1731 IN NET_MAP_ITEM
*Item
,
1736 // Process the queued HTTP response.
1738 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1742 Receive the HTTP header by processing the associated HTTP token.
1744 @param[in] HttpInstance The HTTP instance private data.
1745 @param[in, out] SizeofHeaders The HTTP header length.
1746 @param[in, out] BufferSize The size of buffer to cacahe the header message.
1747 @param[in] Timeout The time to wait for receiving the header packet.
1749 @retval EFI_SUCCESS The HTTP header is received.
1750 @retval Others Other errors as indicated.
1754 HttpTcpReceiveHeader (
1755 IN HTTP_PROTOCOL
*HttpInstance
,
1756 IN OUT UINTN
*SizeofHeaders
,
1757 IN OUT UINTN
*BufferSize
,
1758 IN EFI_EVENT Timeout
1762 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1763 EFI_TCP4_PROTOCOL
*Tcp4
;
1764 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1765 EFI_TCP6_PROTOCOL
*Tcp6
;
1766 CHAR8
**EndofHeader
;
1767 CHAR8
**HttpHeaders
;
1769 NET_FRAGMENT Fragment
;
1771 ASSERT (HttpInstance
!= NULL
);
1773 EndofHeader
= HttpInstance
->EndofHeader
;
1774 HttpHeaders
= HttpInstance
->HttpHeaders
;
1775 Tcp4
= HttpInstance
->Tcp4
;
1776 Tcp6
= HttpInstance
->Tcp6
;
1781 Fragment
.Bulk
= NULL
;
1783 if (HttpInstance
->LocalAddressIsIPv6
) {
1784 ASSERT (Tcp6
!= NULL
);
1786 ASSERT (Tcp4
!= NULL
);
1789 if (!HttpInstance
->UseHttps
) {
1790 Status
= HttpCreateTcpRxEventForHeader (HttpInstance
);
1791 if (EFI_ERROR (Status
)) {
1796 if (!HttpInstance
->LocalAddressIsIPv6
) {
1797 if (!HttpInstance
->UseHttps
) {
1798 Rx4Token
= &HttpInstance
->Rx4Token
;
1799 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1800 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1801 Status
= EFI_OUT_OF_RESOURCES
;
1807 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1809 while (*EndofHeader
== NULL
) {
1810 if (!HttpInstance
->UseHttps
) {
1811 HttpInstance
->IsRxDone
= FALSE
;
1812 Rx4Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1813 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1814 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1815 if (EFI_ERROR (Status
)) {
1816 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1820 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1824 if (!HttpInstance
->IsRxDone
) {
1826 // Cancle the Token before close its Event.
1828 Tcp4
->Cancel (HttpInstance
->Tcp4
, &Rx4Token
->CompletionToken
);
1829 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1830 Rx4Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1833 Status
= Rx4Token
->CompletionToken
.Status
;
1834 if (EFI_ERROR (Status
)) {
1838 Fragment
.Len
= Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1839 Fragment
.Bulk
= (UINT8
*) Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
1841 if (Fragment
.Bulk
!= NULL
) {
1842 FreePool (Fragment
.Bulk
);
1843 Fragment
.Bulk
= NULL
;
1846 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
1847 if (EFI_ERROR (Status
)) {
1848 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1854 // Append the response string.
1856 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
1857 Buffer
= AllocateZeroPool (*BufferSize
);
1858 if (Buffer
== NULL
) {
1859 Status
= EFI_OUT_OF_RESOURCES
;
1863 if (*HttpHeaders
!= NULL
) {
1864 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
1865 FreePool (*HttpHeaders
);
1869 Buffer
+ *SizeofHeaders
,
1873 *HttpHeaders
= Buffer
;
1874 *SizeofHeaders
= *BufferSize
;
1877 // Check whether we received end of HTTP headers.
1879 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1885 if (Rx4Token
!= NULL
&& Rx4Token
->Packet
.RxData
!= NULL
&& Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1886 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1887 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1888 Fragment
.Bulk
= NULL
;
1891 if (Fragment
.Bulk
!= NULL
) {
1892 FreePool (Fragment
.Bulk
);
1893 Fragment
.Bulk
= NULL
;
1896 if (!HttpInstance
->UseHttps
) {
1897 Rx6Token
= &HttpInstance
->Rx6Token
;
1898 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1899 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1900 Status
= EFI_OUT_OF_RESOURCES
;
1906 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1908 while (*EndofHeader
== NULL
) {
1909 if (!HttpInstance
->UseHttps
) {
1910 HttpInstance
->IsRxDone
= FALSE
;
1911 Rx6Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1912 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1913 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1914 if (EFI_ERROR (Status
)) {
1915 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1919 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1923 if (!HttpInstance
->IsRxDone
) {
1925 // Cancle the Token before close its Event.
1927 Tcp6
->Cancel (HttpInstance
->Tcp6
, &Rx6Token
->CompletionToken
);
1928 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1929 Rx6Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1932 Status
= Rx6Token
->CompletionToken
.Status
;
1933 if (EFI_ERROR (Status
)) {
1937 Fragment
.Len
= Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1938 Fragment
.Bulk
= (UINT8
*) Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
1940 if (Fragment
.Bulk
!= NULL
) {
1941 FreePool (Fragment
.Bulk
);
1942 Fragment
.Bulk
= NULL
;
1945 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
1946 if (EFI_ERROR (Status
)) {
1947 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1953 // Append the response string.
1955 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
1956 Buffer
= AllocateZeroPool (*BufferSize
);
1957 if (Buffer
== NULL
) {
1958 Status
= EFI_OUT_OF_RESOURCES
;
1962 if (*HttpHeaders
!= NULL
) {
1963 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
1964 FreePool (*HttpHeaders
);
1968 Buffer
+ *SizeofHeaders
,
1972 *HttpHeaders
= Buffer
;
1973 *SizeofHeaders
= *BufferSize
;
1976 // Check whether we received end of HTTP headers.
1978 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1984 if (Rx6Token
!= NULL
&& Rx6Token
->Packet
.RxData
!= NULL
&& Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1985 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1986 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1987 Fragment
.Bulk
= NULL
;
1990 if (Fragment
.Bulk
!= NULL
) {
1991 FreePool (Fragment
.Bulk
);
1992 Fragment
.Bulk
= NULL
;
1997 // Skip the CRLF after the HTTP headers.
1999 *EndofHeader
= *EndofHeader
+ AsciiStrLen (HTTP_END_OF_HDR_STR
);
2005 Receive the HTTP body by processing the associated HTTP token.
2007 @param[in] Wrap The HTTP token's wrap data.
2008 @param[in] HttpMsg The HTTP message data.
2010 @retval EFI_SUCCESS The HTTP body is received.
2011 @retval Others Other error as indicated.
2015 HttpTcpReceiveBody (
2016 IN HTTP_TOKEN_WRAP
*Wrap
,
2017 IN EFI_HTTP_MESSAGE
*HttpMsg
2021 HTTP_PROTOCOL
*HttpInstance
;
2022 EFI_TCP6_PROTOCOL
*Tcp6
;
2023 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2024 EFI_TCP4_PROTOCOL
*Tcp4
;
2025 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2027 HttpInstance
= Wrap
->HttpInstance
;
2028 Tcp4
= HttpInstance
->Tcp4
;
2029 Tcp6
= HttpInstance
->Tcp6
;
2033 if (HttpInstance
->LocalAddressIsIPv6
) {
2034 ASSERT (Tcp6
!= NULL
);
2036 ASSERT (Tcp4
!= NULL
);
2039 if (HttpInstance
->LocalAddressIsIPv6
) {
2040 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2041 Rx6Token
->Packet
.RxData
->DataLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2042 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2043 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
2044 Rx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2046 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
2047 if (EFI_ERROR (Status
)) {
2048 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
2052 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2053 Rx4Token
->Packet
.RxData
->DataLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2054 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2055 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
2057 Rx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2058 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
2059 if (EFI_ERROR (Status
)) {
2060 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
2070 Clean up Tcp Tokens while the Tcp transmission error occurs.
2072 @param[in] Wrap Pointer to HTTP token's wrap data.
2076 HttpTcpTokenCleanup (
2077 IN HTTP_TOKEN_WRAP
*Wrap
2080 HTTP_PROTOCOL
*HttpInstance
;
2081 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2082 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2084 ASSERT (Wrap
!= NULL
);
2085 HttpInstance
= Wrap
->HttpInstance
;
2089 if (HttpInstance
->LocalAddressIsIPv6
) {
2090 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2092 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2093 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2094 Rx6Token
->CompletionToken
.Event
= NULL
;
2099 Rx6Token
= &HttpInstance
->Rx6Token
;
2101 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2102 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2103 Rx6Token
->CompletionToken
.Event
= NULL
;
2106 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2107 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2108 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2112 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2114 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2115 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2116 Rx4Token
->CompletionToken
.Event
= NULL
;
2121 Rx4Token
= &HttpInstance
->Rx4Token
;
2123 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2124 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2125 Rx4Token
->CompletionToken
.Event
= NULL
;
2129 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2130 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2131 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;