aboutsummaryrefslogtreecommitdiff
path: root/archived/v1/common.h
diff options
context:
space:
mode:
Diffstat (limited to 'archived/v1/common.h')
-rw-r--r--archived/v1/common.h181
1 files changed, 181 insertions, 0 deletions
diff --git a/archived/v1/common.h b/archived/v1/common.h
new file mode 100644
index 0000000..c7bb0dd
--- /dev/null
+++ b/archived/v1/common.h
@@ -0,0 +1,181 @@
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#define PORT 9983
+// max buffer size sent over network
+// TODO: choose a better size
+#define BUF_MAX 256
+// max size for a message sent
+#define MESSAGE_MAX 256
+// max length of author field
+#define MESSAGE_AUTHOR_LEN 13
+// max length of timestamp field
+#define MESSAGE_TIMESTAMP_LEN 9
+// current user's name
+#define USERNAME "Jef Koek"
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef int8_t s8;
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64;
+
+// To serialize the text that could be arbitrary length the lenght is encoded after the author
+// string and before the text.
+struct Message {
+ u8 author[MESSAGE_AUTHOR_LEN];
+ u8 timestamp[MESSAGE_TIMESTAMP_LEN]; // HH:MM:SS
+ u16 text_len; // length of the text including null terminator
+ char *text;
+} typedef Message;
+
+// printf without buffering using write syscall, works when using sockets
+void writef(char *format, ...);
+
+u16 str_len(char *str);
+
+// save the message msg to file in binary format, returns zero on success, returns 1 if the msg.text
+// was empty which should not be allowed.
+u8 message_fsave(Message *msg, FILE *f);
+// load the message msg from file f, returns zero on success, returns 1 if the msg.text
+// was empty which should not be allowed.
+u8 message_fload(Message *msg, FILE *f);
+
+// Encode msg and send it to fd
+// return -1 if send() returns -1. Otherwise returns number of bytes sent.
+// NOTE: this function should not alter the content stored in msg.
+u32 message_send(Message *msg, u32 fd);
+// Decode data from fd and populate msg with it
+// if recv() returns 0 or -1 it will return early and return 0 or -1 accordingly.
+// Otherwise returns the number of bytes received
+u32 message_receive(Message *msg, u32 fd);
+
+void writef(char *format, ...)
+{
+ char buf[255 + 1];
+ va_list args;
+ va_start(args, format);
+
+ vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+ int n = 0;
+ while (*(buf + n) != 0)
+ n++;
+ write(0, buf, n);
+}
+
+// Returns the length of the string plus the null terminator
+u16 str_len(char *str)
+{
+ if (*str == 0)
+ return 0;
+
+ u16 i = 0;
+ while (str[i])
+ i++;
+
+ return i + 1;
+}
+
+void str_cpy(char *to, char *from)
+{
+ while ((*to++ = *from++))
+ ;
+}
+
+// Save msg to file f
+// Returns 0 on success, returns 1 if msg->text is NULL, returns 2 if mfg->len is 0
+u8 message_fsave(Message *msg, FILE *f)
+{
+ if (msg->text == NULL) {
+ return 1;
+ } else if (msg->text_len == 0)
+ return 2;
+
+ fwrite(&msg->timestamp, sizeof(*msg->timestamp) * MESSAGE_TIMESTAMP_LEN, 1, f);
+ fwrite(&msg->author, sizeof(*msg->author) * MESSAGE_AUTHOR_LEN, 1, f);
+ fwrite(&msg->text_len, sizeof(msg->text_len), 1, f);
+ fwrite(&msg->text, msg->text_len, 1, f);
+
+ return 0;
+}
+
+u8 message_fload(Message *msg, FILE *f)
+{
+ fread(msg, sizeof(*msg->timestamp) * MESSAGE_TIMESTAMP_LEN + sizeof(*msg->author) * MESSAGE_AUTHOR_LEN, 1, f);
+ u16 len;
+ fread(&len, sizeof(len), 1, f);
+ if (len == 0) {
+ // TODO: Error: empty message should not be allowed
+ // empty message
+ msg->text = NULL;
+ return 1;
+ }
+ char txt[len];
+ fgets(txt, len, f);
+ memcpy(msg->text, txt, len);
+
+ return 0;
+}
+
+u32 message_send(Message *msg, u32 serverfd)
+{
+ // for protocol see README.md
+ u32 buf_len = sizeof(buf_len) + MESSAGE_AUTHOR_LEN + MESSAGE_TIMESTAMP_LEN + msg->text_len;
+ char buf[buf_len];
+ u32 offset;
+
+ memcpy(buf, &buf_len, sizeof(buf_len));
+ offset = sizeof(buf_len);
+ memcpy(buf + offset, msg->author, MESSAGE_AUTHOR_LEN);
+ offset += MESSAGE_AUTHOR_LEN;
+ memcpy(buf + offset, msg->timestamp, MESSAGE_TIMESTAMP_LEN);
+ offset += MESSAGE_TIMESTAMP_LEN;
+ memcpy(buf + offset, msg->text, msg->text_len);
+
+ u32 n = send(serverfd, &buf, buf_len, 0);
+ if (n == -1)
+ return n;
+
+ return n;
+}
+
+u32 message_receive(Message *msg, u32 clientfd)
+{
+ // for protocol see README.md
+ // must all be of the s
+ u32 nrecv = 0, buf_len = 0;
+ // limit on what can be received with recv()
+ u32 buf_size = 20;
+ // temporary buffer to receive message data over a stream
+ char recv_buf[BUF_MAX] = {0};
+
+ nrecv = recv(clientfd, recv_buf, buf_size, 0);
+ if (nrecv == 0 || nrecv == -1)
+ return nrecv;
+
+ memcpy(&buf_len, recv_buf, sizeof(buf_len));
+
+ u32 i = 0;
+ while (nrecv < buf_len) {
+ // advance the copying by the amounts of bytes received each time
+ i = recv(clientfd, recv_buf + nrecv, buf_size, 0);
+ if (i == 0 || i == -1)
+ return nrecv;
+ nrecv += i;
+ }
+
+ memcpy(msg, recv_buf + sizeof(buf_len), MESSAGE_AUTHOR_LEN + MESSAGE_TIMESTAMP_LEN);
+ msg->text = recv_buf + sizeof(buf_len) + MESSAGE_AUTHOR_LEN + MESSAGE_TIMESTAMP_LEN;
+ msg->text_len = buf_len - sizeof(buf_len) - MESSAGE_AUTHOR_LEN - MESSAGE_TIMESTAMP_LEN;
+
+ return nrecv;
+}