diff --git a/include/libwebsockets/lws-threadpool.h b/include/libwebsockets/lws-threadpool.h index a12c92d36..144c25574 100644 --- a/include/libwebsockets/lws-threadpool.h +++ b/include/libwebsockets/lws-threadpool.h @@ -219,6 +219,9 @@ lws_threadpool_task_status_wsi(struct lws *wsi, LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status lws_threadpool_task_status(struct lws_threadpool_task *task, void **user); +LWS_VISIBLE LWS_EXTERN enum lws_threadpool_task_status +lws_threadpool_task_status_noreap(struct lws_threadpool_task *task); + /** * lws_threadpool_task_sync() - Indicate to a stalled task it may continue * diff --git a/lib/core-net/adopt.c b/lib/core-net/adopt.c index 616449ddc..d9f87a7f5 100644 --- a/lib/core-net/adopt.c +++ b/lib/core-net/adopt.c @@ -260,7 +260,7 @@ lws_adopt_descriptor_vhost2(struct lws *new_wsi, lws_adoption_type type, } #if defined(LWS_WITH_SERVER) else - if (lws_server_socket_service_ssl(new_wsi, fd.sockfd)) { + if (lws_server_socket_service_ssl(new_wsi, fd.sockfd, 0)) { #if defined(LWS_WITH_ACCESS_LOG) lwsl_notice("%s: fail ssl negotiation: %s\n", __func__, new_wsi->simple_ip); diff --git a/lib/core-net/close.c b/lib/core-net/close.c index 062f410ca..f579733e5 100644 --- a/lib/core-net/close.c +++ b/lib/core-net/close.c @@ -454,6 +454,9 @@ just_kill_connection: !wsi->already_did_cce && wsi->protocol) { static const char _reason[] = "closed before established"; + lwsl_notice("%s: closing in unestablished state 0x%x\n", + __func__, lwsi_state(wsi)); + lws_inform_client_conn_fail(wsi, (void *)_reason, sizeof(_reason)); } diff --git a/lib/core-net/connect.c b/lib/core-net/connect.c index a63bab301..96806f141 100644 --- a/lib/core-net/connect.c +++ b/lib/core-net/connect.c @@ -173,7 +173,7 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i) if (p) lws_bind_protocol(wsi, p, __func__); else - lwsl_err("%s: unknown protocol %s\n", __func__, local); + lwsl_info("%s: unknown protocol %s\n", __func__, local); lwsl_info("%s: wsi %p: %s %s entry\n", __func__, wsi, wsi->role_ops->name, diff --git a/lib/core/context.c b/lib/core/context.c index f7a8c9077..a264e18f3 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -306,7 +306,8 @@ lws_create_context(const struct lws_context_creation_info *info) context->ss_proxy_bind = info->ss_proxy_bind; context->ss_proxy_port = info->ss_proxy_port; context->ss_proxy_address = info->ss_proxy_address; - lwsl_notice("%s: using ss proxy bind '%s', port %d, ads '%s'\n", + if (context->ss_proxy_bind && context->ss_proxy_address) + lwsl_notice("%s: using ss proxy bind '%s', port %d, ads '%s'\n", __func__, context->ss_proxy_bind, context->ss_proxy_port, context->ss_proxy_address); #endif diff --git a/lib/core/private-lib-core.h b/lib/core/private-lib-core.h index 49ea3f6bd..6335a89d8 100644 --- a/lib/core/private-lib-core.h +++ b/lib/core/private-lib-core.h @@ -589,7 +589,7 @@ LWS_EXTERN void lwsl_emit_stderr(int level, const char *line); #define lws_ssl_capable_read lws_ssl_capable_read_no_ssl #define lws_ssl_capable_write lws_ssl_capable_write_no_ssl #define lws_ssl_pending lws_ssl_pending_no_ssl - #define lws_server_socket_service_ssl(_b, _c) (0) + #define lws_server_socket_service_ssl(_b, _c, _d) (0) #define lws_ssl_close(_a) (0) #define lws_ssl_context_destroy(_a) #define lws_ssl_SSL_CTX_destroy(_a) diff --git a/lib/misc/threadpool/threadpool.c b/lib/misc/threadpool/threadpool.c index 646c5f2f1..b1e56fd44 100644 --- a/lib/misc/threadpool/threadpool.c +++ b/lib/misc/threadpool/threadpool.c @@ -757,9 +757,8 @@ lws_threadpool_finish(struct lws_threadpool *tp) c = &task->task_queue_next; } - pthread_mutex_unlock(&tp->lock); /* -------------------- tpool unlock */ - pthread_cond_broadcast(&tp->wake_idle); + pthread_mutex_unlock(&tp->lock); /* -------------------- tpool unlock */ } void @@ -1067,6 +1066,12 @@ lws_threadpool_task_status(struct lws_threadpool_task *task, void **user) return status; } +enum lws_threadpool_task_status +lws_threadpool_task_status_noreap(struct lws_threadpool_task *task) +{ + return task->status; +} + enum lws_threadpool_task_status lws_threadpool_task_status_wsi(struct lws *wsi, struct lws_threadpool_task **_task, void **user) @@ -1098,7 +1103,9 @@ lws_threadpool_task_sync(struct lws_threadpool_task *task, int stop) if (stop) state_transition(task, LWS_TP_STATUS_STOPPING); + pthread_mutex_lock(&task->tp->lock); pthread_cond_signal(&task->wake_idle); + pthread_mutex_unlock(&task->tp->lock); } int diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c index 8e100808d..2b273c830 100644 --- a/lib/roles/h1/ops-h1.c +++ b/lib/roles/h1/ops-h1.c @@ -643,7 +643,8 @@ rops_handle_POLLIN_h1(struct lws_context_per_thread *pt, struct lws *wsi, return n; if (lwsi_state(wsi) != LRS_SSL_INIT) if (lws_server_socket_service_ssl(wsi, - LWS_SOCK_INVALID)) + LWS_SOCK_INVALID, + !!(pollfd->revents & LWS_POLLIN))) return LWS_HPI_RET_PLEASE_CLOSE_ME; return LWS_HPI_RET_HANDLED; diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index 97f3a6b28..6a540f84c 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -204,8 +204,6 @@ send_hs: if (lwsi_state(wsi) == LRS_WAITING_CONNECT && (wsi->tls.use_ssl & LCCSCF_USE_SSL)) { - - /* we can retry this... just cook the SSL BIO the first time */ switch (lws_client_create_tls(wsi, &cce, 1)) { @@ -217,13 +215,18 @@ send_hs: goto failed; } + /* + * We succeeded to negotiate a new client tls tunnel. + * If it's h2 alpn, we have arranged to send to h2 + * prefix and set our state to + * LRS_H2_WAITING_TO_SEND_HEADERS already. + */ - - lwsl_notice("%s: wsi %p: st 0x%x\n", + lwsl_notice("%s: wsi %p: tls established st 0x%x\n", __func__, wsi, lwsi_state(wsi)); - if (lwsi_state(wsi) == LRS_WAITING_CONNECT) - lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE2); + if (lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS) + lwsi_set_state(wsi, LRS_WAITING_SSL); lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND, wsi->context->timeout_secs); diff --git a/lib/roles/listen/ops-listen.c b/lib/roles/listen/ops-listen.c index c49159f13..3cb2e9983 100644 --- a/lib/roles/listen/ops-listen.c +++ b/lib/roles/listen/ops-listen.c @@ -153,7 +153,7 @@ rops_handle_POLLIN_listen(struct lws_context_per_thread *pt, struct lws *wsi, return LWS_HPI_RET_WSI_ALREADY_DIED; } /* - if (lws_server_socket_service_ssl(cwsi, accept_fd)) { + if (lws_server_socket_service_ssl(cwsi, accept_fd, 1)) { lws_close_free_wsi(cwsi, LWS_CLOSE_STATUS_NOSTATUS, "listen svc fail"); return LWS_HPI_RET_WSI_ALREADY_DIED; diff --git a/lib/roles/raw-skt/ops-raw-skt.c b/lib/roles/raw-skt/ops-raw-skt.c index 9cdfe2f98..423063dd0 100644 --- a/lib/roles/raw-skt/ops-raw-skt.c +++ b/lib/roles/raw-skt/ops-raw-skt.c @@ -60,7 +60,8 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi, if (lwsi_state(wsi) != LRS_SSL_INIT) if (lws_server_socket_service_ssl(wsi, - LWS_SOCK_INVALID)) + LWS_SOCK_INVALID, + !!(pollfd->revents & pollfd->events & LWS_POLLIN))) return LWS_HPI_RET_PLEASE_CLOSE_ME; return LWS_HPI_RET_HANDLED; diff --git a/lib/system/async-dns/async-dns.c b/lib/system/async-dns/async-dns.c index c1332d14f..88deb4bea 100644 --- a/lib/system/async-dns/async-dns.c +++ b/lib/system/async-dns/async-dns.c @@ -214,8 +214,8 @@ lws_async_dns_writeable(struct lws *wsi, lws_adns_q_t *q) n = lws_ptr_diff(p, pkt + LWS_PRE); m = lws_write(wsi, pkt + LWS_PRE, n, 0); if (m != n) { - lwsl_notice("%s: dns write failed %d %d\n", __func__, - m, n); + lwsl_notice("%s: dns write failed %d %d errno %d\n", __func__, + m, n, errno); goto qfail; } diff --git a/lib/tls/private-network.h b/lib/tls/private-network.h index cf328763d..88474fc19 100644 --- a/lib/tls/private-network.h +++ b/lib/tls/private-network.h @@ -87,7 +87,8 @@ lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, int len); LWS_EXTERN int LWS_WARN_UNUSED_RESULT lws_ssl_pending(struct lws *wsi); LWS_EXTERN int LWS_WARN_UNUSED_RESULT -lws_server_socket_service_ssl(struct lws *new_wsi, lws_sockfd_type accept_fd); +lws_server_socket_service_ssl(struct lws *new_wsi, lws_sockfd_type accept_fd, + char is_pollin); LWS_EXTERN int lws_ssl_close(struct lws *wsi); LWS_EXTERN void diff --git a/lib/tls/tls-server.c b/lib/tls/tls-server.c index 43c930f03..8b1ae6f1e 100644 --- a/lib/tls/tls-server.c +++ b/lib/tls/tls-server.c @@ -123,7 +123,7 @@ lws_context_init_server_ssl(const struct lws_context_creation_info *info, #endif int -lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) +lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd, char from_pollin) { struct lws_context *context = wsi->context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; @@ -141,10 +141,13 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) if (accept_fd == LWS_SOCK_INVALID) assert(0); - if (lws_tls_restrict_borrow(context)) + if (lws_tls_restrict_borrow(context)) { + lwsl_err("%s: failed on ssl restriction\n", __func__); return 1; + } if (lws_tls_server_new_nonblocking(wsi, accept_fd)) { + lwsl_err("%s: failed on lws_tls_server_new_nonblocking\n", __func__); if (accept_fd != LWS_SOCK_INVALID) compatible_close(accept_fd); lws_tls_restrict_return(context); @@ -183,6 +186,10 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) } if (wsi->vhost->tls.allow_non_ssl_on_ssl_port && !wsi->skip_fallback) { + /* + * We came here by POLLIN, so there is supposed to be + * something to read... + */ n = recv(wsi->desc.sockfd, (char *)pt->serv_buf, context->pt_serv_buf_size, MSG_PEEK); @@ -263,13 +270,32 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) } if (!n) { /* - * connection is gone, fail out + * POLLIN but nothing to read is supposed to + * mean the connection is gone, we should + * fail out... + * */ - lwsl_debug("PEEKed 0\n"); + lwsl_warn("%s: PEEKed 0 (from_pollin %d)\n", + __func__, from_pollin); + if (!from_pollin) + /* + * If this wasn't actually info from a + * pollin let it go around again until + * either data came or we still get told + * zero length peek AND POLLIN + */ + goto punt; + + /* + * treat as remote closed + */ + goto fail; } if (n < 0 && (LWS_ERRNO == LWS_EAGAIN || LWS_ERRNO == LWS_EWOULDBLOCK)) { + +punt: /* * well, we get no way to know ssl or not * so go around again waiting for something @@ -277,7 +303,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) * connection. */ if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { - lwsl_info("%s: change_pollfd failed\n", + lwsl_err("%s: change_pollfd failed\n", __func__); return -1; } @@ -303,8 +329,8 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) break; case LWS_SSL_CAPABLE_ERROR: lws_stats_bump(pt, LWSSTATS_C_SSL_CONNECTIONS_FAILED, 1); - lwsl_info("SSL_accept failed socket %u: %d\n", - wsi->desc.sockfd, n); + lwsl_warn("%s: SSL_accept failed socket %u: %d\n", + __func__, wsi->desc.sockfd, n); wsi->socket_is_permanently_unusable = 1; goto fail; @@ -349,8 +375,10 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) context->timeout_secs); lwsi_set_state(wsi, LRS_ESTABLISHED); - if (lws_tls_server_conn_alpn(wsi)) + if (lws_tls_server_conn_alpn(wsi)) { + lwsl_warn("%s: fail on alpn\n", __func__); goto fail; + } lwsl_debug("accepted new SSL conn\n"); break;