/** Transmit the Packet to the other endpoint of the socket. @param[in] Tcp4Io The Tcp4Io wrapping the TCP socket. @param[in] Packet The packet to transmit. @retval EFI_SUCCESS The packet is trasmitted. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @retval Others Other errors as indicated. **/ EFI_STATUS Tcp4IoTransmit ( IN TCP4_IO *Tcp4Io, IN NET_BUF *Packet ) { EFI_TCP4_TRANSMIT_DATA *TxData; EFI_TCP4_PROTOCOL *Tcp4; EFI_STATUS Status; TxData = AllocatePool (sizeof (EFI_TCP4_TRANSMIT_DATA) + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA)); if (TxData == NULL) { return EFI_OUT_OF_RESOURCES; } TxData->Push = TRUE; TxData->Urgent = FALSE; TxData->DataLength = Packet->TotalSize; // // Build the fragment table. // TxData->FragmentCount = Packet->BlockOpNum; NetbufBuildExt (Packet, (NET_FRAGMENT *) &TxData->FragmentTable[0], &TxData->FragmentCount); Tcp4Io->TxToken.Packet.TxData = TxData; // // Trasnmit the packet. // Tcp4 = Tcp4Io->Tcp4; Status = Tcp4->Transmit (Tcp4, &Tcp4Io->TxToken); if (EFI_ERROR (Status)) { goto ON_EXIT; } while (!Tcp4Io->IsTxDone) { Tcp4->Poll (Tcp4); } Tcp4Io->IsTxDone = FALSE; Status = Tcp4Io->TxToken.CompletionToken.Status; ON_EXIT: FreePool (TxData); return Status; }
/** Receive the Packet by processing the associated HTTPS token. @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure. @param[in] Packet The packet to transmit. @param[in] Timeout The time to wait for connection done. @retval EFI_SUCCESS The Packet is received. @retval EFI_INVALID_PARAMETER HttpInstance is NULL or Packet is NULL. @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources. @retval EFI_TIMEOUT The operation is time out. @retval Others Other error as indicated. **/ EFI_STATUS EFIAPI TlsCommonReceive ( IN OUT HTTP_PROTOCOL *HttpInstance, IN NET_BUF *Packet, IN EFI_EVENT Timeout ) { EFI_TCP4_RECEIVE_DATA *Tcp4RxData; EFI_TCP6_RECEIVE_DATA *Tcp6RxData; EFI_STATUS Status; NET_FRAGMENT *Fragment; UINT32 FragmentCount; UINT32 CurrentFragment; Tcp4RxData = NULL; Tcp6RxData = NULL; if ((HttpInstance == NULL) || (Packet == NULL)) { return EFI_INVALID_PARAMETER; } FragmentCount = Packet->BlockOpNum; Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT)); if (Fragment == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } // // Build the fragment table. // NetbufBuildExt (Packet, Fragment, &FragmentCount); if (!HttpInstance->LocalAddressIsIPv6) { Tcp4RxData = HttpInstance->Tcp4TlsRxToken.Packet.RxData; if (Tcp4RxData == NULL) { return EFI_INVALID_PARAMETER; } Tcp4RxData->FragmentCount = 1; } else { Tcp6RxData = HttpInstance->Tcp6TlsRxToken.Packet.RxData; if (Tcp6RxData == NULL) { return EFI_INVALID_PARAMETER; } Tcp6RxData->FragmentCount = 1; } CurrentFragment = 0; Status = EFI_SUCCESS; while (CurrentFragment < FragmentCount) { if (!HttpInstance->LocalAddressIsIPv6) { Tcp4RxData->DataLength = Fragment[CurrentFragment].Len; Tcp4RxData->FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len; Tcp4RxData->FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk; Status = HttpInstance->Tcp4->Receive (HttpInstance->Tcp4, &HttpInstance->Tcp4TlsRxToken); } else { Tcp6RxData->DataLength = Fragment[CurrentFragment].Len; Tcp6RxData->FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len; Tcp6RxData->FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk; Status = HttpInstance->Tcp6->Receive (HttpInstance->Tcp6, &HttpInstance->Tcp6TlsRxToken); } if (EFI_ERROR (Status)) { goto ON_EXIT; } while (!HttpInstance->TlsIsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) { // // Poll until some data is received or an error occurs. // if (!HttpInstance->LocalAddressIsIPv6) { HttpInstance->Tcp4->Poll (HttpInstance->Tcp4); } else { HttpInstance->Tcp6->Poll (HttpInstance->Tcp6); } } if (!HttpInstance->TlsIsRxDone) { // // Timeout occurs, cancel the receive request. // if (!HttpInstance->LocalAddressIsIPv6) { HttpInstance->Tcp4->Cancel (HttpInstance->Tcp4, &HttpInstance->Tcp4TlsRxToken.CompletionToken); } else { HttpInstance->Tcp6->Cancel (HttpInstance->Tcp6, &HttpInstance->Tcp6TlsRxToken.CompletionToken); } Status = EFI_TIMEOUT; goto ON_EXIT; } else { HttpInstance->TlsIsRxDone = FALSE; } if (!HttpInstance->LocalAddressIsIPv6) { Status = HttpInstance->Tcp4TlsRxToken.CompletionToken.Status; if (EFI_ERROR (Status)) { goto ON_EXIT; } Fragment[CurrentFragment].Len -= Tcp4RxData->FragmentTable[0].FragmentLength; if (Fragment[CurrentFragment].Len == 0) { CurrentFragment++; } else { Fragment[CurrentFragment].Bulk += Tcp4RxData->FragmentTable[0].FragmentLength; } } else { Status = HttpInstance->Tcp6TlsRxToken.CompletionToken.Status; if (EFI_ERROR (Status)) { goto ON_EXIT; } Fragment[CurrentFragment].Len -= Tcp6RxData->FragmentTable[0].FragmentLength; if (Fragment[CurrentFragment].Len == 0) { CurrentFragment++; } else { Fragment[CurrentFragment].Bulk += Tcp6RxData->FragmentTable[0].FragmentLength; } } } ON_EXIT: if (Fragment != NULL) { FreePool (Fragment); } return Status; }
/** Transmit the Packet by processing the associated HTTPS token. @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure. @param[in] Packet The packet to transmit. @retval EFI_SUCCESS The packet is transmitted. @retval EFI_INVALID_PARAMETER HttpInstance is NULL or Packet is NULL. @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources. @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. @retval Others Other errors as indicated. **/ EFI_STATUS EFIAPI TlsCommonTransmit ( IN OUT HTTP_PROTOCOL *HttpInstance, IN NET_BUF *Packet ) { EFI_STATUS Status; VOID *Data; UINTN Size; if ((HttpInstance == NULL) || (Packet == NULL)) { return EFI_INVALID_PARAMETER; } if (!HttpInstance->LocalAddressIsIPv6) { Size = sizeof (EFI_TCP4_TRANSMIT_DATA) + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA); } else { Size = sizeof (EFI_TCP6_TRANSMIT_DATA) + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP6_FRAGMENT_DATA); } Data = AllocatePool (Size); if (Data == NULL) { return EFI_OUT_OF_RESOURCES; } if (!HttpInstance->LocalAddressIsIPv6) { ((EFI_TCP4_TRANSMIT_DATA *) Data)->Push = TRUE; ((EFI_TCP4_TRANSMIT_DATA *) Data)->Urgent = FALSE; ((EFI_TCP4_TRANSMIT_DATA *) Data)->DataLength = Packet->TotalSize; // // Build the fragment table. // ((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount = Packet->BlockOpNum; NetbufBuildExt ( Packet, (NET_FRAGMENT *) &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentTable[0], &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount ); HttpInstance->Tcp4TlsTxToken.Packet.TxData = (EFI_TCP4_TRANSMIT_DATA *) Data; Status = EFI_DEVICE_ERROR; // // Transmit the packet. // Status = HttpInstance->Tcp4->Transmit (HttpInstance->Tcp4, &HttpInstance->Tcp4TlsTxToken); if (EFI_ERROR (Status)) { goto ON_EXIT; } while (!HttpInstance->TlsIsTxDone) { HttpInstance->Tcp4->Poll (HttpInstance->Tcp4); } HttpInstance->TlsIsTxDone = FALSE; Status = HttpInstance->Tcp4TlsTxToken.CompletionToken.Status; } else { ((EFI_TCP6_TRANSMIT_DATA *) Data)->Push = TRUE; ((EFI_TCP6_TRANSMIT_DATA *) Data)->Urgent = FALSE; ((EFI_TCP6_TRANSMIT_DATA *) Data)->DataLength = Packet->TotalSize; // // Build the fragment table. // ((EFI_TCP6_TRANSMIT_DATA *) Data)->FragmentCount = Packet->BlockOpNum; NetbufBuildExt ( Packet, (NET_FRAGMENT *) &((EFI_TCP6_TRANSMIT_DATA *) Data)->FragmentTable[0], &((EFI_TCP6_TRANSMIT_DATA *) Data)->FragmentCount ); HttpInstance->Tcp6TlsTxToken.Packet.TxData = (EFI_TCP6_TRANSMIT_DATA *) Data; Status = EFI_DEVICE_ERROR; // // Transmit the packet. // Status = HttpInstance->Tcp6->Transmit (HttpInstance->Tcp6, &HttpInstance->Tcp6TlsTxToken); if (EFI_ERROR (Status)) { goto ON_EXIT; } while (!HttpInstance->TlsIsTxDone) { HttpInstance->Tcp6->Poll (HttpInstance->Tcp6); } HttpInstance->TlsIsTxDone = FALSE; Status = HttpInstance->Tcp6TlsTxToken.CompletionToken.Status; } ON_EXIT: FreePool (Data); return Status; }
/** Receive data from the socket. @param[in, out] TcpIo The TcpIo which wraps the socket to be destroyed. @param[in] Packet The buffer to hold the data copy from the socket rx buffer. @param[in] AsyncMode Is this receive asyncronous or not. @param[in] Timeout The time to wait for receiving the amount of data the Packet can hold. @retval EFI_SUCCESS The required amount of data is received from the socket. @retval EFI_INVALID_PARAMETER One or more parameters are invalid. @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. @retval EFI_OUT_OF_RESOURCES Failed to allocate momery. @retval EFI_TIMEOUT Failed to receive the required amount of data in the specified time period. @retval Others Other errors as indicated. **/ EFI_STATUS EFIAPI TcpIoReceive ( IN OUT TCP_IO *TcpIo, IN NET_BUF *Packet, IN BOOLEAN AsyncMode, IN EFI_EVENT Timeout ) { EFI_TCP4_PROTOCOL *Tcp4; EFI_TCP6_PROTOCOL *Tcp6; EFI_TCP4_RECEIVE_DATA *RxData; EFI_STATUS Status; NET_FRAGMENT *Fragment; UINT32 FragmentCount; UINT32 CurrentFragment; if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)|| (Packet == NULL)) { return EFI_INVALID_PARAMETER; } RxData = TcpIo->RxToken.Tcp4Token.Packet.RxData; if (RxData == NULL) { return EFI_INVALID_PARAMETER; } Tcp4 = NULL; Tcp6 = NULL; if (TcpIo->TcpVersion == TCP_VERSION_4) { Tcp4 = TcpIo->Tcp.Tcp4; if (TcpIo->IsListenDone) { Tcp4 = TcpIo->NewTcp.Tcp4; } if (Tcp4 == NULL) { return EFI_DEVICE_ERROR; } } else if (TcpIo->TcpVersion == TCP_VERSION_6) { Tcp6 = TcpIo->Tcp.Tcp6; if (TcpIo->IsListenDone) { Tcp6 = TcpIo->NewTcp.Tcp6; } if (Tcp6 == NULL) { return EFI_DEVICE_ERROR; } } else { return EFI_UNSUPPORTED; } FragmentCount = Packet->BlockOpNum; Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT)); if (Fragment == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } // // Build the fragment table. // NetbufBuildExt (Packet, Fragment, &FragmentCount); RxData->FragmentCount = 1; CurrentFragment = 0; Status = EFI_SUCCESS; while (CurrentFragment < FragmentCount) { RxData->DataLength = Fragment[CurrentFragment].Len; RxData->FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len; RxData->FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk; if (TcpIo->TcpVersion == TCP_VERSION_4) { Status = Tcp4->Receive (Tcp4, &TcpIo->RxToken.Tcp4Token); } else { Status = Tcp6->Receive (Tcp6, &TcpIo->RxToken.Tcp6Token); } if (EFI_ERROR (Status)) { goto ON_EXIT; } while (!TcpIo->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) { // // Poll until some data is received or an error occurs. // if (TcpIo->TcpVersion == TCP_VERSION_4) { Tcp4->Poll (Tcp4); } else { Tcp6->Poll (Tcp6); } } if (!TcpIo->IsRxDone) { // // Timeout occurs, cancel the receive request. // if (TcpIo->TcpVersion == TCP_VERSION_4) { Tcp4->Cancel (Tcp4, &TcpIo->RxToken.Tcp4Token.CompletionToken); } else { Tcp6->Cancel (Tcp6, &TcpIo->RxToken.Tcp6Token.CompletionToken); } Status = EFI_TIMEOUT; goto ON_EXIT; } else { TcpIo->IsRxDone = FALSE; } Status = TcpIo->RxToken.Tcp4Token.CompletionToken.Status; if (EFI_ERROR (Status)) { goto ON_EXIT; } Fragment[CurrentFragment].Len -= RxData->FragmentTable[0].FragmentLength; if (Fragment[CurrentFragment].Len == 0) { CurrentFragment++; } else { Fragment[CurrentFragment].Bulk += RxData->FragmentTable[0].FragmentLength; } } ON_EXIT: if (Fragment != NULL) { FreePool (Fragment); } return Status; }
/** Transmit the Packet to the other endpoint of the socket. @param[in] TcpIo The TcpIo wrapping the TCP socket. @param[in] Packet The packet to transmit. @retval EFI_SUCCESS The packet is trasmitted. @retval EFI_INVALID_PARAMETER One or more parameters are invalid. @retval EFI_UNSUPPORTED One or more of the control options are not supported in the implementation. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. @retval Others Other errors as indicated. **/ EFI_STATUS EFIAPI TcpIoTransmit ( IN TCP_IO *TcpIo, IN NET_BUF *Packet ) { EFI_STATUS Status; VOID *Data; EFI_TCP4_PROTOCOL *Tcp4; EFI_TCP6_PROTOCOL *Tcp6; UINTN Size; if ((TcpIo == NULL) || (TcpIo->Tcp.Tcp4 == NULL)|| (Packet == NULL)) { return EFI_INVALID_PARAMETER; } if (TcpIo->TcpVersion == TCP_VERSION_4) { Size = sizeof (EFI_TCP4_TRANSMIT_DATA) + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA); } else if (TcpIo->TcpVersion == TCP_VERSION_6) { Size = sizeof (EFI_TCP6_TRANSMIT_DATA) + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP6_FRAGMENT_DATA); } else { return EFI_UNSUPPORTED; } Data = AllocatePool (Size); if (Data == NULL) { return EFI_OUT_OF_RESOURCES; } ((EFI_TCP4_TRANSMIT_DATA *) Data)->Push = TRUE; ((EFI_TCP4_TRANSMIT_DATA *) Data)->Urgent = FALSE; ((EFI_TCP4_TRANSMIT_DATA *) Data)->DataLength = Packet->TotalSize; // // Build the fragment table. // ((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount = Packet->BlockOpNum; NetbufBuildExt ( Packet, (NET_FRAGMENT *) &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentTable[0], &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount ); Tcp4 = NULL; Tcp6 = NULL; Status = EFI_DEVICE_ERROR; // // Trasnmit the packet. // if (TcpIo->TcpVersion == TCP_VERSION_4) { TcpIo->TxToken.Tcp4Token.Packet.TxData = (EFI_TCP4_TRANSMIT_DATA *) Data; Tcp4 = TcpIo->Tcp.Tcp4; if (TcpIo->IsListenDone) { Tcp4 = TcpIo->NewTcp.Tcp4; } if (Tcp4 == NULL) { goto ON_EXIT; } Status = Tcp4->Transmit (Tcp4, &TcpIo->TxToken.Tcp4Token); } else { TcpIo->TxToken.Tcp6Token.Packet.TxData = (EFI_TCP6_TRANSMIT_DATA *) Data; Tcp6 = TcpIo->Tcp.Tcp6; if (TcpIo->IsListenDone) { Tcp6 = TcpIo->NewTcp.Tcp6; } if (Tcp6 == NULL) { goto ON_EXIT; } Status = Tcp6->Transmit (Tcp6, &TcpIo->TxToken.Tcp6Token); } if (EFI_ERROR (Status)) { goto ON_EXIT; } while (!TcpIo->IsTxDone) { if (TcpIo->TcpVersion == TCP_VERSION_4) { Tcp4->Poll (Tcp4); } else { Tcp6->Poll (Tcp6); } } TcpIo->IsTxDone = FALSE; Status = TcpIo->TxToken.Tcp4Token.CompletionToken.Status; ON_EXIT: FreePool (Data); return Status; }
/** Receive data from the socket. @param[in] Tcp4Io The Tcp4Io which wraps the socket to be destroyed. @param[in] Packet The buffer to hold the data copy from the soket rx buffer. @param[in] AsyncMode Is this receive asyncronous or not. @param[in] Timeout The time to wait for receiving the amount of data the Packet can hold. @retval EFI_SUCCESS The required amount of data is received from the socket. @retval EFI_OUT_OF_RESOURCES Failed to allocate momery. @retval EFI_TIMEOUT Failed to receive the required amount of data in the specified time period. @retval Others Other errors as indicated. **/ EFI_STATUS Tcp4IoReceive ( IN TCP4_IO *Tcp4Io, IN NET_BUF *Packet, IN BOOLEAN AsyncMode, IN EFI_EVENT Timeout ) { EFI_TCP4_PROTOCOL *Tcp4; EFI_TCP4_RECEIVE_DATA RxData; EFI_STATUS Status; NET_FRAGMENT *Fragment; UINT32 FragmentCount; UINT32 CurrentFragment; FragmentCount = Packet->BlockOpNum; Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT)); if (Fragment == NULL) { return EFI_OUT_OF_RESOURCES; } // // Build the fragment table. // NetbufBuildExt (Packet, Fragment, &FragmentCount); RxData.FragmentCount = 1; Tcp4Io->RxToken.Packet.RxData = &RxData; CurrentFragment = 0; Tcp4 = Tcp4Io->Tcp4; Status = EFI_SUCCESS; while (CurrentFragment < FragmentCount) { RxData.DataLength = Fragment[CurrentFragment].Len; RxData.FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len; RxData.FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk; Status = Tcp4->Receive (Tcp4, &Tcp4Io->RxToken); if (EFI_ERROR (Status)) { goto ON_EXIT; } while (!Tcp4Io->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) { // // Poll until some data is received or something error happens. // Tcp4->Poll (Tcp4); } if (!Tcp4Io->IsRxDone) { // // Timeout occurs, cancel the receive request. // Tcp4->Cancel (Tcp4, &Tcp4Io->RxToken.CompletionToken); Status = EFI_TIMEOUT; goto ON_EXIT; } else { Tcp4Io->IsRxDone = FALSE; } if (EFI_ERROR (Tcp4Io->RxToken.CompletionToken.Status)) { Status = Tcp4Io->RxToken.CompletionToken.Status; goto ON_EXIT; } Fragment[CurrentFragment].Len -= RxData.FragmentTable[0].FragmentLength; if (Fragment[CurrentFragment].Len == 0) { CurrentFragment++; } else { Fragment[CurrentFragment].Bulk += RxData.FragmentTable[0].FragmentLength; } } ON_EXIT: Tcp4Io->RxToken.Packet.RxData = NULL; FreePool (Fragment); return Status; }