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