2 Miscellaneous routines for HttpDxe driver.
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "HttpDriver.h"
19 The common notify function used in HTTP driver.
21 @param[in] Event The event signaled.
22 @param[in] Context The context.
32 if ((Event
== NULL
) || (Context
== NULL
)) {
36 *((BOOLEAN
*) Context
) = TRUE
;
40 The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().
42 @param[in] Context The context.
47 HttpTcpTransmitNotifyDpc (
51 HTTP_TOKEN_WRAP
*Wrap
;
52 HTTP_PROTOCOL
*HttpInstance
;
54 if (Context
== NULL
) {
58 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
59 HttpInstance
= Wrap
->HttpInstance
;
61 if (!HttpInstance
->LocalAddressIsIPv6
) {
62 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Tx4Token
.CompletionToken
.Status
;
63 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
68 if (Wrap
->TcpWrap
.Tx4Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
69 FreePool (Wrap
->TcpWrap
.Tx4Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
);
72 if (Wrap
->TcpWrap
.Tx4Token
.CompletionToken
.Event
!= NULL
) {
73 gBS
->CloseEvent (Wrap
->TcpWrap
.Tx4Token
.CompletionToken
.Event
);
77 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Status
;
78 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
83 if (Wrap
->TcpWrap
.Tx6Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
84 FreePool (Wrap
->TcpWrap
.Tx6Token
.Packet
.TxData
->FragmentTable
[0].FragmentBuffer
);
87 if (Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Event
!= NULL
) {
88 gBS
->CloseEvent (Wrap
->TcpWrap
.Tx6Token
.CompletionToken
.Event
);
93 Wrap
->TcpWrap
.IsTxDone
= TRUE
;
96 // Check pending TxTokens and sent out.
98 NetMapIterate (&Wrap
->HttpInstance
->TxTokens
, HttpTcpTransmit
, NULL
);
103 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.
105 @param Event The receive event delivered to TCP for transmit.
106 @param Context Context for the callback.
111 HttpTcpTransmitNotify (
117 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
119 QueueDpc (TPL_CALLBACK
, HttpTcpTransmitNotifyDpc
, Context
);
123 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().
125 @param[in] Context The context.
130 HttpTcpReceiveNotifyDpc (
134 HTTP_TOKEN_WRAP
*Wrap
;
138 HTTP_PROTOCOL
*HttpInstance
;
141 if (Context
== NULL
) {
145 Wrap
= (HTTP_TOKEN_WRAP
*) Context
;
146 HttpInstance
= Wrap
->HttpInstance
;
147 UsingIpv6
= HttpInstance
->LocalAddressIsIPv6
;
150 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
151 Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
= NULL
;
153 if (EFI_ERROR (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
)) {
154 DEBUG ((EFI_D_ERROR
, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
));
155 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
156 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
158 Item
= NetMapFindKey (&HttpInstance
->RxTokens
, Wrap
->HttpToken
);
160 NetMapRemoveItem (&HttpInstance
->RxTokens
, Item
, NULL
);
170 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
171 Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
= NULL
;
173 if (EFI_ERROR (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
)) {
174 DEBUG ((EFI_D_ERROR
, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
));
175 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
176 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
178 Item
= NetMapFindKey (&HttpInstance
->RxTokens
, Wrap
->HttpToken
);
180 NetMapRemoveItem (&HttpInstance
->RxTokens
, Item
, NULL
);
191 // Check whether we receive a complete HTTP message.
193 ASSERT (HttpInstance
->MsgParser
!= NULL
);
195 Length
= (UINTN
) Wrap
->TcpWrap
.Rx6Data
.FragmentTable
[0].FragmentLength
;
197 Length
= (UINTN
) Wrap
->TcpWrap
.Rx4Data
.FragmentTable
[0].FragmentLength
;
201 // Record the CallbackData data.
203 HttpInstance
->CallbackData
.Wrap
= (VOID
*) Wrap
;
204 HttpInstance
->CallbackData
.ParseData
= Wrap
->HttpToken
->Message
->Body
;
205 HttpInstance
->CallbackData
.ParseDataLength
= Length
;
208 // Parse Body with CallbackData data.
210 Status
= HttpParseMessageBody (
211 HttpInstance
->MsgParser
,
213 Wrap
->HttpToken
->Message
->Body
215 if (EFI_ERROR (Status
)) {
219 if (HttpIsMessageComplete (HttpInstance
->MsgParser
)) {
221 // Free the MsgParse since we already have a full HTTP message.
223 HttpFreeMsgParser (HttpInstance
->MsgParser
);
224 HttpInstance
->MsgParser
= NULL
;
227 Wrap
->HttpToken
->Message
->BodyLength
= Length
;
228 ASSERT (HttpInstance
->CacheBody
== NULL
);
230 // We receive part of header of next HTTP msg.
232 if (HttpInstance
->NextMsg
!= NULL
) {
233 Wrap
->HttpToken
->Message
->BodyLength
= HttpInstance
->NextMsg
-
234 (CHAR8
*) Wrap
->HttpToken
->Message
->Body
;
235 HttpInstance
->CacheLen
= Length
- Wrap
->HttpToken
->Message
->BodyLength
;
236 if (HttpInstance
->CacheLen
!= 0) {
237 HttpInstance
->CacheBody
= AllocateZeroPool (HttpInstance
->CacheLen
);
238 if (HttpInstance
->CacheBody
== NULL
) {
241 CopyMem (HttpInstance
->CacheBody
, HttpInstance
->NextMsg
, HttpInstance
->CacheLen
);
242 HttpInstance
->NextMsg
= HttpInstance
->CacheBody
;
243 HttpInstance
->CacheOffset
= 0;
247 Item
= NetMapFindKey (&Wrap
->HttpInstance
->RxTokens
, Wrap
->HttpToken
);
249 NetMapRemoveItem (&Wrap
->HttpInstance
->RxTokens
, Item
, NULL
);
253 Wrap
->TcpWrap
.IsRxDone
= TRUE
;
255 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Status
;
257 Wrap
->HttpToken
->Status
= Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Status
;
261 gBS
->SignalEvent (Wrap
->HttpToken
->Event
);
264 // Check pending RxTokens and receive the HTTP message.
266 NetMapIterate (&Wrap
->HttpInstance
->RxTokens
, HttpTcpReceive
, NULL
);
273 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.
275 @param Event The receive event delivered to TCP for receive.
276 @param Context Context for the callback.
281 HttpTcpReceiveNotify (
287 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
289 QueueDpc (TPL_CALLBACK
, HttpTcpReceiveNotifyDpc
, Context
);
293 Create events for the TCP connection token and TCP close token.
295 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
297 @retval EFI_SUCCESS The events are created successfully.
298 @retval others Other error as indicated.
302 HttpCreateTcpConnCloseEvent (
303 IN HTTP_PROTOCOL
*HttpInstance
308 if (!HttpInstance
->LocalAddressIsIPv6
) {
310 // Create events for variuos asynchronous operations.
312 Status
= gBS
->CreateEvent (
316 &HttpInstance
->IsTcp4ConnDone
,
317 &HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
319 if (EFI_ERROR (Status
)) {
324 // Initialize Tcp4CloseToken
326 Status
= gBS
->CreateEvent (
330 &HttpInstance
->IsTcp4CloseDone
,
331 &HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
333 if (EFI_ERROR (Status
)) {
339 // Create events for variuos asynchronous operations.
341 Status
= gBS
->CreateEvent (
345 &HttpInstance
->IsTcp6ConnDone
,
346 &HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
348 if (EFI_ERROR (Status
)) {
353 // Initialize Tcp6CloseToken
355 Status
= gBS
->CreateEvent (
359 &HttpInstance
->IsTcp6CloseDone
,
360 &HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
362 if (EFI_ERROR (Status
)) {
373 HttpCloseTcpConnCloseEvent (HttpInstance
);
380 Close events in the TCP connection token and TCP close token.
382 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
386 HttpCloseTcpConnCloseEvent (
387 IN HTTP_PROTOCOL
*HttpInstance
390 ASSERT (HttpInstance
!= NULL
);
392 if (HttpInstance
->LocalAddressIsIPv6
) {
393 if (NULL
!= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
) {
394 gBS
->CloseEvent (HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
);
395 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Event
= NULL
;
398 if (NULL
!= HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
) {
399 gBS
->CloseEvent(HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
);
400 HttpInstance
->Tcp6CloseToken
.CompletionToken
.Event
= NULL
;
404 if (NULL
!= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
) {
405 gBS
->CloseEvent (HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
);
406 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Event
= NULL
;
409 if (NULL
!= HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
) {
410 gBS
->CloseEvent(HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
);
411 HttpInstance
->Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
418 Create event for the TCP transmit token.
420 @param[in] Wrap Point to HTTP token's wrap data.
422 @retval EFI_SUCCESS The events is created successfully.
423 @retval others Other error as indicated.
427 HttpCreateTcpTxEvent (
428 IN HTTP_TOKEN_WRAP
*Wrap
432 HTTP_PROTOCOL
*HttpInstance
;
433 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
435 HttpInstance
= Wrap
->HttpInstance
;
436 TcpWrap
= &Wrap
->TcpWrap
;
438 if (!HttpInstance
->LocalAddressIsIPv6
) {
439 Status
= gBS
->CreateEvent (
442 HttpTcpTransmitNotify
,
444 &TcpWrap
->Tx4Token
.CompletionToken
.Event
446 if (EFI_ERROR (Status
)) {
450 TcpWrap
->Tx4Data
.Push
= TRUE
;
451 TcpWrap
->Tx4Data
.Urgent
= FALSE
;
452 TcpWrap
->Tx4Data
.FragmentCount
= 1;
453 TcpWrap
->Tx4Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx4Data
;
454 TcpWrap
->Tx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
457 Status
= gBS
->CreateEvent (
460 HttpTcpTransmitNotify
,
462 &TcpWrap
->Tx6Token
.CompletionToken
.Event
464 if (EFI_ERROR (Status
)) {
468 TcpWrap
->Tx6Data
.Push
= TRUE
;
469 TcpWrap
->Tx6Data
.Urgent
= FALSE
;
470 TcpWrap
->Tx6Data
.FragmentCount
= 1;
471 TcpWrap
->Tx6Token
.Packet
.TxData
= &Wrap
->TcpWrap
.Tx6Data
;
472 TcpWrap
->Tx6Token
.CompletionToken
.Status
=EFI_NOT_READY
;
480 Create event for the TCP receive token which is used to receive HTTP header.
482 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
484 @retval EFI_SUCCESS The events is created successfully.
485 @retval others Other error as indicated.
489 HttpCreateTcpRxEventForHeader (
490 IN HTTP_PROTOCOL
*HttpInstance
495 if (!HttpInstance
->LocalAddressIsIPv6
) {
496 Status
= gBS
->CreateEvent (
500 &HttpInstance
->IsRxDone
,
501 &HttpInstance
->Rx4Token
.CompletionToken
.Event
503 if (EFI_ERROR (Status
)) {
507 HttpInstance
->Rx4Data
.FragmentCount
= 1;
508 HttpInstance
->Rx4Token
.Packet
.RxData
= &HttpInstance
->Rx4Data
;
509 HttpInstance
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
512 Status
= gBS
->CreateEvent (
516 &HttpInstance
->IsRxDone
,
517 &HttpInstance
->Rx6Token
.CompletionToken
.Event
519 if (EFI_ERROR (Status
)) {
523 HttpInstance
->Rx6Data
.FragmentCount
=1;
524 HttpInstance
->Rx6Token
.Packet
.RxData
= &HttpInstance
->Rx6Data
;
525 HttpInstance
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
534 Create event for the TCP receive token which is used to receive HTTP body.
536 @param[in] Wrap Point to HTTP token's wrap data.
538 @retval EFI_SUCCESS The events is created successfully.
539 @retval others Other error as indicated.
543 HttpCreateTcpRxEvent (
544 IN HTTP_TOKEN_WRAP
*Wrap
548 HTTP_PROTOCOL
*HttpInstance
;
549 HTTP_TCP_TOKEN_WRAP
*TcpWrap
;
551 HttpInstance
= Wrap
->HttpInstance
;
552 TcpWrap
= &Wrap
->TcpWrap
;
553 if (!HttpInstance
->LocalAddressIsIPv6
) {
554 Status
= gBS
->CreateEvent (
557 HttpTcpReceiveNotify
,
559 &TcpWrap
->Rx4Token
.CompletionToken
.Event
561 if (EFI_ERROR (Status
)) {
565 TcpWrap
->Rx4Data
.FragmentCount
= 1;
566 TcpWrap
->Rx4Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx4Data
;
567 TcpWrap
->Rx4Token
.CompletionToken
.Status
= EFI_NOT_READY
;
570 Status
= gBS
->CreateEvent (
573 HttpTcpReceiveNotify
,
575 &TcpWrap
->Rx6Token
.CompletionToken
.Event
577 if (EFI_ERROR (Status
)) {
581 TcpWrap
->Rx6Data
.FragmentCount
= 1;
582 TcpWrap
->Rx6Token
.Packet
.RxData
= &Wrap
->TcpWrap
.Rx6Data
;
583 TcpWrap
->Rx6Token
.CompletionToken
.Status
= EFI_NOT_READY
;
590 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.
592 @param[in] Wrap Pointer to HTTP token's wrap data.
596 HttpCloseTcpRxEvent (
597 IN HTTP_TOKEN_WRAP
*Wrap
600 HTTP_PROTOCOL
*HttpInstance
;
602 ASSERT (Wrap
!= NULL
);
603 HttpInstance
= Wrap
->HttpInstance
;
605 if (HttpInstance
->LocalAddressIsIPv6
) {
606 if (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
!= NULL
) {
607 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx6Token
.CompletionToken
.Event
);
610 if (HttpInstance
->Rx6Token
.CompletionToken
.Event
!= NULL
) {
611 gBS
->CloseEvent (HttpInstance
->Rx6Token
.CompletionToken
.Event
);
612 HttpInstance
->Rx6Token
.CompletionToken
.Event
= NULL
;
615 if (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
!= NULL
) {
616 gBS
->CloseEvent (Wrap
->TcpWrap
.Rx4Token
.CompletionToken
.Event
);
619 if (HttpInstance
->Rx4Token
.CompletionToken
.Event
!= NULL
) {
620 gBS
->CloseEvent (HttpInstance
->Rx4Token
.CompletionToken
.Event
);
621 HttpInstance
->Rx4Token
.CompletionToken
.Event
= NULL
;
627 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.
629 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
630 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.
632 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
633 @retval Others Other error as indicated.
638 IN OUT HTTP_PROTOCOL
*HttpInstance
,
646 ASSERT (HttpInstance
!= NULL
);
647 UsingIpv6
= IpVersion
;
651 // Create TCP4 child.
653 Status
= NetLibCreateServiceChild (
654 HttpInstance
->Service
->ControllerHandle
,
655 HttpInstance
->Service
->Ip4DriverBindingHandle
,
656 &gEfiTcp4ServiceBindingProtocolGuid
,
657 &HttpInstance
->Tcp4ChildHandle
660 if (EFI_ERROR (Status
)) {
664 Status
= gBS
->OpenProtocol (
665 HttpInstance
->Tcp4ChildHandle
,
666 &gEfiTcp4ProtocolGuid
,
667 (VOID
**) &Interface
,
668 HttpInstance
->Service
->Ip4DriverBindingHandle
,
669 HttpInstance
->Service
->ControllerHandle
,
670 EFI_OPEN_PROTOCOL_BY_DRIVER
673 if (EFI_ERROR (Status
)) {
677 Status
= gBS
->OpenProtocol (
678 HttpInstance
->Tcp4ChildHandle
,
679 &gEfiTcp4ProtocolGuid
,
680 (VOID
**) &HttpInstance
->Tcp4
,
681 HttpInstance
->Service
->Ip4DriverBindingHandle
,
682 HttpInstance
->Handle
,
683 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
685 if (EFI_ERROR(Status
)) {
689 Status
= gBS
->OpenProtocol (
690 HttpInstance
->Service
->Tcp4ChildHandle
,
691 &gEfiTcp4ProtocolGuid
,
692 (VOID
**) &Interface
,
693 HttpInstance
->Service
->Ip4DriverBindingHandle
,
694 HttpInstance
->Handle
,
695 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
697 if (EFI_ERROR(Status
)) {
702 // Create TCP6 Child.
704 Status
= NetLibCreateServiceChild (
705 HttpInstance
->Service
->ControllerHandle
,
706 HttpInstance
->Service
->Ip6DriverBindingHandle
,
707 &gEfiTcp6ServiceBindingProtocolGuid
,
708 &HttpInstance
->Tcp6ChildHandle
711 if (EFI_ERROR (Status
)) {
715 Status
= gBS
->OpenProtocol (
716 HttpInstance
->Tcp6ChildHandle
,
717 &gEfiTcp6ProtocolGuid
,
718 (VOID
**) &Interface
,
719 HttpInstance
->Service
->Ip6DriverBindingHandle
,
720 HttpInstance
->Service
->ControllerHandle
,
721 EFI_OPEN_PROTOCOL_BY_DRIVER
724 if (EFI_ERROR (Status
)) {
728 Status
= gBS
->OpenProtocol (
729 HttpInstance
->Tcp6ChildHandle
,
730 &gEfiTcp6ProtocolGuid
,
731 (VOID
**) &HttpInstance
->Tcp6
,
732 HttpInstance
->Service
->Ip6DriverBindingHandle
,
733 HttpInstance
->Handle
,
734 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
737 if (EFI_ERROR(Status
)) {
741 Status
= gBS
->OpenProtocol (
742 HttpInstance
->Service
->Tcp6ChildHandle
,
743 &gEfiTcp6ProtocolGuid
,
744 (VOID
**) &Interface
,
745 HttpInstance
->Service
->Ip6DriverBindingHandle
,
746 HttpInstance
->Handle
,
747 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
750 if (EFI_ERROR(Status
)) {
755 HttpInstance
->Url
= AllocateZeroPool (HTTP_URL_BUFFER_LEN
);
756 if (HttpInstance
->Url
== NULL
) {
757 Status
= EFI_OUT_OF_RESOURCES
;
765 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
767 HttpInstance
->Tcp4ChildHandle
,
768 &gEfiTcp4ProtocolGuid
,
769 HttpInstance
->Service
->Ip4DriverBindingHandle
,
770 HttpInstance
->Service
->ControllerHandle
774 HttpInstance
->Tcp4ChildHandle
,
775 &gEfiTcp4ProtocolGuid
,
776 HttpInstance
->Service
->Ip4DriverBindingHandle
,
780 NetLibDestroyServiceChild (
781 HttpInstance
->Service
->ControllerHandle
,
782 HttpInstance
->Service
->Ip4DriverBindingHandle
,
783 &gEfiTcp4ServiceBindingProtocolGuid
,
784 HttpInstance
->Tcp4ChildHandle
788 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
790 HttpInstance
->Service
->Tcp4ChildHandle
,
791 &gEfiTcp4ProtocolGuid
,
792 HttpInstance
->Service
->Ip4DriverBindingHandle
,
797 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
799 HttpInstance
->Tcp6ChildHandle
,
800 &gEfiTcp6ProtocolGuid
,
801 HttpInstance
->Service
->Ip6DriverBindingHandle
,
802 HttpInstance
->Service
->ControllerHandle
806 HttpInstance
->Tcp6ChildHandle
,
807 &gEfiTcp6ProtocolGuid
,
808 HttpInstance
->Service
->Ip6DriverBindingHandle
,
812 NetLibDestroyServiceChild (
813 HttpInstance
->Service
->ControllerHandle
,
814 HttpInstance
->Service
->Ip6DriverBindingHandle
,
815 &gEfiTcp6ServiceBindingProtocolGuid
,
816 HttpInstance
->Tcp6ChildHandle
820 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
822 HttpInstance
->Service
->Tcp6ChildHandle
,
823 &gEfiTcp6ProtocolGuid
,
824 HttpInstance
->Service
->Ip6DriverBindingHandle
,
829 return EFI_UNSUPPORTED
;
834 Clean up the HTTP child, release all the resources used by it.
836 @param[in] HttpInstance The HTTP child to clean up.
841 IN HTTP_PROTOCOL
*HttpInstance
844 HttpCloseConnection (HttpInstance
);
846 HttpCloseTcpConnCloseEvent (HttpInstance
);
848 if (HttpInstance
->TimeoutEvent
!= NULL
) {
849 gBS
->CloseEvent (HttpInstance
->TimeoutEvent
);
850 HttpInstance
->TimeoutEvent
= NULL
;
853 if (HttpInstance
->CacheBody
!= NULL
) {
854 FreePool (HttpInstance
->CacheBody
);
855 HttpInstance
->CacheBody
= NULL
;
856 HttpInstance
->NextMsg
= NULL
;
859 if (HttpInstance
->RemoteHost
!= NULL
) {
860 FreePool (HttpInstance
->RemoteHost
);
861 HttpInstance
->RemoteHost
= NULL
;
864 if (HttpInstance
->MsgParser
!= NULL
) {
865 HttpFreeMsgParser (HttpInstance
->MsgParser
);
866 HttpInstance
->MsgParser
= NULL
;
869 if (HttpInstance
->Url
!= NULL
) {
870 FreePool (HttpInstance
->Url
);
871 HttpInstance
->Url
= NULL
;
874 NetMapClean (&HttpInstance
->TxTokens
);
875 NetMapClean (&HttpInstance
->RxTokens
);
877 if (HttpInstance
->TlsSb
!= NULL
&& HttpInstance
->TlsChildHandle
!= NULL
) {
879 // Destroy the TLS instance.
881 HttpInstance
->TlsSb
->DestroyChild (HttpInstance
->TlsSb
, HttpInstance
->TlsChildHandle
);
884 if (HttpInstance
->Tcp4ChildHandle
!= NULL
) {
886 HttpInstance
->Tcp4ChildHandle
,
887 &gEfiTcp4ProtocolGuid
,
888 HttpInstance
->Service
->Ip4DriverBindingHandle
,
889 HttpInstance
->Service
->ControllerHandle
893 HttpInstance
->Tcp4ChildHandle
,
894 &gEfiTcp4ProtocolGuid
,
895 HttpInstance
->Service
->Ip4DriverBindingHandle
,
899 NetLibDestroyServiceChild (
900 HttpInstance
->Service
->ControllerHandle
,
901 HttpInstance
->Service
->Ip4DriverBindingHandle
,
902 &gEfiTcp4ServiceBindingProtocolGuid
,
903 HttpInstance
->Tcp4ChildHandle
907 if (HttpInstance
->Service
->Tcp4ChildHandle
!= NULL
) {
909 HttpInstance
->Service
->Tcp4ChildHandle
,
910 &gEfiTcp4ProtocolGuid
,
911 HttpInstance
->Service
->Ip4DriverBindingHandle
,
916 if (HttpInstance
->Tcp6ChildHandle
!= NULL
) {
918 HttpInstance
->Tcp6ChildHandle
,
919 &gEfiTcp6ProtocolGuid
,
920 HttpInstance
->Service
->Ip6DriverBindingHandle
,
921 HttpInstance
->Service
->ControllerHandle
925 HttpInstance
->Tcp6ChildHandle
,
926 &gEfiTcp6ProtocolGuid
,
927 HttpInstance
->Service
->Ip6DriverBindingHandle
,
931 NetLibDestroyServiceChild (
932 HttpInstance
->Service
->ControllerHandle
,
933 HttpInstance
->Service
->Ip6DriverBindingHandle
,
934 &gEfiTcp6ServiceBindingProtocolGuid
,
935 HttpInstance
->Tcp6ChildHandle
939 if (HttpInstance
->Service
->Tcp6ChildHandle
!= NULL
) {
941 HttpInstance
->Service
->Tcp6ChildHandle
,
942 &gEfiTcp6ProtocolGuid
,
943 HttpInstance
->Service
->Ip6DriverBindingHandle
,
948 TlsCloseTxRxEvent (HttpInstance
);
952 Establish TCP connection with HTTP server.
954 @param[in] HttpInstance The HTTP instance private data.
956 @retval EFI_SUCCESS The TCP connection is established.
957 @retval Others Other error as indicated.
961 HttpCreateConnection (
962 IN HTTP_PROTOCOL
*HttpInstance
968 // Connect to Http server
970 if (!HttpInstance
->LocalAddressIsIPv6
) {
971 HttpInstance
->IsTcp4ConnDone
= FALSE
;
972 HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
973 Status
= HttpInstance
->Tcp4
->Connect (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4ConnToken
);
974 if (EFI_ERROR (Status
)) {
975 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status
));
979 while (!HttpInstance
->IsTcp4ConnDone
) {
980 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
983 Status
= HttpInstance
->Tcp4ConnToken
.CompletionToken
.Status
;
986 HttpInstance
->IsTcp6ConnDone
= FALSE
;
987 HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
= EFI_NOT_READY
;
988 Status
= HttpInstance
->Tcp6
->Connect (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6ConnToken
);
989 if (EFI_ERROR (Status
)) {
990 DEBUG ((EFI_D_ERROR
, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status
));
994 while(!HttpInstance
->IsTcp6ConnDone
) {
995 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
998 Status
= HttpInstance
->Tcp6ConnToken
.CompletionToken
.Status
;
1001 if (!EFI_ERROR (Status
)) {
1002 HttpInstance
->State
= HTTP_STATE_TCP_CONNECTED
;
1009 Close existing TCP connection.
1011 @param[in] HttpInstance The HTTP instance private data.
1013 @retval EFI_SUCCESS The TCP connection is closed.
1014 @retval Others Other error as indicated.
1018 HttpCloseConnection (
1019 IN HTTP_PROTOCOL
*HttpInstance
1024 if (HttpInstance
->State
== HTTP_STATE_TCP_CONNECTED
) {
1026 if (HttpInstance
->LocalAddressIsIPv6
) {
1027 HttpInstance
->Tcp6CloseToken
.AbortOnClose
= TRUE
;
1028 HttpInstance
->IsTcp6CloseDone
= FALSE
;
1029 Status
= HttpInstance
->Tcp6
->Close (HttpInstance
->Tcp6
, &HttpInstance
->Tcp6CloseToken
);
1030 if (EFI_ERROR (Status
)) {
1034 while (!HttpInstance
->IsTcp6CloseDone
) {
1035 HttpInstance
->Tcp6
->Poll (HttpInstance
->Tcp6
);
1039 HttpInstance
->Tcp4CloseToken
.AbortOnClose
= TRUE
;
1040 HttpInstance
->IsTcp4CloseDone
= FALSE
;
1041 Status
= HttpInstance
->Tcp4
->Close (HttpInstance
->Tcp4
, &HttpInstance
->Tcp4CloseToken
);
1042 if (EFI_ERROR (Status
)) {
1046 while (!HttpInstance
->IsTcp4CloseDone
) {
1047 HttpInstance
->Tcp4
->Poll (HttpInstance
->Tcp4
);
1053 HttpInstance
->State
= HTTP_STATE_TCP_CLOSED
;
1058 Configure TCP4 protocol child.
1060 @param[in] HttpInstance The HTTP instance private data.
1061 @param[in] Wrap The HTTP token's wrap data.
1063 @retval EFI_SUCCESS The TCP4 protocol child is configured.
1064 @retval Others Other error as indicated.
1069 IN HTTP_PROTOCOL
*HttpInstance
,
1070 IN HTTP_TOKEN_WRAP
*Wrap
1074 EFI_TCP4_CONFIG_DATA
*Tcp4CfgData
;
1075 EFI_TCP4_ACCESS_POINT
*Tcp4AP
;
1076 EFI_TCP4_OPTION
*Tcp4Option
;
1078 ASSERT (HttpInstance
!= NULL
);
1081 Tcp4CfgData
= &HttpInstance
->Tcp4CfgData
;
1082 ZeroMem (Tcp4CfgData
, sizeof (EFI_TCP4_CONFIG_DATA
));
1084 Tcp4CfgData
->TypeOfService
= HTTP_TOS_DEAULT
;
1085 Tcp4CfgData
->TimeToLive
= HTTP_TTL_DEAULT
;
1086 Tcp4CfgData
->ControlOption
= &HttpInstance
->Tcp4Option
;
1088 Tcp4AP
= &Tcp4CfgData
->AccessPoint
;
1089 Tcp4AP
->UseDefaultAddress
= HttpInstance
->IPv4Node
.UseDefaultAddress
;
1090 if (!Tcp4AP
->UseDefaultAddress
) {
1091 IP4_COPY_ADDRESS (&Tcp4AP
->StationAddress
, &HttpInstance
->IPv4Node
.LocalAddress
);
1092 IP4_COPY_ADDRESS (&Tcp4AP
->SubnetMask
, &HttpInstance
->IPv4Node
.LocalSubnet
);
1095 Tcp4AP
->StationPort
= HttpInstance
->IPv4Node
.LocalPort
;
1096 Tcp4AP
->RemotePort
= HttpInstance
->RemotePort
;
1097 Tcp4AP
->ActiveFlag
= TRUE
;
1098 IP4_COPY_ADDRESS (&Tcp4AP
->RemoteAddress
, &HttpInstance
->RemoteAddr
);
1100 Tcp4Option
= Tcp4CfgData
->ControlOption
;
1101 Tcp4Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1102 Tcp4Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1103 Tcp4Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1104 Tcp4Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1105 Tcp4Option
->DataRetries
= HTTP_DATA_RETRIES
;
1106 Tcp4Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1107 Tcp4Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1108 Tcp4Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1109 Tcp4Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1110 Tcp4Option
->EnableNagle
= TRUE
;
1111 Tcp4CfgData
->ControlOption
= Tcp4Option
;
1113 Status
= HttpInstance
->Tcp4
->Configure (HttpInstance
->Tcp4
, Tcp4CfgData
);
1114 if (EFI_ERROR (Status
)) {
1115 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp4 - %r\n", Status
));
1119 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1120 if (EFI_ERROR (Status
)) {
1124 Status
= HttpCreateTcpTxEvent (Wrap
);
1125 if (EFI_ERROR (Status
)) {
1129 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1135 Configure TCP6 protocol child.
1137 @param[in] HttpInstance The HTTP instance private data.
1138 @param[in] Wrap The HTTP token's wrap data.
1140 @retval EFI_SUCCESS The TCP6 protocol child is configured.
1141 @retval Others Other error as indicated.
1146 IN HTTP_PROTOCOL
*HttpInstance
,
1147 IN HTTP_TOKEN_WRAP
*Wrap
1151 EFI_TCP6_CONFIG_DATA
*Tcp6CfgData
;
1152 EFI_TCP6_ACCESS_POINT
*Tcp6Ap
;
1153 EFI_TCP6_OPTION
*Tcp6Option
;
1155 ASSERT (HttpInstance
!= NULL
);
1157 Tcp6CfgData
= &HttpInstance
->Tcp6CfgData
;
1158 ZeroMem (Tcp6CfgData
, sizeof (EFI_TCP6_CONFIG_DATA
));
1160 Tcp6CfgData
->TrafficClass
= 0;
1161 Tcp6CfgData
->HopLimit
= 255;
1162 Tcp6CfgData
->ControlOption
= &HttpInstance
->Tcp6Option
;
1164 Tcp6Ap
= &Tcp6CfgData
->AccessPoint
;
1165 Tcp6Ap
->ActiveFlag
= TRUE
;
1166 Tcp6Ap
->StationPort
= HttpInstance
->Ipv6Node
.LocalPort
;
1167 Tcp6Ap
->RemotePort
= HttpInstance
->RemotePort
;
1168 IP6_COPY_ADDRESS (&Tcp6Ap
->StationAddress
, &HttpInstance
->Ipv6Node
.LocalAddress
);
1169 IP6_COPY_ADDRESS (&Tcp6Ap
->RemoteAddress
, &HttpInstance
->RemoteIpv6Addr
);
1171 Tcp6Option
= Tcp6CfgData
->ControlOption
;
1172 Tcp6Option
->ReceiveBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1173 Tcp6Option
->SendBufferSize
= HTTP_BUFFER_SIZE_DEAULT
;
1174 Tcp6Option
->MaxSynBackLog
= HTTP_MAX_SYN_BACK_LOG
;
1175 Tcp6Option
->ConnectionTimeout
= HTTP_CONNECTION_TIMEOUT
;
1176 Tcp6Option
->DataRetries
= HTTP_DATA_RETRIES
;
1177 Tcp6Option
->FinTimeout
= HTTP_FIN_TIMEOUT
;
1178 Tcp6Option
->KeepAliveProbes
= HTTP_KEEP_ALIVE_PROBES
;
1179 Tcp6Option
->KeepAliveTime
= HTTP_KEEP_ALIVE_TIME
;
1180 Tcp6Option
->KeepAliveInterval
= HTTP_KEEP_ALIVE_INTERVAL
;
1181 Tcp6Option
->EnableNagle
= TRUE
;
1183 Status
= HttpInstance
->Tcp6
->Configure (HttpInstance
->Tcp6
, Tcp6CfgData
);
1184 if (EFI_ERROR (Status
)) {
1185 DEBUG ((EFI_D_ERROR
, "HttpConfigureTcp6 - %r\n", Status
));
1189 Status
= HttpCreateTcpConnCloseEvent (HttpInstance
);
1190 if (EFI_ERROR (Status
)) {
1194 Status
= HttpCreateTcpTxEvent (Wrap
);
1195 if (EFI_ERROR (Status
)) {
1199 HttpInstance
->State
= HTTP_STATE_TCP_CONFIGED
;
1206 Check existing TCP connection, if in error state, recover TCP4 connection. Then,
1207 connect one TLS session if required.
1209 @param[in] HttpInstance The HTTP instance private data.
1211 @retval EFI_SUCCESS The TCP connection is established.
1212 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1213 @retval Others Other error as indicated.
1218 IN HTTP_PROTOCOL
*HttpInstance
1222 EFI_TCP4_CONNECTION_STATE Tcp4State
;
1225 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp4
== NULL
) {
1226 return EFI_NOT_READY
;
1229 Status
= HttpInstance
->Tcp4
->GetModeData(
1237 if (EFI_ERROR(Status
)){
1238 DEBUG ((EFI_D_ERROR
, "Tcp4 GetModeData fail - %x\n", Status
));
1242 if (Tcp4State
== Tcp4StateEstablished
) {
1244 } else if (Tcp4State
> Tcp4StateEstablished
) {
1245 HttpCloseConnection(HttpInstance
);
1248 Status
= HttpCreateConnection (HttpInstance
);
1249 if (EFI_ERROR(Status
)){
1250 DEBUG ((EFI_D_ERROR
, "Tcp4 Connection fail - %x\n", Status
));
1255 // Tls session connection.
1257 if (HttpInstance
->UseHttps
) {
1258 if (HttpInstance
->TimeoutEvent
== NULL
) {
1260 // Create TimeoutEvent for TLS connection.
1262 Status
= gBS
->CreateEvent (
1267 &HttpInstance
->TimeoutEvent
1269 if (EFI_ERROR (Status
)) {
1270 TlsCloseTxRxEvent (HttpInstance
);
1276 // Start the timer, and wait Timeout seconds for connection.
1278 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1279 if (EFI_ERROR (Status
)) {
1280 TlsCloseTxRxEvent (HttpInstance
);
1284 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1286 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1288 if (EFI_ERROR (Status
)) {
1289 TlsCloseTxRxEvent (HttpInstance
);
1298 Check existing TCP connection, if in error state, recover TCP6 connection. Then,
1299 connect one TLS session if required.
1301 @param[in] HttpInstance The HTTP instance private data.
1303 @retval EFI_SUCCESS The TCP connection is established.
1304 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1305 @retval Others Other error as indicated.
1310 IN HTTP_PROTOCOL
*HttpInstance
1314 EFI_TCP6_CONNECTION_STATE Tcp6State
;
1316 if (HttpInstance
->State
< HTTP_STATE_TCP_CONFIGED
|| HttpInstance
->Tcp6
== NULL
) {
1317 return EFI_NOT_READY
;
1320 Status
= HttpInstance
->Tcp6
->GetModeData (
1329 if (EFI_ERROR(Status
)){
1330 DEBUG ((EFI_D_ERROR
, "Tcp6 GetModeData fail - %x\n", Status
));
1334 if (Tcp6State
== Tcp6StateEstablished
) {
1336 } else if (Tcp6State
> Tcp6StateEstablished
) {
1337 HttpCloseConnection(HttpInstance
);
1340 Status
= HttpCreateConnection (HttpInstance
);
1341 if (EFI_ERROR(Status
)){
1342 DEBUG ((EFI_D_ERROR
, "Tcp6 Connection fail - %x\n", Status
));
1347 // Tls session connection.
1349 if (HttpInstance
->UseHttps
) {
1350 if (HttpInstance
->TimeoutEvent
== NULL
) {
1352 // Create TimeoutEvent for TLS connection.
1354 Status
= gBS
->CreateEvent (
1359 &HttpInstance
->TimeoutEvent
1361 if (EFI_ERROR (Status
)) {
1362 TlsCloseTxRxEvent (HttpInstance
);
1368 // Start the timer, and wait Timeout seconds for connection.
1370 Status
= gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerRelative
, HTTP_CONNECTION_TIMEOUT
* TICKS_PER_SECOND
);
1371 if (EFI_ERROR (Status
)) {
1372 TlsCloseTxRxEvent (HttpInstance
);
1376 Status
= TlsConnectSession (HttpInstance
, HttpInstance
->TimeoutEvent
);
1378 gBS
->SetTimer (HttpInstance
->TimeoutEvent
, TimerCancel
, 0);
1380 if (EFI_ERROR (Status
)) {
1381 TlsCloseTxRxEvent (HttpInstance
);
1390 Initialize Http session.
1392 @param[in] HttpInstance The HTTP instance private data.
1393 @param[in] Wrap The HTTP token's wrap data.
1394 @param[in] Configure The Flag indicates whether need to initialize session.
1395 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session.
1397 @retval EFI_SUCCESS The initialization of session is done.
1398 @retval Others Other error as indicated.
1403 IN HTTP_PROTOCOL
*HttpInstance
,
1404 IN HTTP_TOKEN_WRAP
*Wrap
,
1405 IN BOOLEAN Configure
,
1406 IN BOOLEAN TlsConfigure
1410 ASSERT (HttpInstance
!= NULL
);
1413 // Configure Tls session.
1416 Status
= TlsConfigureSession (HttpInstance
);
1417 if (EFI_ERROR (Status
)) {
1422 if (!HttpInstance
->LocalAddressIsIPv6
) {
1424 // Configure TCP instance.
1427 Status
= HttpConfigureTcp4 (HttpInstance
, Wrap
);
1428 if (EFI_ERROR (Status
)) {
1436 Status
= HttpConnectTcp4 (HttpInstance
);
1437 if (EFI_ERROR (Status
)) {
1442 // Configure TCP instance.
1445 Status
= HttpConfigureTcp6 (HttpInstance
, Wrap
);
1446 if (EFI_ERROR (Status
)) {
1454 Status
= HttpConnectTcp6 (HttpInstance
);
1455 if (EFI_ERROR (Status
)) {
1465 Send the HTTP or HTTPS message through TCP4 or TCP6.
1467 @param[in] HttpInstance The HTTP instance private data.
1468 @param[in] Wrap The HTTP token's wrap data.
1469 @param[in] TxString Buffer containing the HTTP message string.
1470 @param[in] TxStringLen Length of the HTTP message string in bytes.
1472 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1473 @retval Others Other error as indicated.
1478 IN HTTP_PROTOCOL
*HttpInstance
,
1479 IN HTTP_TOKEN_WRAP
*Wrap
,
1481 IN UINTN TxStringLen
1485 EFI_TCP4_IO_TOKEN
*Tx4Token
;
1486 EFI_TCP4_PROTOCOL
*Tcp4
;
1487 EFI_TCP6_IO_TOKEN
*Tx6Token
;
1488 EFI_TCP6_PROTOCOL
*Tcp6
;
1491 NET_FRAGMENT TempFragment
;
1492 NET_FRAGMENT Fragment
;
1496 Status
= EFI_SUCCESS
;
1499 TempFragment
.Len
= 0;
1500 TempFragment
.Bulk
= NULL
;
1502 Fragment
.Bulk
= NULL
;
1507 // Need to encrypt data.
1509 if (HttpInstance
->UseHttps
) {
1511 // Allocate enough buffer for each TLS plaintext records.
1513 TlsRecord
= AllocateZeroPool (TLS_RECORD_HEADER_LENGTH
+ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
);
1514 if (TlsRecord
== NULL
) {
1515 Status
= EFI_OUT_OF_RESOURCES
;
1520 // Allocate enough buffer for all TLS ciphertext records.
1522 RecordCount
= TxStringLen
/ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
+ 1;
1523 Fragment
.Bulk
= AllocateZeroPool (RecordCount
* (TLS_RECORD_HEADER_LENGTH
+ TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH
));
1524 if (Fragment
.Bulk
== NULL
) {
1525 Status
= EFI_OUT_OF_RESOURCES
;
1530 // Encrypt each TLS plaintext records.
1532 RemainingLen
= TxStringLen
;
1533 while (RemainingLen
!= 0) {
1534 PayloadSize
= (UINT16
) MIN (TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
, RemainingLen
);
1536 ((TLS_RECORD_HEADER
*) TlsRecord
)->ContentType
= TlsContentTypeApplicationData
;
1537 ((TLS_RECORD_HEADER
*) TlsRecord
)->Version
.Major
= HttpInstance
->TlsConfigData
.Version
.Major
;
1538 ((TLS_RECORD_HEADER
*) TlsRecord
)->Version
.Minor
= HttpInstance
->TlsConfigData
.Version
.Minor
;
1539 ((TLS_RECORD_HEADER
*) TlsRecord
)->Length
= PayloadSize
;
1541 CopyMem (TlsRecord
+ TLS_RECORD_HEADER_LENGTH
, TxString
+ (TxStringLen
- RemainingLen
), PayloadSize
);
1543 Status
= TlsProcessMessage (
1546 TLS_RECORD_HEADER_LENGTH
+ PayloadSize
,
1550 if (EFI_ERROR (Status
)) {
1555 // Record the processed/encrypted Packet.
1557 CopyMem (Fragment
.Bulk
+ Fragment
.Len
, TempFragment
.Bulk
, TempFragment
.Len
);
1558 Fragment
.Len
+= TempFragment
.Len
;
1560 FreePool (TempFragment
.Bulk
);
1561 TempFragment
.Len
= 0;
1562 TempFragment
.Bulk
= NULL
;
1564 RemainingLen
-= (UINTN
) PayloadSize
;
1565 ZeroMem (TlsRecord
, TLS_RECORD_HEADER_LENGTH
+ TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH
);
1568 FreePool (TlsRecord
);
1572 if (!HttpInstance
->LocalAddressIsIPv6
) {
1573 Tcp4
= HttpInstance
->Tcp4
;
1574 Tx4Token
= &Wrap
->TcpWrap
.Tx4Token
;
1576 if (HttpInstance
->UseHttps
) {
1577 Tx4Token
->Packet
.TxData
->DataLength
= Fragment
.Len
;
1578 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= Fragment
.Len
;
1579 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) Fragment
.Bulk
;
1581 Tx4Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1582 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1583 Tx4Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1586 Tx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1588 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1589 Status
= Tcp4
->Transmit (Tcp4
, Tx4Token
);
1590 if (EFI_ERROR (Status
)) {
1591 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1596 Tcp6
= HttpInstance
->Tcp6
;
1597 Tx6Token
= &Wrap
->TcpWrap
.Tx6Token
;
1599 if (HttpInstance
->UseHttps
) {
1600 Tx6Token
->Packet
.TxData
->DataLength
= Fragment
.Len
;
1601 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= Fragment
.Len
;
1602 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) Fragment
.Bulk
;
1604 Tx6Token
->Packet
.TxData
->DataLength
= (UINT32
) TxStringLen
;
1605 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentLength
= (UINT32
) TxStringLen
;
1606 Tx6Token
->Packet
.TxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) TxString
;
1609 Tx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
1611 Wrap
->TcpWrap
.IsTxDone
= FALSE
;
1612 Status
= Tcp6
->Transmit (Tcp6
, Tx6Token
);
1613 if (EFI_ERROR (Status
)) {
1614 DEBUG ((EFI_D_ERROR
, "Transmit failed: %r\n", Status
));
1623 if (HttpInstance
->UseHttps
) {
1624 if (TlsRecord
!= NULL
) {
1625 FreePool (TlsRecord
);
1629 if (Fragment
.Bulk
!= NULL
) {
1630 FreePool (Fragment
.Bulk
);
1631 Fragment
.Bulk
= NULL
;
1639 Check whether the user's token or event has already
1640 been enqueue on HTTP Tx or Rx Token list.
1642 @param[in] Map The container of either user's transmit or receive
1644 @param[in] Item Current item to check against.
1645 @param[in] Context The Token to check againist.
1647 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1648 @retval EFI_SUCCESS The current item isn't the same token/event as the
1656 IN NET_MAP_ITEM
*Item
,
1660 EFI_HTTP_TOKEN
*Token
;
1661 EFI_HTTP_TOKEN
*TokenInItem
;
1663 Token
= (EFI_HTTP_TOKEN
*) Context
;
1664 TokenInItem
= (EFI_HTTP_TOKEN
*) Item
->Key
;
1666 if (Token
== TokenInItem
|| Token
->Event
== TokenInItem
->Event
) {
1667 return EFI_ACCESS_DENIED
;
1674 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1676 @param[in] Map The container of Tx4Token or Tx6Token.
1677 @param[in] Item Current item to check against.
1678 @param[in] Context The Token to check againist.
1680 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1681 @retval EFI_SUCCESS The HTTP message has been sent out.
1688 IN NET_MAP_ITEM
*Item
,
1692 HTTP_TOKEN_WRAP
*ValueInItem
;
1694 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1696 if (!ValueInItem
->TcpWrap
.IsTxDone
) {
1697 return EFI_NOT_READY
;
1704 Transmit the HTTP or HTTPS mssage by processing the associated HTTP token.
1706 @param[in] Map The container of Tx4Token or Tx6Token.
1707 @param[in] Item Current item to check against.
1708 @param[in] Context The Token to check againist.
1710 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1711 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1719 IN NET_MAP_ITEM
*Item
,
1723 HTTP_TOKEN_WRAP
*ValueInItem
;
1728 UINTN RequestMsgSize
;
1732 ValueInItem
= (HTTP_TOKEN_WRAP
*) Item
->Value
;
1733 if (ValueInItem
->TcpWrap
.IsTxDone
) {
1738 // Parse the URI of the remote host.
1740 UrlSize
= StrLen (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
) + 1;
1741 Url
= AllocatePool (UrlSize
);
1743 return EFI_OUT_OF_RESOURCES
;
1746 UnicodeStrToAsciiStrS (ValueInItem
->HttpToken
->Message
->Data
.Request
->Url
, Url
, UrlSize
);
1749 // Create request message.
1751 Status
= HttpGenRequestMessage (
1752 ValueInItem
->HttpToken
->Message
,
1759 if (EFI_ERROR (Status
) || NULL
== RequestMsg
){
1763 ASSERT (RequestMsg
!= NULL
);
1766 // Transmit the request message.
1768 Status
= HttpTransmitTcp (
1769 ValueInItem
->HttpInstance
,
1771 (UINT8
*) RequestMsg
,
1774 FreePool (RequestMsg
);
1779 Receive the HTTP response by processing the associated HTTP token.
1781 @param[in] Map The container of Rx4Token or Rx6Token.
1782 @param[in] Item Current item to check against.
1783 @param[in] Context The Token to check againist.
1785 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1787 @retval Others Other error as indicated.
1794 IN NET_MAP_ITEM
*Item
,
1799 // Process the queued HTTP response.
1801 return HttpResponseWorker ((HTTP_TOKEN_WRAP
*) Item
->Value
);
1805 Receive the HTTP header by processing the associated HTTP token.
1807 @param[in] HttpInstance The HTTP instance private data.
1808 @param[in, out] SizeofHeaders The HTTP header length.
1809 @param[in, out] BufferSize The size of buffer to cacahe the header message.
1810 @param[in] Timeout The time to wait for receiving the header packet.
1812 @retval EFI_SUCCESS The HTTP header is received.
1813 @retval Others Other errors as indicated.
1817 HttpTcpReceiveHeader (
1818 IN HTTP_PROTOCOL
*HttpInstance
,
1819 IN OUT UINTN
*SizeofHeaders
,
1820 IN OUT UINTN
*BufferSize
,
1821 IN EFI_EVENT Timeout
1825 EFI_TCP4_IO_TOKEN
*Rx4Token
;
1826 EFI_TCP4_PROTOCOL
*Tcp4
;
1827 EFI_TCP6_IO_TOKEN
*Rx6Token
;
1828 EFI_TCP6_PROTOCOL
*Tcp6
;
1829 CHAR8
**EndofHeader
;
1830 CHAR8
**HttpHeaders
;
1832 NET_FRAGMENT Fragment
;
1834 ASSERT (HttpInstance
!= NULL
);
1836 EndofHeader
= HttpInstance
->EndofHeader
;
1837 HttpHeaders
= HttpInstance
->HttpHeaders
;
1838 Tcp4
= HttpInstance
->Tcp4
;
1839 Tcp6
= HttpInstance
->Tcp6
;
1844 Fragment
.Bulk
= NULL
;
1846 if (HttpInstance
->LocalAddressIsIPv6
) {
1847 ASSERT (Tcp6
!= NULL
);
1849 ASSERT (Tcp4
!= NULL
);
1852 if (!HttpInstance
->UseHttps
) {
1853 Status
= HttpCreateTcpRxEventForHeader (HttpInstance
);
1854 if (EFI_ERROR (Status
)) {
1859 if (!HttpInstance
->LocalAddressIsIPv6
) {
1860 if (!HttpInstance
->UseHttps
) {
1861 Rx4Token
= &HttpInstance
->Rx4Token
;
1862 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1863 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1864 Status
= EFI_OUT_OF_RESOURCES
;
1870 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1872 while (*EndofHeader
== NULL
) {
1873 if (!HttpInstance
->UseHttps
) {
1874 HttpInstance
->IsRxDone
= FALSE
;
1875 Rx4Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1876 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1877 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
1878 if (EFI_ERROR (Status
)) {
1879 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1883 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1887 if (!HttpInstance
->IsRxDone
) {
1889 // Cancle the Token before close its Event.
1891 Tcp4
->Cancel (HttpInstance
->Tcp4
, &Rx4Token
->CompletionToken
);
1892 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
1893 Rx4Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1896 Status
= Rx4Token
->CompletionToken
.Status
;
1897 if (EFI_ERROR (Status
)) {
1901 Fragment
.Len
= Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
1902 Fragment
.Bulk
= (UINT8
*) Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
1904 if (Fragment
.Bulk
!= NULL
) {
1905 FreePool (Fragment
.Bulk
);
1906 Fragment
.Bulk
= NULL
;
1909 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
1910 if (EFI_ERROR (Status
)) {
1911 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
1917 // Append the response string along with a Null-terminator.
1919 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
1920 Buffer
= AllocatePool (*BufferSize
+ 1);
1921 if (Buffer
== NULL
) {
1922 Status
= EFI_OUT_OF_RESOURCES
;
1926 if (*HttpHeaders
!= NULL
) {
1927 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
1928 FreePool (*HttpHeaders
);
1932 Buffer
+ *SizeofHeaders
,
1936 *(Buffer
+ *BufferSize
) = '\0';
1937 *HttpHeaders
= Buffer
;
1938 *SizeofHeaders
= *BufferSize
;
1941 // Check whether we received end of HTTP headers.
1943 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
1949 if (Rx4Token
!= NULL
&& Rx4Token
->Packet
.RxData
!= NULL
&& Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
1950 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
1951 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
1952 Fragment
.Bulk
= NULL
;
1955 if (Fragment
.Bulk
!= NULL
) {
1956 FreePool (Fragment
.Bulk
);
1957 Fragment
.Bulk
= NULL
;
1960 if (!HttpInstance
->UseHttps
) {
1961 Rx6Token
= &HttpInstance
->Rx6Token
;
1962 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= AllocateZeroPool (DEF_BUF_LEN
);
1963 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
== NULL
) {
1964 Status
= EFI_OUT_OF_RESOURCES
;
1970 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1972 while (*EndofHeader
== NULL
) {
1973 if (!HttpInstance
->UseHttps
) {
1974 HttpInstance
->IsRxDone
= FALSE
;
1975 Rx6Token
->Packet
.RxData
->DataLength
= DEF_BUF_LEN
;
1976 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= DEF_BUF_LEN
;
1977 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
1978 if (EFI_ERROR (Status
)) {
1979 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
1983 while (!HttpInstance
->IsRxDone
&& ((Timeout
== NULL
) || EFI_ERROR (gBS
->CheckEvent (Timeout
)))) {
1987 if (!HttpInstance
->IsRxDone
) {
1989 // Cancle the Token before close its Event.
1991 Tcp6
->Cancel (HttpInstance
->Tcp6
, &Rx6Token
->CompletionToken
);
1992 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
1993 Rx6Token
->CompletionToken
.Status
= EFI_TIMEOUT
;
1996 Status
= Rx6Token
->CompletionToken
.Status
;
1997 if (EFI_ERROR (Status
)) {
2001 Fragment
.Len
= Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
;
2002 Fragment
.Bulk
= (UINT8
*) Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
;
2004 if (Fragment
.Bulk
!= NULL
) {
2005 FreePool (Fragment
.Bulk
);
2006 Fragment
.Bulk
= NULL
;
2009 Status
= HttpsReceive (HttpInstance
, &Fragment
, Timeout
);
2010 if (EFI_ERROR (Status
)) {
2011 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
2017 // Append the response string along with a Null-terminator.
2019 *BufferSize
= *SizeofHeaders
+ Fragment
.Len
;
2020 Buffer
= AllocatePool (*BufferSize
+ 1);
2021 if (Buffer
== NULL
) {
2022 Status
= EFI_OUT_OF_RESOURCES
;
2026 if (*HttpHeaders
!= NULL
) {
2027 CopyMem (Buffer
, *HttpHeaders
, *SizeofHeaders
);
2028 FreePool (*HttpHeaders
);
2032 Buffer
+ *SizeofHeaders
,
2036 *(Buffer
+ *BufferSize
) = '\0';
2037 *HttpHeaders
= Buffer
;
2038 *SizeofHeaders
= *BufferSize
;
2041 // Check whether we received end of HTTP headers.
2043 *EndofHeader
= AsciiStrStr (*HttpHeaders
, HTTP_END_OF_HDR_STR
);
2049 if (Rx6Token
!= NULL
&& Rx6Token
->Packet
.RxData
!= NULL
&& Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2050 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2051 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2052 Fragment
.Bulk
= NULL
;
2055 if (Fragment
.Bulk
!= NULL
) {
2056 FreePool (Fragment
.Bulk
);
2057 Fragment
.Bulk
= NULL
;
2062 // Skip the CRLF after the HTTP headers.
2064 *EndofHeader
= *EndofHeader
+ AsciiStrLen (HTTP_END_OF_HDR_STR
);
2066 *SizeofHeaders
= *EndofHeader
- *HttpHeaders
;
2072 Receive the HTTP body by processing the associated HTTP token.
2074 @param[in] Wrap The HTTP token's wrap data.
2075 @param[in] HttpMsg The HTTP message data.
2077 @retval EFI_SUCCESS The HTTP body is received.
2078 @retval Others Other error as indicated.
2082 HttpTcpReceiveBody (
2083 IN HTTP_TOKEN_WRAP
*Wrap
,
2084 IN EFI_HTTP_MESSAGE
*HttpMsg
2088 HTTP_PROTOCOL
*HttpInstance
;
2089 EFI_TCP6_PROTOCOL
*Tcp6
;
2090 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2091 EFI_TCP4_PROTOCOL
*Tcp4
;
2092 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2094 HttpInstance
= Wrap
->HttpInstance
;
2095 Tcp4
= HttpInstance
->Tcp4
;
2096 Tcp6
= HttpInstance
->Tcp6
;
2100 if (HttpInstance
->LocalAddressIsIPv6
) {
2101 ASSERT (Tcp6
!= NULL
);
2103 ASSERT (Tcp4
!= NULL
);
2106 if (HttpInstance
->LocalAddressIsIPv6
) {
2107 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2108 Rx6Token
->Packet
.RxData
->DataLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2109 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2110 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
2111 Rx6Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2113 Status
= Tcp6
->Receive (Tcp6
, Rx6Token
);
2114 if (EFI_ERROR (Status
)) {
2115 DEBUG ((EFI_D_ERROR
, "Tcp6 receive failed: %r\n", Status
));
2119 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2120 Rx4Token
->Packet
.RxData
->DataLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2121 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentLength
= (UINT32
) MIN (MAX_UINT32
, HttpMsg
->BodyLength
);
2122 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= (VOID
*) HttpMsg
->Body
;
2124 Rx4Token
->CompletionToken
.Status
= EFI_NOT_READY
;
2125 Status
= Tcp4
->Receive (Tcp4
, Rx4Token
);
2126 if (EFI_ERROR (Status
)) {
2127 DEBUG ((EFI_D_ERROR
, "Tcp4 receive failed: %r\n", Status
));
2137 Clean up Tcp Tokens while the Tcp transmission error occurs.
2139 @param[in] Wrap Pointer to HTTP token's wrap data.
2143 HttpTcpTokenCleanup (
2144 IN HTTP_TOKEN_WRAP
*Wrap
2147 HTTP_PROTOCOL
*HttpInstance
;
2148 EFI_TCP4_IO_TOKEN
*Rx4Token
;
2149 EFI_TCP6_IO_TOKEN
*Rx6Token
;
2151 ASSERT (Wrap
!= NULL
);
2152 HttpInstance
= Wrap
->HttpInstance
;
2156 if (HttpInstance
->LocalAddressIsIPv6
) {
2157 Rx6Token
= &Wrap
->TcpWrap
.Rx6Token
;
2159 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2160 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2161 Rx6Token
->CompletionToken
.Event
= NULL
;
2166 Rx6Token
= &HttpInstance
->Rx6Token
;
2168 if (Rx6Token
->CompletionToken
.Event
!= NULL
) {
2169 gBS
->CloseEvent (Rx6Token
->CompletionToken
.Event
);
2170 Rx6Token
->CompletionToken
.Event
= NULL
;
2173 if (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2174 FreePool (Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2175 Rx6Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;
2179 Rx4Token
= &Wrap
->TcpWrap
.Rx4Token
;
2181 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2182 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2183 Rx4Token
->CompletionToken
.Event
= NULL
;
2188 Rx4Token
= &HttpInstance
->Rx4Token
;
2190 if (Rx4Token
->CompletionToken
.Event
!= NULL
) {
2191 gBS
->CloseEvent (Rx4Token
->CompletionToken
.Event
);
2192 Rx4Token
->CompletionToken
.Event
= NULL
;
2196 if (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
!= NULL
) {
2197 FreePool (Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
);
2198 Rx4Token
->Packet
.RxData
->FragmentTable
[0].FragmentBuffer
= NULL
;