From d1ca974b9f785b928db7758c9985a004bcca7f7e Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sat, 16 Jun 2018 13:24:26 +0800 Subject: [PATCH] http: defer transaction completed if partial pending This is only helpful for http/1... the real solution is cut up sending large things. --- lib/core/output.c | 12 ++++++++++++ lib/roles/h1/ops-h1.c | 10 ++++++++++ lib/roles/http/private.h | 1 + lib/roles/http/server/server.c | 15 +++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/lib/core/output.c b/lib/core/output.c index e2ff18ef2..11965a06b 100644 --- a/lib/core/output.c +++ b/lib/core/output.c @@ -126,6 +126,18 @@ int lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) lwsl_info("** %p signalling to close now\n", wsi); return -1; /* retry closing now */ } + +#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) +#if !defined(LWS_WITHOUT_SERVER) + if (wsi->http.deferred_transaction_completed) { + lwsl_notice("%s: partial completed, doing " + "deferred transaction completed\n", + __func__); + wsi->http.deferred_transaction_completed = 0; + return lws_http_transaction_completed(wsi); + } +#endif +#endif } /* always callback on writeable */ lws_callback_on_writable(wsi); diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c index 8e7294799..9001c864e 100644 --- a/lib/roles/h1/ops-h1.c +++ b/lib/roles/h1/ops-h1.c @@ -445,6 +445,16 @@ try_pollout: if (lwsi_state(wsi) != LRS_ISSUING_FILE) { + if (wsi->trunc_len) { + //lwsl_notice("%s: completing partial\n", __func__); + if (lws_issue_raw(wsi, wsi->trunc_alloc + wsi->trunc_offset, + wsi->trunc_len) < 0) { + lwsl_info("%s signalling to close\n", __func__); + goto fail; + } + return LWS_HPI_RET_HANDLED; + } + lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_WRITEABLE_CB, 1); #if defined(LWS_WITH_STATS) diff --git a/lib/roles/http/private.h b/lib/roles/http/private.h index 2aa7a92f7..569991474 100644 --- a/lib/roles/http/private.h +++ b/lib/roles/http/private.h @@ -227,6 +227,7 @@ struct _lws_http_mode_related { #if defined(LWS_WITH_HTTP_PROXY) unsigned int perform_rewrite:1; #endif + unsigned int deferred_transaction_completed:1; }; diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index 350af3cd7..9356dbb05 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -1714,6 +1714,21 @@ lws_http_transaction_completed(struct lws *wsi) { int n = NO_PENDING_TIMEOUT; + if (wsi->trunc_len) { + /* + * ...so he tried to send something large as the http reply, + * it went as a partial, but he immediately said the + * transaction was completed. + * + * Defer the transaction completed until the last part of the + * partial is sent. + */ + lwsl_notice("%s: deferring due to partial\n", __func__); + wsi->http.deferred_transaction_completed = 1; + + return 0; + } + lwsl_info("%s: wsi %p\n", __func__, wsi); lws_access_log(wsi);