forked from yongs207/libnet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
net_socketpair.c
91 lines (73 loc) · 2.52 KB
/
net_socketpair.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "net_socketpair.h"
#ifndef WSA_START
void static socket_init()
{
WORD version_requested = MAKEWORD (2, 2);
WSADATA wsa_data;
int rc = WSAStartup (version_requested, &wsa_data);
wsa_assert (rc == 0);
net_assert (LOBYTE (wsa_data.wVersion) == 2 &&HIBYTE (wsa_data.wVersion) == 2);
}
#else
void static socket_init()
{
}
#endif
void nsocketpair(fd_t* pair)
{
#ifdef _WIN32
// Create listening socket.
SOCKET listener;
BOOL so_reuseaddr = 1;
int rc;
BOOL tcp_nodelay = 1;
struct sockaddr_in addr;
int addrlen = sizeof (addr);
// Windows has no 'socketpair' function. CreatePipe is no good as pipe
// handles cannot be polled on. Here we create the socketpair by hand.
pair[0] = INVALID_SOCKET;
pair[1] = INVALID_SOCKET;
socket_init();
listener = socket (AF_INET, SOCK_STREAM, 0);
wsa_assert (listener != INVALID_SOCKET);
// Set SO_REUSEADDR and TCP_NODELAY on listening socket.
rc = setsockopt (listener, SOL_SOCKET, SO_REUSEADDR,
(char *)&so_reuseaddr, sizeof (so_reuseaddr));
wsa_assert (rc != SOCKET_ERROR);
rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELAY,
(char *)&tcp_nodelay, sizeof (tcp_nodelay));
wsa_assert (rc != SOCKET_ERROR);
// Bind listening socket to any free local port.
memset (&addr, 0, sizeof (addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
addr.sin_port = 0;
rc = bind (listener, (const struct sockaddr*) &addr, sizeof (addr));
wsa_assert (rc != SOCKET_ERROR);
// Retrieve local port listener is bound to (into addr).
rc = getsockname (listener, (struct sockaddr*) &addr, &addrlen);
wsa_assert (rc != SOCKET_ERROR);
// Listen for incomming connections.
rc = listen (listener, 1);
wsa_assert (rc != SOCKET_ERROR);
// Create the writer socket.
pair[0] = WSASocket (AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
wsa_assert (pair[0] != INVALID_SOCKET);
// Set TCP_NODELAY on writer socket.
rc = setsockopt (pair[0], IPPROTO_TCP, TCP_NODELAY,
(char *)&tcp_nodelay, sizeof (tcp_nodelay));
wsa_assert (rc != SOCKET_ERROR);
// Connect writer to the listener.
rc = connect (pair[0], (struct sockaddr *) &addr, sizeof (addr));
wsa_assert (rc != SOCKET_ERROR);
// Accept connection from writer.
pair[1] = accept (listener, NULL, NULL);
wsa_assert (pair[1] != INVALID_SOCKET);
// We don't need the listening socket anymore. Close it.
rc = closesocket (listener);
wsa_assert (rc != SOCKET_ERROR);
#else
int rc = socketpair (AF_UNIX, SOCK_STREAM, 0, pair);
errno_assert (rc == 0);
#endif
}