Add message sending and ack
This commit is contained in:
parent
3beda7742f
commit
539dbf9f14
187
ethermess.c
187
ethermess.c
|
@ -24,6 +24,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#define EM_PROTOCOL_VERSION 0
|
||||
#define EM_MESSAGE_MAX_LENGTH (1500 - 2 - 2 - 2)
|
||||
|
||||
#define EMT_SPEAK_VERSION 0
|
||||
#define EMT_STATUS_REQUEST 1
|
||||
|
@ -37,6 +38,9 @@
|
|||
#define EMS_UNAVAILABLE 1
|
||||
#define EMS_OFFLINE 2
|
||||
|
||||
unsigned const char veth0a_mac[6] = {0xb2, 0xc8, 0x5b, 0x78, 0xb4, 0xef}; //debg
|
||||
unsigned const char veth0b_mac[6] = {0xf6, 0x18, 0xfd, 0x2a, 0x80, 0xf3}; //debg
|
||||
|
||||
bool running = true;
|
||||
|
||||
int packet_socket;
|
||||
|
@ -46,15 +50,15 @@ unsigned char own_mac[6];
|
|||
unsigned char broadcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
unsigned char own_status = EMS_AVAILABLE;
|
||||
unsigned char own_nick[256] = {'n', 'o', 'r', 't', 't', 'i'};
|
||||
unsigned char own_nick_length = 6;
|
||||
unsigned char own_nick[256];
|
||||
unsigned char own_nick_length = 0;
|
||||
time_t next_status_broadcast;
|
||||
|
||||
bool own_message_queued = false;
|
||||
enum message_send_states {IDLE, QUEUED, SENDING};
|
||||
enum message_send_states own_message_send_state = IDLE;
|
||||
unsigned char own_message_destination_mac[6];
|
||||
unsigned char own_message[1500 - 2 - 2 - 2];
|
||||
unsigned char own_message[EM_MESSAGE_MAX_LENGTH];
|
||||
size_t own_message_length = 0;
|
||||
bool own_message_msgid_known = false;
|
||||
uint16_t own_message_msgid = 0;
|
||||
|
||||
struct msgid_cache_entry {
|
||||
|
@ -245,6 +249,37 @@ void send_msgid(const unsigned char destination[6]) {
|
|||
send_frame(frame, sizeof(frame));
|
||||
}
|
||||
|
||||
void send_message(void) {
|
||||
unsigned char frame[14 + 2 + 2 + 2 + own_message_length];
|
||||
|
||||
write_headers(frame, own_message_destination_mac, EMT_MESSAGE);
|
||||
|
||||
// Message ID
|
||||
frame[16] = own_message_msgid >> 8;
|
||||
frame[17] = own_message_msgid & 0xff;
|
||||
|
||||
// Message length
|
||||
frame[18] = own_message_length >> 8;
|
||||
frame[19] = own_message_length & 0xff;
|
||||
|
||||
// Message
|
||||
memcpy(&frame[20], own_message, own_message_length);
|
||||
|
||||
send_frame(frame, sizeof(frame));
|
||||
}
|
||||
|
||||
void send_ack(const unsigned char destination[6], uint16_t msgid) {
|
||||
unsigned char frame[14 + 2 + 2];
|
||||
|
||||
write_headers(frame, destination, EMT_ACK);
|
||||
|
||||
// Message ID
|
||||
frame[16] = msgid >> 8;
|
||||
frame[17] = msgid & 0xff;
|
||||
|
||||
send_frame(frame, sizeof(frame));
|
||||
}
|
||||
|
||||
void read_command(void) {
|
||||
errno = 0;
|
||||
int cmd = getchar();
|
||||
|
@ -252,12 +287,24 @@ void read_command(void) {
|
|||
err(1, "getchar");
|
||||
}
|
||||
|
||||
unsigned const char *other_mac;
|
||||
if (memcmp(own_mac, veth0a_mac, 6) == 0) {
|
||||
other_mac = veth0b_mac;
|
||||
} else {
|
||||
other_mac = veth0a_mac;
|
||||
}
|
||||
|
||||
if (cmd == 'q') {
|
||||
running = false;
|
||||
} else if (cmd == 's') {
|
||||
send_status_request(broadcast_mac);
|
||||
send_status_request(other_mac);
|
||||
} else if (cmd == 'i') {
|
||||
send_msgid_request(broadcast_mac);
|
||||
send_msgid_request(other_mac);
|
||||
} else if (cmd == 'm') {
|
||||
memcpy(own_message, "Hello, world!", 13);
|
||||
own_message_length = 13;
|
||||
memcpy(own_message_destination_mac, other_mac, 6);
|
||||
own_message_send_state = QUEUED;
|
||||
} else if (cmd == '\n') {
|
||||
// Ignore
|
||||
} else {
|
||||
|
@ -302,7 +349,7 @@ void handle_status(const unsigned char source_mac[6], const unsigned char *data,
|
|||
return;
|
||||
}
|
||||
|
||||
unsigned char nick[256];
|
||||
unsigned char nick[nick_length];
|
||||
memcpy(nick, &data[2], nick_length);
|
||||
|
||||
if (!check_padding(data, 2 + nick_length, data_length)) {
|
||||
|
@ -356,7 +403,7 @@ void handle_msgid(const unsigned char source_mac[6], const unsigned char *data,
|
|||
return;
|
||||
}
|
||||
|
||||
uint16_t msgid = data[0] << 8 | data[1];
|
||||
uint16_t msgid = (data[0] << 8) | data[1];
|
||||
|
||||
if (!check_padding(data, 2, data_length)) {
|
||||
// Malformed padding
|
||||
|
@ -386,6 +433,90 @@ void handle_msgid(const unsigned char source_mac[6], const unsigned char *data,
|
|||
}
|
||||
}
|
||||
|
||||
void handle_message(const unsigned char source_mac[6], const unsigned char *data, size_t data_length) {
|
||||
if (data_length < 4) {
|
||||
// Too short
|
||||
fprintf(stderr, "Data too short: %zu\n", data_length); // debg
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t msgid = (data[0] << 8) | data[1];
|
||||
|
||||
uint16_t message_length = (data[2] << 8) | data[3];
|
||||
|
||||
if (message_length > data_length - 4 || message_length > EM_MESSAGE_MAX_LENGTH) {
|
||||
// Malformed length field
|
||||
fprintf(stderr, "Message length %u, remaining packet length %zu, max message length %u\n", message_length, data_length, EM_MESSAGE_MAX_LENGTH); // debg
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char message[message_length];
|
||||
memcpy(message, &data[4], message_length);
|
||||
|
||||
if (!check_padding(data, 4 + message_length, data_length)) {
|
||||
// Malformed padding
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Check that the message is valid utf-8 with newline as the only control char
|
||||
|
||||
// TODO: Check whether we've received this message already and update msgid cache
|
||||
|
||||
char mac[18];
|
||||
format_mac(source_mac, mac);
|
||||
|
||||
errno = 0;
|
||||
if (printf("%s (%" PRIu16 "): ", mac, msgid) == -1) {
|
||||
err(1, "printf");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < message_length; i++) {
|
||||
errno = 0;
|
||||
if (putchar(message[i]) == EOF) {
|
||||
err(1, "putchar");
|
||||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
if (putchar('\n') == EOF) {
|
||||
err(1, "putchar");
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
if (fflush(stdout) == EOF) {
|
||||
err(1, "fflush");
|
||||
}
|
||||
|
||||
send_ack(source_mac, msgid);
|
||||
}
|
||||
|
||||
void handle_ack(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];
|
||||
|
||||
if (!check_padding(data, 2, data_length)) {
|
||||
// Malformed padding
|
||||
return;
|
||||
}
|
||||
|
||||
char mac[18];
|
||||
format_mac(source_mac, mac);
|
||||
|
||||
errno = 0;
|
||||
if (printf("%s ack %" PRIu16 "\n", mac, msgid) == -1) {
|
||||
err(1, "printf");
|
||||
}
|
||||
|
||||
if (own_message_send_state == SENDING && msgid == own_message_msgid) {
|
||||
own_message_send_state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void process_frame(void) {
|
||||
unsigned char frame[1518]; // Largest a 802.3 frame can be without FCS
|
||||
|
||||
|
@ -454,6 +585,14 @@ void process_frame(void) {
|
|||
handle_msgid(source_mac, &frame[16], packet_length - 16);
|
||||
break;
|
||||
|
||||
case EMT_MESSAGE:
|
||||
handle_message(source_mac, &frame[16], packet_length - 16);
|
||||
break;
|
||||
|
||||
case EMT_ACK:
|
||||
handle_ack(source_mac, &frame[16], packet_length - 16);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Ignoring packet of type %i\n", packet_type);
|
||||
}
|
||||
|
@ -472,6 +611,27 @@ void eventloop(void) {
|
|||
pollfds[1].events = POLLIN;
|
||||
|
||||
while (running) {
|
||||
// (Attempt) to process a message send
|
||||
if (own_message_send_state == QUEUED) {
|
||||
// We need to have the correct msgid to be able to send
|
||||
ssize_t cache_index = msgid_cache_lookup(own_message_destination_mac);
|
||||
|
||||
if (cache_index == -1 || !msgid_cache[cache_index].know_send) {
|
||||
// We don't know what the msgid should be
|
||||
// -> ask the other side
|
||||
// TODO: Implement a timer
|
||||
send_msgid_request(own_message_destination_mac);
|
||||
} else {
|
||||
// It is in the cache
|
||||
own_message_msgid = msgid_cache[cache_index].next_send++;
|
||||
own_message_send_state = SENDING;
|
||||
}
|
||||
}
|
||||
|
||||
if (own_message_send_state == SENDING) {
|
||||
send_message();
|
||||
}
|
||||
|
||||
// Figure out how many ms to wait
|
||||
int wait_ms;
|
||||
time_t now = monotonic_time();
|
||||
|
@ -581,6 +741,15 @@ int main(int argc, char **argv) {
|
|||
format_mac(own_mac, own_mac_str);
|
||||
fprintf(stderr, "%s\n", own_mac_str);
|
||||
|
||||
// Set our nick
|
||||
if (memcmp(own_mac, veth0a_mac, 6) == 0) {
|
||||
memcpy(own_nick, "foo", 3);
|
||||
own_nick_length = 3;
|
||||
} else {
|
||||
memcpy(own_nick, "bar", 3);
|
||||
own_nick_length = 3;
|
||||
}
|
||||
|
||||
// Initialize the message id cache
|
||||
memset(msgid_cache, 0, sizeof(msgid_cache));
|
||||
|
||||
|
|
Loading…
Reference in New Issue