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
)) {
157 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
159 if (EFI_ERROR (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
)) {
165 // Check whether we receive a complete HTTP message.
167 ASSERT (HttpInstance
->MsgParser
!= NULL
);
169 Length
= (UINTN
) Wrap
->TcpWrap
.Rx6Data
.FragmentTable
[0].FragmentLength
;
171 Length
= (UINTN
) Wrap
->TcpWrap
.Rx4Data
.FragmentTable
[0].FragmentLength
;
174 Status
= HttpParseMessageBody (
175 HttpInstance
->MsgParser
,
177 Wrap
->HttpToken
->Message
->Body
179 if (EFI_ERROR (Status
)) {
183 if (HttpIsMessageComplete (HttpInstance
->MsgParser
)) {
185 // Free the MsgParse since we already have a full HTTP message.
187 HttpFreeMsgParser (HttpInstance
->MsgParser
);
188 HttpInstance
->MsgParser
= NULL
;
191 Wrap
->HttpToken
->Message
->BodyLength
= Length
;
192 ASSERT (HttpInstance
->CacheBody
== NULL
);
194 // We receive part of header of next HTTP msg.
196 if (HttpInstance
->NextMsg
!= NULL
) {
197 Wrap
->HttpToken
->Message
->BodyLength
= HttpInstance
->NextMsg
-
198 (CHAR8
*) Wrap
->HttpToken
->Message
->Body
;
199 HttpInstance
->CacheLen
= Length
- Wrap
->HttpToken
->Message
->BodyLength
;
200 if (HttpInstance
->CacheLen
!= 0) {
201 HttpInstance
->CacheBody
= AllocateZeroPool (HttpInstance
->CacheLen
);
202 if (HttpInstance
->CacheBody
== NULL
) {
205 CopyMem (HttpInstance
->CacheBody
, HttpInstance
->NextMsg
, HttpInstance
->CacheLen
);
206 HttpInstance
->NextMsg
= HttpInstance
->CacheBody
;
207 HttpInstance
->CacheOffset
= 0;
211 Item
= NetMapFindKey (&Wrap
->HttpInstance
->RxTokens
, Wrap
->HttpToken
);
213 NetMapRemoveItem (&Wrap
->HttpInstance
->RxTokens
, Item
, NULL
);
217 Wrap
->TcpWrap
.IsRxDone
= TRUE
;
219 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
221 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
225 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
228 // Check pending RxTokens and receive the HTTP message.
230 NetMapIterate (&Wrap
->HttpInstance
->RxTokens
, HttpTcpReceive
, NULL
);
236 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.
238 @param Event The receive event delivered to TCP for receive.
239 @param Context Context for the callback.
244 HttpTcpReceiveNotify (
250 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
252 QueueDpc (TPL_CALLBACK
, HttpTcpReceiveNotifyDpc
, Context
);
256 Create events for the TCP connection token and TCP close token.
258 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
260 @retval EFI_SUCCESS The events are created successfully.
261 @retval others Other error as indicated.
265 HttpCreateTcpConnCloseEvent (
266 IN HTTP_PROTOCOL
*HttpInstance
271 if (!HttpInstance
->LocalAddressIsIPv6
) {
273 // Create events for variuos asynchronous operations.
275 Status
= gBS
->CreateEvent (
279 &HttpInstance
->IsTcp4ConnDone
,
280 &HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
282 if (EFI_ERROR (Status
)) {
287 // Initialize Tcp4CloseToken
289 Status
= gBS
->CreateEvent (
293 &HttpInstance
->IsTcp4CloseDone
,
294 &HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
296 if (EFI_ERROR (Status
)) {
302 // Create events for variuos asynchronous operations.
304 Status
= gBS
->CreateEvent (
308 &HttpInstance
->IsTcp6ConnDone
,
309 &HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
311 if (EFI_ERROR (Status
)) {
316 // Initialize Tcp6CloseToken
318 Status
= gBS
->CreateEvent (
322 &HttpInstance
->IsTcp6CloseDone
,
323 &HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
325 if (EFI_ERROR (Status
)) {
336 HttpCloseTcpConnCloseEvent (HttpInstance
);
343 Close events in the TCP connection token and TCP close token.
345 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
349 HttpCloseTcpConnCloseEvent (
350 IN HTTP_PROTOCOL
*HttpInstance
353 ASSERT (HttpInstance
!= NULL
);
355 if (HttpInstance
->LocalAddressIsIPv6
) {
356 if (NULL
!= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
) {
357 gBS
->CloseEvent (HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
);
358 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
= NULL
;
361 if (NULL
!= HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
) {
362 gBS
->CloseEvent(HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
);
363 HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
= NULL
;
367 if (NULL
!= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
) {
368 gBS
->CloseEvent (HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
);
369 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
= NULL
;
372 if (NULL
!= HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
) {
373 gBS
->CloseEvent(HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
);
374 HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
381 Create event for the TCP transmit token.
383 @param[in] Wrap Point to HTTP token's wrap data.
385 @retval EFI_SUCCESS The events is created successfully.
386 @retval others Other error as indicated.
390 HttpCreateTcpTxEvent (
391 IN HTTP_TOKEN_WRAP
*Wrap
395 HTTP_PROTOCOL
*HttpInstance
;
396 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
398 HttpInstance
= Wrap
->HttpInstance
;
399 TcpWrap
= &Wrap
->TcpWrap
;
401 if (!HttpInstance
->LocalAddressIsIPv6
) {
402 Status
= gBS
->CreateEvent (
405 HttpTcpTransmitNotify
,
407 &TcpWrap
->Tx4Token
.CompletionToken
.Event
409 if (EFI_ERROR (Status
)) {
413 TcpWrap
->Tx4Data
.Push
= TRUE
;
414 TcpWrap
->Tx4Data
.Urgent
= FALSE
;
415 TcpWrap
->Tx4Data
.FragmentCount
= 1;
416 TcpWrap
->Tx4Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx4Data
;
417 TcpWrap
->Tx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
420 Status
= gBS
->CreateEvent (
423 HttpTcpTransmitNotify
,
425 &TcpWrap
->Tx6Token
.CompletionToken
.Event
427 if (EFI_ERROR (Status
)) {
431 TcpWrap
->Tx6Data
.Push
= TRUE
;
432 TcpWrap
->Tx6Data
.Urgent
= FALSE
;
433 TcpWrap
->Tx6Data
.FragmentCount
= 1;
434 TcpWrap
->Tx6Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx6Data
;
435 TcpWrap
->Tx6Token
.CompletionToken
.Status
=EFI_NOT_READY
;
444 Create event for the TCP receive token which is used to receive HTTP header.
446 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
448 @retval EFI_SUCCESS The events is created successfully.
449 @retval others Other error as indicated.
453 HttpCreateTcpRxEventForHeader (
454 IN HTTP_PROTOCOL
*HttpInstance
459 if (!HttpInstance
->LocalAddressIsIPv6
) {
460 Status
= gBS
->CreateEvent (
464 &HttpInstance
->IsRxDone
,
465 &HttpInstance
->Rx4Token
.CompletionToken
.Event
467 if (EFI_ERROR (Status
)) {
471 HttpInstance
->Rx4Data
.FragmentCount
= 1;
472 HttpInstance
->Rx4Token
.Packet
.RxData
= &HttpInstance
->Rx4Data
;
473 HttpInstance
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
476 Status
= gBS
->CreateEvent (
480 &HttpInstance
->IsRxDone
,
481 &HttpInstance
->Rx6Token
.CompletionToken
.Event
483 if (EFI_ERROR (Status
)) {
487 HttpInstance
->Rx6Data
.FragmentCount
=1;
488 HttpInstance
->Rx6Token
.Packet
.RxData
= &HttpInstance
->Rx6Data
;
489 HttpInstance
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
498 Create event for the TCP receive token which is used to receive HTTP body.
500 @param[in] Wrap Point to HTTP token's wrap data.
502 @retval EFI_SUCCESS The events is created successfully.
503 @retval others Other error as indicated.
507 HttpCreateTcpRxEvent (
508 IN HTTP_TOKEN_WRAP
*Wrap
512 HTTP_PROTOCOL
*HttpInstance
;
513 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
515 HttpInstance
= Wrap
->HttpInstance
;
516 TcpWrap
= &Wrap
->TcpWrap
;
517 if (!HttpInstance
->LocalAddressIsIPv6
) {
518 Status
= gBS
->CreateEvent (
521 HttpTcpReceiveNotify
,
523 &TcpWrap
->Rx4Token
.CompletionToken
.Event
525 if (EFI_ERROR (Status
)) {
529 TcpWrap
->Rx4Data
.FragmentCount
= 1;
530 TcpWrap
->Rx4Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx4Data
;
531 TcpWrap
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
534 Status
= gBS
->CreateEvent (
537 HttpTcpReceiveNotify
,
539 &TcpWrap
->Rx6Token
.CompletionToken
.Event
541 if (EFI_ERROR (Status
)) {
545 TcpWrap
->Rx6Data
.FragmentCount
= 1;
546 TcpWrap
->Rx6Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx6Data
;
547 TcpWrap
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
554 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.
556 @param[in] Wrap Pointer to HTTP token's wrap data.
560 HttpCloseTcpRxEvent (
561 IN HTTP_TOKEN_WRAP
*Wrap
564 HTTP_PROTOCOL
*HttpInstance
;
565 EFI_TCP4_IO_TOKEN
*Rx4Token
;
566 EFI_TCP6_IO_TOKEN
*Rx6Token
;
568 ASSERT (Wrap
!= NULL
);
569 HttpInstance
= Wrap
->HttpInstance
;
573 if (HttpInstance
->LocalAddressIsIPv6
) {
574 if (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
!= NULL
) {
575 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
578 if (HttpInstance
->Rx6Token
.CompletionToken
.Event
!= NULL
) {
579 gBS
->CloseEvent (HttpInstance
->Rx6Token
.CompletionToken
.Event
);
580 HttpInstance
->Rx6Token
.CompletionToken
.Event
= NULL
;
583 if (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
!= NULL
) {
584 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
587 if (HttpInstance
->Rx4Token
.CompletionToken
.Event
!= NULL
) {
588 gBS
->CloseEvent (HttpInstance
->Rx4Token
.CompletionToken
.Event
);
589 HttpInstance
->Rx4Token
.CompletionToken
.Event
= NULL
;
595 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.
597 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
598 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.
600 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
601 @retval Others Other error as indicated.
606 IN OUT HTTP_PROTOCOL
*HttpInstance
,
614 ASSERT (HttpInstance
!= NULL
);
615 UsingIpv6
= IpVersion
;
619 // Create TCP4 child.
621 Status
= NetLibCreateServiceChild (
622 HttpInstance
->Service
->ControllerHandle
,
623 HttpInstance
->Service
->ImageHandle
,
624 &gEfiTcp4ServiceBindingProtocolGuid
,
625 &HttpInstance
->Tcp4ChildHandle
628 if (EFI_ERROR (Status
)) {
632 Status
= gBS
->OpenProtocol (
633 HttpInstance
->Tcp4ChildHandle
,
634 &gEfiTcp4ProtocolGuid
,
635 (VOID
**) &Interface
,
636 HttpInstance
->Service
->ImageHandle
,
637 HttpInstance
->Service
->ControllerHandle
,
638 EFI_OPEN_PROTOCOL_BY_DRIVER
641 if (EFI_ERROR (Status
)) {
645 Status
= gBS
->OpenProtocol (
646 HttpInstance
->Tcp4ChildHandle
,
647 &gEfiTcp4ProtocolGuid
,
648 (VOID
**) &HttpInstance
->Tcp4
,
649 HttpInstance
->Service
->ImageHandle
,
650 HttpInstance
->Handle
,
651 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
653 if (EFI_ERROR(Status
)) {
657 Status
= gBS
->OpenProtocol (
658 HttpInstance
->Service
->Tcp4ChildHandle
,
659 &gEfiTcp4ProtocolGuid
,
660 (VOID
**) &Interface
,
661 HttpInstance
->Service
->ImageHandle
,
662 HttpInstance
->Handle
,
663 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
665 if (EFI_ERROR(Status
)) {
670 // Create TCP6 Child.
672 Status
= NetLibCreateServiceChild (
673 HttpInstance
->Service
->ControllerHandle
,
674 HttpInstance
->Service
->ImageHandle
,
675 &gEfiTcp6ServiceBindingProtocolGuid
,
676 &HttpInstance
->Tcp6ChildHandle
679 if (EFI_ERROR (Status
)) {
683 Status
= gBS
->OpenProtocol (
684 HttpInstance
->Tcp6ChildHandle
,
685 &gEfiTcp6ProtocolGuid
,
686 (VOID
**) &Interface
,
687 HttpInstance
->Service
->ImageHandle
,
688 HttpInstance
->Service
->ControllerHandle
,
689 EFI_OPEN_PROTOCOL_BY_DRIVER
692 if (EFI_ERROR (Status
)) {
696 Status
= gBS
->OpenProtocol (
697 HttpInstance
->Tcp6ChildHandle
,
698 &gEfiTcp6ProtocolGuid
,
699 (VOID
**) &HttpInstance
->Tcp6
,
700 HttpInstance
->Service
->ImageHandle
,
701 HttpInstance
->Handle
,
702 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
705 if (EFI_ERROR(Status
)) {
709 Status
= gBS
->OpenProtocol (
710 HttpInstance
->Service
->Tcp6ChildHandle
,
711 &gEfiTcp6ProtocolGuid
,
712 (VOID
**) &Interface
,
713 HttpInstance
->Service
->ImageHandle
,
714 HttpInstance
->Handle
,
715 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
718 if (EFI_ERROR(Status
)) {
723 HttpInstance
->Url
= AllocateZeroPool (HTTP_URL_BUFFER_LEN
);
724 if (HttpInstance
->Url
== NULL
) {
725 Status
= EFI_OUT_OF_RESOURCES
;
733 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
735 HttpInstance
->Tcp4ChildHandle
,
736 &gEfiTcp4ProtocolGuid
,
737 HttpInstance
->Service
->ImageHandle
,
738 HttpInstance
->Service
->ControllerHandle
742 HttpInstance
->Tcp4ChildHandle
,
743 &gEfiTcp4ProtocolGuid
,
744 HttpInstance
->Service
->ImageHandle
,
748 NetLibDestroyServiceChild (
749 HttpInstance
->Service
->ControllerHandle
,
750 HttpInstance
->Service
->ImageHandle
,
751 &gEfiTcp4ServiceBindingProtocolGuid
,
752 HttpInstance
->Tcp4ChildHandle
756 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
758 HttpInstance
->Service
->Tcp4ChildHandle
,
759 &gEfiTcp4ProtocolGuid
,
760 HttpInstance
->Service
->ImageHandle
,
765 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
767 HttpInstance
->Tcp6ChildHandle
,
768 &gEfiTcp6ProtocolGuid
,
769 HttpInstance
->Service
->ImageHandle
,
770 HttpInstance
->Service
->ControllerHandle
774 HttpInstance
->Tcp6ChildHandle
,
775 &gEfiTcp6ProtocolGuid
,
776 HttpInstance
->Service
->ImageHandle
,
780 NetLibDestroyServiceChild (
781 HttpInstance
->Service
->ControllerHandle
,
782 HttpInstance
->Service
->ImageHandle
,
783 &gEfiTcp6ServiceBindingProtocolGuid
,
784 HttpInstance
->Tcp6ChildHandle
788 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
790 HttpInstance
->Service
->Tcp6ChildHandle
,
791 &gEfiTcp6ProtocolGuid
,
792 HttpInstance
->Service
->ImageHandle
,
797 return EFI_UNSUPPORTED
;
802 Clean up the HTTP child, release all the resources used by it.
804 @param[in] HttpInstance The HTTP child to clean up.
809 IN HTTP_PROTOCOL
*HttpInstance
812 HttpCloseConnection (HttpInstance
);
814 HttpCloseTcpConnCloseEvent (HttpInstance
);
816 if (HttpInstance
->CacheBody
!= NULL
) {
817 FreePool (HttpInstance
->CacheBody
);
818 HttpInstance
->CacheBody
= NULL
;
819 HttpInstance
->NextMsg
= NULL
;
822 if (HttpInstance
->RemoteHost
!= NULL
) {
823 FreePool (HttpInstance
->RemoteHost
);
824 HttpInstance
->RemoteHost
= NULL
;
827 if (HttpInstance
->MsgParser
!= NULL
) {
828 HttpFreeMsgParser (HttpInstance
->MsgParser
);
829 HttpInstance
->MsgParser
= NULL
;
832 if (HttpInstance
->Url
!= NULL
) {
833 FreePool (HttpInstance
->Url
);
834 HttpInstance
->Url
= NULL
;
837 NetMapClean (&HttpInstance
->TxTokens
);
838 NetMapClean (&HttpInstance
->RxTokens
);
840 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
842 HttpInstance
->Tcp4ChildHandle
,
843 &gEfiTcp4ProtocolGuid
,
844 HttpInstance
->Service
->ImageHandle
,
845 HttpInstance
->Service
->ControllerHandle
849 HttpInstance
->Tcp4ChildHandle
,
850 &gEfiTcp4ProtocolGuid
,
851 HttpInstance
->Service
->ImageHandle
,
855 NetLibDestroyServiceChild (
856 HttpInstance
->Service
->ControllerHandle
,
857 HttpInstance
->Service
->ImageHandle
,
858 &gEfiTcp4ServiceBindingProtocolGuid
,
859 HttpInstance
->Tcp4ChildHandle
863 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
865 HttpInstance
->Service
->Tcp4ChildHandle
,
866 &gEfiTcp4ProtocolGuid
,
867 HttpInstance
->Service
->ImageHandle
,
872 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
874 HttpInstance
->Tcp6ChildHandle
,
875 &gEfiTcp6ProtocolGuid
,
876 HttpInstance
->Service
->ImageHandle
,
877 HttpInstance
->Service
->ControllerHandle
881 HttpInstance
->Tcp6ChildHandle
,
882 &gEfiTcp6ProtocolGuid
,
883 HttpInstance
->Service
->ImageHandle
,
887 NetLibDestroyServiceChild (
888 HttpInstance
->Service
->ControllerHandle
,
889 HttpInstance
->Service
->ImageHandle
,
890 &gEfiTcp6ServiceBindingProtocolGuid
,
891 HttpInstance
->Tcp6ChildHandle
895 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
897 HttpInstance
->Service
->Tcp6ChildHandle
,
898 &gEfiTcp6ProtocolGuid
,
899 HttpInstance
->Service
->ImageHandle
,
907 Establish TCP connection with HTTP server.
909 @param[in] HttpInstance The HTTP instance private data.
911 @retval EFI_SUCCESS The TCP connection is established.
912 @retval Others Other error as indicated.
916 HttpCreateConnection (
917 IN HTTP_PROTOCOL
*HttpInstance
923 // Connect to Http server
925 if (!HttpInstance
->LocalAddressIsIPv6
) {
926 HttpInstance
->IsTcp4ConnDone
= FALSE
;
927 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
928 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4ConnToken
);
929 if (EFI_ERROR (Status
)) {
930 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
934 while (!HttpInstance
->IsTcp4ConnDone
) {
935 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
938 Status
= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
;
941 HttpInstance
->IsTcp6ConnDone
= FALSE
;
942 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
943 Status
= HttpInstance
->Tcp6
->Connect (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6ConnToken
);
944 if (EFI_ERROR (Status
)) {
945 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status
));
949 while(!HttpInstance
->IsTcp6ConnDone
) {
950 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
953 Status
= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
;
956 if (!EFI_ERROR (Status
)) {
957 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
964 Close existing TCP connection.
966 @param[in] HttpInstance The HTTP instance private data.
968 @retval EFI_SUCCESS The TCP connection is closed.
969 @retval Others Other error as indicated.
973 HttpCloseConnection (
974 IN HTTP_PROTOCOL
*HttpInstance
979 if (HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) {
981 if (HttpInstance
->LocalAddressIsIPv6
) {
982 HttpInstance
->Tcp6CloseToken
.AbortOnClose
= TRUE
;
983 HttpInstance
->IsTcp6CloseDone
= FALSE
;
984 Status
= HttpInstance
->Tcp6
->Close (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6CloseToken
);
985 if (EFI_ERROR (Status
)) {
989 while (!HttpInstance
->IsTcp6CloseDone
) {
990 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
994 HttpInstance
->Tcp4CloseToken
.AbortOnClose
= TRUE
;
995 HttpInstance
->IsTcp4CloseDone
= FALSE
;
996 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4CloseToken
);
997 if (EFI_ERROR (Status
)) {
1001 while (!HttpInstance
->IsTcp4CloseDone
) {
1002 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
1008 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
1013 Configure TCP4 protocol child.
1015 @param[in] HttpInstance The HTTP instance private data.
1016 @param[in] Wrap The HTTP token's wrap data.
1018 @retval EFI_SUCCESS The TCP4 protocol child is configured.
1019 @retval Others Other error as indicated.
1024 IN HTTP_PROTOCOL
*HttpInstance
,
1025 IN HTTP_TOKEN_WRAP
*Wrap
1029 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
1030 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
1031 EFI_TCP4_OPTION
*Tcp4Option
;
1033 ASSERT (HttpInstance
!= NULL
);
1036 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
1037 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
1039 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
1040 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
1041 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
1043 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
1044 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
1045 if (!Tcp4AP
->UseDefaultAddress
) {
1046 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
1047 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
1050 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
1051 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
1052 Tcp4AP
->ActiveFlag
= TRUE
;
1053 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
1055 Tcp4Option
= Tcp4CfgData
->ControlOption
;
1056 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1057 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1058 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1059 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1060 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
1061 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1062 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1063 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1064 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1065 Tcp4Option
->EnableNagle
= TRUE
;
1066 Tcp4CfgData
->ControlOption
= Tcp4Option
;
1068 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
1069 if (EFI_ERROR (Status
)) {
1070 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
1074 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1075 if (EFI_ERROR (Status
)) {
1079 Status
= HttpCreateTcpTxEvent (Wrap
);
1080 if (EFI_ERROR (Status
)) {
1084 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1090 Configure TCP6 protocol child.
1092 @param[in] HttpInstance The HTTP instance private data.
1093 @param[in] Wrap The HTTP token's wrap data.
1095 @retval EFI_SUCCESS The TCP6 protocol child is configured.
1096 @retval Others Other error as indicated.
1101 IN HTTP_PROTOCOL
*HttpInstance
,
1102 IN HTTP_TOKEN_WRAP
*Wrap
1106 EFI_TCP6_CONFIG_DATA
*Tcp6CfgData
;
1107 EFI_TCP6_ACCESS_POINT
*Tcp6Ap
;
1108 EFI_TCP6_OPTION
*Tcp6Option
;
1110 ASSERT (HttpInstance
!= NULL
);
1112 Tcp6CfgData
= &HttpInstance
->Tcp6CfgData
;
1113 ZeroMem (Tcp6CfgData
, sizeof (EFI_TCP6_CONFIG_DATA
));
1115 Tcp6CfgData
->TrafficClass
= 0;
1116 Tcp6CfgData
->HopLimit
= 255;
1117 Tcp6CfgData
->ControlOption
= &HttpInstance
->Tcp6Option
;
1119 Tcp6Ap
= &Tcp6CfgData
->AccessPoint
;
1120 Tcp6Ap
->ActiveFlag
= TRUE
;
1121 Tcp6Ap
->StationPort
= HttpInstance
->Ipv6Node
.LocalPort
;
1122 Tcp6Ap
->RemotePort
= HttpInstance
->RemotePort
;
1123 IP6_COPY_ADDRESS (&Tcp6Ap
->StationAddress
, &HttpInstance
->Ipv6Node
.LocalAddress
);
1124 IP6_COPY_ADDRESS (&Tcp6Ap
->RemoteAddress
, &HttpInstance
->RemoteIpv6Addr
);
1126 Tcp6Option
= Tcp6CfgData
->ControlOption
;
1127 Tcp6Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1128 Tcp6Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1129 Tcp6Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1130 Tcp6Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1131 Tcp6Option
->DataRetries
= HTTP_DATA_RETRIES
;
1132 Tcp6Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1133 Tcp6Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1134 Tcp6Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1135 Tcp6Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1136 Tcp6Option
->EnableNagle
= TRUE
;
1138 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, Tcp6CfgData
);
1139 if (EFI_ERROR (Status
)) {
1140 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp6 - %r\n", Status
));
1144 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1145 if (EFI_ERROR (Status
)) {
1149 Status
= HttpCreateTcpTxEvent (Wrap
);
1150 if (EFI_ERROR (Status
)) {
1154 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1161 Check existing TCP connection, if in error state, recover TCP4 connection.
1163 @param[in] HttpInstance The HTTP instance private data.
1165 @retval EFI_SUCCESS The TCP connection is established.
1166 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1167 @retval Others Other error as indicated.
1172 IN HTTP_PROTOCOL
*HttpInstance
1176 EFI_TCP4_CONNECTION_STATE Tcp4State
;
1179 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp4
== NULL
) {
1180 return EFI_NOT_READY
;
1183 Status
= HttpInstance
->Tcp4
->GetModeData(
1191 if (EFI_ERROR(Status
)){
1192 DEBUG ((EFI_D_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
1196 if (Tcp4State
== Tcp4StateEstablished
) {
1198 } else if (Tcp4State
> Tcp4StateEstablished
) {
1199 HttpCloseConnection(HttpInstance
);
1202 return HttpCreateConnection (HttpInstance
);
1206 Check existing TCP connection, if in error state, recover TCP6 connection.
1208 @param[in] HttpInstance The HTTP instance private data.
1210 @retval EFI_SUCCESS The TCP connection is established.
1211 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1212 @retval Others Other error as indicated.
1217 IN HTTP_PROTOCOL
*HttpInstance
1221 EFI_TCP6_CONNECTION_STATE Tcp6State
;
1223 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp6
== NULL
) {
1224 return EFI_NOT_READY
;
1227 Status
= HttpInstance
->Tcp6
->GetModeData (
1236 if (EFI_ERROR(Status
)){
1237 DEBUG ((EFI_D_ERROR
, "Tcp6 GetModeData fail - %x\n", Status
));
1241 if (Tcp6State
== Tcp6StateEstablished
) {
1243 } else if (Tcp6State
> Tcp6StateEstablished
) {
1244 HttpCloseConnection(HttpInstance
);
1247 return HttpCreateConnection (HttpInstance
);
1251 Initialize TCP related data.
1253 @param[in] HttpInstance The HTTP instance private data.
1254 @param[in] Wrap The HTTP token's wrap data.
1255 @param[in] Configure The Flag indicates whether the first time to initialize Tcp.
1257 @retval EFI_SUCCESS The initialization of TCP instance is done.
1258 @retval Others Other error as indicated.
1263 IN HTTP_PROTOCOL
*HttpInstance
,
1264 IN HTTP_TOKEN_WRAP
*Wrap
,
1265 IN BOOLEAN Configure
1269 ASSERT (HttpInstance
!= NULL
);
1271 if (!HttpInstance
->LocalAddressIsIPv6
) {
1273 // Configure TCP instance.
1276 Status
= HttpConfigureTcp4 (HttpInstance
, Wrap
);
1277 if (EFI_ERROR (Status
)) {
1285 Status
= HttpConnectTcp4 (HttpInstance
);
1286 if (EFI_ERROR (Status
)) {
1291 // Configure TCP instance.
1294 Status
= HttpConfigureTcp6 (HttpInstance
, Wrap
);
1295 if (EFI_ERROR (Status
)) {
1303 Status
= HttpConnectTcp6 (HttpInstance
);
1304 if (EFI_ERROR (Status
)) {
1314 Send the HTTP message through TCP4 or TCP6.
1316 @param[in] HttpInstance The HTTP instance private data.
1317 @param[in] Wrap The HTTP token's wrap data.
1318 @param[in] TxString Buffer containing the HTTP message string.
1319 @param[in] TxStringLen Length of the HTTP message string in bytes.
1321 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1322 @retval Others Other error as indicated.
1327 IN HTTP_PROTOCOL
*HttpInstance
,
1328 IN HTTP_TOKEN_WRAP
*Wrap
,
1330 IN UINTN TxStringLen
1334 EFI_TCP4_IO_TOKEN
*Tx4Token
;
1335 EFI_TCP4_PROTOCOL
*Tcp4
;
1336 EFI_TCP6_IO_TOKEN
*Tx6Token
;
1337 EFI_TCP6_PROTOCOL
*Tcp6
;
1339 if (!HttpInstance
->LocalAddressIsIPv6
) {
1340 Tcp4
= HttpInstance
->Tcp4
;
1341 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1343 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1344 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1345 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1346 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1348 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1349 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1350 if (EFI_ERROR (Status
)) {
1351 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1356 Tcp6
= HttpInstance
->Tcp6
;
1357 Tx6Token
= &Wrap
->TcpWrap
.Tx6Token
;
1359 Tx6Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1360 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1361 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1362 Tx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1364 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1365 Status
= Tcp6
->Transmit (Tcp6
, Tx6Token
);
1366 if (EFI_ERROR (Status
)) {
1367 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1377 Translate the status code in HTTP message to EFI_HTTP_STATUS_CODE defined
1378 in UEFI 2.5 specification.
1380 @param[in] StatusCode The status code value in HTTP message.
1382 @return Value defined in EFI_HTTP_STATUS_CODE .
1385 EFI_HTTP_STATUS_CODE
1386 HttpMappingToStatusCode (
1390 switch (StatusCode
) {
1392 return HTTP_STATUS_100_CONTINUE
;
1394 return HTTP_STATUS_101_SWITCHING_PROTOCOLS
;
1396 return HTTP_STATUS_200_OK
;
1398 return HTTP_STATUS_201_CREATED
;
1400 return HTTP_STATUS_202_ACCEPTED
;
1402 return HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION
;
1404 return HTTP_STATUS_204_NO_CONTENT
;
1406 return HTTP_STATUS_205_RESET_CONTENT
;
1408 return HTTP_STATUS_206_PARTIAL_CONTENT
;
1410 return HTTP_STATUS_300_MULTIPLE_CHIOCES
;
1412 return HTTP_STATUS_301_MOVED_PERMANENTLY
;
1414 return HTTP_STATUS_302_FOUND
;
1416 return HTTP_STATUS_303_SEE_OTHER
;
1418 return HTTP_STATUS_304_NOT_MODIFIED
;
1420 return HTTP_STATUS_305_USE_PROXY
;
1422 return HTTP_STATUS_307_TEMPORARY_REDIRECT
;
1424 return HTTP_STATUS_400_BAD_REQUEST
;
1426 return HTTP_STATUS_401_UNAUTHORIZED
;
1428 return HTTP_STATUS_402_PAYMENT_REQUIRED
;
1430 return HTTP_STATUS_403_FORBIDDEN
;
1432 return HTTP_STATUS_404_NOT_FOUND
;
1434 return HTTP_STATUS_405_METHOD_NOT_ALLOWED
;
1436 return HTTP_STATUS_406_NOT_ACCEPTABLE
;
1438 return HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED
;
1440 return HTTP_STATUS_408_REQUEST_TIME_OUT
;
1442 return HTTP_STATUS_409_CONFLICT
;
1444 return HTTP_STATUS_410_GONE
;
1446 return HTTP_STATUS_411_LENGTH_REQUIRED
;
1448 return HTTP_STATUS_412_PRECONDITION_FAILED
;
1450 return HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE
;
1452 return HTTP_STATUS_414_REQUEST_URI_TOO_LARGE
;
1454 return HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE
;
1456 return HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED
;
1458 return HTTP_STATUS_417_EXPECTATION_FAILED
;
1460 return HTTP_STATUS_500_INTERNAL_SERVER_ERROR
;
1462 return HTTP_STATUS_501_NOT_IMPLEMENTED
;
1464 return HTTP_STATUS_502_BAD_GATEWAY
;
1466 return HTTP_STATUS_503_SERVICE_UNAVAILABLE
;
1468 return HTTP_STATUS_504_GATEWAY_TIME_OUT
;
1470 return HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED
;
1473 return HTTP_STATUS_UNSUPPORTED_STATUS
;
1478 Check whether the user's token or event has already
1479 been enqueue on HTTP Tx or Rx Token list.
1481 @param[in] Map The container of either user's transmit or receive
1483 @param[in] Item Current item to check against.
1484 @param[in] Context The Token to check againist.
1486 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1487 @retval EFI_SUCCESS The current item isn't the same token/event as the
1495 IN NET_MAP_ITEM
*Item
,
1499 EFI_HTTP_TOKEN
*Token
;
1500 EFI_HTTP_TOKEN
*TokenInItem
;
1502 Token
= (EFI_HTTP_TOKEN
*) Context
;
1503 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
1505 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
1506 return EFI_ACCESS_DENIED
;
1513 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1515 @param[in] Map The container of Tx4Token or Tx6Token.
1516 @param[in] Item Current item to check against.
1517 @param[in] Context The Token to check againist.
1519 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1520 @retval EFI_SUCCESS The HTTP message has been sent out.
1527 IN NET_MAP_ITEM
*Item
,
1531 HTTP_TOKEN_WRAP
*ValueInItem
;
1533 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1535 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
1536 return EFI_NOT_READY
;
1543 Transmit the HTTP mssage by processing the associated HTTP token.
1545 @param[in] Map The container of Tx4Token or Tx6Token.
1546 @param[in] Item Current item to check against.
1547 @param[in] Context The Token to check againist.
1549 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1550 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1558 IN NET_MAP_ITEM
*Item
,
1562 HTTP_TOKEN_WRAP
*ValueInItem
;
1567 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1568 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1573 // Parse the URI of the remote host.
1575 Url
= AllocatePool (StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1);
1577 return EFI_OUT_OF_RESOURCES
;
1580 UnicodeStrToAsciiStr (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
);
1583 // Create request message.
1585 RequestStr
= HttpGenRequestString (
1586 ValueInItem
->HttpInstance
,
1587 ValueInItem
->HttpToken
->Message
,
1591 if (RequestStr
== NULL
) {
1592 return EFI_OUT_OF_RESOURCES
;
1596 // Transmit the request message.
1598 Status
= HttpTransmitTcp (
1599 ValueInItem
->HttpInstance
,
1601 (UINT8
*) RequestStr
,
1602 AsciiStrLen (RequestStr
)
1604 FreePool (RequestStr
);
1609 Receive the HTTP response by processing the associated HTTP token.
1611 @param[in] Map The container of Rx4Token or Rx6Token.
1612 @param[in] Item Current item to check against.
1613 @param[in] Context The Token to check againist.
1615 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1617 @retval Others Other error as indicated.
1624 IN NET_MAP_ITEM
*Item
,
1629 // Process the queued HTTP response.
1631 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1635 Receive the HTTP header by processing the associated HTTP token.
1637 @param[in] HttpInstance The HTTP instance private data.
1638 @param[in, out] SizeofHeaders The HTTP header length.
1639 @param[in, out] BufferSize The size of buffer to cacahe the header message.
1641 @retval EFI_SUCCESS The HTTP header is received.
1642 @retval Others Other errors as indicated.
1646 HttpTcpReceiveHeader (
1647 IN HTTP_PROTOCOL
*HttpInstance
,
1648 IN OUT UINTN
*SizeofHeaders
,
1649 IN OUT UINTN
*BufferSize
1653 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1654 EFI_TCP4_PROTOCOL
*Tcp4
;
1655 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1656 EFI_TCP6_PROTOCOL
*Tcp6
;
1657 CHAR8
**EndofHeader
;
1658 CHAR8
**HttpHeaders
;
1661 ASSERT (HttpInstance
!= NULL
);
1663 EndofHeader
= HttpInstance
->EndofHeader
;
1664 HttpHeaders
= HttpInstance
->HttpHeaders
;
1665 Tcp4
= HttpInstance
->Tcp4
;
1666 Tcp6
= HttpInstance
->Tcp6
;
1671 if (HttpInstance
->LocalAddressIsIPv6
) {
1672 ASSERT (Tcp6
!= NULL
);
1674 ASSERT (Tcp4
!= NULL
);
1677 if (!HttpInstance
->LocalAddressIsIPv6
) {
1678 Rx4Token
= &HttpInstance
->Rx4Token
;
1679 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1680 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1681 Status
= EFI_OUT_OF_RESOURCES
;
1686 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1688 while (*EndofHeader
== NULL
) {
1689 HttpInstance
->IsRxDone
= FALSE
;
1690 Rx4Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1691 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1692 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1693 if (EFI_ERROR (Status
)) {
1694 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1698 while (!HttpInstance
->IsRxDone
) {
1702 Status
= Rx4Token
->CompletionToken
.Status
;
1703 if (EFI_ERROR (Status
)) {
1708 // Append the response string.
1710 *BufferSize
= (*SizeofHeaders
) + Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1711 Buffer
= AllocateZeroPool (*BufferSize
);
1712 if (Buffer
== NULL
) {
1713 Status
= EFI_OUT_OF_RESOURCES
;
1717 if (*HttpHeaders
!= NULL
) {
1718 CopyMem (Buffer
, *HttpHeaders
, (*SizeofHeaders
));
1719 FreePool (*HttpHeaders
);
1723 Buffer
+ (*SizeofHeaders
),
1724 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
,
1725 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
1727 *HttpHeaders
= Buffer
;
1728 *SizeofHeaders
= *BufferSize
;
1731 // Check whether we received end of HTTP headers.
1733 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1735 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1736 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1739 Rx6Token
= &HttpInstance
->Rx6Token
;
1740 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1741 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1742 Status
= EFI_OUT_OF_RESOURCES
;
1747 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1749 while (*EndofHeader
== NULL
) {
1750 HttpInstance
->IsRxDone
= FALSE
;
1751 Rx6Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1752 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1753 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1754 if (EFI_ERROR (Status
)) {
1755 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1759 while (!HttpInstance
->IsRxDone
) {
1763 Status
= Rx6Token
->CompletionToken
.Status
;
1764 if (EFI_ERROR (Status
)) {
1769 // Append the response string.
1771 *BufferSize
= (*SizeofHeaders
) + Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1772 Buffer
= AllocateZeroPool (*BufferSize
);
1773 if (Buffer
== NULL
) {
1774 Status
= EFI_OUT_OF_RESOURCES
;
1778 if (*HttpHeaders
!= NULL
) {
1779 CopyMem (Buffer
, *HttpHeaders
, (*SizeofHeaders
));
1780 FreePool (*HttpHeaders
);
1784 Buffer
+ (*SizeofHeaders
),
1785 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
,
1786 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
1788 *HttpHeaders
= Buffer
;
1789 *SizeofHeaders
= *BufferSize
;
1792 // Check whether we received end of HTTP headers.
1794 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1797 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1798 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1802 // Skip the CRLF after the HTTP headers.
1804 *EndofHeader
= *EndofHeader
+ AsciiStrLen (HTTP_END_OF_HDR_STR
);
1810 Receive the HTTP body by processing the associated HTTP token.
1812 @param[in] Wrap The HTTP token's wrap data.
1813 @param[in] HttpMsg The HTTP message data.
1815 @retval EFI_SUCCESS The HTTP body is received.
1816 @retval Others Other error as indicated.
1820 HttpTcpReceiveBody (
1821 IN HTTP_TOKEN_WRAP
*Wrap
,
1822 IN EFI_HTTP_MESSAGE
*HttpMsg
1826 HTTP_PROTOCOL
*HttpInstance
;
1827 EFI_TCP6_PROTOCOL
*Tcp6
;
1828 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1829 EFI_TCP4_PROTOCOL
*Tcp4
;
1830 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1832 HttpInstance
= Wrap
->HttpInstance
;
1833 Tcp4
= HttpInstance
->Tcp4
;
1834 Tcp6
= HttpInstance
->Tcp6
;
1839 if (HttpInstance
->LocalAddressIsIPv6
) {
1840 ASSERT (Tcp6
!= NULL
);
1842 ASSERT (Tcp4
!= NULL
);
1845 if (HttpInstance
->LocalAddressIsIPv6
) {
1846 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
1847 Rx6Token
->Packet
.RxData
->DataLength
= (UINT32
) HttpMsg
->BodyLength
;
1848 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) HttpMsg
->BodyLength
;
1849 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
1850 Rx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1852 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1853 if (EFI_ERROR (Status
)) {
1854 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1859 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
1860 Rx4Token
->Packet
.RxData
->DataLength
= (UINT32
) HttpMsg
->BodyLength
;
1861 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) HttpMsg
->BodyLength
;
1862 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
1864 Rx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1865 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1866 if (EFI_ERROR (Status
)) {
1867 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1877 Clean up Tcp Tokens while the Tcp transmission error occurs.
1879 @param[in] Wrap Pointer to HTTP token's wrap data.
1883 HttpTcpTokenCleanup (
1884 IN HTTP_TOKEN_WRAP
*Wrap
1887 HTTP_PROTOCOL
*HttpInstance
;
1888 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1889 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1891 ASSERT (Wrap
!= NULL
);
1892 HttpInstance
= Wrap
->HttpInstance
;
1896 if (HttpInstance
->LocalAddressIsIPv6
) {
1897 if (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
!= NULL
) {
1898 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
1901 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
1902 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1903 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1904 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1908 if (HttpInstance
->Rx6Token
.CompletionToken
.Event
!= NULL
) {
1909 gBS
->CloseEvent (HttpInstance
->Rx6Token
.CompletionToken
.Event
);
1910 HttpInstance
->Rx6Token
.CompletionToken
.Event
= NULL
;
1913 Rx6Token
= &HttpInstance
->Rx6Token
;
1914 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1915 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1916 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1920 if (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
!= NULL
) {
1921 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
1923 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
1924 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1925 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1926 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1930 if (HttpInstance
->Rx4Token
.CompletionToken
.Event
!= NULL
) {
1931 gBS
->CloseEvent (HttpInstance
->Rx4Token
.CompletionToken
.Event
);
1932 HttpInstance
->Rx4Token
.CompletionToken
.Event
= NULL
;
1935 Rx4Token
= &HttpInstance
->Rx4Token
;
1936 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1937 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1938 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1945 Generate HTTP request string.
1947 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
1948 @param[in] Message Pointer to storage containing HTTP message data.
1949 @param[in] Url The URL of a remote host.
1951 @return Pointer to the created HTTP request string.
1952 @return NULL if any error occured.
1956 HttpGenRequestString (
1957 IN HTTP_PROTOCOL
*HttpInstance
,
1958 IN EFI_HTTP_MESSAGE
*Message
,
1970 EFI_HTTP_HEADER
**AppendList
;
1973 ASSERT (HttpInstance
!= NULL
);
1974 ASSERT (Message
!= NULL
);
1976 DEBUG ((EFI_D_ERROR
, "HttpMethod - %x\n", Message
->Data
.Request
->Method
));
1986 AppendList
= AllocateZeroPool (sizeof (EFI_HTTP_HEADER
*) * (Message
->HeaderCount
));
1987 if (AppendList
== NULL
) {
1991 for(Index
= 0; Index
< Message
->HeaderCount
; Index
++){
1992 AppendList
[Index
] = &Message
->Headers
[Index
];
1996 // Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.
1998 if (mHttpUtilities
== NULL
) {
2003 // Build raw unformatted HTTP headers.
2005 Status
= mHttpUtilities
->Build (
2011 Message
->HeaderCount
,
2016 FreePool (AppendList
);
2017 if (EFI_ERROR (Status
) || HttpHdr
== NULL
) {
2022 // Calculate HTTP message length.
2024 MsgSize
= Message
->BodyLength
+ HTTP_MAXIMUM_METHOD_LEN
+ AsciiStrLen (Url
) +
2025 AsciiStrLen (HTTP_VERSION_CRLF_STR
) + HttpHdrSize
;
2026 Request
= AllocateZeroPool (MsgSize
);
2027 if (Request
== NULL
) {
2031 RequestPtr
= Request
;
2033 // Construct header request
2035 switch (Message
->Data
.Request
->Method
) {
2037 StrLength
= sizeof (HTTP_GET_STR
) - 1;
2038 CopyMem (RequestPtr
, HTTP_GET_STR
, StrLength
);
2039 RequestPtr
+= StrLength
;
2041 case HttpMethodHead
:
2042 StrLength
= sizeof (HTTP_HEAD_STR
) - 1;
2043 CopyMem (RequestPtr
, HTTP_HEAD_STR
, StrLength
);
2044 RequestPtr
+= StrLength
;
2051 StrLength
= AsciiStrLen (Url
);
2052 CopyMem (RequestPtr
, Url
, StrLength
);
2053 RequestPtr
+= StrLength
;
2055 StrLength
= sizeof (HTTP_VERSION_CRLF_STR
) - 1;
2056 CopyMem (RequestPtr
, HTTP_VERSION_CRLF_STR
, StrLength
);
2057 RequestPtr
+= StrLength
;
2062 CopyMem (RequestPtr
, HttpHdr
, HttpHdrSize
);
2063 RequestPtr
+= HttpHdrSize
;
2068 if (Message
->Body
!= NULL
) {
2069 CopyMem (RequestPtr
, Message
->Body
, Message
->BodyLength
);
2070 RequestPtr
+= Message
->BodyLength
;
2082 if (Request
!= NULL
) {
2089 if (HttpHdr
!= NULL
) {
2093 return (CHAR8
*) Request
;