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