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