aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPreston Pan <ret2pop@gmail.com>2025-01-30 21:02:42 -0800
committerPreston Pan <ret2pop@gmail.com>2025-01-30 21:02:42 -0800
commit3780f207f924f14734cb839fd015bd883fe52ff1 (patch)
treede13568dbf97ffe477943854bcb3ea6001b46cf8 /src
parentef9ab1fd141f4057d41f2d6ed8ab8d67c44894d5 (diff)
restructure projectHEADmain
Diffstat (limited to 'src')
-rw-r--r--src/common/better_string.c15
-rw-r--r--src/common/bsv.c33
-rw-r--r--src/common/hash_table.c19
-rw-r--r--src/common/protocol.c20
-rw-r--r--src/common/stdobj.c12
-rw-r--r--src/common/tsv.c33
-rw-r--r--src/include/better_string.h7
-rw-r--r--src/include/bsv.h21
-rw-r--r--src/include/hash_table.h31
-rw-r--r--src/include/list.h1
-rw-r--r--src/include/protocol.h98
-rw-r--r--src/include/stdobj.h8
-rw-r--r--src/include/tsv.h16
-rw-r--r--src/ramen/main.c102
-rw-r--r--src/ramen/protocol.c49
15 files changed, 321 insertions, 144 deletions
diff --git a/src/common/better_string.c b/src/common/better_string.c
index 7863da0..0788aab 100644
--- a/src/common/better_string.c
+++ b/src/common/better_string.c
@@ -1,6 +1,7 @@
#include "../include/better_string.h"
#include "../include/helpers.h"
#include <stdlib.h>
+#include <stdbool.h>
#include <string.h>
string_t *init_string(const char *src) {
@@ -17,6 +18,16 @@ string_t *init_string(const char *src) {
return s;
}
+string_t *string_copy(string_t *s) {
+ return init_string(s->buf);
+}
+
+char *string_copy_raw(string_t *s) {
+ char *raw = calloc(s->len + 1, sizeof(char));
+ strncpy(raw, s->buf, s->len);
+ return raw;
+}
+
void string_push(string_t *s, char c) {
if (s->len >= s->size - 3) {
s->size *= 2;
@@ -44,6 +55,10 @@ void string_concat(string_t *s1, string_t *s2) {
}
}
+bool string_cmp(string_t *s1, string_t *s2) {
+ return strcmp(s1->buf, s2->buf) == 0;
+}
+
void string_free(void *x) {
string_t *s = x;
diff --git a/src/common/bsv.c b/src/common/bsv.c
new file mode 100644
index 0000000..4a3d000
--- /dev/null
+++ b/src/common/bsv.c
@@ -0,0 +1,33 @@
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include "../include/tsv.h"
+#include "../include/helpers.h"
+#include "../include/better_string.h"
+
+tsv_t *init_tsv(char *source, char delim) {
+ tsv_t *tsv = safe_calloc(1, sizeof(tsv_t *));
+ tsv->source = source;
+ tsv->i = 0;
+ tsv->c = tsv->source[tsv->i];
+ tsv->delim = delim;
+ return tsv;
+}
+
+void tsv_move(tsv_t *tsv) {
+ if (tsv->c != '\0') {
+ tsv->i++;
+ tsv->c = tsv->source[tsv->i];
+ }
+}
+
+string_t *tsv_next(tsv_t *tsv) {
+ string_t *s = init_string(NULL);
+ bool escape = false;
+ while (tsv->c != tsv->delim && !escape) {
+ if (tsv->c == '\0') break;
+ string_push(s, tsv->c);
+ tsv_move(tsv);
+ }
+ return s;
+}
diff --git a/src/common/hash_table.c b/src/common/hash_table.c
index 6b4c014..caefae6 100644
--- a/src/common/hash_table.c
+++ b/src/common/hash_table.c
@@ -111,6 +111,17 @@ void ht_insert(ht_t *ht, char *key, void *value) {
list_push_back(bucket, init_pair(key, value));
}
+void *ht_modify(ht_t *ht, char *key, void *newval) {
+ void *oldval = ht_pop(ht, key);
+ ht_insert(ht, key, newval);
+ return oldval;
+}
+
+void ht_overwrite(ht_t *ht, char *key, void *newval, void (*freefunc)(void *)) {
+ void *oldval = ht_modify(ht, key, newval);
+ freefunc(oldval);
+}
+
void *ht_pop(ht_t *ht, char *key) {
unsigned long bn = hash(key) % ht->size;
list_t *bucket = ht->buckets[bn];
@@ -136,6 +147,14 @@ void ht_free(void *x, void (*freefunc)(void *)) {
free(ht);
}
+ht_t *init_map(size_t size) {
+ ht_t *ht = safe_calloc(1, sizeof(size));
+ size_t realsize = size == 0 ? DEFAULT_HT_SIZE : size;
+ ht->buckets = safe_calloc(realsize, sizeof(list_t *));
+ ht->is_map = true;
+ return ht;
+}
+
/* DJB2 hash function */
unsigned long hash(char *str) {
unsigned long hash = 5381;
diff --git a/src/common/protocol.c b/src/common/protocol.c
deleted file mode 100644
index 9be3bcf..0000000
--- a/src/common/protocol.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "../include/protocol.h"
-#include "../include/better_string.h"
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <time.h>
-
-string_t *date_str() {
- char dateStr[11];
- time_t t = time(NULL);
- struct tm *tm_info = localtime(&t);
-
- strftime(dateStr, sizeof(dateStr), "%d-%m-%Y", tm_info);
- return init_string(dateStr);
-}
-
-bool same_day(struct tm *date1, struct tm *date2) {
- return (date1->tm_year == date2->tm_year && date1->tm_mon == date2->tm_mon &&
- date1->tm_mday == date2->tm_mday);
-}
diff --git a/src/common/stdobj.c b/src/common/stdobj.c
new file mode 100644
index 0000000..c7657ed
--- /dev/null
+++ b/src/common/stdobj.c
@@ -0,0 +1,12 @@
+#include "../include/stdobj.h"
+#include "../include/better_string.h"
+#include <stdbool.h>
+#include <stdlib.h>
+
+bool array_in(array_t *a, string_t *s) {
+ for (int i = 0; i < a->size; i++) {
+ if (string_cmp(a->items[i], s))
+ return true;
+ }
+ return false;
+}
diff --git a/src/common/tsv.c b/src/common/tsv.c
index c06163b..290dc43 100644
--- a/src/common/tsv.c
+++ b/src/common/tsv.c
@@ -1,32 +1,33 @@
#include <stdlib.h>
#include <stdbool.h>
-#include "../include/tsv.h"
+#include "../include/bsv.h"
#include "../include/helpers.h"
#include "../include/better_string.h"
-tsv_t *init_tsv(char *source) {
- tsv_t *tsv = safe_calloc(1, sizeof(tsv_t *));
- tsv->source = source;
- tsv->i = 0;
- tsv->c = tsv->source[tsv->i];
- return tsv;
+bsv_t *init_bsv(char *source, char delim) {
+ bsv_t *bsv = safe_calloc(1, sizeof(bsv_t *));
+ bsv->source = source;
+ bsv->i = 0;
+ bsv->c = bsv->source[bsv->i];
+ bsv->delim = delim;
+ return bsv;
}
-void tsv_move(tsv_t *tsv) {
- if (tsv->c != '\0') {
- tsv->i++;
- tsv->c = tsv->source[tsv->i];
+void bsv_move(bsv_t *bsv) {
+ if (bsv->c != '\0') {
+ bsv->i++;
+ bsv->c = bsv->source[bsv->i];
}
}
-string_t *tsv_next(tsv_t *tsv) {
+string_t *bsv_next(bsv_t *bsv) {
string_t *s = init_string(NULL);
bool escape = false;
- while (tsv->c != '\t' && !escape) {
- if (tsv->c == '\0') break;
- string_push(s, tsv->c);
- tsv_move(tsv);
+ while (bsv->c != bsv->delim && !escape) {
+ if (bsv->c == '\0') break;
+ string_push(s, bsv->c);
+ bsv_move(bsv);
}
return s;
}
diff --git a/src/include/better_string.h b/src/include/better_string.h
index 0fdc8bd..4fc4315 100644
--- a/src/include/better_string.h
+++ b/src/include/better_string.h
@@ -2,6 +2,7 @@
#define STRING_H
#include <stdlib.h>
+#include <stdbool.h>
#define DEFAULT_STR_SIZE 10
typedef struct {
@@ -12,6 +13,10 @@ typedef struct {
string_t *init_string(const char *source);
+string_t *string_copy(string_t *s);
+
+char *string_copy_raw(string_t *s);
+
void string_push(string_t *s, char c);
void string_concat(string_t *s1, string_t *s2);
@@ -20,6 +25,8 @@ void string_concat_const(string_t *s, const char *src);
char string_pop(string_t *s);
+bool string_cmp(string_t *s1, string_t *s2);
+
void string_free(void *s);
#endif
diff --git a/src/include/bsv.h b/src/include/bsv.h
new file mode 100644
index 0000000..dd8206d
--- /dev/null
+++ b/src/include/bsv.h
@@ -0,0 +1,21 @@
+#ifndef BSV_H
+#define BSV_H
+
+#include "better_string.h"
+
+/*! @brief State for byte delimited values */
+typedef struct BSV_STRUCT {
+ /*! @brief the source bsv separated list */
+ char *source;
+ /*! @brief current index */
+ unsigned int i;
+ char c;
+ char delim;
+} bsv_t;
+
+/*! @brief Initializes memory for new bsv struct */
+bsv_t *init_bsv(char *source, char delim);
+
+/*! @brief get the next byte delimited token */
+string_t *bsv_next(bsv_t *bsv);
+#endif
diff --git a/src/include/hash_table.h b/src/include/hash_table.h
index 8f19635..55136ba 100644
--- a/src/include/hash_table.h
+++ b/src/include/hash_table.h
@@ -2,16 +2,21 @@
#define HASH_TABLE_H
#include "list.h"
#include <stdlib.h>
+
#define DEFAULT_HT_SIZE 500
typedef struct PAIR_STRUCT {
- char *key;
+ union {
+ char *key;
+ int ikey;
+ };
void *v;
} pair_t;
typedef struct {
list_t **buckets;
size_t size;
+ bool is_map;
} ht_t;
pair_t *init_pair(char *key, void *value);
@@ -22,10 +27,34 @@ void *bucket_pop(list_t *b, char *key);
void bucket_free(void *x, void (*freefunc)(void *));
+pair_t *init_long_pair(unsigned long key, void *value);
+
+void *bucket_get_by_long(list_t *b, unsigned long key);
+
+void *bucket_pop_by_long(list_t *b, unsigned long key);
+
+void bucket_free_with_long(void *x, void (*freefunc)(void *));
+
ht_t *init_ht(size_t size);
+ht_t *init_map(size_t size);
+
+void map_insert(ht_t *ht, unsigned long key, void *value);
+
+void *map_pop(ht_t *ht, unsigned long key);
+
+void *map_get(ht_t *ht, unsigned long key);
+
+void map_free(void *x);
+
void ht_insert(ht_t *ht, char *key, void *value);
+/*! @brief returns the old value, mutates ht state with new value */
+void *ht_modify(ht_t *ht, char *key, void *newval);
+
+/*! @brief overwrites old value with new value while freeing the old */
+void ht_overwrite(ht_t *ht, char *key, void *newval, void (*freefunc)(void *));
+
void *ht_pop(ht_t *ht, char *key);
void *ht_get(ht_t *ht, char *key);
diff --git a/src/include/list.h b/src/include/list.h
index 055106a..a9d1539 100644
--- a/src/include/list.h
+++ b/src/include/list.h
@@ -13,6 +13,7 @@ typedef struct {
size_t size;
node_t *head;
node_t *tail;
+ bool type;
} list_t;
node_t *init_node(void *item);
diff --git a/src/include/protocol.h b/src/include/protocol.h
index 31138c2..958ba26 100644
--- a/src/include/protocol.h
+++ b/src/include/protocol.h
@@ -1,9 +1,8 @@
#ifndef PROTOCOL_H
#define PROTOCOL_H
-
-#include <time.h>
-#include <stdio.h>
#include <stdbool.h>
+#include <stdio.h>
+#include <time.h>
#include "array.h"
#include "better_string.h"
@@ -21,48 +20,80 @@
#define KEYLEN 512
typedef struct {
- string_t *nick;
- bool is_guest;
- int fd;
-
- /* list of channels where user is in */
- array_t *channels;
- array_t *dms;
+ array_t *friends;
+ /* if NULL then guest */
+ unsigned char *passhash;
array_t *autojoin;
- unsigned char passhash[SHA256_DIGEST_LENGTH];
-} user_t;
+ array_t *dms;
+ string_t *name;
+} account_t;
typedef struct {
+ /*! @brief nick who sent the message */
string_t *nick;
+ /*! @brief message content */
string_t *msg;
+ /*! @brief Unix time */
time_t time;
} message_t;
-typedef struct {
- FILE *messages;
-
- user_t *admin;
+/*! @brief describes multiple user chats */
+typedef struct CHANNEL_STRUCT {
+ account_t *admin;
+ /*! @brief account_t array */
array_t *mods;
-
+ /*! @brief No guests */
bool registered_only;
-
- bool invite_only;
+ /*! @brief account_t array
+ * if set, allowed_users creates a private conversation with only
+ * these users
+ */
array_t *allowed_users;
-
+ /*! @brief Explicitly banned users, account_t array */
+ array_t *banned_users;
+ /*! @brief account_t array */
array_t *users;
-
- string_t *chan_name;
+ /*! @brief Description of channel can be set after creation */
string_t *desc;
+ /*! @brief message logs */
+ array_t *msgs;
} channel_t;
-typedef struct {
- user_t *user1;
- user_t *user2;
-
- struct tm *date;
- FILE *msgs;
+/*! @brief struct that contains DM */
+typedef struct DM_STRUCT {
+ account_t *src;
+ array_t *msgs;
} dm_t;
+typedef struct SERVER_STRUCT server_t;
+
+/*! @brief wrapper for server handler that conforms to C spec */
+typedef struct SFUNC_STRUCT {
+ /*! @brief In C spec, function pointers are not the same size as regular pointers */
+ void (*f)(server_t *, list_t *);
+} sfunc_t;
+
+/*! @brief Server state encapsulation */
+struct SERVER_STRUCT {
+ /*! @brief account name => user_t */
+ ht_t *accmap;
+ /*! @brief username => user_t */
+ ht_t *usermap;
+ /*! @brief account name => friends */
+ ht_t *friendmap;
+ /*! @brief fd (int) => string_t */
+ ht_t *fdmap;
+ /*! @brief channel name => channel_t */
+ ht_t *chanmap;
+
+ /*! @brief op name => sfunc_t */
+ ht_t *opmap;
+
+ struct pollfd *fds;
+ int nfds;
+ size_t fd_capacity;
+};
+
string_t *date_str();
bool same_day(struct tm *date1, struct tm *date2);
@@ -71,4 +102,15 @@ string_t *encode_chanstate(ht_t *chans);
string_t *encode_usersstate(ht_t *u);
+message_t *init_message(string_t *nick, string_t *msg, time_t time);
+
+void cop_ok(server_t *s, list_t *args);
+
+void cop_nop(server_t *s, list_t *args);
+
+server_t *init_server(size_t size);
+
+void server_addop(server_t *s, void (*sfunc)(server_t *s, list_t *args));
+
+void server_execop(server_t *s, list_t *stk);
#endif
diff --git a/src/include/stdobj.h b/src/include/stdobj.h
new file mode 100644
index 0000000..d755637
--- /dev/null
+++ b/src/include/stdobj.h
@@ -0,0 +1,8 @@
+#ifndef STDOBJ_H
+#define STDOBJ_H
+#include <stdbool.h>
+#include "array.h"
+#include "better_string.h"
+
+bool array_in(array_t *a, string_t *s);
+#endif
diff --git a/src/include/tsv.h b/src/include/tsv.h
deleted file mode 100644
index 57bb70a..0000000
--- a/src/include/tsv.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef TSV_H
-#define TSV_H
-
-#include "better_string.h"
-
-typedef struct {
- char *source;
- unsigned int i;
- char c;
-} tsv_t;
-
-tsv_t *init_tsv(char *source);
-
-string_t *tsv_next(tsv_t *tsv);
-
-#endif
diff --git a/src/ramen/main.c b/src/ramen/main.c
index 799a5b2..86a4d2c 100644
--- a/src/ramen/main.c
+++ b/src/ramen/main.c
@@ -12,39 +12,32 @@
#include <sys/time.h>
#include <unistd.h>
+#include "../include/stdobj.h"
#include "../include/better_string.h"
#include "../include/hash_table.h"
#include "../include/helpers.h"
#include "../include/list.h"
#include "../include/opcodes.h"
#include "../include/protocol.h"
-#include "../include/tsv.h"
+#include "../include/bsv.h"
#include "../include/opcodes.h"
int PORT = DEFAULT_PORT;
-int nfds = 1;
-struct pollfd fds[MAX_CONNECTIONS * 2];
-ht_t *CHAN;
-ht_t *USERS;
+server_t *STATE;
void handle_sigint(int sig) {
- for (int i = 0; i < nfds; i++) {
- if (fds[i].fd >= 0) {
- close(fds[i].fd);
- }
- }
exit(0);
}
list_t *tokenize_buf(char *buf) {
- tsv_t *tsv = init_tsv(buf);
- string_t *s = tsv_next(tsv);
+ bsv_t *bsv = init_bsv(buf, '\t');
+ string_t *s = bsv_next(bsv);
list_t *a = init_list();
while (s) {
list_push_back(a, s);
- s = tsv_next(tsv);
+ s = bsv_next(bsv);
}
return a;
@@ -59,9 +52,9 @@ void set_non_blocking(int sock) {
int main(int argc, char **argv) {
char buffer[MAX_BUFSIZE];
char res_buffer[MAX_BUFSIZE];
- struct pollfd *local_fds1 = fds;
- struct pollfd *local_fds2 = fds + MAX_CONNECTIONS;
- struct pollfd *local_fds = local_fds1;
+ STATE = init_server(1000);
+ struct pollfd *local_fds1 = STATE->fds;
+ struct pollfd *local_fds2 = STATE->fds + MAX_CONNECTIONS;
/* We start by initializing our net-related structs */
signal(SIGINT, handle_sigint);
@@ -99,9 +92,9 @@ int main(int argc, char **argv) {
connects, we know from the listening socket.
*/
- alloc_zero(fds, sizeof(fds));
- fds[0].fd = listen_sd;
- fds[0].events = POLLIN;
+ alloc_zero(STATE->fds, 2 * MAX_BUFSIZE * sizeof(struct pollfd));
+ STATE->fds[0].fd = listen_sd;
+ STATE->fds[0].events = POLLIN;
int timeout = 6000;
int sock_poll;
@@ -114,19 +107,19 @@ int main(int argc, char **argv) {
if an fd loses connection, we want to remove all -1's from the fds array
*/
- sock_poll = poll(local_fds, nfds, timeout);
+ sock_poll = poll(STATE->fds, STATE->nfds, timeout);
die_lz(sock_poll, "poll()");
- for (int i = 0; i < nfds; i++) {
- if (local_fds[i].revents == 0)
+ for (int i = 0; i < STATE->nfds; i++) {
+ if (STATE->fds[i].revents == 0)
continue;
- if (local_fds[i].revents != POLLIN) {
+ if (STATE->fds[i].revents != POLLIN) {
end_server = true;
break;
}
- if (local_fds[i].fd == listen_sd) {
+ if (STATE->fds[i].fd == listen_sd) {
printf("socket is readable\n");
int new_sd;
@@ -139,15 +132,18 @@ int main(int argc, char **argv) {
break;
}
- local_fds[nfds].fd = new_sd;
- local_fds[nfds].events = POLLIN;
- nfds++;
+ STATE->fds[STATE->nfds].fd = new_sd;
+ STATE->fds[STATE->nfds].events = POLLIN;
+ STATE->nfds++;
+ /* TODO: Create new user */
+
+ /* TODO: add new user to maps */
} while (new_sd >= 0);
} else {
bool close_conn = false;
int fd_recv;
int fd_send;
- fd_recv = recv(local_fds[i].fd, buffer, sizeof(buffer), 0);
+ fd_recv = recv(STATE->fds[i].fd, buffer, sizeof(buffer), 0);
if (fd_recv < 0 && errno != EWOULDBLOCK) {
perror("recv() failed");
@@ -157,29 +153,9 @@ int main(int argc, char **argv) {
close_conn = true;
} else {
list_t *tokens = tokenize_buf(buffer);
- string_t *opcode = list_pop_front(tokens);
- int op = encode_server_opcode(opcode->buf);
-
- switch (op) {
- case CO_NCK:
- break;
- case CO_JN:
- break;
- case CO_NOP:
- break;
- case CO_PST:
- break;
- case CO_DM:
- break;
- case CO_QT:
- break;
- case CO_LVE:
- break;
- default:
- break;
- }
-
- fd_send = send(local_fds[i].fd, buffer, fd_recv, 0);
+ server_execop(STATE, tokens);
+ /* TODO: correct reciept */
+ fd_send = send(STATE->fds[i].fd, buffer, fd_recv, 0);
if (fd_send < 0) {
perror("send()");
close_conn = true;
@@ -187,33 +163,33 @@ int main(int argc, char **argv) {
}
if (close_conn) {
- close(local_fds[i].fd);
- local_fds[i].fd = 0;
+ close(STATE->fds[i].fd);
+ STATE->fds[i].fd = 0;
compress_array = true;
}
}
}
if (compress_array) {
- int cur_nfds = nfds;
- nfds = 0;
+ int cur_nfds = STATE->nfds;
+ STATE->nfds = 0;
for (int i = 0; i < cur_nfds; i++) {
- if (local_fds[i].fd != 0) {
- local_fds2[nfds] = local_fds[i];
- nfds++;
+ if (STATE->fds[i].fd != 0) {
+ local_fds2[STATE->nfds] = STATE->fds[i];
+ STATE->nfds++;
}
}
local_fds1 = local_fds2;
- local_fds2 = local_fds;
- local_fds = local_fds1;
+ local_fds2 = STATE->fds;
+ STATE->fds = local_fds1;
alloc_zero(local_fds2, MAX_CONNECTIONS);
}
} while (!end_server);
- for (int i = 0; i < nfds; i++) {
- if (fds[i].fd >= 0) {
- close(fds[i].fd);
+ for (int i = 0; i < STATE->nfds; i++) {
+ if (STATE->fds[i].fd >= 0) {
+ close(STATE->fds[i].fd);
}
}
diff --git a/src/ramen/protocol.c b/src/ramen/protocol.c
new file mode 100644
index 0000000..eea5da2
--- /dev/null
+++ b/src/ramen/protocol.c
@@ -0,0 +1,49 @@
+#include "../include/protocol.h"
+#include "../include/better_string.h"
+#include "../include/helpers.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <time.h>
+
+extern int GUESTS;
+
+string_t *date_str() {
+ char dateStr[11];
+ time_t t = time(NULL);
+ struct tm *tm_info = localtime(&t);
+
+ strftime(dateStr, sizeof(dateStr), "%d-%m-%Y", tm_info);
+ return init_string(dateStr);
+}
+
+bool same_day(struct tm *date1, struct tm *date2) {
+ return (date1->tm_year == date2->tm_year && date1->tm_mon == date2->tm_mon &&
+ date1->tm_mday == date2->tm_mday);
+}
+
+user_t *init_user(int fd) {
+ char buf[20];
+ user_t *user = safe_calloc(1, sizeof(user_t));
+ string_t *nick = init_string("guest");
+ GUESTS++;
+ snprintf(buf, 20, "%d", GUESTS);
+ string_concat_const(nick, buf);
+ user->is_guest = true;
+ user->autojoin = NULL;
+ user->dms = NULL;
+ return user;
+}
+
+server_t *init_server(size_t size) {
+ server_t *s = safe_calloc(1, sizeof(server_t));
+ s->accmap = init_ht(size);
+ s->chanmap = init_ht(size);
+ s->fdmap = init_ht(size);
+ s->friendmap = init_ht(size);
+ s->opmap = init_ht(size);
+ s->usermap = init_ht(size);
+ s->fds = NULL;
+ s->nfds = 4096;
+ return s;
+}