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