diff options
author | Raymaekers Luca <raymaekers.luca@gmail.com> | 2024-10-19 15:31:51 +0200 |
---|---|---|
committer | Raymaekers Luca <raymaekers.luca@gmail.com> | 2024-10-19 15:31:51 +0200 |
commit | ff0aae89238f4d60267def24476e8b9f4cb596cf (patch) | |
tree | d8a646d04c0e2617bf279b387e5d11960906d340 | |
parent | 104dabefd62952f2d892a2dcdfb5700d9379ac00 (diff) |
add serialization to file code
-rw-r--r-- | client.c | 36 | ||||
-rw-r--r-- | common.c | 59 | ||||
-rw-r--r-- | common.h | 28 | ||||
-rw-r--r-- | config.h | 19 | ||||
-rw-r--r-- | server.c | 6 |
5 files changed, 113 insertions, 35 deletions
@@ -9,6 +9,7 @@ #define TB_IMPL #include "termbox2.h" // clang-format on +#include "common.h" #include "config.h" #include <arpa/inet.h> @@ -32,10 +33,9 @@ int prompt_offs_y = 3; static int serverfd; // Input message to be send struct message input = { - .buf = {0}, .author = USERNAME, .timestamp = {0}, - .buf_len = 0, + .len = 0, }; // All messages sent and received in order struct message *messages; @@ -76,7 +76,7 @@ void screen_welcome() if (lines_available - nmessages < 0) skip = nmessages - lines_available; for (msg_y = skip; msg_y < nmessages; msg_y++) { - tb_printf(0, msg_y - skip, 0, 0, "%s [%s]: %s", messages[msg_y].timestamp, messages[msg_y].author, messages[msg_y].buf); + tb_printf(0, msg_y - skip, 0, 0, "%s [%s]: %s", messages[msg_y].timestamp, messages[msg_y].author, messages[msg_y].text); } } @@ -84,10 +84,10 @@ void screen_welcome() void add_message(struct message msg) { int i; - for (i = 0; (messages[nmessages].buf[i] = msg.buf[i]); i++) + for (i = 0; (messages[nmessages].text[i] = msg.text[i]); i++) ; - messages[nmessages].buf[i] = 0; - messages[nmessages].buf_len = i; + messages[nmessages].text[i] = 0; + messages[nmessages].len = i; for (i = 0; (messages[nmessages].timestamp[i] = msg.timestamp[i]); i++) ; messages[nmessages].timestamp[i] = 0; @@ -174,11 +174,11 @@ int main(void) tb_print(global.cursor_x, global.cursor_y, 0, 0, " "); } tb_set_cursor(curs_offs_x, global.cursor_y); - input.buf_len = 0; + input.len = 0; break; // send message case TB_KEY_CTRL_M: - if (input.buf_len <= 0) + if (input.len <= 0) break; while (global.cursor_x > curs_offs_x) { global.cursor_x--; @@ -187,7 +187,7 @@ int main(void) tb_set_cursor(curs_offs_x, global.cursor_y); // zero terminate - input.buf[input.buf_len] = 0; + input.text[input.len] = 0; // print new message time(&now); @@ -200,7 +200,7 @@ int main(void) err_exit("Error while sending message."); // reset buffer - input.buf_len = 0; + input.len = 0; // update the screen // NOTE: kind of wasteful cause we should only display new message @@ -211,28 +211,28 @@ int main(void) // remove word case TB_KEY_CTRL_W: // Delete consecutive space - while (input.buf[input.buf_len - 1] == ' ' && global.cursor_x > curs_offs_x) { + while (input.text[input.len - 1] == ' ' && global.cursor_x > curs_offs_x) { global.cursor_x--; - input.buf_len--; + input.len--; tb_print(global.cursor_x, global.cursor_y, 0, 0, " "); } // Delete until next non-space - while (input.buf[input.buf_len - 1] != ' ' && global.cursor_x > curs_offs_x) { + while (input.text[input.len - 1] != ' ' && global.cursor_x > curs_offs_x) { global.cursor_x--; - input.buf_len--; + input.len--; tb_print(global.cursor_x, global.cursor_y, 0, 0, " "); } - input.buf[input.buf_len] = 0; + input.text[input.len] = 0; break; } - // append pressed character to input.buf + // append pressed character to input.text // TODO: wrap instead - if (ev.ch > 0 && input.buf_len < MSG_MAX && input.buf_len < global.width - 3 - 1) { + if (ev.ch > 0 && input.len < MSG_MAX && input.len < global.width - 3 - 1) { tb_printf(global.cursor_x, global.cursor_y, 0, 0, "%c", ev.ch); global.cursor_x++; - input.buf[input.buf_len++] = ev.ch; + input.text[input.len++] = ev.ch; } } else if (fds[FD_SERVER].revents & POLLIN) { @@ -1,9 +1,12 @@ +#include "common.h" #include "config.h" + #include <stdarg.h> +#include <stdint.h> +#include <stdio.h> #include <strings.h> #include <unistd.h> -// wrapper for write void writef(char *format, ...) { va_list args; @@ -18,3 +21,57 @@ void writef(char *format, ...) n++; write(0, buf, n); } + +u16 str_len(char *str) +{ + u16 i = 0; + while (str[i]) + i++; + return i; +} + +void str_cpy(char *to, char *from) +{ + while ((*to++ = *from++)) + ; +} + +u8 save_message(struct message *msg, FILE *f) +{ + u8 err = 0; + u16 len; + if (msg->text == NULL) { + len = 0; + msg->text = ""; // TODO: Error empty message should not be allowed. + } else { + len = str_len(msg->text); + } + + if (len == 0) + err = 1; + + fwrite(&msg->timestamp, sizeof(*msg->timestamp) * MSG_TIMESTAMP_LEN, 1, f); + fwrite(&msg->author, sizeof(*msg->author) * MSG_AUTHOR_LEN, 1, f); + fwrite(&len, sizeof(len), 1, f); + fputs(msg->text, f); + + return err; +} + +u8 load_message(struct message *msg, FILE *f) +{ + fread(msg, sizeof(*msg->timestamp) * MSG_TIMESTAMP_LEN + sizeof(*msg->author) * MSG_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 = ""; + return 1; + } + char txt[len]; + fgets(txt, len, f); + msg->text = txt; + + return 0; +} diff --git a/common.h b/common.h new file mode 100644 index 0000000..f737e2f --- /dev/null +++ b/common.h @@ -0,0 +1,28 @@ +#include <stdint.h> +#include <stdio.h> + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; + +// To serialize the text that could be arbitrary length the lenght is encoded after the author +// string and before the text. +struct message { + char timestamp[9]; // HH:MM:SS + char author[12]; + u16 len; + char *text; +}; + +// printf without buffering using write syscall, works when using sockets +void writef(char *format, ...); + +u16 str_len(char *str); +void str_cpy(char *to, char *from); + +// 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 save_message(struct 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 load_message(struct message *msg, FILE *f); @@ -1,20 +1,11 @@ -#include <stdarg.h> -#include <stdio.h> -#include <unistd.h> - #define PORT 9983 // max size for a message sent #define BUF_MAX 255 // max length of messages #define MSG_MAX 256 +// max length of author field +#define MSG_AUTHOR_LEN 12 +// max length of timestamp field +#define MSG_TIMESTAMP_LEN 9 // current user's name -#define USERNAME "unrtdqttr" - -void writef(char* format, ...); - -struct message { - char buf[MSG_MAX]; - int buf_len; - char timestamp[9]; // HH:MM:SS - char author[12]; -}; +#define USERNAME "Jef Koek" @@ -15,12 +15,14 @@ // - max y for new messages and make them scroll // - check resize event // - asynchronously receive/send a message +// - fix receiving messages with arbitrary text length // TODO: send message to all other clients // - implement different rooms // - implement history // - implement tls +#include "common.h" #include "config.h" #include <arpa/inet.h> #include <errno.h> @@ -33,6 +35,8 @@ #define MAX_CONNECTIONS 5 #define FD_MAX MAX_CONNECTIONS + 1 +static const char *filename = "history.dat"; + enum { FD_SERVER = 0 }; int serverfd; @@ -156,7 +160,6 @@ int main(void) printf("Retransmitted message to client %d.\n", j); } - // // TODO: check if bytes are correct // FILE *f = fopen("srv_recv.bin", "wb"); // fwrite(&msg_recv, sizeof(struct message), 1, f); @@ -164,7 +167,6 @@ int main(void) // // printf("written %lu bytes to srv_recv.bin\n", sizeof(msg_recv)); // return 0; - } } |