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 }