protoverse

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

net.c (6955B)


      1 
      2 #include "net.h"
      3 #include "cursor.h"
      4 #include "util.h"
      5 #include "varint.h"
      6 #include "env.h"
      7 #include "entity.h"
      8 
      9 #include <sys/types.h>
     10 #include <assert.h>
     11 #include <errno.h>
     12 #include <netinet/in.h>
     13 #include <arpa/inet.h>
     14 #include <stdio.h>
     15 #include <string.h>
     16 
     17 static int push_fetch_response_packet(struct cursor *c,
     18 		struct fetch_response_packet *resp)
     19 {
     20 	int ok;
     21 	ok = push_prefixed_str(c, resp->path);
     22 	if (!ok) return 0;
     23 	ok = push_varint(c, resp->data_len);
     24 	if (!ok) return 0;
     25 	return cursor_push(c, resp->data, resp->data_len);
     26 }
     27 
     28 static int pull_fetch_response_packet(struct cursor *c, struct cursor *buf,
     29 				      struct fetch_response_packet *resp)
     30 {
     31 	int ok;
     32 	ok = pull_prefixed_str(c, buf, &resp->path);
     33 	if (!ok) return 0;
     34 	ok = pull_varint(c, &resp->data_len);
     35 	if (!ok) return 0;
     36 	return pull_data_into_cursor(c, buf, &resp->data, resp->data_len);
     37 }
     38 
     39 static int push_fetch_packet(struct cursor *c, struct fetch_packet *fetch)
     40 {
     41 	return push_prefixed_str(c, fetch->path);
     42 }
     43 
     44 /* TODO: CPU-independent encoding */
     45 static int push_message_packet(struct cursor *c, struct message_packet *msg)
     46 {
     47 	int ok;
     48 	ok = push_varint(c, msg->type);
     49 	if (!ok) return 0;
     50 
     51 	ok = push_varint(c, msg->receiver);
     52 	if (!ok) return 0;
     53 
     54 	return push_prefixed_str(c, msg->message);
     55 }
     56 
     57 static int pull_message_packet(struct cursor *c, struct cursor *buf, struct message_packet *msg)
     58 {
     59 	int ok;
     60 
     61 	ok = pull_varint(c, &msg->type);
     62 	if (!ok) return 0;
     63 
     64 	ok = pull_varint(c, &msg->receiver);
     65 	if (!ok) return 0;
     66 
     67 	return pull_prefixed_str(c, buf, &msg->message);
     68 }
     69 
     70 static int pull_fetch_packet(struct cursor *c, struct cursor *buf, struct fetch_packet *fetch)
     71 {
     72 	return pull_prefixed_str(c, buf, &fetch->path);
     73 }
     74 
     75 
     76 int send_packet(int sockfd, struct sockaddr_in *to_addr, struct packet *packet)
     77 {
     78 	static unsigned char buf[0xFFFF];
     79 	int ok, len;
     80 
     81 	len = push_packet(buf, sizeof(buf), packet);
     82 	if (!len) return 0;
     83 
     84 	ok = sendto(sockfd, buf, len, 0, (struct sockaddr*)to_addr,
     85 			sizeof(*to_addr));
     86 
     87 	if (ok != len) {
     88 		printf("sendto: sent %d != packet_len %d - %s\n", ok, len,
     89 				strerror(errno));
     90 		return 0;
     91 	}
     92 
     93 	return ok;
     94 }
     95 
     96 int recv_packet(int sockfd, struct cursor *buf, struct sockaddr_in *from, struct packet *packet)
     97 {
     98 	static unsigned char tmp[0xFFFF];
     99 	struct cursor tmp_cursor;
    100 	socklen_t size = sizeof(*from);
    101 	int bytes;
    102 
    103 	bytes = recvfrom(sockfd, tmp, sizeof(tmp), 0, (struct sockaddr*)from,
    104 			&size);
    105 	assert(size == sizeof(*from));
    106 	make_cursor(tmp, tmp + sizeof(tmp), &tmp_cursor);
    107 
    108 	return pull_packet(&tmp_cursor, buf, packet, bytes);
    109 }
    110 
    111 static int push_envelope(struct cursor *cursor, enum packet_type type, int len)
    112 {
    113 	int ok;
    114 	int env_len;
    115 
    116 	ok = push_varint(cursor, (int)type);
    117 	if (!ok) return 0;
    118 
    119 	env_len = ok;
    120 
    121 	ok = push_varint(cursor, len);
    122 
    123 	env_len += ok;
    124 
    125 	return env_len;
    126 }
    127 
    128 static int pull_envelope(struct cursor *cursor, enum packet_type *type,
    129 		int *len)
    130 {
    131 	int ok, env_len;
    132 	ok = pull_varint(cursor, (int*)type);
    133 	if (!ok) return 0;
    134 
    135 	if (*type >= PKT_NUM_TYPES)
    136 		return 0;
    137 
    138 	env_len = ok;
    139 
    140 	ok = pull_varint(cursor, len);
    141 	if (!ok) return 0;
    142 
    143 	env_len += ok;
    144 
    145 	return env_len;
    146 }
    147 
    148 static int push_packet_data(struct cursor *c, struct packet *packet)
    149 {
    150 	switch (packet->type) {
    151 	case PKT_FETCH_DATA:
    152 		return push_fetch_packet(c, &packet->data.fetch);
    153 	case PKT_FETCH_DATA_RESPONSE:
    154 		return push_fetch_response_packet(c,
    155 				&packet->data.fetch_response);
    156 	case PKT_MESSAGE:
    157 		return push_message_packet(c, &packet->data.message);
    158 	case PKT_NUM_TYPES:
    159 		return 0;
    160 	}
    161 
    162 	return 0;
    163 }
    164 
    165 int push_packet(unsigned char *buf, int bufsize, struct packet *packet)
    166 {
    167 	struct cursor cursor;
    168 	struct cursor envelope_cursor;
    169 	int len, ok, envelope_size;
    170 	envelope_size = VARINT_MAX_LEN * 2;
    171 
    172 	make_cursor(buf, buf + envelope_size, &envelope_cursor);
    173 	make_cursor(buf + envelope_size, buf + bufsize, &cursor);
    174 
    175 	ok = push_packet_data(&cursor, packet);
    176 	if (!ok) return 0;
    177 
    178 	len = cursor.p - cursor.start;
    179 
    180 	ok = push_envelope(&envelope_cursor, packet->type, len);
    181 	if (!ok) return 0;
    182 
    183 	memmove(buf + ok, cursor.start, len);
    184 
    185 	return len + ok;
    186 }
    187 
    188 
    189 static int pull_packet_data(struct cursor *c, struct cursor *buf,
    190 			    struct packet *packet, int len)
    191 {
    192 	(void)c;
    193 	(void)len;
    194 	switch (packet->type) {
    195 	case PKT_FETCH_DATA:
    196 		return pull_fetch_packet(c, buf, &packet->data.fetch);
    197 	case PKT_FETCH_DATA_RESPONSE:
    198 		return pull_fetch_response_packet(c, buf,
    199 						  &packet->data.fetch_response);
    200 	case PKT_MESSAGE:
    201 		return pull_message_packet(c, buf, &packet->data.message);
    202 	case PKT_NUM_TYPES:
    203 		break;
    204 	}
    205 
    206 	return 0;
    207 }
    208 
    209 int pull_packet(struct cursor *c, struct cursor *buf, struct packet *packet,
    210 		int received_bytes)
    211 {
    212 	int ok, env_size, len, capacity_left;
    213 
    214 	env_size = pull_envelope(c, &packet->type, &len);
    215 	if (!env_size) return 0;
    216 
    217 	if (len + env_size != received_bytes) {
    218 		printf("invalid packet size. expected %d, got %d\n", len+env_size,
    219 		       received_bytes);
    220 		return 0;
    221 	}
    222 
    223 	capacity_left = cursor_remaining_capacity(c) - 1;
    224 	if (len > capacity_left) {
    225 		printf("sanity: packet larger (%d)"
    226 		       " than remaining buffer size: %d", len, capacity_left);
    227 		return 0;
    228 	}
    229 
    230 	ok = pull_packet_data(c, buf, packet, len);
    231 	if (!ok) return 0;
    232 
    233 	return len + env_size;
    234 }
    235 
    236 static int packet_message_eq(struct message_packet *a, struct message_packet *b)
    237 {
    238 	/* fail if either is 0 but not both 0 or both not 0 */
    239 	if (!a->message ^ !b->message)
    240 		return 0;
    241 
    242 	return !strcmp(a->message, b->message);
    243 }
    244 
    245 static int packet_fetch_eq(struct fetch_packet *a, struct fetch_packet *b)
    246 {
    247 	if (!a->path ^ !b->path)
    248 		return 0;
    249 
    250 	return !strcmp(a->path, b->path);
    251 }
    252 
    253 static int packet_fetch_resp_eq(struct fetch_response_packet *a,
    254 				struct fetch_response_packet *b)
    255 {
    256 	if (!a->path ^ !b->path)
    257 		return 0;
    258 
    259 	return memeq(a->data, a->data_len, b->data, b->data_len);
    260 }
    261 
    262 int packet_eq(struct packet *a, struct packet *b)
    263 {
    264 	if (a->type != b->type)
    265 		return 0;
    266 
    267 	switch (a->type) {
    268 	case PKT_MESSAGE:
    269 		return packet_message_eq(&a->data.message, &b->data.message);
    270 	case PKT_FETCH_DATA:
    271 		return packet_fetch_eq(&a->data.fetch, &b->data.fetch);
    272 	case PKT_FETCH_DATA_RESPONSE:
    273 		return packet_fetch_resp_eq(&a->data.fetch_response,
    274 					    &b->data.fetch_response);
    275 	case PKT_NUM_TYPES:
    276 		return 0;
    277 	}
    278 
    279 	return 0;
    280 }
    281 
    282 static void print_message_packet(struct env *env, struct message_packet *msg)
    283 {
    284 	/* eventually print entity data from environment */
    285 	(void)env;
    286 	printf("(message (to %d) (msg '%s'))\n", msg->receiver,
    287 			msg->message);
    288 }
    289 
    290 void print_packet(struct env *env, struct packet *packet)
    291 {
    292 	switch (packet->type) {
    293 	case PKT_MESSAGE:
    294 		print_message_packet(env, &packet->data.message);
    295 		return;
    296 	case PKT_FETCH_DATA_RESPONSE:
    297 		printf("(fetch-resp (path \"%s\") (data %d))\n",
    298 			packet->data.fetch_response.path,
    299 			packet->data.fetch_response.data_len);
    300 		return;
    301 	case PKT_FETCH_DATA:
    302 		printf("(fetch (path \"%s\"))\n",
    303 		       packet->data.fetch.path);
    304 		return;
    305 	case PKT_NUM_TYPES:
    306 		break;
    307 	}
    308 
    309 	printf("(unknown)\n");
    310 }