1 /** @file
2   Implement the sendto API.
3 
4   Copyright (c) 2011, Intel Corporation
5   All rights reserved. This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include <SocketInternals.h>
16 
17 
18 /**
19   Send data using a network connection.
20 
21   The sendto routine queues data to the network for transmission.
22   This routine is typically used for SOCK_DGRAM sockets that are shared
23   between multiple machine where it is required to specify the target
24   system address when sending the data.
25 
26   The
27   <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html">POSIX</a>
28   documentation is available online.
29 
30   @param [in] s         Socket file descriptor returned from ::socket.
31 
32   @param [in] buffer    Address of a buffer containing the data to send.
33 
34   @param [in] length    Length of the buffer in bytes.
35 
36   @param [in] flags     Message control flags
37 
38   @param [in] to        Remote system address
39 
40   @param [in] tolen     Length of remote system address structure
41 
42   @return     This routine returns the number of data bytes that were
43               sent and -1 when an error occurs.  In the case of
44               an error, ::errno contains more details.
45 
46  **/
47 ssize_t
sendto(int s,const void * buffer,size_t length,int flags,const struct sockaddr * to,socklen_t tolen)48 sendto (
49   int s,
50   const void * buffer,
51   size_t length,
52   int flags,
53   const struct sockaddr * to,
54   socklen_t tolen
55   )
56 {
57   BOOLEAN bBlocking;
58   ssize_t LengthInBytes;
59   CONST UINT8 * pData;
60   struct __filedes * pDescriptor;
61   EFI_SOCKET_PROTOCOL * pSocketProtocol;
62   EFI_STATUS Status;
63 
64   //
65   //  Assume failure
66   //
67   LengthInBytes = -1;
68 
69   //
70   //  Locate the context for this socket
71   //
72   pSocketProtocol = BslFdToSocketProtocol ( s,
73                                             &pDescriptor,
74                                             &errno );
75   if ( NULL != pSocketProtocol ) {
76     //
77     //  Determine if the operation is blocking
78     //
79     bBlocking = (BOOLEAN)( 0 == ( pDescriptor->Oflags & O_NONBLOCK ));
80 
81     //
82     //  Send the data using the socket
83     //
84     pData = buffer;
85     do {
86       errno = 0;
87       Status = pSocketProtocol->pfnTransmit ( pSocketProtocol,
88                                               flags,
89                                               length,
90                                               pData,
91                                               (size_t *)&LengthInBytes,
92                                               to,
93                                               tolen,
94                                               &errno );
95       if ( EFI_ERROR ( Status ) && ( EFI_NOT_READY != Status )) {
96         LengthInBytes = -1;
97         break;
98       }
99 
100       //
101       //  Account for the data sent
102       //
103       pData += LengthInBytes;
104       length -= LengthInBytes;
105     } while (( 0 != length ) && ( EFI_NOT_READY == Status ) && bBlocking );
106   }
107 
108   //
109   //  Return the number of data bytes sent, -1 for errors
110   //
111   return (INT32)LengthInBytes;
112 }
113