Browse Source

klishd: Unfinished message receiving. The updates for faux is necessary

Serj Kalichev 6 months ago
parent
commit
7c56e35872
4 changed files with 108 additions and 5 deletions
  1. 12 1
      bin/klish/klish.c
  2. 4 0
      klish/ktp.h
  3. 90 4
      klish/ktp/ktpd_session.c
  4. 2 0
      klish/ktp/private.h

+ 12 - 1
bin/klish/klish.c

@@ -14,6 +14,7 @@
 
 #include <faux/faux.h>
 #include <faux/str.h>
+#include <faux/msg.h>
 
 #include <klish/ktp.h>
 #include <klish/ktp_session.h>
@@ -27,6 +28,8 @@ int main(int argc, char **argv)
 	struct options *opts = NULL;
 	int unix_sock = -1;
 	ktp_session_t *session = NULL;
+	faux_msg_t *msg = NULL;
+	faux_net_t *net = NULL;
 
 	// Parse command line options
 	opts = opts_init();
@@ -48,7 +51,15 @@ int main(int argc, char **argv)
 		goto err;
 	}
 
-	write(ktp_session_fd(session), "hello", 5);
+	net = faux_net_new();
+	faux_net_set_fd(net, ktp_session_fd(session));
+	msg = faux_msg_new(KTP_MAGIC, KTP_MAJOR, KTP_MINOR);
+	faux_msg_set_cmd(msg, KTP_AUTH);
+	faux_msg_send(msg, net);
+//	write(ktp_session_fd(session), "hello", 5);
+
+	faux_msg_free(msg);
+	faux_net_free(net);
 
 	retval = 0;
 

+ 4 - 0
klish/ktp.h

@@ -8,6 +8,10 @@
 
 #include <faux/msg.h>
 
+#define KTP_MAGIC 0x2050544b
+#define KTP_MAJOR 0x01
+#define KTP_MINOR 0x00
+
 typedef enum {
 	KTP_NULL = '\0',
 	KTP_STDIN = 'i',

+ 90 - 4
klish/ktp/ktpd_session.c

@@ -12,24 +12,105 @@
 
 #include <faux/str.h>
 #include <faux/async.h>
+#include <faux/msg.h>
+#include <klish/ktp.h>
 #include <klish/ktp_session.h>
 
 #include "private.h"
 
 
+static bool_t check_ktp_header(faux_msg_t *msg)
+{
+	assert(msg);
+	if (!msg)
+		return BOOL_FALSE;
+
+	if (faux_msg_get_magic(msg) != KTP_MAGIC)
+		return BOOL_FALSE;
+	if (faux_msg_get_major(msg) != KTP_MAJOR)
+		return BOOL_FALSE;
+	if (faux_msg_get_minor(msg) != KTP_MINOR)
+		return BOOL_FALSE;
+	if (faux_msg_get_len(msg) < (int)sizeof(faux_hdr_t))
+		return BOOL_FALSE;
+
+	return BOOL_TRUE;
+}
+
+
+static bool_t ktpd_session_dispatch(ktpd_session_t *session, faux_msg_t *msg)
+{
+	assert(session);
+	if (!session)
+		return BOOL_FALSE;
+	assert(msg);
+	if (!msg)
+		return BOOL_FALSE;
+
+	printf("Dispatch %d\n", faux_msg_get_len(msg));
+
+	return BOOL_TRUE;
+}
+
+
+/** @brief Low-level function to receive KTP message.
+ *
+ * Firstly function gets the header of message. Then it checks and parses
+ * header and find out the length of whole message. Then it receives the rest
+ * of message.
+ */
 static bool_t ktpd_session_read_cb(faux_async_t *async,
 	void *data, size_t len, void *user_data)
 {
 	ktpd_session_t *session = (ktpd_session_t *)user_data;
+	faux_msg_t *completed_msg = NULL;
 
 	assert(async);
 	assert(data);
 	assert(session);
 
-	printf("Read cb %lu\n", len);
-	faux_free(data);
-
-	async = async; // Happy compiler
+printf("cb %ld, phdr %ld, hdr %ld\n", len, sizeof(faux_phdr_t), sizeof(faux_hdr_t));
+	// Receive header
+	if (!session->partial_msg) {
+		size_t whole_len = 0;
+		size_t msg_wo_hdr = 0;
+
+		session->partial_msg = (faux_msg_t *)data;
+		// Check for broken header
+		if (!check_ktp_header(session->partial_msg)) {
+			// Use faux_free() instead faux_msg_free() because
+			// it's not completed message.
+			faux_free(session->partial_msg);
+			session->partial_msg = NULL;
+			return BOOL_FALSE;
+		}
+
+		whole_len = faux_msg_get_len(session->partial_msg);
+		// msg_wo_hdr >= 0 because check_ktp_header() validates whole_len
+		msg_wo_hdr = whole_len - sizeof(faux_hdr_t);
+		// Plan to receive message body
+		if (msg_wo_hdr > 0) {
+			faux_async_set_read_limits(async,
+				msg_wo_hdr, msg_wo_hdr);
+			return BOOL_TRUE;
+		}
+		// Here message is completed (msg body has zero length)
+		completed_msg = session->partial_msg;
+
+	// Receive message body
+	} else {
+		completed_msg = realloc(session->partial_msg,
+			sizeof(faux_hdr_t) + len);
+		memcpy((char *)completed_msg + sizeof(faux_hdr_t), data, len);
+	}
+
+	// Here message is completed
+	ktpd_session_dispatch(session, session->partial_msg);
+	faux_msg_free(session->partial_msg);
+	session->partial_msg = NULL; // Ready to recv new header
+	// Plan to receive msg header
+	faux_async_set_read_limits(session->async,
+		sizeof(faux_hdr_t), sizeof(faux_hdr_t));
 
 	return BOOL_TRUE;
 }
@@ -71,7 +152,11 @@ ktpd_session_t *ktpd_session_new(int sock)
 	session->state = KTPD_SESSION_STATE_NOT_AUTHORIZED;
 	session->async = faux_async_new(sock);
 	assert(session->async);
+	// Receive message header first
+	faux_async_set_read_limits(session->async,
+		sizeof(faux_hdr_t), sizeof(faux_hdr_t));
 	faux_async_set_read_cb(session->async, ktpd_session_read_cb, session);
+	session->partial_msg = NULL;
 
 	return session;
 }
@@ -82,6 +167,7 @@ void ktpd_session_free(ktpd_session_t *session)
 	if (!session)
 		return;
 
+	faux_free(session->partial_msg); // It can be partial faux_msg_t
 	close(ktpd_session_fd(session));
 	faux_async_free(session->async);
 	faux_free(session);

+ 2 - 0
klish/ktp/private.h

@@ -3,6 +3,7 @@
 
 #include <faux/net.h>
 #include <faux/async.h>
+#include <faux/msg.h>
 #include <klish/ktp_session.h>
 
 
@@ -21,6 +22,7 @@ struct ktpd_session_s {
 	faux_async_t *async;
 	faux_session_stall_cb_f stall_cb; // Stall callback
 	void *stall_udata;
+	faux_msg_t *partial_msg; // Engine will receive header and then msg
 };