1 #if defined(_WIN32)
2
3 #include "win32_socket.h"
4
5 #undef socket
6 #undef connect
7 #undef accept
8 #undef shutdown
9
10 #include <string.h>
11 #include <errno.h>
12 #include <assert.h>
13
win32_poll(struct pollfd * fds,unsigned int nfds,int timo)14 int win32_poll(struct pollfd *fds, unsigned int nfds, int timo) {
15 struct timeval timeout, *toptr;
16 fd_set ifds, ofds, efds, *ip, *op;
17 unsigned int i;
18 int rc;
19
20 #ifdef _MSC_VER
21 #pragma warning(disable: 4548)
22 #endif
23
24 /* Set up the file-descriptor sets in ifds, ofds and efds. */
25 FD_ZERO(&ifds);
26 FD_ZERO(&ofds);
27 FD_ZERO(&efds);
28
29 for (i = 0, op = ip = 0; i < nfds; ++i) {
30 fds[i].revents = 0;
31
32 if (fds[i].events & (POLLIN | POLLPRI)) {
33 ip = &ifds;
34 FD_SET(fds[i].fd, ip);
35 }
36
37 if (fds[i].events & POLLOUT) {
38 op = &ofds;
39 FD_SET(fds[i].fd, op);
40 }
41
42 FD_SET(fds[i].fd, &efds);
43 }
44
45 #ifdef _MSC_VER
46 #pragma warning(default: 4548)
47 #endif
48
49 /* Set up the timeval structure for the timeout parameter */
50 if (timo < 0) {
51 toptr = 0;
52 } else {
53 toptr = &timeout;
54 timeout.tv_sec = timo / 1000;
55 timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000;
56 }
57
58 #ifdef DEBUG_POLL
59 printf("Entering select() sec=%ld usec=%ld ip=%lx op=%lx\n",
60 (long)timeout.tv_sec, (long)timeout.tv_usec, (long)ip, (long)op);
61 #endif
62
63 rc = select(0, ip, op, &efds, toptr);
64
65 #ifdef DEBUG_POLL
66 printf("Exiting select rc=%d\n", rc);
67 #endif
68
69 if (rc <= 0) { return(rc); }
70
71 if (rc > 0) {
72 for ( i = 0; i < nfds; ++i) {
73 int fd = fds[i].fd;
74
75 if (fds[i].events & (POLLIN | POLLPRI) && FD_ISSET(fd, &ifds)) {
76 fds[i].revents |= POLLIN;
77 }
78
79 if (fds[i].events & POLLOUT && FD_ISSET(fd, &ofds)) {
80 fds[i].revents |= POLLOUT;
81 }
82
83 if (FD_ISSET(fd, &efds)) {
84 // Some error was detected ... should be some way to know
85 fds[i].revents |= POLLHUP;
86 }
87
88 #ifdef DEBUG_POLL
89 printf("%d %d %d revent = %x\n",
90 FD_ISSET(fd, &ifds),
91 FD_ISSET(fd, &ofds),
92 FD_ISSET(fd, &efds),
93 fds[i].revents);
94 #endif
95
96 }
97 }
98
99 return(rc);
100 }
101
set_connect_errno(int winsock_err)102 static void set_connect_errno(int winsock_err) {
103 switch (winsock_err) {
104 case WSAEINVAL:
105 case WSAEALREADY:
106 case WSAEWOULDBLOCK:
107 errno = EINPROGRESS;
108 break;
109 default:
110 errno = winsock_err;
111 break;
112 }
113 }
114
set_socket_errno(int winsock_err)115 static void set_socket_errno(int winsock_err) {
116 switch (winsock_err) {
117 case WSAEWOULDBLOCK:
118 errno = EAGAIN;
119 break;
120 default:
121 errno = winsock_err;
122 break;
123 }
124 }
125
126 /* A wrapper around the socket() function.
127 * The purpose of this wrapper is to ensure that the global errno symbol is set if an error occurs,
128 * even if we are using winsock.
129 */
win32_socket(int domain,int type,int protocol)130 SOCKET win32_socket(int domain, int type, int protocol) {
131 SOCKET fd = socket(domain, type, protocol);
132
133 if (fd == INVALID_SOCKET) { set_socket_errno(WSAGetLastError()); }
134
135 return(fd);
136 }
137
138 /* A wrapper around the connect() function.
139 * The purpose of this wrapper is to ensure that the global errno symbol is set if an error occurs,
140 * even if we are using winsock.
141 */
win32_connect(SOCKET fd,struct sockaddr * addr,socklen_t addr_len)142 int win32_connect(SOCKET fd, struct sockaddr *addr, socklen_t addr_len) {
143 int rc = connect(fd, addr, addr_len);
144 assert(rc == 0 || rc == SOCKET_ERROR);
145
146 if (rc == SOCKET_ERROR) { set_connect_errno(WSAGetLastError()); }
147
148 return(rc);
149 }
150
151 /* A wrapper around the accept() function.
152 * The purpose of this wrapper is to ensure that the global errno symbol is set if an error occurs,
153 * even if we are using winsock.
154 */
win32_accept(SOCKET fd,struct sockaddr * addr,socklen_t * addr_len)155 SOCKET win32_accept(SOCKET fd, struct sockaddr *addr, socklen_t *addr_len) {
156 SOCKET newfd = accept(fd, addr, addr_len);
157
158 if (newfd == INVALID_SOCKET) {
159 set_socket_errno(WSAGetLastError());
160 newfd = (SOCKET)-1;
161 }
162
163 return(newfd);
164 }
165
166 /* A wrapper around the shutdown() function.
167 * The purpose of this wrapper is to ensure that the global errno symbol is set if an error occurs,
168 * even if we are using winsock.
169 */
win32_shutdown(SOCKET fd,int mode)170 int win32_shutdown(SOCKET fd, int mode) {
171 int rc = shutdown(fd, mode);
172 assert(rc == 0 || rc == SOCKET_ERROR);
173
174 if (rc == SOCKET_ERROR) { set_socket_errno(WSAGetLastError()); }
175
176 return(rc);
177 }
178
win32_close_socket(SOCKET fd)179 int win32_close_socket(SOCKET fd) {
180 int rc = closesocket(fd);
181
182 if (rc == SOCKET_ERROR) { set_socket_errno(WSAGetLastError()); }
183
184 return(rc);
185 }
186
win32_write_socket(SOCKET fd,void * buf,int n)187 ssize_t win32_write_socket(SOCKET fd, void *buf, int n) {
188 int rc = send(fd, buf, n, 0);
189
190 if (rc == SOCKET_ERROR) { set_socket_errno(WSAGetLastError()); }
191
192 return(rc);
193 }
194
win32_read_socket(SOCKET fd,void * buf,int n)195 ssize_t win32_read_socket(SOCKET fd, void *buf, int n) {
196 int rc = recv(fd, buf, n, 0);
197
198 if (rc == SOCKET_ERROR) { set_socket_errno(WSAGetLastError()); }
199
200 return(rc);
201 }
202
203
win32_strtok_r(char * s,const char * delim,char ** lasts)204 char * win32_strtok_r(char *s, const char *delim, char **lasts) {
205 register char *spanp;
206 register int c, sc;
207 char *tok;
208
209
210 if (s == NULL && (s = *lasts) == NULL) { return (NULL); }
211
212 // skip (span) leading delimiters (s += strspn(s, delim), sort of).
213 cont:
214 c = *s++;
215
216 for (spanp = (char *)delim; (sc = *spanp++) != 0;)
217 if (c == sc) { goto cont; }
218
219
220 if (c == 0) { // no non-delimiter characters
221 *lasts = NULL;
222 return (NULL);
223 }
224
225 tok = s - 1;
226
227 /* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
228 * Note that delim must have one NUL; we stop if we see that, too.
229 */
230 for ( ; ;) {
231 c = *s++;
232 spanp = (char *)delim;
233
234 do {
235 if ((sc = *spanp++) == c) {
236 if (c == 0) {
237 s = NULL;
238 } else {
239 s[-1] = 0;
240 }
241
242 *lasts = s;
243 return(tok);
244 }
245
246 } while (sc != 0);
247 }
248
249 // NOT REACHED
250 }
251
win32_strsep(char ** stringp,const char * delim)252 char *win32_strsep (char **stringp, const char *delim) {
253 register char *s;
254 register const char *spanp;
255 register int c, sc;
256 char *tok;
257
258 if ((s = *stringp) == NULL) {
259 return(NULL);
260 }
261
262 for (tok = s; ;) {
263 c = *s++;
264 spanp = delim;
265
266 do {
267 if ((sc = *spanp++) == c) {
268 if (c == 0) {
269 s = NULL;
270 } else {
271 s[-1] = 0;
272 }
273
274 *stringp = s;
275 return(tok);
276 }
277
278 } while (sc != 0);
279 }
280
281 // NOT REACHED
282 }
283
284 #ifndef STLINK_HAVE_UNISTD_H
usleep(unsigned int waitTime)285 int usleep(unsigned int waitTime) {
286 if (waitTime >= 1000) {
287 /* Don't do long busy-waits.
288 * However much it seems like the QPC code would be more accurate,
289 * you can and probably will lose your time slice at any point during the wait,
290 * so we might as well voluntarily give up the CPU with a WaitForSingleObject.
291 */
292 HANDLE timer;
293 LARGE_INTEGER dueTime;
294 dueTime.QuadPart = -10 * (LONGLONG)waitTime;
295 timer = CreateWaitableTimer(NULL, TRUE, NULL);
296 SetWaitableTimer(timer, &dueTime, 0, NULL, NULL, 0);
297 WaitForSingleObject(timer, INFINITE);
298 CloseHandle(timer);
299
300 return(0);
301 }
302
303 LARGE_INTEGER perf_cnt, start, now;
304
305 QueryPerformanceFrequency(&perf_cnt);
306 QueryPerformanceCounter(&start);
307
308 do {
309 QueryPerformanceCounter((LARGE_INTEGER*)&now);
310 } while ((now.QuadPart - start.QuadPart) / (float)perf_cnt.QuadPart * 1000 * 1000 < waitTime);
311
312 return(0);
313 }
314 #endif
315
316 #endif // defined(_WIN32)
317