void lws_free_wsi(struct lws *wsi) { if (!wsi) return; /* Protocol user data may be allocated either internally by lws * or by specified the user. * We should only free what we allocated. */ if (wsi->protocol && wsi->protocol->per_session_data_size && wsi->user_space && !wsi->user_space_externally_allocated) lws_free(wsi->user_space); lws_free_set_NULL(wsi->rxflow_buffer); lws_free_set_NULL(wsi->trunc_alloc); if (wsi->u.hdr.ah) /* we're closing, losing some rx is OK */ wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; /* we may not have an ah, but may be on the waiting list... */ lws_header_table_detach(wsi, 0); wsi->context->count_wsi_allocated--; lwsl_debug("%s: %p, remaining wsi %d\n", __func__, wsi, wsi->context->count_wsi_allocated); lws_free(wsi); }
void lws_free_wsi(struct lws *wsi) { if (!wsi) return; /* Protocol user data may be allocated either internally by lws * or by specified the user. * We should only free what we allocated. */ if (wsi->protocol && wsi->protocol->per_session_data_size && wsi->user_space && !wsi->user_space_externally_allocated) lws_free(wsi->user_space); lws_free_set_NULL(wsi->rxflow_buffer); lws_free_set_NULL(wsi->trunc_alloc); /* * These union members have an ah at the start * * struct _lws_http_mode_related http; * struct _lws_http2_related http2; * struct _lws_header_related hdr; * * basically ws-related union member does not */ if (wsi->mode != LWSCM_WS_CLIENT && wsi->mode != LWSCM_WS_SERVING) if (wsi->u.hdr.ah) lws_free_header_table(wsi); lws_free(wsi); }
int lws_access_log(struct lws *wsi) { char *p = wsi->http.access_log.user_agent, ass[512], *p1 = wsi->http.access_log.referrer; int l; if (!wsi->vhost) return 0; if (wsi->vhost->log_fd == (int)LWS_INVALID_FILE) return 0; if (!wsi->access_log_pending) return 0; if (!wsi->http.access_log.header_log) return 0; if (!p) p = ""; if (!p1) p1 = ""; /* * We do this in two parts to restrict an oversize referrer such that * we will always have space left to append an empty useragent, while * maintaining the structure of the log text */ l = lws_snprintf(ass, sizeof(ass) - 7, "%s %d %lu \"%s", wsi->http.access_log.header_log, wsi->http.access_log.response, wsi->http.access_log.sent, p1); if (strlen(p) > sizeof(ass) - 6 - l) p[sizeof(ass) - 6 - l] = '\0'; l += lws_snprintf(ass + l, sizeof(ass) - 1 - l, "\" \"%s\"\n", p); if (write(wsi->vhost->log_fd, ass, l) != l) lwsl_err("Failed to write log\n"); if (wsi->http.access_log.header_log) { lws_free(wsi->http.access_log.header_log); wsi->http.access_log.header_log = NULL; } if (wsi->http.access_log.user_agent) { lws_free(wsi->http.access_log.user_agent); wsi->http.access_log.user_agent = NULL; } if (wsi->http.access_log.referrer) { lws_free(wsi->http.access_log.referrer); wsi->http.access_log.referrer = NULL; } wsi->access_log_pending = 0; return 0; }
int lws_plat_inet_pton(int af, const char *src, void *dst) { WCHAR *buffer; DWORD bufferlen = (int)strlen(src) + 1; BOOL ok = FALSE; buffer = lws_malloc(bufferlen * 2, "inet_pton"); if (!buffer) { lwsl_err("Out of memory\n"); return -1; } if (MultiByteToWideChar(CP_ACP, 0, src, bufferlen, buffer, bufferlen) <= 0) { lwsl_err("Failed to convert multi byte to wide char\n"); lws_free(buffer); return -1; } if (af == AF_INET) { struct sockaddr_in dstaddr; int dstaddrlen = sizeof(dstaddr); bzero(&dstaddr, sizeof(dstaddr)); dstaddr.sin_family = AF_INET; if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) { ok = TRUE; memcpy(dst, &dstaddr.sin_addr, sizeof(dstaddr.sin_addr)); } #ifdef LWS_WITH_IPV6 } else if (af == AF_INET6) { struct sockaddr_in6 dstaddr; int dstaddrlen = sizeof(dstaddr); bzero(&dstaddr, sizeof(dstaddr)); dstaddr.sin6_family = AF_INET6; if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) { ok = TRUE; memcpy(dst, &dstaddr.sin6_addr, sizeof(dstaddr.sin6_addr)); } #endif } else lwsl_err("Unsupported type\n"); if (!ok) { int rv = WSAGetLastError(); lwsl_err("WSAAddressToString() : %d\n", rv); } lws_free(buffer); return ok ? 1 : -1; }
int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf, lws_filepos_t *amount) { nvs_handle nvh; size_t s; int n = 0; ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh)); if (nvs_get_blob(nvh, filename, NULL, &s) != ESP_OK) { n = 1; goto bail; } *buf = lws_malloc(s, "alloc_file"); if (!*buf) { n = 2; goto bail; } if (nvs_get_blob(nvh, filename, (char *)*buf, &s) != ESP_OK) { lws_free(*buf); n = 1; goto bail; } *amount = s; bail: nvs_close(nvh); return n; }
void lws_libuv_destroyloop(struct lws_context *context, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; int m; if (!(context->options & LWS_SERVER_OPTION_LIBUV)) return; if (!pt->io_loop_uv) return; if (context->use_ev_sigint) uv_signal_stop(&pt->w_sigint.uv_watcher); for (m = 0; m < ARRAY_SIZE(sigs); m++) uv_signal_stop(&pt->signals[m]); if (!pt->ev_loop_foreign) { uv_stop(pt->io_loop_uv); uv_walk(pt->io_loop_uv, lws_uv_walk_cb, NULL); while (uv_run(pt->io_loop_uv, UV_RUN_NOWAIT)); m = uv_loop_close(pt->io_loop_uv); if (m == UV_EBUSY) lwsl_debug("%s: uv_loop_close: UV_EBUSY\n", __func__); lws_free(pt->io_loop_uv); } }
static void lws_libuv_closewsi_m(uv_handle_t* handle) { lws_sockfd_type sockfd = (lws_sockfd_type)(lws_intptr_t)handle->data; lwsl_debug("%s: sockfd %d\n", __func__, sockfd); compatible_close(sockfd); lws_free(handle); }
LWS_VISIBLE void lws_plat_context_early_destroy(struct libwebsocket_context *context) { if (context->events) { WSACloseEvent(context->events[0]); lws_free(context->events); } }
static struct lws * lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd) { struct lws_context *context = vh->context; struct lws *new_wsi = lws_create_new_server_wsi(vh); if (!new_wsi) { compatible_close(accept_fd); return NULL; } lwsl_info("%s: new wsi %p, sockfd %d\n", __func__, new_wsi, accept_fd); new_wsi->sock = accept_fd; /* the transport is accepted... give him time to negotiate */ lws_set_timeout(new_wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER, context->timeout_secs); #if LWS_POSIX == 0 mbed3_tcp_stream_accept(accept_fd, new_wsi); #endif /* * A new connection was accepted. Give the user a chance to * set properties of the newly created wsi. There's no protocol * selected yet so we issue this to protocols[0] */ if ((context->vhost_list->protocols[0].callback)(new_wsi, LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED, NULL, NULL, 0)) { compatible_close(new_wsi->sock); lws_free(new_wsi); return NULL; } lws_libev_accept(new_wsi, new_wsi->sock); lws_libuv_accept(new_wsi, new_wsi->sock); if (!LWS_SSL_ENABLED(new_wsi->vhost)) { if (insert_wsi_socket_into_fds(context, new_wsi)) { lwsl_err("%s: fail inserting socket\n", __func__); goto fail; } } else { new_wsi->mode = LWSCM_SSL_INIT; if (lws_server_socket_service_ssl(new_wsi, accept_fd)) { lwsl_err("%s: fail ssl negotiation\n", __func__); goto fail; } } return new_wsi; fail: lws_close_free_wsi(new_wsi, LWS_CLOSE_STATUS_NOSTATUS); return NULL; }
void lws_struct_json_serialize_destroy(lws_struct_serialize_t **pjs) { if (!*pjs) return; lws_free(*pjs); *pjs = NULL; }
LWS_VISIBLE void lws_plat_context_late_destroy(struct lws_context *context) { if (context->lws_lookup) lws_free(context->lws_lookup); close(context->dummy_pipe_fds[0]); close(context->dummy_pipe_fds[1]); close(context->fd_random); }
void lws_libuv_destroyloop(struct lws_context *context, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; // struct lws_context *ctx; int m, budget = 100, ns; if (!lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV)) return; if (!pt->io_loop_uv) return; lwsl_notice("%s: closing signals + timers context %p\n", __func__, context); if (context->use_ev_sigint) { uv_signal_stop(&pt->w_sigint.uv_watcher); ns = ARRAY_SIZE(sigs); if (lws_check_opt(context->options, LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN)) ns = 2; for (m = 0; m < ns; m++) { uv_signal_stop(&pt->signals[m]); uv_close((uv_handle_t *)&pt->signals[m], lws_uv_close_cb); } } uv_timer_stop(&pt->uv_timeout_watcher); uv_close((uv_handle_t *)&pt->uv_timeout_watcher, lws_uv_close_cb); uv_idle_stop(&pt->uv_idle); uv_close((uv_handle_t *)&pt->uv_idle, lws_uv_close_cb); if (pt->ev_loop_foreign) return; while (budget-- && uv_run(pt->io_loop_uv, UV_RUN_NOWAIT)) ; lwsl_notice("%s: closing all loop handles context %p\n", __func__, context); uv_stop(pt->io_loop_uv); uv_walk(pt->io_loop_uv, lws_uv_walk_cb, NULL); while (uv_run(pt->io_loop_uv, UV_RUN_NOWAIT)) ; #if UV_VERSION_MAJOR > 0 m = uv_loop_close(pt->io_loop_uv); if (m == UV_EBUSY) lwsl_err("%s: uv_loop_close: UV_EBUSY\n", __func__); #endif lws_free(pt->io_loop_uv); }
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); }
int alloc_pem_to_der_file(struct lws_context *context, const char *filename, uint8_t **buf, lws_filepos_t *amount) { uint8_t *pem, *p, *q, *end; lws_filepos_t len; int n; n = alloc_file(context, filename, &pem, &len); if (n) return n; /* trim the first line */ p = pem; end = p + len; if (strncmp((char *)p, "-----", 5)) goto bail; p += 5; while (p < end && *p != '\n' && *p != '-') p++; if (*p != '-') goto bail; while (p < end && *p != '\n') p++; if (p >= end) goto bail; p++; /* trim the last line */ q = end - 2; while (q > pem && *q != '\n') q--; if (*q != '\n') goto bail; *q = '\0'; *amount = lws_b64_decode_string((char *)p, (char *)pem, len); *buf = pem; return 0; bail: lws_free(pem); return 4; }
LWS_VISIBLE void lws_plat_context_late_destroy(struct lws_context *context) { int n; for (n = 0; n < FD_HASHTABLE_MODULUS; n++) { if (context->fd_hashtable[n].wsi) lws_free(context->fd_hashtable[n].wsi); } WSACleanup(); }
void lws_free_wsi(struct libwebsocket *wsi) { if (!wsi) return; /* Protocol user data may be allocated either internally by lws * or by specified the user. Important we don't free external user data */ if (wsi->protocol && wsi->protocol->per_session_data_size && wsi->user_space && !wsi->user_space_externally_allocated) { lws_free(wsi->user_space); } lws_free2(wsi->rxflow_buffer); lws_free2(wsi->truncated_send_malloc); // TODO: Probably should handle the union structs in wsi->u here depending // on connection mode as well. Too spaghetti for me to follow however... lws_free_header_table(wsi); lws_free(wsi); }
LWS_VISIBLE void lws_plat_context_early_destroy(struct lws_context *context) { struct lws_context_per_thread *pt = &context->pt[0]; int n = context->count_threads; while (n--) { if (pt->events) { WSACloseEvent(pt->events[0]); lws_free(pt->events); } pt++; } }
void lws_free_wsi(struct lws *wsi) { if (!wsi) return; /* Protocol user data may be allocated either internally by lws * or by specified the user. * We should only free what we allocated. */ if (wsi->protocol && wsi->protocol->per_session_data_size && wsi->user_space && !wsi->user_space_externally_allocated) { lws_free(wsi->user_space); wsi->user_space = NULL; } lws_free2(wsi->rxflow_buffer); lws_free2(wsi->truncated_send_malloc); lws_free_header_table(wsi); lws_free(wsi); }
int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf, lws_filepos_t *amount) { FILE *f; size_t s; int n = 0; f = fopen(filename, "rb"); if (f == NULL) { n = 1; goto bail; } if (fseek(f, 0, SEEK_END) != 0) { n = 1; goto bail; } s = ftell(f); if (s == -1) { n = 1; goto bail; } if (fseek(f, 0, SEEK_SET) != 0) { n = 1; goto bail; } *buf = lws_malloc(s, "alloc_file"); if (!*buf) { n = 2; goto bail; } if (fread(*buf, s, 1, f) != 1) { lws_free(*buf); n = 1; goto bail; } *amount = s; bail: if (f) fclose(f); return n; }
struct libwebsocket * libwebsocket_create_new_server_wsi(struct libwebsocket_context *context) { struct libwebsocket *new_wsi; new_wsi = lws_zalloc(sizeof(struct libwebsocket)); if (new_wsi == NULL) { lwsl_err("Out of memory for new connection\n"); return NULL; } new_wsi->pending_timeout = NO_PENDING_TIMEOUT; new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW; /* intialize the instance struct */ new_wsi->state = WSI_STATE_HTTP; new_wsi->mode = LWS_CONNMODE_HTTP_SERVING; new_wsi->hdr_parsing_completed = 0; #ifdef LWS_OPENSSL_SUPPORT new_wsi->use_ssl = LWS_SSL_ENABLED(context); #endif if (lws_allocate_header_table(new_wsi)) { lws_free(new_wsi); return NULL; } /* * these can only be set once the protocol is known * we set an unestablished connection's protocol pointer * to the start of the supported list, so it can look * for matching ones during the handshake */ new_wsi->protocol = context->protocols; new_wsi->user_space = NULL; new_wsi->ietf_spec_revision = 0; new_wsi->sock = LWS_SOCK_INVALID; /* * outermost create notification for wsi * no user_space because no protocol selection */ context->protocols[0].callback(context, new_wsi, LWS_CALLBACK_WSI_CREATE, NULL, NULL, 0); return new_wsi; }
void lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost) { if (vhost->ssl_ctx) { #if defined(LWS_USE_POLARSSL) lws_free(vhost->ssl_ctx); #else #if defined(LWS_USE_MBEDTLS) #else SSL_CTX_free(vhost->ssl_ctx); #endif #endif } if (!vhost->user_supplied_ssl_ctx && vhost->ssl_client_ctx) { #if defined(LWS_USE_POLARSSL) lws_free(vhost->ssl_client_ctx); #else #if defined(LWS_USE_MBEDTLS) #else SSL_CTX_free(vhost->ssl_client_ctx); #endif #endif } }
LWS_VISIBLE LWS_EXTERN void lws_ring_destroy(struct lws_ring *ring) { if (ring->destroy_element) while (ring->oldest_tail != ring->head) { ring->destroy_element((uint8_t *)ring->buf + ring->oldest_tail); ring->oldest_tail = (ring->oldest_tail + ring->element_len) % ring->buflen; } if (ring->buf) lws_free_set_NULL(ring->buf); lws_free(ring); }
LWS_VISIBLE void lws_plat_context_late_destroy(struct lws_context *context) { struct lws_context_per_thread *pt = &context->pt[0]; int m = context->count_threads; if (context->lws_lookup) lws_free(context->lws_lookup); while (m--) { close(pt->dummy_pipe_fds[0]); close(pt->dummy_pipe_fds[1]); pt++; } close(context->fd_random); }
static int lws_urldecode_s_destroy(struct lws_urldecode_stateful *s) { int ret = 0; if (s->state != US_IDLE) ret = -1; if (!ret) if (s->output(s->data, s->name, &s->out, s->pos, 1)) ret = -1; lws_free(s); return ret; }
struct lws * lws_create_server_child_wsi(struct lws_vhost *vhost, struct lws *parent_wsi, unsigned int sid) { struct lws *wsi = lws_create_new_server_wsi(vhost); if (!wsi) return NULL; /* no more children allowed by parent */ if (parent_wsi->u.http2.child_count + 1 == parent_wsi->u.http2.peer_settings.setting[ LWS_HTTP2_SETTINGS__MAX_CONCURRENT_STREAMS]) goto bail; lws_http2_init(&wsi->u.http2.peer_settings); lws_http2_init(&wsi->u.http2.my_settings); wsi->u.http2.stream_id = sid; wsi->u.http2.my_stream_id = sid; wsi->u.http2.parent_wsi = parent_wsi; wsi->u.http2.next_child_wsi = parent_wsi->u.http2.next_child_wsi; parent_wsi->u.http2.next_child_wsi = wsi; parent_wsi->u.http2.child_count++; wsi->u.http2.my_priority = 16; wsi->u.http2.tx_credit = 65535; wsi->state = LWSS_HTTP2_ESTABLISHED; wsi->mode = parent_wsi->mode; wsi->protocol = &vhost->protocols[0]; if (lws_ensure_user_space(wsi)) goto bail; lwsl_info("%s: %p new child %p, sid %d, user_space=%p\n", __func__, parent_wsi, wsi, sid, wsi->user_space); return wsi; bail: vhost->protocols[0].callback(wsi, LWS_CALLBACK_WSI_DESTROY, NULL, NULL, 0); lws_free(wsi); return NULL; }
LWS_VISIBLE const char * lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt) { WCHAR *buffer; DWORD bufferlen = cnt; BOOL ok = FALSE; buffer = lws_malloc(bufferlen); if (!buffer) { lwsl_err("Out of memory\n"); return NULL; } if (af == AF_INET) { struct sockaddr_in srcaddr; bzero(&srcaddr, sizeof(srcaddr)); srcaddr.sin_family = AF_INET; memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr)); if (!WSAAddressToStringW((struct sockaddr*)&srcaddr, sizeof(srcaddr), 0, buffer, &bufferlen)) ok = TRUE; #ifdef LWS_USE_IPV6 } else if (af == AF_INET6) { struct sockaddr_in6 srcaddr; bzero(&srcaddr, sizeof(srcaddr)); srcaddr.sin6_family = AF_INET6; memcpy(&(srcaddr.sin6_addr), src, sizeof(srcaddr.sin6_addr)); if (!WSAAddressToStringW((struct sockaddr*)&srcaddr, sizeof(srcaddr), 0, buffer, &bufferlen)) ok = TRUE; #endif } else lwsl_err("Unsupported type\n"); if (!ok) { int rv = WSAGetLastError(); lwsl_err("WSAAddressToString() : %d\n", rv); } else { if (WideCharToMultiByte(CP_ACP, 0, buffer, bufferlen, dst, cnt, 0, NULL) <= 0) ok = FALSE; } lws_free(buffer); return ok ? dst : NULL; }
LWS_VISIBLE void lws_plat_context_late_destroy(struct lws_context *context) { struct lws_context_per_thread *pt = &context->pt[0]; int m = context->count_threads; #ifdef LWS_WITH_PLUGINS if (context->plugin_list) lws_plat_plugins_destroy(context); #endif if (context->lws_lookup) lws_free(context->lws_lookup); while (m--) { close(pt->dummy_pipe_fds[0]); close(pt->dummy_pipe_fds[1]); pt++; } close(context->fd_random); }
LWS_VISIBLE int lws_plat_change_pollfd(struct lws_context *context, struct lws *wsi, struct lws_pollfd *pfd) { void *p; //lwsl_notice("%s: %p: wsi->pift=%d, events %d\n", // __func__, wsi, wsi->position_in_fds_table, pfd->events); if (pfd->events & LWS_POLLIN) { if (wsi->premature_rx) { lwsl_notice("replaying buffered rx: wsi %p\n", wsi); p = wsi->premature_rx; wsi->premature_rx = NULL; esp8266_cb_rx(wsi->desc.sockfd, (char *)p + wsi->prem_rx_pos, wsi->prem_rx_size - wsi->prem_rx_pos); wsi->prem_rx_size = 0; wsi->prem_rx_pos = 0; lws_free(p); } if (espconn_recv_unhold(wsi->desc.sockfd) < 0) return -1; } else if (espconn_recv_hold(wsi->desc.sockfd) < 0) return -1; if (!(pfd->events & LWS_POLLOUT)) return 0; if (!wsi->pending_send_completion) { pfd->revents |= LWS_POLLOUT; // lwsl_notice("doing POLLOUT\n"); lws_service_fd(lws_get_context(wsi), pfd); } //else //lwsl_notice("pending sc\n"); return 0; }
void freeifaddrs(struct ifaddrs *ifp) { struct ifaddrs *p, *q; for (p = ifp; p; ) { lws_free(p->ifa_name); lws_free(p->ifa_addr); lws_free(p->ifa_dstaddr); lws_free(p->ifa_netmask); lws_free(p->ifa_data); q = p; p = p->ifa_next; lws_free(q); } }
LWS_VISIBLE LWS_EXTERN struct lws_ring * lws_ring_create(size_t element_len, size_t count, void (*destroy_element)(void *)) { struct lws_ring *ring = lws_malloc(sizeof(*ring), "ring create"); if (!ring) return NULL; ring->buflen = (uint32_t)(count * element_len); ring->element_len = (uint32_t)element_len; ring->head = 0; ring->oldest_tail = 0; ring->destroy_element = destroy_element; ring->buf = lws_malloc(ring->buflen, "ring buf"); if (!ring->buf) { lws_free(ring); return NULL; } return ring; }