1 /** @file 2 Implementation of the Socket. 3 4 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR> 5 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 "SockImpl.h" 17 18 /** 19 Get the first buffer block in the specific socket buffer. 20 21 @param[in] Sockbuf Pointer to the socket buffer. 22 23 @return Pointer to the first buffer in the queue. NULL if the queue is empty. 24 25 **/ 26 NET_BUF * 27 SockBufFirst ( 28 IN SOCK_BUFFER *Sockbuf 29 ) 30 { 31 LIST_ENTRY *NetbufList; 32 33 NetbufList = &(Sockbuf->DataQueue->BufList); 34 35 if (IsListEmpty (NetbufList)) { 36 return NULL; 37 } 38 39 return NET_LIST_HEAD (NetbufList, NET_BUF, List); 40 } 41 42 /** 43 Get the next buffer block in the specific socket buffer. 44 45 @param[in] Sockbuf Pointer to the socket buffer. 46 @param[in] SockEntry Pointer to the buffer block prior to the required one. 47 48 @return Pointer to the buffer block next to SockEntry. NULL if SockEntry is 49 the tail or head entry. 50 51 **/ 52 NET_BUF * 53 SockBufNext ( 54 IN SOCK_BUFFER *Sockbuf, 55 IN NET_BUF *SockEntry 56 ) 57 { 58 LIST_ENTRY *NetbufList; 59 60 NetbufList = &(Sockbuf->DataQueue->BufList); 61 62 if ((SockEntry->List.ForwardLink == NetbufList) || 63 (SockEntry->List.BackLink == &SockEntry->List) || 64 (SockEntry->List.ForwardLink == &SockEntry->List) 65 ) { 66 67 return NULL; 68 } 69 70 return NET_LIST_USER_STRUCT (SockEntry->List.ForwardLink, NET_BUF, List); 71 } 72 73 /** 74 User provided callback function for NetbufFromExt. 75 76 @param[in] Event The Event this notify function registered to, ignored. 77 78 **/ 79 VOID 80 EFIAPI 81 SockFreeFoo ( 82 IN EFI_EVENT Event 83 ) 84 { 85 return; 86 } 87 88 /** 89 Get the length of the data that can be retrieved from the socket 90 receive buffer. 91 92 @param[in] SockBuffer Pointer to the socket receive buffer. 93 @param[out] IsUrg Pointer to a BOOLEAN variable. 94 If TRUE the data is OOB. 95 @param[in] BufLen The maximum length of the data buffer to 96 store the received data in the socket layer. 97 98 @return The length of the data can be retreived. 99 100 **/ 101 UINT32 102 SockTcpDataToRcv ( 103 IN SOCK_BUFFER *SockBuffer, 104 OUT BOOLEAN *IsUrg, 105 IN UINT32 BufLen 106 ) 107 { 108 NET_BUF *RcvBufEntry; 109 UINT32 DataLen; 110 TCP_RSV_DATA *TcpRsvData; 111 BOOLEAN Urg; 112 113 ASSERT ((SockBuffer != NULL) && (IsUrg != NULL) && (BufLen > 0)); 114 115 // 116 // Get the first socket receive buffer 117 // 118 RcvBufEntry = SockBufFirst (SockBuffer); 119 ASSERT (RcvBufEntry != NULL); 120 121 TcpRsvData = (TCP_RSV_DATA *) RcvBufEntry->ProtoData; 122 123 // 124 // Check whether the receive data is out of bound. If yes, calculate the maximum 125 // allowed length of the urgent data and output it. 126 // 127 *IsUrg = (BOOLEAN) ((TcpRsvData->UrgLen > 0) ? TRUE : FALSE); 128 129 if (*IsUrg && (TcpRsvData->UrgLen < RcvBufEntry->TotalSize)) { 130 131 DataLen = MIN (TcpRsvData->UrgLen, BufLen); 132 133 if (DataLen < TcpRsvData->UrgLen) { 134 TcpRsvData->UrgLen = TcpRsvData->UrgLen - DataLen; 135 } else { 136 TcpRsvData->UrgLen = 0; 137 } 138 139 return DataLen; 140 141 } 142 143 // 144 // Process the next socket receive buffer to get the maximum allowed length 145 // of the received data. 146 // 147 DataLen = RcvBufEntry->TotalSize; 148 149 RcvBufEntry = SockBufNext (SockBuffer, RcvBufEntry); 150 151 while ((BufLen > DataLen) && (RcvBufEntry != NULL)) { 152 153 TcpRsvData = (TCP_RSV_DATA *) RcvBufEntry->ProtoData; 154 155 Urg = (BOOLEAN) ((TcpRsvData->UrgLen > 0) ? TRUE : FALSE); 156 157 if (*IsUrg != Urg) { 158 break; 159 } 160 161 if (*IsUrg && TcpRsvData->UrgLen < RcvBufEntry->TotalSize) { 162 163 if (TcpRsvData->UrgLen + DataLen < BufLen) { 164 TcpRsvData->UrgLen = 0; 165 } else { 166 TcpRsvData->UrgLen = TcpRsvData->UrgLen - (BufLen - DataLen); 167 } 168 169 return MIN (TcpRsvData->UrgLen + DataLen, BufLen); 170 171 } 172 173 DataLen += RcvBufEntry->TotalSize; 174 175 RcvBufEntry = SockBufNext (SockBuffer, RcvBufEntry); 176 } 177 178 DataLen = MIN (BufLen, DataLen); 179 return DataLen; 180 } 181 182 /** 183 Copy data from socket buffer to an application provided receive buffer. 184 185 @param[in] Sock Pointer to the socket. 186 @param[in] TcpRxData Pointer to the application provided receive buffer. 187 @param[in] RcvdBytes The maximum length of the data can be copied. 188 @param[in] IsUrg If TRUE the data is Out of Bound, FALSE the data is normal. 189 190 **/ 191 VOID 192 SockSetTcpRxData ( 193 IN SOCKET *Sock, 194 IN VOID *TcpRxData, 195 IN UINT32 RcvdBytes, 196 IN BOOLEAN IsUrg 197 ) 198 { 199 UINT32 Index; 200 UINT32 CopyBytes; 201 UINT32 OffSet; 202 EFI_TCP4_RECEIVE_DATA *RxData; 203 EFI_TCP4_FRAGMENT_DATA *Fragment; 204 205 RxData = (EFI_TCP4_RECEIVE_DATA *) TcpRxData; 206 207 OffSet = 0; 208 209 ASSERT (RxData->DataLength >= RcvdBytes); 210 211 RxData->DataLength = RcvdBytes; 212 RxData->UrgentFlag = IsUrg; 213 214 // 215 // Copy the CopyBytes data from socket receive buffer to RxData. 216 // 217 for (Index = 0; (Index < RxData->FragmentCount) && (RcvdBytes > 0); Index++) { 218 219 Fragment = &RxData->FragmentTable[Index]; 220 CopyBytes = MIN ((UINT32) (Fragment->FragmentLength), RcvdBytes); 221 222 NetbufQueCopy ( 223 Sock->RcvBuffer.DataQueue, 224 OffSet, 225 CopyBytes, 226 Fragment->FragmentBuffer 227 ); 228 229 Fragment->FragmentLength = CopyBytes; 230 RcvdBytes -= CopyBytes; 231 OffSet += CopyBytes; 232 } 233 } 234 235 /** 236 Process the send token. 237 238 @param[in, out] Sock Pointer to the socket. 239 240 **/ 241 VOID 242 SockProcessSndToken ( 243 IN OUT SOCKET *Sock 244 ) 245 { 246 UINT32 FreeSpace; 247 SOCK_TOKEN *SockToken; 248 UINT32 DataLen; 249 SOCK_IO_TOKEN *SndToken; 250 EFI_TCP4_TRANSMIT_DATA *TxData; 251 EFI_STATUS Status; 252 253 ASSERT ((Sock != NULL) && (SockStream == Sock->Type)); 254 255 FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF); 256 257 // 258 // to determine if process a send token using 259 // socket layer flow control policy 260 // 261 while ((FreeSpace >= Sock->SndBuffer.LowWater) && !IsListEmpty (&Sock->SndTokenList)) { 262 263 SockToken = NET_LIST_HEAD ( 264 &(Sock->SndTokenList), 265 SOCK_TOKEN, 266 TokenList 267 ); 268 269 // 270 // process this token 271 // 272 RemoveEntryList (&(SockToken->TokenList)); 273 InsertTailList ( 274 &(Sock->ProcessingSndTokenList), 275 &(SockToken->TokenList) 276 ); 277 278 // 279 // Proceess it in the light of SockType 280 // 281 SndToken = (SOCK_IO_TOKEN *) SockToken->Token; 282 TxData = SndToken->Packet.TxData; 283 284 DataLen = TxData->DataLength; 285 Status = SockProcessTcpSndData (Sock, TxData); 286 287 if (EFI_ERROR (Status)) { 288 goto OnError; 289 } 290 291 if (DataLen >= FreeSpace) { 292 FreeSpace = 0; 293 294 } else { 295 FreeSpace -= DataLen; 296 297 } 298 } 299 300 return; 301 302 OnError: 303 304 RemoveEntryList (&SockToken->TokenList); 305 SIGNAL_TOKEN (SockToken->Token, Status); 306 FreePool (SockToken); 307 } 308 309 /** 310 Get received data from the socket layer to the receive token. 311 312 @param[in, out] Sock Pointer to the socket. 313 @param[in, out] RcvToken Pointer to the application provided receive token. 314 315 @return The length of data received in this token. 316 317 **/ 318 UINT32 319 SockProcessRcvToken ( 320 IN OUT SOCKET *Sock, 321 IN OUT SOCK_IO_TOKEN *RcvToken 322 ) 323 { 324 UINT32 TokenRcvdBytes; 325 EFI_TCP4_RECEIVE_DATA *RxData; 326 BOOLEAN IsUrg; 327 328 ASSERT (Sock != NULL); 329 330 ASSERT (SockStream == Sock->Type); 331 332 RxData = RcvToken->Packet.RxData; 333 334 TokenRcvdBytes = SockTcpDataToRcv ( 335 &Sock->RcvBuffer, 336 &IsUrg, 337 RxData->DataLength 338 ); 339 340 // 341 // Copy data from RcvBuffer of socket to user 342 // provided RxData and set the fields in TCP RxData 343 // 344 SockSetTcpRxData (Sock, RxData, TokenRcvdBytes, IsUrg); 345 346 NetbufQueTrim (Sock->RcvBuffer.DataQueue, TokenRcvdBytes); 347 SIGNAL_TOKEN (&(RcvToken->Token), EFI_SUCCESS); 348 349 return TokenRcvdBytes; 350 } 351 352 /** 353 Process the TCP send data, buffer the tcp txdata, and append 354 the buffer to socket send buffer, then try to send it. 355 356 @param[in] Sock Pointer to the socket. 357 @param[in] TcpTxData Pointer to the application provided send buffer. 358 359 @retval EFI_SUCCESS The operation completed successfully. 360 @retval EFI_OUT_OF_RESOURCES Failed due to resource limits. 361 362 **/ 363 EFI_STATUS 364 SockProcessTcpSndData ( 365 IN SOCKET *Sock, 366 IN VOID *TcpTxData 367 ) 368 { 369 NET_BUF *SndData; 370 EFI_STATUS Status; 371 EFI_TCP4_TRANSMIT_DATA *TxData; 372 373 TxData = (EFI_TCP4_TRANSMIT_DATA *) TcpTxData; 374 375 // 376 // transform this TxData into a NET_BUFFER 377 // and insert it into Sock->SndBuffer 378 // 379 SndData = NetbufFromExt ( 380 (NET_FRAGMENT *) TxData->FragmentTable, 381 TxData->FragmentCount, 382 0, 383 0, 384 SockFreeFoo, 385 NULL 386 ); 387 388 if (NULL == SndData) { 389 DEBUG ( 390 (EFI_D_ERROR, 391 "SockKProcessSndData: Failed to call NetBufferFromExt\n") 392 ); 393 394 return EFI_OUT_OF_RESOURCES; 395 } 396 397 NetbufQueAppend (Sock->SndBuffer.DataQueue, SndData); 398 399 // 400 // notify the low layer protocol to handle this send token 401 // 402 if (TxData->Urgent) { 403 Status = Sock->ProtoHandler (Sock, SOCK_SNDURG, NULL); 404 405 if (EFI_ERROR (Status)) { 406 return Status; 407 } 408 } 409 410 if (TxData->Push) { 411 Status = Sock->ProtoHandler (Sock, SOCK_SNDPUSH, NULL); 412 413 if (EFI_ERROR (Status)) { 414 return Status; 415 } 416 } 417 418 // 419 // low layer protocol should really handle the sending 420 // process when catching SOCK_SND request 421 // 422 Status = Sock->ProtoHandler (Sock, SOCK_SND, NULL); 423 424 if (EFI_ERROR (Status)) { 425 return Status; 426 } 427 428 return EFI_SUCCESS; 429 } 430 431 /** 432 Flush the tokens in the specific token list. 433 434 @param[in] Sock Pointer to the socket. 435 @param[in, out] PendingTokenList Pointer to the token list to be flushed. 436 437 **/ 438 VOID 439 SockFlushPendingToken ( 440 IN SOCKET *Sock, 441 IN OUT LIST_ENTRY *PendingTokenList 442 ) 443 { 444 SOCK_TOKEN *SockToken; 445 SOCK_COMPLETION_TOKEN *Token; 446 447 ASSERT ((Sock != NULL) && (PendingTokenList != NULL)); 448 449 while (!IsListEmpty (PendingTokenList)) { 450 SockToken = NET_LIST_HEAD ( 451 PendingTokenList, 452 SOCK_TOKEN, 453 TokenList 454 ); 455 456 Token = SockToken->Token; 457 SIGNAL_TOKEN (Token, Sock->SockError); 458 459 RemoveEntryList (&(SockToken->TokenList)); 460 FreePool (SockToken); 461 } 462 } 463 464 /** 465 Wake up the connection token while the connection is successfully established, 466 then try to process any pending send token. 467 468 @param[in, out] Sock Pointer to the socket. 469 470 **/ 471 VOID 472 SockWakeConnToken ( 473 IN OUT SOCKET *Sock 474 ) 475 { 476 ASSERT (Sock->ConnectionToken != NULL); 477 478 SIGNAL_TOKEN (Sock->ConnectionToken, EFI_SUCCESS); 479 Sock->ConnectionToken = NULL; 480 481 // 482 // check to see if some pending send token existed? 483 // 484 SockProcessSndToken (Sock); 485 } 486 487 /** 488 Wake up the listen token while the connection is established successfully. 489 490 @param[in, out] Sock Pointer to the socket. 491 492 **/ 493 VOID 494 SockWakeListenToken ( 495 IN OUT SOCKET *Sock 496 ) 497 { 498 SOCKET *Parent; 499 SOCK_TOKEN *SockToken; 500 EFI_TCP4_LISTEN_TOKEN *ListenToken; 501 502 Parent = Sock->Parent; 503 504 ASSERT ((Parent != NULL) && SOCK_IS_LISTENING (Parent) && SOCK_IS_CONNECTED (Sock)); 505 506 if (!IsListEmpty (&Parent->ListenTokenList)) { 507 SockToken = NET_LIST_HEAD ( 508 &Parent->ListenTokenList, 509 SOCK_TOKEN, 510 TokenList 511 ); 512 513 ListenToken = (EFI_TCP4_LISTEN_TOKEN *) SockToken->Token; 514 ListenToken->NewChildHandle = Sock->SockHandle; 515 516 SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS); 517 518 RemoveEntryList (&SockToken->TokenList); 519 FreePool (SockToken); 520 521 RemoveEntryList (&Sock->ConnectionList); 522 523 Parent->ConnCnt--; 524 DEBUG ( 525 (EFI_D_NET, 526 "SockWakeListenToken: accept a socket, now conncnt is %d", 527 Parent->ConnCnt) 528 ); 529 530 Sock->Parent = NULL; 531 } 532 } 533 534 /** 535 Wake up the receive token while some data is received. 536 537 @param[in, out] Sock Pointer to the socket. 538 539 **/ 540 VOID 541 SockWakeRcvToken ( 542 IN OUT SOCKET *Sock 543 ) 544 { 545 UINT32 RcvdBytes; 546 UINT32 TokenRcvdBytes; 547 SOCK_TOKEN *SockToken; 548 SOCK_IO_TOKEN *RcvToken; 549 550 ASSERT (Sock->RcvBuffer.DataQueue != NULL); 551 552 RcvdBytes = (Sock->RcvBuffer.DataQueue)->BufSize; 553 554 ASSERT (RcvdBytes > 0); 555 556 while (RcvdBytes > 0 && !IsListEmpty (&Sock->RcvTokenList)) { 557 558 SockToken = NET_LIST_HEAD ( 559 &Sock->RcvTokenList, 560 SOCK_TOKEN, 561 TokenList 562 ); 563 564 RcvToken = (SOCK_IO_TOKEN *) SockToken->Token; 565 TokenRcvdBytes = SockProcessRcvToken (Sock, RcvToken); 566 567 if (0 == TokenRcvdBytes) { 568 return ; 569 } 570 571 RemoveEntryList (&(SockToken->TokenList)); 572 FreePool (SockToken); 573 RcvdBytes -= TokenRcvdBytes; 574 } 575 } 576 577 /** 578 Cancel the tokens in the specific token list. 579 580 @param[in] Token Pointer to the Token. If NULL, all tokens 581 in SpecifiedTokenList will be canceled. 582 @param[in, out] SpecifiedTokenList Pointer to the token list to be checked. 583 584 @retval EFI_SUCCESS Cancel the tokens in the specific token listsuccessfully. 585 @retval EFI_NOT_FOUND The Token is not found in SpecifiedTokenList. 586 587 **/ 588 EFI_STATUS 589 SockCancelToken ( 590 IN SOCK_COMPLETION_TOKEN *Token, 591 IN OUT LIST_ENTRY *SpecifiedTokenList 592 ) 593 { 594 EFI_STATUS Status; 595 LIST_ENTRY *Entry; 596 SOCK_TOKEN *SockToken; 597 598 Status = EFI_SUCCESS; 599 Entry = NULL; 600 SockToken = NULL; 601 602 if (IsListEmpty (SpecifiedTokenList) && Token != NULL) { 603 return EFI_NOT_FOUND; 604 } 605 606 // 607 // Iterate through the SpecifiedTokenList. 608 // 609 Entry = SpecifiedTokenList->ForwardLink; 610 while (Entry != SpecifiedTokenList) { 611 SockToken = NET_LIST_USER_STRUCT (Entry, SOCK_TOKEN, TokenList); 612 613 if (Token == NULL) { 614 SIGNAL_TOKEN (SockToken->Token, EFI_ABORTED); 615 RemoveEntryList (&SockToken->TokenList); 616 FreePool (SockToken); 617 618 Entry = SpecifiedTokenList->ForwardLink; 619 Status = EFI_SUCCESS; 620 } else { 621 if (Token == (VOID *) SockToken->Token) { 622 SIGNAL_TOKEN (Token, EFI_ABORTED); 623 RemoveEntryList (&(SockToken->TokenList)); 624 FreePool (SockToken); 625 626 return EFI_SUCCESS; 627 } 628 629 Status = EFI_NOT_FOUND; 630 631 Entry = Entry->ForwardLink; 632 } 633 } 634 635 ASSERT (IsListEmpty (SpecifiedTokenList) || Token != NULL); 636 637 return Status; 638 } 639 640 /** 641 Create a socket with initial data SockInitData. 642 643 @param[in] SockInitData Pointer to the initial data of the socket. 644 645 @return Pointer to the newly created socket, return NULL when an exception occurs. 646 647 **/ 648 SOCKET * 649 SockCreate ( 650 IN SOCK_INIT_DATA *SockInitData 651 ) 652 { 653 SOCKET *Sock; 654 SOCKET *Parent; 655 EFI_STATUS Status; 656 EFI_GUID *TcpProtocolGuid; 657 UINTN ProtocolLength; 658 659 ASSERT ((SockInitData != NULL) && (SockInitData->ProtoHandler != NULL)); 660 ASSERT (SockInitData->Type == SockStream); 661 ASSERT ((SockInitData->ProtoData != NULL) && (SockInitData->DataSize <= PROTO_RESERVED_LEN)); 662 663 if (SockInitData->IpVersion == IP_VERSION_4) { 664 TcpProtocolGuid = &gEfiTcp4ProtocolGuid; 665 ProtocolLength = sizeof (EFI_TCP4_PROTOCOL); 666 } else { 667 TcpProtocolGuid = &gEfiTcp6ProtocolGuid; 668 ProtocolLength = sizeof (EFI_TCP6_PROTOCOL); 669 } 670 671 672 Parent = SockInitData->Parent; 673 674 if ((Parent != NULL) && (Parent->ConnCnt == Parent->BackLog)) { 675 DEBUG ( 676 (EFI_D_ERROR, 677 "SockCreate: Socket parent has reached its connection limit with %d ConnCnt and %d BackLog\n", 678 Parent->ConnCnt, 679 Parent->BackLog) 680 ); 681 682 return NULL; 683 } 684 685 Sock = AllocateZeroPool (sizeof (SOCKET)); 686 if (NULL == Sock) { 687 688 DEBUG ((EFI_D_ERROR, "SockCreate: No resource to create a new socket\n")); 689 return NULL; 690 } 691 692 InitializeListHead (&Sock->Link); 693 InitializeListHead (&Sock->ConnectionList); 694 InitializeListHead (&Sock->ListenTokenList); 695 InitializeListHead (&Sock->RcvTokenList); 696 InitializeListHead (&Sock->SndTokenList); 697 InitializeListHead (&Sock->ProcessingSndTokenList); 698 699 EfiInitializeLock (&(Sock->Lock), TPL_CALLBACK); 700 701 Sock->SndBuffer.DataQueue = NetbufQueAlloc (); 702 if (NULL == Sock->SndBuffer.DataQueue) { 703 DEBUG ( 704 (EFI_D_ERROR, 705 "SockCreate: No resource to allocate SndBuffer for new socket\n") 706 ); 707 708 goto OnError; 709 } 710 711 Sock->RcvBuffer.DataQueue = NetbufQueAlloc (); 712 if (NULL == Sock->RcvBuffer.DataQueue) { 713 DEBUG ( 714 (EFI_D_ERROR, 715 "SockCreate: No resource to allocate RcvBuffer for new socket\n") 716 ); 717 718 goto OnError; 719 } 720 721 Sock->Signature = SOCK_SIGNATURE; 722 723 Sock->Parent = Parent; 724 Sock->BackLog = SockInitData->BackLog; 725 Sock->ProtoHandler = SockInitData->ProtoHandler; 726 Sock->SndBuffer.HighWater = SockInitData->SndBufferSize; 727 Sock->RcvBuffer.HighWater = SockInitData->RcvBufferSize; 728 Sock->Type = SockInitData->Type; 729 Sock->DriverBinding = SockInitData->DriverBinding; 730 Sock->State = SockInitData->State; 731 Sock->CreateCallback = SockInitData->CreateCallback; 732 Sock->DestroyCallback = SockInitData->DestroyCallback; 733 Sock->Context = SockInitData->Context; 734 735 Sock->SockError = EFI_ABORTED; 736 Sock->SndBuffer.LowWater = SOCK_BUFF_LOW_WATER; 737 Sock->RcvBuffer.LowWater = SOCK_BUFF_LOW_WATER; 738 739 Sock->IpVersion = SockInitData->IpVersion; 740 741 // 742 // Install protocol on Sock->SockHandle 743 // 744 CopyMem (&Sock->NetProtocol, SockInitData->Protocol, ProtocolLength); 745 746 // 747 // copy the protodata into socket 748 // 749 CopyMem (Sock->ProtoReserved, SockInitData->ProtoData, SockInitData->DataSize); 750 751 Status = gBS->InstallMultipleProtocolInterfaces ( 752 &Sock->SockHandle, 753 TcpProtocolGuid, 754 &Sock->NetProtocol, 755 NULL 756 ); 757 758 if (EFI_ERROR (Status)) { 759 DEBUG ( 760 (EFI_D_ERROR, 761 "SockCreate: Install TCP protocol in socket failed with %r\n", 762 Status) 763 ); 764 765 goto OnError; 766 } 767 768 if (Parent != NULL) { 769 ASSERT (Parent->BackLog > 0); 770 ASSERT (SOCK_IS_LISTENING (Parent)); 771 772 // 773 // need to add it into Parent->ConnectionList 774 // if the Parent->ConnCnt < Parent->BackLog 775 // 776 Parent->ConnCnt++; 777 778 DEBUG ( 779 (EFI_D_NET, 780 "SockCreate: Create a new socket and add to parent, now conncnt is %d\n", 781 Parent->ConnCnt) 782 ); 783 784 InsertTailList (&Parent->ConnectionList, &Sock->ConnectionList); 785 } 786 787 if (Sock->CreateCallback != NULL) { 788 Status = Sock->CreateCallback (Sock, Sock->Context); 789 if (EFI_ERROR (Status)) { 790 goto OnError; 791 } 792 } 793 794 return Sock; 795 796 OnError: 797 798 if (Sock->SockHandle != NULL) { 799 gBS->UninstallMultipleProtocolInterfaces ( 800 Sock->SockHandle, 801 TcpProtocolGuid, 802 &Sock->NetProtocol, 803 NULL 804 ); 805 } 806 807 if (NULL != Sock->SndBuffer.DataQueue) { 808 NetbufQueFree (Sock->SndBuffer.DataQueue); 809 } 810 811 if (NULL != Sock->RcvBuffer.DataQueue) { 812 NetbufQueFree (Sock->RcvBuffer.DataQueue); 813 } 814 815 FreePool (Sock); 816 817 return NULL; 818 } 819 820 /** 821 Destroy a socket. 822 823 @param[in, out] Sock Pointer to the socket. 824 825 **/ 826 VOID 827 SockDestroy ( 828 IN OUT SOCKET *Sock 829 ) 830 { 831 VOID *SockProtocol; 832 EFI_GUID *TcpProtocolGuid; 833 EFI_STATUS Status; 834 835 ASSERT (SockStream == Sock->Type); 836 837 if (Sock->DestroyCallback != NULL) { 838 Sock->DestroyCallback (Sock, Sock->Context); 839 } 840 841 // 842 // Flush the completion token buffered 843 // by sock and rcv, snd buffer 844 // 845 if (!SOCK_IS_UNCONFIGURED (Sock)) { 846 847 SockConnFlush (Sock); 848 SockSetState (Sock, SO_CLOSED); 849 Sock->ConfigureState = SO_UNCONFIGURED; 850 851 } 852 // 853 // Destroy the RcvBuffer Queue and SendBuffer Queue 854 // 855 NetbufQueFree (Sock->RcvBuffer.DataQueue); 856 NetbufQueFree (Sock->SndBuffer.DataQueue); 857 858 // 859 // Remove it from parent connection list if needed 860 // 861 if (Sock->Parent != NULL) { 862 863 RemoveEntryList (&(Sock->ConnectionList)); 864 (Sock->Parent->ConnCnt)--; 865 866 DEBUG ( 867 (EFI_D_WARN, 868 "SockDestroy: Delete a unaccepted socket from parent now conncnt is %d\n", 869 Sock->Parent->ConnCnt) 870 ); 871 872 Sock->Parent = NULL; 873 } 874 875 // 876 // Set the protocol guid and driver binding handle 877 // in the light of Sock->SockType 878 // 879 if (Sock->IpVersion == IP_VERSION_4) { 880 TcpProtocolGuid = &gEfiTcp4ProtocolGuid; 881 } else { 882 TcpProtocolGuid = &gEfiTcp6ProtocolGuid; 883 } 884 885 // 886 // Retrieve the protocol installed on this sock 887 // 888 Status = gBS->OpenProtocol ( 889 Sock->SockHandle, 890 TcpProtocolGuid, 891 &SockProtocol, 892 Sock->DriverBinding, 893 Sock->SockHandle, 894 EFI_OPEN_PROTOCOL_GET_PROTOCOL 895 ); 896 897 if (EFI_ERROR (Status)) { 898 899 DEBUG ( 900 (EFI_D_ERROR, 901 "SockDestroy: Open protocol installed on socket failed with %r\n", 902 Status) 903 ); 904 905 goto FreeSock; 906 } 907 908 // 909 // Uninstall the protocol installed on this sock 910 // in the light of Sock->SockType 911 // 912 gBS->UninstallMultipleProtocolInterfaces ( 913 Sock->SockHandle, 914 TcpProtocolGuid, 915 SockProtocol, 916 NULL 917 ); 918 919 FreeSock: 920 921 FreePool (Sock); 922 } 923 924 /** 925 Flush the sndBuffer and rcvBuffer of socket. 926 927 @param[in, out] Sock Pointer to the socket. 928 929 **/ 930 VOID 931 SockConnFlush ( 932 IN OUT SOCKET *Sock 933 ) 934 { 935 SOCKET *Child; 936 937 ASSERT (Sock != NULL); 938 939 // 940 // Clear the flag in this socket 941 // 942 Sock->Flag = 0; 943 944 // 945 // Flush the SndBuffer and RcvBuffer of Sock 946 // 947 NetbufQueFlush (Sock->SndBuffer.DataQueue); 948 NetbufQueFlush (Sock->RcvBuffer.DataQueue); 949 950 // 951 // Signal the pending token 952 // 953 if (Sock->ConnectionToken != NULL) { 954 SIGNAL_TOKEN (Sock->ConnectionToken, Sock->SockError); 955 Sock->ConnectionToken = NULL; 956 } 957 958 if (Sock->CloseToken != NULL) { 959 SIGNAL_TOKEN (Sock->CloseToken, Sock->SockError); 960 Sock->CloseToken = NULL; 961 } 962 963 SockFlushPendingToken (Sock, &(Sock->ListenTokenList)); 964 SockFlushPendingToken (Sock, &(Sock->RcvTokenList)); 965 SockFlushPendingToken (Sock, &(Sock->SndTokenList)); 966 SockFlushPendingToken (Sock, &(Sock->ProcessingSndTokenList)); 967 968 // 969 // Destroy the pending connection, if it is a listening socket 970 // 971 if (SOCK_IS_LISTENING (Sock)) { 972 while (!IsListEmpty (&Sock->ConnectionList)) { 973 Child = NET_LIST_HEAD ( 974 &Sock->ConnectionList, 975 SOCKET, 976 ConnectionList 977 ); 978 979 SockDestroyChild (Child); 980 } 981 982 Sock->ConnCnt = 0; 983 } 984 985 } 986 987 /** 988 Set the state of the socket. 989 990 @param[in, out] Sock Pointer to the socket. 991 @param[in] State The new socket state to be set. 992 993 **/ 994 VOID 995 SockSetState ( 996 IN OUT SOCKET *Sock, 997 IN UINT8 State 998 ) 999 { 1000 Sock->State = State; 1001 } 1002 1003 /** 1004 Clone a new socket, including its associated protocol control block. 1005 1006 @param[in] Sock Pointer to the socket to be cloned. 1007 1008 @return Pointer to the newly cloned socket. If NULL, an error condition occurred. 1009 1010 **/ 1011 SOCKET * 1012 SockClone ( 1013 IN SOCKET *Sock 1014 ) 1015 { 1016 SOCKET *ClonedSock; 1017 SOCK_INIT_DATA InitData; 1018 1019 InitData.BackLog = Sock->BackLog; 1020 InitData.Parent = Sock; 1021 InitData.State = Sock->State; 1022 InitData.ProtoHandler = Sock->ProtoHandler; 1023 InitData.Type = Sock->Type; 1024 InitData.RcvBufferSize = Sock->RcvBuffer.HighWater; 1025 InitData.SndBufferSize = Sock->SndBuffer.HighWater; 1026 InitData.DriverBinding = Sock->DriverBinding; 1027 InitData.IpVersion = Sock->IpVersion; 1028 InitData.Protocol = &(Sock->NetProtocol); 1029 InitData.CreateCallback = Sock->CreateCallback; 1030 InitData.DestroyCallback = Sock->DestroyCallback; 1031 InitData.Context = Sock->Context; 1032 InitData.ProtoData = Sock->ProtoReserved; 1033 InitData.DataSize = sizeof (Sock->ProtoReserved); 1034 1035 ClonedSock = SockCreate (&InitData); 1036 1037 if (NULL == ClonedSock) { 1038 DEBUG ((EFI_D_ERROR, "SockClone: no resource to create a cloned sock\n")); 1039 return NULL; 1040 } 1041 1042 SockSetState (ClonedSock, SO_CONNECTING); 1043 ClonedSock->ConfigureState = Sock->ConfigureState; 1044 1045 return ClonedSock; 1046 } 1047 1048 /** 1049 Called by the low layer protocol to indicate the socket a connection is 1050 established. 1051 1052 This function just changes the socket's state to SO_CONNECTED 1053 and signals the token used for connection establishment. 1054 1055 @param[in, out] Sock Pointer to the socket associated with the 1056 established connection. 1057 1058 **/ 1059 VOID 1060 SockConnEstablished ( 1061 IN OUT SOCKET *Sock 1062 ) 1063 { 1064 1065 ASSERT (SO_CONNECTING == Sock->State); 1066 1067 SockSetState (Sock, SO_CONNECTED); 1068 1069 if (NULL == Sock->Parent) { 1070 SockWakeConnToken (Sock); 1071 } else { 1072 SockWakeListenToken (Sock); 1073 } 1074 1075 } 1076 1077 /** 1078 Called by the low layer protocol to indicate the connection is closed. 1079 1080 This function flushes the socket, sets the state to SO_CLOSED, and signals 1081 the close token. 1082 1083 @param[in, out] Sock Pointer to the socket associated with the closed 1084 connection. 1085 1086 **/ 1087 VOID 1088 SockConnClosed ( 1089 IN OUT SOCKET *Sock 1090 ) 1091 { 1092 if (Sock->CloseToken != NULL) { 1093 SIGNAL_TOKEN (Sock->CloseToken, EFI_SUCCESS); 1094 Sock->CloseToken = NULL; 1095 } 1096 1097 SockConnFlush (Sock); 1098 SockSetState (Sock, SO_CLOSED); 1099 1100 if (Sock->Parent != NULL) { 1101 SockDestroyChild (Sock); 1102 } 1103 1104 } 1105 1106 /** 1107 Called by low layer protocol to indicate that some data was sent or processed. 1108 1109 This function trims the sent data in the socket send buffer, and signals the data 1110 token if proper. 1111 1112 @param[in, out] Sock Pointer to the socket. 1113 @param[in] Count The length of the data processed or sent, in bytes. 1114 1115 **/ 1116 VOID 1117 SockDataSent ( 1118 IN OUT SOCKET *Sock, 1119 IN UINT32 Count 1120 ) 1121 { 1122 SOCK_TOKEN *SockToken; 1123 SOCK_COMPLETION_TOKEN *SndToken; 1124 1125 ASSERT (!IsListEmpty (&Sock->ProcessingSndTokenList)); 1126 ASSERT (Count <= (Sock->SndBuffer.DataQueue)->BufSize); 1127 1128 NetbufQueTrim (Sock->SndBuffer.DataQueue, Count); 1129 1130 // 1131 // To check if we can signal some snd token in this socket 1132 // 1133 while (Count > 0) { 1134 SockToken = NET_LIST_HEAD ( 1135 &(Sock->ProcessingSndTokenList), 1136 SOCK_TOKEN, 1137 TokenList 1138 ); 1139 1140 SndToken = SockToken->Token; 1141 1142 if (SockToken->RemainDataLen <= Count) { 1143 1144 RemoveEntryList (&(SockToken->TokenList)); 1145 SIGNAL_TOKEN (SndToken, EFI_SUCCESS); 1146 Count -= SockToken->RemainDataLen; 1147 FreePool (SockToken); 1148 } else { 1149 1150 SockToken->RemainDataLen -= Count; 1151 Count = 0; 1152 } 1153 } 1154 1155 // 1156 // to judge if we can process some send token in 1157 // Sock->SndTokenList, if so process those send token 1158 // 1159 SockProcessSndToken (Sock); 1160 } 1161 1162 /** 1163 Called by the low layer protocol to copy some data in the socket send 1164 buffer starting from the specific offset to a buffer provided by 1165 the caller. 1166 1167 @param[in] Sock Pointer to the socket. 1168 @param[in] Offset The start point of the data to be copied. 1169 @param[in] Len The length of the data to be copied. 1170 @param[out] Dest Pointer to the destination to copy the data. 1171 1172 @return The data size copied. 1173 1174 **/ 1175 UINT32 1176 SockGetDataToSend ( 1177 IN SOCKET *Sock, 1178 IN UINT32 Offset, 1179 IN UINT32 Len, 1180 OUT UINT8 *Dest 1181 ) 1182 { 1183 ASSERT ((Sock != NULL) && SockStream == Sock->Type); 1184 1185 return NetbufQueCopy ( 1186 Sock->SndBuffer.DataQueue, 1187 Offset, 1188 Len, 1189 Dest 1190 ); 1191 } 1192 1193 /** 1194 Called by the low layer protocol to deliver received data to socket layer. 1195 1196 This function will append the data to the socket receive buffer, set the 1197 urgent data length, and then check if any receive token can be signaled. 1198 1199 @param[in, out] Sock Pointer to the socket. 1200 @param[in, out] NetBuffer Pointer to the buffer that contains the received data. 1201 @param[in] UrgLen The length of the urgent data in the received data. 1202 1203 **/ 1204 VOID 1205 SockDataRcvd ( 1206 IN OUT SOCKET *Sock, 1207 IN OUT NET_BUF *NetBuffer, 1208 IN UINT32 UrgLen 1209 ) 1210 { 1211 ASSERT ((Sock != NULL) && (Sock->RcvBuffer.DataQueue != NULL) && 1212 UrgLen <= NetBuffer->TotalSize); 1213 1214 NET_GET_REF (NetBuffer); 1215 1216 ((TCP_RSV_DATA *) (NetBuffer->ProtoData))->UrgLen = UrgLen; 1217 1218 NetbufQueAppend (Sock->RcvBuffer.DataQueue, NetBuffer); 1219 1220 SockWakeRcvToken (Sock); 1221 } 1222 1223 /** 1224 Get the length of the free space of the specific socket buffer. 1225 1226 @param[in] Sock Pointer to the socket. 1227 @param[in] Which Flag to indicate which socket buffer to check: 1228 either send buffer or receive buffer. 1229 1230 @return The length of the free space, in bytes. 1231 1232 **/ 1233 UINT32 1234 SockGetFreeSpace ( 1235 IN SOCKET *Sock, 1236 IN UINT32 Which 1237 ) 1238 { 1239 UINT32 BufferCC; 1240 SOCK_BUFFER *SockBuffer; 1241 1242 ASSERT (Sock != NULL && ((SOCK_SND_BUF == Which) || (SOCK_RCV_BUF == Which))); 1243 1244 if (SOCK_SND_BUF == Which) { 1245 SockBuffer = &(Sock->SndBuffer); 1246 } else { 1247 SockBuffer = &(Sock->RcvBuffer); 1248 } 1249 1250 BufferCC = (SockBuffer->DataQueue)->BufSize; 1251 1252 if (BufferCC >= SockBuffer->HighWater) { 1253 1254 return 0; 1255 } 1256 1257 return SockBuffer->HighWater - BufferCC; 1258 } 1259 1260 /** 1261 Called by the low layer protocol to indicate that there will be no more data 1262 from the communication peer. 1263 1264 This function sets the socket's state to SO_NO_MORE_DATA and signals all queued 1265 IO tokens with the error status EFI_CONNECTION_FIN. 1266 1267 @param[in, out] Sock Pointer to the socket. 1268 1269 **/ 1270 VOID 1271 SockNoMoreData ( 1272 IN OUT SOCKET *Sock 1273 ) 1274 { 1275 EFI_STATUS Err; 1276 1277 SOCK_NO_MORE_DATA (Sock); 1278 1279 if (!IsListEmpty (&Sock->RcvTokenList)) { 1280 1281 ASSERT (0 == GET_RCV_DATASIZE (Sock)); 1282 1283 Err = Sock->SockError; 1284 1285 SOCK_ERROR (Sock, EFI_CONNECTION_FIN); 1286 1287 SockFlushPendingToken (Sock, &Sock->RcvTokenList); 1288 1289 SOCK_ERROR (Sock, Err); 1290 1291 } 1292 } 1293 1294