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