From 1bd6117db875932583fb3cf052cfa469f5929703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 9 Oct 2019 03:07:32 +1100 Subject: [PATCH] Handle large queries with SSL enabled This commit fixes the following bug: if a client connection uses SSL and sends a query larger than 32KB, the query is never executed and the connection hang --- include/MySQL_Data_Stream.h | 2 ++ lib/MySQL_Thread.cpp | 13 ++++++++++++- lib/mysql_data_stream.cpp | 15 +++++++++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/include/MySQL_Data_Stream.h b/include/MySQL_Data_Stream.h index 6962ef003..eb212b796 100644 --- a/include/MySQL_Data_Stream.h +++ b/include/MySQL_Data_Stream.h @@ -210,5 +210,7 @@ class MySQL_Data_Stream void free_mysql_real_query(); void reinit_queues(); void destroy_queues(); + + bool data_in_rbio(); }; #endif /* __CLASS_MYSQL_DATA_STREAM_H */ diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index 87b65345b..55d9e57dc 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -4139,7 +4139,18 @@ bool MySQL_Thread::process_data_on_data_stream(MySQL_Data_Stream *myds, unsigned rb = 0; // exit loop } } else { - rb = 0; // exit loop + bool set_rb_zero = true; + if (rb > 0 && myds->myds_type == MYDS_FRONTEND) { + if (myds->encrypted == true) { + if (SSL_is_init_finished(myds->ssl)) { + if (myds->data_in_rbio()) { + set_rb_zero = false; + } + } + } + } + if (set_rb_zero) + rb = 0; // exit loop } } while (rb > 0); diff --git a/lib/mysql_data_stream.cpp b/lib/mysql_data_stream.cpp index aec768218..e73d9f4a1 100644 --- a/lib/mysql_data_stream.cpp +++ b/lib/mysql_data_stream.cpp @@ -437,6 +437,7 @@ int MySQL_Data_Stream::read_from_net() { r = SSL_read (ssl, queue_w_ptr(queueIN), s); } */ + PROXY_TRACE(); if (s < MY_SSL_BUFFER) { return 0; // no enough space for reads } @@ -444,7 +445,8 @@ int MySQL_Data_Stream::read_from_net() { //ssize_t n = read(fd, buf, sizeof(buf)); int n = recv(fd, buf, sizeof(buf), 0); //proxy_info("SSL recv of %d bytes\n", n); - if (n > 0) { + proxy_debug(PROXY_DEBUG_NET, 7, "Session=%p: recv() read %d bytes. num_write: %u , num_read: %u\n", sess, n, rbio_ssl->num_write , rbio_ssl->num_read); + if (n > 0 || rbio_ssl->num_write > rbio_ssl->num_read) { //on_read_cb(buf, (size_t)n); char buf2[MY_SSL_BUFFER]; @@ -452,8 +454,9 @@ int MySQL_Data_Stream::read_from_net() { enum sslstatus status; char *src = buf; int len = n; - while (len) { + while (len > 0) { n2 = BIO_write(rbio_ssl, src, len); + proxy_debug(PROXY_DEBUG_NET, 5, "Session=%p: write %d bytes into BIO %p, len=%d\n", sess, n2, rbio_ssl, len); //proxy_info("BIO_write with len = %d and %d bytes\n", len , n2); if (n2 <= 0) { shut_soft(); @@ -477,6 +480,7 @@ int MySQL_Data_Stream::read_from_net() { } } n2 = SSL_read (ssl, queue_w_ptr(queueIN), s); + proxy_debug(PROXY_DEBUG_NET, 5, "Session=%p: read %d bytes from BIO %p into a buffer with %d bytes free\n", sess, n2, rbio_ssl, s); r = n2; //proxy_info("Read %d bytes from SSL\n", r); if (n2 > 0) { @@ -1398,3 +1402,10 @@ void MySQL_Data_Stream::destroy_MySQL_Connection_From_Pool(bool sq) { mc->send_quit=sq; MyHGM->destroy_MyConn_from_pool(mc); } + +bool MySQL_Data_Stream::data_in_rbio() { + if (rbio_ssl->num_write > rbio_ssl->num_read) { + return true; + } + return false; +}