1 #include "private-libwebsockets.h"
2 #include "freertos/timers.h"
5 * included from libwebsockets.c for unix builds
8 unsigned long long time_in_microseconds(void)
11 gettimeofday(&tv, NULL);
12 return ((unsigned long long)tv.tv_sec * 1000000LL) + tv.tv_usec;
16 lws_get_random(struct lws_context *context, void *buf, int len)
23 lws_send_pipe_choked(struct lws *wsi)
26 struct timeval tv = { 0, 0 };
28 /* treat the fact we got a truncated send pending as if we're choked */
33 FD_SET(wsi->desc.sockfd, &writefds);
35 if (select(wsi->desc.sockfd + 1, NULL, &writefds, NULL, &tv) < 1)
42 lws_poll_listen_fd(struct lws_pollfd *fd)
45 struct timeval tv = { 0, 0 };
48 FD_SET(fd->fd, &readfds);
50 return select(fd->fd + 1, &readfds, NULL, NULL, &tv);
54 lws_cancel_service_pt(struct lws *wsi)
59 lws_cancel_service(struct lws_context *context)
63 LWS_VISIBLE void lwsl_emit_syslog(int level, const char *line)
65 printf("%d: %s", level, line);
68 LWS_VISIBLE LWS_EXTERN int
69 _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
71 struct lws_context_per_thread *pt;
74 /* stay dead once we are dead */
76 if (!context || !context->vhost_list)
79 pt = &context->pt[tsi];
84 if (!context->service_tid_detected) {
87 memset(&_lws, 0, sizeof(_lws));
88 _lws.context = context;
90 context->service_tid_detected =
91 context->vhost_list->protocols[0].callback(
92 &_lws, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
94 context->service_tid = context->service_tid_detected;
97 * is there anybody with pending stuff that needs service forcing?
99 if (!lws_service_adjust_timeout(context, 1, tsi)) {
100 /* -1 timeout means just do forced service */
101 _lws_plat_service_tsi(context, -1, pt->tid);
102 /* still somebody left who wants forced service? */
103 if (!lws_service_adjust_timeout(context, 1, pt->tid))
104 /* yes... come back again quickly */
108 // n = poll(pt->fds, pt->fds_count, timeout_ms);
110 fd_set readfds, writefds, errfds;
111 struct timeval tv = { timeout_ms / 1000,
112 (timeout_ms % 1000) * 1000 };
118 for (n = 0; n < pt->fds_count; n++) {
119 pt->fds[n].revents = 0;
120 if (pt->fds[n].fd >= max_fd)
121 max_fd = pt->fds[n].fd;
122 if (pt->fds[n].events & LWS_POLLIN)
123 FD_SET(pt->fds[n].fd, &readfds);
124 if (pt->fds[n].events & LWS_POLLOUT)
125 FD_SET(pt->fds[n].fd, &writefds);
126 FD_SET(pt->fds[n].fd, &errfds);
129 n = select(max_fd + 1, &readfds, &writefds, &errfds, &tv);
130 for (n = 0; n < pt->fds_count; n++) {
131 if (FD_ISSET(pt->fds[n].fd, &readfds))
132 pt->fds[n].revents |= LWS_POLLIN;
133 if (FD_ISSET(pt->fds[n].fd, &writefds))
134 pt->fds[n].revents |= LWS_POLLOUT;
135 if (FD_ISSET(pt->fds[n].fd, &errfds))
136 pt->fds[n].revents |= LWS_POLLHUP;
141 #ifdef LWS_OPENSSL_SUPPORT
142 if (!pt->rx_draining_ext_list &&
143 !lws_ssl_anybody_has_buffered_read_tsi(context, tsi) && !n) {
145 if (!pt->rx_draining_ext_list && !n) /* poll timeout */ {
147 lws_service_fd_tsi(context, NULL, tsi);
152 m = lws_service_flag_pending(context, tsi);
154 c = -1; /* unknown limit */
157 if (LWS_ERRNO != LWS_EINTR)
163 /* any socket with events to service? */
164 for (n = 0; n < pt->fds_count && c; n++) {
165 if (!pt->fds[n].revents)
170 m = lws_service_fd_tsi(context, &pt->fds[n], tsi);
173 /* if something closed, retry this slot */
182 lws_plat_check_connection_error(struct lws *wsi)
188 lws_plat_service(struct lws_context *context, int timeout_ms)
190 return _lws_plat_service_tsi(context, timeout_ms, 0);
194 lws_plat_set_socket_options(struct lws_vhost *vhost, int fd)
197 socklen_t optlen = sizeof(optval);
199 #if defined(__APPLE__) || \
200 defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
201 defined(__NetBSD__) || \
203 struct protoent *tcp_proto;
206 if (vhost->ka_time) {
207 /* enable keepalive on this socket */
209 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
210 (const void *)&optval, optlen) < 0)
213 #if defined(__APPLE__) || \
214 defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
215 defined(__NetBSD__) || \
216 defined(__CYGWIN__) || defined(__OpenBSD__) || defined (__sun)
219 * didn't find a way to set these per-socket, need to
220 * tune kernel systemwide values
223 /* set the keepalive conditions we want on it too */
224 optval = vhost->ka_time;
225 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE,
226 (const void *)&optval, optlen) < 0)
229 optval = vhost->ka_interval;
230 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,
231 (const void *)&optval, optlen) < 0)
234 optval = vhost->ka_probes;
235 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,
236 (const void *)&optval, optlen) < 0)
243 // if (setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen) < 0)
245 tcp_proto = getprotobyname("TCP");
246 if (setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, &optval, optlen) < 0)
249 /* We are nonblocking... */
250 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
257 lws_plat_drop_app_privileges(struct lws_context_creation_info *info)
262 lws_plat_context_early_init(void)
264 //signal(SIGPIPE, SIG_IGN);
266 // signal(SIGABRT, sigabrt_handler);
272 lws_plat_context_early_destroy(struct lws_context *context)
277 lws_plat_context_late_destroy(struct lws_context *context)
279 #ifdef LWS_WITH_PLUGINS
280 if (context->plugin_list)
281 lws_plat_plugins_destroy(context);
284 if (context->lws_lookup)
285 lws_free(context->lws_lookup);
288 /* cast a struct sockaddr_in6 * into addr for ipv6 */
291 lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
300 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
304 for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) {
308 lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname);
310 if (strcmp(ifc->ifa_name, ifname))
313 switch (ifc->ifa_addr->sa_family) {
317 /* map IPv4 to IPv6 */
318 bzero((char *)&addr6->sin6_addr,
319 sizeof(struct in6_addr));
320 addr6->sin6_addr.s6_addr[10] = 0xff;
321 addr6->sin6_addr.s6_addr[11] = 0xff;
322 memcpy(&addr6->sin6_addr.s6_addr[12],
323 &((struct sockaddr_in *)ifc->ifa_addr)->sin_addr,
324 sizeof(struct in_addr));
328 (struct sockaddr_in *)ifc->ifa_addr,
329 sizeof(struct sockaddr_in));
333 memcpy(&addr6->sin6_addr,
334 &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr,
335 sizeof(struct in6_addr));
347 /* check if bind to IP address */
349 if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1)
353 if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1)
364 lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
366 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
368 pt->fds[pt->fds_count++].revents = 0;
372 lws_plat_delete_socket_from_fds(struct lws_context *context,
373 struct lws *wsi, int m)
375 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
381 lws_plat_service_periodic(struct lws_context *context)
386 lws_plat_change_pollfd(struct lws_context *context,
387 struct lws *wsi, struct lws_pollfd *pfd)
392 LWS_VISIBLE const char *
393 lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
395 return inet_ntop(af, src, dst, cnt);
398 LWS_VISIBLE lws_fop_fd_t
399 _lws_plat_file_open(struct lws_plat_file_ops *fops, const char *filename,
400 const char *vpath, lws_fop_flags_t *flags)
402 struct stat stat_buf;
404 int ret = open(filename, *flags, 0664);
409 if (fstat(ret, &stat_buf) < 0)
411 fop_fd = malloc(sizeof(*fop_fd));
417 fop_fd->flags = *flags;
418 fop_fd->filesystem_priv = NULL; /* we don't use it */
420 fop_fd->len = stat_buf.st_size;
431 _lws_plat_file_close(lws_fop_fd_t *fops_fd)
433 int fd = (*fops_fd)->fd;
441 LWS_VISIBLE lws_fileofs_t
442 _lws_plat_file_seek_cur(lws_fop_fd_t fops_fd, lws_fileofs_t offset)
444 return lseek(fops_fd->fd, offset, SEEK_CUR);
448 _lws_plat_file_read(lws_fop_fd_t fops_fd, lws_filepos_t *amount,
449 uint8_t *buf, lws_filepos_t len)
453 n = read(fops_fd->fd, buf, len);
465 _lws_plat_file_write(lws_fop_fd_t fops_fd, lws_filepos_t *amount,
466 uint8_t *buf, lws_filepos_t len)
470 n = write(fops_fd->fd, buf, len);
483 lws_plat_init(struct lws_context *context,
484 struct lws_context_creation_info *info)
486 /* master context has the global fd lookup array */
487 context->lws_lookup = lws_zalloc(sizeof(struct lws *) *
489 if (context->lws_lookup == NULL) {
490 lwsl_err("OOM on lws_lookup array for %d connections\n",
495 lwsl_notice(" mem: platform fd map: %5lu bytes\n",
496 (unsigned long)(sizeof(struct lws *) * context->max_fds));
498 #ifdef LWS_WITH_PLUGINS
499 if (info->plugin_dirs)
500 lws_plat_plugins_init(context, info->plugin_dirs);
507 LWS_VISIBLE void esp32_uvtimer_cb(TimerHandle_t t)
509 struct timer_mapping *p = pvTimerGetTimerID(t);