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 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 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 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