diff --git a/lib/client-handshake.c b/lib/client-handshake.c index 1ff5721e..329492b0 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -119,7 +119,7 @@ struct libwebsocket *libwebsocket_client_connect_2( goto oom4; } - if (lws_set_socket_options(context, wsi->sock)) { + if (lws_plat_set_socket_options(context, wsi->sock)) { lwsl_err("Failed to set wsi socket options\n"); compatible_close(wsi->sock); goto oom4; @@ -186,7 +186,8 @@ struct libwebsocket *libwebsocket_client_connect_2( * must do specifically a POLLOUT poll to hear * about the connect completion */ - lws_change_pollfd(wsi, 0, LWS_POLLOUT); + if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) + goto oom4; return wsi; } diff --git a/lib/client.c b/lib/client.c index 6cc7515c..0705949f 100644 --- a/lib/client.c +++ b/lib/client.c @@ -118,7 +118,8 @@ int lws_client_socket_service(struct libwebsocket_context *context, * happening at a time when there's no real connection yet */ - lws_change_pollfd(wsi, LWS_POLLOUT, 0); + if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) + return -1; /* we can retry this... just cook the SSL BIO the first time */ diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index 0c94db53..ba85dd2c 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 Andy Green + * Copyright (C) 2010-2014 Andy Green * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -87,7 +87,15 @@ static const char * const log_level_names[] = { struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd); #endif - +/* + * This is just used to interrupt poll waiting + * we don't have to do anything with it. + */ +#ifdef LWS_OPENSSL_SUPPORT +static void lws_sigusr2(int sig) +{ +} +#endif #if defined(WIN32) || defined(_WIN32) #include "lws-plat-win.c" @@ -140,16 +148,8 @@ insert_wsi_socket_into_fds(struct libwebsocket_context *context, wsi->position_in_fds_table = context->fds_count; context->fds[context->fds_count].fd = wsi->sock; context->fds[context->fds_count].events = LWS_POLLIN; -#ifdef LWS_USE_LIBEV - if (context && context->io_loop && LWS_LIBEV_ENABLED(context)) - ev_io_start(context->io_loop, (struct ev_io *)&wsi->w_read); - -#endif /* LWS_USE_LIBEV */ - context->fds[context->fds_count++].revents = 0; -#ifdef _WIN32 - context->events[context->fds_count] = WSACreateEvent(); - WSAEventSelect(wsi->sock, context->events[context->fds_count], LWS_POLLIN); -#endif + + lws_plat_insert_socket_into_fds(context, wsi); /* external POLL support via protocol 0 */ context->protocols[0].callback(context, wsi, @@ -168,7 +168,7 @@ remove_wsi_socket_from_fds(struct libwebsocket_context *context, struct libwebsocket *wsi) { int m; - struct libwebsocket_pollargs pa = { wsi->sock, 0, 0}; + struct libwebsocket_pollargs pa = { wsi->sock, 0, 0 }; #ifdef LWS_USE_LIBEV if (LWS_LIBEV_ENABLED(context)) { @@ -201,10 +201,9 @@ remove_wsi_socket_from_fds(struct libwebsocket_context *context, /* have the last guy take up the vacant slot */ context->fds[m] = context->fds[context->fds_count]; -#ifdef _WIN32 - WSACloseEvent(context->events[m + 1]); - context->events[m + 1] = context->events[context->fds_count + 1]; -#endif + + lws_plat_delete_socket_from_fds(context, wsi, m); + /* * end guy's fds_lookup entry remains unchanged * (still same fd pointing to same wsi) @@ -270,7 +269,6 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context, goto just_kill_connection; } - if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) { if (wsi->u.http.post_buffer) { free(wsi->u.http.post_buffer); @@ -278,11 +276,7 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context, } if (wsi->u.http.fd != LWS_INVALID_FILE) { lwsl_debug("closing http file\n"); -#if defined(WIN32) || defined(_WIN32) - CloseHandle(wsi->u.http.fd); -#else - close(wsi->u.http.fd); -#endif + compatible_file_close(wsi->u.http.fd); wsi->u.http.fd = LWS_INVALID_FILE; context->protocols[0].callback(context, wsi, LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0); @@ -309,7 +303,6 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context, * up to the extension to track the attempted close, let's * just bail */ - if (m) { lwsl_ext("extension vetoed close\n"); return; @@ -451,7 +444,7 @@ just_kill_connection: lwsl_debug("calling back CLOSED\n"); wsi->protocol->callback(context, wsi, LWS_CALLBACK_CLOSED, wsi->user_space, NULL, 0); - } else if ( wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED ) { + } else if (wsi->mode == LWS_CONNMODE_HTTP_SERVING_ACCEPTED) { lwsl_debug("calling back CLOSED_HTTP\n"); context->protocols[0].callback(context, wsi, LWS_CALLBACK_CLOSED_HTTP, wsi->user_space, NULL, 0 ); @@ -615,22 +608,22 @@ libwebsockets_get_peer_addresses(struct libwebsocket_context *context, if (p == NULL) continue; if ((host1->h_addrtype != AF_INET) - #ifdef AF_LOCAL +#ifdef AF_LOCAL && (host1->h_addrtype != AF_LOCAL) - #endif +#endif ) continue; if (host1->h_addrtype == AF_INET) sprintf(ip, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]); - #ifdef AF_LOCAL +#ifdef AF_LOCAL else { un = (struct sockaddr_un *)p; strncpy(ip, un->sun_path, sizeof(ip) - 1); ip[sizeof(ip) - 1] = '\0'; } - #endif +#endif p = NULL; strncpy(rip, ip, rip_len); rip[rip_len - 1] = '\0'; @@ -642,80 +635,6 @@ bail: lws_latency(context, wsi, "libwebsockets_get_peer_addresses", ret, 1); } -int lws_set_socket_options(struct libwebsocket_context *context, int fd) -{ - int optval = 1; - socklen_t optlen = sizeof(optval); -#if defined(WIN32) || defined(_WIN32) - u_long optl = 1; -#endif -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) - struct protoent *tcp_proto; -#endif - - if (context->ka_time) { - /* enable keepalive on this socket */ - optval = 1; - if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, - (const void *)&optval, optlen) < 0) - return 1; - -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__CYGWIN__) - - /* - * didn't find a way to set these per-socket, need to - * tune kernel systemwide values - */ -#elif WIN32 - { - DWORD dwBytesRet; - struct tcp_keepalive alive; - alive.onoff = TRUE; - alive.keepalivetime = context->ka_time; - alive.keepaliveinterval = context->ka_interval; - - if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), - NULL, 0, &dwBytesRet, NULL, NULL)) - return 1; - } -#else - /* set the keepalive conditions we want on it too */ - optval = context->ka_time; - if (setsockopt(fd, IPPROTO_IP, TCP_KEEPIDLE, - (const void *)&optval, optlen) < 0) - return 1; - - optval = context->ka_interval; - if (setsockopt(fd, IPPROTO_IP, TCP_KEEPINTVL, - (const void *)&optval, optlen) < 0) - return 1; - - optval = context->ka_probes; - if (setsockopt(fd, IPPROTO_IP, TCP_KEEPCNT, - (const void *)&optval, optlen) < 0) - return 1; -#endif - } - - /* Disable Nagle */ - optval = 1; -#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__) - setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen); -#else - tcp_proto = getprotobyname("TCP"); - setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen); -#endif - - /* We are nonblocking... */ -#if defined(WIN32) || defined(_WIN32) - ioctlsocket(fd, FIONBIO, &optl); -#else - fcntl(fd, F_SETFL, O_NONBLOCK); -#endif - - return 0; -} - int lws_handle_POLLOUT_event(struct libwebsocket_context *context, struct libwebsocket *wsi, struct libwebsocket_pollfd *pollfd) @@ -846,7 +765,8 @@ user_service: /* one shot */ if (pollfd) { - lws_change_pollfd(wsi, LWS_POLLOUT, 0); + if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) + return 1; #ifdef LWS_USE_LIBEV if (LWS_LIBEV_ENABLED(context)) ev_io_stop(context->io_loop, @@ -886,8 +806,8 @@ libwebsocket_service_timeout_check(struct libwebsocket_context *context, context, wsi->active_extensions[n], wsi, LWS_EXT_CALLBACK_1HZ, wsi->active_extensions_user[n], NULL, sec); - #endif + if (!wsi->pending_timeout) return 0; @@ -963,12 +883,7 @@ libwebsocket_service_fd(struct libwebsocket_context *context, if (context->last_timeout_check_s != now) { context->last_timeout_check_s = now; -#ifndef WIN32 - /* if our parent went down, don't linger around */ - if (context->started_with_parent && - kill(context->started_with_parent, 0) < 0) - kill(getpid(), SIGTERM); -#endif + lws_plat_service_periodic(context); /* global timeout check once per second */ @@ -1287,17 +1202,7 @@ libwebsocket_context_destroy(struct libwebsocket_context *context) protocol++; } - -#if defined(WIN32) || defined(_WIN32) - if (context->events) { - WSACloseEvent(context->events[0]); - free(context->events); - } -#else - close(context->dummy_pipe_fds[0]); - close(context->dummy_pipe_fds[1]); - close(context->fd_random); -#endif + lws_plat_context_early_destroy(context); #ifdef LWS_OPENSSL_SUPPORT if (context->ssl_ctx) @@ -1318,9 +1223,7 @@ libwebsocket_context_destroy(struct libwebsocket_context *context) free(context); -#if defined(WIN32) || defined(_WIN32) - WSACleanup(); -#endif + lws_plat_context_late_destroy(context); } /** @@ -1373,118 +1276,10 @@ libwebsocket_context_user(struct libwebsocket_context *context) LWS_VISIBLE int libwebsocket_service(struct libwebsocket_context *context, int timeout_ms) { - int n; -#ifdef _WIN32 - int i; - DWORD ev; - WSANETWORKEVENTS networkevents; - struct libwebsocket_pollfd *pfd; -#else - int m; - char buf; -#endif - - /* stay dead once we are dead */ - - if (context == NULL) - return 1; - -#ifdef LWS_USE_LIBEV - if (context->io_loop && LWS_LIBEV_ENABLED(context)) - ev_run(context->io_loop, 0); -#endif /* LWS_USE_LIBEV */ - context->service_tid = context->protocols[0].callback(context, NULL, - LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); - -#ifdef _WIN32 - for (i = 0; i < context->fds_count; ++i) { - pfd = &context->fds[i]; - if (pfd->fd == context->listen_service_fd) - continue; - if (pfd->events & LWS_POLLOUT) { - if (context->lws_lookup[pfd->fd]->sock_send_blocking) - continue; - pfd->revents = LWS_POLLOUT; - n = libwebsocket_service_fd(context, pfd); - if (n < 0) - return n; - } - } - - ev = WSAWaitForMultipleEvents(context->fds_count + 1, - context->events, FALSE, timeout_ms, FALSE); - context->service_tid = 0; - - if (ev == WSA_WAIT_TIMEOUT) { - libwebsocket_service_fd(context, NULL); - return 0; - } - - if (ev == WSA_WAIT_EVENT_0) { - WSAResetEvent(context->events[0]); - return 0; - } - - if (ev < WSA_WAIT_EVENT_0 || ev > WSA_WAIT_EVENT_0 + context->fds_count) - return -1; - - pfd = &context->fds[ev - WSA_WAIT_EVENT_0 - 1]; - - if (WSAEnumNetworkEvents(pfd->fd, context->events[ev - WSA_WAIT_EVENT_0], - &networkevents) == SOCKET_ERROR) { - lwsl_err("WSAEnumNetworkEvents() failed with error %d\n", LWS_ERRNO); - return -1; - } - - pfd->revents = networkevents.lNetworkEvents; - - if (pfd->revents & LWS_POLLOUT) - context->lws_lookup[pfd->fd]->sock_send_blocking = FALSE; - - return libwebsocket_service_fd(context, pfd); -#else - n = poll(context->fds, context->fds_count, timeout_ms); - context->service_tid = 0; - - if (n == 0) /* poll timeout */ { - libwebsocket_service_fd(context, NULL); - return 0; - } - - if (n < 0) { - if (LWS_ERRNO != LWS_EINTR) - return -1; - else - return 0; - } - - /* any socket with events to service? */ - - for (n = 0; n < context->fds_count; n++) { - if (!context->fds[n].revents) - continue; - - if (context->fds[n].fd == context->dummy_pipe_fds[0]) { - if (read(context->fds[n].fd, &buf, 1) != 1) - lwsl_err("Cannot read from dummy pipe."); - continue; - } - - m = libwebsocket_service_fd(context, &context->fds[n]); - if (m < 0) - return -1; - /* if something closed, retry this slot */ - if (m) - n--; - } - - return 0; -#endif + return lws_plat_service(context, timeout_ms); } - - #ifndef LWS_NO_EXTENSIONS int lws_any_extension_handled(struct libwebsocket_context *context, @@ -1531,7 +1326,7 @@ lws_get_extension_user_matching_ext(struct libwebsocket *wsi, } #endif -void +int lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or) { struct libwebsocket_context *context = wsi->protocol->owning_server; @@ -1539,9 +1334,6 @@ lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or) int sampled_tid; struct libwebsocket_pollfd *pfd; struct libwebsocket_pollargs pa; -#ifdef _WIN32 - long networkevents = LWS_POLLOUT | LWS_POLLHUP; -#endif pfd = &context->fds[wsi->position_in_fds_table]; pa.fd = wsi->sock; @@ -1551,7 +1343,6 @@ lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or) wsi->user_space, (void *) &pa, 0); pa.prev_events = pfd->events; - pa.events = pfd->events = (pfd->events & ~_and) | _or; context->protocols[0].callback(context, wsi, @@ -1566,17 +1357,9 @@ lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or) * then cancel it to force a restart with our changed events */ if (pa.prev_events != pa.events) { -#ifdef _WIN32 - if ((pfd->events & LWS_POLLIN)) - networkevents |= LWS_POLLIN; - - if (WSAEventSelect(wsi->sock, - context->events[wsi->position_in_fds_table + 1], - networkevents) == SOCKET_ERROR) { - lwsl_err("WSAEventSelect() failed with error %d\n", - LWS_ERRNO); - } -#endif + + if (lws_plat_change_pollfd(context, wsi, pfd)) + return 1; sampled_tid = context->service_tid; if (sampled_tid) { @@ -1590,6 +1373,8 @@ lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or) context->protocols[0].callback(context, wsi, LWS_CALLBACK_UNLOCK_POLL, wsi->user_space, (void *) &pa, 0); + + return 0; } @@ -1630,7 +1415,9 @@ libwebsocket_callback_on_writable(struct libwebsocket_context *context, return -1; } - lws_change_pollfd(wsi, 0, LWS_POLLOUT); + if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) + return -1; + #ifdef LWS_USE_LIBEV if (LWS_LIBEV_ENABLED(context)) ev_io_start(context->io_loop, (struct ev_io *)&wsi->w_write); @@ -1805,10 +1592,12 @@ _libwebsocket_rx_flow_control(struct libwebsocket *wsi) /* adjust the pollfd for this wsi */ - if (wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW) - lws_change_pollfd(wsi, 0, LWS_POLLIN); - else - lws_change_pollfd(wsi, LWS_POLLIN, 0); + if (wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW) { + if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) + return -1; + } else + if (lws_change_pollfd(wsi, LWS_POLLIN, 0)) + return -1; return 1; } @@ -1880,11 +1669,6 @@ libwebsocket_canonical_hostname(struct libwebsocket_context *context) return (const char *)context->canonical_hostname; } - -static void sigpipe_handler(int x) -{ -} - #ifdef LWS_OPENSSL_SUPPORT static int OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) @@ -1933,16 +1717,6 @@ int user_callback_handle_rxflow(callback_function callback_function, return n; } -/* - * This is just used to interrupt poll waiting - * we don't have to do anything with it. - */ -#ifdef LWS_OPENSSL_SUPPORT -static void lws_sigusr2(int sig) -{ -} -#endif - /** * libwebsocket_create_context() - Create the websocket handler * @info: pointer to struct with parameters @@ -2034,26 +1808,8 @@ libwebsocket_create_context(struct lws_context_creation_info *info) lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH); lwsl_info(" LWS_MAX_ZLIB_CONN_BUFFER: %u\n", LWS_MAX_ZLIB_CONN_BUFFER); -#ifdef _WIN32 - { - WORD wVersionRequested; - WSADATA wsaData; - int err; - - /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */ - wVersionRequested = MAKEWORD(2, 2); - - err = WSAStartup(wVersionRequested, &wsaData); - if (err) { - /* - * Tell the user that we could not find a usable - * Winsock DLL - */ - lwsl_err("WSAStartup failed with error: %d\n", err); - return NULL; - } - } -#endif + if (lws_plat_context_early_init()) + return NULL; context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context)); @@ -2096,13 +1852,6 @@ libwebsocket_create_context(struct lws_context_creation_info *info) return NULL; } -#ifdef LWS_USE_LIBEV - if (LWS_LIBEV_ENABLED(context)) { - context->w_accept.context = context; - context->w_sigint.context = context; - } -#endif /* LWS_USE_LIBEV */ - context->lws_lookup = (struct libwebsocket **) malloc(sizeof(struct libwebsocket *) * context->max_fds); if (context->lws_lookup == NULL) { @@ -2116,39 +1865,12 @@ libwebsocket_create_context(struct lws_context_creation_info *info) memset(context->lws_lookup, 0, sizeof(struct libwebsocket *) * context->max_fds); -#ifdef _WIN32 - context->events = (WSAEVENT *)malloc(sizeof(WSAEVENT) * - (context->max_fds + 1)); - if (context->events == NULL) { - lwsl_err("Unable to allocate events array for %d connections\n", - context->max_fds); + if (lws_plat_init_fd_tables(context)) { free(context->lws_lookup); free(context->fds); free(context); return NULL; } -#endif - - if (!LWS_LIBEV_ENABLED(context)) { - #ifdef _WIN32 - context->fds_count = 0; - context->events[0] = WSACreateEvent(); - #else - if (pipe(context->dummy_pipe_fds)) { - lwsl_err("Unable to create pipe\n"); - free(context->lws_lookup); - free(context->fds); - free(context); - return NULL; - } - - /* use the read end of pipe as first item */ - context->fds[0].fd = context->dummy_pipe_fds[0]; - context->fds[0].events = LWS_POLLIN; - context->fds[0].revents = 0; - context->fds_count = 1; - #endif - } #ifndef LWS_NO_EXTENSIONS context->extensions = info->extensions; @@ -2156,17 +1878,6 @@ libwebsocket_create_context(struct lws_context_creation_info *info) context->last_timeout_check_s = 0; context->user_space = info->user; -#if defined(WIN32) || defined(_WIN32) - context->fd_random = 0; -#else - context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY); - if (context->fd_random < 0) { - lwsl_err("Unable to open random device %s %d\n", - SYSTEM_RANDOM_FILEPATH, context->fd_random); - goto bail; - } -#endif - #ifdef LWS_OPENSSL_SUPPORT context->use_ssl = 0; context->allow_non_ssl_on_ssl_port = 0; @@ -2254,13 +1965,6 @@ libwebsocket_create_context(struct lws_context_creation_info *info) } #endif - /* ignore SIGPIPE */ -#if defined(WIN32) || defined(_WIN32) -#else - signal(SIGPIPE, sigpipe_handler); -#endif - - #ifdef LWS_OPENSSL_SUPPORT /* basic openssl init */ @@ -2297,18 +2001,6 @@ libwebsocket_create_context(struct lws_context_creation_info *info) goto bail; } -#if defined(WIN32) || defined(_WIN32) -#else - signal(SIGUSR2, lws_sigusr2); - { - sigset_t mask; - sigemptyset (&mask); - sigaddset (&mask, SIGUSR2); - - sigprocmask(SIG_BLOCK, &mask, NULL); - } -#endif - #ifdef SSL_OP_NO_COMPRESSION SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION); #endif @@ -2512,7 +2204,7 @@ libwebsocket_create_context(struct lws_context_creation_info *info) setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt)); - lws_set_socket_options(context, sockfd); + lws_plat_set_socket_options(context, sockfd); #ifdef LWS_USE_IPV6 if (LWS_IPV6_ENABLED(context)) { @@ -2588,15 +2280,7 @@ libwebsocket_create_context(struct lws_context_creation_info *info) * to listen on port < 1023 we would have needed root, but now we are * listening, we don't want the power for anything else */ -#if defined(WIN32) || defined(_WIN32) -#else - if (info->gid != -1) - if (setgid(info->gid)) - lwsl_warn("setgid: %s\n", strerror(LWS_ERRNO)); - if (info->uid != -1) - if (setuid(info->uid)) - lwsl_warn("setuid: %s\n", strerror(LWS_ERRNO)); -#endif + lws_plat_drop_app_privileges(info); /* initialize supported protocols */ @@ -2796,69 +2480,4 @@ LWS_VISIBLE void lws_set_log_level(int level, void (*log_emit_function)(int leve log_level = level; if (log_emit_function) lwsl_emit = log_emit_function; -} - -/* cast a struct sockaddr_in6 * into addr for ipv6 */ - -int -interface_to_sa(struct libwebsocket_context *context, - const char *ifname, struct sockaddr_in *addr, size_t addrlen) -{ - int rc = -1; -#if defined(WIN32) || defined(_WIN32) - /* TODO */ -#else - struct ifaddrs *ifr; - struct ifaddrs *ifc; -#ifdef LWS_USE_IPV6 - struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; -#endif - - getifaddrs(&ifr); - for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) { - if (!ifc->ifa_addr) - continue; - - lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname); - - if (strcmp(ifc->ifa_name, ifname)) - continue; - - switch (ifc->ifa_addr->sa_family) { - case AF_INET: -#ifdef LWS_USE_IPV6 - if (LWS_IPV6_ENABLED(context)) { - /* map IPv4 to IPv6 */ - bzero((char *)&addr6->sin6_addr, - sizeof(struct in6_addr)); - addr6->sin6_addr.s6_addr[10] = 0xff; - addr6->sin6_addr.s6_addr[11] = 0xff; - memcpy(&addr6->sin6_addr.s6_addr[12], - &((struct sockaddr_in *)ifc->ifa_addr)->sin_addr, - sizeof(struct in_addr)); - } else -#endif - memcpy(addr, - (struct sockaddr_in *)ifc->ifa_addr, - sizeof(struct sockaddr_in)); - break; -#ifdef LWS_USE_IPV6 - case AF_INET6: - if (rc >= 0) - break; - memcpy(&addr6->sin6_addr, - &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr, - sizeof(struct in6_addr)); - break; -#endif - default: - continue; - } - rc = 0; - } - - freeifaddrs(ifr); -#endif - return rc; -} - +} \ No newline at end of file diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index f517f369..51f12a6f 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -26,6 +26,10 @@ extern "C" { #include #endif + +#ifdef CMAKE_BUILD +#include "lws_config.h" +#endif #if defined(WIN32) || defined(_WIN32) @@ -74,6 +78,13 @@ extern "C" { #ifndef LWS_EXTERN #define LWS_EXTERN extern #endif + +#ifdef _WIN32 +#define random rand +#else +#include +#include +#endif #define CONTEXT_PORT_NO_LISTEN -1 #define MAX_MUX_RECURSION 2 diff --git a/lib/lws-plat-unix.c b/lib/lws-plat-unix.c index ebfc551f..70b73c54 100644 --- a/lib/lws-plat-unix.c +++ b/lib/lws-plat-unix.c @@ -166,4 +166,291 @@ LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line) break; } syslog(syslog_level, "%s", line); +} + +LWS_VISIBLE int +lws_plat_service(struct libwebsocket_context *context, int timeout_ms) +{ + int n; + int m; + char buf; + + /* stay dead once we are dead */ + + if (context == NULL) + return 1; + +#ifdef LWS_USE_LIBEV + if (context->io_loop && LWS_LIBEV_ENABLED(context)) + ev_run(context->io_loop, 0); +#endif /* LWS_USE_LIBEV */ + context->service_tid = context->protocols[0].callback(context, NULL, + LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); + + n = poll(context->fds, context->fds_count, timeout_ms); + context->service_tid = 0; + + if (n == 0) /* poll timeout */ { + libwebsocket_service_fd(context, NULL); + return 0; + } + + if (n < 0) { + if (LWS_ERRNO != LWS_EINTR) + return -1; + return 0; + } + + /* any socket with events to service? */ + + for (n = 0; n < context->fds_count; n++) { + if (!context->fds[n].revents) + continue; + + if (context->fds[n].fd == context->dummy_pipe_fds[0]) { + if (read(context->fds[n].fd, &buf, 1) != 1) + lwsl_err("Cannot read from dummy pipe."); + continue; + } + + m = libwebsocket_service_fd(context, &context->fds[n]); + if (m < 0) + return -1; + /* if something closed, retry this slot */ + if (m) + n--; + } + + return 0; +} + +int lws_plat_set_socket_options(struct libwebsocket_context *context, int fd) +{ + int optval = 1; + socklen_t optlen = sizeof(optval); + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) + struct protoent *tcp_proto; +#endif + + if (context->ka_time) { + /* enable keepalive on this socket */ + optval = 1; + if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, + (const void *)&optval, optlen) < 0) + return 1; + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__CYGWIN__) + + /* + * didn't find a way to set these per-socket, need to + * tune kernel systemwide values + */ +#else + /* set the keepalive conditions we want on it too */ + optval = context->ka_time; + if (setsockopt(fd, IPPROTO_IP, TCP_KEEPIDLE, + (const void *)&optval, optlen) < 0) + return 1; + + optval = context->ka_interval; + if (setsockopt(fd, IPPROTO_IP, TCP_KEEPINTVL, + (const void *)&optval, optlen) < 0) + return 1; + + optval = context->ka_probes; + if (setsockopt(fd, IPPROTO_IP, TCP_KEEPCNT, + (const void *)&optval, optlen) < 0) + return 1; +#endif + } + + /* Disable Nagle */ + optval = 1; +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__) + setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen); +#else + tcp_proto = getprotobyname("TCP"); + setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen); +#endif + + /* We are nonblocking... */ + fcntl(fd, F_SETFL, O_NONBLOCK); + + return 0; +} + +static void lws_plat_drop_app_privileges(struct lws_context_creation_info *info) +{ + if (info->gid != -1) + if (setgid(info->gid)) + lwsl_warn("setgid: %s\n", strerror(LWS_ERRNO)); + if (info->uid != -1) + if (setuid(info->uid)) + lwsl_warn("setuid: %s\n", strerror(LWS_ERRNO)); +} + +static int lws_plat_init_fd_tables(struct libwebsocket_context *context) +{ +#ifdef LWS_USE_LIBEV + if (LWS_LIBEV_ENABLED(context)) { + context->w_accept.context = context; + context->w_sigint.context = context; + return 0; + } +#endif + if (pipe(context->dummy_pipe_fds)) { + lwsl_err("Unable to create pipe\n"); + return 1; + } + + /* use the read end of pipe as first item */ + context->fds[0].fd = context->dummy_pipe_fds[0]; + context->fds[0].events = LWS_POLLIN; + context->fds[0].revents = 0; + context->fds_count = 1; + + context->fd_random = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY); + if (context->fd_random < 0) { + lwsl_err("Unable to open random device %s %d\n", + SYSTEM_RANDOM_FILEPATH, context->fd_random); + return 1; + } + + return 0; +} + +static void sigpipe_handler(int x) +{ +} + + +static int lws_plat_context_early_init(void) +{ + sigset_t mask; + + signal(SIGUSR2, lws_sigusr2); + sigemptyset(&mask); + sigaddset(&mask, SIGUSR2); + + sigprocmask(SIG_BLOCK, &mask, NULL); + + signal(SIGPIPE, sigpipe_handler); + + return 0; +} + +static void lws_plat_context_early_destroy(struct libwebsocket_context *context) +{ +} + +static void lws_plat_context_late_destroy(struct libwebsocket_context *context) +{ + close(context->dummy_pipe_fds[0]); + close(context->dummy_pipe_fds[1]); + close(context->fd_random); +} + +/* cast a struct sockaddr_in6 * into addr for ipv6 */ + +int +interface_to_sa(struct libwebsocket_context *context, + const char *ifname, struct sockaddr_in *addr, size_t addrlen) +{ + int rc = -1; + + struct ifaddrs *ifr; + struct ifaddrs *ifc; +#ifdef LWS_USE_IPV6 + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; +#endif + + getifaddrs(&ifr); + for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) { + if (!ifc->ifa_addr) + continue; + + lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname); + + if (strcmp(ifc->ifa_name, ifname)) + continue; + + switch (ifc->ifa_addr->sa_family) { + case AF_INET: +#ifdef LWS_USE_IPV6 + if (LWS_IPV6_ENABLED(context)) { + /* map IPv4 to IPv6 */ + bzero((char *)&addr6->sin6_addr, + sizeof(struct in6_addr)); + addr6->sin6_addr.s6_addr[10] = 0xff; + addr6->sin6_addr.s6_addr[11] = 0xff; + memcpy(&addr6->sin6_addr.s6_addr[12], + &((struct sockaddr_in *)ifc->ifa_addr)->sin_addr, + sizeof(struct in_addr)); + } else +#endif + memcpy(addr, + (struct sockaddr_in *)ifc->ifa_addr, + sizeof(struct sockaddr_in)); + break; +#ifdef LWS_USE_IPV6 + case AF_INET6: + if (rc >= 0) + break; + memcpy(&addr6->sin6_addr, + &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr, + sizeof(struct in6_addr)); + break; +#endif + default: + continue; + } + rc = 0; + } + + freeifaddrs(ifr); + + return rc; +} + +void lws_plat_insert_socket_into_fds(struct libwebsocket_context *context, + struct libwebsocket *wsi) +{ +#ifdef LWS_USE_LIBEV + if (context && context->io_loop && LWS_LIBEV_ENABLED(context)) + ev_io_start(context->io_loop, (struct ev_io *)&wsi->w_read); +#endif /* LWS_USE_LIBEV */ + context->fds[context->fds_count++].revents = 0; +} + +void lws_plat_delete_socket_from_fds(struct libwebsocket_context *context, + struct libwebsocket *wsi, int m) +{ +} + +static void lws_plat_service_periodic(struct libwebsocket_context *context) +{ + /* if our parent went down, don't linger around */ + if (context->started_with_parent && + kill(context->started_with_parent, 0) < 0) + kill(getpid(), SIGTERM); +} + +static int lws_plat_change_pollfd(struct libwebsocket_context *context, + struct libwebsocket *wsi, struct libwebsocket_pollfd *pfd) +{ + return 0; +} + +int lws_plat_open_file(const char* filename, unsigned long* filelen) +{ + struct stat stat_buf; + int ret = open(filename, O_RDONLY); + + if (ret < 0) + return LWS_INVALID_FILE; + + fstat(ret, &stat_buf); + *filelen = stat_buf.st_size; + return ret; } \ No newline at end of file diff --git a/lib/lws-plat-win.c b/lib/lws-plat-win.c index 97bced60..2ec4e3cc 100644 --- a/lib/lws-plat-win.c +++ b/lib/lws-plat-win.c @@ -78,3 +78,221 @@ LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line) { lwsl_emit_stderr(level, line); } + +LWS_VISIBLE int +lws_plat_service(struct libwebsocket_context *context, int timeout_ms) +{ + int n; + int i; + DWORD ev; + WSANETWORKEVENTS networkevents; + struct libwebsocket_pollfd *pfd; + + /* stay dead once we are dead */ + + if (context == NULL) + return 1; + + context->service_tid = context->protocols[0].callback(context, NULL, + LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); + + for (i = 0; i < context->fds_count; ++i) { + pfd = &context->fds[i]; + if (pfd->fd == context->listen_service_fd) + continue; + + if (pfd->events & LWS_POLLOUT) { + if (context->lws_lookup[pfd->fd]->sock_send_blocking) + continue; + pfd->revents = LWS_POLLOUT; + n = libwebsocket_service_fd(context, pfd); + if (n < 0) + return n; + } + } + + ev = WSAWaitForMultipleEvents(context->fds_count + 1, + context->events, FALSE, timeout_ms, FALSE); + context->service_tid = 0; + + if (ev == WSA_WAIT_TIMEOUT) { + libwebsocket_service_fd(context, NULL); + return 0; + } + + if (ev == WSA_WAIT_EVENT_0) { + WSAResetEvent(context->events[0]); + return 0; + } + + if (ev < WSA_WAIT_EVENT_0 || ev > WSA_WAIT_EVENT_0 + context->fds_count) + return -1; + + pfd = &context->fds[ev - WSA_WAIT_EVENT_0 - 1]; + + if (WSAEnumNetworkEvents(pfd->fd, + context->events[ev - WSA_WAIT_EVENT_0], + &networkevents) == SOCKET_ERROR) { + lwsl_err("WSAEnumNetworkEvents() failed with error %d\n", + LWS_ERRNO); + return -1; + } + + pfd->revents = networkevents.lNetworkEvents; + + if (pfd->revents & LWS_POLLOUT) + context->lws_lookup[pfd->fd]->sock_send_blocking = FALSE; + + return libwebsocket_service_fd(context, pfd); +} + +int lws_plat_set_socket_options(struct libwebsocket_context *context, int fd) +{ + int optval = 1; + socklen_t optlen = sizeof(optval); + u_long optl = 1; + DWORD dwBytesRet; + struct tcp_keepalive alive; + + if (context->ka_time) { + /* enable keepalive on this socket */ + optval = 1; + if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, + (const void *)&optval, optlen) < 0) + return 1; + + alive.onoff = TRUE; + alive.keepalivetime = context->ka_time; + alive.keepaliveinterval = context->ka_interval; + + if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive), + NULL, 0, &dwBytesRet, NULL, NULL)) + return 1; + } + + /* Disable Nagle */ + optval = 1; + tcp_proto = getprotobyname("TCP"); + setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen); + + /* We are nonblocking... */ + ioctlsocket(fd, FIONBIO, &optl); + + return 0; +} + +static void lws_plat_drop_app_privileges(struct lws_context_creation_info *info) +{ +} + +static int lws_plat_init_fd_tables(struct libwebsocket_context *context) +{ + context->events = (WSAEVENT *)malloc(sizeof(WSAEVENT) * + (context->max_fds + 1)); + if (context->events == NULL) { + lwsl_err("Unable to allocate events array for %d connections\n", + context->max_fds); + return 1; + } + + context->fds_count = 0; + context->events[0] = WSACreateEvent(); + + context->fd_random = 0; + + return 0; +} + +static int lws_plat_context_early_init(void) +{ + WORD wVersionRequested; + WSADATA wsaData; + int err; + + /* Use the MAKEWORD(lowbyte, highbyte) macro from Windef.h */ + wVersionRequested = MAKEWORD(2, 2); + + err = WSAStartup(wVersionRequested, &wsaData); + if (!err) + return 0; + /* + * Tell the user that we could not find a usable + * Winsock DLL + */ + lwsl_err("WSAStartup failed with error: %d\n", err); + + return 1; +} + +static void lws_plat_context_early_destroy(struct libwebsocket_context *context) +{ + if (context->events) { + WSACloseEvent(context->events[0]); + free(context->events); + } +} + +static void lws_plat_context_late_destroy(struct libwebsocket_context *context) +{ + WSACleanup(); +} + +int +interface_to_sa(struct libwebsocket_context *context, + const char *ifname, struct sockaddr_in *addr, size_t addrlen) +{ + return -1; +} + +void lws_plat_insert_socket_into_fds(struct libwebsocket_context *context, + struct libwebsocket *wsi) +{ + context->fds[context->fds_count++].revents = 0; + context->events[context->fds_count] = WSACreateEvent(); + WSAEventSelect(wsi->sock, context->events[context->fds_count], LWS_POLLIN); +} + +static void lws_plat_delete_socket_from_fds(struct libwebsocket_context *context, + struct libwebsocket *wsi, int m) +{ + WSACloseEvent(context->events[m + 1]); + context->events[m + 1] = context->events[context->fds_count + 1]; +} + +static void lws_plat_service_periodic(struct libwebsocket_context *context) +{ +} + +static int lws_plat_change_pollfd(struct libwebsocket_context *context, + struct libwebsocket *wsi, struct libwebsocket_pollfd *pfd) +{ + long networkevents = LWS_POLLOUT | LWS_POLLHUP; + + if ((pfd->events & LWS_POLLIN)) + networkevents |= LWS_POLLIN; + + if (WSAEventSelect(wsi->sock, + context->events[wsi->position_in_fds_table + 1], + networkevents) != SOCKET_ERROR) + return 0; + + lwsl_err("WSAEventSelect() failed with error %d\n", LWS_ERRNO); + + return 1; +} + +HANDLE lws_plat_open_file(const char* filename, unsigned long* filelen) +{ + HANDLE ret; + WCHAR buffer[MAX_PATH]; + + MultiByteToWideChar(CP_UTF8, 0, filename, -1, buffer, + sizeof(buffer) / sizeof(buffer[0])); + ret = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (ret != LWS_INVALID_FILE) + *filelen = GetFileSize(ret, NULL); + + return ret; +} \ No newline at end of file diff --git a/lib/output.c b/lib/output.c index afc93ae6..c73e917d 100644 --- a/lib/output.c +++ b/lib/output.c @@ -86,13 +86,6 @@ LWS_VISIBLE void lwsl_hexdump(void *vbuf, size_t len) #endif -static void lws_set_blocking_send(struct libwebsocket *wsi) -{ -#ifdef _WIN32 - wsi->sock_send_blocking = TRUE; -#endif -} - /* * notice this returns number of bytes consumed, or -1 */ @@ -102,7 +95,6 @@ int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len) struct libwebsocket_context *context = wsi->protocol->owning_server; int n; size_t real_len = len; - #ifndef LWS_NO_EXTENSIONS int m; #endif @@ -150,19 +142,6 @@ int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len) /* * nope, send it on the socket directly */ - -#if 0 - lwsl_debug(" TX: "); - lws_hexdump(buf, len); -#endif - -#if 0 - /* test partial send support by forcing multiple sends on everything */ - len = len / 2; - if (!len) - len = 1; -#endif - lws_latency_pre(context, wsi); #ifdef LWS_OPENSSL_SUPPORT if (wsi->ssl) { @@ -186,8 +165,9 @@ int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len) n = send(wsi->sock, buf, len, MSG_NOSIGNAL); lws_latency(context, wsi, "send lws_issue_raw", n, n == len); if (n < 0) { - if (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK - || LWS_ERRNO == LWS_EINTR) { + if (LWS_ERRNO == LWS_EAGAIN || + LWS_ERRNO == LWS_EWOULDBLOCK || + LWS_ERRNO == LWS_EINTR) { if (LWS_ERRNO == LWS_EWOULDBLOCK) lws_set_blocking_send(wsi); n = 0; @@ -201,7 +181,6 @@ int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len) #endif handle_truncated_send: - /* * already handling a truncated send? */ @@ -604,12 +583,6 @@ do_more_inside_frame: } send_raw: - -#if 0 - lwsl_debug("send %ld: ", len + pre + post); - lwsl_hexdump(&buf[-pre], len + pre + post); -#endif - switch (protocol) { case LWS_WRITE_CLOSE: /* lwsl_hexdump(&buf[-pre], len + post); */ @@ -666,11 +639,7 @@ send_raw: LWS_VISIBLE int libwebsockets_serve_http_file_fragment( struct libwebsocket_context *context, struct libwebsocket *wsi) { -#if defined(WIN32) || defined(_WIN32) - DWORD n; -#else int n; -#endif int m; while (!lws_send_pipe_choked(wsi)) { @@ -685,17 +654,10 @@ LWS_VISIBLE int libwebsockets_serve_http_file_fragment( if (wsi->u.http.filepos == wsi->u.http.filelen) goto all_sent; -#if defined(WIN32) || defined(_WIN32) - if (!ReadFile(wsi->u.http.fd, context->service_buffer, - sizeof(context->service_buffer), &n, NULL)) - return -1; /* caller will close */ -#else - n = read(wsi->u.http.fd, context->service_buffer, + compatible_file_read(n, wsi->u.http.fd, context->service_buffer, sizeof(context->service_buffer)); - if (n < 0) return -1; /* caller will close */ -#endif if (n) { m = libwebsocket_write(wsi, context->service_buffer, n, LWS_WRITE_HTTP); @@ -703,15 +665,9 @@ LWS_VISIBLE int libwebsockets_serve_http_file_fragment( return -1; wsi->u.http.filepos += m; - if (m != n) { + if (m != n) /* adjust for what was not sent */ -#if defined(WIN32) || defined(_WIN32) - SetFilePointer(wsi->u.http.fd, m - n, - NULL, FILE_CURRENT); -#else - lseek(wsi->u.http.fd, m - n, SEEK_CUR); -#endif - } + compatible_file_seek_cur(wsi->u.http.fd, m - n); } all_sent: if (!wsi->truncated_send_len && diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 5918cc83..1d46ac51 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -25,8 +25,17 @@ #else #if defined(WIN32) || defined(_WIN32) #define inline __inline +#include #else #include "config.h" +#ifdef LWS_BUILTIN_GETIFADDRS +#include +#else +#include +#endif +#include +#include +#include #endif #endif @@ -58,11 +67,21 @@ #define SHUT_RDWR SD_BOTH #define SOL_TCP IPPROTO_TCP -#define compatible_close(fd) closesocket(fd); +#define compatible_close(fd) closesocket(fd) +#define compatible_file_close(fd) CloseHandle(fd) +#define compatible_file_seek_cur(fd, offset) SetFilePointer(fd, offset, FILE_CURRENT) +#define compatible_file_read(amount, fd, buf, len) {\ + DWORD _amount; \ + if (!ReadFile(fd, buf, len, &amount, NULL)) \ + amount = -1; \ + else \ + amount = _amount; \ + } +#define lws_set_blocking_send(wsi) wsi->sock_send_blocking = TRUE #include #include #define LWS_INVALID_FILE INVALID_HANDLE_VALUE -#else +#else /* not windows --> */ #include #include #include @@ -98,7 +117,12 @@ #define LWS_POLLHUP (POLLHUP|POLLERR) #define LWS_POLLIN (POLLIN) #define LWS_POLLOUT (POLLOUT) -#define compatible_close(fd) close(fd); +#define compatible_close(fd) close(fd) +#define compatible_file_close(fd) close(fd) +#define compatible_file_seek_cur(fd, offset) lseek(fd, offset, SEEK_CUR) +#define compatible_file_read(amount, fd, buf, len) \ + amount = read(fd, buf, len); +#define lws_set_blocking_send(wsi) #endif #ifndef HAVE_BZERO @@ -126,6 +150,54 @@ SHA1(const unsigned char *d, size_t n, unsigned char *md); #include "libwebsockets.h" +#if defined(WIN32) || defined(_WIN32) + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 /* to show byte order (taken from gcc) */ +#endif +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif +typedef unsigned __int64 u_int64_t; + +#undef __P +#ifndef __P +#if __STDC__ +#define __P(protos) protos +#else +#define __P(protos) () +#endif +#endif + +#else + +#include +#include +#include + +#if defined(__APPLE__) +#include +#elif defined(__FreeBSD__) +#include +#elif defined(__linux__) +#include +#endif + +#if !defined(BYTE_ORDER) +# define BYTE_ORDER __BYTE_ORDER +#endif +#if !defined(LITTLE_ENDIAN) +# define LITTLE_ENDIAN __LITTLE_ENDIAN +#endif +#if !defined(BIG_ENDIAN) +# define BIG_ENDIAN __BIG_ENDIAN +#endif + +#endif + /* * Mac OSX as well as iOS do not define the MSG_NOSIGNAL flag, * but happily have something equivalent in the SO_NOSIGPIPE flag. @@ -594,7 +666,7 @@ user_callback_handle_rxflow(callback_function, void *in, size_t len); LWS_EXTERN int -lws_set_socket_options(struct libwebsocket_context *context, int fd); +lws_plat_set_socket_options(struct libwebsocket_context *context, int fd); LWS_EXTERN int lws_allocate_header_table(struct libwebsocket *wsi); @@ -609,7 +681,7 @@ lws_hdr_simple_create(struct libwebsocket *wsi, LWS_EXTERN int libwebsocket_ensure_user_space(struct libwebsocket *wsi); -LWS_EXTERN void +LWS_EXTERN int lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or); #ifndef LWS_NO_SERVER @@ -624,6 +696,12 @@ LWS_EXTERN int get_daemonize_pid(); extern int interface_to_sa(struct libwebsocket_context *context, const char *ifname, struct sockaddr_in *addr, size_t addrlen); +#ifdef _WIN32 +LWS_EXTERN HANDLE lws_plat_open_file(const char* filename, unsigned long* filelen); +#else +LWS_EXTERN int lws_plat_open_file(const char* filename, unsigned long* filelen); +#endif + #ifndef LWS_OPENSSL_SUPPORT unsigned char * diff --git a/lib/server.c b/lib/server.c index 1a310ad3..14031b28 100644 --- a/lib/server.c +++ b/lib/server.c @@ -22,19 +22,6 @@ #include "private-libwebsockets.h" -#if defined(WIN32) || defined(_WIN32) -#include -#else -#ifdef LWS_BUILTIN_GETIFADDRS -#include -#else -#include -#endif -#include -#include -#include -#endif - #ifdef LWS_OPENSSL_SUPPORT static void @@ -187,7 +174,8 @@ int lws_server_socket_service(struct libwebsocket_context *context, break; /* one shot */ - lws_change_pollfd(wsi, LWS_POLLOUT, 0); + if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) + goto fail; #ifdef LWS_USE_LIBEV if (LWS_LIBEV_ENABLED(context)) ev_io_stop(context->io_loop, @@ -239,7 +227,7 @@ int lws_server_socket_service(struct libwebsocket_context *context, break; } - lws_set_socket_options(context, accept_fd); + lws_plat_set_socket_options(context, accept_fd); /* * look at who we connected to and give user code a chance @@ -357,7 +345,8 @@ int lws_server_socket_service(struct libwebsocket_context *context, case LWS_CONNMODE_SSL_ACK_PENDING: - lws_change_pollfd(wsi, LWS_POLLOUT, 0); + if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) + goto fail; #ifdef LWS_USE_LIBEV if (LWS_LIBEV_ENABLED(context)) ev_io_stop(context->io_loop, @@ -406,7 +395,8 @@ int lws_server_socket_service(struct libwebsocket_context *context, m, ERR_error_string(m, NULL)); if (m == SSL_ERROR_WANT_READ) { - lws_change_pollfd(wsi, 0, LWS_POLLIN); + if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) + goto fail; #ifdef LWS_USE_LIBEV if (LWS_LIBEV_ENABLED(context)) ev_io_start(context->io_loop, @@ -416,7 +406,8 @@ int lws_server_socket_service(struct libwebsocket_context *context, break; } if (m == SSL_ERROR_WANT_WRITE) { - lws_change_pollfd(wsi, 0, LWS_POLLOUT); + if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) + goto fail; #ifdef LWS_USE_LIBEV if (LWS_LIBEV_ENABLED(context)) ev_io_start(context->io_loop, @@ -448,6 +439,11 @@ accepted: break; } return 0; + +fail: + libwebsocket_close_and_free_session(context, wsi, + LWS_CLOSE_STATUS_NOSTATUS); + return 1; } @@ -520,37 +516,6 @@ LWS_VISIBLE int libwebsockets_return_http_status( return m; } -#if defined(WIN32) || defined(_WIN32) -static inline HANDLE lws_open_file(const char* filename, unsigned long* filelen) -{ - HANDLE ret; - WCHAR buffer[MAX_PATH]; - - MultiByteToWideChar(CP_UTF8, 0, filename, -1, buffer, - sizeof(buffer) / sizeof(buffer[0])); - ret = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (ret != LWS_INVALID_FILE) - *filelen = GetFileSize(ret, NULL); - - return ret; -} -#else -static inline int lws_open_file(const char* filename, unsigned long* filelen) -{ - struct stat stat_buf; - int ret = open(filename, O_RDONLY); - - if (ret < 0) - return LWS_INVALID_FILE; - - fstat(ret, &stat_buf); - *filelen = stat_buf.st_size; - return ret; -} -#endif - /** * libwebsockets_serve_http_file() - Send a file back to the client using http * @context: libwebsockets context @@ -578,7 +543,7 @@ LWS_VISIBLE int libwebsockets_serve_http_file( int ret = 0; int n; - wsi->u.http.fd = lws_open_file(file, &wsi->u.http.filelen); + wsi->u.http.fd = lws_plat_open_file(file, &wsi->u.http.filelen); if (wsi->u.http.fd == LWS_INVALID_FILE) { lwsl_err("Unable to open '%s'\n", file); diff --git a/lib/sha-1.c b/lib/sha-1.c index 8b4ccb43..98b208b2 100644 --- a/lib/sha-1.c +++ b/lib/sha-1.c @@ -38,57 +38,6 @@ #include #endif -#if defined(WIN32) || defined(_WIN32) - -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 /* to show byte order (taken from gcc) */ -#endif -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif -#ifndef BYTE_ORDER -#define BYTE_ORDER LITTLE_ENDIAN -#endif - -typedef unsigned __int64 u_int64_t; - -#undef __P -#ifndef __P -#if __STDC__ -#define __P(protos) protos -#else -#define __P(protos) () -#endif -#endif - -#else - -#include -#include -#include - -#if defined(__APPLE__) -#include -#elif defined(__FreeBSD__) -#include -#elif defined(__linux__) -#include -#endif - -#if !defined(BYTE_ORDER) -# define BYTE_ORDER __BYTE_ORDER -#endif -#if !defined(LITTLE_ENDIAN) -# define LITTLE_ENDIAN __LITTLE_ENDIAN -#endif -#if !defined(BIG_ENDIAN) -# define BIG_ENDIAN __BIG_ENDIAN -#endif - -#endif - -#include - struct sha1_ctxt { union { unsigned char b8[20]; diff --git a/test-server/test-fraggle.c b/test-server/test-fraggle.c index c2529df4..f2ea1e01 100644 --- a/test-server/test-fraggle.c +++ b/test-server/test-fraggle.c @@ -23,18 +23,6 @@ #include #include #include - -#ifdef _WIN32 -#define random rand -#else -#include -#include -#endif - -#ifdef CMAKE_BUILD -#include "lws_config.h" -#endif - #include "../lib/libwebsockets.h" #define LOCAL_RESOURCE_PATH INSTALL_DATADIR"/libwebsockets-test-server"