]>
git.proxmox.com Git - mirror_edk2.git/blob - StdLib/BsdSocketLib/recvfrom.c
2 Implement the recvfrom API.
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
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.
15 #include <SocketInternals.h>
19 Receive data from a network connection and return the remote system's address.
21 The recvfrom routine waits for receive data from a remote network
22 connection. This routine is typically called for SOCK_DGRAM sockets
23 when the socket is being shared by multiple remote systems and it is
24 important to get the remote system address for a response.
27 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html">POSIX</a>
28 documentation is available online.
30 @param [in] s Socket file descriptor returned from ::socket.
32 @param [in] buffer Address of a buffer to receive the data.
34 @param [in] length Length of the buffer in bytes.
36 @param [in] flags Message control flags
38 @param [out] address Network address to receive the remote system address
40 @param [in] address_len Length of the remote network address structure
42 @return This routine returns the number of valid bytes in the buffer,
43 zero if no data was received, and -1 when an error occurs.
44 In the case of an error, ::errno contains more details.
53 struct sockaddr
* address
,
54 socklen_t
* address_len
58 ssize_t LengthInBytes
;
60 EFI_SOCKET_PROTOCOL
* pSocketProtocol
;
62 struct timeval TimeVal
;
73 // Locate the context for this socket
75 pSocketProtocol
= BslFdToSocketProtocol ( s
, NULL
, &errno
);
76 if ( NULL
!= pSocketProtocol
) {
78 // Receive the data from the socket
80 Status
= pSocketProtocol
->pfnReceive ( pSocketProtocol
,
84 (size_t *)&LengthInBytes
,
88 if ( EFI_ERROR ( Status
)) {
90 if ( EAGAIN
== errno
) {
94 ByteCount
= sizeof ( TimeVal
);
95 LengthInBytes
= getsockopt ( s
,
100 if ( 0 == LengthInBytes
) {
102 // Compute the timeout
104 Timeout
= TimeVal
.tv_sec
;
105 Timeout
*= 1000 * 1000;
106 Timeout
+= TimeVal
.tv_usec
;
110 // The timer is only necessary if a timeout is running
113 Status
= EFI_SUCCESS
;
115 if ( 0 != Timeout
) {
116 Status
= gBS
->CreateEvent ( EVT_TIMER
,
122 if ( !EFI_ERROR ( Status
)) {
126 if ( NULL
!= pTimer
) {
127 Status
= gBS
->SetTimer ( pTimer
,
131 if ( !EFI_ERROR ( Status
)) {
133 // Loop until data is received or the timeout
137 pData
= (UINT8
*)buffer
;
140 // Determine if the timeout expired
142 if ( NULL
!= pTimer
) {
143 Status
= gBS
->CheckEvent ( pTimer
);
144 if ( EFI_SUCCESS
== Status
) {
146 if ( 0 == TotalBytes
) {
154 // Attempt to receive some data
156 Status
= pSocketProtocol
->pfnReceive ( pSocketProtocol
,
160 (size_t *)&LengthInBytes
,
164 if ( !EFI_ERROR ( Status
)) {
166 // Account for the data received
168 TotalBytes
+= LengthInBytes
;
169 pData
+= LengthInBytes
;
170 length
-= LengthInBytes
;
172 } while ( EFI_NOT_READY
== Status
);
173 LengthInBytes
= TotalBytes
;
178 if ( NULL
!= pTimer
) {
179 gBS
->SetTimer ( pTimer
,
188 if ( NULL
!= pTimer
) {
189 gBS
->CloseEvent ( pTimer
);
198 // Return the receive data length, -1 for errors
200 return LengthInBytes
;