int main(int argc, char **argv) { struct lws_context_creation_info info; char *cs; int opts = 0, cs_len = LWSWS_CONFIG_STRING_SIZE - 1; int n = 0; #ifndef _WIN32 int syslog_options = LOG_PID | LOG_PERROR; #endif #ifndef LWS_NO_DAEMONIZE int daemonize = 0; #endif int debug_level = 7; char *config_dir = "/etc/lwsws/conf.d"; char *config_strings; memset(&info, 0, sizeof info); while (n >= 0) { n = getopt_long(argc, argv, "hd:c:D", options, NULL); if (n < 0) continue; switch (n) { #ifndef LWS_NO_DAEMONIZE case 'D': daemonize = 1; #ifndef _WIN32 syslog_options &= ~LOG_PERROR; #endif printf("Daemonizing...\n"); break; #endif case 'd': debug_level = atoi(optarg); break; case 'c': strncpy(config_dir, optarg, sizeof(config_dir) - 1); config_dir[sizeof(config_dir) - 1] = '\0'; break; case 'h': fprintf(stderr, "Usage: lwsws [-c <config dir>] " "[-d <log bitfield>] [-D] [--help]\n"); exit(1); } } #if !defined(LWS_NO_DAEMONIZE) && !defined(WIN32) /* * normally lock path would be /var/lock/lwsts or similar, to * simplify getting started without having to take care about * permissions or running as root, set to /tmp/.lwsts-lock */ if (daemonize && lws_daemonize("/tmp/.lwsts-lock")) { fprintf(stderr, "Failed to daemonize\n"); return 10; } if (daemonize) lwsl_notice("Daemonized\n"); #endif #ifndef _WIN32 /* we will only try to log things according to our debug_level */ setlogmask(LOG_UPTO (LOG_DEBUG)); openlog("lwsws", syslog_options, LOG_DAEMON); #endif lws_set_log_level(debug_level, lwsl_emit_syslog); lwsl_notice("lwsws libwebsockets web server - license GPL2.1\n"); lwsl_notice("(C) Copyright 2010-2016 Andy Green <*****@*****.**>\n"); cs = config_strings = malloc(LWSWS_CONFIG_STRING_SIZE); if (!config_strings) { lwsl_err("Unable to allocate config strings heap\n"); return -1; } memset(&info, 0, sizeof(info)); info.max_http_header_pool = 16; info.options = opts | LWS_SERVER_OPTION_VALIDATE_UTF8 | LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_LIBUV; info.plugin_dirs = plugin_dirs; lwsl_notice("Using config dir: \"%s\"\n", config_dir); /* * first go through the config for creating the outer context */ if (lwsws_get_config_globals(&info, config_dir, &cs, &cs_len)) goto init_failed; context = lws_create_context(&info); if (context == NULL) { lwsl_err("libwebsocket init failed\n"); goto init_failed; } /* * then create the vhosts... protocols are entirely coming from * plugins, so we leave it NULL */ info.extensions = exts; if (!lwsws_get_config_vhosts(context, &info, config_dir, &cs, &cs_len)) { /* run the server */ lws_uv_sigint_cfg(context, 1, signal_cb); lws_uv_initloop(context, NULL, 0); lws_libuv_run(context, 0); } lws_context_destroy(context); free(config_strings); fprintf(stderr, "lwsws exited cleanly\n"); #ifndef _WIN32 closelog(); #endif return 0; init_failed: free(config_strings); return 1; }
LWS_VISIBLE LWS_EXTERN int _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; int n = -1, m, c; char buf; /* stay dead once we are dead */ if (!context || !context->vhost_list) return 1; if (timeout_ms < 0) goto faked_service; lws_libev_run(context, tsi); lws_libuv_run(context, tsi); if (!context->service_tid_detected) { struct lws _lws; memset(&_lws, 0, sizeof(_lws)); _lws.context = context; context->service_tid_detected = context->vhost_list->protocols[0].callback( &_lws, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); } context->service_tid = context->service_tid_detected; /* * is there anybody with pending stuff that needs service forcing? */ if (!lws_service_adjust_timeout(context, 1, tsi)) { /* -1 timeout means just do forced service */ _lws_plat_service_tsi(context, -1, pt->tid); /* still somebody left who wants forced service? */ if (!lws_service_adjust_timeout(context, 1, pt->tid)) /* yes... come back again quickly */ timeout_ms = 0; } n = poll(pt->fds, pt->fds_count, timeout_ms); #ifdef LWS_OPENSSL_SUPPORT if (!pt->rx_draining_ext_list && !lws_ssl_anybody_has_buffered_read_tsi(context, tsi) && !n) { #else if (!pt->rx_draining_ext_list && !n) /* poll timeout */ { #endif lws_service_fd_tsi(context, NULL, tsi); return 0; } faked_service: m = lws_service_flag_pending(context, tsi); if (m) c = -1; /* unknown limit */ else if (n < 0) { if (LWS_ERRNO != LWS_EINTR) return -1; return 0; } else c = n; /* any socket with events to service? */ for (n = 0; n < pt->fds_count && c; n++) { if (!pt->fds[n].revents) continue; c--; if (pt->fds[n].fd == pt->dummy_pipe_fds[0]) { if (read(pt->fds[n].fd, &buf, 1) != 1) lwsl_err("Cannot read from dummy pipe."); continue; } m = lws_service_fd_tsi(context, &pt->fds[n], tsi); if (m < 0) return -1; /* if something closed, retry this slot */ if (m) n--; } return 0; } LWS_VISIBLE int lws_plat_check_connection_error(struct lws *wsi) { return 0; } LWS_VISIBLE int lws_plat_service(struct lws_context *context, int timeout_ms) { return _lws_plat_service_tsi(context, timeout_ms, 0); } LWS_VISIBLE int lws_plat_set_socket_options(struct lws_vhost *vhost, int fd) { int optval = 1; socklen_t optlen = sizeof(optval); #if defined(__APPLE__) || \ defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ defined(__NetBSD__) || \ defined(__OpenBSD__) struct protoent *tcp_proto; #endif if (vhost->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(__FreeBSD_kernel__) || \ defined(__NetBSD__) || \ defined(__CYGWIN__) || defined(__OpenBSD__) || defined (__sun) /* * 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 = vhost->ka_time; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (const void *)&optval, optlen) < 0) return 1; optval = vhost->ka_interval; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (const void *)&optval, optlen) < 0) return 1; optval = vhost->ka_probes; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, (const void *)&optval, optlen) < 0) return 1; #endif } /* Disable Nagle */ optval = 1; #if defined (__sun) if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const void *)&optval, optlen) < 0) return 1; #elif !defined(__APPLE__) && \ !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && \ !defined(__NetBSD__) && \ !defined(__OpenBSD__) if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen) < 0) return 1; #else tcp_proto = getprotobyname("TCP"); if (setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen) < 0) return 1; #endif /* We are nonblocking... */ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) return 1; return 0; }
int main(int argc, char **argv) { struct lws_context_creation_info info; char interface_name[128] = ""; uv_timer_t timeout_watcher; const char *iface = NULL; char cert_path[1024]; char key_path[1024]; int use_ssl = 0; int opts = 0; int n = 0; #ifndef _WIN32 int syslog_options = LOG_PID | LOG_PERROR; #endif #ifndef LWS_NO_DAEMONIZE int daemonize = 0; #endif /* * take care to zero down the info struct, he contains random garbaage * from the stack otherwise */ memset(&info, 0, sizeof info); info.port = 7681; while (n >= 0) { n = getopt_long(argc, argv, "eci:hsap:d:Dr:", options, NULL); if (n < 0) continue; switch (n) { case 'e': opts |= LWS_SERVER_OPTION_LIBEV; break; #ifndef LWS_NO_DAEMONIZE case 'D': daemonize = 1; #ifndef _WIN32 syslog_options &= ~LOG_PERROR; #endif break; #endif case 'd': debug_level = atoi(optarg); break; case 's': use_ssl = 1; break; case 'a': opts |= LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT; break; case 'p': info.port = atoi(optarg); break; case 'i': strncpy(interface_name, optarg, sizeof interface_name); interface_name[(sizeof interface_name) - 1] = '\0'; iface = interface_name; break; case 'c': close_testing = 1; fprintf(stderr, " Close testing mode -- closes on " "client after 50 dumb increments" "and suppresses lws_mirror spam\n"); break; case 'r': resource_path = optarg; printf("Setting resource path to \"%s\"\n", resource_path); break; case 'h': fprintf(stderr, "Usage: test-server " "[--port=<p>] [--ssl] " "[-d <log bitfield>] " "[--resource_path <path>]\n"); exit(1); } } #if !defined(WIN32) #if !defined(LWS_NO_DAEMONIZE) /* * normally lock path would be /var/lock/lwsts or similar, to * simplify getting started without having to take care about * permissions or running as root, set to /tmp/.lwsts-lock */ if (daemonize && lws_daemonize("/tmp/.lwsts-lock")) { fprintf(stderr, "Failed to daemonize\n"); return 1; } #endif /* we will only try to log things according to our debug_level */ setlogmask(LOG_UPTO (LOG_DEBUG)); openlog("lwsts", syslog_options, LOG_DAEMON); #endif /* tell the library what debug level to emit and to send it to syslog */ lws_set_log_level(debug_level, lwsl_emit_syslog); lwsl_notice("libwebsockets test server libuv - license LGPL2.1+SLE\n"); lwsl_notice("(C) Copyright 2010-2016 Andy Green <*****@*****.**>\n"); lwsl_info("Using resource path \"%s\"\n", resource_path); info.iface = iface; info.protocols = protocols; info.extensions = exts; info.ssl_cert_filepath = NULL; info.ssl_private_key_filepath = NULL; if (use_ssl) { if (strlen(resource_path) > sizeof(cert_path) - 32) { lwsl_err("resource path too long\n"); return -1; } sprintf(cert_path, "%s/libwebsockets-test-server.pem", resource_path); if (strlen(resource_path) > sizeof(key_path) - 32) { lwsl_err("resource path too long\n"); return -1; } sprintf(key_path, "%s/libwebsockets-test-server.key.pem", resource_path); info.ssl_cert_filepath = cert_path; info.ssl_private_key_filepath = key_path; opts |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; } info.gid = -1; info.uid = -1; info.max_http_header_pool = 1; info.timeout_secs = 5; info.options = opts | LWS_SERVER_OPTION_LIBUV; context = lws_create_context(&info); if (context == NULL) { lwsl_err("libwebsocket init failed\n"); return -1; } lws_uv_sigint_cfg(context, 1, signal_cb); if (lws_uv_initloop(context, NULL, 0)) { lwsl_err("lws_uv_initloop failed\n"); goto bail; } uv_timer_init(lws_uv_getloop(context, 0), &timeout_watcher); uv_timer_start(&timeout_watcher, uv_timeout_cb_dumb_increment, 50, 50); lws_libuv_run(context, 0); bail: lws_context_destroy(context); lwsl_notice("libwebsockets-test-server exited cleanly\n"); return 0; }