Back to index

openldap  2.4.31
sockpair.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1998-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in the file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 
00016 #include "portable.h"
00017 #include <ac/socket.h>
00018 #include <ac/unistd.h>
00019 
00020 #include <lutil.h>
00021 
00022 /* Return a pair of socket descriptors that are connected to each other.
00023  * The returned descriptors are suitable for use with select(). The two
00024  * descriptors may or may not be identical; the function may return
00025  * the same descriptor number in both slots. It is guaranteed that
00026  * data written on sds[1] will be readable on sds[0]. The returned
00027  * descriptors may be datagram oriented, so data should be written
00028  * in reasonably small pieces and read all at once. On Unix systems
00029  * this function is best implemented using a single pipe() call.
00030  */
00031 
00032 int lutil_pair( ber_socket_t sds[2] )
00033 {
00034 #ifdef USE_PIPE
00035        return pipe( sds );
00036 #else
00037        struct sockaddr_in si;
00038        int rc;
00039        ber_socklen_t len = sizeof(si);
00040        ber_socket_t sd;
00041 
00042        sd = socket( AF_INET, SOCK_DGRAM, 0 );
00043        if ( sd == AC_SOCKET_INVALID ) {
00044               return sd;
00045        }
00046        
00047        (void) memset( (void*) &si, '\0', len );
00048        si.sin_family = AF_INET;
00049        si.sin_port = 0;
00050        si.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
00051 
00052        rc = bind( sd, (struct sockaddr *)&si, len );
00053        if ( rc == AC_SOCKET_ERROR ) {
00054               tcp_close(sd);
00055               return rc;
00056        }
00057 
00058        rc = getsockname( sd, (struct sockaddr *)&si, &len );
00059        if ( rc == AC_SOCKET_ERROR ) {
00060               tcp_close(sd);
00061               return rc;
00062        }
00063 
00064        rc = connect( sd, (struct sockaddr *)&si, len );
00065        if ( rc == AC_SOCKET_ERROR ) {
00066               tcp_close(sd);
00067               return rc;
00068        }
00069 
00070        sds[0] = sd;
00071 #if !HAVE_WINSOCK
00072        sds[1] = dup( sds[0] );
00073 #else
00074        sds[1] = sds[0];
00075 #endif
00076        return 0;
00077 #endif
00078 }