2 Miscellaneous routines for HttpDxe driver.
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HttpDriver.h"
19 The common notify function used in HTTP driver.
21 @param[in] Event The event signaled.
22 @param[in] Context The context.
32 if ((Event
== NULL
) || (Context
== NULL
)) {
36 *((BOOLEAN
*) Context
) = TRUE
;
40 The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().
42 @param[in] Context The context.
47 HttpTcpTransmitNotifyDpc (
51 HTTP_TOKEN_WRAP
*Wrap
;
52 HTTP_PROTOCOL
*HttpInstance
;
54 if (Context
== NULL
) {
58 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
59 HttpInstance
= Wrap
->HttpInstance
;
61 if (!HttpInstance
->LocalAddressIsIPv6
) {
62 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Tx4Token
.CompletionToken
.Status
;
63 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
68 if (Wrap
->TcpWrap
.Tx4Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
69 FreePool (Wrap
->TcpWrap
.Tx4Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
);
72 if (Wrap
->TcpWrap
.Tx4Token
.CompletionToken
.Event
!= NULL
) {
73 gBS
->CloseEvent (Wrap
->TcpWrap
.Tx4Token
.CompletionToken
.Event
);
77 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Status
;
78 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
83 if (Wrap
->TcpWrap
.Tx6Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
84 FreePool (Wrap
->TcpWrap
.Tx6Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
);
87 if (Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Event
!= NULL
) {
88 gBS
->CloseEvent (Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Event
);
93 Wrap
->TcpWrap
.IsTxDone
= TRUE
;
96 // Check pending TxTokens and sent out.
98 NetMapIterate (&Wrap
->HttpInstance
->TxTokens
, HttpTcpTransmit
, NULL
);
103 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.
105 @param Event The receive event delivered to TCP for transmit.
106 @param Context Context for the callback.
111 HttpTcpTransmitNotify (
117 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
119 QueueDpc (TPL_CALLBACK
, HttpTcpTransmitNotifyDpc
, Context
);
123 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().
125 @param[in] Context The context.
130 HttpTcpReceiveNotifyDpc (
134 HTTP_TOKEN_WRAP
*Wrap
;
138 HTTP_PROTOCOL
*HttpInstance
;
141 if (Context
== NULL
) {
145 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
146 HttpInstance
= Wrap
->HttpInstance
;
147 UsingIpv6
= HttpInstance
->LocalAddressIsIPv6
;
150 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
152 if (EFI_ERROR (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
)) {
153 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
154 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
160 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
162 if (EFI_ERROR (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
)) {
163 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
164 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
171 // Check whether we receive a complete HTTP message.
173 ASSERT (HttpInstance
->MsgParser
!= NULL
);
175 Length
= (UINTN
) Wrap
->TcpWrap
.Rx6Data
.FragmentTable
[0].FragmentLength
;
177 Length
= (UINTN
) Wrap
->TcpWrap
.Rx4Data
.FragmentTable
[0].FragmentLength
;
180 Status
= HttpParseMessageBody (
181 HttpInstance
->MsgParser
,
183 Wrap
->HttpToken
->Message
->Body
185 if (EFI_ERROR (Status
)) {
189 if (HttpIsMessageComplete (HttpInstance
->MsgParser
)) {
191 // Free the MsgParse since we already have a full HTTP message.
193 HttpFreeMsgParser (HttpInstance
->MsgParser
);
194 HttpInstance
->MsgParser
= NULL
;
197 Wrap
->HttpToken
->Message
->BodyLength
= Length
;
198 ASSERT (HttpInstance
->CacheBody
== NULL
);
200 // We receive part of header of next HTTP msg.
202 if (HttpInstance
->NextMsg
!= NULL
) {
203 Wrap
->HttpToken
->Message
->BodyLength
= HttpInstance
->NextMsg
-
204 (CHAR8
*) Wrap
->HttpToken
->Message
->Body
;
205 HttpInstance
->CacheLen
= Length
- Wrap
->HttpToken
->Message
->BodyLength
;
206 if (HttpInstance
->CacheLen
!= 0) {
207 HttpInstance
->CacheBody
= AllocateZeroPool (HttpInstance
->CacheLen
);
208 if (HttpInstance
->CacheBody
== NULL
) {
211 CopyMem (HttpInstance
->CacheBody
, HttpInstance
->NextMsg
, HttpInstance
->CacheLen
);
212 HttpInstance
->NextMsg
= HttpInstance
->CacheBody
;
213 HttpInstance
->CacheOffset
= 0;
217 Item
= NetMapFindKey (&Wrap
->HttpInstance
->RxTokens
, Wrap
->HttpToken
);
219 NetMapRemoveItem (&Wrap
->HttpInstance
->RxTokens
, Item
, NULL
);
223 Wrap
->TcpWrap
.IsRxDone
= TRUE
;
225 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
227 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
231 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
234 // Check pending RxTokens and receive the HTTP message.
236 NetMapIterate (&Wrap
->HttpInstance
->RxTokens
, HttpTcpReceive
, NULL
);
242 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.
244 @param Event The receive event delivered to TCP for receive.
245 @param Context Context for the callback.
250 HttpTcpReceiveNotify (
256 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
258 QueueDpc (TPL_CALLBACK
, HttpTcpReceiveNotifyDpc
, Context
);
262 Create events for the TCP connection token and TCP close token.
264 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
266 @retval EFI_SUCCESS The events are created successfully.
267 @retval others Other error as indicated.
271 HttpCreateTcpConnCloseEvent (
272 IN HTTP_PROTOCOL
*HttpInstance
277 if (!HttpInstance
->LocalAddressIsIPv6
) {
279 // Create events for variuos asynchronous operations.
281 Status
= gBS
->CreateEvent (
285 &HttpInstance
->IsTcp4ConnDone
,
286 &HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
288 if (EFI_ERROR (Status
)) {
293 // Initialize Tcp4CloseToken
295 Status
= gBS
->CreateEvent (
299 &HttpInstance
->IsTcp4CloseDone
,
300 &HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
302 if (EFI_ERROR (Status
)) {
308 // Create events for variuos asynchronous operations.
310 Status
= gBS
->CreateEvent (
314 &HttpInstance
->IsTcp6ConnDone
,
315 &HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
317 if (EFI_ERROR (Status
)) {
322 // Initialize Tcp6CloseToken
324 Status
= gBS
->CreateEvent (
328 &HttpInstance
->IsTcp6CloseDone
,
329 &HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
331 if (EFI_ERROR (Status
)) {
342 HttpCloseTcpConnCloseEvent (HttpInstance
);
349 Close events in the TCP connection token and TCP close token.
351 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
355 HttpCloseTcpConnCloseEvent (
356 IN HTTP_PROTOCOL
*HttpInstance
359 ASSERT (HttpInstance
!= NULL
);
361 if (HttpInstance
->LocalAddressIsIPv6
) {
362 if (NULL
!= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
) {
363 gBS
->CloseEvent (HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
);
364 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
= NULL
;
367 if (NULL
!= HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
) {
368 gBS
->CloseEvent(HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
);
369 HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
= NULL
;
373 if (NULL
!= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
) {
374 gBS
->CloseEvent (HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
);
375 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
= NULL
;
378 if (NULL
!= HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
) {
379 gBS
->CloseEvent(HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
);
380 HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
387 Create event for the TCP transmit token.
389 @param[in] Wrap Point to HTTP token's wrap data.
391 @retval EFI_SUCCESS The events is created successfully.
392 @retval others Other error as indicated.
396 HttpCreateTcpTxEvent (
397 IN HTTP_TOKEN_WRAP
*Wrap
401 HTTP_PROTOCOL
*HttpInstance
;
402 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
404 HttpInstance
= Wrap
->HttpInstance
;
405 TcpWrap
= &Wrap
->TcpWrap
;
407 if (!HttpInstance
->LocalAddressIsIPv6
) {
408 Status
= gBS
->CreateEvent (
411 HttpTcpTransmitNotify
,
413 &TcpWrap
->Tx4Token
.CompletionToken
.Event
415 if (EFI_ERROR (Status
)) {
419 TcpWrap
->Tx4Data
.Push
= TRUE
;
420 TcpWrap
->Tx4Data
.Urgent
= FALSE
;
421 TcpWrap
->Tx4Data
.FragmentCount
= 1;
422 TcpWrap
->Tx4Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx4Data
;
423 TcpWrap
->Tx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
426 Status
= gBS
->CreateEvent (
429 HttpTcpTransmitNotify
,
431 &TcpWrap
->Tx6Token
.CompletionToken
.Event
433 if (EFI_ERROR (Status
)) {
437 TcpWrap
->Tx6Data
.Push
= TRUE
;
438 TcpWrap
->Tx6Data
.Urgent
= FALSE
;
439 TcpWrap
->Tx6Data
.FragmentCount
= 1;
440 TcpWrap
->Tx6Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx6Data
;
441 TcpWrap
->Tx6Token
.CompletionToken
.Status
=EFI_NOT_READY
;
450 Create event for the TCP receive token which is used to receive HTTP header.
452 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
454 @retval EFI_SUCCESS The events is created successfully.
455 @retval others Other error as indicated.
459 HttpCreateTcpRxEventForHeader (
460 IN HTTP_PROTOCOL
*HttpInstance
465 if (!HttpInstance
->LocalAddressIsIPv6
) {
466 Status
= gBS
->CreateEvent (
470 &HttpInstance
->IsRxDone
,
471 &HttpInstance
->Rx4Token
.CompletionToken
.Event
473 if (EFI_ERROR (Status
)) {
477 HttpInstance
->Rx4Data
.FragmentCount
= 1;
478 HttpInstance
->Rx4Token
.Packet
.RxData
= &HttpInstance
->Rx4Data
;
479 HttpInstance
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
482 Status
= gBS
->CreateEvent (
486 &HttpInstance
->IsRxDone
,
487 &HttpInstance
->Rx6Token
.CompletionToken
.Event
489 if (EFI_ERROR (Status
)) {
493 HttpInstance
->Rx6Data
.FragmentCount
=1;
494 HttpInstance
->Rx6Token
.Packet
.RxData
= &HttpInstance
->Rx6Data
;
495 HttpInstance
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
504 Create event for the TCP receive token which is used to receive HTTP body.
506 @param[in] Wrap Point to HTTP token's wrap data.
508 @retval EFI_SUCCESS The events is created successfully.
509 @retval others Other error as indicated.
513 HttpCreateTcpRxEvent (
514 IN HTTP_TOKEN_WRAP
*Wrap
518 HTTP_PROTOCOL
*HttpInstance
;
519 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
521 HttpInstance
= Wrap
->HttpInstance
;
522 TcpWrap
= &Wrap
->TcpWrap
;
523 if (!HttpInstance
->LocalAddressIsIPv6
) {
524 Status
= gBS
->CreateEvent (
527 HttpTcpReceiveNotify
,
529 &TcpWrap
->Rx4Token
.CompletionToken
.Event
531 if (EFI_ERROR (Status
)) {
535 TcpWrap
->Rx4Data
.FragmentCount
= 1;
536 TcpWrap
->Rx4Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx4Data
;
537 TcpWrap
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
540 Status
= gBS
->CreateEvent (
543 HttpTcpReceiveNotify
,
545 &TcpWrap
->Rx6Token
.CompletionToken
.Event
547 if (EFI_ERROR (Status
)) {
551 TcpWrap
->Rx6Data
.FragmentCount
= 1;
552 TcpWrap
->Rx6Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx6Data
;
553 TcpWrap
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
560 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.
562 @param[in] Wrap Pointer to HTTP token's wrap data.
566 HttpCloseTcpRxEvent (
567 IN HTTP_TOKEN_WRAP
*Wrap
570 HTTP_PROTOCOL
*HttpInstance
;
571 EFI_TCP4_IO_TOKEN
*Rx4Token
;
572 EFI_TCP6_IO_TOKEN
*Rx6Token
;
574 ASSERT (Wrap
!= NULL
);
575 HttpInstance
= Wrap
->HttpInstance
;
579 if (HttpInstance
->LocalAddressIsIPv6
) {
580 if (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
!= NULL
) {
581 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
584 if (HttpInstance
->Rx6Token
.CompletionToken
.Event
!= NULL
) {
585 gBS
->CloseEvent (HttpInstance
->Rx6Token
.CompletionToken
.Event
);
586 HttpInstance
->Rx6Token
.CompletionToken
.Event
= NULL
;
589 if (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
!= NULL
) {
590 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
593 if (HttpInstance
->Rx4Token
.CompletionToken
.Event
!= NULL
) {
594 gBS
->CloseEvent (HttpInstance
->Rx4Token
.CompletionToken
.Event
);
595 HttpInstance
->Rx4Token
.CompletionToken
.Event
= NULL
;
601 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.
603 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
604 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.
606 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
607 @retval Others Other error as indicated.
612 IN OUT HTTP_PROTOCOL
*HttpInstance
,
620 ASSERT (HttpInstance
!= NULL
);
621 UsingIpv6
= IpVersion
;
625 // Create TCP4 child.
627 Status
= NetLibCreateServiceChild (
628 HttpInstance
->Service
->ControllerHandle
,
629 HttpInstance
->Service
->ImageHandle
,
630 &gEfiTcp4ServiceBindingProtocolGuid
,
631 &HttpInstance
->Tcp4ChildHandle
634 if (EFI_ERROR (Status
)) {
638 Status
= gBS
->OpenProtocol (
639 HttpInstance
->Tcp4ChildHandle
,
640 &gEfiTcp4ProtocolGuid
,
641 (VOID
**) &Interface
,
642 HttpInstance
->Service
->ImageHandle
,
643 HttpInstance
->Service
->ControllerHandle
,
644 EFI_OPEN_PROTOCOL_BY_DRIVER
647 if (EFI_ERROR (Status
)) {
651 Status
= gBS
->OpenProtocol (
652 HttpInstance
->Tcp4ChildHandle
,
653 &gEfiTcp4ProtocolGuid
,
654 (VOID
**) &HttpInstance
->Tcp4
,
655 HttpInstance
->Service
->ImageHandle
,
656 HttpInstance
->Handle
,
657 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
659 if (EFI_ERROR(Status
)) {
663 Status
= gBS
->OpenProtocol (
664 HttpInstance
->Service
->Tcp4ChildHandle
,
665 &gEfiTcp4ProtocolGuid
,
666 (VOID
**) &Interface
,
667 HttpInstance
->Service
->ImageHandle
,
668 HttpInstance
->Handle
,
669 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
671 if (EFI_ERROR(Status
)) {
676 // Create TCP6 Child.
678 Status
= NetLibCreateServiceChild (
679 HttpInstance
->Service
->ControllerHandle
,
680 HttpInstance
->Service
->ImageHandle
,
681 &gEfiTcp6ServiceBindingProtocolGuid
,
682 &HttpInstance
->Tcp6ChildHandle
685 if (EFI_ERROR (Status
)) {
689 Status
= gBS
->OpenProtocol (
690 HttpInstance
->Tcp6ChildHandle
,
691 &gEfiTcp6ProtocolGuid
,
692 (VOID
**) &Interface
,
693 HttpInstance
->Service
->ImageHandle
,
694 HttpInstance
->Service
->ControllerHandle
,
695 EFI_OPEN_PROTOCOL_BY_DRIVER
698 if (EFI_ERROR (Status
)) {
702 Status
= gBS
->OpenProtocol (
703 HttpInstance
->Tcp6ChildHandle
,
704 &gEfiTcp6ProtocolGuid
,
705 (VOID
**) &HttpInstance
->Tcp6
,
706 HttpInstance
->Service
->ImageHandle
,
707 HttpInstance
->Handle
,
708 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
711 if (EFI_ERROR(Status
)) {
715 Status
= gBS
->OpenProtocol (
716 HttpInstance
->Service
->Tcp6ChildHandle
,
717 &gEfiTcp6ProtocolGuid
,
718 (VOID
**) &Interface
,
719 HttpInstance
->Service
->ImageHandle
,
720 HttpInstance
->Handle
,
721 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
724 if (EFI_ERROR(Status
)) {
729 HttpInstance
->Url
= AllocateZeroPool (HTTP_URL_BUFFER_LEN
);
730 if (HttpInstance
->Url
== NULL
) {
731 Status
= EFI_OUT_OF_RESOURCES
;
739 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
741 HttpInstance
->Tcp4ChildHandle
,
742 &gEfiTcp4ProtocolGuid
,
743 HttpInstance
->Service
->ImageHandle
,
744 HttpInstance
->Service
->ControllerHandle
748 HttpInstance
->Tcp4ChildHandle
,
749 &gEfiTcp4ProtocolGuid
,
750 HttpInstance
->Service
->ImageHandle
,
754 NetLibDestroyServiceChild (
755 HttpInstance
->Service
->ControllerHandle
,
756 HttpInstance
->Service
->ImageHandle
,
757 &gEfiTcp4ServiceBindingProtocolGuid
,
758 HttpInstance
->Tcp4ChildHandle
762 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
764 HttpInstance
->Service
->Tcp4ChildHandle
,
765 &gEfiTcp4ProtocolGuid
,
766 HttpInstance
->Service
->ImageHandle
,
771 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
773 HttpInstance
->Tcp6ChildHandle
,
774 &gEfiTcp6ProtocolGuid
,
775 HttpInstance
->Service
->ImageHandle
,
776 HttpInstance
->Service
->ControllerHandle
780 HttpInstance
->Tcp6ChildHandle
,
781 &gEfiTcp6ProtocolGuid
,
782 HttpInstance
->Service
->ImageHandle
,
786 NetLibDestroyServiceChild (
787 HttpInstance
->Service
->ControllerHandle
,
788 HttpInstance
->Service
->ImageHandle
,
789 &gEfiTcp6ServiceBindingProtocolGuid
,
790 HttpInstance
->Tcp6ChildHandle
794 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
796 HttpInstance
->Service
->Tcp6ChildHandle
,
797 &gEfiTcp6ProtocolGuid
,
798 HttpInstance
->Service
->ImageHandle
,
803 return EFI_UNSUPPORTED
;
808 Clean up the HTTP child, release all the resources used by it.
810 @param[in] HttpInstance The HTTP child to clean up.
815 IN HTTP_PROTOCOL
*HttpInstance
818 HttpCloseConnection (HttpInstance
);
820 HttpCloseTcpConnCloseEvent (HttpInstance
);
822 if (HttpInstance
->CacheBody
!= NULL
) {
823 FreePool (HttpInstance
->CacheBody
);
824 HttpInstance
->CacheBody
= NULL
;
825 HttpInstance
->NextMsg
= NULL
;
828 if (HttpInstance
->RemoteHost
!= NULL
) {
829 FreePool (HttpInstance
->RemoteHost
);
830 HttpInstance
->RemoteHost
= NULL
;
833 if (HttpInstance
->MsgParser
!= NULL
) {
834 HttpFreeMsgParser (HttpInstance
->MsgParser
);
835 HttpInstance
->MsgParser
= NULL
;
838 if (HttpInstance
->Url
!= NULL
) {
839 FreePool (HttpInstance
->Url
);
840 HttpInstance
->Url
= NULL
;
843 NetMapClean (&HttpInstance
->TxTokens
);
844 NetMapClean (&HttpInstance
->RxTokens
);
846 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
848 HttpInstance
->Tcp4ChildHandle
,
849 &gEfiTcp4ProtocolGuid
,
850 HttpInstance
->Service
->ImageHandle
,
851 HttpInstance
->Service
->ControllerHandle
855 HttpInstance
->Tcp4ChildHandle
,
856 &gEfiTcp4ProtocolGuid
,
857 HttpInstance
->Service
->ImageHandle
,
861 NetLibDestroyServiceChild (
862 HttpInstance
->Service
->ControllerHandle
,
863 HttpInstance
->Service
->ImageHandle
,
864 &gEfiTcp4ServiceBindingProtocolGuid
,
865 HttpInstance
->Tcp4ChildHandle
869 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
871 HttpInstance
->Service
->Tcp4ChildHandle
,
872 &gEfiTcp4ProtocolGuid
,
873 HttpInstance
->Service
->ImageHandle
,
878 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
880 HttpInstance
->Tcp6ChildHandle
,
881 &gEfiTcp6ProtocolGuid
,
882 HttpInstance
->Service
->ImageHandle
,
883 HttpInstance
->Service
->ControllerHandle
887 HttpInstance
->Tcp6ChildHandle
,
888 &gEfiTcp6ProtocolGuid
,
889 HttpInstance
->Service
->ImageHandle
,
893 NetLibDestroyServiceChild (
894 HttpInstance
->Service
->ControllerHandle
,
895 HttpInstance
->Service
->ImageHandle
,
896 &gEfiTcp6ServiceBindingProtocolGuid
,
897 HttpInstance
->Tcp6ChildHandle
901 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
903 HttpInstance
->Service
->Tcp6ChildHandle
,
904 &gEfiTcp6ProtocolGuid
,
905 HttpInstance
->Service
->ImageHandle
,
913 Establish TCP connection with HTTP server.
915 @param[in] HttpInstance The HTTP instance private data.
917 @retval EFI_SUCCESS The TCP connection is established.
918 @retval Others Other error as indicated.
922 HttpCreateConnection (
923 IN HTTP_PROTOCOL
*HttpInstance
929 // Connect to Http server
931 if (!HttpInstance
->LocalAddressIsIPv6
) {
932 HttpInstance
->IsTcp4ConnDone
= FALSE
;
933 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
934 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4ConnToken
);
935 if (EFI_ERROR (Status
)) {
936 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
940 while (!HttpInstance
->IsTcp4ConnDone
) {
941 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
944 Status
= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
;
947 HttpInstance
->IsTcp6ConnDone
= FALSE
;
948 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
949 Status
= HttpInstance
->Tcp6
->Connect (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6ConnToken
);
950 if (EFI_ERROR (Status
)) {
951 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status
));
955 while(!HttpInstance
->IsTcp6ConnDone
) {
956 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
959 Status
= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
;
962 if (!EFI_ERROR (Status
)) {
963 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
970 Close existing TCP connection.
972 @param[in] HttpInstance The HTTP instance private data.
974 @retval EFI_SUCCESS The TCP connection is closed.
975 @retval Others Other error as indicated.
979 HttpCloseConnection (
980 IN HTTP_PROTOCOL
*HttpInstance
985 if (HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) {
987 if (HttpInstance
->LocalAddressIsIPv6
) {
988 HttpInstance
->Tcp6CloseToken
.AbortOnClose
= TRUE
;
989 HttpInstance
->IsTcp6CloseDone
= FALSE
;
990 Status
= HttpInstance
->Tcp6
->Close (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6CloseToken
);
991 if (EFI_ERROR (Status
)) {
995 while (!HttpInstance
->IsTcp6CloseDone
) {
996 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
1000 HttpInstance
->Tcp4CloseToken
.AbortOnClose
= TRUE
;
1001 HttpInstance
->IsTcp4CloseDone
= FALSE
;
1002 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4CloseToken
);
1003 if (EFI_ERROR (Status
)) {
1007 while (!HttpInstance
->IsTcp4CloseDone
) {
1008 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
1014 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
1019 Configure TCP4 protocol child.
1021 @param[in] HttpInstance The HTTP instance private data.
1022 @param[in] Wrap The HTTP token's wrap data.
1024 @retval EFI_SUCCESS The TCP4 protocol child is configured.
1025 @retval Others Other error as indicated.
1030 IN HTTP_PROTOCOL
*HttpInstance
,
1031 IN HTTP_TOKEN_WRAP
*Wrap
1035 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
1036 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
1037 EFI_TCP4_OPTION
*Tcp4Option
;
1039 ASSERT (HttpInstance
!= NULL
);
1042 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
1043 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
1045 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
1046 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
1047 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
1049 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
1050 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
1051 if (!Tcp4AP
->UseDefaultAddress
) {
1052 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
1053 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
1056 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
1057 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
1058 Tcp4AP
->ActiveFlag
= TRUE
;
1059 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
1061 Tcp4Option
= Tcp4CfgData
->ControlOption
;
1062 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1063 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1064 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1065 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1066 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
1067 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1068 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1069 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1070 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1071 Tcp4Option
->EnableNagle
= TRUE
;
1072 Tcp4CfgData
->ControlOption
= Tcp4Option
;
1074 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
1075 if (EFI_ERROR (Status
)) {
1076 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
1080 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1081 if (EFI_ERROR (Status
)) {
1085 Status
= HttpCreateTcpTxEvent (Wrap
);
1086 if (EFI_ERROR (Status
)) {
1090 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1096 Configure TCP6 protocol child.
1098 @param[in] HttpInstance The HTTP instance private data.
1099 @param[in] Wrap The HTTP token's wrap data.
1101 @retval EFI_SUCCESS The TCP6 protocol child is configured.
1102 @retval Others Other error as indicated.
1107 IN HTTP_PROTOCOL
*HttpInstance
,
1108 IN HTTP_TOKEN_WRAP
*Wrap
1112 EFI_TCP6_CONFIG_DATA
*Tcp6CfgData
;
1113 EFI_TCP6_ACCESS_POINT
*Tcp6Ap
;
1114 EFI_TCP6_OPTION
*Tcp6Option
;
1116 ASSERT (HttpInstance
!= NULL
);
1118 Tcp6CfgData
= &HttpInstance
->Tcp6CfgData
;
1119 ZeroMem (Tcp6CfgData
, sizeof (EFI_TCP6_CONFIG_DATA
));
1121 Tcp6CfgData
->TrafficClass
= 0;
1122 Tcp6CfgData
->HopLimit
= 255;
1123 Tcp6CfgData
->ControlOption
= &HttpInstance
->Tcp6Option
;
1125 Tcp6Ap
= &Tcp6CfgData
->AccessPoint
;
1126 Tcp6Ap
->ActiveFlag
= TRUE
;
1127 Tcp6Ap
->StationPort
= HttpInstance
->Ipv6Node
.LocalPort
;
1128 Tcp6Ap
->RemotePort
= HttpInstance
->RemotePort
;
1129 IP6_COPY_ADDRESS (&Tcp6Ap
->StationAddress
, &HttpInstance
->Ipv6Node
.LocalAddress
);
1130 IP6_COPY_ADDRESS (&Tcp6Ap
->RemoteAddress
, &HttpInstance
->RemoteIpv6Addr
);
1132 Tcp6Option
= Tcp6CfgData
->ControlOption
;
1133 Tcp6Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1134 Tcp6Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1135 Tcp6Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1136 Tcp6Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1137 Tcp6Option
->DataRetries
= HTTP_DATA_RETRIES
;
1138 Tcp6Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1139 Tcp6Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1140 Tcp6Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1141 Tcp6Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1142 Tcp6Option
->EnableNagle
= TRUE
;
1144 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, Tcp6CfgData
);
1145 if (EFI_ERROR (Status
)) {
1146 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp6 - %r\n", Status
));
1150 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1151 if (EFI_ERROR (Status
)) {
1155 Status
= HttpCreateTcpTxEvent (Wrap
);
1156 if (EFI_ERROR (Status
)) {
1160 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1167 Check existing TCP connection, if in error state, recover TCP4 connection.
1169 @param[in] HttpInstance The HTTP instance private data.
1171 @retval EFI_SUCCESS The TCP connection is established.
1172 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1173 @retval Others Other error as indicated.
1178 IN HTTP_PROTOCOL
*HttpInstance
1182 EFI_TCP4_CONNECTION_STATE Tcp4State
;
1185 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp4
== NULL
) {
1186 return EFI_NOT_READY
;
1189 Status
= HttpInstance
->Tcp4
->GetModeData(
1197 if (EFI_ERROR(Status
)){
1198 DEBUG ((EFI_D_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
1202 if (Tcp4State
== Tcp4StateEstablished
) {
1204 } else if (Tcp4State
> Tcp4StateEstablished
) {
1205 HttpCloseConnection(HttpInstance
);
1208 return HttpCreateConnection (HttpInstance
);
1212 Check existing TCP connection, if in error state, recover TCP6 connection.
1214 @param[in] HttpInstance The HTTP instance private data.
1216 @retval EFI_SUCCESS The TCP connection is established.
1217 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1218 @retval Others Other error as indicated.
1223 IN HTTP_PROTOCOL
*HttpInstance
1227 EFI_TCP6_CONNECTION_STATE Tcp6State
;
1229 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp6
== NULL
) {
1230 return EFI_NOT_READY
;
1233 Status
= HttpInstance
->Tcp6
->GetModeData (
1242 if (EFI_ERROR(Status
)){
1243 DEBUG ((EFI_D_ERROR
, "Tcp6 GetModeData fail - %x\n", Status
));
1247 if (Tcp6State
== Tcp6StateEstablished
) {
1249 } else if (Tcp6State
> Tcp6StateEstablished
) {
1250 HttpCloseConnection(HttpInstance
);
1253 return HttpCreateConnection (HttpInstance
);
1257 Initialize TCP related data.
1259 @param[in] HttpInstance The HTTP instance private data.
1260 @param[in] Wrap The HTTP token's wrap data.
1261 @param[in] Configure The Flag indicates whether the first time to initialize Tcp.
1263 @retval EFI_SUCCESS The initialization of TCP instance is done.
1264 @retval Others Other error as indicated.
1269 IN HTTP_PROTOCOL
*HttpInstance
,
1270 IN HTTP_TOKEN_WRAP
*Wrap
,
1271 IN BOOLEAN Configure
1275 ASSERT (HttpInstance
!= NULL
);
1277 if (!HttpInstance
->LocalAddressIsIPv6
) {
1279 // Configure TCP instance.
1282 Status
= HttpConfigureTcp4 (HttpInstance
, Wrap
);
1283 if (EFI_ERROR (Status
)) {
1291 Status
= HttpConnectTcp4 (HttpInstance
);
1292 if (EFI_ERROR (Status
)) {
1297 // Configure TCP instance.
1300 Status
= HttpConfigureTcp6 (HttpInstance
, Wrap
);
1301 if (EFI_ERROR (Status
)) {
1309 Status
= HttpConnectTcp6 (HttpInstance
);
1310 if (EFI_ERROR (Status
)) {
1320 Send the HTTP message through TCP4 or TCP6.
1322 @param[in] HttpInstance The HTTP instance private data.
1323 @param[in] Wrap The HTTP token's wrap data.
1324 @param[in] TxString Buffer containing the HTTP message string.
1325 @param[in] TxStringLen Length of the HTTP message string in bytes.
1327 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1328 @retval Others Other error as indicated.
1333 IN HTTP_PROTOCOL
*HttpInstance
,
1334 IN HTTP_TOKEN_WRAP
*Wrap
,
1336 IN UINTN TxStringLen
1340 EFI_TCP4_IO_TOKEN
*Tx4Token
;
1341 EFI_TCP4_PROTOCOL
*Tcp4
;
1342 EFI_TCP6_IO_TOKEN
*Tx6Token
;
1343 EFI_TCP6_PROTOCOL
*Tcp6
;
1345 if (!HttpInstance
->LocalAddressIsIPv6
) {
1346 Tcp4
= HttpInstance
->Tcp4
;
1347 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1349 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1350 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1351 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1352 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1354 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1355 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1356 if (EFI_ERROR (Status
)) {
1357 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1362 Tcp6
= HttpInstance
->Tcp6
;
1363 Tx6Token
= &Wrap
->TcpWrap
.Tx6Token
;
1365 Tx6Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1366 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1367 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1368 Tx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1370 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1371 Status
= Tcp6
->Transmit (Tcp6
, Tx6Token
);
1372 if (EFI_ERROR (Status
)) {
1373 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1383 Translate the status code in HTTP message to EFI_HTTP_STATUS_CODE defined
1384 in UEFI 2.5 specification.
1386 @param[in] StatusCode The status code value in HTTP message.
1388 @return Value defined in EFI_HTTP_STATUS_CODE .
1391 EFI_HTTP_STATUS_CODE
1392 HttpMappingToStatusCode (
1396 switch (StatusCode
) {
1398 return HTTP_STATUS_100_CONTINUE
;
1400 return HTTP_STATUS_101_SWITCHING_PROTOCOLS
;
1402 return HTTP_STATUS_200_OK
;
1404 return HTTP_STATUS_201_CREATED
;
1406 return HTTP_STATUS_202_ACCEPTED
;
1408 return HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION
;
1410 return HTTP_STATUS_204_NO_CONTENT
;
1412 return HTTP_STATUS_205_RESET_CONTENT
;
1414 return HTTP_STATUS_206_PARTIAL_CONTENT
;
1416 return HTTP_STATUS_300_MULTIPLE_CHIOCES
;
1418 return HTTP_STATUS_301_MOVED_PERMANENTLY
;
1420 return HTTP_STATUS_302_FOUND
;
1422 return HTTP_STATUS_303_SEE_OTHER
;
1424 return HTTP_STATUS_304_NOT_MODIFIED
;
1426 return HTTP_STATUS_305_USE_PROXY
;
1428 return HTTP_STATUS_307_TEMPORARY_REDIRECT
;
1430 return HTTP_STATUS_400_BAD_REQUEST
;
1432 return HTTP_STATUS_401_UNAUTHORIZED
;
1434 return HTTP_STATUS_402_PAYMENT_REQUIRED
;
1436 return HTTP_STATUS_403_FORBIDDEN
;
1438 return HTTP_STATUS_404_NOT_FOUND
;
1440 return HTTP_STATUS_405_METHOD_NOT_ALLOWED
;
1442 return HTTP_STATUS_406_NOT_ACCEPTABLE
;
1444 return HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED
;
1446 return HTTP_STATUS_408_REQUEST_TIME_OUT
;
1448 return HTTP_STATUS_409_CONFLICT
;
1450 return HTTP_STATUS_410_GONE
;
1452 return HTTP_STATUS_411_LENGTH_REQUIRED
;
1454 return HTTP_STATUS_412_PRECONDITION_FAILED
;
1456 return HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE
;
1458 return HTTP_STATUS_414_REQUEST_URI_TOO_LARGE
;
1460 return HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE
;
1462 return HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED
;
1464 return HTTP_STATUS_417_EXPECTATION_FAILED
;
1466 return HTTP_STATUS_500_INTERNAL_SERVER_ERROR
;
1468 return HTTP_STATUS_501_NOT_IMPLEMENTED
;
1470 return HTTP_STATUS_502_BAD_GATEWAY
;
1472 return HTTP_STATUS_503_SERVICE_UNAVAILABLE
;
1474 return HTTP_STATUS_504_GATEWAY_TIME_OUT
;
1476 return HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED
;
1479 return HTTP_STATUS_UNSUPPORTED_STATUS
;
1484 Check whether the user's token or event has already
1485 been enqueue on HTTP Tx or Rx Token list.
1487 @param[in] Map The container of either user's transmit or receive
1489 @param[in] Item Current item to check against.
1490 @param[in] Context The Token to check againist.
1492 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1493 @retval EFI_SUCCESS The current item isn't the same token/event as the
1501 IN NET_MAP_ITEM
*Item
,
1505 EFI_HTTP_TOKEN
*Token
;
1506 EFI_HTTP_TOKEN
*TokenInItem
;
1508 Token
= (EFI_HTTP_TOKEN
*) Context
;
1509 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
1511 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
1512 return EFI_ACCESS_DENIED
;
1519 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1521 @param[in] Map The container of Tx4Token or Tx6Token.
1522 @param[in] Item Current item to check against.
1523 @param[in] Context The Token to check againist.
1525 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1526 @retval EFI_SUCCESS The HTTP message has been sent out.
1533 IN NET_MAP_ITEM
*Item
,
1537 HTTP_TOKEN_WRAP
*ValueInItem
;
1539 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1541 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
1542 return EFI_NOT_READY
;
1549 Transmit the HTTP mssage by processing the associated HTTP token.
1551 @param[in] Map The container of Tx4Token or Tx6Token.
1552 @param[in] Item Current item to check against.
1553 @param[in] Context The Token to check againist.
1555 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1556 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1564 IN NET_MAP_ITEM
*Item
,
1568 HTTP_TOKEN_WRAP
*ValueInItem
;
1573 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1574 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1579 // Parse the URI of the remote host.
1581 Url
= AllocatePool (StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1);
1583 return EFI_OUT_OF_RESOURCES
;
1586 UnicodeStrToAsciiStr (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
);
1589 // Create request message.
1591 RequestStr
= HttpGenRequestString (
1592 ValueInItem
->HttpInstance
,
1593 ValueInItem
->HttpToken
->Message
,
1597 if (RequestStr
== NULL
) {
1598 return EFI_OUT_OF_RESOURCES
;
1602 // Transmit the request message.
1604 Status
= HttpTransmitTcp (
1605 ValueInItem
->HttpInstance
,
1607 (UINT8
*) RequestStr
,
1608 AsciiStrLen (RequestStr
)
1610 FreePool (RequestStr
);
1615 Receive the HTTP response by processing the associated HTTP token.
1617 @param[in] Map The container of Rx4Token or Rx6Token.
1618 @param[in] Item Current item to check against.
1619 @param[in] Context The Token to check againist.
1621 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1623 @retval Others Other error as indicated.
1630 IN NET_MAP_ITEM
*Item
,
1635 // Process the queued HTTP response.
1637 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1641 Receive the HTTP header by processing the associated HTTP token.
1643 @param[in] HttpInstance The HTTP instance private data.
1644 @param[in, out] SizeofHeaders The HTTP header length.
1645 @param[in, out] BufferSize The size of buffer to cacahe the header message.
1647 @retval EFI_SUCCESS The HTTP header is received.
1648 @retval Others Other errors as indicated.
1652 HttpTcpReceiveHeader (
1653 IN HTTP_PROTOCOL
*HttpInstance
,
1654 IN OUT UINTN
*SizeofHeaders
,
1655 IN OUT UINTN
*BufferSize
1659 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1660 EFI_TCP4_PROTOCOL
*Tcp4
;
1661 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1662 EFI_TCP6_PROTOCOL
*Tcp6
;
1663 CHAR8
**EndofHeader
;
1664 CHAR8
**HttpHeaders
;
1667 ASSERT (HttpInstance
!= NULL
);
1669 EndofHeader
= HttpInstance
->EndofHeader
;
1670 HttpHeaders
= HttpInstance
->HttpHeaders
;
1671 Tcp4
= HttpInstance
->Tcp4
;
1672 Tcp6
= HttpInstance
->Tcp6
;
1677 if (HttpInstance
->LocalAddressIsIPv6
) {
1678 ASSERT (Tcp6
!= NULL
);
1680 ASSERT (Tcp4
!= NULL
);
1683 if (!HttpInstance
->LocalAddressIsIPv6
) {
1684 Rx4Token
= &HttpInstance
->Rx4Token
;
1685 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1686 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1687 Status
= EFI_OUT_OF_RESOURCES
;
1692 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1694 while (*EndofHeader
== NULL
) {
1695 HttpInstance
->IsRxDone
= FALSE
;
1696 Rx4Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1697 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1698 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1699 if (EFI_ERROR (Status
)) {
1700 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1704 while (!HttpInstance
->IsRxDone
) {
1708 Status
= Rx4Token
->CompletionToken
.Status
;
1709 if (EFI_ERROR (Status
)) {
1714 // Append the response string.
1716 *BufferSize
= (*SizeofHeaders
) + Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1717 Buffer
= AllocateZeroPool (*BufferSize
);
1718 if (Buffer
== NULL
) {
1719 Status
= EFI_OUT_OF_RESOURCES
;
1723 if (*HttpHeaders
!= NULL
) {
1724 CopyMem (Buffer
, *HttpHeaders
, (*SizeofHeaders
));
1725 FreePool (*HttpHeaders
);
1729 Buffer
+ (*SizeofHeaders
),
1730 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
,
1731 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
1733 *HttpHeaders
= Buffer
;
1734 *SizeofHeaders
= *BufferSize
;
1737 // Check whether we received end of HTTP headers.
1739 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1741 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1742 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1745 Rx6Token
= &HttpInstance
->Rx6Token
;
1746 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1747 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1748 Status
= EFI_OUT_OF_RESOURCES
;
1753 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1755 while (*EndofHeader
== NULL
) {
1756 HttpInstance
->IsRxDone
= FALSE
;
1757 Rx6Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1758 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1759 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1760 if (EFI_ERROR (Status
)) {
1761 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1765 while (!HttpInstance
->IsRxDone
) {
1769 Status
= Rx6Token
->CompletionToken
.Status
;
1770 if (EFI_ERROR (Status
)) {
1775 // Append the response string.
1777 *BufferSize
= (*SizeofHeaders
) + Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1778 Buffer
= AllocateZeroPool (*BufferSize
);
1779 if (Buffer
== NULL
) {
1780 Status
= EFI_OUT_OF_RESOURCES
;
1784 if (*HttpHeaders
!= NULL
) {
1785 CopyMem (Buffer
, *HttpHeaders
, (*SizeofHeaders
));
1786 FreePool (*HttpHeaders
);
1790 Buffer
+ (*SizeofHeaders
),
1791 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
,
1792 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
1794 *HttpHeaders
= Buffer
;
1795 *SizeofHeaders
= *BufferSize
;
1798 // Check whether we received end of HTTP headers.
1800 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1803 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1804 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1808 // Skip the CRLF after the HTTP headers.
1810 *EndofHeader
= *EndofHeader
+ AsciiStrLen (HTTP_END_OF_HDR_STR
);
1816 Receive the HTTP body by processing the associated HTTP token.
1818 @param[in] Wrap The HTTP token's wrap data.
1819 @param[in] HttpMsg The HTTP message data.
1821 @retval EFI_SUCCESS The HTTP body is received.
1822 @retval Others Other error as indicated.
1826 HttpTcpReceiveBody (
1827 IN HTTP_TOKEN_WRAP
*Wrap
,
1828 IN EFI_HTTP_MESSAGE
*HttpMsg
1832 HTTP_PROTOCOL
*HttpInstance
;
1833 EFI_TCP6_PROTOCOL
*Tcp6
;
1834 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1835 EFI_TCP4_PROTOCOL
*Tcp4
;
1836 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1838 HttpInstance
= Wrap
->HttpInstance
;
1839 Tcp4
= HttpInstance
->Tcp4
;
1840 Tcp6
= HttpInstance
->Tcp6
;
1845 if (HttpInstance
->LocalAddressIsIPv6
) {
1846 ASSERT (Tcp6
!= NULL
);
1848 ASSERT (Tcp4
!= NULL
);
1851 if (HttpInstance
->LocalAddressIsIPv6
) {
1852 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
1853 Rx6Token
->Packet
.RxData
->DataLength
= (UINT32
) HttpMsg
->BodyLength
;
1854 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) HttpMsg
->BodyLength
;
1855 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
1856 Rx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1858 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1859 if (EFI_ERROR (Status
)) {
1860 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1865 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
1866 Rx4Token
->Packet
.RxData
->DataLength
= (UINT32
) HttpMsg
->BodyLength
;
1867 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) HttpMsg
->BodyLength
;
1868 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
1870 Rx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1871 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1872 if (EFI_ERROR (Status
)) {
1873 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1883 Clean up Tcp Tokens while the Tcp transmission error occurs.
1885 @param[in] Wrap Pointer to HTTP token's wrap data.
1889 HttpTcpTokenCleanup (
1890 IN HTTP_TOKEN_WRAP
*Wrap
1893 HTTP_PROTOCOL
*HttpInstance
;
1894 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1895 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1897 ASSERT (Wrap
!= NULL
);
1898 HttpInstance
= Wrap
->HttpInstance
;
1902 if (HttpInstance
->LocalAddressIsIPv6
) {
1903 if (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
!= NULL
) {
1904 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
1907 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
1908 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1909 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1910 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1914 if (HttpInstance
->Rx6Token
.CompletionToken
.Event
!= NULL
) {
1915 gBS
->CloseEvent (HttpInstance
->Rx6Token
.CompletionToken
.Event
);
1916 HttpInstance
->Rx6Token
.CompletionToken
.Event
= NULL
;
1919 Rx6Token
= &HttpInstance
->Rx6Token
;
1920 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1921 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1922 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1926 if (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
!= NULL
) {
1927 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
1929 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
1930 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1931 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1932 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1936 if (HttpInstance
->Rx4Token
.CompletionToken
.Event
!= NULL
) {
1937 gBS
->CloseEvent (HttpInstance
->Rx4Token
.CompletionToken
.Event
);
1938 HttpInstance
->Rx4Token
.CompletionToken
.Event
= NULL
;
1941 Rx4Token
= &HttpInstance
->Rx4Token
;
1942 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1943 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1944 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1951 Generate HTTP request string.
1953 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
1954 @param[in] Message Pointer to storage containing HTTP message data.
1955 @param[in] Url The URL of a remote host.
1957 @return Pointer to the created HTTP request string.
1958 @return NULL if any error occured.
1962 HttpGenRequestString (
1963 IN HTTP_PROTOCOL
*HttpInstance
,
1964 IN EFI_HTTP_MESSAGE
*Message
,
1976 EFI_HTTP_HEADER
**AppendList
;
1979 ASSERT (HttpInstance
!= NULL
);
1980 ASSERT (Message
!= NULL
);
1982 DEBUG ((EFI_D_ERROR
, "HttpMethod - %x\n", Message
->Data
.Request
->Method
));
1992 AppendList
= AllocateZeroPool (sizeof (EFI_HTTP_HEADER
*) * (Message
->HeaderCount
));
1993 if (AppendList
== NULL
) {
1997 for(Index
= 0; Index
< Message
->HeaderCount
; Index
++){
1998 AppendList
[Index
] = &Message
->Headers
[Index
];
2002 // Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.
2004 if (mHttpUtilities
== NULL
) {
2009 // Build raw unformatted HTTP headers.
2011 Status
= mHttpUtilities
->Build (
2017 Message
->HeaderCount
,
2022 FreePool (AppendList
);
2023 if (EFI_ERROR (Status
) || HttpHdr
== NULL
) {
2028 // Calculate HTTP message length.
2030 MsgSize
= Message
->BodyLength
+ HTTP_MAXIMUM_METHOD_LEN
+ AsciiStrLen (Url
) +
2031 AsciiStrLen (HTTP_VERSION_CRLF_STR
) + HttpHdrSize
;
2032 Request
= AllocateZeroPool (MsgSize
);
2033 if (Request
== NULL
) {
2037 RequestPtr
= Request
;
2039 // Construct header request
2041 switch (Message
->Data
.Request
->Method
) {
2043 StrLength
= sizeof (HTTP_GET_STR
) - 1;
2044 CopyMem (RequestPtr
, HTTP_GET_STR
, StrLength
);
2045 RequestPtr
+= StrLength
;
2047 case HttpMethodHead
:
2048 StrLength
= sizeof (HTTP_HEAD_STR
) - 1;
2049 CopyMem (RequestPtr
, HTTP_HEAD_STR
, StrLength
);
2050 RequestPtr
+= StrLength
;
2057 StrLength
= AsciiStrLen (Url
);
2058 CopyMem (RequestPtr
, Url
, StrLength
);
2059 RequestPtr
+= StrLength
;
2061 StrLength
= sizeof (HTTP_VERSION_CRLF_STR
) - 1;
2062 CopyMem (RequestPtr
, HTTP_VERSION_CRLF_STR
, StrLength
);
2063 RequestPtr
+= StrLength
;
2068 CopyMem (RequestPtr
, HttpHdr
, HttpHdrSize
);
2069 RequestPtr
+= HttpHdrSize
;
2074 if (Message
->Body
!= NULL
) {
2075 CopyMem (RequestPtr
, Message
->Body
, Message
->BodyLength
);
2076 RequestPtr
+= Message
->BodyLength
;
2088 if (Request
!= NULL
) {
2095 if (HttpHdr
!= NULL
) {
2099 return (CHAR8
*) Request
;