Commit 06670d34 authored by Deomid Ryabkov's avatar Deomid Ryabkov Committed by Cesanta Bot

Fix double-removal of send_mbuf data with SSL on

Other minor fixes.
Also decrease idle poll interval to 100 ms, as a workaround for some cases of incorrect next poll delay computation.

Added HW tests for SSL fetches.

Fixes cesanta/mongoose-os#262

PUBLISHED_FROM=4d19f845768b4b3b990d25959d4211972368d7fc
parent acfc66cd
...@@ -2461,6 +2461,7 @@ void mg_send(struct mg_connection *nc, const void *buf, int len) { ...@@ -2461,6 +2461,7 @@ void mg_send(struct mg_connection *nc, const void *buf, int len) {
} }
void mg_if_sent_cb(struct mg_connection *nc, int num_sent) { void mg_if_sent_cb(struct mg_connection *nc, int num_sent) {
DBG(("%p %d", nc, num_sent));
#if !defined(NO_LIBC) && MG_ENABLE_HEXDUMP #if !defined(NO_LIBC) && MG_ENABLE_HEXDUMP
if (nc->mgr && nc->mgr->hexdump_file != NULL) { if (nc->mgr && nc->mgr->hexdump_file != NULL) {
char *buf = nc->send_mbuf.buf; char *buf = nc->send_mbuf.buf;
...@@ -5507,21 +5508,26 @@ static void mg_http_transfer_file_data(struct mg_connection *nc) { ...@@ -5507,21 +5508,26 @@ static void mg_http_transfer_file_data(struct mg_connection *nc) {
if (pd->file.type == DATA_FILE) { if (pd->file.type == DATA_FILE) {
struct mbuf *io = &nc->send_mbuf; struct mbuf *io = &nc->send_mbuf;
if (io->len < sizeof(buf)) { if (io->len >= MG_MAX_HTTP_SEND_MBUF) {
to_read = sizeof(buf) - io->len; to_read = 0;
} else {
to_read = MG_MAX_HTTP_SEND_MBUF - io->len;
} }
if (to_read > left) {
if (left > 0 && to_read > left) {
to_read = left; to_read = left;
} }
if (to_read > 0) {
if (to_read == 0) { n = mg_fread(buf, 1, to_read, pd->file.fp);
/* Rate limiting. send_mbuf is too full, wait until it's drained. */ if (n > 0) {
} else if (pd->file.sent < pd->file.cl && mg_send(nc, buf, n);
(n = mg_fread(buf, 1, to_read, pd->file.fp)) > 0) { pd->file.sent += n;
mg_send(nc, buf, n); DBG(("%p sent %d (total %d)", nc, (int) n, (int) pd->file.sent));
pd->file.sent += n; }
} else { } else {
/* Rate-limited */
}
if (pd->file.sent >= pd->file.cl) {
LOG(LL_DEBUG, ("%p done, %d bytes", nc, (int) pd->file.sent));
if (!pd->file.keepalive) nc->flags |= MG_F_SEND_AND_CLOSE; if (!pd->file.keepalive) nc->flags |= MG_F_SEND_AND_CLOSE;
mg_http_free_proto_data_file(&pd->file); mg_http_free_proto_data_file(&pd->file);
} }
...@@ -14056,7 +14062,7 @@ void mg_lwip_mgr_schedule_poll(struct mg_mgr *mgr); ...@@ -14056,7 +14062,7 @@ void mg_lwip_mgr_schedule_poll(struct mg_mgr *mgr);
#include <lwip/tcp.h> #include <lwip/tcp.h>
#include <lwip/tcpip.h> #include <lwip/tcpip.h>
#if LWIP_VERSION >= 0x01050000 #if LWIP_VERSION >= 0x01050000
#include <lwip/priv/tcpip_priv.h> /* For tcp_seg */ #include <lwip/priv/tcp_priv.h> /* For tcp_seg */
#else #else
#include <lwip/tcp_impl.h> #include <lwip/tcp_impl.h>
#endif #endif
...@@ -14259,10 +14265,10 @@ static void mg_lwip_handle_recv_tcp(struct mg_connection *nc) { ...@@ -14259,10 +14265,10 @@ static void mg_lwip_handle_recv_tcp(struct mg_connection *nc) {
static err_t mg_lwip_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb, static err_t mg_lwip_tcp_sent_cb(void *arg, struct tcp_pcb *tpcb,
u16_t num_sent) { u16_t num_sent) {
struct mg_connection *nc = (struct mg_connection *) arg; struct mg_connection *nc = (struct mg_connection *) arg;
DBG(("%p %p %u", nc, tpcb, num_sent)); DBG(("%p %p %u %u %u", nc, tpcb, num_sent, tpcb->unsent, tpcb->unacked));
if (nc == NULL) return ERR_OK; if (nc == NULL) return ERR_OK;
if ((nc->flags & MG_F_SEND_AND_CLOSE) && !(nc->flags & MG_F_WANT_WRITE) && if ((nc->flags & MG_F_SEND_AND_CLOSE) && !(nc->flags & MG_F_WANT_WRITE) &&
nc->send_mbuf.len == 0 && tpcb->unacked == 0) { nc->send_mbuf.len == 0 && tpcb->unsent == 0 && tpcb->unacked == 0) {
mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc); mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
} }
return ERR_OK; return ERR_OK;
...@@ -14530,7 +14536,8 @@ static void mg_lwip_tcp_write_tcpip(void *arg) { ...@@ -14530,7 +14536,8 @@ static void mg_lwip_tcp_write_tcpip(void *arg) {
struct mg_connection *nc = ctx->nc; struct mg_connection *nc = ctx->nc;
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
struct tcp_pcb *tpcb = cs->pcb.tcp; struct tcp_pcb *tpcb = cs->pcb.tcp;
uint16_t len = MIN(tpcb->mss, MIN(ctx->len, tpcb->snd_buf)); size_t len = MIN(tpcb->mss, MIN(ctx->len, tpcb->snd_buf));
size_t unsent, unacked;
if (len == 0) { if (len == 0) {
DBG(("%p no buf avail %u %u %u %p %p", tpcb, tpcb->acked, tpcb->snd_buf, DBG(("%p no buf avail %u %u %u %p %p", tpcb, tpcb->acked, tpcb->snd_buf,
tpcb->snd_queuelen, tpcb->unsent, tpcb->unacked)); tpcb->snd_queuelen, tpcb->unsent, tpcb->unacked));
...@@ -14538,6 +14545,8 @@ static void mg_lwip_tcp_write_tcpip(void *arg) { ...@@ -14538,6 +14545,8 @@ static void mg_lwip_tcp_write_tcpip(void *arg) {
ctx->ret = 0; ctx->ret = 0;
return; return;
} }
unsent = (tpcb->unsent != NULL ? tpcb->unsent->len : 0);
unacked = (tpcb->unacked != NULL ? tpcb->unacked->len : 0);
/* /*
* On ESP8266 we only allow one TCP segment in flight at any given time. * On ESP8266 we only allow one TCP segment in flight at any given time.
* This may increase latency and reduce efficiency of tcp windowing, * This may increase latency and reduce efficiency of tcp windowing,
...@@ -14545,16 +14554,16 @@ static void mg_lwip_tcp_write_tcpip(void *arg) { ...@@ -14545,16 +14554,16 @@ static void mg_lwip_tcp_write_tcpip(void *arg) {
* reduce footprint. * reduce footprint.
*/ */
#if CS_PLATFORM == CS_P_ESP8266 #if CS_PLATFORM == CS_P_ESP8266
if (tpcb->unacked != NULL) { if (unacked > 0) {
ctx->ret = 0; ctx->ret = 0;
return; return;
} }
if (tpcb->unsent != NULL) { len = MIN(len, (TCP_MSS - unsent));
len = MIN(len, (TCP_MSS - tpcb->unsent->len));
}
#endif #endif
cs->err = tcp_write(tpcb, ctx->data, len, TCP_WRITE_FLAG_COPY); cs->err = tcp_write(tpcb, ctx->data, len, TCP_WRITE_FLAG_COPY);
DBG(("%p tcp_write %u = %d", tpcb, len, cs->err)); unsent = (tpcb->unsent != NULL ? tpcb->unsent->len : 0);
unacked = (tpcb->unacked != NULL ? tpcb->unacked->len : 0);
DBG(("%p tcp_write %u = %d, %u %u", tpcb, len, cs->err, unsent, unacked));
if (cs->err != ERR_OK) { if (cs->err != ERR_OK) {
/* /*
* We ignore ERR_MEM because memory will be freed up when the data is sent * We ignore ERR_MEM because memory will be freed up when the data is sent
...@@ -14984,7 +14993,11 @@ uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr) { ...@@ -14984,7 +14993,11 @@ uint32_t mg_lwip_get_poll_delay_ms(struct mg_mgr *mgr) {
} }
num_timers++; num_timers++;
} }
if (nc->send_mbuf.len > 0) { if (nc->send_mbuf.len > 0
#if MG_ENABLE_SSL
|| (nc->flags & MG_F_WANT_WRITE)
#endif
) {
int can_send = 0; int can_send = 0;
/* We have stuff to send, but can we? */ /* We have stuff to send, but can we? */
if (nc->flags & MG_F_UDP) { if (nc->flags & MG_F_UDP) {
...@@ -15097,11 +15110,9 @@ void mg_lwip_ssl_send(struct mg_connection *nc) { ...@@ -15097,11 +15110,9 @@ void mg_lwip_ssl_send(struct mg_connection *nc) {
len = MIN(MG_LWIP_SSL_IO_SIZE, nc->send_mbuf.len); len = MIN(MG_LWIP_SSL_IO_SIZE, nc->send_mbuf.len);
} }
int ret = mg_ssl_if_write(nc, nc->send_mbuf.buf, len); int ret = mg_ssl_if_write(nc, nc->send_mbuf.buf, len);
DBG(("%p SSL_write %u = %d, %d", nc, len, ret)); DBG(("%p SSL_write %u = %d", nc, len, ret));
if (ret > 0) { if (ret > 0) {
mg_if_sent_cb(nc, ret); mg_if_sent_cb(nc, ret);
mbuf_remove(&nc->send_mbuf, ret);
mbuf_trim(&nc->send_mbuf);
cs->last_ssl_write_size = 0; cs->last_ssl_write_size = 0;
} else if (ret < 0) { } else if (ret < 0) {
/* This is tricky. We must remember the exact data we were sending to retry /* This is tricky. We must remember the exact data we were sending to retry
...@@ -15186,8 +15197,8 @@ int ssl_socket_send(void *ctx, const unsigned char *buf, size_t len) { ...@@ -15186,8 +15197,8 @@ int ssl_socket_send(void *ctx, const unsigned char *buf, size_t len) {
struct mg_connection *nc = (struct mg_connection *) ctx; struct mg_connection *nc = (struct mg_connection *) ctx;
struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
int ret = mg_lwip_tcp_write(cs->nc, buf, len); int ret = mg_lwip_tcp_write(cs->nc, buf, len);
LOG(LL_DEBUG, ("%p %d -> %d", nc, len, ret));
if (ret == 0) ret = MBEDTLS_ERR_SSL_WANT_WRITE; if (ret == 0) ret = MBEDTLS_ERR_SSL_WANT_WRITE;
LOG(LL_DEBUG, ("%p %d -> %d", nc, len, ret));
return ret; return ret;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment