Handle communicating message IDs
This commit is contained in:
parent
e51066ebb8
commit
4d03f397df
1 changed files with 128 additions and 0 deletions
128
ethermess.c
128
ethermess.c
|
@ -24,6 +24,8 @@
|
||||||
#define EMT_SPEAK_VERSION 0
|
#define EMT_SPEAK_VERSION 0
|
||||||
#define EMT_STATUS_REQUEST 1
|
#define EMT_STATUS_REQUEST 1
|
||||||
#define EMT_STATUS 2
|
#define EMT_STATUS 2
|
||||||
|
#define EMT_MSGID_REQUEST 3
|
||||||
|
#define EMT_MSGID 4
|
||||||
|
|
||||||
#define EMS_AVAILABLE 0
|
#define EMS_AVAILABLE 0
|
||||||
#define EMS_UNAVAILABLE 1
|
#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[256] = {'n', 'o', 'r', 't', 't', 'i'};
|
||||||
unsigned char own_nick_length = 6;
|
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) {
|
char hexify(int nybble) {
|
||||||
assert(0 <= nybble && nybble <= 16);
|
assert(0 <= nybble && nybble <= 16);
|
||||||
return "0123456789abcdef"[nybble];
|
return "0123456789abcdef"[nybble];
|
||||||
|
@ -129,6 +170,44 @@ void send_status(const unsigned char destination[6]) {
|
||||||
send_frame(frame, sizeof(frame));
|
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) {
|
void read_command(void) {
|
||||||
int cmd = getchar();
|
int cmd = getchar();
|
||||||
if (cmd == EOF) {
|
if (cmd == EOF) {
|
||||||
|
@ -139,6 +218,8 @@ void read_command(void) {
|
||||||
running = false;
|
running = false;
|
||||||
} else if (cmd == 's') {
|
} else if (cmd == 's') {
|
||||||
send_status_request(broadcast_mac);
|
send_status_request(broadcast_mac);
|
||||||
|
} else if (cmd == 'i') {
|
||||||
|
send_msgid_request(broadcast_mac);
|
||||||
} else if (cmd == '\n') {
|
} else if (cmd == '\n') {
|
||||||
// Ignore
|
// Ignore
|
||||||
} else {
|
} else {
|
||||||
|
@ -172,6 +253,8 @@ void handle_status(const unsigned char source_mac[6], const unsigned char *data,
|
||||||
unsigned char nick[256];
|
unsigned char nick[256];
|
||||||
memcpy(nick, &data[2], nick_length);
|
memcpy(nick, &data[2], nick_length);
|
||||||
|
|
||||||
|
// TODO: check that nick is valid utf-8 with no control chars
|
||||||
|
|
||||||
char mac[18];
|
char mac[18];
|
||||||
format_mac(source_mac, mac);
|
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) {
|
void process_frame(void) {
|
||||||
unsigned char frame[1518]; // Largest a 802.3 frame can be without FCS
|
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);
|
handle_status(source_mac, &frame[16], packet_length - 16);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EMT_MSGID_REQUEST:
|
||||||
|
send_msgid(source_mac);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EMT_MSGID:
|
||||||
|
handle_msgid(source_mac, &frame[16], packet_length - 16);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Ignoring packet of type %i\n", packet_type);
|
fprintf(stderr, "Ignoring packet of type %i\n", packet_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Check that padding, if any, is all zeroes
|
||||||
}
|
}
|
||||||
|
|
||||||
void eventloop(void) {
|
void eventloop(void) {
|
||||||
|
@ -367,6 +492,9 @@ int main(int argc, char **argv) {
|
||||||
format_mac(own_mac, own_mac_str);
|
format_mac(own_mac, own_mac_str);
|
||||||
fprintf(stderr, "%s\n", 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
|
// Request status from everyone, so that we can get an idea of who is on the network
|
||||||
send_status_request(broadcast_mac);
|
send_status_request(broadcast_mac);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue