[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 06/09: test_upgrade: added timeout detection on send/rec
From: |
gnunet |
Subject: |
[libmicrohttpd] 06/09: test_upgrade: added timeout detection on send/recv operations |
Date: |
Fri, 24 Nov 2023 19:54:01 +0100 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit 7d7d9bc6b18e7aafeb4b01b13554bac4674221f4
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Tue Oct 24 17:47:23 2023 +0300
test_upgrade: added timeout detection on send/recv operations
---
src/microhttpd/test_upgrade.c | 138 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 128 insertions(+), 10 deletions(-)
diff --git a/src/microhttpd/test_upgrade.c b/src/microhttpd/test_upgrade.c
index ed4275c7..f21c145a 100644
--- a/src/microhttpd/test_upgrade.c
+++ b/src/microhttpd/test_upgrade.c
@@ -162,7 +162,7 @@ _testErrorLog_func (const char *errDesc, const char
*funcName, int lineNum)
/* Could be increased to facilitate debugging */
-static unsigned int test_timeout = 5U;
+static int test_timeout = 5;
static int verbose = 0;
@@ -511,10 +511,69 @@ wr_connect (struct wr_socket *s,
}
+enum wr_wait_for_type
+{
+ WR_WAIT_FOR_RECV = 0,
+ WR_WAIT_FOR_SEND = 1
+};
+
+static void
+wr_wait_socket_ready_ (struct wr_socket *s,
+ int timeout_ms,
+ enum wr_wait_for_type wait_for)
+{
+ fd_set fds;
+ int sel_res;
+ struct timeval tmo;
+
+ if (0 > timeout_ms)
+ return;
+
+#ifndef MHD_WINSOCK_SOCKETS
+ if (FD_SETSIZE <= s->fd)
+ externalErrorExitDesc ("Too large FD value");
+#endif /* ! MHD_WINSOCK_SOCKETS */
+ FD_ZERO (&fds);
+ FD_SET (s->fd, &fds);
+#if ! defined(_WIN32) || defined(__CYGWIN__)
+ tmo.tv_sec = (time_t) (timeout_ms / 1000);
+#else /* Native W32 */
+ tmo.tv_sec = (long) (timeout_ms / 1000);
+#endif /* Native W32 */
+ tmo.tv_usec = ((long) (timeout_ms % 1000)) * 1000;
+
+ if (WR_WAIT_FOR_RECV == wait_for)
+ sel_res = select (1 + (int) s->fd, &fds, NULL, NULL, &tmo);
+ else
+ sel_res = select (1 + (int) s->fd, NULL, &fds, NULL, &tmo);
+
+ if (1 == sel_res)
+ return;
+
+ if (0 == sel_res)
+ fprintf (stderr, "Timeout");
+ else
+ {
+#ifndef MHD_WINSOCK_SOCKETS
+ fprintf (stderr, "Error %d (%s)", (int) errno, strerror (errno));
+#else /* MHD_WINSOCK_SOCKETS */
+ fprintf (stderr, "Error (WSAGetLastError code: %d)",
+ (int) WSAGetLastError ());
+#endif /* MHD_WINSOCK_SOCKETS */
+ }
+ fprintf (stderr, " waiting for socket to be available for %s.\n",
+ (WR_WAIT_FOR_RECV == wait_for) ? "receiving" : "sending");
+ if (WR_WAIT_FOR_RECV == wait_for)
+ mhdErrorExitDesc ("Client or application failed to receive the data");
+ else
+ mhdErrorExitDesc ("Client or application failed to send the data");
+}
+
+
#ifdef HTTPS_SUPPORT
/* Only to be called from wr_send() and wr_recv() ! */
static bool
-wr_handshake (struct wr_socket *s)
+wr_handshake_ (struct wr_socket *s)
{
int res = gnutls_handshake (s->tls_s);
if (GNUTLS_E_SUCCESS == res)
@@ -545,24 +604,31 @@ wr_handshake (struct wr_socket *s)
* @param s the socket to use
* @param buf the buffer with data to send
* @param len the length of data in @a buf
+ * @param timeout_ms the maximum wait time in milliseconds to send the data,
+ * no limit if negative value is used
* @return number of bytes were sent if succeed,
* -1 if failed. Use #MHD_socket_get_error_()
* to get socket error.
*/
static ssize_t
-wr_send (struct wr_socket *s,
- const void *buf,
- size_t len)
+wr_send_tmo (struct wr_socket *s,
+ const void *buf,
+ size_t len,
+ int timeout_ms)
{
if (wr_plain == s->t)
+ {
+ wr_wait_socket_ready_ (s, timeout_ms, WR_WAIT_FOR_SEND);
return MHD_send_ (s->fd, buf, len);
+ }
#ifdef HTTPS_SUPPORT
if (wr_tls == s->t)
{
ssize_t ret;
- if (! s->tls_connected && ! wr_handshake (s))
+ if (! s->tls_connected && ! wr_handshake_ (s))
return -1;
+ wr_wait_socket_ready_ (s, timeout_ms, WR_WAIT_FOR_SEND);
ret = gnutls_record_send (s->tls_s, buf, len);
if (ret > 0)
return ret;
@@ -589,29 +655,54 @@ wr_send (struct wr_socket *s,
}
+/**
+ * Send data to remote by socket.
+ * @param s the socket to use
+ * @param buf the buffer with data to send
+ * @param len the length of data in @a buf
+ * @return number of bytes were sent if succeed,
+ * -1 if failed. Use #MHD_socket_get_error_()
+ * to get socket error.
+ */
+static ssize_t
+wr_send (struct wr_socket *s,
+ const void *buf,
+ size_t len)
+{
+ return wr_send_tmo (s, buf, len, test_timeout * 1000);
+}
+
+
/**
* Receive data from remote by socket.
* @param s the socket to use
* @param buf the buffer to store received data
* @param len the length of @a buf
+ * @param timeout_ms the maximum wait time in milliseconds to receive the data,
+ * no limit if negative value is used
* @return number of bytes were received if succeed,
* -1 if failed. Use #MHD_socket_get_error_()
* to get socket error.
*/
static ssize_t
-wr_recv (struct wr_socket *s,
- void *buf,
- size_t len)
+wr_recv_tmo (struct wr_socket *s,
+ void *buf,
+ size_t len,
+ int timeout_ms)
{
if (wr_plain == s->t)
+ {
+ wr_wait_socket_ready_ (s, timeout_ms, WR_WAIT_FOR_RECV);
return MHD_recv_ (s->fd, buf, len);
+ }
#ifdef HTTPS_SUPPORT
if (wr_tls == s->t)
{
ssize_t ret;
- if (! s->tls_connected && ! wr_handshake (s))
+ if (! s->tls_connected && ! wr_handshake_ (s))
return -1;
+ wr_wait_socket_ready_ (s, timeout_ms, WR_WAIT_FOR_RECV);
ret = gnutls_record_recv (s->tls_s, buf, len);
if (ret >= 0)
return ret;
@@ -636,6 +727,24 @@ wr_recv (struct wr_socket *s,
}
+/**
+ * Receive data from remote by socket.
+ * @param s the socket to use
+ * @param buf the buffer to store received data
+ * @param len the length of @a buf
+ * @return number of bytes were received if succeed,
+ * -1 if failed. Use #MHD_socket_get_error_()
+ * to get socket error.
+ */
+static ssize_t
+wr_recv (struct wr_socket *s,
+ void *buf,
+ size_t len)
+{
+ return wr_recv_tmo (s, buf, len, test_timeout * 1000);
+}
+
+
/**
* Close socket and release allocated resourced
* @param s the socket to close
@@ -1475,6 +1584,15 @@ main (int argc,
has_param (argc, argv, "-s") ||
has_param (argc, argv, "--silent"));
+ if ((((int) ((~((unsigned int) 0U)) >> 1)) / 1000) < test_timeout)
+ {
+ fprintf (stderr, "The test timeout value (%d) is too large.\n"
+ "The test cannot run.\n", test_timeout);
+ fprintf (stderr, "The maximum allowed timeout value is %d.\n",
+ (((int) ((~((unsigned int) 0U)) >> 1)) / 1000));
+ return 3;
+ }
+
if (test_tls)
{
use_tls_tool = TLS_LIB_GNUTLS; /* Should be always available as MHD uses
it. */
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [libmicrohttpd] branch master updated (a19df909 -> 38c06b6a), gnunet, 2023/11/24
- [libmicrohttpd] 01/09: mhd_sockets: fixed error code for W32, gnunet, 2023/11/24
- [libmicrohttpd] 03/09: test_upgrade: used sized send and receive, removed VLA, other improvements, gnunet, 2023/11/24
- [libmicrohttpd] 02/09: test_upgrade{,_large}: minor improvements, gnunet, 2023/11/24
- [libmicrohttpd] 09/09: test_upgrade: implemented timeouts for all socket operations, gnunet, 2023/11/24
- [libmicrohttpd] 05/09: test_upgrade: set TCP_NODELAY unconditionally on used sockets, gnunet, 2023/11/24
- [libmicrohttpd] 06/09: test_upgrade: added timeout detection on send/recv operations,
gnunet <=
- [libmicrohttpd] 04/09: test_upgrade: added initial support for timeout detection, gnunet, 2023/11/24
- [libmicrohttpd] 07/09: test_upgrade: fixed timeout value for external select, gnunet, 2023/11/24
- [libmicrohttpd] 08/09: test_upgrade: merged similar code paths, gnunet, 2023/11/24