diff mbox series

[v2,02/22] gweb: Refactor 'received_data' into 'received_data_{finalize,continue}'.

Message ID 8f55c77f87703048d35509d4aaf014a9bc37d23d.1741059516.git.gerickson@nuovations.com (mailing list archive)
State Accepted
Commit 3820ccb51238fa30fc9c5ec027bf8077112946f3
Headers show
Series Close Two GWeb Request "Bookend" Failure "Holes" | expand

Commit Message

Grant Erickson March 4, 2025, 3:39 a.m. UTC
The receive-data-and-process-it path for the glib I/O add watch
received data handler was already sufficiently long to warrant its own
function. That now exists and 'received_data_continue'.

While short enough at present, as further error-handling cases are
developed, the finalization logic for an outstanding web request
session warranted its own peer function to
'received_data_continue'. That now exists as 'received_data_finalize'
where error or EOF cases are now handled.
---
 gweb/gweb.c | 88 +++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 62 insertions(+), 26 deletions(-)
diff mbox series

Patch

diff --git a/gweb/gweb.c b/gweb/gweb.c
index 8e0b79c52254..d4bdbdd641f5 100644
--- a/gweb/gweb.c
+++ b/gweb/gweb.c
@@ -1091,37 +1091,22 @@  static void add_header_field(struct web_session *session)
 	}
 }
 
-static gboolean received_data(GIOChannel *channel, GIOCondition cond,
-							gpointer user_data)
+static void received_data_finalize(struct web_session *session)
 {
-	struct web_session *session = user_data;
-	guint8 *ptr = session->receive_buffer;
-	gsize bytes_read;
-	GIOStatus status;
+	const guint16 code = GWEB_HTTP_STATUS_CODE_UNKNOWN;
 
-	cancel_connect_timeout(session);
+	session->transport_watch = 0;
 
-	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
-		session->transport_watch = 0;
-		session->result.buffer = NULL;
-		session->result.length = 0;
-		call_result_func(session, GWEB_HTTP_STATUS_CODE_BAD_REQUEST);
-		return FALSE;
-	}
-
-	status = g_io_channel_read_chars(channel,
-				(gchar *) session->receive_buffer,
-				session->receive_space - 1, &bytes_read, NULL);
+	session->result.buffer = NULL;
+	session->result.length = 0;
 
-	debug(session->web, "bytes read %zu", bytes_read);
+	call_result_func(session, code);
+}
 
-	if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) {
-		session->transport_watch = 0;
-		session->result.buffer = NULL;
-		session->result.length = 0;
-		call_result_func(session, GWEB_HTTP_STATUS_CODE_UNKNOWN);
-		return FALSE;
-	}
+static bool received_data_continue(struct web_session *session,
+				gsize bytes_read)
+{
+	guint8 *ptr = session->receive_buffer;
 
 	session->receive_buffer[bytes_read] = '\0';
 
@@ -1210,6 +1195,57 @@  static gboolean received_data(GIOChannel *channel, GIOCondition cond,
 	return TRUE;
 }
 
+static gboolean received_data(GIOChannel *channel, GIOCondition cond,
+							gpointer user_data)
+{
+	struct web_session *session = user_data;
+	gsize bytes_read;
+	GIOStatus status;
+
+	/* We received some data or condition, cancel the connect timeout. */
+
+	cancel_connect_timeout(session);
+
+	/* If there was a low-level I/O condition or error, there is
+	 * nothing more to do; simply fail the request.
+	 */
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+		session->transport_watch = 0;
+
+		session->result.buffer = NULL;
+		session->result.length = 0;
+
+		call_result_func(session, GWEB_HTTP_STATUS_CODE_BAD_REQUEST);
+
+		return FALSE;
+	}
+
+	/* Attempt to read received data from the channel. */
+
+	status = g_io_channel_read_chars(channel,
+				(gchar *) session->receive_buffer,
+				session->receive_space - 1, &bytes_read, NULL);
+
+	debug(session->web, "bytes read %zu status %d", bytes_read,
+		status);
+
+	/* Handle post-channel read errors, which could be either
+	 * G_IO_STATUS_ERROR or G_IO_STATUS_EOF.
+	 */
+	if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) {
+		received_data_finalize(session);
+
+		return FALSE;
+	}
+
+	/* Otherwise, continue the session request and process the
+	 * received data.
+	 */
+
+	return received_data_continue(session, bytes_read);
+}
+
 static int bind_to_address(int sk, const char *interface, int family)
 {
 	struct ifaddrs *ifaddr_list, *ifaddr;