aboutsummaryrefslogtreecommitdiff
path: root/chatty.h
diff options
context:
space:
mode:
Diffstat (limited to 'chatty.h')
-rw-r--r--chatty.h220
1 files changed, 50 insertions, 170 deletions
diff --git a/chatty.h b/chatty.h
index 916ae4a..5337656 100644
--- a/chatty.h
+++ b/chatty.h
@@ -1,7 +1,8 @@
-#ifndef CHATTY_IMPL
+#ifndef CHATTY_H
#include <assert.h>
#include <locale.h>
+#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -11,6 +12,7 @@
#include <sys/mman.h>
#include <sys/socket.h>
#include <time.h>
+#include <unistd.h>
#include <wchar.h>
typedef uint8_t u8;
@@ -28,13 +30,54 @@ typedef enum {
// port for chatty
#define PORT 9983
+// max number of bytes that can be logged at once
+#define LOGMESSAGE_MAX 2048
+#define LOG_FMT "%H:%M:%S "
+#define LOG_LEN 10
#define Kilobytes(Value) ((Value) * 1024)
#define Megabytes(Value) (Kilobytes(Value) * 1024)
#define Gigabytes(Value) (Megabytes((u64)Value) * 1024)
#define Terabytes(Value) (Gigabytes((u64)Value) * 1024)
#define PAGESIZE 4096
+#define local_persist static
+#define global_variable
+#define internal static
+global_variable s32 logfd;
+
+u32
+wstrlen(u32* str)
+{
+ u32 i = 0;
+ while (str[i] != 0)
+ i++;
+ return i;
+}
+
+void
+loggingf(char* format, ...)
+{
+ char buf[LOGMESSAGE_MAX];
+ va_list args;
+ va_start(args, format);
+
+ vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+
+ int n = 0;
+ while (*(buf + n) != 0) n++;
+
+ u64 t = time(0);
+ u8 timestamp[LOG_LEN];
+ struct tm* ltime = localtime((time_t*)&t);
+ strftime((char*)timestamp, LOG_LEN, LOG_FMT, ltime);
+ write(logfd, timestamp, LOG_LEN - 1);
+
+ write(logfd, buf, n);
+}
+
+// Arena Allocator
struct Arena {
void* addr;
u64 size;
@@ -46,25 +89,20 @@ struct Arena {
#define PushStruct(arena, type) PushArray((arena), (type), 1)
#define PushStructZero(arena, type) PushArrayZero((arena), (type), 1)
-Arena*
-ArenaAlloc(u64 size)
+// Returns arena in case of success, or 0 if it failed to alllocate the memory
+void
+ArenaAlloc(Arena* arena, u64 size)
{
- Arena* arena = (Arena*)malloc(sizeof(Arena));
-
- arena->addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
- if (arena->addr == MAP_FAILED)
- return NULL;
+ arena->addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ assert(arena->addr != MAP_FAILED);
arena->pos = 0;
arena->size = size;
-
- return arena;
}
void
ArenaRelease(Arena* arena)
{
munmap(arena->addr, arena->size);
- free(arena);
}
void*
@@ -73,167 +111,9 @@ ArenaPush(Arena* arena, u64 size)
u8* mem;
mem = (u8*)arena->addr + arena->pos;
arena->pos += size;
+ assert(arena->pos <= arena->size);
return mem;
}
-/// Protocol
-// - every message has format Header + Message
-// TODO: authentication
-// TODO: encryption
-
-/// Protocol Header
-// - 2 bytes for version
-// - 1 byte for message type
-// - 16 bytes for checksum
-//
-// Text Message
-// - 12 bytes for the author
-// - 8 bytes for the timestamp
-// - 2 bytes for the text length
-// - x*4 bytes for the text
-//
-// History Message
-// This message is for requesting messages sent after a timestamp.
-// - 8 bytes for the timestamp
-
-/// Naming convention
-// Messages end with the Message suffix (eg. TextMessag, HistoryMessage)
-// A function that is coupled to a type works like
-// <noun><type> eg. (printTextMessage, formatTimestamp)
-
-#define PROTOCOL_VERSION 0
-
-typedef struct {
- u16 version;
- u8 type;
-} HeaderMessage;
-
-enum { HEADER_TYPE_TEXT = 0,
- HEADER_TYPE_HISTORY,
- HEADER_TYPE_PRESENCE };
-#define HEADER_TEXTMESSAGE {.version = PROTOCOL_VERSION, .type = HEADER_TYPE_TEXT};
-#define HEADER_HISTORYMESSAGE {.version = PROTOCOL_VERSION, .type = HEADER_TYPE_HISTORY};
-#define HEADER_PRESENCEMESSAGE {.version = PROTOCOL_VERSION, .type = HEADER_TYPE_PRESENCE};
-
-// Size of author string including null terminator
-#define AUTHOR_LEN 13
-// Size of formatted timestamp string including null terminator
-#define TIMESTAMP_LEN 9
-
-typedef struct {
- u8 checksum[16];
- u8 author[AUTHOR_LEN];
- u64 timestamp;
- u16 len; // including null terminator
- u32* text; // placeholder for indexing
- // TODO: 0-length field?
-} TextMessage;
-
-// Size of TextMessage without text pointer, used when receiving the message over a stream
-#define TEXTMESSAGE_TEXT_SIZE(m) (m.len * sizeof(*m.text))
-#define TEXTMESSAGE_SIZE (sizeof(TextMessage) - sizeof(u32*))
-
-typedef struct {
- u64 timestamp;
-} HistoryMessage;
-
-typedef struct {
- u8 author[AUTHOR_LEN];
- u8 type;
-} PresenceMessage;
-enum { PRESENCE_TYPE_CONNECTED = 0,
- PRESENCE_TYPE_DISCONNECTED };
-
-// Returns string for type byte in HeaderMessage
-u8*
-headerTypeString(u8 type)
-{
- switch (type) {
- case HEADER_TYPE_TEXT: return (u8*)"TextMessage";
- case HEADER_TYPE_HISTORY: return (u8*)"HistoryMessage";
- case HEADER_TYPE_PRESENCE: return (u8*)"PresenceMessage";
- default: return (u8*)"Unknown";
- }
-}
-
-u8*
-presenceTypeString(u8 type)
-{
- switch (type) {
- case PRESENCE_TYPE_CONNECTED: return (u8*)"connected";
- case PRESENCE_TYPE_DISCONNECTED: return (u8*)"disconnected";
- default: return (u8*)"Unknown";
- }
-}
-
-// from Tsoding video on minicel (https://youtu.be/HCAgvKQDJng?t=4546)
-// sv(https://github.com/tsoding/sv)
-#define PH_FMT "header: v%d %s(%d)"
-#define PH_ARG(header) header.version, headerTypeString(header.type), header.type
-
-void
-formatTimestamp(u8 tmsp[TIMESTAMP_LEN], u64 t)
-{
- struct tm* ltime;
- ltime = localtime((time_t*)&t);
- strftime((char*)tmsp, TIMESTAMP_LEN, "%H:%M:%S", ltime);
-}
-
-void
-printTextMessage(TextMessage* message, u8 wide)
-{
- u8 timestamp[TIMESTAMP_LEN] = {0};
- formatTimestamp(timestamp, message->timestamp);
-
- assert(setlocale(LC_ALL, "") != NULL);
-
- if (wide)
- wprintf(L"TextMessage: %s [%s] %ls\n", timestamp, message->author, (wchar_t*)&message->text);
- else {
- u8 str[message->len];
- wcstombs((char*)str, (wchar_t*)&message->text, message->len * sizeof(*message->text));
- printf("TextMessage: %s [%s] (%d)%s\n", timestamp, message->author, message->len, str);
- }
-}
-
-// Receive a message from fd and store it to the msgsArena,
-// if dest is not NULL point it to the new message created on msgsArena
-// Returns the number of bytes received
-u32
-recvTextMessage(Arena* msgsArena, u32 fd, TextMessage** dest)
-{
- s32 nrecv = 0;
-
- TextMessage* message = ArenaPush(msgsArena, TEXTMESSAGE_SIZE);
- if (dest != NULL)
- *dest = message;
-
- // Receive everything but the text so we can know the text's size and act accordingly
- nrecv = recv(fd, message, TEXTMESSAGE_SIZE, 0);
- assert(nrecv != -1);
- assert(nrecv == TEXTMESSAGE_SIZE);
-
- nrecv = 0;
-
- // Allocate memory for text and receive in that memory
- u32 text_size = message->len * sizeof(*message->text);
- ArenaPush(msgsArena, text_size);
-
- nrecv = recv(fd, (u8*)&message->text, text_size, 0);
- assert(nrecv != -1);
- assert(nrecv == message->len * sizeof(*message->text));
-
- return TEXTMESSAGE_SIZE + nrecv;
-}
-
-u32
-wstrlen(u32* str)
-{
- u32 i = 0;
- while (str[i] != 0)
- i++;
- return i;
-}
-
#endif
#define CHATTY_H