blob: 4b65e6baae14eb7bda8c1bf4b4e0dace6b0279b8 [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.
Roger Meierb69d24d2012-10-04 18:02:15 +00003 * This code is Free Software. It may be copied freely, in original or
Roger Meier84e4a3c2011-09-16 20:58:44 +00004 * 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
Roger Meierb69d24d2012-10-04 18:02:15 +00008 * of copying or use, license is withheld.
Roger Meier84e4a3c2011-09-16 20:58:44 +00009 */
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
Roger Meier4285ba22013-06-10 21:17:23 +020030#include <thrift/windows/SocketPair.h>
Roger Meierd051ca02013-08-15 01:35:11 +020031#include <thrift/Thrift.h>
Roger Meier84e4a3c2011-09-16 20:58:44 +000032
33// stl
34#include <string.h>
35
36// Win32
Roger Meier84e4a3c2011-09-16 20:58:44 +000037#include <WS2tcpip.h>
38
Carl Yeksigian7cb7fc82013-06-07 07:33:01 -040039int thrift_socketpair(int d, int type, int protocol, THRIFT_SOCKET sv[2])
Roger Meier84e4a3c2011-09-16 20:58:44 +000040{
Roger Meierd051ca02013-08-15 01:35:11 +020041 THRIFT_UNUSED_VARIABLE(protocol);
42 THRIFT_UNUSED_VARIABLE(type);
43 THRIFT_UNUSED_VARIABLE(d);
44
Roger Meier84e4a3c2011-09-16 20:58:44 +000045 union {
46 struct sockaddr_in inaddr;
47 struct sockaddr addr;
48 } a;
Carl Yeksigian7cb7fc82013-06-07 07:33:01 -040049 THRIFT_SOCKET listener;
Roger Meier84e4a3c2011-09-16 20:58:44 +000050 int e;
51 socklen_t addrlen = sizeof(a.inaddr);
52 DWORD flags = 0;
53 int reuse = 1;
54
55 if (sv == 0) {
56 WSASetLastError(WSAEINVAL);
57 return SOCKET_ERROR;
58 }
59
60 listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
Roger Meierb69d24d2012-10-04 18:02:15 +000061 if (listener == INVALID_SOCKET)
Roger Meier84e4a3c2011-09-16 20:58:44 +000062 return SOCKET_ERROR;
63
64 memset(&a, 0, sizeof(a));
65 a.inaddr.sin_family = AF_INET;
66 a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
Roger Meierb69d24d2012-10-04 18:02:15 +000067 a.inaddr.sin_port = 0;
Roger Meier84e4a3c2011-09-16 20:58:44 +000068
69 sv[0] = sv[1] = INVALID_SOCKET;
70 do {
Carl Yeksigian7cb7fc82013-06-07 07:33:01 -040071 //ignore errors coming out of this setsockopt. This is because
72 //SO_EXCLUSIVEADDRUSE requires admin privileges on WinXP, but we don't
73 //want to force socket pairs to be an admin.
74 setsockopt(listener, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
75 (char*) &reuse, (socklen_t) sizeof(reuse));
Roger Meier84e4a3c2011-09-16 20:58:44 +000076 if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
77 break;
78 if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR)
79 break;
80 if (listen(listener, 1) == SOCKET_ERROR)
81 break;
82 sv[0] = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, flags);
83 if (sv[0] == INVALID_SOCKET)
84 break;
85 if (connect(sv[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
86 break;
87 sv[1] = accept(listener, NULL, NULL);
88 if (sv[1] == INVALID_SOCKET)
89 break;
90
91 closesocket(listener);
92 return 0;
93
94 } while (0);
95
96 e = WSAGetLastError();
97 closesocket(listener);
98 closesocket(sv[0]);
99 closesocket(sv[1]);
100 WSASetLastError(e);
101 return SOCKET_ERROR;
102}