Browse Source

faux.msg: Get hdr.c. Functions to work with header

Serj Kalichev 3 years ago
parent
commit
89d68c2ebb
4 changed files with 385 additions and 52 deletions
  1. 21 0
      faux/msg.h
  2. 1 0
      faux/msg/Makefile.am
  3. 274 0
      faux/msg/hdr.c
  4. 89 52
      faux/msg/msg.c

+ 21 - 0
faux/msg.h

@@ -71,6 +71,24 @@ typedef struct faux_hdr_s {
 
 C_DECL_BEGIN
 
+// Header functions
+void faux_hdr_set_cmd(faux_hdr_t *hdr, uint16_t cmd);
+uint16_t faux_hdr_cmd(const faux_hdr_t *hdr);
+void faux_hdr_set_status(faux_hdr_t *hdr, uint32_t status);
+uint32_t faux_hdr_status(const faux_hdr_t *hdr);
+void faux_hdr_set_req_id(faux_hdr_t *hdr, uint32_t req_id);
+uint32_t faux_hdr_req_id(const faux_hdr_t *hdr);
+void faux_hdr_set_param_num(faux_hdr_t *hdr, uint32_t param_num);
+uint32_t faux_hdr_param_num(const faux_hdr_t *hdr);
+void faux_hdr_set_len(faux_hdr_t *hdr, uint32_t len);
+int faux_hdr_len(const faux_hdr_t *hdr);
+void faux_hdr_set_magic(faux_hdr_t *hdr, uint32_t magic);
+uint32_t faux_hdr_magic(const faux_hdr_t *hdr);
+void faux_hdr_set_major(faux_hdr_t *hdr, uint8_t major);
+uint8_t faux_hdr_major(const faux_hdr_t *hdr);
+void faux_hdr_set_minor(faux_hdr_t *hdr, uint8_t minor);
+uint8_t faux_hdr_minor(const faux_hdr_t *hdr);
+
 // Parameter functions
 void faux_phdr_set_type(faux_phdr_t *phdr, uint16_t param_type);
 uint16_t faux_phdr_get_type(const faux_phdr_t *phdr);
@@ -104,6 +122,9 @@ ssize_t faux_msg_send(const faux_msg_t *msg, faux_net_t *faux_net);
 faux_msg_t *faux_msg_recv(faux_net_t *faux_net);
 bool_t faux_msg_iov(const faux_msg_t *msg, struct iovec **iov_out, size_t *iov_num_out);
 bool_t faux_msg_serialize(const faux_msg_t *msg, char **buf, size_t *len);
+faux_msg_t *faux_msg_deserialize_parts(const faux_hdr_t *hdr,
+	const char *body, size_t body_len);
+faux_msg_t *faux_msg_deserialize(const char *data, size_t len);
 
 void faux_msg_debug(faux_msg_t *msg);
 

+ 1 - 0
faux/msg/Makefile.am

@@ -1,4 +1,5 @@
 libfaux_la_SOURCES += \
+	faux/msg/hdr.c \
 	faux/msg/phdr.c \
 	faux/msg/msg.c
 

+ 274 - 0
faux/msg/hdr.c

@@ -0,0 +1,274 @@
+/** @file hdr.c
+ */
+
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+
+#include <faux/faux.h>
+#include <faux/str.h>
+#include <faux/list.h>
+#include <faux/net.h>
+#include <faux/msg.h>
+
+
+/** @brief Sets command code to header.
+ *
+ * See the protocol and header description for possible values.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @param [in] cmd Command code (16 bit).
+ */
+void faux_hdr_set_cmd(faux_hdr_t *hdr, uint16_t cmd)
+{
+	assert(hdr);
+	if (!hdr)
+		return;
+	hdr->cmd = htons(cmd);
+}
+
+
+/** @brief Gets command code from header.
+ *
+ * See the protocol and header description for possible values.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @return Command code or 0 on error.
+ */
+uint16_t faux_hdr_cmd(const faux_hdr_t *hdr)
+{
+	assert(hdr);
+	if (!hdr)
+		return 0;
+
+	return ntohs(hdr->cmd);
+}
+
+
+/** @brief Sets message status to header.
+ *
+ * See the protocol and header description for possible values.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @param [in] status Message status.
+ */
+void faux_hdr_set_status(faux_hdr_t *hdr, uint32_t status)
+{
+	assert(hdr);
+	if (!hdr)
+		return;
+	hdr->status = htonl(status);
+}
+
+
+/** @brief Gets message status from header.
+ *
+ * See the protocol and header description for possible values.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @return Message status or 0 on error.
+ */
+uint32_t faux_hdr_status(const faux_hdr_t *hdr)
+{
+	assert(hdr);
+	if (!hdr)
+		return 0;
+
+	return ntohl(hdr->status);
+}
+
+
+/** @brief Sets request ID to header.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @param [in] req_id Request ID.
+ */
+void faux_hdr_set_req_id(faux_hdr_t *hdr, uint32_t req_id)
+{
+	assert(hdr);
+	if (!hdr)
+		return;
+	hdr->req_id = htonl(req_id);
+}
+
+
+/** @brief Gets request ID from header.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @return Request ID or 0 on error.
+ */
+uint32_t faux_hdr_req_id(const faux_hdr_t *hdr)
+{
+	assert(hdr);
+	if (!hdr)
+		return 0;
+
+	return ntohl(hdr->req_id);
+}
+
+
+/** @brief Sets number of parameters to header.
+ *
+ * It's a static function because external user can add or remove parameters
+ * but class calculates total number of parameters internally.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @param [in] param_num Number of parameters.
+ */
+void faux_hdr_set_param_num(faux_hdr_t *hdr, uint32_t param_num)
+{
+	assert(hdr);
+	if (!hdr)
+		return;
+	hdr->param_num = htonl(param_num);
+}
+
+
+/** @brief Gets number of parameters from header.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @return Number of parameters or 0 on error.
+ */
+uint32_t faux_hdr_param_num(const faux_hdr_t *hdr)
+{
+	assert(hdr);
+	if (!hdr)
+		return -1;
+
+	return ntohl(hdr->param_num);
+}
+
+
+/** @brief Sets total length of message to header.
+ *
+ * It's a static function because external user can add or remove parameters
+ * but class calculates total length of message internally.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @param [in] len Total length of message.
+ */
+void faux_hdr_set_len(faux_hdr_t *hdr, uint32_t len)
+{
+	assert(hdr);
+	if (!hdr)
+		return;
+	hdr->len = htonl(len);
+}
+
+
+/** @brief Gets total length of message from header.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @return Total length of message or 0 on error.
+ */
+int faux_hdr_len(const faux_hdr_t *hdr)
+{
+	assert(hdr);
+	if (!hdr)
+		return 0;
+
+	return ntohl(hdr->len);
+}
+
+
+/** @brief Sets magic number to header.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @param [in] magic Magic number.
+ */
+void faux_hdr_set_magic(faux_hdr_t *hdr, uint32_t magic)
+{
+	assert(hdr);
+	if (!hdr)
+		return;
+
+	hdr->magic = htonl(magic);
+}
+
+
+/** @brief Gets magic number from header.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @return Magic number or 0 on error.
+ */
+uint32_t faux_hdr_magic(const faux_hdr_t *hdr)
+{
+	assert(hdr);
+	if (!hdr)
+		return 0;
+
+	return ntohl(hdr->magic);
+}
+
+
+/** @brief Sets major version to header.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @param [in] major Major protocol version.
+ * @return Major version number or 0 on error.
+ */
+void faux_hdr_set_major(faux_hdr_t *hdr, uint8_t major)
+{
+	assert(hdr);
+	if (!hdr)
+		return;
+
+	hdr->major = major;
+}
+
+
+/** @brief Gets major version from header.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @return Major version number or 0 on error.
+ */
+uint8_t faux_hdr_major(const faux_hdr_t *hdr)
+{
+	assert(hdr);
+	if (!hdr)
+		return 0;
+
+	return hdr->major;
+}
+
+
+/** @brief Sets minor version to header.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @param [in] minor Minor protocol version.
+ * @return Major version number or 0 on error.
+ */
+void faux_hdr_set_minor(faux_hdr_t *hdr, uint8_t minor)
+{
+	assert(hdr);
+	if (!hdr)
+		return;
+
+	hdr->minor = minor;
+}
+
+
+/** @brief Gets minor version from header.
+ *
+ * @param [in] hdr Allocated faux_hdr_t object.
+ * @return Minor version number or 0 on error.
+ */
+uint8_t faux_hdr_minor(const faux_hdr_t *hdr)
+{
+	assert(hdr);
+	if (!hdr)
+		return 0;
+
+	return hdr->minor;
+}

+ 89 - 52
faux/msg/msg.c

@@ -708,6 +708,82 @@ bool_t faux_msg_serialize(const faux_msg_t *msg, char **buf, size_t *len)
 	return BOOL_TRUE;
 }
 
+
+faux_msg_t *faux_msg_deserialize_parts(const faux_hdr_t *hdr,
+	const char *body, size_t body_len)
+{
+	faux_msg_t *msg = NULL;
+	faux_phdr_t *phdr = NULL;
+	size_t phdr_whole_len = 0;
+	size_t params_whole_len = 0;
+	unsigned int i = 0;
+	const char *data = NULL;
+	uint32_t param_num = 0;
+
+	msg = faux_msg_allocate();
+	assert(msg);
+	if (!msg)
+		return NULL;
+
+	// Replace message header by new one
+	memcpy(msg->hdr, hdr, sizeof(*hdr));
+
+	if (0 == body_len) // Message contains header only
+		return msg;
+
+	// Process message body i.e. parameters
+	param_num = faux_msg_get_param_num(msg);
+	if (0 == param_num) { // Something went wrong
+		faux_msg_free(msg);
+		return NULL;
+	}
+
+	phdr_whole_len = param_num * sizeof(*phdr);
+	if (phdr_whole_len > body_len) { // Something went wrong
+		faux_msg_free(msg);
+		return NULL;
+	}
+	phdr = (faux_phdr_t *)body;
+	// Find out whole parameters length
+	for (i = 0; i < param_num; i++)
+		params_whole_len += faux_phdr_get_len(phdr + i);
+	if ((phdr_whole_len + params_whole_len) != body_len) { // Something went wrong
+		faux_msg_free(msg);
+		return NULL;
+	}
+
+	// Parameters
+	data = body + phdr_whole_len;
+	for (i = 0; i < param_num; i++) {
+		size_t cur_data_len = faux_phdr_get_len(phdr + i);
+		if (0 == cur_data_len)
+			continue;
+		faux_msg_add_param_internal(msg,
+			faux_phdr_get_type(phdr + i),
+			data, cur_data_len, BOOL_FALSE);
+		data += cur_data_len;
+	}
+
+	return msg;
+}
+
+
+faux_msg_t *faux_msg_deserialize(const char *data, size_t len)
+{
+	const faux_hdr_t *msg_hdr = (const faux_hdr_t *)data;
+	const char *msg_body = data + sizeof(*msg_hdr);
+	size_t msg_body_len = len - sizeof(*msg_hdr);
+
+	assert(data);
+	if (!data)
+		return NULL;
+	if (len < sizeof(*msg_hdr))
+		return NULL;
+
+	return faux_msg_deserialize_parts(msg_hdr, msg_body, msg_body_len);
+}
+
+
 /** @brief Receives full message and allocates faux_msg_t object for it.
  *
  * Function receives message from network using preinitialized faux_net_t object.
@@ -727,64 +803,25 @@ faux_msg_t *faux_msg_recv(faux_net_t *faux_net)
 {
 	faux_msg_t *msg = NULL;
 	size_t received = 0;
-	faux_phdr_t *phdr = NULL;
-	size_t phdr_whole_len = 0;
-	size_t max_data_len = 0;
-	unsigned int i = 0;
-	char *data = NULL;
-	uint32_t param_num = 0;
+	faux_hdr_t hdr = {};
+	char *body = NULL;
+	size_t body_len = 0;
 
-	msg = faux_msg_allocate();
-	assert(msg);
-	if (!msg)
+	// Receive message header
+	received = faux_net_recv(faux_net, &hdr, sizeof(hdr));
+	if (received != sizeof(hdr))
 		return NULL;
 
-	// Receive message header
-	received = faux_net_recv(faux_net, msg->hdr, sizeof(*msg->hdr));
-	if (received != sizeof(*msg->hdr)) {
-		faux_msg_free(msg);
+	body_len = hdr.len;
+	body = faux_malloc(body_len);
+	received = faux_net_recv(faux_net, body, body_len);
+	if (received != body_len) {
+		faux_free(body);
 		return NULL;
 	}
 
-	// Receive parameter headers
-	param_num = faux_msg_get_param_num(msg);
-	if (param_num != 0) {
-		phdr_whole_len = param_num * sizeof(*phdr);
-		phdr = faux_zmalloc(phdr_whole_len);
-		received = faux_net_recv(faux_net, phdr, phdr_whole_len);
-		if (received != phdr_whole_len) {
-			faux_free(phdr);
-			faux_msg_free(msg);
-			return NULL;
-		}
-		// Find out maximum data length
-		for (i = 0; i < param_num; i++) {
-			size_t cur_data_len = faux_phdr_get_len(phdr + i);
-			if (cur_data_len > max_data_len)
-				max_data_len = cur_data_len;
-		}
-
-		// Receive parameter data
-		data = faux_zmalloc(max_data_len);
-		for (i = 0; i < param_num; i++) {
-			size_t cur_data_len = faux_phdr_get_len(phdr + i);
-			if (0 == cur_data_len)
-				continue;
-			received = faux_net_recv(faux_net, data, cur_data_len);
-			if (received != cur_data_len) {
-				faux_free(data);
-				faux_free(phdr);
-				faux_msg_free(msg);
-				return NULL;
-			}
-			faux_msg_add_param_internal(msg,
-				faux_phdr_get_type(phdr + i),
-				data, cur_data_len, BOOL_FALSE);
-		}
-
-		faux_free(data);
-		faux_free(phdr);
-	}
+	msg = faux_msg_deserialize_parts(&hdr, body, body_len);
+	faux_free(body);
 
 #ifdef DEBUG
 	// Debug