protoverse

A metaverse protocol
git clone git://jb55.com/protoverse
Log | Files | Refs | README | LICENSE

commit e42fce43b9acf783a820abf6620802286329ee9c
parent d1c18cd0c344e524e9c76d4f4832f4ea7fbb4ad0
Author: William Casarin <jb55@jb55.com>
Date:   Sat,  8 Aug 2020 08:44:50 -0700

serve data wip

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Mclient.c | 6++----
Mio.h | 3+--
Mnet.c | 18+++++++++---------
Mnet.h | 17+++++++++++++----
Mprotoverse.c | 8+++++++-
Mserve.c | 110++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Mserve.h | 11++++++++++-
Mtest.c | 2+-
8 files changed, 147 insertions(+), 28 deletions(-)

diff --git a/client.c b/client.c @@ -44,14 +44,12 @@ int protoverse_connect(const char *server_ip_str, int port) packet.data.chat.message = "hello, world"; packet.data.chat.sender = 0xFFFFFF; - send_packet(sockfd, (struct sockaddr*)&server_addr, - sizeof(server_addr), &packet); + send_packet(sockfd, &server_addr, &packet); packet.type = PKT_FETCH_DATA; packet.data.fetch.path = "/some/room.space"; - send_packet(sockfd, (struct sockaddr*)&server_addr, - sizeof(server_addr), &packet); + send_packet(sockfd, &server_addr, &packet); return 1; } diff --git a/io.h b/io.h @@ -5,8 +5,7 @@ #include <stdio.h> int read_fd(FILE *fd, unsigned char *buf, size_t buflen, size_t *written); -int read_file(const char *filename, unsigned char *buf, size_t buflen, - size_t *written); +int read_file(const char *filename, unsigned char *buf, size_t buflen, size_t *written); int read_file_or_stdin(const char *filename, unsigned char *buf, size_t buflen, size_t *written); diff --git a/net.c b/net.c @@ -9,7 +9,7 @@ #include <stdio.h> #include <string.h> -static int push_fetch_packet(struct cursor *c, struct fetch_data_packet *fetch) +static int push_fetch_packet(struct cursor *c, struct fetch_packet *fetch) { return push_prefixed_str(c, fetch->path); } @@ -34,12 +34,12 @@ static int pull_chat_packet(struct cursor *c, struct cursor *buf, struct chat_pa return pull_prefixed_str(c, buf, &chat->message); } -static int pull_fetch_packet(struct cursor *c, struct cursor *buf, struct fetch_data_packet *fetch) +static int pull_fetch_packet(struct cursor *c, struct cursor *buf, struct fetch_packet *fetch) { return pull_prefixed_str(c, buf, &fetch->path); } -int send_packet(int sockfd, struct sockaddr *to_addr, int to_addr_len, struct packet *packet) +int send_packet(int sockfd, struct sockaddr_in *to_addr, struct packet *packet) { static unsigned char buf[0xFFFF]; int ok, len; @@ -47,7 +47,9 @@ int send_packet(int sockfd, struct sockaddr *to_addr, int to_addr_len, struct pa len = push_packet(buf, sizeof(buf), packet); if (!len) return 0; - ok = sendto(sockfd, buf, len, 0, to_addr, to_addr_len); + ok = sendto(sockfd, buf, len, 0, + (struct sockaddr*)to_addr, + sizeof(struct sockaddr_in)); if (ok != len) { printf("sendto: sent %d != packet_len %d\n", ok, len); @@ -57,15 +59,13 @@ int send_packet(int sockfd, struct sockaddr *to_addr, int to_addr_len, struct pa return ok; } -int recv_packet(int sockfd, struct cursor *buf, struct packet *packet) +int recv_packet(int sockfd, struct cursor *buf, struct sockaddr_in *from, struct packet *packet) { static unsigned char tmp[0xFFFF]; struct cursor tmp_cursor; - struct sockaddr addr; - socklen_t addrlen; - - recvfrom(sockfd, tmp, sizeof(tmp), 0, &addr, &addrlen); + socklen_t size; + recvfrom(sockfd, tmp, sizeof(tmp), 0, (struct sockaddr*)from, &size); make_cursor(tmp, tmp + sizeof(tmp), &tmp_cursor); return pull_packet(&tmp_cursor, buf, packet); diff --git a/net.h b/net.h @@ -3,25 +3,34 @@ #define PROTOVERSE_NET_H #include <sys/socket.h> +#include <arpa/inet.h> #include "cursor.h" enum packet_type { PKT_FETCH_DATA, + PKT_FETCH_DATA_RESPONSE, PKT_CHAT, PKT_NUM_TYPES, }; -struct fetch_data_packet { +struct fetch_packet { const char *path; }; +struct fetch_response_packet { + const char *path; + int data_len; + const unsigned char *data; +}; + struct chat_packet { int sender; const char *message; }; union packet_data { - struct fetch_data_packet fetch; + struct fetch_packet fetch; + struct fetch_response_packet fetch_response; struct chat_packet chat; }; @@ -30,8 +39,8 @@ struct packet { union packet_data data; }; -int send_packet(int fd, struct sockaddr *to_addr, int to_addr_len, struct packet *packet); -int recv_packet(int fd, struct cursor *buf, struct packet *packet); +int send_packet(int fd, struct sockaddr_in *to_addr, struct packet *packet); +int recv_packet(int sockfd, struct cursor *buf, struct sockaddr_in *from, struct packet *packet); int push_packet(unsigned char *buf, int bufsize, struct packet *packet); int pull_packet(struct cursor *c, struct cursor *buf, struct packet *packet); diff --git a/protoverse.c b/protoverse.c @@ -137,6 +137,7 @@ int main(int argc, const char *argv[]) const char *space; const char *cmd; struct parser parser; + struct protoverse_server server; u16 root; int ok; @@ -160,7 +161,12 @@ int main(int argc, const char *argv[]) return usage(); space = argv[2]; printf("serving protoverse on port 1988...\n"); - protoverse_serve("127.0.0.1", 1988); + + server.path = ""; + server.port = 1988; + server.bind = "127.0.0.1"; + + protoverse_serve(&server); } else if (streq(cmd, "client")) { protoverse_connect("127.0.0.1", 1988); } diff --git a/serve.c b/serve.c @@ -6,20 +6,117 @@ #include <stdio.h> #include <string.h> #include <errno.h> +#include <assert.h> #include "serve.h" #include "net.h" +#include "io.h" + +#define MAX_CACHED_FILES 12 int inet_aton(const char *cp, struct in_addr *inp); -int protoverse_serve(const char *bind_addr_str, int port) +struct file_cache { + const char *path; + int data_len; + unsigned char *dat; +}; + +static int load_data(struct cursor *buf, const char *path, + int *data_len, const unsigned char **data) +{ + /* TODO: better file cache */ + static struct file_cache file_cache[MAX_CACHED_FILES] = {0}; + static int cached_files = 0; + struct file_cache *cached_file; + int i, ok; + size_t written; + + for (i = 0; i < cached_files; i++) { + if (!strcmp(path, file_cache[i].path)) { + *data_len = file_cache[i].data_len; + *data = file_cache[i].dat; + return 1; + } + } + + ok = read_file(path, buf->p, buf->end - buf->p, &written); + if (!ok) return 0; + + assert(written <= (size_t)(buf->end - buf->p)); + + *data = buf->p; + + buf->p += written; + + if (cached_files + 1 > MAX_CACHED_FILES) + return 1; + + cached_file = &file_cache[cached_files++]; + cached_file->path = path; + cached_file->data_len = written; + cached_file->dat = buf->p - written; + + return 1; +} + +static int make_fetch_response(struct cursor *buf, + struct packet *response, + const char *path) +{ + int data_len, ok; + data_len = 0; + + ok = load_data(buf, path, &data_len, + &response->data.fetch_response.data); + + if (!ok) return 0; + + response->type = PKT_FETCH_DATA_RESPONSE; + response->data.fetch_response.path = path; + response->data.fetch_response.data_len = data_len; + + return 1; +} + +static int handle_packet(int sockfd, + struct cursor *buf, + struct sockaddr_in *from, + struct packet *packet) +{ + struct packet response; + int ok; + + print_packet(packet); + switch (packet->type) { + case PKT_CHAT: + return 0; + case PKT_FETCH_DATA: + ok = make_fetch_response(buf, &response, + packet->data.fetch.path); + if (!ok) return 0; + return send_packet(sockfd, from, &response); + + case PKT_FETCH_DATA_RESPONSE: + printf("todo: handle fetch response\n"); + return 0; + case PKT_NUM_TYPES: + return 0; + } + + return 0; +} + +int protoverse_serve(struct protoverse_server *server) { - static unsigned char buf_[1024]; + static unsigned char buf_[0xFFFF]; struct in_addr my_addr; struct sockaddr_in bind_addr; + struct sockaddr_in from; struct packet packet; struct cursor buf; + socklen_t from_addr_len; int err, ok, fd; @@ -30,13 +127,13 @@ int protoverse_serve(const char *bind_addr_str, int port) return 0; } - if (inet_aton(bind_addr_str, &my_addr) == 0) { + if (inet_aton(server->bind, &my_addr) == 0) { printf("inet_aton failed: %s\n", strerror(errno)); return 0; } bind_addr.sin_family = AF_INET; - bind_addr.sin_port = port == 0 || port == -1 ? 1988 : port; + bind_addr.sin_port = server->port == 0 || server->port == -1 ? 1988 : server->port; bind_addr.sin_addr = my_addr; err = bind(fd, (struct sockaddr*)&bind_addr, @@ -48,13 +145,14 @@ int protoverse_serve(const char *bind_addr_str, int port) } while (1) { - ok = recv_packet(fd, &buf, &packet); + ok = recv_packet(fd, &buf, &from, &packet); + assert(sizeof(from) == from_addr_len); if (!ok) { printf("malformed packet\n"); continue; } - print_packet(&packet); + handle_packet(fd, &buf, &from, &packet); } } diff --git a/serve.h b/serve.h @@ -2,6 +2,15 @@ #ifndef PROTOVERSE_SERVE_H #define PROTOVERSE_SERVE_H -int protoverse_serve(const char *bind, int port); +struct protoverse_server { + const char *bind; + int port; + + const char *path; +}; + + + +int protoverse_serve(struct protoverse_server *server); #endif diff --git a/test.c b/test.c @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) } packet.type = PKT_CHAT; - packet.data.chat.sender = 1; + packet.data.chat.sender = 0xFFFF; packet.data.chat.message = "hello there"; pushed[0] = push_packet(bufs[0], sizeof(bufs[0]), &packet);