lib/server.c: fix ipv6 support
[platform/upstream/libwebsockets.git] / lib / lws-plat-win.c
1 #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
2 #define _WINSOCK_DEPRECATED_NO_WARNINGS
3 #endif
4 #include "private-libwebsockets.h"
5
6 unsigned long long
7 time_in_microseconds()
8 {
9 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
10         FILETIME filetime;
11         ULARGE_INTEGER datetime;
12
13 #ifdef _WIN32_WCE
14         GetCurrentFT(&filetime);
15 #else
16         GetSystemTimeAsFileTime(&filetime);
17 #endif
18
19         /*
20          * As per Windows documentation for FILETIME, copy the resulting FILETIME structure to a
21          * ULARGE_INTEGER structure using memcpy (using memcpy instead of direct assignment can
22          * prevent alignment faults on 64-bit Windows).
23          */
24         memcpy(&datetime, &filetime, sizeof(datetime));
25
26         /* Windows file times are in 100s of nanoseconds. */
27         return (datetime.QuadPart - DELTA_EPOCH_IN_MICROSECS) / 10;
28 }
29
30 #ifdef _WIN32_WCE
31 time_t time(time_t *t)
32 {
33         time_t ret = time_in_microseconds() / 1000000;
34         *t = ret;
35         return ret;
36 }
37 #endif
38
39 /* file descriptor hash management */
40
41 struct lws *
42 wsi_from_fd(const struct lws_context *context, lws_sockfd_type fd)
43 {
44         int h = LWS_FD_HASH(fd);
45         int n = 0;
46
47         for (n = 0; n < context->fd_hashtable[h].length; n++)
48                 if (context->fd_hashtable[h].wsi[n]->sock == fd)
49                         return context->fd_hashtable[h].wsi[n];
50
51         return NULL;
52 }
53
54 int
55 insert_wsi(struct lws_context *context, struct lws *wsi)
56 {
57         int h = LWS_FD_HASH(wsi->sock);
58
59         if (context->fd_hashtable[h].length == (getdtablesize() - 1)) {
60                 lwsl_err("hash table overflow\n");
61                 return 1;
62         }
63
64         context->fd_hashtable[h].wsi[context->fd_hashtable[h].length++] = wsi;
65
66         return 0;
67 }
68
69 int
70 delete_from_fd(struct lws_context *context, lws_sockfd_type fd)
71 {
72         int h = LWS_FD_HASH(fd);
73         int n = 0;
74
75         for (n = 0; n < context->fd_hashtable[h].length; n++)
76                 if (context->fd_hashtable[h].wsi[n]->sock == fd) {
77                         while (n < context->fd_hashtable[h].length) {
78                                 context->fd_hashtable[h].wsi[n] =
79                                             context->fd_hashtable[h].wsi[n + 1];
80                                 n++;
81                         }
82                         context->fd_hashtable[h].length--;
83
84                         return 0;
85                 }
86
87         lwsl_err("Failed to find fd %d requested for "
88                  "delete in hashtable\n", fd);
89         return 1;
90 }
91
92 LWS_VISIBLE int lws_get_random(struct lws_context *context,
93                                                              void *buf, int len)
94 {
95         int n;
96         char *p = (char *)buf;
97
98         for (n = 0; n < len; n++)
99                 p[n] = (unsigned char)rand();
100
101         return n;
102 }
103
104 LWS_VISIBLE int lws_send_pipe_choked(struct lws *wsi)
105 {
106         return (int)wsi->sock_send_blocking;
107 }
108
109 LWS_VISIBLE int lws_poll_listen_fd(struct lws_pollfd *fd)
110 {
111         fd_set readfds;
112         struct timeval tv = { 0, 0 };
113
114         assert((fd->events & LWS_POLLIN) == LWS_POLLIN);
115
116         FD_ZERO(&readfds);
117         FD_SET(fd->fd, &readfds);
118
119         return select(fd->fd + 1, &readfds, NULL, NULL, &tv);
120 }
121
122 /**
123  * lws_cancel_service() - Cancel servicing of pending websocket activity
124  * @context:    Websocket context
125  *
126  *      This function let a call to lws_service() waiting for a timeout
127  *      immediately return.
128  */
129 LWS_VISIBLE void
130 lws_cancel_service(struct lws_context *context)
131 {
132         struct lws_context_per_thread *pt = &context->pt[0];
133         int n = context->count_threads;
134
135         while (n--) {
136                 WSASetEvent(pt->events[0]);
137                 pt++;
138         }
139 }
140
141 LWS_VISIBLE void
142 lws_cancel_service_pt(struct lws *wsi)
143 {
144         struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
145         WSASetEvent(pt->events[0]);
146 }
147
148 LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line)
149 {
150         lwsl_emit_stderr(level, line);
151 }
152
153 LWS_VISIBLE int
154 lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
155 {
156         struct lws_context_per_thread *pt = &context->pt[tsi];
157         WSANETWORKEVENTS networkevents;
158         struct lws_pollfd *pfd;
159         struct lws *wsi;
160         unsigned int i;
161         DWORD ev;
162         int n, m;
163
164         /* stay dead once we are dead */
165         if (context == NULL)
166                 return 1;
167
168         if (!context->service_tid_detected) {
169                 struct lws _lws;
170
171                 memset(&_lws, 0, sizeof(_lws));
172                 _lws.context = context;
173
174                 context->service_tid_detected = context->vhost_list->
175                         protocols[0].callback(&_lws, LWS_CALLBACK_GET_THREAD_ID,
176                                               NULL, NULL, 0);
177         }
178         context->service_tid = context->service_tid_detected;
179
180         if (timeout_ms < 0)
181                 goto faked_service;
182
183         for (i = 0; i < pt->fds_count; ++i) {
184                 pfd = &pt->fds[i];
185
186                 if (!(pfd->events & LWS_POLLOUT))
187                         continue;
188
189                 wsi = wsi_from_fd(context, pfd->fd);
190                 if (wsi->listener)
191                         continue;
192                 if (!wsi || wsi->sock_send_blocking)
193                         continue;
194                 pfd->revents = LWS_POLLOUT;
195                 n = lws_service_fd(context, pfd);
196                 if (n < 0)
197                         return -1;
198                 /* if something closed, retry this slot */
199                 if (n)
200                         i--;
201         }
202
203         /* if we know something needs service already, don't wait in poll */
204         timeout_ms = lws_service_adjust_timeout(context, timeout_ms, tsi);
205
206         ev = WSAWaitForMultipleEvents(pt->fds_count + 1, pt->events,
207                                       FALSE, timeout_ms, FALSE);
208         context->service_tid = 0;
209
210         if (ev == WSA_WAIT_TIMEOUT) {
211                 lws_service_fd(context, NULL);
212                 return 0;
213         }
214
215         if (ev == WSA_WAIT_EVENT_0) {
216                 WSAResetEvent(pt->events[0]);
217                 return 0;
218         }
219
220         if (ev < WSA_WAIT_EVENT_0 || ev > WSA_WAIT_EVENT_0 + pt->fds_count)
221                 return -1;
222
223         pfd = &pt->fds[ev - WSA_WAIT_EVENT_0 - 1];
224
225         /* eh... is one event at a time the best windows can do? */
226
227         if (WSAEnumNetworkEvents(pfd->fd, pt->events[ev - WSA_WAIT_EVENT_0],
228                                  &networkevents) == SOCKET_ERROR) {
229                 lwsl_err("WSAEnumNetworkEvents() failed with error %d\n",
230                                                                      LWS_ERRNO);
231                 return -1;
232         }
233
234         pfd->revents = (short)networkevents.lNetworkEvents;
235
236         if (pfd->revents & LWS_POLLOUT) {
237                 wsi = wsi_from_fd(context, pfd->fd);
238                 if (wsi)
239                         wsi->sock_send_blocking = 0;
240         }
241
242 faked_service:
243
244         /* if someone faked their LWS_POLLIN, then go through all active fds */
245
246         if (lws_service_flag_pending(context, tsi)) {
247                 /* any socket with events to service? */
248                 for (n = 0; n < (int)pt->fds_count; n++) {
249                         if (!pt->fds[n].revents)
250                                 continue;
251
252                         m = lws_service_fd_tsi(context, &pt->fds[n], tsi);
253                         if (m < 0)
254                                 return -1;
255                         /* if something closed, retry this slot */
256                         if (m)
257                                 n--;
258                 }
259                 return 0;
260         }
261
262         if (timeout_ms < 0)
263                 return 0;
264
265         /* otherwise just do the one... must be a way to improve that... */
266
267         return lws_service_fd_tsi(context, pfd, tsi);
268 }
269
270 LWS_VISIBLE int
271 lws_plat_service(struct lws_context *context, int timeout_ms)
272 {
273         return lws_plat_service_tsi(context, timeout_ms, 0);
274 }
275
276 LWS_VISIBLE int
277 lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd)
278 {
279         int optval = 1;
280         int optlen = sizeof(optval);
281         u_long optl = 1;
282         DWORD dwBytesRet;
283         struct tcp_keepalive alive;
284         int protonbr;
285 #ifndef _WIN32_WCE
286         struct protoent *tcp_proto;
287 #endif
288
289         if (vhost->ka_time) {
290                 /* enable keepalive on this socket */
291                 optval = 1;
292                 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
293                                              (const char *)&optval, optlen) < 0)
294                         return 1;
295
296                 alive.onoff = TRUE;
297                 alive.keepalivetime = vhost->ka_time;
298                 alive.keepaliveinterval = vhost->ka_interval;
299
300                 if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
301                                               NULL, 0, &dwBytesRet, NULL, NULL))
302                         return 1;
303         }
304
305         /* Disable Nagle */
306         optval = 1;
307 #ifndef _WIN32_WCE
308         tcp_proto = getprotobyname("TCP");
309         if (!tcp_proto) {
310                 lwsl_err("getprotobyname() failed with error %d\n", LWS_ERRNO);
311                 return 1;
312         }
313         protonbr = tcp_proto->p_proto;
314 #else
315         protonbr = 6;
316 #endif
317
318         setsockopt(fd, protonbr, TCP_NODELAY, (const char *)&optval, optlen);
319
320         /* We are nonblocking... */
321         ioctlsocket(fd, FIONBIO, &optl);
322
323         return 0;
324 }
325
326 LWS_VISIBLE void
327 lws_plat_drop_app_privileges(struct lws_context_creation_info *info)
328 {
329 }
330
331 LWS_VISIBLE int
332 lws_plat_context_early_init(void)
333 {
334         WORD wVersionRequested;
335         WSADATA wsaData;
336         int err;
337
338         /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */
339         wVersionRequested = MAKEWORD(2, 2);
340
341         err = WSAStartup(wVersionRequested, &wsaData);
342         if (!err)
343                 return 0;
344         /*
345          * Tell the user that we could not find a usable
346          * Winsock DLL
347          */
348         lwsl_err("WSAStartup failed with error: %d\n", err);
349
350         return 1;
351 }
352
353 LWS_VISIBLE void
354 lws_plat_context_early_destroy(struct lws_context *context)
355 {
356         struct lws_context_per_thread *pt = &context->pt[0];
357         int n = context->count_threads;
358
359         while (n--) {
360                 if (pt->events) {
361                         WSACloseEvent(pt->events[0]);
362                         lws_free(pt->events);
363                 }
364                 pt++;
365         }
366 }
367
368 LWS_VISIBLE void
369 lws_plat_context_late_destroy(struct lws_context *context)
370 {
371         int n;
372
373         for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
374                 if (context->fd_hashtable[n].wsi)
375                         lws_free(context->fd_hashtable[n].wsi);
376         }
377
378         WSACleanup();
379 }
380
381 LWS_VISIBLE LWS_EXTERN int
382 lws_interface_to_sa(int ipv6,
383                 const char *ifname, struct sockaddr_in *addr, size_t addrlen)
384 {
385         long long address = inet_addr(ifname);
386
387         if (address == INADDR_NONE) {
388                 struct hostent *entry = gethostbyname(ifname);
389                 if (entry)
390                         address = ((struct in_addr *)entry->h_addr_list[0])->s_addr;
391         }
392
393         if (address == INADDR_NONE)
394                 return -1;
395
396         addr->sin_addr.s_addr = (unsigned long)address;
397
398         return 0;
399 }
400
401 LWS_VISIBLE void
402 lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
403 {
404         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
405
406         pt->fds[pt->fds_count++].revents = 0;
407         pt->events[pt->fds_count] = WSACreateEvent();
408         WSAEventSelect(wsi->sock, pt->events[pt->fds_count],
409                        LWS_POLLIN | LWS_POLLHUP);
410 }
411
412 LWS_VISIBLE void
413 lws_plat_delete_socket_from_fds(struct lws_context *context,
414                                                 struct lws *wsi, int m)
415 {
416         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
417
418         WSACloseEvent(pt->events[m + 1]);
419         pt->events[m + 1] = pt->events[pt->fds_count--];
420 }
421
422 LWS_VISIBLE void
423 lws_plat_service_periodic(struct lws_context *context)
424 {
425 }
426
427 LWS_VISIBLE int
428 lws_plat_change_pollfd(struct lws_context *context,
429                       struct lws *wsi, struct lws_pollfd *pfd)
430 {
431         struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
432         long networkevents = LWS_POLLHUP;
433
434         if ((pfd->events & LWS_POLLIN))
435                 networkevents |= LWS_POLLIN;
436
437         if ((pfd->events & LWS_POLLOUT))
438                 networkevents |= LWS_POLLOUT;
439
440         if (WSAEventSelect(wsi->sock,
441                         pt->events[wsi->position_in_fds_table + 1],
442                                                networkevents) != SOCKET_ERROR)
443                 return 0;
444
445         lwsl_err("WSAEventSelect() failed with error %d\n", LWS_ERRNO);
446
447         return 1;
448 }
449
450 LWS_VISIBLE const char *
451 lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
452 {
453         WCHAR *buffer;
454         DWORD bufferlen = cnt;
455         BOOL ok = FALSE;
456
457         buffer = lws_malloc(bufferlen);
458         if (!buffer) {
459                 lwsl_err("Out of memory\n");
460                 return NULL;
461         }
462
463         if (af == AF_INET) {
464                 struct sockaddr_in srcaddr;
465                 bzero(&srcaddr, sizeof(srcaddr));
466                 srcaddr.sin_family = AF_INET;
467                 memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr));
468
469                 if (!WSAAddressToStringW((struct sockaddr*)&srcaddr, sizeof(srcaddr), 0, buffer, &bufferlen))
470                         ok = TRUE;
471 #ifdef LWS_USE_IPV6
472         } else if (af == AF_INET6) {
473                 struct sockaddr_in6 srcaddr;
474                 bzero(&srcaddr, sizeof(srcaddr));
475                 srcaddr.sin6_family = AF_INET6;
476                 memcpy(&(srcaddr.sin6_addr), src, sizeof(srcaddr.sin6_addr));
477
478                 if (!WSAAddressToStringW((struct sockaddr*)&srcaddr, sizeof(srcaddr), 0, buffer, &bufferlen))
479                         ok = TRUE;
480 #endif
481         } else
482                 lwsl_err("Unsupported type\n");
483
484         if (!ok) {
485                 int rv = WSAGetLastError();
486                 lwsl_err("WSAAddressToString() : %d\n", rv);
487         } else {
488                 if (WideCharToMultiByte(CP_ACP, 0, buffer, bufferlen, dst, cnt, 0, NULL) <= 0)
489                         ok = FALSE;
490         }
491
492         lws_free(buffer);
493         return ok ? dst : NULL;
494 }
495
496 static lws_filefd_type
497 _lws_plat_file_open(struct lws *wsi, const char *filename,
498                     unsigned long *filelen, int flags)
499 {
500         HANDLE ret;
501         WCHAR buf[MAX_PATH];
502
503         (void)wsi;
504         MultiByteToWideChar(CP_UTF8, 0, filename, -1, buf, ARRAY_SIZE(buf));
505         if ((flags & 7) == _O_RDONLY) {
506                 ret = CreateFileW(buf, GENERIC_READ, FILE_SHARE_READ,
507                           NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
508         } else {
509                 lwsl_err("%s: open for write not implemented\n", __func__);
510                 *filelen = 0;
511                 return LWS_INVALID_FILE;
512         }
513
514         if (ret != LWS_INVALID_FILE)
515                 *filelen = GetFileSize(ret, NULL);
516
517         return ret;
518 }
519
520 static int
521 _lws_plat_file_close(struct lws *wsi, lws_filefd_type fd)
522 {
523         (void)wsi;
524
525         CloseHandle((HANDLE)fd);
526
527         return 0;
528 }
529
530 static unsigned long
531 _lws_plat_file_seek_cur(struct lws *wsi, lws_filefd_type fd, long offset)
532 {
533         (void)wsi;
534
535         return SetFilePointer((HANDLE)fd, offset, NULL, FILE_CURRENT);
536 }
537
538 static int
539 _lws_plat_file_read(struct lws *wsi, lws_filefd_type fd, unsigned long *amount,
540                     unsigned char* buf, unsigned long len)
541 {
542         DWORD _amount;
543
544         if (!ReadFile((HANDLE)fd, buf, (DWORD)len, &_amount, NULL)) {
545                 *amount = 0;
546
547                 return 1;
548         }
549
550         *amount = (unsigned long)_amount;
551
552         return 0;
553 }
554
555 static int
556 _lws_plat_file_write(struct lws *wsi, lws_filefd_type fd, unsigned long *amount,
557                      unsigned char* buf, unsigned long len)
558 {
559         (void)wsi;
560         (void)fd;
561         (void)amount;
562         (void)buf;
563         (void)len;
564
565         lwsl_err("%s: not implemented yet on this platform\n", __func__);
566
567         return -1;
568 }
569
570 LWS_VISIBLE int
571 lws_plat_init(struct lws_context *context,
572               struct lws_context_creation_info *info)
573 {
574         struct lws_context_per_thread *pt = &context->pt[0];
575         int i, n = context->count_threads;
576
577         for (i = 0; i < FD_HASHTABLE_MODULUS; i++) {
578                 context->fd_hashtable[i].wsi =
579                         lws_zalloc(sizeof(struct lws*) * context->max_fds);
580
581                 if (!context->fd_hashtable[i].wsi)
582                         return -1;
583         }
584
585         while (n--) {
586                 pt->events = lws_malloc(sizeof(WSAEVENT) *
587                                         (context->fd_limit_per_thread + 1));
588                 if (pt->events == NULL) {
589                         lwsl_err("Unable to allocate events array for %d connections\n",
590                                         context->fd_limit_per_thread + 1);
591                         return 1;
592                 }
593
594                 pt->fds_count = 0;
595                 pt->events[0] = WSACreateEvent();
596
597                 pt++;
598         }
599
600         context->fd_random = 0;
601
602         context->fops.open      = _lws_plat_file_open;
603         context->fops.close     = _lws_plat_file_close;
604         context->fops.seek_cur  = _lws_plat_file_seek_cur;
605         context->fops.read      = _lws_plat_file_read;
606         context->fops.write     = _lws_plat_file_write;
607
608         return 0;
609 }