Handle communicating message IDs
This commit is contained in:
parent
e51066ebb8
commit
4d03f397df
128
ethermess.c
128
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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue