1 /** @file 2 Miscellaneous routines for HttpDxe driver. 3 4 Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR> 5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 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 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 **/ 269 VOID 270 EFIAPI 271 HttpTcpReceiveNotify ( 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 **/ 291 EFI_STATUS 292 HttpCreateTcpConnCloseEvent ( 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 359 ERROR: 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 **/ 375 VOID 376 HttpCloseTcpConnCloseEvent ( 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 **/ 416 EFI_STATUS 417 HttpCreateTcpTxEvent ( 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 **/ 478 EFI_STATUS 479 HttpCreateTcpRxEventForHeader ( 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 **/ 532 EFI_STATUS 533 HttpCreateTcpRxEvent ( 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 **/ 585 VOID 586 HttpCloseTcpRxEvent ( 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 **/ 626 EFI_STATUS 627 HttpInitProtocol ( 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->ImageHandle, 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->ImageHandle, 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->ImageHandle, 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->ImageHandle, 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->ImageHandle, 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->ImageHandle, 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->ImageHandle, 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->ImageHandle, 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 753 ON_ERROR: 754 755 if (HttpInstance->Tcp4ChildHandle != NULL) { 756 gBS->CloseProtocol ( 757 HttpInstance->Tcp4ChildHandle, 758 &gEfiTcp4ProtocolGuid, 759 HttpInstance->Service->ImageHandle, 760 HttpInstance->Service->ControllerHandle 761 ); 762 763 gBS->CloseProtocol ( 764 HttpInstance->Tcp4ChildHandle, 765 &gEfiTcp4ProtocolGuid, 766 HttpInstance->Service->ImageHandle, 767 HttpInstance->Handle 768 ); 769 770 NetLibDestroyServiceChild ( 771 HttpInstance->Service->ControllerHandle, 772 HttpInstance->Service->ImageHandle, 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->ImageHandle, 783 HttpInstance->Handle 784 ); 785 } 786 787 if (HttpInstance->Tcp6ChildHandle != NULL) { 788 gBS->CloseProtocol ( 789 HttpInstance->Tcp6ChildHandle, 790 &gEfiTcp6ProtocolGuid, 791 HttpInstance->Service->ImageHandle, 792 HttpInstance->Service->ControllerHandle 793 ); 794 795 gBS->CloseProtocol ( 796 HttpInstance->Tcp6ChildHandle, 797 &gEfiTcp6ProtocolGuid, 798 HttpInstance->Service->ImageHandle, 799 HttpInstance->Handle 800 ); 801 802 NetLibDestroyServiceChild ( 803 HttpInstance->Service->ControllerHandle, 804 HttpInstance->Service->ImageHandle, 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->ImageHandle, 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 **/ 829 VOID 830 HttpCleanProtocol ( 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->Tcp4ChildHandle != NULL) { 868 gBS->CloseProtocol ( 869 HttpInstance->Tcp4ChildHandle, 870 &gEfiTcp4ProtocolGuid, 871 HttpInstance->Service->ImageHandle, 872 HttpInstance->Service->ControllerHandle 873 ); 874 875 gBS->CloseProtocol ( 876 HttpInstance->Tcp4ChildHandle, 877 &gEfiTcp4ProtocolGuid, 878 HttpInstance->Service->ImageHandle, 879 HttpInstance->Handle 880 ); 881 882 NetLibDestroyServiceChild ( 883 HttpInstance->Service->ControllerHandle, 884 HttpInstance->Service->ImageHandle, 885 &gEfiTcp4ServiceBindingProtocolGuid, 886 HttpInstance->Tcp4ChildHandle 887 ); 888 } 889 890 if (HttpInstance->Service->Tcp4ChildHandle != NULL) { 891 gBS->CloseProtocol ( 892 HttpInstance->Service->Tcp4ChildHandle, 893 &gEfiTcp4ProtocolGuid, 894 HttpInstance->Service->ImageHandle, 895 HttpInstance->Handle 896 ); 897 } 898 899 if (HttpInstance->Tcp6ChildHandle != NULL) { 900 gBS->CloseProtocol ( 901 HttpInstance->Tcp6ChildHandle, 902 &gEfiTcp6ProtocolGuid, 903 HttpInstance->Service->ImageHandle, 904 HttpInstance->Service->ControllerHandle 905 ); 906 907 gBS->CloseProtocol ( 908 HttpInstance->Tcp6ChildHandle, 909 &gEfiTcp6ProtocolGuid, 910 HttpInstance->Service->ImageHandle, 911 HttpInstance->Handle 912 ); 913 914 NetLibDestroyServiceChild ( 915 HttpInstance->Service->ControllerHandle, 916 HttpInstance->Service->ImageHandle, 917 &gEfiTcp6ServiceBindingProtocolGuid, 918 HttpInstance->Tcp6ChildHandle 919 ); 920 } 921 922 if (HttpInstance->Service->Tcp6ChildHandle != NULL) { 923 gBS->CloseProtocol ( 924 HttpInstance->Service->Tcp6ChildHandle, 925 &gEfiTcp6ProtocolGuid, 926 HttpInstance->Service->ImageHandle, 927 HttpInstance->Handle 928 ); 929 } 930 931 TlsCloseTxRxEvent (HttpInstance); 932 } 933 934 /** 935 Establish TCP connection with HTTP server. 936 937 @param[in] HttpInstance The HTTP instance private data. 938 939 @retval EFI_SUCCESS The TCP connection is established. 940 @retval Others Other error as indicated. 941 942 **/ 943 EFI_STATUS 944 HttpCreateConnection ( 945 IN HTTP_PROTOCOL *HttpInstance 946 ) 947 { 948 EFI_STATUS Status; 949 950 // 951 // Connect to Http server 952 // 953 if (!HttpInstance->LocalAddressIsIPv6) { 954 HttpInstance->IsTcp4ConnDone = FALSE; 955 HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY; 956 Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken); 957 if (EFI_ERROR (Status)) { 958 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status)); 959 return Status; 960 } 961 962 while (!HttpInstance->IsTcp4ConnDone) { 963 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4); 964 } 965 966 Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status; 967 968 } else { 969 HttpInstance->IsTcp6ConnDone = FALSE; 970 HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY; 971 Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken); 972 if (EFI_ERROR (Status)) { 973 DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status)); 974 return Status; 975 } 976 977 while(!HttpInstance->IsTcp6ConnDone) { 978 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6); 979 } 980 981 Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status; 982 } 983 984 if (!EFI_ERROR (Status)) { 985 HttpInstance->State = HTTP_STATE_TCP_CONNECTED; 986 } 987 988 return Status; 989 } 990 991 /** 992 Close existing TCP connection. 993 994 @param[in] HttpInstance The HTTP instance private data. 995 996 @retval EFI_SUCCESS The TCP connection is closed. 997 @retval Others Other error as indicated. 998 999 **/ 1000 EFI_STATUS 1001 HttpCloseConnection ( 1002 IN HTTP_PROTOCOL *HttpInstance 1003 ) 1004 { 1005 EFI_STATUS Status; 1006 1007 if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) { 1008 1009 if (HttpInstance->LocalAddressIsIPv6) { 1010 HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE; 1011 HttpInstance->IsTcp6CloseDone = FALSE; 1012 Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken); 1013 if (EFI_ERROR (Status)) { 1014 return Status; 1015 } 1016 1017 while (!HttpInstance->IsTcp6CloseDone) { 1018 HttpInstance->Tcp6->Poll (HttpInstance->Tcp6); 1019 } 1020 1021 } else { 1022 HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE; 1023 HttpInstance->IsTcp4CloseDone = FALSE; 1024 Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken); 1025 if (EFI_ERROR (Status)) { 1026 return Status; 1027 } 1028 1029 while (!HttpInstance->IsTcp4CloseDone) { 1030 HttpInstance->Tcp4->Poll (HttpInstance->Tcp4); 1031 } 1032 } 1033 1034 } 1035 1036 HttpInstance->State = HTTP_STATE_TCP_CLOSED; 1037 return EFI_SUCCESS; 1038 } 1039 1040 /** 1041 Configure TCP4 protocol child. 1042 1043 @param[in] HttpInstance The HTTP instance private data. 1044 @param[in] Wrap The HTTP token's wrap data. 1045 1046 @retval EFI_SUCCESS The TCP4 protocol child is configured. 1047 @retval Others Other error as indicated. 1048 1049 **/ 1050 EFI_STATUS 1051 HttpConfigureTcp4 ( 1052 IN HTTP_PROTOCOL *HttpInstance, 1053 IN HTTP_TOKEN_WRAP *Wrap 1054 ) 1055 { 1056 EFI_STATUS Status; 1057 EFI_TCP4_CONFIG_DATA *Tcp4CfgData; 1058 EFI_TCP4_ACCESS_POINT *Tcp4AP; 1059 EFI_TCP4_OPTION *Tcp4Option; 1060 1061 ASSERT (HttpInstance != NULL); 1062 1063 1064 Tcp4CfgData = &HttpInstance->Tcp4CfgData; 1065 ZeroMem (Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA)); 1066 1067 Tcp4CfgData->TypeOfService = HTTP_TOS_DEAULT; 1068 Tcp4CfgData->TimeToLive = HTTP_TTL_DEAULT; 1069 Tcp4CfgData->ControlOption = &HttpInstance->Tcp4Option; 1070 1071 Tcp4AP = &Tcp4CfgData->AccessPoint; 1072 Tcp4AP->UseDefaultAddress = HttpInstance->IPv4Node.UseDefaultAddress; 1073 if (!Tcp4AP->UseDefaultAddress) { 1074 IP4_COPY_ADDRESS (&Tcp4AP->StationAddress, &HttpInstance->IPv4Node.LocalAddress); 1075 IP4_COPY_ADDRESS (&Tcp4AP->SubnetMask, &HttpInstance->IPv4Node.LocalSubnet); 1076 } 1077 1078 Tcp4AP->StationPort = HttpInstance->IPv4Node.LocalPort; 1079 Tcp4AP->RemotePort = HttpInstance->RemotePort; 1080 Tcp4AP->ActiveFlag = TRUE; 1081 IP4_COPY_ADDRESS (&Tcp4AP->RemoteAddress, &HttpInstance->RemoteAddr); 1082 1083 Tcp4Option = Tcp4CfgData->ControlOption; 1084 Tcp4Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT; 1085 Tcp4Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT; 1086 Tcp4Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG; 1087 Tcp4Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT; 1088 Tcp4Option->DataRetries = HTTP_DATA_RETRIES; 1089 Tcp4Option->FinTimeout = HTTP_FIN_TIMEOUT; 1090 Tcp4Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES; 1091 Tcp4Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME; 1092 Tcp4Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL; 1093 Tcp4Option->EnableNagle = TRUE; 1094 Tcp4CfgData->ControlOption = Tcp4Option; 1095 1096 Status = HttpInstance->Tcp4->Configure (HttpInstance->Tcp4, Tcp4CfgData); 1097 if (EFI_ERROR (Status)) { 1098 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp4 - %r\n", Status)); 1099 return Status; 1100 } 1101 1102 Status = HttpCreateTcpConnCloseEvent (HttpInstance); 1103 if (EFI_ERROR (Status)) { 1104 return Status; 1105 } 1106 1107 Status = HttpCreateTcpTxEvent (Wrap); 1108 if (EFI_ERROR (Status)) { 1109 return Status; 1110 } 1111 1112 HttpInstance->State = HTTP_STATE_TCP_CONFIGED; 1113 1114 return EFI_SUCCESS; 1115 } 1116 1117 /** 1118 Configure TCP6 protocol child. 1119 1120 @param[in] HttpInstance The HTTP instance private data. 1121 @param[in] Wrap The HTTP token's wrap data. 1122 1123 @retval EFI_SUCCESS The TCP6 protocol child is configured. 1124 @retval Others Other error as indicated. 1125 1126 **/ 1127 EFI_STATUS 1128 HttpConfigureTcp6 ( 1129 IN HTTP_PROTOCOL *HttpInstance, 1130 IN HTTP_TOKEN_WRAP *Wrap 1131 ) 1132 { 1133 EFI_STATUS Status; 1134 EFI_TCP6_CONFIG_DATA *Tcp6CfgData; 1135 EFI_TCP6_ACCESS_POINT *Tcp6Ap; 1136 EFI_TCP6_OPTION *Tcp6Option; 1137 1138 ASSERT (HttpInstance != NULL); 1139 1140 Tcp6CfgData = &HttpInstance->Tcp6CfgData; 1141 ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA)); 1142 1143 Tcp6CfgData->TrafficClass = 0; 1144 Tcp6CfgData->HopLimit = 255; 1145 Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option; 1146 1147 Tcp6Ap = &Tcp6CfgData->AccessPoint; 1148 Tcp6Ap->ActiveFlag = TRUE; 1149 Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort; 1150 Tcp6Ap->RemotePort = HttpInstance->RemotePort; 1151 IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress); 1152 IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress , &HttpInstance->RemoteIpv6Addr); 1153 1154 Tcp6Option = Tcp6CfgData->ControlOption; 1155 Tcp6Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT; 1156 Tcp6Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT; 1157 Tcp6Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG; 1158 Tcp6Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT; 1159 Tcp6Option->DataRetries = HTTP_DATA_RETRIES; 1160 Tcp6Option->FinTimeout = HTTP_FIN_TIMEOUT; 1161 Tcp6Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES; 1162 Tcp6Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME; 1163 Tcp6Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL; 1164 Tcp6Option->EnableNagle = TRUE; 1165 1166 Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData); 1167 if (EFI_ERROR (Status)) { 1168 DEBUG ((EFI_D_ERROR, "HttpConfigureTcp6 - %r\n", Status)); 1169 return Status; 1170 } 1171 1172 Status = HttpCreateTcpConnCloseEvent (HttpInstance); 1173 if (EFI_ERROR (Status)) { 1174 return Status; 1175 } 1176 1177 Status = HttpCreateTcpTxEvent (Wrap); 1178 if (EFI_ERROR (Status)) { 1179 return Status; 1180 } 1181 1182 HttpInstance->State = HTTP_STATE_TCP_CONFIGED; 1183 1184 return EFI_SUCCESS; 1185 1186 } 1187 1188 /** 1189 Check existing TCP connection, if in error state, recover TCP4 connection. Then, 1190 connect one TLS session if required. 1191 1192 @param[in] HttpInstance The HTTP instance private data. 1193 1194 @retval EFI_SUCCESS The TCP connection is established. 1195 @retval EFI_NOT_READY TCP4 protocol child is not created or configured. 1196 @retval Others Other error as indicated. 1197 1198 **/ 1199 EFI_STATUS 1200 HttpConnectTcp4 ( 1201 IN HTTP_PROTOCOL *HttpInstance 1202 ) 1203 { 1204 EFI_STATUS Status; 1205 EFI_TCP4_CONNECTION_STATE Tcp4State; 1206 1207 1208 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) { 1209 return EFI_NOT_READY; 1210 } 1211 1212 Status = HttpInstance->Tcp4->GetModeData( 1213 HttpInstance->Tcp4, 1214 &Tcp4State, 1215 NULL, 1216 NULL, 1217 NULL, 1218 NULL 1219 ); 1220 if (EFI_ERROR(Status)){ 1221 DEBUG ((EFI_D_ERROR, "Tcp4 GetModeData fail - %x\n", Status)); 1222 return Status; 1223 } 1224 1225 if (Tcp4State == Tcp4StateEstablished) { 1226 return EFI_SUCCESS; 1227 } else if (Tcp4State > Tcp4StateEstablished ) { 1228 HttpCloseConnection(HttpInstance); 1229 } 1230 1231 Status = HttpCreateConnection (HttpInstance); 1232 if (EFI_ERROR(Status)){ 1233 DEBUG ((EFI_D_ERROR, "Tcp4 Connection fail - %x\n", Status)); 1234 return Status; 1235 } 1236 1237 // 1238 // Tls session connection. 1239 // 1240 if (HttpInstance->UseHttps) { 1241 if (HttpInstance->TimeoutEvent == NULL) { 1242 // 1243 // Create TimeoutEvent for TLS connection. 1244 // 1245 Status = gBS->CreateEvent ( 1246 EVT_TIMER, 1247 TPL_CALLBACK, 1248 NULL, 1249 NULL, 1250 &HttpInstance->TimeoutEvent 1251 ); 1252 if (EFI_ERROR (Status)) { 1253 TlsCloseTxRxEvent (HttpInstance); 1254 return Status; 1255 } 1256 } 1257 1258 // 1259 // Start the timer, and wait Timeout seconds for connection. 1260 // 1261 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND); 1262 if (EFI_ERROR (Status)) { 1263 TlsCloseTxRxEvent (HttpInstance); 1264 return Status; 1265 } 1266 1267 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent); 1268 1269 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0); 1270 1271 if (EFI_ERROR (Status)) { 1272 TlsCloseTxRxEvent (HttpInstance); 1273 return Status; 1274 } 1275 } 1276 1277 return Status; 1278 } 1279 1280 /** 1281 Check existing TCP connection, if in error state, recover TCP6 connection. Then, 1282 connect one TLS session if required. 1283 1284 @param[in] HttpInstance The HTTP instance private data. 1285 1286 @retval EFI_SUCCESS The TCP connection is established. 1287 @retval EFI_NOT_READY TCP6 protocol child is not created or configured. 1288 @retval Others Other error as indicated. 1289 1290 **/ 1291 EFI_STATUS 1292 HttpConnectTcp6 ( 1293 IN HTTP_PROTOCOL *HttpInstance 1294 ) 1295 { 1296 EFI_STATUS Status; 1297 EFI_TCP6_CONNECTION_STATE Tcp6State; 1298 1299 if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) { 1300 return EFI_NOT_READY; 1301 } 1302 1303 Status = HttpInstance->Tcp6->GetModeData ( 1304 HttpInstance->Tcp6, 1305 &Tcp6State, 1306 NULL, 1307 NULL, 1308 NULL, 1309 NULL 1310 ); 1311 1312 if (EFI_ERROR(Status)){ 1313 DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status)); 1314 return Status; 1315 } 1316 1317 if (Tcp6State == Tcp6StateEstablished) { 1318 return EFI_SUCCESS; 1319 } else if (Tcp6State > Tcp6StateEstablished ) { 1320 HttpCloseConnection(HttpInstance); 1321 } 1322 1323 Status = HttpCreateConnection (HttpInstance); 1324 if (EFI_ERROR(Status)){ 1325 DEBUG ((EFI_D_ERROR, "Tcp6 Connection fail - %x\n", Status)); 1326 return Status; 1327 } 1328 1329 // 1330 // Tls session connection. 1331 // 1332 if (HttpInstance->UseHttps) { 1333 if (HttpInstance->TimeoutEvent == NULL) { 1334 // 1335 // Create TimeoutEvent for TLS connection. 1336 // 1337 Status = gBS->CreateEvent ( 1338 EVT_TIMER, 1339 TPL_CALLBACK, 1340 NULL, 1341 NULL, 1342 &HttpInstance->TimeoutEvent 1343 ); 1344 if (EFI_ERROR (Status)) { 1345 TlsCloseTxRxEvent (HttpInstance); 1346 return Status; 1347 } 1348 } 1349 1350 // 1351 // Start the timer, and wait Timeout seconds for connection. 1352 // 1353 Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND); 1354 if (EFI_ERROR (Status)) { 1355 TlsCloseTxRxEvent (HttpInstance); 1356 return Status; 1357 } 1358 1359 Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent); 1360 1361 gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0); 1362 1363 if (EFI_ERROR (Status)) { 1364 TlsCloseTxRxEvent (HttpInstance); 1365 return Status; 1366 } 1367 } 1368 1369 return Status; 1370 } 1371 1372 /** 1373 Initialize Http session. 1374 1375 @param[in] HttpInstance The HTTP instance private data. 1376 @param[in] Wrap The HTTP token's wrap data. 1377 @param[in] Configure The Flag indicates whether need to initialize session. 1378 @param[in] TlsConfigure The Flag indicates whether it's the new Tls session. 1379 1380 @retval EFI_SUCCESS The initialization of session is done. 1381 @retval Others Other error as indicated. 1382 1383 **/ 1384 EFI_STATUS 1385 HttpInitSession ( 1386 IN HTTP_PROTOCOL *HttpInstance, 1387 IN HTTP_TOKEN_WRAP *Wrap, 1388 IN BOOLEAN Configure, 1389 IN BOOLEAN TlsConfigure 1390 ) 1391 { 1392 EFI_STATUS Status; 1393 ASSERT (HttpInstance != NULL); 1394 1395 // 1396 // Configure Tls session. 1397 // 1398 if (TlsConfigure) { 1399 Status = TlsConfigureSession (HttpInstance); 1400 if (EFI_ERROR (Status)) { 1401 return Status; 1402 } 1403 } 1404 1405 if (!HttpInstance->LocalAddressIsIPv6) { 1406 // 1407 // Configure TCP instance. 1408 // 1409 if (Configure) { 1410 Status = HttpConfigureTcp4 (HttpInstance, Wrap); 1411 if (EFI_ERROR (Status)) { 1412 return Status; 1413 } 1414 } 1415 1416 // 1417 // Connect TCP. 1418 // 1419 Status = HttpConnectTcp4 (HttpInstance); 1420 if (EFI_ERROR (Status)) { 1421 return Status; 1422 } 1423 } else { 1424 // 1425 // Configure TCP instance. 1426 // 1427 if (Configure) { 1428 Status = HttpConfigureTcp6 (HttpInstance, Wrap); 1429 if (EFI_ERROR (Status)) { 1430 return Status; 1431 } 1432 } 1433 1434 // 1435 // Connect TCP. 1436 // 1437 Status = HttpConnectTcp6 (HttpInstance); 1438 if (EFI_ERROR (Status)) { 1439 return Status; 1440 } 1441 } 1442 1443 return EFI_SUCCESS; 1444 1445 } 1446 1447 /** 1448 Send the HTTP or HTTPS message through TCP4 or TCP6. 1449 1450 @param[in] HttpInstance The HTTP instance private data. 1451 @param[in] Wrap The HTTP token's wrap data. 1452 @param[in] TxString Buffer containing the HTTP message string. 1453 @param[in] TxStringLen Length of the HTTP message string in bytes. 1454 1455 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit queue. 1456 @retval Others Other error as indicated. 1457 1458 **/ 1459 EFI_STATUS 1460 HttpTransmitTcp ( 1461 IN HTTP_PROTOCOL *HttpInstance, 1462 IN HTTP_TOKEN_WRAP *Wrap, 1463 IN UINT8 *TxString, 1464 IN UINTN TxStringLen 1465 ) 1466 { 1467 EFI_STATUS Status; 1468 EFI_TCP4_IO_TOKEN *Tx4Token; 1469 EFI_TCP4_PROTOCOL *Tcp4; 1470 EFI_TCP6_IO_TOKEN *Tx6Token; 1471 EFI_TCP6_PROTOCOL *Tcp6; 1472 UINT8 *Buffer; 1473 UINTN BufferSize; 1474 NET_FRAGMENT TempFragment; 1475 1476 Status = EFI_SUCCESS; 1477 Buffer = NULL; 1478 TempFragment.Len = 0; 1479 TempFragment.Bulk = NULL; 1480 1481 // 1482 // Need to encrypt data. 1483 // 1484 if (HttpInstance->UseHttps) { 1485 // 1486 // Build BufferOut data 1487 // 1488 BufferSize = sizeof (TLS_RECORD_HEADER) + TxStringLen; 1489 Buffer = AllocateZeroPool (BufferSize); 1490 if (Buffer == NULL) { 1491 Status = EFI_OUT_OF_RESOURCES; 1492 return Status; 1493 } 1494 ((TLS_RECORD_HEADER *) Buffer)->ContentType = TLS_CONTENT_TYPE_APPLICATION_DATA; 1495 ((TLS_RECORD_HEADER *) Buffer)->Version.Major = HttpInstance->TlsConfigData.Version.Major; 1496 ((TLS_RECORD_HEADER *) Buffer)->Version.Minor = HttpInstance->TlsConfigData.Version.Minor; 1497 ((TLS_RECORD_HEADER *) Buffer)->Length = (UINT16) (TxStringLen); 1498 CopyMem (Buffer + sizeof (TLS_RECORD_HEADER), TxString, TxStringLen); 1499 1500 // 1501 // Encrypt Packet. 1502 // 1503 Status = TlsProcessMessage ( 1504 HttpInstance, 1505 Buffer, 1506 BufferSize, 1507 EfiTlsEncrypt, 1508 &TempFragment 1509 ); 1510 1511 FreePool (Buffer); 1512 1513 if (EFI_ERROR (Status)) { 1514 return Status; 1515 } 1516 } 1517 1518 if (!HttpInstance->LocalAddressIsIPv6) { 1519 Tcp4 = HttpInstance->Tcp4; 1520 Tx4Token = &Wrap->TcpWrap.Tx4Token; 1521 1522 if (HttpInstance->UseHttps) { 1523 Tx4Token->Packet.TxData->DataLength = TempFragment.Len; 1524 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = TempFragment.Len; 1525 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TempFragment.Bulk; 1526 } else { 1527 Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen; 1528 Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen; 1529 Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString; 1530 } 1531 1532 Tx4Token->CompletionToken.Status = EFI_NOT_READY; 1533 1534 Wrap->TcpWrap.IsTxDone = FALSE; 1535 Status = Tcp4->Transmit (Tcp4, Tx4Token); 1536 if (EFI_ERROR (Status)) { 1537 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status)); 1538 return Status; 1539 } 1540 1541 } else { 1542 Tcp6 = HttpInstance->Tcp6; 1543 Tx6Token = &Wrap->TcpWrap.Tx6Token; 1544 1545 if (HttpInstance->UseHttps) { 1546 Tx6Token->Packet.TxData->DataLength = TempFragment.Len; 1547 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = TempFragment.Len; 1548 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TempFragment.Bulk; 1549 } else { 1550 Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen; 1551 Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen; 1552 Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString; 1553 } 1554 1555 Tx6Token->CompletionToken.Status = EFI_NOT_READY; 1556 1557 Wrap->TcpWrap.IsTxDone = FALSE; 1558 Status = Tcp6->Transmit (Tcp6, Tx6Token); 1559 if (EFI_ERROR (Status)) { 1560 DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status)); 1561 return Status; 1562 } 1563 } 1564 1565 return Status; 1566 } 1567 1568 /** 1569 Check whether the user's token or event has already 1570 been enqueue on HTTP Tx or Rx Token list. 1571 1572 @param[in] Map The container of either user's transmit or receive 1573 token. 1574 @param[in] Item Current item to check against. 1575 @param[in] Context The Token to check againist. 1576 1577 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP 1578 @retval EFI_SUCCESS The current item isn't the same token/event as the 1579 context. 1580 1581 **/ 1582 EFI_STATUS 1583 EFIAPI 1584 HttpTokenExist ( 1585 IN NET_MAP *Map, 1586 IN NET_MAP_ITEM *Item, 1587 IN VOID *Context 1588 ) 1589 { 1590 EFI_HTTP_TOKEN *Token; 1591 EFI_HTTP_TOKEN *TokenInItem; 1592 1593 Token = (EFI_HTTP_TOKEN *) Context; 1594 TokenInItem = (EFI_HTTP_TOKEN *) Item->Key; 1595 1596 if (Token == TokenInItem || Token->Event == TokenInItem->Event) { 1597 return EFI_ACCESS_DENIED; 1598 } 1599 1600 return EFI_SUCCESS; 1601 } 1602 1603 /** 1604 Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out. 1605 1606 @param[in] Map The container of Tx4Token or Tx6Token. 1607 @param[in] Item Current item to check against. 1608 @param[in] Context The Token to check againist. 1609 1610 @retval EFI_NOT_READY The HTTP message is still queued in the list. 1611 @retval EFI_SUCCESS The HTTP message has been sent out. 1612 1613 **/ 1614 EFI_STATUS 1615 EFIAPI 1616 HttpTcpNotReady ( 1617 IN NET_MAP *Map, 1618 IN NET_MAP_ITEM *Item, 1619 IN VOID *Context 1620 ) 1621 { 1622 HTTP_TOKEN_WRAP *ValueInItem; 1623 1624 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value; 1625 1626 if (!ValueInItem->TcpWrap.IsTxDone) { 1627 return EFI_NOT_READY; 1628 } 1629 1630 return EFI_SUCCESS; 1631 } 1632 1633 /** 1634 Transmit the HTTP or HTTPS mssage by processing the associated HTTP token. 1635 1636 @param[in] Map The container of Tx4Token or Tx6Token. 1637 @param[in] Item Current item to check against. 1638 @param[in] Context The Token to check againist. 1639 1640 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. 1641 @retval EFI_SUCCESS The HTTP message is queued into TCP transmit 1642 queue. 1643 1644 **/ 1645 EFI_STATUS 1646 EFIAPI 1647 HttpTcpTransmit ( 1648 IN NET_MAP *Map, 1649 IN NET_MAP_ITEM *Item, 1650 IN VOID *Context 1651 ) 1652 { 1653 HTTP_TOKEN_WRAP *ValueInItem; 1654 EFI_STATUS Status; 1655 CHAR8 *RequestMsg; 1656 CHAR8 *Url; 1657 UINTN UrlSize; 1658 UINTN RequestMsgSize; 1659 1660 RequestMsg = NULL; 1661 1662 ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value; 1663 if (ValueInItem->TcpWrap.IsTxDone) { 1664 return EFI_SUCCESS; 1665 } 1666 1667 // 1668 // Parse the URI of the remote host. 1669 // 1670 UrlSize = StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1; 1671 Url = AllocatePool (UrlSize); 1672 if (Url == NULL) { 1673 return EFI_OUT_OF_RESOURCES; 1674 } 1675 1676 UnicodeStrToAsciiStrS (ValueInItem->HttpToken->Message->Data.Request->Url, Url, UrlSize); 1677 1678 // 1679 // Create request message. 1680 // 1681 Status = HttpGenRequestMessage ( 1682 ValueInItem->HttpToken->Message, 1683 Url, 1684 &RequestMsg, 1685 &RequestMsgSize 1686 ); 1687 FreePool (Url); 1688 1689 if (EFI_ERROR (Status) || NULL == RequestMsg){ 1690 return Status; 1691 } 1692 1693 ASSERT (RequestMsg != NULL); 1694 1695 // 1696 // Transmit the request message. 1697 // 1698 Status = HttpTransmitTcp ( 1699 ValueInItem->HttpInstance, 1700 ValueInItem, 1701 (UINT8*) RequestMsg, 1702 RequestMsgSize 1703 ); 1704 FreePool (RequestMsg); 1705 return Status; 1706 } 1707 1708 /** 1709 Receive the HTTP response by processing the associated HTTP token. 1710 1711 @param[in] Map The container of Rx4Token or Rx6Token. 1712 @param[in] Item Current item to check against. 1713 @param[in] Context The Token to check againist. 1714 1715 @retval EFI_SUCCESS The HTTP response is queued into TCP receive 1716 queue. 1717 @retval Others Other error as indicated. 1718 1719 **/ 1720 EFI_STATUS 1721 EFIAPI 1722 HttpTcpReceive ( 1723 IN NET_MAP *Map, 1724 IN NET_MAP_ITEM *Item, 1725 IN VOID *Context 1726 ) 1727 { 1728 // 1729 // Process the queued HTTP response. 1730 // 1731 return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value); 1732 } 1733 1734 /** 1735 Receive the HTTP header by processing the associated HTTP token. 1736 1737 @param[in] HttpInstance The HTTP instance private data. 1738 @param[in, out] SizeofHeaders The HTTP header length. 1739 @param[in, out] BufferSize The size of buffer to cacahe the header message. 1740 @param[in] Timeout The time to wait for receiving the header packet. 1741 1742 @retval EFI_SUCCESS The HTTP header is received. 1743 @retval Others Other errors as indicated. 1744 1745 **/ 1746 EFI_STATUS 1747 HttpTcpReceiveHeader ( 1748 IN HTTP_PROTOCOL *HttpInstance, 1749 IN OUT UINTN *SizeofHeaders, 1750 IN OUT UINTN *BufferSize, 1751 IN EFI_EVENT Timeout 1752 ) 1753 { 1754 EFI_STATUS Status; 1755 EFI_TCP4_IO_TOKEN *Rx4Token; 1756 EFI_TCP4_PROTOCOL *Tcp4; 1757 EFI_TCP6_IO_TOKEN *Rx6Token; 1758 EFI_TCP6_PROTOCOL *Tcp6; 1759 CHAR8 **EndofHeader; 1760 CHAR8 **HttpHeaders; 1761 CHAR8 *Buffer; 1762 NET_FRAGMENT Fragment; 1763 1764 ASSERT (HttpInstance != NULL); 1765 1766 EndofHeader = HttpInstance->EndofHeader; 1767 HttpHeaders = HttpInstance->HttpHeaders; 1768 Tcp4 = HttpInstance->Tcp4; 1769 Tcp6 = HttpInstance->Tcp6; 1770 Buffer = NULL; 1771 Rx4Token = NULL; 1772 Rx6Token = NULL; 1773 Fragment.Len = 0; 1774 Fragment.Bulk = NULL; 1775 1776 if (HttpInstance->LocalAddressIsIPv6) { 1777 ASSERT (Tcp6 != NULL); 1778 } else { 1779 ASSERT (Tcp4 != NULL); 1780 } 1781 1782 if (!HttpInstance->UseHttps) { 1783 Status = HttpCreateTcpRxEventForHeader (HttpInstance); 1784 if (EFI_ERROR (Status)) { 1785 return Status; 1786 } 1787 } 1788 1789 if (!HttpInstance->LocalAddressIsIPv6) { 1790 if (!HttpInstance->UseHttps) { 1791 Rx4Token = &HttpInstance->Rx4Token; 1792 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN); 1793 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) { 1794 Status = EFI_OUT_OF_RESOURCES; 1795 return Status; 1796 } 1797 } 1798 1799 // 1800 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL. 1801 // 1802 while (*EndofHeader == NULL) { 1803 if (!HttpInstance->UseHttps) { 1804 HttpInstance->IsRxDone = FALSE; 1805 Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN; 1806 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN; 1807 Status = Tcp4->Receive (Tcp4, Rx4Token); 1808 if (EFI_ERROR (Status)) { 1809 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status)); 1810 return Status; 1811 } 1812 1813 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) { 1814 Tcp4->Poll (Tcp4); 1815 } 1816 1817 if (!HttpInstance->IsRxDone) { 1818 // 1819 // Cancle the Token before close its Event. 1820 // 1821 Tcp4->Cancel (HttpInstance->Tcp4, &Rx4Token->CompletionToken); 1822 gBS->CloseEvent (Rx4Token->CompletionToken.Event); 1823 Rx4Token->CompletionToken.Status = EFI_TIMEOUT; 1824 } 1825 1826 Status = Rx4Token->CompletionToken.Status; 1827 if (EFI_ERROR (Status)) { 1828 return Status; 1829 } 1830 1831 Fragment.Len = Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength; 1832 Fragment.Bulk = (UINT8 *) Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer; 1833 } else { 1834 if (Fragment.Bulk != NULL) { 1835 FreePool (Fragment.Bulk); 1836 Fragment.Bulk = NULL; 1837 } 1838 1839 Status = HttpsReceive (HttpInstance, &Fragment, Timeout); 1840 if (EFI_ERROR (Status)) { 1841 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status)); 1842 return Status; 1843 } 1844 } 1845 1846 // 1847 // Append the response string. 1848 // 1849 *BufferSize = *SizeofHeaders + Fragment.Len; 1850 Buffer = AllocateZeroPool (*BufferSize); 1851 if (Buffer == NULL) { 1852 Status = EFI_OUT_OF_RESOURCES; 1853 return Status; 1854 } 1855 1856 if (*HttpHeaders != NULL) { 1857 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders); 1858 FreePool (*HttpHeaders); 1859 } 1860 1861 CopyMem ( 1862 Buffer + *SizeofHeaders, 1863 Fragment.Bulk, 1864 Fragment.Len 1865 ); 1866 *HttpHeaders = Buffer; 1867 *SizeofHeaders = *BufferSize; 1868 1869 // 1870 // Check whether we received end of HTTP headers. 1871 // 1872 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); 1873 }; 1874 1875 // 1876 // Free the buffer. 1877 // 1878 if (Rx4Token != NULL && Rx4Token->Packet.RxData != NULL && Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) { 1879 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer); 1880 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; 1881 Fragment.Bulk = NULL; 1882 } 1883 1884 if (Fragment.Bulk != NULL) { 1885 FreePool (Fragment.Bulk); 1886 Fragment.Bulk = NULL; 1887 } 1888 } else { 1889 if (!HttpInstance->UseHttps) { 1890 Rx6Token = &HttpInstance->Rx6Token; 1891 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN); 1892 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) { 1893 Status = EFI_OUT_OF_RESOURCES; 1894 return Status; 1895 } 1896 } 1897 1898 // 1899 // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL. 1900 // 1901 while (*EndofHeader == NULL) { 1902 if (!HttpInstance->UseHttps) { 1903 HttpInstance->IsRxDone = FALSE; 1904 Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN; 1905 Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN; 1906 Status = Tcp6->Receive (Tcp6, Rx6Token); 1907 if (EFI_ERROR (Status)) { 1908 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status)); 1909 return Status; 1910 } 1911 1912 while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) { 1913 Tcp6->Poll (Tcp6); 1914 } 1915 1916 if (!HttpInstance->IsRxDone) { 1917 // 1918 // Cancle the Token before close its Event. 1919 // 1920 Tcp6->Cancel (HttpInstance->Tcp6, &Rx6Token->CompletionToken); 1921 gBS->CloseEvent (Rx6Token->CompletionToken.Event); 1922 Rx6Token->CompletionToken.Status = EFI_TIMEOUT; 1923 } 1924 1925 Status = Rx6Token->CompletionToken.Status; 1926 if (EFI_ERROR (Status)) { 1927 return Status; 1928 } 1929 1930 Fragment.Len = Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength; 1931 Fragment.Bulk = (UINT8 *) Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer; 1932 } else { 1933 if (Fragment.Bulk != NULL) { 1934 FreePool (Fragment.Bulk); 1935 Fragment.Bulk = NULL; 1936 } 1937 1938 Status = HttpsReceive (HttpInstance, &Fragment, Timeout); 1939 if (EFI_ERROR (Status)) { 1940 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status)); 1941 return Status; 1942 } 1943 } 1944 1945 // 1946 // Append the response string. 1947 // 1948 *BufferSize = *SizeofHeaders + Fragment.Len; 1949 Buffer = AllocateZeroPool (*BufferSize); 1950 if (Buffer == NULL) { 1951 Status = EFI_OUT_OF_RESOURCES; 1952 return Status; 1953 } 1954 1955 if (*HttpHeaders != NULL) { 1956 CopyMem (Buffer, *HttpHeaders, *SizeofHeaders); 1957 FreePool (*HttpHeaders); 1958 } 1959 1960 CopyMem ( 1961 Buffer + *SizeofHeaders, 1962 Fragment.Bulk, 1963 Fragment.Len 1964 ); 1965 *HttpHeaders = Buffer; 1966 *SizeofHeaders = *BufferSize; 1967 1968 // 1969 // Check whether we received end of HTTP headers. 1970 // 1971 *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); 1972 }; 1973 1974 // 1975 // Free the buffer. 1976 // 1977 if (Rx6Token != NULL && Rx6Token->Packet.RxData != NULL && Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) { 1978 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer); 1979 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; 1980 Fragment.Bulk = NULL; 1981 } 1982 1983 if (Fragment.Bulk != NULL) { 1984 FreePool (Fragment.Bulk); 1985 Fragment.Bulk = NULL; 1986 } 1987 } 1988 1989 // 1990 // Skip the CRLF after the HTTP headers. 1991 // 1992 *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR); 1993 1994 return EFI_SUCCESS; 1995 } 1996 1997 /** 1998 Receive the HTTP body by processing the associated HTTP token. 1999 2000 @param[in] Wrap The HTTP token's wrap data. 2001 @param[in] HttpMsg The HTTP message data. 2002 2003 @retval EFI_SUCCESS The HTTP body is received. 2004 @retval Others Other error as indicated. 2005 2006 **/ 2007 EFI_STATUS 2008 HttpTcpReceiveBody ( 2009 IN HTTP_TOKEN_WRAP *Wrap, 2010 IN EFI_HTTP_MESSAGE *HttpMsg 2011 ) 2012 { 2013 EFI_STATUS Status; 2014 HTTP_PROTOCOL *HttpInstance; 2015 EFI_TCP6_PROTOCOL *Tcp6; 2016 EFI_TCP6_IO_TOKEN *Rx6Token; 2017 EFI_TCP4_PROTOCOL *Tcp4; 2018 EFI_TCP4_IO_TOKEN *Rx4Token; 2019 2020 HttpInstance = Wrap->HttpInstance; 2021 Tcp4 = HttpInstance->Tcp4; 2022 Tcp6 = HttpInstance->Tcp6; 2023 Rx4Token = NULL; 2024 Rx6Token = NULL; 2025 2026 if (HttpInstance->LocalAddressIsIPv6) { 2027 ASSERT (Tcp6 != NULL); 2028 } else { 2029 ASSERT (Tcp4 != NULL); 2030 } 2031 2032 if (HttpInstance->LocalAddressIsIPv6) { 2033 Rx6Token = &Wrap->TcpWrap.Rx6Token; 2034 Rx6Token ->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength; 2035 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength; 2036 Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body; 2037 Rx6Token->CompletionToken.Status = EFI_NOT_READY; 2038 2039 Status = Tcp6->Receive (Tcp6, Rx6Token); 2040 if (EFI_ERROR (Status)) { 2041 DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status)); 2042 return Status; 2043 } 2044 } else { 2045 Rx4Token = &Wrap->TcpWrap.Rx4Token; 2046 Rx4Token->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength; 2047 Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength; 2048 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body; 2049 2050 Rx4Token->CompletionToken.Status = EFI_NOT_READY; 2051 Status = Tcp4->Receive (Tcp4, Rx4Token); 2052 if (EFI_ERROR (Status)) { 2053 DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status)); 2054 return Status; 2055 } 2056 } 2057 2058 return EFI_SUCCESS; 2059 2060 } 2061 2062 /** 2063 Clean up Tcp Tokens while the Tcp transmission error occurs. 2064 2065 @param[in] Wrap Pointer to HTTP token's wrap data. 2066 2067 **/ 2068 VOID 2069 HttpTcpTokenCleanup ( 2070 IN HTTP_TOKEN_WRAP *Wrap 2071 ) 2072 { 2073 HTTP_PROTOCOL *HttpInstance; 2074 EFI_TCP4_IO_TOKEN *Rx4Token; 2075 EFI_TCP6_IO_TOKEN *Rx6Token; 2076 2077 ASSERT (Wrap != NULL); 2078 HttpInstance = Wrap->HttpInstance; 2079 Rx4Token = NULL; 2080 Rx6Token = NULL; 2081 2082 if (HttpInstance->LocalAddressIsIPv6) { 2083 Rx6Token = &Wrap->TcpWrap.Rx6Token; 2084 2085 if (Rx6Token->CompletionToken.Event != NULL) { 2086 gBS->CloseEvent (Rx6Token->CompletionToken.Event); 2087 Rx6Token->CompletionToken.Event = NULL; 2088 } 2089 2090 FreePool (Wrap); 2091 2092 Rx6Token = &HttpInstance->Rx6Token; 2093 2094 if (Rx6Token->CompletionToken.Event != NULL) { 2095 gBS->CloseEvent (Rx6Token->CompletionToken.Event); 2096 Rx6Token->CompletionToken.Event = NULL; 2097 } 2098 2099 if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) { 2100 FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer); 2101 Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; 2102 } 2103 2104 } else { 2105 Rx4Token = &Wrap->TcpWrap.Rx4Token; 2106 2107 if (Rx4Token->CompletionToken.Event != NULL) { 2108 gBS->CloseEvent (Rx4Token->CompletionToken.Event); 2109 Rx4Token->CompletionToken.Event = NULL; 2110 } 2111 2112 FreePool (Wrap); 2113 2114 Rx4Token = &HttpInstance->Rx4Token; 2115 2116 if (Rx4Token->CompletionToken.Event != NULL) { 2117 gBS->CloseEvent (Rx4Token->CompletionToken.Event); 2118 Rx4Token->CompletionToken.Event = NULL; 2119 } 2120 2121 2122 if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) { 2123 FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer); 2124 Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL; 2125 } 2126 } 2127 2128 } 2129