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:
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);