1 /** @file
2 Implement the accept 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 Worker routine for ::accept and ::AcceptNB
20
21 @param [in] s Socket file descriptor returned from ::socket.
22
23 @param [in] bBlockingAllowed TRUE if this is a blocking call
24 @param [in] address Address of a buffer to receive the remote network address.
25
26 @param [in, out] address_len Address of a buffer containing the Length in bytes
27 of the remote network address buffer. Upon return,
28 contains the length of the remote network address.
29
30 @return AcceptWork returns zero if successful and -1 when an error occurs.
31 In the case of an error, ::errno contains more details.
32
33 **/
34 int
AcceptWork(int s,BOOLEAN bBlockingAllowed,struct sockaddr * address,socklen_t * address_len)35 AcceptWork (
36 int s,
37 BOOLEAN bBlockingAllowed,
38 struct sockaddr * address,
39 socklen_t * address_len
40 )
41 {
42 BOOLEAN bBlocking;
43 INT32 NewSocketFd;
44 struct __filedes * pDescriptor;
45 EFI_SOCKET_PROTOCOL * pNewSocket;
46 EFI_SOCKET_PROTOCOL * pSocketProtocol;
47 EFI_STATUS Status;
48
49 //
50 // Assume failure
51 //
52 NewSocketFd = -1;
53
54 //
55 // Locate the context for this socket
56 //
57 pSocketProtocol = BslFdToSocketProtocol ( s,
58 &pDescriptor,
59 &errno );
60 if ( NULL != pSocketProtocol ) {
61 //
62 // Determine if the operation is blocking
63 //
64 bBlocking = (BOOLEAN)( 0 == ( pDescriptor->Oflags & O_NONBLOCK ));
65 bBlocking &= bBlockingAllowed;
66
67 //
68 // Attempt to accept a new network connection
69 //
70 do {
71 Status = pSocketProtocol->pfnAccept ( pSocketProtocol,
72 address,
73 address_len,
74 &pNewSocket,
75 &errno );
76 } while ( bBlocking && ( EFI_NOT_READY == Status ));
77
78 //
79 // Convert the protocol to a socket
80 //
81 if ( !EFI_ERROR ( Status )) {
82 NewSocketFd = BslSocketProtocolToFd ( pNewSocket, &errno );
83 if ( -1 == NewSocketFd ) {
84 //
85 // Close the socket
86 //
87 BslSocketCloseWork ( pNewSocket, NULL );
88 }
89 }
90 }
91
92 //
93 // Return the new socket file descriptor
94 //
95 return NewSocketFd;
96 }
97
98
99 /**
100 Accept a network connection.
101
102 The accept routine waits for a network connection to the socket.
103 It returns the remote network address to the caller if requested.
104
105 The
106 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html">POSIX</a>
107 documentation is available online.
108
109 @param [in] s Socket file descriptor returned from ::socket.
110
111 @param [in] address Address of a buffer to receive the remote network address.
112
113 @param [in, out] address_len Address of a buffer containing the Length in bytes
114 of the remote network address buffer. Upon return,
115 contains the length of the remote network address.
116
117 @return The accept routine returns zero if successful and -1 when an error occurs.
118 In the case of an error, ::errno contains more details.
119
120 **/
121 int
accept(int s,struct sockaddr * address,socklen_t * address_len)122 accept (
123 int s,
124 struct sockaddr * address,
125 socklen_t * address_len
126 )
127 {
128 //
129 // Wait for the accept call to complete
130 //
131 return AcceptWork ( s, TRUE, address, address_len );
132 }
133
134
135 /**
136 Non blocking version of ::accept.
137
138 @param [in] s Socket file descriptor returned from ::socket.
139
140 @param [in] address Address of a buffer to receive the remote network address.
141
142 @param [in, out] address_len Address of a buffer containing the Length in bytes
143 of the remote network address buffer. Upon return,
144 contains the length of the remote network address.
145
146 @return This routine returns zero if successful and -1 when an error occurs.
147 In the case of an error, ::errno contains more details.
148
149 **/
150 int
AcceptNB(int s,struct sockaddr * address,socklen_t * address_len)151 AcceptNB (
152 int s,
153 struct sockaddr * address,
154 socklen_t * address_len
155 )
156 {
157 //
158 // Attempt to accept a network connection
159 //
160 return AcceptWork ( s, FALSE, address, address_len );
161 }
162