Handle communicating message IDs

This commit is contained in:
Juhani Krekelä 2019-07-07 19:37:51 +03:00
parent e51066ebb8
commit 4d03f397df
1 changed files with 128 additions and 0 deletions

View File

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