protoverse

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

serve.c (3027B)


      1 
      2 #include <sys/types.h>
      3 #include <sys/socket.h>
      4 #include <netinet/in.h>
      5 #include <arpa/inet.h>
      6 #include <stdio.h>
      7 #include <string.h>
      8 #include <errno.h>
      9 #include <assert.h>
     10 #include <stdlib.h>
     11 
     12 #include "serve.h"
     13 #include "entity.h"
     14 #include "net.h"
     15 #include "io.h"
     16 
     17 #define MAX_CACHED_FILES 12
     18 
     19 int inet_aton(const char *cp, struct in_addr *inp);
     20 
     21 struct file_cache {
     22 	const char *path;
     23 	int data_len;
     24 	unsigned char *dat;
     25 };
     26 
     27 static int load_data(struct cursor *buf, const char *path,
     28 		     int *data_len, unsigned char **data)
     29 {
     30 	int ok;
     31 
     32 	ok = read_file(path, buf->p, buf->end - buf->p, data_len);
     33 	if (!ok) return 0;
     34 
     35 	assert(*data_len <= buf->end - buf->p);
     36 
     37 	*data = buf->p;
     38 
     39 	buf->p += *data_len;
     40 
     41 	return 1;
     42 }
     43 
     44 static int make_fetch_response(struct cursor *buf,
     45 			       struct packet *response,
     46 			       const char *path)
     47 {
     48 	int data_len, ok;
     49 	data_len = 0;
     50 
     51 	ok = load_data(buf, path, &data_len,
     52 		       &response->data.fetch_response.data);
     53 
     54 	/* printf("load_data %d ok %d\n", data_len, ok); */
     55 
     56 	if (!ok) return 0;
     57 
     58 	response->type = PKT_FETCH_DATA_RESPONSE;
     59 	response->data.fetch_response.path = path;
     60 	response->data.fetch_response.data_len = data_len;
     61 
     62 	return 1;
     63 }
     64 
     65 static int handle_packet(int sockfd,
     66 			 struct env *env,
     67 			 struct cursor *buf,
     68 			 struct sockaddr_in *from,
     69 			 struct packet *packet)
     70 {
     71 	struct packet response;
     72 	int ok;
     73 
     74 	print_packet(env, packet);
     75 	switch (packet->type) {
     76 	case PKT_MESSAGE:
     77 		return send_packet(sockfd, from, packet);
     78 	case PKT_FETCH_DATA:
     79 		ok = make_fetch_response(buf, &response,
     80 					 packet->data.fetch.path);
     81 		if (!ok) return 0;
     82 		return send_packet(sockfd, from, &response);
     83 	case PKT_FETCH_DATA_RESPONSE:
     84 		printf("todo: handle fetch response\n");
     85 		return 0;
     86 	case PKT_NUM_TYPES:
     87 		return 0;
     88 	}
     89 
     90 	return 0;
     91 }
     92 
     93 
     94 int protoverse_serve(struct protoverse_server *server)
     95 {
     96         #define FILEBUF_SIZE 31457280
     97 	static unsigned char *buf_;
     98 
     99 	struct in_addr my_addr;
    100 	struct sockaddr_in bind_addr;
    101 	struct sockaddr_in from;
    102 	struct packet packet;
    103 	struct cursor buf;
    104 	/* socklen_t from_addr_len; */
    105 
    106 	int err, ok, fd;
    107 
    108 	buf_ = malloc(FILEBUF_SIZE);
    109 	make_cursor(buf_, buf_ + FILEBUF_SIZE, &buf);
    110 
    111 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
    112 		printf("socket creation failed: %s\n", strerror(errno));
    113 		return 0;
    114 	}
    115 
    116 	if (inet_aton(server->bind, &my_addr) == 0) {
    117 		printf("inet_aton failed: %s\n", strerror(errno));
    118 		return 0;
    119 	}
    120 
    121 	bind_addr.sin_family = AF_INET;
    122 	bind_addr.sin_port = server->port == 0 || server->port == -1 ? 1988 : server->port;
    123 	bind_addr.sin_addr = my_addr;
    124 
    125 	err = bind(fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) == -1;
    126 
    127 	if (err) {
    128 		printf("bind failed: %s\n", strerror(errno));
    129 		return 0;
    130 	}
    131 
    132 	while (1) {
    133 		ok = recv_packet(fd, &buf, &from, &packet);
    134 		if (!ok) {
    135 			printf("malformed packet\n");
    136 			continue;
    137 		}
    138 
    139 		ok = handle_packet(fd, &server->env, &buf, &from, &packet);
    140 		if (!ok) {
    141 			printf("handle packet failed for ");
    142 			print_packet(&server->env, &packet);
    143 		}
    144 
    145 		buf.p = buf.start;
    146 	}
    147 
    148 	free(buf_);
    149 }