VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/HttpDxe/HttpProto.c@ 77662

Last change on this file since 77662 was 77662, checked in by vboxsync, 6 years ago

EFI: First step in UDK2018 merge. Does not build yet.

  • Property svn:eol-style set to native
File size: 59.7 KB
Line 
1/** @file
2 Miscellaneous routines for HttpDxe driver.
3
4Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
5(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6This program and the accompanying materials
7are licensed and made available under the terms and conditions of the BSD License
8which accompanies this distribution. The full text of the license may be found at
9http://opensource.org/licenses/bsd-license.php
10
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14**/
15
16#include "HttpDriver.h"
17
18/**
19 The common notify function used in HTTP driver.
20
21 @param[in] Event The event signaled.
22 @param[in] Context The context.
23
24**/
25VOID
26EFIAPI
27HttpCommonNotify (
28 IN EFI_EVENT Event,
29 IN VOID *Context
30 )
31{
32 if ((Event == NULL) || (Context == NULL)) {
33 return ;
34 }
35
36 *((BOOLEAN *) Context) = TRUE;
37}
38
39/**
40 The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().
41
42 @param[in] Context The context.
43
44**/
45VOID
46EFIAPI
47HttpTcpTransmitNotifyDpc (
48 IN VOID *Context
49 )
50{
51 HTTP_TOKEN_WRAP *Wrap;
52 HTTP_PROTOCOL *HttpInstance;
53
54 if (Context == NULL) {
55 return ;
56 }
57
58 Wrap = (HTTP_TOKEN_WRAP *) Context;
59 HttpInstance = Wrap->HttpInstance;
60
61 if (!HttpInstance->LocalAddressIsIPv6) {
62 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx4Token.CompletionToken.Status;
63 gBS->SignalEvent (Wrap->HttpToken->Event);
64
65 //
66 // Free resources.
67 //
68 if (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {
69 FreePool (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer);
70 }
71
72 if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {
73 gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);
74 }
75
76 } else {
77 Wrap->HttpToken->Status = Wrap->TcpWrap.Tx6Token.CompletionToken.Status;
78 gBS->SignalEvent (Wrap->HttpToken->Event);
79
80 //
81 // Free resources.
82 //
83 if (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {
84 FreePool (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer);
85 }
86
87 if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {
88 gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);
89 }
90 }
91
92
93 Wrap->TcpWrap.IsTxDone = TRUE;
94
95 //
96 // Check pending TxTokens and sent out.
97 //
98 NetMapIterate (&Wrap->HttpInstance->TxTokens, HttpTcpTransmit, NULL);
99
100}
101
102/**
103 Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK.
104
105 @param Event The receive event delivered to TCP for transmit.
106 @param Context Context for the callback.
107
108**/
109VOID
110EFIAPI
111HttpTcpTransmitNotify (
112 IN EFI_EVENT Event,
113 IN VOID *Context
114 )
115{
116 //
117 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
118 //
119 QueueDpc (TPL_CALLBACK, HttpTcpTransmitNotifyDpc, Context);
120}
121
122/**
123 The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().
124
125 @param[in] Context The context.
126
127**/
128VOID
129EFIAPI
130HttpTcpReceiveNotifyDpc (
131 IN VOID *Context
132 )
133{
134 HTTP_TOKEN_WRAP *Wrap;
135 NET_MAP_ITEM *Item;
136 UINTN Length;
137 EFI_STATUS Status;
138 HTTP_PROTOCOL *HttpInstance;
139 BOOLEAN UsingIpv6;
140
141 if (Context == NULL) {
142 return ;
143 }
144
145 Wrap = (HTTP_TOKEN_WRAP *) Context;
146 HttpInstance = Wrap->HttpInstance;
147 UsingIpv6 = HttpInstance->LocalAddressIsIPv6;
148
149 if (UsingIpv6) {
150 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);
151 Wrap->TcpWrap.Rx6Token.CompletionToken.Event = NULL;
152
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);
157
158 Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);
159 if (Item != NULL) {
160 NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);
161 }
162
163 FreePool (Wrap);
164 Wrap = NULL;
165
166 return ;
167 }
168
169 } else {
170 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);
171 Wrap->TcpWrap.Rx4Token.CompletionToken.Event = NULL;
172
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);
177
178 Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);
179 if (Item != NULL) {
180 NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);
181 }
182
183 FreePool (Wrap);
184 Wrap = NULL;
185
186 return ;
187 }
188 }
189
190 //
191 // Check whether we receive a complete HTTP message.
192 //
193 ASSERT (HttpInstance->MsgParser != NULL);
194 if (UsingIpv6) {
195 Length = (UINTN) Wrap->TcpWrap.Rx6Data.FragmentTable[0].FragmentLength;
196 } else {
197 Length = (UINTN) Wrap->TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;
198 }
199
200 Status = HttpParseMessageBody (
201 HttpInstance->MsgParser,
202 Length,
203 Wrap->HttpToken->Message->Body
204 );
205 if (EFI_ERROR (Status)) {
206 return ;
207 }
208
209 if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
210 //
211 // Free the MsgParse since we already have a full HTTP message.
212 //
213 HttpFreeMsgParser (HttpInstance->MsgParser);
214 HttpInstance->MsgParser = NULL;
215 }
216
217 Wrap->HttpToken->Message->BodyLength = Length;
218 ASSERT (HttpInstance->CacheBody == NULL);
219 //
220 // We receive part of header of next HTTP msg.
221 //
222 if (HttpInstance->NextMsg != NULL) {
223 Wrap->HttpToken->Message->BodyLength = HttpInstance->NextMsg -
224 (CHAR8 *) Wrap->HttpToken->Message->Body;
225 HttpInstance->CacheLen = Length - Wrap->HttpToken->Message->BodyLength;
226 if (HttpInstance->CacheLen != 0) {
227 HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);
228 if (HttpInstance->CacheBody == NULL) {
229 return ;
230 }
231 CopyMem (HttpInstance->CacheBody, HttpInstance->NextMsg, HttpInstance->CacheLen);
232 HttpInstance->NextMsg = HttpInstance->CacheBody;
233 HttpInstance->CacheOffset = 0;
234 }
235 }
236
237 Item = NetMapFindKey (&Wrap->HttpInstance->RxTokens, Wrap->HttpToken);
238 if (Item != NULL) {
239 NetMapRemoveItem (&Wrap->HttpInstance->RxTokens, Item, NULL);
240 }
241
242
243 Wrap->TcpWrap.IsRxDone = TRUE;
244 if (UsingIpv6) {
245 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;
246 } else {
247 Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;
248 }
249
250
251 gBS->SignalEvent (Wrap->HttpToken->Event);
252
253 //
254 // Check pending RxTokens and receive the HTTP message.
255 //
256 NetMapIterate (&Wrap->HttpInstance->RxTokens, HttpTcpReceive, NULL);
257
258 FreePool (Wrap);
259 Wrap = NULL;
260}
261
262/**
263 Request HttpTcpReceiveNotifyDpc as a DPC at TPL_CALLBACK.
264
265 @param Event The receive event delivered to TCP for receive.
266 @param Context Context for the callback.
267
268**/
269VOID
270EFIAPI
271HttpTcpReceiveNotify (
272 IN EFI_EVENT Event,
273 IN VOID *Context
274 )
275{
276 //
277 // Request HttpTcpTransmitNotifyDpc as a DPC at TPL_CALLBACK
278 //
279 QueueDpc (TPL_CALLBACK, HttpTcpReceiveNotifyDpc, Context);
280}
281
282/**
283 Create events for the TCP connection token and TCP close token.
284
285 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
286
287 @retval EFI_SUCCESS The events are created successfully.
288 @retval others Other error as indicated.
289
290**/
291EFI_STATUS
292HttpCreateTcpConnCloseEvent (
293 IN HTTP_PROTOCOL *HttpInstance
294 )
295{
296 EFI_STATUS Status;
297
298 if (!HttpInstance->LocalAddressIsIPv6) {
299 //
300 // Create events for variuos asynchronous operations.
301 //
302 Status = gBS->CreateEvent (
303 EVT_NOTIFY_SIGNAL,
304 TPL_NOTIFY,
305 HttpCommonNotify,
306 &HttpInstance->IsTcp4ConnDone,
307 &HttpInstance->Tcp4ConnToken.CompletionToken.Event
308 );
309 if (EFI_ERROR (Status)) {
310 goto ERROR;
311 }
312
313 //
314 // Initialize Tcp4CloseToken
315 //
316 Status = gBS->CreateEvent (
317 EVT_NOTIFY_SIGNAL,
318 TPL_NOTIFY,
319 HttpCommonNotify,
320 &HttpInstance->IsTcp4CloseDone,
321 &HttpInstance->Tcp4CloseToken.CompletionToken.Event
322 );
323 if (EFI_ERROR (Status)) {
324 goto ERROR;
325 }
326
327 } else {
328 //
329 // Create events for variuos asynchronous operations.
330 //
331 Status = gBS->CreateEvent (
332 EVT_NOTIFY_SIGNAL,
333 TPL_NOTIFY,
334 HttpCommonNotify,
335 &HttpInstance->IsTcp6ConnDone,
336 &HttpInstance->Tcp6ConnToken.CompletionToken.Event
337 );
338 if (EFI_ERROR (Status)) {
339 goto ERROR;
340 }
341
342 //
343 // Initialize Tcp6CloseToken
344 //
345 Status = gBS->CreateEvent (
346 EVT_NOTIFY_SIGNAL,
347 TPL_NOTIFY,
348 HttpCommonNotify,
349 &HttpInstance->IsTcp6CloseDone,
350 &HttpInstance->Tcp6CloseToken.CompletionToken.Event
351 );
352 if (EFI_ERROR (Status)) {
353 goto ERROR;
354 }
355 }
356
357 return EFI_SUCCESS;
358
359ERROR:
360 //
361 // Error handling
362 //
363 HttpCloseTcpConnCloseEvent (HttpInstance);
364
365 return Status;
366}
367
368
369/**
370 Close events in the TCP connection token and TCP close token.
371
372 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
373
374**/
375VOID
376HttpCloseTcpConnCloseEvent (
377 IN HTTP_PROTOCOL *HttpInstance
378 )
379{
380 ASSERT (HttpInstance != NULL);
381
382 if (HttpInstance->LocalAddressIsIPv6) {
383 if (NULL != HttpInstance->Tcp6ConnToken.CompletionToken.Event) {
384 gBS->CloseEvent (HttpInstance->Tcp6ConnToken.CompletionToken.Event);
385 HttpInstance->Tcp6ConnToken.CompletionToken.Event = NULL;
386 }
387
388 if (NULL != HttpInstance->Tcp6CloseToken.CompletionToken.Event) {
389 gBS->CloseEvent(HttpInstance->Tcp6CloseToken.CompletionToken.Event);
390 HttpInstance->Tcp6CloseToken.CompletionToken.Event = NULL;
391 }
392
393 } else {
394 if (NULL != HttpInstance->Tcp4ConnToken.CompletionToken.Event) {
395 gBS->CloseEvent (HttpInstance->Tcp4ConnToken.CompletionToken.Event);
396 HttpInstance->Tcp4ConnToken.CompletionToken.Event = NULL;
397 }
398
399 if (NULL != HttpInstance->Tcp4CloseToken.CompletionToken.Event) {
400 gBS->CloseEvent(HttpInstance->Tcp4CloseToken.CompletionToken.Event);
401 HttpInstance->Tcp4CloseToken.CompletionToken.Event = NULL;
402 }
403 }
404
405}
406
407/**
408 Create event for the TCP transmit token.
409
410 @param[in] Wrap Point to HTTP token's wrap data.
411
412 @retval EFI_SUCCESS The events is created successfully.
413 @retval others Other error as indicated.
414
415**/
416EFI_STATUS
417HttpCreateTcpTxEvent (
418 IN HTTP_TOKEN_WRAP *Wrap
419 )
420{
421 EFI_STATUS Status;
422 HTTP_PROTOCOL *HttpInstance;
423 HTTP_TCP_TOKEN_WRAP *TcpWrap;
424
425 HttpInstance = Wrap->HttpInstance;
426 TcpWrap = &Wrap->TcpWrap;
427
428 if (!HttpInstance->LocalAddressIsIPv6) {
429 Status = gBS->CreateEvent (
430 EVT_NOTIFY_SIGNAL,
431 TPL_NOTIFY,
432 HttpTcpTransmitNotify,
433 Wrap,
434 &TcpWrap->Tx4Token.CompletionToken.Event
435 );
436 if (EFI_ERROR (Status)) {
437 return Status;
438 }
439
440 TcpWrap->Tx4Data.Push = TRUE;
441 TcpWrap->Tx4Data.Urgent = FALSE;
442 TcpWrap->Tx4Data.FragmentCount = 1;
443 TcpWrap->Tx4Token.Packet.TxData = &Wrap->TcpWrap.Tx4Data;
444 TcpWrap->Tx4Token.CompletionToken.Status = EFI_NOT_READY;
445
446 } else {
447 Status = gBS->CreateEvent (
448 EVT_NOTIFY_SIGNAL,
449 TPL_NOTIFY,
450 HttpTcpTransmitNotify,
451 Wrap,
452 &TcpWrap->Tx6Token.CompletionToken.Event
453 );
454 if (EFI_ERROR (Status)) {
455 return Status;
456 }
457
458 TcpWrap->Tx6Data.Push = TRUE;
459 TcpWrap->Tx6Data.Urgent = FALSE;
460 TcpWrap->Tx6Data.FragmentCount = 1;
461 TcpWrap->Tx6Token.Packet.TxData = &Wrap->TcpWrap.Tx6Data;
462 TcpWrap->Tx6Token.CompletionToken.Status =EFI_NOT_READY;
463
464 }
465
466 return EFI_SUCCESS;
467}
468
469/**
470 Create event for the TCP receive token which is used to receive HTTP header.
471
472 @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
473
474 @retval EFI_SUCCESS The events is created successfully.
475 @retval others Other error as indicated.
476
477**/
478EFI_STATUS
479HttpCreateTcpRxEventForHeader (
480 IN HTTP_PROTOCOL *HttpInstance
481 )
482{
483 EFI_STATUS Status;
484
485 if (!HttpInstance->LocalAddressIsIPv6) {
486 Status = gBS->CreateEvent (
487 EVT_NOTIFY_SIGNAL,
488 TPL_NOTIFY,
489 HttpCommonNotify,
490 &HttpInstance->IsRxDone,
491 &HttpInstance->Rx4Token.CompletionToken.Event
492 );
493 if (EFI_ERROR (Status)) {
494 return Status;
495 }
496
497 HttpInstance->Rx4Data.FragmentCount = 1;
498 HttpInstance->Rx4Token.Packet.RxData = &HttpInstance->Rx4Data;
499 HttpInstance->Rx4Token.CompletionToken.Status = EFI_NOT_READY;
500
501 } else {
502 Status = gBS->CreateEvent (
503 EVT_NOTIFY_SIGNAL,
504 TPL_NOTIFY,
505 HttpCommonNotify,
506 &HttpInstance->IsRxDone,
507 &HttpInstance->Rx6Token.CompletionToken.Event
508 );
509 if (EFI_ERROR (Status)) {
510 return Status;
511 }
512
513 HttpInstance->Rx6Data.FragmentCount =1;
514 HttpInstance->Rx6Token.Packet.RxData = &HttpInstance->Rx6Data;
515 HttpInstance->Rx6Token.CompletionToken.Status = EFI_NOT_READY;
516
517 }
518
519
520 return EFI_SUCCESS;
521}
522
523/**
524 Create event for the TCP receive token which is used to receive HTTP body.
525
526 @param[in] Wrap Point to HTTP token's wrap data.
527
528 @retval EFI_SUCCESS The events is created successfully.
529 @retval others Other error as indicated.
530
531**/
532EFI_STATUS
533HttpCreateTcpRxEvent (
534 IN HTTP_TOKEN_WRAP *Wrap
535 )
536{
537 EFI_STATUS Status;
538 HTTP_PROTOCOL *HttpInstance;
539 HTTP_TCP_TOKEN_WRAP *TcpWrap;
540
541 HttpInstance = Wrap->HttpInstance;
542 TcpWrap = &Wrap->TcpWrap;
543 if (!HttpInstance->LocalAddressIsIPv6) {
544 Status = gBS->CreateEvent (
545 EVT_NOTIFY_SIGNAL,
546 TPL_NOTIFY,
547 HttpTcpReceiveNotify,
548 Wrap,
549 &TcpWrap->Rx4Token.CompletionToken.Event
550 );
551 if (EFI_ERROR (Status)) {
552 return Status;
553 }
554
555 TcpWrap->Rx4Data.FragmentCount = 1;
556 TcpWrap->Rx4Token.Packet.RxData = &Wrap->TcpWrap.Rx4Data;
557 TcpWrap->Rx4Token.CompletionToken.Status = EFI_NOT_READY;
558
559 } else {
560 Status = gBS->CreateEvent (
561 EVT_NOTIFY_SIGNAL,
562 TPL_NOTIFY,
563 HttpTcpReceiveNotify,
564 Wrap,
565 &TcpWrap->Rx6Token.CompletionToken.Event
566 );
567 if (EFI_ERROR (Status)) {
568 return Status;
569 }
570
571 TcpWrap->Rx6Data.FragmentCount = 1;
572 TcpWrap->Rx6Token.Packet.RxData = &Wrap->TcpWrap.Rx6Data;
573 TcpWrap->Rx6Token.CompletionToken.Status = EFI_NOT_READY;
574 }
575
576 return EFI_SUCCESS;
577}
578
579/**
580 Close Events for Tcp Receive Tokens for HTTP body and HTTP header.
581
582 @param[in] Wrap Pointer to HTTP token's wrap data.
583
584**/
585VOID
586HttpCloseTcpRxEvent (
587 IN HTTP_TOKEN_WRAP *Wrap
588 )
589{
590 HTTP_PROTOCOL *HttpInstance;
591
592 ASSERT (Wrap != NULL);
593 HttpInstance = Wrap->HttpInstance;
594
595 if (HttpInstance->LocalAddressIsIPv6) {
596 if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {
597 gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);
598 }
599
600 if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {
601 gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);
602 HttpInstance->Rx6Token.CompletionToken.Event = NULL;
603 }
604 } else {
605 if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {
606 gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);
607 }
608
609 if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {
610 gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);
611 HttpInstance->Rx4Token.CompletionToken.Event = NULL;
612 }
613 }
614}
615
616/**
617 Intiialize the HTTP_PROTOCOL structure to the unconfigured state.
618
619 @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
620 @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.
621
622 @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully.
623 @retval Others Other error as indicated.
624
625**/
626EFI_STATUS
627HttpInitProtocol (
628 IN OUT HTTP_PROTOCOL *HttpInstance,
629 IN BOOLEAN IpVersion
630 )
631{
632 EFI_STATUS Status;
633 VOID *Interface;
634 BOOLEAN UsingIpv6;
635
636 ASSERT (HttpInstance != NULL);
637 UsingIpv6 = IpVersion;
638
639 if (!UsingIpv6) {
640 //
641 // Create TCP4 child.
642 //
643 Status = NetLibCreateServiceChild (
644 HttpInstance->Service->ControllerHandle,
645 HttpInstance->Service->Ip4DriverBindingHandle,
646 &gEfiTcp4ServiceBindingProtocolGuid,
647 &HttpInstance->Tcp4ChildHandle
648 );
649
650 if (EFI_ERROR (Status)) {
651 goto ON_ERROR;
652 }
653
654 Status = gBS->OpenProtocol (
655 HttpInstance->Tcp4ChildHandle,
656 &gEfiTcp4ProtocolGuid,
657 (VOID **) &Interface,
658 HttpInstance->Service->Ip4DriverBindingHandle,
659 HttpInstance->Service->ControllerHandle,
660 EFI_OPEN_PROTOCOL_BY_DRIVER
661 );
662
663 if (EFI_ERROR (Status)) {
664 goto ON_ERROR;
665 }
666
667 Status = gBS->OpenProtocol (
668 HttpInstance->Tcp4ChildHandle,
669 &gEfiTcp4ProtocolGuid,
670 (VOID **) &HttpInstance->Tcp4,
671 HttpInstance->Service->Ip4DriverBindingHandle,
672 HttpInstance->Handle,
673 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
674 );
675 if (EFI_ERROR(Status)) {
676 goto ON_ERROR;
677 }
678
679 Status = gBS->OpenProtocol (
680 HttpInstance->Service->Tcp4ChildHandle,
681 &gEfiTcp4ProtocolGuid,
682 (VOID **) &Interface,
683 HttpInstance->Service->Ip4DriverBindingHandle,
684 HttpInstance->Handle,
685 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
686 );
687 if (EFI_ERROR(Status)) {
688 goto ON_ERROR;
689 }
690 } else {
691 //
692 // Create TCP6 Child.
693 //
694 Status = NetLibCreateServiceChild (
695 HttpInstance->Service->ControllerHandle,
696 HttpInstance->Service->Ip6DriverBindingHandle,
697 &gEfiTcp6ServiceBindingProtocolGuid,
698 &HttpInstance->Tcp6ChildHandle
699 );
700
701 if (EFI_ERROR (Status)) {
702 goto ON_ERROR;
703 }
704
705 Status = gBS->OpenProtocol (
706 HttpInstance->Tcp6ChildHandle,
707 &gEfiTcp6ProtocolGuid,
708 (VOID **) &Interface,
709 HttpInstance->Service->Ip6DriverBindingHandle,
710 HttpInstance->Service->ControllerHandle,
711 EFI_OPEN_PROTOCOL_BY_DRIVER
712 );
713
714 if (EFI_ERROR (Status)) {
715 goto ON_ERROR;
716 }
717
718 Status = gBS->OpenProtocol (
719 HttpInstance->Tcp6ChildHandle,
720 &gEfiTcp6ProtocolGuid,
721 (VOID **) &HttpInstance->Tcp6,
722 HttpInstance->Service->Ip6DriverBindingHandle,
723 HttpInstance->Handle,
724 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
725 );
726
727 if (EFI_ERROR(Status)) {
728 goto ON_ERROR;
729 }
730
731 Status = gBS->OpenProtocol (
732 HttpInstance->Service->Tcp6ChildHandle,
733 &gEfiTcp6ProtocolGuid,
734 (VOID **) &Interface,
735 HttpInstance->Service->Ip6DriverBindingHandle,
736 HttpInstance->Handle,
737 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
738 );
739
740 if (EFI_ERROR(Status)) {
741 goto ON_ERROR;
742 }
743 }
744
745 HttpInstance->Url = AllocateZeroPool (HTTP_URL_BUFFER_LEN);
746 if (HttpInstance->Url == NULL) {
747 Status = EFI_OUT_OF_RESOURCES;
748 goto ON_ERROR;
749 }
750
751 return EFI_SUCCESS;
752
753ON_ERROR:
754
755 if (HttpInstance->Tcp4ChildHandle != NULL) {
756 gBS->CloseProtocol (
757 HttpInstance->Tcp4ChildHandle,
758 &gEfiTcp4ProtocolGuid,
759 HttpInstance->Service->Ip4DriverBindingHandle,
760 HttpInstance->Service->ControllerHandle
761 );
762
763 gBS->CloseProtocol (
764 HttpInstance->Tcp4ChildHandle,
765 &gEfiTcp4ProtocolGuid,
766 HttpInstance->Service->Ip4DriverBindingHandle,
767 HttpInstance->Handle
768 );
769
770 NetLibDestroyServiceChild (
771 HttpInstance->Service->ControllerHandle,
772 HttpInstance->Service->Ip4DriverBindingHandle,
773 &gEfiTcp4ServiceBindingProtocolGuid,
774 HttpInstance->Tcp4ChildHandle
775 );
776 }
777
778 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {
779 gBS->CloseProtocol (
780 HttpInstance->Service->Tcp4ChildHandle,
781 &gEfiTcp4ProtocolGuid,
782 HttpInstance->Service->Ip4DriverBindingHandle,
783 HttpInstance->Handle
784 );
785 }
786
787 if (HttpInstance->Tcp6ChildHandle != NULL) {
788 gBS->CloseProtocol (
789 HttpInstance->Tcp6ChildHandle,
790 &gEfiTcp6ProtocolGuid,
791 HttpInstance->Service->Ip6DriverBindingHandle,
792 HttpInstance->Service->ControllerHandle
793 );
794
795 gBS->CloseProtocol (
796 HttpInstance->Tcp6ChildHandle,
797 &gEfiTcp6ProtocolGuid,
798 HttpInstance->Service->Ip6DriverBindingHandle,
799 HttpInstance->Handle
800 );
801
802 NetLibDestroyServiceChild (
803 HttpInstance->Service->ControllerHandle,
804 HttpInstance->Service->Ip6DriverBindingHandle,
805 &gEfiTcp6ServiceBindingProtocolGuid,
806 HttpInstance->Tcp6ChildHandle
807 );
808 }
809
810 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {
811 gBS->CloseProtocol (
812 HttpInstance->Service->Tcp6ChildHandle,
813 &gEfiTcp6ProtocolGuid,
814 HttpInstance->Service->Ip6DriverBindingHandle,
815 HttpInstance->Handle
816 );
817 }
818
819 return EFI_UNSUPPORTED;
820
821}
822
823/**
824 Clean up the HTTP child, release all the resources used by it.
825
826 @param[in] HttpInstance The HTTP child to clean up.
827
828**/
829VOID
830HttpCleanProtocol (
831 IN HTTP_PROTOCOL *HttpInstance
832 )
833{
834 HttpCloseConnection (HttpInstance);
835
836 HttpCloseTcpConnCloseEvent (HttpInstance);
837
838 if (HttpInstance->TimeoutEvent != NULL) {
839 gBS->CloseEvent (HttpInstance->TimeoutEvent);
840 HttpInstance->TimeoutEvent = NULL;
841 }
842
843 if (HttpInstance->CacheBody != NULL) {
844 FreePool (HttpInstance->CacheBody);
845 HttpInstance->CacheBody = NULL;
846 HttpInstance->NextMsg = NULL;
847 }
848
849 if (HttpInstance->RemoteHost != NULL) {
850 FreePool (HttpInstance->RemoteHost);
851 HttpInstance->RemoteHost = NULL;
852 }
853
854 if (HttpInstance->MsgParser != NULL) {
855 HttpFreeMsgParser (HttpInstance->MsgParser);
856 HttpInstance->MsgParser = NULL;
857 }
858
859 if (HttpInstance->Url != NULL) {
860 FreePool (HttpInstance->Url);
861 HttpInstance->Url = NULL;
862 }
863
864 NetMapClean (&HttpInstance->TxTokens);
865 NetMapClean (&HttpInstance->RxTokens);
866
867 if (HttpInstance->TlsSb != NULL && HttpInstance->TlsChildHandle != NULL) {
868 //
869 // Destroy the TLS instance.
870 //
871 HttpInstance->TlsSb->DestroyChild (HttpInstance->TlsSb, HttpInstance->TlsChildHandle);
872 }
873
874 if (HttpInstance->Tcp4ChildHandle != NULL) {
875 gBS->CloseProtocol (
876 HttpInstance->Tcp4ChildHandle,
877 &gEfiTcp4ProtocolGuid,
878 HttpInstance->Service->Ip4DriverBindingHandle,
879 HttpInstance->Service->ControllerHandle
880 );
881
882 gBS->CloseProtocol (
883 HttpInstance->Tcp4ChildHandle,
884 &gEfiTcp4ProtocolGuid,
885 HttpInstance->Service->Ip4DriverBindingHandle,
886 HttpInstance->Handle
887 );
888
889 NetLibDestroyServiceChild (
890 HttpInstance->Service->ControllerHandle,
891 HttpInstance->Service->Ip4DriverBindingHandle,
892 &gEfiTcp4ServiceBindingProtocolGuid,
893 HttpInstance->Tcp4ChildHandle
894 );
895 }
896
897 if (HttpInstance->Service->Tcp4ChildHandle != NULL) {
898 gBS->CloseProtocol (
899 HttpInstance->Service->Tcp4ChildHandle,
900 &gEfiTcp4ProtocolGuid,
901 HttpInstance->Service->Ip4DriverBindingHandle,
902 HttpInstance->Handle
903 );
904 }
905
906 if (HttpInstance->Tcp6ChildHandle != NULL) {
907 gBS->CloseProtocol (
908 HttpInstance->Tcp6ChildHandle,
909 &gEfiTcp6ProtocolGuid,
910 HttpInstance->Service->Ip6DriverBindingHandle,
911 HttpInstance->Service->ControllerHandle
912 );
913
914 gBS->CloseProtocol (
915 HttpInstance->Tcp6ChildHandle,
916 &gEfiTcp6ProtocolGuid,
917 HttpInstance->Service->Ip6DriverBindingHandle,
918 HttpInstance->Handle
919 );
920
921 NetLibDestroyServiceChild (
922 HttpInstance->Service->ControllerHandle,
923 HttpInstance->Service->Ip6DriverBindingHandle,
924 &gEfiTcp6ServiceBindingProtocolGuid,
925 HttpInstance->Tcp6ChildHandle
926 );
927 }
928
929 if (HttpInstance->Service->Tcp6ChildHandle != NULL) {
930 gBS->CloseProtocol (
931 HttpInstance->Service->Tcp6ChildHandle,
932 &gEfiTcp6ProtocolGuid,
933 HttpInstance->Service->Ip6DriverBindingHandle,
934 HttpInstance->Handle
935 );
936 }
937
938 TlsCloseTxRxEvent (HttpInstance);
939}
940
941/**
942 Establish TCP connection with HTTP server.
943
944 @param[in] HttpInstance The HTTP instance private data.
945
946 @retval EFI_SUCCESS The TCP connection is established.
947 @retval Others Other error as indicated.
948
949**/
950EFI_STATUS
951HttpCreateConnection (
952 IN HTTP_PROTOCOL *HttpInstance
953 )
954{
955 EFI_STATUS Status;
956
957 //
958 // Connect to Http server
959 //
960 if (!HttpInstance->LocalAddressIsIPv6) {
961 HttpInstance->IsTcp4ConnDone = FALSE;
962 HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY;
963 Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken);
964 if (EFI_ERROR (Status)) {
965 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));
966 return Status;
967 }
968
969 while (!HttpInstance->IsTcp4ConnDone) {
970 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
971 }
972
973 Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;
974
975 } else {
976 HttpInstance->IsTcp6ConnDone = FALSE;
977 HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY;
978 Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken);
979 if (EFI_ERROR (Status)) {
980 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status));
981 return Status;
982 }
983
984 while(!HttpInstance->IsTcp6ConnDone) {
985 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);
986 }
987
988 Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status;
989 }
990
991 if (!EFI_ERROR (Status)) {
992 HttpInstance->State = HTTP_STATE_TCP_CONNECTED;
993 }
994
995 return Status;
996}
997
998/**
999 Close existing TCP connection.
1000
1001 @param[in] HttpInstance The HTTP instance private data.
1002
1003 @retval EFI_SUCCESS The TCP connection is closed.
1004 @retval Others Other error as indicated.
1005
1006**/
1007EFI_STATUS
1008HttpCloseConnection (
1009 IN HTTP_PROTOCOL *HttpInstance
1010 )
1011{
1012 EFI_STATUS Status;
1013
1014 if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {
1015
1016 if (HttpInstance->LocalAddressIsIPv6) {
1017 HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE;
1018 HttpInstance->IsTcp6CloseDone = FALSE;
1019 Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken);
1020 if (EFI_ERROR (Status)) {
1021 return Status;
1022 }
1023
1024 while (!HttpInstance->IsTcp6CloseDone) {
1025 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);
1026 }
1027
1028 } else {
1029 HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE;
1030 HttpInstance->IsTcp4CloseDone = FALSE;
1031 Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken);
1032 if (EFI_ERROR (Status)) {
1033 return Status;
1034 }
1035
1036 while (!HttpInstance->IsTcp4CloseDone) {
1037 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
1038 }
1039 }
1040
1041 }
1042
1043 HttpInstance->State = HTTP_STATE_TCP_CLOSED;
1044 return EFI_SUCCESS;
1045}
1046
1047/**
1048 Configure TCP4 protocol child.
1049
1050 @param[in] HttpInstance The HTTP instance private data.
1051 @param[in] Wrap The HTTP token's wrap data.
1052
1053 @retval EFI_SUCCESS The TCP4 protocol child is configured.
1054 @retval Others Other error as indicated.
1055
1056**/
1057EFI_STATUS
1058HttpConfigureTcp4 (
1059 IN HTTP_PROTOCOL *HttpInstance,
1060 IN HTTP_TOKEN_WRAP *Wrap
1061 )
1062{
1063 EFI_STATUS Status;
1064 EFI_TCP4_CONFIG_DATA *Tcp4CfgData;
1065 EFI_TCP4_ACCESS_POINT *Tcp4AP;
1066 EFI_TCP4_OPTION *Tcp4Option;
1067
1068 ASSERT (HttpInstance != NULL);
1069
1070
1071 Tcp4CfgData = &HttpInstance->Tcp4CfgData;
1072 ZeroMem (Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));
1073
1074 Tcp4CfgData->TypeOfService = HTTP_TOS_DEAULT;
1075 Tcp4CfgData->TimeToLive = HTTP_TTL_DEAULT;
1076 Tcp4CfgData->ControlOption = &HttpInstance->Tcp4Option;
1077
1078 Tcp4AP = &Tcp4CfgData->AccessPoint;
1079 Tcp4AP->UseDefaultAddress = HttpInstance->IPv4Node.UseDefaultAddress;
1080 if (!Tcp4AP->UseDefaultAddress) {
1081 IP4_COPY_ADDRESS (&Tcp4AP->StationAddress, &HttpInstance->IPv4Node.LocalAddress);
1082 IP4_COPY_ADDRESS (&Tcp4AP->SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);
1083 }
1084
1085 Tcp4AP->StationPort = HttpInstance->IPv4Node.LocalPort;
1086 Tcp4AP->RemotePort = HttpInstance->RemotePort;
1087 Tcp4AP->ActiveFlag = TRUE;
1088 IP4_COPY_ADDRESS (&Tcp4AP->RemoteAddress, &HttpInstance->RemoteAddr);
1089
1090 Tcp4Option = Tcp4CfgData->ControlOption;
1091 Tcp4Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;
1092 Tcp4Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;
1093 Tcp4Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;
1094 Tcp4Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;
1095 Tcp4Option->DataRetries = HTTP_DATA_RETRIES;
1096 Tcp4Option->FinTimeout = HTTP_FIN_TIMEOUT;
1097 Tcp4Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;
1098 Tcp4Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;
1099 Tcp4Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;
1100 Tcp4Option->EnableNagle = TRUE;
1101 Tcp4CfgData->ControlOption = Tcp4Option;
1102
1103 Status = HttpInstance->Tcp4->Configure (HttpInstance->Tcp4, Tcp4CfgData);
1104 if (EFI_ERROR (Status)) {
1105 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp4 - %r\n", Status));
1106 return Status;
1107 }
1108
1109 Status = HttpCreateTcpConnCloseEvent (HttpInstance);
1110 if (EFI_ERROR (Status)) {
1111 return Status;
1112 }
1113
1114 Status = HttpCreateTcpTxEvent (Wrap);
1115 if (EFI_ERROR (Status)) {
1116 return Status;
1117 }
1118
1119 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;
1120
1121 return EFI_SUCCESS;
1122}
1123
1124/**
1125 Configure TCP6 protocol child.
1126
1127 @param[in] HttpInstance The HTTP instance private data.
1128 @param[in] Wrap The HTTP token's wrap data.
1129
1130 @retval EFI_SUCCESS The TCP6 protocol child is configured.
1131 @retval Others Other error as indicated.
1132
1133**/
1134EFI_STATUS
1135HttpConfigureTcp6 (
1136 IN HTTP_PROTOCOL *HttpInstance,
1137 IN HTTP_TOKEN_WRAP *Wrap
1138 )
1139{
1140 EFI_STATUS Status;
1141 EFI_TCP6_CONFIG_DATA *Tcp6CfgData;
1142 EFI_TCP6_ACCESS_POINT *Tcp6Ap;
1143 EFI_TCP6_OPTION *Tcp6Option;
1144
1145 ASSERT (HttpInstance != NULL);
1146
1147 Tcp6CfgData = &HttpInstance->Tcp6CfgData;
1148 ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA));
1149
1150 Tcp6CfgData->TrafficClass = 0;
1151 Tcp6CfgData->HopLimit = 255;
1152 Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option;
1153
1154 Tcp6Ap = &Tcp6CfgData->AccessPoint;
1155 Tcp6Ap->ActiveFlag = TRUE;
1156 Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort;
1157 Tcp6Ap->RemotePort = HttpInstance->RemotePort;
1158 IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress);
1159 IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress , &HttpInstance->RemoteIpv6Addr);
1160
1161 Tcp6Option = Tcp6CfgData->ControlOption;
1162 Tcp6Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;
1163 Tcp6Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;
1164 Tcp6Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;
1165 Tcp6Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;
1166 Tcp6Option->DataRetries = HTTP_DATA_RETRIES;
1167 Tcp6Option->FinTimeout = HTTP_FIN_TIMEOUT;
1168 Tcp6Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;
1169 Tcp6Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;
1170 Tcp6Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;
1171 Tcp6Option->EnableNagle = TRUE;
1172
1173 Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);
1174 if (EFI_ERROR (Status)) {
1175 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp6 - %r\n", Status));
1176 return Status;
1177 }
1178
1179 Status = HttpCreateTcpConnCloseEvent (HttpInstance);
1180 if (EFI_ERROR (Status)) {
1181 return Status;
1182 }
1183
1184 Status = HttpCreateTcpTxEvent (Wrap);
1185 if (EFI_ERROR (Status)) {
1186 return Status;
1187 }
1188
1189 HttpInstance->State = HTTP_STATE_TCP_CONFIGED;
1190
1191 return EFI_SUCCESS;
1192
1193}
1194
1195/**
1196 Check existing TCP connection, if in error state, recover TCP4 connection. Then,
1197 connect one TLS session if required.
1198
1199 @param[in] HttpInstance The HTTP instance private data.
1200
1201 @retval EFI_SUCCESS The TCP connection is established.
1202 @retval EFI_NOT_READY TCP4 protocol child is not created or configured.
1203 @retval Others Other error as indicated.
1204
1205**/
1206EFI_STATUS
1207HttpConnectTcp4 (
1208 IN HTTP_PROTOCOL *HttpInstance
1209 )
1210{
1211 EFI_STATUS Status;
1212 EFI_TCP4_CONNECTION_STATE Tcp4State;
1213
1214
1215 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) {
1216 return EFI_NOT_READY;
1217 }
1218
1219 Status = HttpInstance->Tcp4->GetModeData(
1220 HttpInstance->Tcp4,
1221 &Tcp4State,
1222 NULL,
1223 NULL,
1224 NULL,
1225 NULL
1226 );
1227 if (EFI_ERROR(Status)){
1228 DEBUG ((EFI_D_ERROR, "Tcp4 GetModeData fail - %x\n", Status));
1229 return Status;
1230 }
1231
1232 if (Tcp4State == Tcp4StateEstablished) {
1233 return EFI_SUCCESS;
1234 } else if (Tcp4State > Tcp4StateEstablished ) {
1235 HttpCloseConnection(HttpInstance);
1236 }
1237
1238 Status = HttpCreateConnection (HttpInstance);
1239 if (EFI_ERROR(Status)){
1240 DEBUG ((EFI_D_ERROR, "Tcp4 Connection fail - %x\n", Status));
1241 return Status;
1242 }
1243
1244 //
1245 // Tls session connection.
1246 //
1247 if (HttpInstance->UseHttps) {
1248 if (HttpInstance->TimeoutEvent == NULL) {
1249 //
1250 // Create TimeoutEvent for TLS connection.
1251 //
1252 Status = gBS->CreateEvent (
1253 EVT_TIMER,
1254 TPL_CALLBACK,
1255 NULL,
1256 NULL,
1257 &HttpInstance->TimeoutEvent
1258 );
1259 if (EFI_ERROR (Status)) {
1260 TlsCloseTxRxEvent (HttpInstance);
1261 return Status;
1262 }
1263 }
1264
1265 //
1266 // Start the timer, and wait Timeout seconds for connection.
1267 //
1268 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);
1269 if (EFI_ERROR (Status)) {
1270 TlsCloseTxRxEvent (HttpInstance);
1271 return Status;
1272 }
1273
1274 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);
1275
1276 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);
1277
1278 if (EFI_ERROR (Status)) {
1279 TlsCloseTxRxEvent (HttpInstance);
1280 return Status;
1281 }
1282 }
1283
1284 return Status;
1285}
1286
1287/**
1288 Check existing TCP connection, if in error state, recover TCP6 connection. Then,
1289 connect one TLS session if required.
1290
1291 @param[in] HttpInstance The HTTP instance private data.
1292
1293 @retval EFI_SUCCESS The TCP connection is established.
1294 @retval EFI_NOT_READY TCP6 protocol child is not created or configured.
1295 @retval Others Other error as indicated.
1296
1297**/
1298EFI_STATUS
1299HttpConnectTcp6 (
1300 IN HTTP_PROTOCOL *HttpInstance
1301 )
1302{
1303 EFI_STATUS Status;
1304 EFI_TCP6_CONNECTION_STATE Tcp6State;
1305
1306 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {
1307 return EFI_NOT_READY;
1308 }
1309
1310 Status = HttpInstance->Tcp6->GetModeData (
1311 HttpInstance->Tcp6,
1312 &Tcp6State,
1313 NULL,
1314 NULL,
1315 NULL,
1316 NULL
1317 );
1318
1319 if (EFI_ERROR(Status)){
1320 DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status));
1321 return Status;
1322 }
1323
1324 if (Tcp6State == Tcp6StateEstablished) {
1325 return EFI_SUCCESS;
1326 } else if (Tcp6State > Tcp6StateEstablished ) {
1327 HttpCloseConnection(HttpInstance);
1328 }
1329
1330 Status = HttpCreateConnection (HttpInstance);
1331 if (EFI_ERROR(Status)){
1332 DEBUG ((EFI_D_ERROR, "Tcp6 Connection fail - %x\n", Status));
1333 return Status;
1334 }
1335
1336 //
1337 // Tls session connection.
1338 //
1339 if (HttpInstance->UseHttps) {
1340 if (HttpInstance->TimeoutEvent == NULL) {
1341 //
1342 // Create TimeoutEvent for TLS connection.
1343 //
1344 Status = gBS->CreateEvent (
1345 EVT_TIMER,
1346 TPL_CALLBACK,
1347 NULL,
1348 NULL,
1349 &HttpInstance->TimeoutEvent
1350 );
1351 if (EFI_ERROR (Status)) {
1352 TlsCloseTxRxEvent (HttpInstance);
1353 return Status;
1354 }
1355 }
1356
1357 //
1358 // Start the timer, and wait Timeout seconds for connection.
1359 //
1360 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);
1361 if (EFI_ERROR (Status)) {
1362 TlsCloseTxRxEvent (HttpInstance);
1363 return Status;
1364 }
1365
1366 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);
1367
1368 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);
1369
1370 if (EFI_ERROR (Status)) {
1371 TlsCloseTxRxEvent (HttpInstance);
1372 return Status;
1373 }
1374 }
1375
1376 return Status;
1377}
1378
1379/**
1380 Initialize Http session.
1381
1382 @param[in] HttpInstance The HTTP instance private data.
1383 @param[in] Wrap The HTTP token's wrap data.
1384 @param[in] Configure The Flag indicates whether need to initialize session.
1385 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session.
1386
1387 @retval EFI_SUCCESS The initialization of session is done.
1388 @retval Others Other error as indicated.
1389
1390**/
1391EFI_STATUS
1392HttpInitSession (
1393 IN HTTP_PROTOCOL *HttpInstance,
1394 IN HTTP_TOKEN_WRAP *Wrap,
1395 IN BOOLEAN Configure,
1396 IN BOOLEAN TlsConfigure
1397 )
1398{
1399 EFI_STATUS Status;
1400 ASSERT (HttpInstance != NULL);
1401
1402 //
1403 // Configure Tls session.
1404 //
1405 if (TlsConfigure) {
1406 Status = TlsConfigureSession (HttpInstance);
1407 if (EFI_ERROR (Status)) {
1408 return Status;
1409 }
1410 }
1411
1412 if (!HttpInstance->LocalAddressIsIPv6) {
1413 //
1414 // Configure TCP instance.
1415 //
1416 if (Configure) {
1417 Status = HttpConfigureTcp4 (HttpInstance, Wrap);
1418 if (EFI_ERROR (Status)) {
1419 return Status;
1420 }
1421 }
1422
1423 //
1424 // Connect TCP.
1425 //
1426 Status = HttpConnectTcp4 (HttpInstance);
1427 if (EFI_ERROR (Status)) {
1428 return Status;
1429 }
1430 } else {
1431 //
1432 // Configure TCP instance.
1433 //
1434 if (Configure) {
1435 Status = HttpConfigureTcp6 (HttpInstance, Wrap);
1436 if (EFI_ERROR (Status)) {
1437 return Status;
1438 }
1439 }
1440
1441 //
1442 // Connect TCP.
1443 //
1444 Status = HttpConnectTcp6 (HttpInstance);
1445 if (EFI_ERROR (Status)) {
1446 return Status;
1447 }
1448 }
1449
1450 return EFI_SUCCESS;
1451
1452}
1453
1454/**
1455 Send the HTTP or HTTPS message through TCP4 or TCP6.
1456
1457 @param[in] HttpInstance The HTTP instance private data.
1458 @param[in] Wrap The HTTP token's wrap data.
1459 @param[in] TxString Buffer containing the HTTP message string.
1460 @param[in] TxStringLen Length of the HTTP message string in bytes.
1461
1462 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue.
1463 @retval Others Other error as indicated.
1464
1465**/
1466EFI_STATUS
1467HttpTransmitTcp (
1468 IN HTTP_PROTOCOL *HttpInstance,
1469 IN HTTP_TOKEN_WRAP *Wrap,
1470 IN UINT8 *TxString,
1471 IN UINTN TxStringLen
1472 )
1473{
1474 EFI_STATUS Status;
1475 EFI_TCP4_IO_TOKEN *Tx4Token;
1476 EFI_TCP4_PROTOCOL *Tcp4;
1477 EFI_TCP6_IO_TOKEN *Tx6Token;
1478 EFI_TCP6_PROTOCOL *Tcp6;
1479 UINT8 *Buffer;
1480 UINTN BufferSize;
1481 NET_FRAGMENT TempFragment;
1482
1483 Status = EFI_SUCCESS;
1484 Buffer = NULL;
1485 TempFragment.Len = 0;
1486 TempFragment.Bulk = NULL;
1487
1488 //
1489 // Need to encrypt data.
1490 //
1491 if (HttpInstance->UseHttps) {
1492 //
1493 // Build BufferOut data
1494 //
1495 BufferSize = sizeof (TLS_RECORD_HEADER) + TxStringLen;
1496 Buffer = AllocateZeroPool (BufferSize);
1497 if (Buffer == NULL) {
1498 Status = EFI_OUT_OF_RESOURCES;
1499 return Status;
1500 }
1501 ((TLS_RECORD_HEADER *) Buffer)->ContentType = TlsContentTypeApplicationData;
1502 ((TLS_RECORD_HEADER *) Buffer)->Version.Major = HttpInstance->TlsConfigData.Version.Major;
1503 ((TLS_RECORD_HEADER *) Buffer)->Version.Minor = HttpInstance->TlsConfigData.Version.Minor;
1504 ((TLS_RECORD_HEADER *) Buffer)->Length = (UINT16) (TxStringLen);
1505 CopyMem (Buffer + sizeof (TLS_RECORD_HEADER), TxString, TxStringLen);
1506
1507 //
1508 // Encrypt Packet.
1509 //
1510 Status = TlsProcessMessage (
1511 HttpInstance,
1512 Buffer,
1513 BufferSize,
1514 EfiTlsEncrypt,
1515 &TempFragment
1516 );
1517
1518 FreePool (Buffer);
1519
1520 if (EFI_ERROR (Status)) {
1521 return Status;
1522 }
1523 }
1524
1525 if (!HttpInstance->LocalAddressIsIPv6) {
1526 Tcp4 = HttpInstance->Tcp4;
1527 Tx4Token = &Wrap->TcpWrap.Tx4Token;
1528
1529 if (HttpInstance->UseHttps) {
1530 Tx4Token->Packet.TxData->DataLength = TempFragment.Len;
1531 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = TempFragment.Len;
1532 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TempFragment.Bulk;
1533 } else {
1534 Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;
1535 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;
1536 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;
1537 }
1538
1539 Tx4Token->CompletionToken.Status = EFI_NOT_READY;
1540
1541 Wrap->TcpWrap.IsTxDone = FALSE;
1542 Status = Tcp4->Transmit (Tcp4, Tx4Token);
1543 if (EFI_ERROR (Status)) {
1544 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));
1545 return Status;
1546 }
1547
1548 } else {
1549 Tcp6 = HttpInstance->Tcp6;
1550 Tx6Token = &Wrap->TcpWrap.Tx6Token;
1551
1552 if (HttpInstance->UseHttps) {
1553 Tx6Token->Packet.TxData->DataLength = TempFragment.Len;
1554 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = TempFragment.Len;
1555 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TempFragment.Bulk;
1556 } else {
1557 Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;
1558 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;
1559 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;
1560 }
1561
1562 Tx6Token->CompletionToken.Status = EFI_NOT_READY;
1563
1564 Wrap->TcpWrap.IsTxDone = FALSE;
1565 Status = Tcp6->Transmit (Tcp6, Tx6Token);
1566 if (EFI_ERROR (Status)) {
1567 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));
1568 return Status;
1569 }
1570 }
1571
1572 return Status;
1573}
1574
1575/**
1576 Check whether the user's token or event has already
1577 been enqueue on HTTP Tx or Rx Token list.
1578
1579 @param[in] Map The container of either user's transmit or receive
1580 token.
1581 @param[in] Item Current item to check against.
1582 @param[in] Context The Token to check againist.
1583
1584 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1585 @retval EFI_SUCCESS The current item isn't the same token/event as the
1586 context.
1587
1588**/
1589EFI_STATUS
1590EFIAPI
1591HttpTokenExist (
1592 IN NET_MAP *Map,
1593 IN NET_MAP_ITEM *Item,
1594 IN VOID *Context
1595 )
1596{
1597 EFI_HTTP_TOKEN *Token;
1598 EFI_HTTP_TOKEN *TokenInItem;
1599
1600 Token = (EFI_HTTP_TOKEN *) Context;
1601 TokenInItem = (EFI_HTTP_TOKEN *) Item->Key;
1602
1603 if (Token == TokenInItem || Token->Event == TokenInItem->Event) {
1604 return EFI_ACCESS_DENIED;
1605 }
1606
1607 return EFI_SUCCESS;
1608}
1609
1610/**
1611 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.
1612
1613 @param[in] Map The container of Tx4Token or Tx6Token.
1614 @param[in] Item Current item to check against.
1615 @param[in] Context The Token to check againist.
1616
1617 @retval EFI_NOT_READY The HTTP message is still queued in the list.
1618 @retval EFI_SUCCESS The HTTP message has been sent out.
1619
1620**/
1621EFI_STATUS
1622EFIAPI
1623HttpTcpNotReady (
1624 IN NET_MAP *Map,
1625 IN NET_MAP_ITEM *Item,
1626 IN VOID *Context
1627 )
1628{
1629 HTTP_TOKEN_WRAP *ValueInItem;
1630
1631 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;
1632
1633 if (!ValueInItem->TcpWrap.IsTxDone) {
1634 return EFI_NOT_READY;
1635 }
1636
1637 return EFI_SUCCESS;
1638}
1639
1640/**
1641 Transmit the HTTP or HTTPS mssage by processing the associated HTTP token.
1642
1643 @param[in] Map The container of Tx4Token or Tx6Token.
1644 @param[in] Item Current item to check against.
1645 @param[in] Context The Token to check againist.
1646
1647 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1648 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit
1649 queue.
1650
1651**/
1652EFI_STATUS
1653EFIAPI
1654HttpTcpTransmit (
1655 IN NET_MAP *Map,
1656 IN NET_MAP_ITEM *Item,
1657 IN VOID *Context
1658 )
1659{
1660 HTTP_TOKEN_WRAP *ValueInItem;
1661 EFI_STATUS Status;
1662 CHAR8 *RequestMsg;
1663 CHAR8 *Url;
1664 UINTN UrlSize;
1665 UINTN RequestMsgSize;
1666
1667 RequestMsg = NULL;
1668
1669 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;
1670 if (ValueInItem->TcpWrap.IsTxDone) {
1671 return EFI_SUCCESS;
1672 }
1673
1674 //
1675 // Parse the URI of the remote host.
1676 //
1677 UrlSize = StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1;
1678 Url = AllocatePool (UrlSize);
1679 if (Url == NULL) {
1680 return EFI_OUT_OF_RESOURCES;
1681 }
1682
1683 UnicodeStrToAsciiStrS (ValueInItem->HttpToken->Message->Data.Request->Url, Url, UrlSize);
1684
1685 //
1686 // Create request message.
1687 //
1688 Status = HttpGenRequestMessage (
1689 ValueInItem->HttpToken->Message,
1690 Url,
1691 &RequestMsg,
1692 &RequestMsgSize
1693 );
1694 FreePool (Url);
1695
1696 if (EFI_ERROR (Status) || NULL == RequestMsg){
1697 return Status;
1698 }
1699
1700 ASSERT (RequestMsg != NULL);
1701
1702 //
1703 // Transmit the request message.
1704 //
1705 Status = HttpTransmitTcp (
1706 ValueInItem->HttpInstance,
1707 ValueInItem,
1708 (UINT8*) RequestMsg,
1709 RequestMsgSize
1710 );
1711 FreePool (RequestMsg);
1712 return Status;
1713}
1714
1715/**
1716 Receive the HTTP response by processing the associated HTTP token.
1717
1718 @param[in] Map The container of Rx4Token or Rx6Token.
1719 @param[in] Item Current item to check against.
1720 @param[in] Context The Token to check againist.
1721
1722 @retval EFI_SUCCESS The HTTP response is queued into TCP receive
1723 queue.
1724 @retval Others Other error as indicated.
1725
1726**/
1727EFI_STATUS
1728EFIAPI
1729HttpTcpReceive (
1730 IN NET_MAP *Map,
1731 IN NET_MAP_ITEM *Item,
1732 IN VOID *Context
1733 )
1734{
1735 //
1736 // Process the queued HTTP response.
1737 //
1738 return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value);
1739}
1740
1741/**
1742 Receive the HTTP header by processing the associated HTTP token.
1743
1744 @param[in] HttpInstance The HTTP instance private data.
1745 @param[in, out] SizeofHeaders The HTTP header length.
1746 @param[in, out] BufferSize The size of buffer to cacahe the header message.
1747 @param[in] Timeout The time to wait for receiving the header packet.
1748
1749 @retval EFI_SUCCESS The HTTP header is received.
1750 @retval Others Other errors as indicated.
1751
1752**/
1753EFI_STATUS
1754HttpTcpReceiveHeader (
1755 IN HTTP_PROTOCOL *HttpInstance,
1756 IN OUT UINTN *SizeofHeaders,
1757 IN OUT UINTN *BufferSize,
1758 IN EFI_EVENT Timeout
1759 )
1760{
1761 EFI_STATUS Status;
1762 EFI_TCP4_IO_TOKEN *Rx4Token;
1763 EFI_TCP4_PROTOCOL *Tcp4;
1764 EFI_TCP6_IO_TOKEN *Rx6Token;
1765 EFI_TCP6_PROTOCOL *Tcp6;
1766 CHAR8 **EndofHeader;
1767 CHAR8 **HttpHeaders;
1768 CHAR8 *Buffer;
1769 NET_FRAGMENT Fragment;
1770
1771 ASSERT (HttpInstance != NULL);
1772
1773 EndofHeader = HttpInstance->EndofHeader;
1774 HttpHeaders = HttpInstance->HttpHeaders;
1775 Tcp4 = HttpInstance->Tcp4;
1776 Tcp6 = HttpInstance->Tcp6;
1777 Buffer = NULL;
1778 Rx4Token = NULL;
1779 Rx6Token = NULL;
1780 Fragment.Len = 0;
1781 Fragment.Bulk = NULL;
1782
1783 if (HttpInstance->LocalAddressIsIPv6) {
1784 ASSERT (Tcp6 != NULL);
1785 } else {
1786 ASSERT (Tcp4 != NULL);
1787 }
1788
1789 if (!HttpInstance->UseHttps) {
1790 Status = HttpCreateTcpRxEventForHeader (HttpInstance);
1791 if (EFI_ERROR (Status)) {
1792 return Status;
1793 }
1794 }
1795
1796 if (!HttpInstance->LocalAddressIsIPv6) {
1797 if (!HttpInstance->UseHttps) {
1798 Rx4Token = &HttpInstance->Rx4Token;
1799 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);
1800 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {
1801 Status = EFI_OUT_OF_RESOURCES;
1802 return Status;
1803 }
1804 }
1805
1806 //
1807 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1808 //
1809 while (*EndofHeader == NULL) {
1810 if (!HttpInstance->UseHttps) {
1811 HttpInstance->IsRxDone = FALSE;
1812 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;
1813 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;
1814 Status = Tcp4->Receive (Tcp4, Rx4Token);
1815 if (EFI_ERROR (Status)) {
1816 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));
1817 return Status;
1818 }
1819
1820 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
1821 Tcp4->Poll (Tcp4);
1822 }
1823
1824 if (!HttpInstance->IsRxDone) {
1825 //
1826 // Cancle the Token before close its Event.
1827 //
1828 Tcp4->Cancel (HttpInstance->Tcp4, &Rx4Token->CompletionToken);
1829 gBS->CloseEvent (Rx4Token->CompletionToken.Event);
1830 Rx4Token->CompletionToken.Status = EFI_TIMEOUT;
1831 }
1832
1833 Status = Rx4Token->CompletionToken.Status;
1834 if (EFI_ERROR (Status)) {
1835 return Status;
1836 }
1837
1838 Fragment.Len = Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;
1839 Fragment.Bulk = (UINT8 *) Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer;
1840 } else {
1841 if (Fragment.Bulk != NULL) {
1842 FreePool (Fragment.Bulk);
1843 Fragment.Bulk = NULL;
1844 }
1845
1846 Status = HttpsReceive (HttpInstance, &Fragment, Timeout);
1847 if (EFI_ERROR (Status)) {
1848 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));
1849 return Status;
1850 }
1851 }
1852
1853 //
1854 // Append the response string.
1855 //
1856 *BufferSize = *SizeofHeaders + Fragment.Len;
1857 Buffer = AllocateZeroPool (*BufferSize);
1858 if (Buffer == NULL) {
1859 Status = EFI_OUT_OF_RESOURCES;
1860 return Status;
1861 }
1862
1863 if (*HttpHeaders != NULL) {
1864 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);
1865 FreePool (*HttpHeaders);
1866 }
1867
1868 CopyMem (
1869 Buffer + *SizeofHeaders,
1870 Fragment.Bulk,
1871 Fragment.Len
1872 );
1873 *HttpHeaders = Buffer;
1874 *SizeofHeaders = *BufferSize;
1875
1876 //
1877 // Check whether we received end of HTTP headers.
1878 //
1879 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);
1880 };
1881
1882 //
1883 // Free the buffer.
1884 //
1885 if (Rx4Token != NULL && Rx4Token->Packet.RxData != NULL && Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
1886 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);
1887 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
1888 Fragment.Bulk = NULL;
1889 }
1890
1891 if (Fragment.Bulk != NULL) {
1892 FreePool (Fragment.Bulk);
1893 Fragment.Bulk = NULL;
1894 }
1895 } else {
1896 if (!HttpInstance->UseHttps) {
1897 Rx6Token = &HttpInstance->Rx6Token;
1898 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);
1899 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {
1900 Status = EFI_OUT_OF_RESOURCES;
1901 return Status;
1902 }
1903 }
1904
1905 //
1906 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.
1907 //
1908 while (*EndofHeader == NULL) {
1909 if (!HttpInstance->UseHttps) {
1910 HttpInstance->IsRxDone = FALSE;
1911 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;
1912 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;
1913 Status = Tcp6->Receive (Tcp6, Rx6Token);
1914 if (EFI_ERROR (Status)) {
1915 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));
1916 return Status;
1917 }
1918
1919 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
1920 Tcp6->Poll (Tcp6);
1921 }
1922
1923 if (!HttpInstance->IsRxDone) {
1924 //
1925 // Cancle the Token before close its Event.
1926 //
1927 Tcp6->Cancel (HttpInstance->Tcp6, &Rx6Token->CompletionToken);
1928 gBS->CloseEvent (Rx6Token->CompletionToken.Event);
1929 Rx6Token->CompletionToken.Status = EFI_TIMEOUT;
1930 }
1931
1932 Status = Rx6Token->CompletionToken.Status;
1933 if (EFI_ERROR (Status)) {
1934 return Status;
1935 }
1936
1937 Fragment.Len = Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;
1938 Fragment.Bulk = (UINT8 *) Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer;
1939 } else {
1940 if (Fragment.Bulk != NULL) {
1941 FreePool (Fragment.Bulk);
1942 Fragment.Bulk = NULL;
1943 }
1944
1945 Status = HttpsReceive (HttpInstance, &Fragment, Timeout);
1946 if (EFI_ERROR (Status)) {
1947 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));
1948 return Status;
1949 }
1950 }
1951
1952 //
1953 // Append the response string.
1954 //
1955 *BufferSize = *SizeofHeaders + Fragment.Len;
1956 Buffer = AllocateZeroPool (*BufferSize);
1957 if (Buffer == NULL) {
1958 Status = EFI_OUT_OF_RESOURCES;
1959 return Status;
1960 }
1961
1962 if (*HttpHeaders != NULL) {
1963 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);
1964 FreePool (*HttpHeaders);
1965 }
1966
1967 CopyMem (
1968 Buffer + *SizeofHeaders,
1969 Fragment.Bulk,
1970 Fragment.Len
1971 );
1972 *HttpHeaders = Buffer;
1973 *SizeofHeaders = *BufferSize;
1974
1975 //
1976 // Check whether we received end of HTTP headers.
1977 //
1978 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);
1979 };
1980
1981 //
1982 // Free the buffer.
1983 //
1984 if (Rx6Token != NULL && Rx6Token->Packet.RxData != NULL && Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
1985 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);
1986 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
1987 Fragment.Bulk = NULL;
1988 }
1989
1990 if (Fragment.Bulk != NULL) {
1991 FreePool (Fragment.Bulk);
1992 Fragment.Bulk = NULL;
1993 }
1994 }
1995
1996 //
1997 // Skip the CRLF after the HTTP headers.
1998 //
1999 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);
2000
2001 *SizeofHeaders = *EndofHeader - *HttpHeaders;
2002
2003 return EFI_SUCCESS;
2004}
2005
2006/**
2007 Receive the HTTP body by processing the associated HTTP token.
2008
2009 @param[in] Wrap The HTTP token's wrap data.
2010 @param[in] HttpMsg The HTTP message data.
2011
2012 @retval EFI_SUCCESS The HTTP body is received.
2013 @retval Others Other error as indicated.
2014
2015**/
2016EFI_STATUS
2017HttpTcpReceiveBody (
2018 IN HTTP_TOKEN_WRAP *Wrap,
2019 IN EFI_HTTP_MESSAGE *HttpMsg
2020 )
2021{
2022 EFI_STATUS Status;
2023 HTTP_PROTOCOL *HttpInstance;
2024 EFI_TCP6_PROTOCOL *Tcp6;
2025 EFI_TCP6_IO_TOKEN *Rx6Token;
2026 EFI_TCP4_PROTOCOL *Tcp4;
2027 EFI_TCP4_IO_TOKEN *Rx4Token;
2028
2029 HttpInstance = Wrap->HttpInstance;
2030 Tcp4 = HttpInstance->Tcp4;
2031 Tcp6 = HttpInstance->Tcp6;
2032 Rx4Token = NULL;
2033 Rx6Token = NULL;
2034
2035 if (HttpInstance->LocalAddressIsIPv6) {
2036 ASSERT (Tcp6 != NULL);
2037 } else {
2038 ASSERT (Tcp4 != NULL);
2039 }
2040
2041 if (HttpInstance->LocalAddressIsIPv6) {
2042 Rx6Token = &Wrap->TcpWrap.Rx6Token;
2043 Rx6Token ->Packet.RxData->DataLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);
2044 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);
2045 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;
2046 Rx6Token->CompletionToken.Status = EFI_NOT_READY;
2047
2048 Status = Tcp6->Receive (Tcp6, Rx6Token);
2049 if (EFI_ERROR (Status)) {
2050 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));
2051 return Status;
2052 }
2053 } else {
2054 Rx4Token = &Wrap->TcpWrap.Rx4Token;
2055 Rx4Token->Packet.RxData->DataLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);
2056 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);
2057 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;
2058
2059 Rx4Token->CompletionToken.Status = EFI_NOT_READY;
2060 Status = Tcp4->Receive (Tcp4, Rx4Token);
2061 if (EFI_ERROR (Status)) {
2062 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));
2063 return Status;
2064 }
2065 }
2066
2067 return EFI_SUCCESS;
2068
2069}
2070
2071/**
2072 Clean up Tcp Tokens while the Tcp transmission error occurs.
2073
2074 @param[in] Wrap Pointer to HTTP token's wrap data.
2075
2076**/
2077VOID
2078HttpTcpTokenCleanup (
2079 IN HTTP_TOKEN_WRAP *Wrap
2080 )
2081{
2082 HTTP_PROTOCOL *HttpInstance;
2083 EFI_TCP4_IO_TOKEN *Rx4Token;
2084 EFI_TCP6_IO_TOKEN *Rx6Token;
2085
2086 ASSERT (Wrap != NULL);
2087 HttpInstance = Wrap->HttpInstance;
2088 Rx4Token = NULL;
2089 Rx6Token = NULL;
2090
2091 if (HttpInstance->LocalAddressIsIPv6) {
2092 Rx6Token = &Wrap->TcpWrap.Rx6Token;
2093
2094 if (Rx6Token->CompletionToken.Event != NULL) {
2095 gBS->CloseEvent (Rx6Token->CompletionToken.Event);
2096 Rx6Token->CompletionToken.Event = NULL;
2097 }
2098
2099 FreePool (Wrap);
2100
2101 Rx6Token = &HttpInstance->Rx6Token;
2102
2103 if (Rx6Token->CompletionToken.Event != NULL) {
2104 gBS->CloseEvent (Rx6Token->CompletionToken.Event);
2105 Rx6Token->CompletionToken.Event = NULL;
2106 }
2107
2108 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
2109 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);
2110 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
2111 }
2112
2113 } else {
2114 Rx4Token = &Wrap->TcpWrap.Rx4Token;
2115
2116 if (Rx4Token->CompletionToken.Event != NULL) {
2117 gBS->CloseEvent (Rx4Token->CompletionToken.Event);
2118 Rx4Token->CompletionToken.Event = NULL;
2119 }
2120
2121 FreePool (Wrap);
2122
2123 Rx4Token = &HttpInstance->Rx4Token;
2124
2125 if (Rx4Token->CompletionToken.Event != NULL) {
2126 gBS->CloseEvent (Rx4Token->CompletionToken.Event);
2127 Rx4Token->CompletionToken.Event = NULL;
2128 }
2129
2130
2131 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
2132 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);
2133 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
2134 }
2135 }
2136
2137}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette