From 4d03f397dfc352a958344dcd9454a4d904242d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Sun, 7 Jul 2019 19:37:51 +0300 Subject: [PATCH] Handle communicating message IDs --- ethermess.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/ethermess.c b/ethermess.c index 04beaae..954955c 100644 --- a/ethermess.c +++ b/ethermess.c @@ -24,6 +24,8 @@ #define EMT_SPEAK_VERSION 0 #define EMT_STATUS_REQUEST 1 #define EMT_STATUS 2 +#define EMT_MSGID_REQUEST 3 +#define EMT_MSGID 4 #define EMS_AVAILABLE 0 #define EMS_UNAVAILABLE 1 @@ -39,6 +41,45 @@ unsigned char own_status = EMS_AVAILABLE; unsigned char own_nick[256] = {'n', 'o', 'r', 't', 't', 'i'}; unsigned char own_nick_length = 6; +bool own_message_queued = false; +unsigned char own_message_destination_mac[6]; +unsigned char own_message[1500 - 2 - 2 - 2]; +size_t own_message_length = 0; + +struct msgid_cache_entry { + unsigned char other_mac[6]; + bool know_send; + bool know_receive; + uint16_t next_send; + uint16_t next_receive; +}; + +struct msgid_cache_entry msgid_cache[256]; +ssize_t msgid_cache_fill = 0; +unsigned char next_slot = 0; + +ssize_t msgid_cache_lookup(const unsigned char mac[6]) { + for (ssize_t i = 0; i < msgid_cache_fill; i++) { + if (memcmp(msgid_cache[i].other_mac, mac, 6) == 0) { + // Found it + return i; + } + } + + // Did not find it + return -1; +} + +ssize_t msgid_cache_add(const unsigned char mac[6]) { + ssize_t index = next_slot++; + + memcpy(msgid_cache[index].other_mac, mac, sizeof(msgid_cache[index].other_mac)); + msgid_cache[index].know_send = false; + msgid_cache[index].know_receive = false; + + return index; +} + char hexify(int nybble) { assert(0 <= nybble && nybble <= 16); return "0123456789abcdef"[nybble]; @@ -129,6 +170,44 @@ void send_status(const unsigned char destination[6]) { send_frame(frame, sizeof(frame)); } +void send_msgid_request(const unsigned char destination[6]) { + unsigned char frame[14 + 2]; + + write_headers(frame, destination, EMT_MSGID_REQUEST); + + send_frame(frame, sizeof(frame)); +} + +void send_msgid(const unsigned char destination[6]) { + unsigned char frame[14 + 2 + 2]; + + write_headers(frame, destination, EMT_MSGID); + + // Look up destination in the ID cache + ssize_t cache_index = msgid_cache_lookup(destination); + if (cache_index == -1) { + // Not in the cache + // Create a new entry + cache_index = msgid_cache_add(destination); + } + + if (!msgid_cache[cache_index].know_receive) { + // We don't have receive ID stored in the cache + // In that case, start from 0 + // TODO: Make it random instead + msgid_cache[cache_index].next_receive = 0; + msgid_cache[cache_index].know_receive = true; + } + + // Message ID of next message we're waiting to receive + uint16_t msgid = msgid_cache[cache_index].next_receive; + + frame[16] = msgid >> 8; + frame[17] = msgid & 0xff; + + send_frame(frame, sizeof(frame)); +} + void read_command(void) { int cmd = getchar(); if (cmd == EOF) { @@ -139,6 +218,8 @@ void read_command(void) { running = false; } else if (cmd == 's') { send_status_request(broadcast_mac); + } else if (cmd == 'i') { + send_msgid_request(broadcast_mac); } else if (cmd == '\n') { // Ignore } else { @@ -172,6 +253,8 @@ void handle_status(const unsigned char source_mac[6], const unsigned char *data, unsigned char nick[256]; memcpy(nick, &data[2], nick_length); + // TODO: check that nick is valid utf-8 with no control chars + char mac[18]; format_mac(source_mac, mac); @@ -205,6 +288,38 @@ void handle_status(const unsigned char source_mac[6], const unsigned char *data, } } +void handle_msgid(const unsigned char source_mac[6], const unsigned char *data, size_t data_length) { + if (data_length < 2) { + // Too short + fprintf(stderr, "Data too short: %zu\n", data_length); // debg + return; + } + + uint16_t msgid = data[0] << 8 | data[1]; + + ssize_t cache_index = msgid_cache_lookup(source_mac); + if (cache_index == -1) { + // Not in the cache, so add it there + cache_index = msgid_cache_add(source_mac); + } + + msgid_cache[cache_index].next_send = msgid; + msgid_cache[cache_index].know_send = true; + + char mac[18]; + format_mac(source_mac, mac); + + errno = 0; + if (printf("%s awaits message ID %" PRIu16 "\n", mac, msgid_cache[cache_index].next_send) == 0) { + err(1, "printf"); + } + + errno = 0; + if (fflush(stdout) == EOF) { + err(1, "fflush"); + } +} + void process_frame(void) { unsigned char frame[1518]; // Largest a 802.3 frame can be without FCS @@ -261,9 +376,19 @@ void process_frame(void) { handle_status(source_mac, &frame[16], packet_length - 16); break; + case EMT_MSGID_REQUEST: + send_msgid(source_mac); + break; + + case EMT_MSGID: + handle_msgid(source_mac, &frame[16], packet_length - 16); + break; + default: fprintf(stderr, "Ignoring packet of type %i\n", packet_type); } + + // TODO: Check that padding, if any, is all zeroes } void eventloop(void) { @@ -367,6 +492,9 @@ int main(int argc, char **argv) { format_mac(own_mac, own_mac_str); fprintf(stderr, "%s\n", own_mac_str); + // Initialize the message id cache + memset(msgid_cache, 0, sizeof(msgid_cache)); + // Request status from everyone, so that we can get an idea of who is on the network send_status_request(broadcast_mac);