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