Home | History | Annotate | Download | only in BsdSocketLib
      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