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