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
->Tcp4ChildHandle
!= NULL
) {
869 HttpInstance
->Tcp4ChildHandle
,
870 &gEfiTcp4ProtocolGuid
,
871 HttpInstance
->Service
->Ip4DriverBindingHandle
,
872 HttpInstance
->Service
->ControllerHandle
876 HttpInstance
->Tcp4ChildHandle
,
877 &gEfiTcp4ProtocolGuid
,
878 HttpInstance
->Service
->Ip4DriverBindingHandle
,
882 NetLibDestroyServiceChild (
883 HttpInstance
->Service
->ControllerHandle
,
884 HttpInstance
->Service
->Ip4DriverBindingHandle
,
885 &gEfiTcp4ServiceBindingProtocolGuid
,
886 HttpInstance
->Tcp4ChildHandle
890 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
892 HttpInstance
->Service
->Tcp4ChildHandle
,
893 &gEfiTcp4ProtocolGuid
,
894 HttpInstance
->Service
->Ip4DriverBindingHandle
,
899 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
901 HttpInstance
->Tcp6ChildHandle
,
902 &gEfiTcp6ProtocolGuid
,
903 HttpInstance
->Service
->Ip6DriverBindingHandle
,
904 HttpInstance
->Service
->ControllerHandle
908 HttpInstance
->Tcp6ChildHandle
,
909 &gEfiTcp6ProtocolGuid
,
910 HttpInstance
->Service
->Ip6DriverBindingHandle
,
914 NetLibDestroyServiceChild (
915 HttpInstance
->Service
->ControllerHandle
,
916 HttpInstance
->Service
->Ip6DriverBindingHandle
,
917 &gEfiTcp6ServiceBindingProtocolGuid
,
918 HttpInstance
->Tcp6ChildHandle
922 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
924 HttpInstance
->Service
->Tcp6ChildHandle
,
925 &gEfiTcp6ProtocolGuid
,
926 HttpInstance
->Service
->Ip6DriverBindingHandle
,
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
;
1478 TempFragment
.Len
= 0;
1479 TempFragment
.Bulk
= NULL
;
1482 // Need to encrypt data.
1484 if (HttpInstance
->UseHttps
) {
1486 // Build BufferOut data
1488 BufferSize
= sizeof (TLS_RECORD_HEADER
) + TxStringLen
;
1489 Buffer
= AllocateZeroPool (BufferSize
);
1490 if (Buffer
== NULL
) {
1491 Status
= EFI_OUT_OF_RESOURCES
;
1494 ((TLS_RECORD_HEADER
*) Buffer
)->ContentType
= TlsContentTypeApplicationData
;
1495 ((TLS_RECORD_HEADER
*) Buffer
)->Version
.Major
= HttpInstance
->TlsConfigData
.Version
.Major
;
1496 ((TLS_RECORD_HEADER
*) Buffer
)->Version
.Minor
= HttpInstance
->TlsConfigData
.Version
.Minor
;
1497 ((TLS_RECORD_HEADER
*) Buffer
)->Length
= (UINT16
) (TxStringLen
);
1498 CopyMem (Buffer
+ sizeof (TLS_RECORD_HEADER
), TxString
, TxStringLen
);
1503 Status
= TlsProcessMessage (
1513 if (EFI_ERROR (Status
)) {
1518 if (!HttpInstance
->LocalAddressIsIPv6
) {
1519 Tcp4
= HttpInstance
->Tcp4
;
1520 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1522 if (HttpInstance
->UseHttps
) {
1523 Tx4Token
->Packet
.TxData
->DataLength
= TempFragment
.Len
;
1524 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= TempFragment
.Len
;
1525 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TempFragment
.Bulk
;
1527 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1528 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1529 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1532 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1534 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1535 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1536 if (EFI_ERROR (Status
)) {
1537 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1542 Tcp6
= HttpInstance
->Tcp6
;
1543 Tx6Token
= &Wrap
->TcpWrap
.Tx6Token
;
1545 if (HttpInstance
->UseHttps
) {
1546 Tx6Token
->Packet
.TxData
->DataLength
= TempFragment
.Len
;
1547 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= TempFragment
.Len
;
1548 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TempFragment
.Bulk
;
1550 Tx6Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1551 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1552 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1555 Tx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1557 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1558 Status
= Tcp6
->Transmit (Tcp6
, Tx6Token
);
1559 if (EFI_ERROR (Status
)) {
1560 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1569 Check whether the user's token or event has already
1570 been enqueue on HTTP Tx or Rx Token list.
1572 @param[in] Map The container of either user's transmit or receive
1574 @param[in] Item Current item to check against.
1575 @param[in] Context The Token to check againist.
1577 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1578 @retval EFI_SUCCESS The current item isn't the same token/event as the
1586 IN NET_MAP_ITEM
*Item
,
1590 EFI_HTTP_TOKEN
*Token
;
1591 EFI_HTTP_TOKEN
*TokenInItem
;
1593 Token
= (EFI_HTTP_TOKEN
*) Context
;
1594 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
1596 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
1597 return EFI_ACCESS_DENIED
;
1604 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1606 @param[in] Map The container of Tx4Token or Tx6Token.
1607 @param[in] Item Current item to check against.
1608 @param[in] Context The Token to check againist.
1610 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1611 @retval EFI_SUCCESS The HTTP message has been sent out.
1618 IN NET_MAP_ITEM
*Item
,
1622 HTTP_TOKEN_WRAP
*ValueInItem
;
1624 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1626 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
1627 return EFI_NOT_READY
;
1634 Transmit the HTTP or HTTPS mssage by processing the associated HTTP token.
1636 @param[in] Map The container of Tx4Token or Tx6Token.
1637 @param[in] Item Current item to check against.
1638 @param[in] Context The Token to check againist.
1640 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1641 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1649 IN NET_MAP_ITEM
*Item
,
1653 HTTP_TOKEN_WRAP
*ValueInItem
;
1658 UINTN RequestMsgSize
;
1662 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1663 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1668 // Parse the URI of the remote host.
1670 UrlSize
= StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1;
1671 Url
= AllocatePool (UrlSize
);
1673 return EFI_OUT_OF_RESOURCES
;
1676 UnicodeStrToAsciiStrS (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
, UrlSize
);
1679 // Create request message.
1681 Status
= HttpGenRequestMessage (
1682 ValueInItem
->HttpToken
->Message
,
1689 if (EFI_ERROR (Status
) || NULL
== RequestMsg
){
1693 ASSERT (RequestMsg
!= NULL
);
1696 // Transmit the request message.
1698 Status
= HttpTransmitTcp (
1699 ValueInItem
->HttpInstance
,
1701 (UINT8
*) RequestMsg
,
1704 FreePool (RequestMsg
);
1709 Receive the HTTP response by processing the associated HTTP token.
1711 @param[in] Map The container of Rx4Token or Rx6Token.
1712 @param[in] Item Current item to check against.
1713 @param[in] Context The Token to check againist.
1715 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1717 @retval Others Other error as indicated.
1724 IN NET_MAP_ITEM
*Item
,
1729 // Process the queued HTTP response.
1731 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1735 Receive the HTTP header by processing the associated HTTP token.
1737 @param[in] HttpInstance The HTTP instance private data.
1738 @param[in, out] SizeofHeaders The HTTP header length.
1739 @param[in, out] BufferSize The size of buffer to cacahe the header message.
1740 @param[in] Timeout The time to wait for receiving the header packet.
1742 @retval EFI_SUCCESS The HTTP header is received.
1743 @retval Others Other errors as indicated.
1747 HttpTcpReceiveHeader (
1748 IN HTTP_PROTOCOL
*HttpInstance
,
1749 IN OUT UINTN
*SizeofHeaders
,
1750 IN OUT UINTN
*BufferSize
,
1751 IN EFI_EVENT Timeout
1755 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1756 EFI_TCP4_PROTOCOL
*Tcp4
;
1757 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1758 EFI_TCP6_PROTOCOL
*Tcp6
;
1759 CHAR8
**EndofHeader
;
1760 CHAR8
**HttpHeaders
;
1762 NET_FRAGMENT Fragment
;
1764 ASSERT (HttpInstance
!= NULL
);
1766 EndofHeader
= HttpInstance
->EndofHeader
;
1767 HttpHeaders
= HttpInstance
->HttpHeaders
;
1768 Tcp4
= HttpInstance
->Tcp4
;
1769 Tcp6
= HttpInstance
->Tcp6
;
1774 Fragment
.Bulk
= NULL
;
1776 if (HttpInstance
->LocalAddressIsIPv6
) {
1777 ASSERT (Tcp6
!= NULL
);
1779 ASSERT (Tcp4
!= NULL
);
1782 if (!HttpInstance
->UseHttps
) {
1783 Status
= HttpCreateTcpRxEventForHeader (HttpInstance
);
1784 if (EFI_ERROR (Status
)) {
1789 if (!HttpInstance
->LocalAddressIsIPv6
) {
1790 if (!HttpInstance
->UseHttps
) {
1791 Rx4Token
= &HttpInstance
->Rx4Token
;
1792 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1793 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1794 Status
= EFI_OUT_OF_RESOURCES
;
1800 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1802 while (*EndofHeader
== NULL
) {
1803 if (!HttpInstance
->UseHttps
) {
1804 HttpInstance
->IsRxDone
= FALSE
;
1805 Rx4Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1806 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1807 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1808 if (EFI_ERROR (Status
)) {
1809 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1813 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1817 if (!HttpInstance
->IsRxDone
) {
1819 // Cancle the Token before close its Event.
1821 Tcp4
->Cancel (HttpInstance
->Tcp4
, &Rx4Token
->CompletionToken
);
1822 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1823 Rx4Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1826 Status
= Rx4Token
->CompletionToken
.Status
;
1827 if (EFI_ERROR (Status
)) {
1831 Fragment
.Len
= Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1832 Fragment
.Bulk
= (UINT8
*) Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
1834 if (Fragment
.Bulk
!= NULL
) {
1835 FreePool (Fragment
.Bulk
);
1836 Fragment
.Bulk
= NULL
;
1839 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
1840 if (EFI_ERROR (Status
)) {
1841 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1847 // Append the response string.
1849 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
1850 Buffer
= AllocateZeroPool (*BufferSize
);
1851 if (Buffer
== NULL
) {
1852 Status
= EFI_OUT_OF_RESOURCES
;
1856 if (*HttpHeaders
!= NULL
) {
1857 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
1858 FreePool (*HttpHeaders
);
1862 Buffer
+ *SizeofHeaders
,
1866 *HttpHeaders
= Buffer
;
1867 *SizeofHeaders
= *BufferSize
;
1870 // Check whether we received end of HTTP headers.
1872 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1878 if (Rx4Token
!= NULL
&& Rx4Token
->Packet
.RxData
!= NULL
&& Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1879 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1880 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1881 Fragment
.Bulk
= NULL
;
1884 if (Fragment
.Bulk
!= NULL
) {
1885 FreePool (Fragment
.Bulk
);
1886 Fragment
.Bulk
= NULL
;
1889 if (!HttpInstance
->UseHttps
) {
1890 Rx6Token
= &HttpInstance
->Rx6Token
;
1891 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1892 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1893 Status
= EFI_OUT_OF_RESOURCES
;
1899 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1901 while (*EndofHeader
== NULL
) {
1902 if (!HttpInstance
->UseHttps
) {
1903 HttpInstance
->IsRxDone
= FALSE
;
1904 Rx6Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1905 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1906 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1907 if (EFI_ERROR (Status
)) {
1908 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1912 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1916 if (!HttpInstance
->IsRxDone
) {
1918 // Cancle the Token before close its Event.
1920 Tcp6
->Cancel (HttpInstance
->Tcp6
, &Rx6Token
->CompletionToken
);
1921 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1922 Rx6Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1925 Status
= Rx6Token
->CompletionToken
.Status
;
1926 if (EFI_ERROR (Status
)) {
1930 Fragment
.Len
= Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1931 Fragment
.Bulk
= (UINT8
*) Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
1933 if (Fragment
.Bulk
!= NULL
) {
1934 FreePool (Fragment
.Bulk
);
1935 Fragment
.Bulk
= NULL
;
1938 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
1939 if (EFI_ERROR (Status
)) {
1940 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1946 // Append the response string.
1948 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
1949 Buffer
= AllocateZeroPool (*BufferSize
);
1950 if (Buffer
== NULL
) {
1951 Status
= EFI_OUT_OF_RESOURCES
;
1955 if (*HttpHeaders
!= NULL
) {
1956 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
1957 FreePool (*HttpHeaders
);
1961 Buffer
+ *SizeofHeaders
,
1965 *HttpHeaders
= Buffer
;
1966 *SizeofHeaders
= *BufferSize
;
1969 // Check whether we received end of HTTP headers.
1971 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1977 if (Rx6Token
!= NULL
&& Rx6Token
->Packet
.RxData
!= NULL
&& Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1978 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1979 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1980 Fragment
.Bulk
= NULL
;
1983 if (Fragment
.Bulk
!= NULL
) {
1984 FreePool (Fragment
.Bulk
);
1985 Fragment
.Bulk
= NULL
;
1990 // Skip the CRLF after the HTTP headers.
1992 *EndofHeader
= *EndofHeader
+ AsciiStrLen (HTTP_END_OF_HDR_STR
);
1998 Receive the HTTP body by processing the associated HTTP token.
2000 @param[in] Wrap The HTTP token's wrap data.
2001 @param[in] HttpMsg The HTTP message data.
2003 @retval EFI_SUCCESS The HTTP body is received.
2004 @retval Others Other error as indicated.
2008 HttpTcpReceiveBody (
2009 IN HTTP_TOKEN_WRAP
*Wrap
,
2010 IN EFI_HTTP_MESSAGE
*HttpMsg
2014 HTTP_PROTOCOL
*HttpInstance
;
2015 EFI_TCP6_PROTOCOL
*Tcp6
;
2016 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2017 EFI_TCP4_PROTOCOL
*Tcp4
;
2018 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2020 HttpInstance
= Wrap
->HttpInstance
;
2021 Tcp4
= HttpInstance
->Tcp4
;
2022 Tcp6
= HttpInstance
->Tcp6
;
2026 if (HttpInstance
->LocalAddressIsIPv6
) {
2027 ASSERT (Tcp6
!= NULL
);
2029 ASSERT (Tcp4
!= NULL
);
2032 if (HttpInstance
->LocalAddressIsIPv6
) {
2033 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2034 Rx6Token
->Packet
.RxData
->DataLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2035 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2036 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
2037 Rx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2039 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
2040 if (EFI_ERROR (Status
)) {
2041 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
2045 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2046 Rx4Token
->Packet
.RxData
->DataLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2047 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2048 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
2050 Rx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2051 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
2052 if (EFI_ERROR (Status
)) {
2053 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
2063 Clean up Tcp Tokens while the Tcp transmission error occurs.
2065 @param[in] Wrap Pointer to HTTP token's wrap data.
2069 HttpTcpTokenCleanup (
2070 IN HTTP_TOKEN_WRAP
*Wrap
2073 HTTP_PROTOCOL
*HttpInstance
;
2074 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2075 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2077 ASSERT (Wrap
!= NULL
);
2078 HttpInstance
= Wrap
->HttpInstance
;
2082 if (HttpInstance
->LocalAddressIsIPv6
) {
2083 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2085 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2086 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2087 Rx6Token
->CompletionToken
.Event
= NULL
;
2092 Rx6Token
= &HttpInstance
->Rx6Token
;
2094 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2095 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2096 Rx6Token
->CompletionToken
.Event
= NULL
;
2099 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2100 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2101 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2105 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2107 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2108 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2109 Rx4Token
->CompletionToken
.Event
= NULL
;
2114 Rx4Token
= &HttpInstance
->Rx4Token
;
2116 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2117 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2118 Rx4Token
->CompletionToken
.Event
= NULL
;
2122 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2123 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2124 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;