diff options
Diffstat (limited to 'thirdparty/libwebsockets/plat/lws-plat-unix.c')
-rw-r--r-- | thirdparty/libwebsockets/plat/lws-plat-unix.c | 977 |
1 files changed, 0 insertions, 977 deletions
diff --git a/thirdparty/libwebsockets/plat/lws-plat-unix.c b/thirdparty/libwebsockets/plat/lws-plat-unix.c deleted file mode 100644 index 7dba3bd82f..0000000000 --- a/thirdparty/libwebsockets/plat/lws-plat-unix.c +++ /dev/null @@ -1,977 +0,0 @@ -/* - * libwebsockets - small server side websockets and web server implementation - * - * Copyright (C) 2010-2017 Andy Green <andy@warmcat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation: - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - */ - -#define _GNU_SOURCE -#include "core/private.h" - -#include <pwd.h> -#include <grp.h> - -#ifdef LWS_WITH_PLUGINS -#include <dlfcn.h> -#endif -#include <dirent.h> - -void lws_plat_apply_FD_CLOEXEC(int n) -{ - if (n != -1) - fcntl(n, F_SETFD, FD_CLOEXEC ); -} - -int -lws_plat_socket_offset(void) -{ - return 0; -} - -int -lws_plat_pipe_create(struct lws *wsi) -{ - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; - -#if defined(LWS_HAVE_PIPE2) - return pipe2(pt->dummy_pipe_fds, O_NONBLOCK); -#else - return pipe(pt->dummy_pipe_fds); -#endif -} - -int -lws_plat_pipe_signal(struct lws *wsi) -{ - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; - char buf = 0; - int n; - - n = write(pt->dummy_pipe_fds[1], &buf, 1); - - return n != 1; -} - -void -lws_plat_pipe_close(struct lws *wsi) -{ - struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; - - if (pt->dummy_pipe_fds[0] && pt->dummy_pipe_fds[0] != -1) - close(pt->dummy_pipe_fds[0]); - if (pt->dummy_pipe_fds[1] && pt->dummy_pipe_fds[1] != -1) - close(pt->dummy_pipe_fds[1]); - - pt->dummy_pipe_fds[0] = pt->dummy_pipe_fds[1] = -1; -} - -#ifdef __QNX__ -# include "netinet/tcp_var.h" -# define TCP_KEEPINTVL TCPCTL_KEEPINTVL -# define TCP_KEEPIDLE TCPCTL_KEEPIDLE -# define TCP_KEEPCNT TCPCTL_KEEPCNT -#endif - -unsigned long long time_in_microseconds(void) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - return ((unsigned long long)tv.tv_sec * 1000000LL) + tv.tv_usec; -} - -LWS_VISIBLE int -lws_get_random(struct lws_context *context, void *buf, int len) -{ - return read(context->fd_random, (char *)buf, len); -} - -LWS_VISIBLE int -lws_send_pipe_choked(struct lws *wsi) -{ - struct lws_pollfd fds; - struct lws *wsi_eff = wsi; - -#if defined(LWS_WITH_HTTP2) - wsi_eff = lws_get_network_wsi(wsi); -#endif - - /* the fact we checked implies we avoided back-to-back writes */ - wsi_eff->could_have_pending = 0; - - /* treat the fact we got a truncated send pending as if we're choked */ - if (wsi_eff->trunc_len) - return 1; - - fds.fd = wsi_eff->desc.sockfd; - fds.events = POLLOUT; - fds.revents = 0; - - if (poll(&fds, 1, 0) != 1) - return 1; - - if ((fds.revents & POLLOUT) == 0) - return 1; - - /* okay to send another packet without blocking */ - - return 0; -} - -LWS_VISIBLE int -lws_poll_listen_fd(struct lws_pollfd *fd) -{ - return poll(fd, 1, 0); -} - -LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line) -{ - int syslog_level = LOG_DEBUG; - - switch (level) { - case LLL_ERR: - syslog_level = LOG_ERR; - break; - case LLL_WARN: - syslog_level = LOG_WARNING; - break; - case LLL_NOTICE: - syslog_level = LOG_NOTICE; - break; - case LLL_INFO: - syslog_level = LOG_INFO; - break; - } - syslog(syslog_level, "%s", line); -} - -LWS_VISIBLE LWS_EXTERN int -_lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) -{ - volatile struct lws_foreign_thread_pollfd *ftp, *next; - volatile struct lws_context_per_thread *vpt; - struct lws_context_per_thread *pt; - int n = -1, m, c; - - /* stay dead once we are dead */ - - if (!context || !context->vhost_list) - return 1; - - pt = &context->pt[tsi]; - vpt = (volatile struct lws_context_per_thread *)pt; - - lws_stats_atomic_bump(context, pt, LWSSTATS_C_SERVICE_ENTRY, 1); - - if (timeout_ms < 0) - goto faked_service; - - if (context->event_loop_ops->run_pt) - context->event_loop_ops->run_pt(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; - context->service_tid_detected = 1; - } - - /* - * 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; - } - - if (timeout_ms) { - lws_pt_lock(pt, __func__); - /* don't stay in poll wait longer than next hr timeout */ - lws_usec_t t = __lws_hrtimer_service(pt); - if ((lws_usec_t)timeout_ms * 1000 > t) - timeout_ms = t / 1000; - lws_pt_unlock(pt); - } - - vpt->inside_poll = 1; - lws_memory_barrier(); - n = poll(pt->fds, pt->fds_count, timeout_ms); - vpt->inside_poll = 0; - lws_memory_barrier(); - - /* Collision will be rare and brief. Just spin until it completes */ - while (vpt->foreign_spinlock) - ; - - /* - * At this point we are not inside a foreign thread pollfd change, - * and we have marked ourselves as outside the poll() wait. So we - * are the only guys that can modify the lws_foreign_thread_pollfd - * list on the pt. Drain the list and apply the changes to the - * affected pollfds in the correct order. - */ - - lws_pt_lock(pt, __func__); - - ftp = vpt->foreign_pfd_list; - //lwsl_notice("cleared list %p\n", ftp); - while (ftp) { - struct lws *wsi; - struct lws_pollfd *pfd; - - next = ftp->next; - pfd = &vpt->fds[ftp->fd_index]; - if (lws_socket_is_valid(pfd->fd)) { - wsi = wsi_from_fd(context, pfd->fd); - if (wsi) - __lws_change_pollfd(wsi, ftp->_and, ftp->_or); - } - lws_free((void *)ftp); - ftp = next; - } - vpt->foreign_pfd_list = NULL; - lws_memory_barrier(); - - /* we have come out of a poll wait... check the hrtimer list */ - - __lws_hrtimer_service(pt); - - lws_pt_unlock(pt); - - m = 0; -#if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS) - m |= !!pt->ws.rx_draining_ext_list; -#endif - - if (pt->context->tls_ops && - pt->context->tls_ops->fake_POLLIN_for_buffered) - m |= pt->context->tls_ops->fake_POLLIN_for_buffered(pt); - - if (!m && !n) { /* nothing to do */ - lws_service_fd_tsi(context, NULL, tsi); - lws_service_do_ripe_rxflow(pt); - - 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 < (int)pt->fds_count && c; n++) { - if (!pt->fds[n].revents) - continue; - - c--; - - m = lws_service_fd_tsi(context, &pt->fds[n], tsi); - if (m < 0) - return -1; - /* if something closed, retry this slot */ - if (m) - n--; - } - - lws_service_do_ripe_rxflow(pt); - - 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__) || \ - defined(__HAIKU__) - struct protoent *tcp_proto; -#endif - - fcntl(fd, F_SETFD, FD_CLOEXEC); - - 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) || \ - defined(__HAIKU__) - - /* - * 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 */ - -#if defined(LWS_HAVE_TCP_USER_TIMEOUT) - optval = 1000 * (vhost->ka_time + - (vhost->ka_interval * vhost->ka_probes)); - if (setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, - (const void *)&optval, optlen) < 0) - return 1; -#endif - 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 - } - -#if defined(SO_BINDTODEVICE) - if (vhost->bind_iface && vhost->iface) { - lwsl_info("binding listen skt to %s using SO_BINDTODEVICE\n", vhost->iface); - if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, vhost->iface, - strlen(vhost->iface)) < 0) { - lwsl_warn("Failed to bind to device %s\n", vhost->iface); - return 1; - } - } -#endif - - /* Disable Nagle */ - optval = 1; -#if defined (__sun) || defined(__QNX__) - 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__) && \ - !defined(__HAIKU__) - 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; -} - -#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) -static void -_lws_plat_apply_caps(int mode, const cap_value_t *cv, int count) -{ - cap_t caps; - - if (!count) - return; - - caps = cap_get_proc(); - - cap_set_flag(caps, mode, count, cv, CAP_SET); - cap_set_proc(caps); - prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); - cap_free(caps); -} -#endif - -LWS_VISIBLE void -lws_plat_drop_app_privileges(const struct lws_context_creation_info *info) -{ -#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) - int n; -#endif - - if (info->gid && info->gid != -1) - if (setgid(info->gid)) - lwsl_warn("setgid: %s\n", strerror(LWS_ERRNO)); - - if (info->uid && info->uid != -1) { - struct passwd *p = getpwuid(info->uid); - - if (p) { - -#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) - _lws_plat_apply_caps(CAP_PERMITTED, info->caps, info->count_caps); -#endif - - initgroups(p->pw_name, info->gid); - if (setuid(info->uid)) - lwsl_warn("setuid: %s\n", strerror(LWS_ERRNO)); - else - lwsl_notice("Set privs to user '%s'\n", p->pw_name); - -#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) - _lws_plat_apply_caps(CAP_EFFECTIVE, info->caps, info->count_caps); - - if (info->count_caps) - for (n = 0; n < info->count_caps; n++) - lwsl_notice(" RETAINING CAPABILITY %d\n", (int)info->caps[n]); -#endif - - } else - lwsl_warn("getpwuid: unable to find uid %d", info->uid); - } -} - -#ifdef LWS_WITH_PLUGINS - -#if defined(LWS_WITH_LIBUV) && UV_VERSION_MAJOR > 0 - -/* libuv.c implements these in a cross-platform way */ - -#else - -static int filter(const struct dirent *ent) -{ - if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) - return 0; - - return 1; -} - -LWS_VISIBLE int -lws_plat_plugins_init(struct lws_context * context, const char * const *d) -{ - struct lws_plugin_capability lcaps; - struct lws_plugin *plugin; - lws_plugin_init_func initfunc; - struct dirent **namelist; - int n, i, m, ret = 0; - char path[256]; - void *l; - - lwsl_notice(" Plugins:\n"); - - while (d && *d) { - n = scandir(*d, &namelist, filter, alphasort); - if (n < 0) { - lwsl_err("Scandir on %s failed\n", *d); - return 1; - } - - for (i = 0; i < n; i++) { - if (strlen(namelist[i]->d_name) < 7) - goto inval; - - lwsl_notice(" %s\n", namelist[i]->d_name); - - lws_snprintf(path, sizeof(path) - 1, "%s/%s", *d, - namelist[i]->d_name); - l = dlopen(path, RTLD_NOW); - if (!l) { - lwsl_err("Error loading DSO: %s\n", dlerror()); - while (i++ < n) - free(namelist[i]); - goto bail; - } - /* we could open it, can we get his init function? */ - m = lws_snprintf(path, sizeof(path) - 1, "init_%s", - namelist[i]->d_name + 3 /* snip lib... */); - path[m - 3] = '\0'; /* snip the .so */ - initfunc = dlsym(l, path); - if (!initfunc) { - lwsl_err("Failed to get init on %s: %s", - namelist[i]->d_name, dlerror()); - dlclose(l); - } - lcaps.api_magic = LWS_PLUGIN_API_MAGIC; - m = initfunc(context, &lcaps); - if (m) { - lwsl_err("Initializing %s failed %d\n", - namelist[i]->d_name, m); - dlclose(l); - goto skip; - } - - plugin = lws_malloc(sizeof(*plugin), "plugin"); - if (!plugin) { - lwsl_err("OOM\n"); - goto bail; - } - plugin->list = context->plugin_list; - context->plugin_list = plugin; - lws_strncpy(plugin->name, namelist[i]->d_name, - sizeof(plugin->name)); - plugin->l = l; - plugin->caps = lcaps; - context->plugin_protocol_count += lcaps.count_protocols; - context->plugin_extension_count += lcaps.count_extensions; - - free(namelist[i]); - continue; - - skip: - dlclose(l); - inval: - free(namelist[i]); - } - free(namelist); - d++; - } - -bail: - free(namelist); - - return ret; -} - -LWS_VISIBLE int -lws_plat_plugins_destroy(struct lws_context * context) -{ - struct lws_plugin *plugin = context->plugin_list, *p; - lws_plugin_destroy_func func; - char path[256]; - int m; - - if (!plugin) - return 0; - - lwsl_notice("%s\n", __func__); - - while (plugin) { - p = plugin; - m = lws_snprintf(path, sizeof(path) - 1, "destroy_%s", plugin->name + 3); - path[m - 3] = '\0'; - func = dlsym(plugin->l, path); - if (!func) { - lwsl_err("Failed to get destroy on %s: %s", - plugin->name, dlerror()); - goto next; - } - m = func(context); - if (m) - lwsl_err("Initializing %s failed %d\n", - plugin->name, m); -next: - dlclose(p->l); - plugin = p->list; - p->list = NULL; - free(p); - } - - context->plugin_list = NULL; - - return 0; -} - -#endif -#endif - - -#if 0 -static void -sigabrt_handler(int x) -{ - printf("%s\n", __func__); -} -#endif - -LWS_VISIBLE int -lws_plat_context_early_init(void) -{ -#if !defined(LWS_AVOID_SIGPIPE_IGN) - signal(SIGPIPE, SIG_IGN); -#endif - - return 0; -} - -LWS_VISIBLE void -lws_plat_context_early_destroy(struct lws_context *context) -{ -} - -LWS_VISIBLE void -lws_plat_context_late_destroy(struct lws_context *context) -{ -#ifdef LWS_WITH_PLUGINS - if (context->plugin_list) - lws_plat_plugins_destroy(context); -#endif - - if (context->lws_lookup) - lws_free(context->lws_lookup); - - if (!context->fd_random) - lwsl_err("ZERO RANDOM FD\n"); - if (context->fd_random != LWS_INVALID_FILE) - close(context->fd_random); -} - -/* cast a struct sockaddr_in6 * into addr for ipv6 */ - -LWS_VISIBLE int -lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, - size_t addrlen) -{ - int rc = LWS_ITOSA_NOT_EXIST; - - struct ifaddrs *ifr; - struct ifaddrs *ifc; -#ifdef LWS_WITH_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_debug(" interface %s vs %s (fam %d) ipv6 %d\n", ifc->ifa_name, ifname, ifc->ifa_addr->sa_family, ipv6); - - if (strcmp(ifc->ifa_name, ifname)) - continue; - - switch (ifc->ifa_addr->sa_family) { -#if defined(AF_PACKET) - case AF_PACKET: - /* interface exists but is not usable */ - rc = LWS_ITOSA_NOT_USABLE; - continue; -#endif - - case AF_INET: -#ifdef LWS_WITH_IPV6 - if (ipv6) { - /* 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_WITH_IPV6 - case AF_INET6: - memcpy(&addr6->sin6_addr, - &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr, - sizeof(struct in6_addr)); - break; -#endif - default: - continue; - } - rc = LWS_ITOSA_USABLE; - } - - freeifaddrs(ifr); - - if (rc) { - /* check if bind to IP address */ -#ifdef LWS_WITH_IPV6 - if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1) - rc = LWS_ITOSA_USABLE; - else -#endif - if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1) - rc = LWS_ITOSA_USABLE; - } - - return rc; -} - -LWS_VISIBLE void -lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi) -{ - struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; - - if (context->event_loop_ops->io) - context->event_loop_ops->io(wsi, LWS_EV_START | LWS_EV_READ); - - pt->fds[pt->fds_count++].revents = 0; -} - -LWS_VISIBLE void -lws_plat_delete_socket_from_fds(struct lws_context *context, - struct lws *wsi, int m) -{ - struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; - - if (context->event_loop_ops->io) - context->event_loop_ops->io(wsi, - LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE); - - pt->fds_count--; -} - -LWS_VISIBLE void -lws_plat_service_periodic(struct lws_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); -} - -LWS_VISIBLE int -lws_plat_change_pollfd(struct lws_context *context, - struct lws *wsi, struct lws_pollfd *pfd) -{ - return 0; -} - -LWS_VISIBLE const char * -lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt) -{ - return inet_ntop(af, src, dst, cnt); -} - -LWS_VISIBLE int -lws_plat_inet_pton(int af, const char *src, void *dst) -{ - return inet_pton(af, src, dst); -} - -LWS_VISIBLE lws_fop_fd_t -_lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, - const char *vpath, lws_fop_flags_t *flags) -{ - struct stat stat_buf; - int ret = open(filename, (*flags) & LWS_FOP_FLAGS_MASK, 0664); - lws_fop_fd_t fop_fd; - - if (ret < 0) - return NULL; - - if (fstat(ret, &stat_buf) < 0) - goto bail; - - fop_fd = malloc(sizeof(*fop_fd)); - if (!fop_fd) - goto bail; - - fop_fd->fops = fops; - fop_fd->flags = *flags; - fop_fd->fd = ret; - fop_fd->filesystem_priv = NULL; /* we don't use it */ - fop_fd->len = stat_buf.st_size; - fop_fd->pos = 0; - - return fop_fd; - -bail: - close(ret); - return NULL; -} - -LWS_VISIBLE int -_lws_plat_file_close(lws_fop_fd_t *fop_fd) -{ - int fd = (*fop_fd)->fd; - - free(*fop_fd); - *fop_fd = NULL; - - return close(fd); -} - -LWS_VISIBLE lws_fileofs_t -_lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset) -{ - lws_fileofs_t r; - - if (offset > 0 && - offset > (lws_fileofs_t)fop_fd->len - (lws_fileofs_t)fop_fd->pos) - offset = fop_fd->len - fop_fd->pos; - - if ((lws_fileofs_t)fop_fd->pos + offset < 0) - offset = -fop_fd->pos; - - r = lseek(fop_fd->fd, offset, SEEK_CUR); - - if (r >= 0) - fop_fd->pos = r; - else - lwsl_err("error seeking from cur %ld, offset %ld\n", - (long)fop_fd->pos, (long)offset); - - return r; -} - -LWS_VISIBLE int -_lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, - uint8_t *buf, lws_filepos_t len) -{ - long n; - - n = read((int)fop_fd->fd, buf, len); - if (n == -1) { - *amount = 0; - return -1; - } - fop_fd->pos += n; - lwsl_debug("%s: read %ld of req %ld, pos %ld, len %ld\n", __func__, n, - (long)len, (long)fop_fd->pos, (long)fop_fd->len); - *amount = n; - - return 0; -} - -LWS_VISIBLE int -_lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount, - uint8_t *buf, lws_filepos_t len) -{ - long n; - - n = write((int)fop_fd->fd, buf, len); - if (n == -1) { - *amount = 0; - return -1; - } - - fop_fd->pos += n; - *amount = n; - - return 0; -} - -LWS_VISIBLE int -lws_plat_init(struct lws_context *context, - const struct lws_context_creation_info *info) -{ - int fd; - - /* master context has the global fd lookup array */ - context->lws_lookup = lws_zalloc(sizeof(struct lws *) * - context->max_fds, "lws_lookup"); - if (context->lws_lookup == NULL) { - lwsl_err("OOM on lws_lookup array for %d connections\n", - context->max_fds); - return 1; - } - - lwsl_info(" mem: platform fd map: %5lu bytes\n", - (unsigned long)(sizeof(struct lws *) * context->max_fds)); - fd = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY); - - context->fd_random = fd; - if (context->fd_random < 0) { - lwsl_err("Unable to open random device %s %d\n", - SYSTEM_RANDOM_FILEPATH, context->fd_random); - return 1; - } - -#ifdef LWS_WITH_PLUGINS - if (info->plugin_dirs) - lws_plat_plugins_init(context, info->plugin_dirs); -#endif - - return 0; -} - -LWS_VISIBLE int -lws_plat_write_cert(struct lws_vhost *vhost, int is_key, int fd, void *buf, - int len) -{ - int n; - - n = write(fd, buf, len); - - fsync(fd); - lseek(fd, 0, SEEK_SET); - - return n != len; -} - -LWS_VISIBLE int -lws_plat_write_file(const char *filename, void *buf, int len) -{ - int m, fd; - - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); - - if (fd == -1) - return 1; - - m = write(fd, buf, len); - close(fd); - - return m != len; -} - -LWS_VISIBLE int -lws_plat_read_file(const char *filename, void *buf, int len) -{ - int n, fd = lws_open(filename, O_RDONLY); - if (fd == -1) - return -1; - - n = read(fd, buf, len); - close(fd); - - return n; -} - -LWS_VISIBLE int -lws_plat_recommended_rsa_bits(void) -{ - return 4096; -} |