]>
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
23 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html">POSIX</a>
24 documentation is available online.
26 @param [in] s Socket file descriptor returned from ::socket.
28 @param [in] buffer Address of a buffer to receive the data.
30 @param [in] length Length of the buffer in bytes.
32 @param [in] flags Message control flags
34 @param [out] address Network address to receive the remote system address
36 @param [in] address_len Length of the remote network address structure
38 @return ::recvfrom returns the number of valid bytes in the buffer,
39 zero if no data was received, and -1 when an error occurs.
40 In the case of an error, errno contains more details.
49 struct sockaddr
* address
,
50 socklen_t
* address_len
54 ssize_t LengthInBytes
;
56 EFI_SOCKET_PROTOCOL
* pSocketProtocol
;
58 struct timeval TimeVal
;
69 // Locate the context for this socket
71 pSocketProtocol
= BslFdToSocketProtocol ( s
, NULL
, &errno
);
72 if ( NULL
!= pSocketProtocol
) {
74 // Receive the data from the socket
76 Status
= pSocketProtocol
->pfnReceive ( pSocketProtocol
,
80 (size_t *)&LengthInBytes
,
84 if ( EFI_ERROR ( Status
)) {
86 if ( EAGAIN
== errno
) {
90 ByteCount
= sizeof ( TimeVal
);
91 LengthInBytes
= getsockopt ( s
,
96 if ( 0 == LengthInBytes
) {
98 // Compute the timeout
100 Timeout
= TimeVal
.tv_sec
;
101 Timeout
*= 1000 * 1000;
102 Timeout
+= TimeVal
.tv_usec
;
106 // The timer is only necessary if a timeout is running
109 Status
= EFI_SUCCESS
;
111 if ( 0 != Timeout
) {
112 Status
= gBS
->CreateEvent ( EVT_TIMER
,
118 if ( !EFI_ERROR ( Status
)) {
122 if ( NULL
!= pTimer
) {
123 Status
= gBS
->SetTimer ( pTimer
,
127 if ( !EFI_ERROR ( Status
)) {
129 // Loop until data is received or the timeout
133 pData
= (UINT8
*)buffer
;
136 // Determine if the timeout expired
138 if ( NULL
!= pTimer
) {
139 Status
= gBS
->CheckEvent ( pTimer
);
140 if ( EFI_SUCCESS
== Status
) {
142 if ( 0 == TotalBytes
) {
150 // Attempt to receive some data
152 Status
= pSocketProtocol
->pfnReceive ( pSocketProtocol
,
156 (size_t *)&LengthInBytes
,
160 if ( !EFI_ERROR ( Status
)) {
162 // Account for the data received
164 TotalBytes
+= LengthInBytes
;
165 pData
+= LengthInBytes
;
166 length
-= LengthInBytes
;
168 } while ( EFI_NOT_READY
== Status
);
169 LengthInBytes
= TotalBytes
;
174 if ( NULL
!= pTimer
) {
175 gBS
->SetTimer ( pTimer
,
184 if ( NULL
!= pTimer
) {
185 gBS
->CloseEvent ( pTimer
);
194 // Return the receive data length, -1 for errors
196 return LengthInBytes
;