blob: 5eee4ae9ca052c71bbd036ba76903a0185389ab2 [file] [log] [blame]
Roger Meier84e4a3c2011-09-16 20:58:44 +00001/* socketpair.c
2 * Copyright 2007 by Nathan C. Myers <ncm@cantrip.org>; some rights reserved.
3 * This code is Free Software. It may be copied freely, in original or
4 * modified form, subject only to the restrictions that (1) the author is
5 * relieved from all responsibilities for any use for any purpose, and (2)
6 * this copyright notice must be retained, unchanged, in its entirety. If
7 * for any reason the author might be held responsible for any consequences
8 * of copying or use, license is withheld.
9 */
10
11/*
12 * Licensed to the Apache Software Foundation (ASF) under one
13 * or more contributor license agreements. See the NOTICE file
14 * distributed with this work for additional information
15 * regarding copyright ownership. The ASF licenses this file
16 * to you under the Apache License, Version 2.0 (the
17 * "License"); you may not use this file except in compliance
18 * with the License. You may obtain a copy of the License at
19 *
20 * http://www.apache.org/licenses/LICENSE-2.0
21 *
22 * Unless required by applicable law or agreed to in writing,
23 * software distributed under the License is distributed on an
24 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
25 * KIND, either express or implied. See the License for the
26 * specific language governing permissions and limitations
27 * under the License.
28 */
29
30#include "SocketPair.h"
31
32// stl
33#include <string.h>
34
35// Win32
36#include <Winsock2.h>
37#include <WS2tcpip.h>
38
39int socketpair(int d, int type, int protocol, int sv[2])
40{
41 union {
42 struct sockaddr_in inaddr;
43 struct sockaddr addr;
44 } a;
45 SOCKET listener;
46 int e;
47 socklen_t addrlen = sizeof(a.inaddr);
48 DWORD flags = 0;
49 int reuse = 1;
50
51 if (sv == 0) {
52 WSASetLastError(WSAEINVAL);
53 return SOCKET_ERROR;
54 }
55
56 listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
57 if (listener == INVALID_SOCKET)
58 return SOCKET_ERROR;
59
60 memset(&a, 0, sizeof(a));
61 a.inaddr.sin_family = AF_INET;
62 a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
63 a.inaddr.sin_port = 0;
64
65 sv[0] = sv[1] = INVALID_SOCKET;
66 do {
67 if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR,
68 (char*) &reuse, (socklen_t) sizeof(reuse)) == -1)
69 break;
70 if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
71 break;
72 if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR)
73 break;
74 if (listen(listener, 1) == SOCKET_ERROR)
75 break;
76 sv[0] = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, flags);
77 if (sv[0] == INVALID_SOCKET)
78 break;
79 if (connect(sv[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
80 break;
81 sv[1] = accept(listener, NULL, NULL);
82 if (sv[1] == INVALID_SOCKET)
83 break;
84
85 closesocket(listener);
86 return 0;
87
88 } while (0);
89
90 e = WSAGetLastError();
91 closesocket(listener);
92 closesocket(sv[0]);
93 closesocket(sv[1]);
94 WSASetLastError(e);
95 return SOCKET_ERROR;
96}