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