| /** @file | |
| Implement the sendto API. | |
| Copyright (c) 2011, Intel Corporation | |
| All rights reserved. This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include <SocketInternals.h> | |
| /** | |
| Send data using a network connection. | |
| The sendto routine queues data to the network for transmission. | |
| This routine is typically used for SOCK_DGRAM sockets that are shared | |
| between multiple machine where it is required to specify the target | |
| system address when sending the data. | |
| The | |
| <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html">POSIX</a> | |
| documentation is available online. | |
| @param [in] s Socket file descriptor returned from ::socket. | |
| @param [in] buffer Address of a buffer containing the data to send. | |
| @param [in] length Length of the buffer in bytes. | |
| @param [in] flags Message control flags | |
| @param [in] to Remote system address | |
| @param [in] tolen Length of remote system address structure | |
| @return This routine returns the number of data bytes that were | |
| sent and -1 when an error occurs. In the case of | |
| an error, ::errno contains more details. | |
| **/ | |
| ssize_t | |
| sendto ( | |
| int s, | |
| const void * buffer, | |
| size_t length, | |
| int flags, | |
| const struct sockaddr * to, | |
| socklen_t tolen | |
| ) | |
| { | |
| BOOLEAN bBlocking; | |
| ssize_t LengthInBytes; | |
| CONST UINT8 * pData; | |
| struct __filedes * pDescriptor; | |
| EFI_SOCKET_PROTOCOL * pSocketProtocol; | |
| EFI_STATUS Status; | |
| // | |
| // Assume failure | |
| // | |
| LengthInBytes = -1; | |
| // | |
| // Locate the context for this socket | |
| // | |
| pSocketProtocol = BslFdToSocketProtocol ( s, | |
| &pDescriptor, | |
| &errno ); | |
| if ( NULL != pSocketProtocol ) { | |
| // | |
| // Determine if the operation is blocking | |
| // | |
| bBlocking = (BOOLEAN)( 0 == ( pDescriptor->Oflags & O_NONBLOCK )); | |
| // | |
| // Send the data using the socket | |
| // | |
| pData = buffer; | |
| do { | |
| errno = 0; | |
| Status = pSocketProtocol->pfnTransmit ( pSocketProtocol, | |
| flags, | |
| length, | |
| pData, | |
| (size_t *)&LengthInBytes, | |
| to, | |
| tolen, | |
| &errno ); | |
| if ( EFI_ERROR ( Status ) && ( EFI_NOT_READY != Status )) { | |
| LengthInBytes = -1; | |
| break; | |
| } | |
| // | |
| // Account for the data sent | |
| // | |
| pData += LengthInBytes; | |
| length -= LengthInBytes; | |
| } while (( 0 != length ) && ( EFI_NOT_READY == Status ) && bBlocking ); | |
| } | |
| // | |
| // Return the number of data bytes sent, -1 for errors | |
| // | |
| return (INT32)LengthInBytes; | |
| } |