/* 
 * sockutil.c --
 *
 *	This module implements utilities for sockets.
 *
 * Copyright (c) 1990-1994 The Regents of the University of California.
 * All rights reserved.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 */

#include "xlibInt.h"

/*
 *--------------------------------------------------------------
 *
 * CreateSocketPair --
 *
 *	This procedure creates a connected socket pair
 *
 * Results:
 *	0 if OK, the error if not OK.
 *
 * Side effects:
 *	None
 *
 *--------------------------------------------------------------
 */
int
CreateSocketPair(void *sockPair)
{
    SOCKET servsock, *pair;
    int val;
    struct sockaddr_in serv_addr, cli_addr;

    pair = (SOCKET *) sockPair;

    servsock = socket(PF_INET, SOCK_STREAM, 0);
    if (servsock == INVALID_SOCKET) {
	return WSAGetLastError();
    }

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(0);
    
    val = sizeof(serv_addr);
    if (bind(servsock, (struct sockaddr *) &serv_addr, val) < 0) {
	closesocket(servsock);
	return WSAGetLastError();
    }

    listen(servsock, 1);

    if (getsockname (servsock, (struct sockaddr *) &serv_addr, &val) < 0) {
	closesocket(servsock);
	return WSAGetLastError();
    }

    pair[0] = socket(PF_INET, SOCK_STREAM, 0);
    if (pair[0] == INVALID_SOCKET) {
	closesocket(servsock);
	return WSAGetLastError();
    }

    memset(&cli_addr, 0, sizeof(cli_addr));
    cli_addr.sin_family = AF_INET;
    cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    cli_addr.sin_port = serv_addr.sin_port;

    if (connect(pair[0], (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0) {
	closesocket(pair[0]);
	closesocket(servsock);
	return WSAGetLastError();
    }

    pair[1] = accept(servsock, (struct sockaddr *) &serv_addr, &val);
    if (pair[1] == INVALID_SOCKET) {
	closesocket(pair[0]);
	closesocket(servsock);
	return WSAGetLastError();
    }
    
    closesocket(servsock);

    return 0;
}
