1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pipe/p_compiler.h"
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_network.h"
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_debug.h"
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#  include <winsock2.h>
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#  include <windows.h>
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || \
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   defined(PIPE_OS_APPLE) || defined(PIPE_OS_CYGWIN) || defined(PIPE_OS_SOLARIS)
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#  include <sys/socket.h>
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#  include <netinet/in.h>
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#  include <unistd.h>
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#  include <fcntl.h>
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#  include <netdb.h>
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#  warning "No socket implementation"
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgboolean
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgu_socket_init()
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   WORD wVersionRequested;
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   WSADATA wsaData;
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int err;
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   wVersionRequested = MAKEWORD(1, 1);
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   err = WSAStartup(wVersionRequested, &wsaData);
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (err != 0) {
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      debug_printf("WSAStartup failed with error: %d\n", err);
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return FALSE;
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#elif defined(PIPE_HAVE_SOCKETS)
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return FALSE;
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgu_socket_stop()
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   WSACleanup();
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgu_socket_close(int s)
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (s < 0)
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) \
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    || defined(PIPE_OS_APPLE) || defined(PIPE_OS_SOLARIS)
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shutdown(s, SHUT_RDWR);
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   close(s);
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   shutdown(s, SD_BOTH);
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   closesocket(s);
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(0);
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint u_socket_accept(int s)
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(PIPE_HAVE_SOCKETS)
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return accept(s, NULL, NULL);
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return -1;
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgu_socket_send(int s, void *data, size_t size)
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(PIPE_HAVE_SOCKETS)
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return send(s, data, size, 0);
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return -1;
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgu_socket_peek(int s, void *data, size_t size)
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(PIPE_HAVE_SOCKETS)
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return recv(s, data, size, MSG_PEEK);
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return -1;
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgu_socket_recv(int s, void *data, size_t size)
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(PIPE_HAVE_SOCKETS)
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return recv(s, data, size, 0);
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return -1;
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgu_socket_connect(const char *hostname, uint16_t port)
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(PIPE_HAVE_SOCKETS)
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int s;
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct sockaddr_in sa;
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct hostent *host = NULL;
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&sa, 0, sizeof(struct sockaddr_in));
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   host = gethostbyname(hostname);
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!host)
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return -1;
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memcpy((char *)&sa.sin_addr,host->h_addr_list[0],host->h_length);
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   sa.sin_family= host->h_addrtype;
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   sa.sin_port = htons(port);
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s = socket(host->h_addrtype, SOCK_STREAM, IPPROTO_TCP);
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (s < 0)
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return -1;
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (connect(s, (struct sockaddr *)&sa, sizeof(sa))) {
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      u_socket_close(s);
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return -1;
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return s;
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(0);
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return -1;
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgu_socket_listen_on_port(uint16_t portnum)
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(PIPE_HAVE_SOCKETS)
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int s;
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct sockaddr_in sa;
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&sa, 0, sizeof(struct sockaddr_in));
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   sa.sin_family = AF_INET;
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   sa.sin_port = htons(portnum);
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (s < 0)
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return -1;
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (bind(s, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) == -1) {
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      u_socket_close(s);
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return -1;
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   listen(s, 0);
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return s;
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(0);
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return -1;
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgu_socket_block(int s, boolean block)
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) \
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    || defined(PIPE_OS_APPLE) || defined(PIPE_OS_SOLARIS)
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int old = fcntl(s, F_GETFL, 0);
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (old == -1)
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* TODO obey block */
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (block)
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      fcntl(s, F_SETFL, old & ~O_NONBLOCK);
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      fcntl(s, F_SETFL, old | O_NONBLOCK);
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   u_long iMode = block ? 0 : 1;
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ioctlsocket(s, FIONBIO, &iMode);
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(0);
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
192