mirror of
https://github.com/sudomesh/disaster-radio.git
synced 2026-02-20 02:01:18 +01:00
@@ -1,7 +1,7 @@
|
||||
|
||||
-include $(dir $(SKETCH))settings.mk
|
||||
|
||||
SKETCH = ./firmware/firmware.ino
|
||||
SKETCH = ./firmware/firmware.cpp
|
||||
ESP_ROOT = ./esp8266-arduino
|
||||
FS_DIR = ./web/static
|
||||
LIBS = ./libs/ESPAsyncTCP \
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
#include <LoRa.h>
|
||||
#include <SD.h>
|
||||
#include "AsyncSDServer.ino"
|
||||
#include "routing.h"
|
||||
|
||||
#define HEADERSIZE 4
|
||||
#define BUFFERSIZE 252
|
||||
#define SHA1_LEN 40
|
||||
|
||||
byte mac[6];
|
||||
char macaddr[14];
|
||||
uint8_t mac[ADDR_LENGTH];
|
||||
char macaddr[ADDR_LENGTH*2];
|
||||
int _loraInitialized = 0;
|
||||
|
||||
char ssid[32] = "disaster.radio ";
|
||||
const char * hostName = "disaster-node";
|
||||
|
||||
@@ -30,13 +32,11 @@ AsyncWebServer server(80);
|
||||
AsyncWebSocket ws("/ws");
|
||||
AsyncEventSource events("/events");
|
||||
|
||||
int loraInitialized = 0; // has the LoRa radio been initialized?
|
||||
int sdInitialized = 0; // has the LoRa radio been initialized?
|
||||
|
||||
int retransmitEnabled = 0;
|
||||
int pollingEnabled = 0;
|
||||
int hashingEnabled = 1;
|
||||
int asyncTx = 1;
|
||||
|
||||
int beaconModeEnabled = 0;
|
||||
int beaconInterval = 30000;
|
||||
@@ -57,18 +57,16 @@ const int SDChipSelect = 2;
|
||||
|
||||
//TODO: switch to volatile byte for interrupt
|
||||
|
||||
byte localAddress; // assigned to last byte of mac address in setup
|
||||
byte destination = 0xFF; // destination to send to default broadcast
|
||||
|
||||
bool echo_on = false;
|
||||
|
||||
char hashTable[256][40];
|
||||
int hashEntry = 0;
|
||||
|
||||
char incomingBuffer[8][256];
|
||||
int incomingBufferLength[8];
|
||||
int bufferEntry = 0;
|
||||
int bufferInterval = 5000;
|
||||
struct webSocketMessage {
|
||||
uint8_t id;
|
||||
uint8_t type;
|
||||
uint8_t delimiter;
|
||||
uint8_t data;
|
||||
};
|
||||
|
||||
/*
|
||||
FORWARD-DEFINED FUNCTIONS
|
||||
@@ -91,54 +89,6 @@ void SPIenable(int opt){
|
||||
}
|
||||
}
|
||||
|
||||
bool isHashNew(char incoming[SHA1_LEN]){
|
||||
bool hashNew = true;
|
||||
for( int i = 0 ; i <= hashEntry ; i++){
|
||||
if(strcmp(incoming, hashTable[i]) == 0){
|
||||
hashNew = false;
|
||||
}
|
||||
}
|
||||
if( hashNew ){
|
||||
Serial.printf("New message received");
|
||||
Serial.printf("\r\n");
|
||||
for( int i = 0 ; i < SHA1_LEN ; i++){
|
||||
hashTable[hashEntry][i] = incoming[i];
|
||||
}
|
||||
hashEntry++;
|
||||
}
|
||||
return hashNew;
|
||||
}
|
||||
|
||||
void sendMessage(char* outgoing, int outgoingLength) {
|
||||
|
||||
|
||||
if(!loraInitialized){
|
||||
return;
|
||||
}
|
||||
|
||||
if(hashingEnabled){
|
||||
// do not send message if already transmitted once
|
||||
char hashOutgoing[SHA1_LEN];
|
||||
String hash = sha1(outgoing, outgoingLength);
|
||||
hash.toCharArray(hashOutgoing, SHA1_LEN);
|
||||
|
||||
if(!isHashNew(hashOutgoing)){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Serial.printf("Sending: ");
|
||||
|
||||
LoRa.beginPacket();
|
||||
for( int i = 0 ; i < outgoingLength ; i++){
|
||||
LoRa.write(outgoing[i]);
|
||||
Serial.printf("%c", outgoing[i]);
|
||||
}
|
||||
Serial.printf("\r\n");
|
||||
LoRa.endPacket(asyncTx);
|
||||
LoRa.receive();
|
||||
}
|
||||
|
||||
void printToWS(char message[252], int messageLength){
|
||||
|
||||
char msg[256] = "99c|";
|
||||
@@ -192,103 +142,9 @@ void printCharArray(char *buf, int len){
|
||||
Serial.printf("\r\n");
|
||||
}
|
||||
|
||||
void addToBuffer(char message[256], int length){
|
||||
if(bufferEntry > 7){
|
||||
bufferEntry = 0;
|
||||
}
|
||||
Serial.printf("adding message to buffer");
|
||||
Serial.printf("\r\n");
|
||||
incomingBufferLength[bufferEntry] = length;
|
||||
for( int i = 0 ; i < length ; i++){
|
||||
incomingBuffer[bufferEntry][i] = message[i];
|
||||
}
|
||||
bufferEntry++;
|
||||
}
|
||||
|
||||
void handleMessage(char message[256], int length){
|
||||
void handleMessage(uint8_t message[240], uint8_t length){
|
||||
|
||||
ws.binaryAll(message, length);
|
||||
if(retransmitEnabled){
|
||||
addToBuffer(message, length);
|
||||
}
|
||||
}
|
||||
|
||||
void handleHopCounter(char buffer[256], int length){
|
||||
|
||||
int hops = buffer[4]-'0'; //convert char to int by subtracting ASCII value of zero
|
||||
// this will only work for <10 hops
|
||||
char origin[14];
|
||||
for( int i = 0 ; i < 14 ; i++){
|
||||
origin[i] = buffer[6+i];
|
||||
}
|
||||
hops++;
|
||||
|
||||
char message[256];
|
||||
char retransmit[256];
|
||||
|
||||
sprintf(message, "%d hop from %s", hops, origin);
|
||||
sprintf(retransmit, "FFh|%d,%s", hops, origin);
|
||||
|
||||
printToWS(message, 29);
|
||||
|
||||
if(hashingEnabled){
|
||||
// do not send message if already transmitted once
|
||||
buffer[4] = '*'; //convert char to int by subtracting ASCII value of zero
|
||||
char bufferHash[SHA1_LEN];
|
||||
String hash = sha1(buffer, length);
|
||||
hash.toCharArray(bufferHash, SHA1_LEN);
|
||||
|
||||
if(!isHashNew(bufferHash)){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(retransmitEnabled){
|
||||
addToBuffer(retransmit, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
long lastCheckTime = millis();
|
||||
void checkBuffer(){
|
||||
if (millis() - lastCheckTime > bufferInterval) {
|
||||
if (retransmitEnabled){
|
||||
Serial.printf("checking buffer");
|
||||
Serial.printf("\r\n");
|
||||
if (bufferEntry > 0){
|
||||
Serial.printf("removing from buffer and retransmiting");
|
||||
Serial.printf("\r\n");
|
||||
int retransmitLength = incomingBufferLength[bufferEntry-1];
|
||||
char retransmit[retransmitLength];
|
||||
for( int i = 0 ; i < retransmitLength ; i++){
|
||||
retransmit[i] = incomingBuffer[bufferEntry-1][i];
|
||||
Serial.printf("%c", retransmit[i]);
|
||||
incomingBuffer[bufferEntry-1][i] = 0;
|
||||
}
|
||||
Serial.printf("\r\n");
|
||||
bufferEntry--;
|
||||
sendMessage(retransmit, retransmitLength);
|
||||
}
|
||||
}
|
||||
lastCheckTime = millis();
|
||||
}
|
||||
}
|
||||
|
||||
long lastBeaconTime = millis();
|
||||
void transmitBeacon(){
|
||||
if (millis() - lastBeaconTime > beaconInterval) {
|
||||
int test_length = 6;
|
||||
char test_message[256] = "FFh|0,"; // send a message
|
||||
for(int i = 0 ; i < 14 ; i++){
|
||||
test_message[test_length] = macaddr[i];
|
||||
test_length++;
|
||||
}
|
||||
Serial.printf("Sending: %s", test_message);
|
||||
Serial.printf("\r\n");
|
||||
sendMessage(test_message, test_length);
|
||||
|
||||
lastBeaconTime = millis();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -306,31 +162,24 @@ void onReceive(int packetSize) {
|
||||
incomingLength++;
|
||||
}
|
||||
|
||||
char type = incoming[2];
|
||||
Serial.printf("message type: %c", type);
|
||||
Serial.printf("\r\n");
|
||||
struct Packet packet = packet_received(incoming, incomingLength);
|
||||
|
||||
Serial.printf("PACKET|");
|
||||
printCharArray(incoming, incomingLength);
|
||||
Serial.printf("\r\n");
|
||||
|
||||
storeMessage(incoming, incomingLength);
|
||||
|
||||
switch(type){
|
||||
//storeMessage(incoming, incomingLength);
|
||||
|
||||
switch(packet.type){
|
||||
case 'c':
|
||||
Serial.printf("received chat message");
|
||||
Serial.printf("\r\n");
|
||||
handleMessage(incoming, incomingLength);
|
||||
handleMessage(packet.data, packet.totalLength-HEADER_LENGTH);
|
||||
break;
|
||||
case 'm':
|
||||
Serial.printf("received map message");
|
||||
Serial.printf("\r\n");
|
||||
handleMessage(incoming, incomingLength);
|
||||
handleMessage(packet.data, packet.totalLength-HEADER_LENGTH);
|
||||
break;
|
||||
case 'h':
|
||||
Serial.printf("received hop message");
|
||||
case 'r':
|
||||
Serial.printf("received routing message");
|
||||
Serial.printf("\r\n");
|
||||
handleHopCounter(incoming, incomingLength);
|
||||
break;
|
||||
default:
|
||||
Serial.printf("Error: Unknown message type");
|
||||
@@ -348,7 +197,7 @@ void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventT
|
||||
if(!sdInitialized){
|
||||
printToWS("WARNING: SD card not found, functionality may be limited", 57);
|
||||
}
|
||||
if(!loraInitialized){
|
||||
if(!_loraInitialized){
|
||||
printToWS("WARNING: LoRa radio not found, functionality may be limited", 60);
|
||||
}
|
||||
client->ping();
|
||||
@@ -415,7 +264,11 @@ void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventT
|
||||
ws.binary(client->id(), msg_id, 3);
|
||||
|
||||
//transmit message over LoRa
|
||||
sendMessage(msg, msg_length);
|
||||
//uint8_t data[240] = "Hola";
|
||||
//int dataLength = 4;
|
||||
uint8_t destination[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
struct Packet packet = buildPacket(1, mac, destination, messageCount(), 'c', data, msg_length);
|
||||
pushToBuffer(packet);
|
||||
|
||||
//echoing message to ws
|
||||
if(echo_on){
|
||||
@@ -447,7 +300,8 @@ void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventT
|
||||
*/
|
||||
void wifiSetup(){
|
||||
WiFi.macAddress(mac);
|
||||
sprintf(macaddr, "%02x%02x%02x%02x%02x%02x", mac[5], mac[4], mac[3], mac[2], mac[1], mac [0]);
|
||||
sprintf(macaddr, "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac [5]);
|
||||
setLocalAddress(macaddr);
|
||||
strcat(ssid, macaddr);
|
||||
WiFi.hostname(hostName);
|
||||
WiFi.mode(WIFI_AP);
|
||||
@@ -518,7 +372,6 @@ void spiffsSetup(){
|
||||
|
||||
void webServerSetup(){
|
||||
|
||||
|
||||
ws.onEvent(onWsEvent);
|
||||
server.addHandler(&ws);
|
||||
|
||||
@@ -593,9 +446,15 @@ void webServerSetup(){
|
||||
|
||||
}
|
||||
|
||||
int loraInitialized(){
|
||||
if(_loraInitialized){
|
||||
return 1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void loraSetup(){
|
||||
localAddress = mac[0];
|
||||
|
||||
// override the default CS, reset, and IRQ pins (optional)
|
||||
LoRa.setPins(loraChipSelect, resetPin, irqPin); // set CS, reset, IRQ pin
|
||||
@@ -610,16 +469,18 @@ void loraSetup(){
|
||||
LoRa.onReceive(onReceive);
|
||||
LoRa.receive();
|
||||
|
||||
loraInitialized = 1;
|
||||
_loraInitialized = 1;
|
||||
|
||||
Serial.printf("LoRa init succeeded.\r\n");
|
||||
Serial.printf("local address: %02x\r\n", localAddress);
|
||||
Serial.printf("%s\r\n", macaddr);
|
||||
}
|
||||
|
||||
/*
|
||||
START MAIN
|
||||
*/
|
||||
long startTime;
|
||||
long lastRoutingTime; // time of last packet send
|
||||
int routingInterval = 10000 + random(5000); // 5-15 seconds
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
@@ -628,55 +489,32 @@ void setup(){
|
||||
pinMode(SDChipSelect, OUTPUT);
|
||||
pinMode(irqPin, INPUT);
|
||||
|
||||
|
||||
wifiSetup();
|
||||
mdnsSetup();
|
||||
|
||||
SPIenable(0); //SD
|
||||
sdCardSetup();
|
||||
|
||||
if(!sdInitialized){
|
||||
spiffsSetup();
|
||||
}
|
||||
|
||||
webServerSetup();
|
||||
|
||||
loraSetup();
|
||||
|
||||
}
|
||||
uint8_t* myAddress = localAddress();
|
||||
Serial.printf("local address: ");
|
||||
printAddress(myAddress);
|
||||
Serial.printf("\n");
|
||||
|
||||
int interval = 10000 + random(5000); // 5-15 seconds
|
||||
long lastSendTime = 0; // time of last packet send
|
||||
startTime = getTime();
|
||||
lastRoutingTime = startTime;
|
||||
}
|
||||
|
||||
void loop(){
|
||||
|
||||
int packetSize;
|
||||
|
||||
if(LoRa.beginPacket() == 0){
|
||||
// do stuff while LoRa packet is being sent
|
||||
//Serial.print("transmitting a packet...\r\n");
|
||||
//delay(100);
|
||||
return;
|
||||
}else{
|
||||
// do stuff when LoRa packet is NOT being sent
|
||||
//Serial.printf("learning... %d\r", getTime() - startTime);
|
||||
checkBuffer();
|
||||
|
||||
if (beaconModeEnabled){
|
||||
transmitBeacon();
|
||||
long timestamp = transmitRoutes(routingInterval, lastRoutingTime);
|
||||
if(timestamp){
|
||||
Serial.print("routes transmitted");
|
||||
lastRoutingTime = timestamp;
|
||||
}
|
||||
|
||||
if (pollingEnabled){
|
||||
|
||||
if (millis() - lastSendTime > interval) {
|
||||
|
||||
int packetSize = LoRa.parsePacket();
|
||||
Serial.printf("checking for data: %d\r\n", packetSize);
|
||||
if(packetSize) {
|
||||
onReceive(packetSize);
|
||||
}
|
||||
lastSendTime = millis();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
721
firmware/routing.cpp
Normal file
721
firmware/routing.cpp
Normal file
@@ -0,0 +1,721 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "routing.h"
|
||||
|
||||
#ifdef LORA
|
||||
#include <LoRa.h>
|
||||
#endif
|
||||
|
||||
#ifdef SIM
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <openssl/sha.h>
|
||||
#endif
|
||||
|
||||
uint8_t _localAddress[ADDR_LENGTH];
|
||||
uint8_t _messageCount;
|
||||
|
||||
// metric weights
|
||||
float packetSuccessWeight = .8;
|
||||
float randomMetricWeight = .2;
|
||||
|
||||
// tables and buffers
|
||||
struct Packet buffer[8];
|
||||
int bufferEntry = 0;
|
||||
|
||||
uint8_t hashTable[256][SHA1_LENGTH];
|
||||
uint8_t hashEntry = 0;
|
||||
|
||||
struct NeighborTableEntry neighborTable[255];
|
||||
int neighborEntry = 0;
|
||||
|
||||
struct RoutingTableEntry routeTable[255];
|
||||
int routeEntry = 0;
|
||||
|
||||
// timeout intervals
|
||||
int _helloInterval = 10;
|
||||
int _routeInterval = 10;
|
||||
int _messageInterval = 5;
|
||||
int _discoveryTimeout = 30;
|
||||
int _learningTimeout = 400;
|
||||
int _maxRandomDelay = 20;
|
||||
int timeDistortion = 1;
|
||||
|
||||
uint8_t messageCount(){
|
||||
return _messageCount;
|
||||
}
|
||||
|
||||
int simulationTime(int realTime) {
|
||||
return realTime * timeDistortion;
|
||||
}
|
||||
int helloInterval() {
|
||||
return simulationTime(_helloInterval);
|
||||
}
|
||||
int routeInterval() {
|
||||
return simulationTime(_routeInterval);
|
||||
}
|
||||
int messageInterval() {
|
||||
return simulationTime(_messageInterval);
|
||||
}
|
||||
int discoveryTimeout() {
|
||||
return simulationTime(_discoveryTimeout);
|
||||
}
|
||||
int learningTimeout() {
|
||||
return simulationTime(_learningTimeout);
|
||||
}
|
||||
int maxRandomDelay() {
|
||||
return simulationTime(_maxRandomDelay);
|
||||
}
|
||||
|
||||
uint8_t hex_digit(char ch){
|
||||
if(( '0' <= ch ) && ( ch <= '9' )){
|
||||
ch -= '0';
|
||||
}else{
|
||||
if(( 'a' <= ch ) && ( ch <= 'f' )){
|
||||
ch += 10 - 'a';
|
||||
}else{
|
||||
if(( 'A' <= ch ) && ( ch <= 'F' ) ){
|
||||
ch += 10 - 'A';
|
||||
}else{
|
||||
ch = 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
int setLocalAddress(char* macString){
|
||||
for( int i = 0; i < sizeof(_localAddress)/sizeof(_localAddress[0]); ++i ){
|
||||
_localAddress[i] = hex_digit( macString[2*i] ) << 4;
|
||||
_localAddress[i] |= hex_digit( macString[2*i+1] );
|
||||
}
|
||||
if(_localAddress){
|
||||
return 1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* localAddress(){
|
||||
return _localAddress;
|
||||
}
|
||||
|
||||
#ifdef LORA
|
||||
int getTime(){
|
||||
return millis();
|
||||
}
|
||||
|
||||
int isHashNew(char incoming[SHA1_LENGTH]){
|
||||
int hashNew = 1;
|
||||
for( int i = 0 ; i <= hashEntry ; i++){
|
||||
if(strcmp(incoming, (char*) hashTable[i]) == 0){
|
||||
hashNew = 0;
|
||||
}
|
||||
}
|
||||
if( hashNew ){
|
||||
Serial.printf("New message received");
|
||||
Serial.printf("\r\n");
|
||||
for( int i = 0 ; i < SHA1_LENGTH ; i++){
|
||||
hashTable[hashEntry][i] = incoming[i];
|
||||
}
|
||||
hashEntry++;
|
||||
}
|
||||
return hashNew;
|
||||
}
|
||||
|
||||
int send_packet(char* data, int len){
|
||||
|
||||
Serial.printf("Sending: ");
|
||||
if(LoRa.beginPacket()){
|
||||
for( int i = 0 ; i < len ; i++){
|
||||
LoRa.write(data[i]);
|
||||
Serial.printf("%02x", data[i]);
|
||||
}
|
||||
Serial.printf("\r\n");
|
||||
LoRa.endPacket(1);
|
||||
LoRa.receive();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SIM
|
||||
int getTime(){
|
||||
return time(NULL);
|
||||
}
|
||||
|
||||
int isHashNew(uint8_t hash[SHA1_LENGTH]){
|
||||
|
||||
int hashNew = 1;
|
||||
Serial.printf("hash is %x\n", hash);
|
||||
for( int i = 0 ; i <= hashEntry ; i++){
|
||||
if(strcmp(hash, hashTable[i]) == 0){
|
||||
hashNew = 0;
|
||||
Serial.printf("Not new!\n");
|
||||
}
|
||||
}
|
||||
if(hashNew){
|
||||
// add to hash table
|
||||
Serial.printf("New message received");
|
||||
Serial.printf("\r\n");
|
||||
for( int i = 0 ; i < SHA1_LENGTH ; i++){
|
||||
hashTable[hashEntry][i] = hash[i];
|
||||
}
|
||||
hashEntry++;
|
||||
}
|
||||
return hashNew;
|
||||
}
|
||||
|
||||
int send_packet(char* data, uint8_t len) {
|
||||
|
||||
char packet[258];
|
||||
ssize_t written = 0;
|
||||
ssize_t ret;
|
||||
if(!len) {
|
||||
len = strlen(data);
|
||||
}
|
||||
if(len > 256) {
|
||||
fprintf(stderr, "Attempted to send packet larger than 256 bytes\n");
|
||||
return -1;
|
||||
}
|
||||
packet[0] = len;
|
||||
memcpy(packet+1, data, len);
|
||||
while(written < len) {
|
||||
ret = write(STDOUT, (void*) packet, len+1);
|
||||
if(ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
written += ret;
|
||||
}
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int debug_printf(const char* format, ...) {
|
||||
|
||||
if(DEBUG){
|
||||
int ret;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
ret = vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
fflush(stderr);
|
||||
return ret;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int sendPacket(struct Packet packet) {
|
||||
|
||||
uint8_t* sending = (uint8_t*) malloc(sizeof(packet));
|
||||
memcpy(sending, &packet, sizeof(packet));
|
||||
/*
|
||||
int send = 1;
|
||||
if(hashingEnabled){
|
||||
// do not send message if already transmitted once
|
||||
//uint8_t hash[SHA1_LENGTH];
|
||||
//SHA1(sending, packet.totalLength, hash);
|
||||
//if(isHashNew(hash)){
|
||||
// send = 0;
|
||||
//}
|
||||
}
|
||||
*/
|
||||
send_packet((char*) sending, packet.totalLength);
|
||||
_messageCount++;
|
||||
return _messageCount;
|
||||
}
|
||||
|
||||
void pushToBuffer(struct Packet packet){
|
||||
|
||||
if(bufferEntry > 7){
|
||||
bufferEntry = 0;
|
||||
}
|
||||
|
||||
memset(&buffer[bufferEntry], 0, sizeof(buffer[bufferEntry]));
|
||||
memcpy(&buffer[bufferEntry], &packet, sizeof(buffer[bufferEntry]));
|
||||
bufferEntry++;
|
||||
}
|
||||
|
||||
struct Packet popFromBuffer(){
|
||||
|
||||
bufferEntry--;
|
||||
struct Packet pop;
|
||||
memcpy(&pop, &buffer[bufferEntry], sizeof(pop));
|
||||
return pop;
|
||||
}
|
||||
|
||||
void checkBuffer(){
|
||||
|
||||
if (bufferEntry > 0){
|
||||
struct Packet packet = popFromBuffer();
|
||||
sendPacket(packet);
|
||||
}
|
||||
//else buffer is empty;
|
||||
}
|
||||
|
||||
struct Packet buildPacket( uint8_t ttl, uint8_t src[6], uint8_t dest[6], uint8_t sequence, uint8_t type, uint8_t data[240], uint8_t dataLength){
|
||||
|
||||
uint8_t packetLength = HEADER_LENGTH + dataLength;
|
||||
uint8_t* buffer = (uint8_t*) malloc(dataLength);
|
||||
buffer = (uint8_t*) data;
|
||||
struct Packet packet = {
|
||||
ttl,
|
||||
packetLength,
|
||||
src[0], src[1], src[2], src[3], src[4], src[5],
|
||||
dest[0], dest[1], dest[2], dest[3], dest[4], dest[5],
|
||||
sequence,
|
||||
type
|
||||
};
|
||||
memcpy(&packet.data, buffer, packet.totalLength);
|
||||
return packet;
|
||||
}
|
||||
|
||||
void printMetadata(struct Metadata metadata){
|
||||
Serial.printf("RSSI: %x\n", metadata.rssi);
|
||||
Serial.printf("SNR: %x\n", metadata.snr);
|
||||
}
|
||||
|
||||
void printPacketInfo(struct Packet packet){
|
||||
|
||||
Serial.printf("\r\n");
|
||||
Serial.printf("ttl: %d\r\n", packet.ttl);
|
||||
Serial.printf("length: %d\r\n", packet.totalLength);
|
||||
Serial.printf("source: ");
|
||||
for(int i = 0 ; i < ADDR_LENGTH ; i++){
|
||||
Serial.printf("%x", packet.source[i]);
|
||||
}
|
||||
Serial.printf("\r\n");
|
||||
Serial.printf("destination: ");
|
||||
for(int i = 0 ; i < ADDR_LENGTH ; i++){
|
||||
Serial.printf("%x", packet.destination[i]);
|
||||
}
|
||||
Serial.printf("\r\n");
|
||||
Serial.printf("sequence: %02x\r\n", packet.sequence);
|
||||
Serial.printf("type: %c\r\n", packet.type);
|
||||
Serial.printf("data: ");
|
||||
for(int i = 0 ; i < packet.totalLength-HEADER_LENGTH ; i++){
|
||||
Serial.printf("%02x", packet.data[i]);
|
||||
}
|
||||
Serial.printf("\r\n");
|
||||
}
|
||||
|
||||
void printNeighborTable(){
|
||||
|
||||
Serial.printf("\n");
|
||||
Serial.printf("Neighbor Table:\n");
|
||||
for( int i = 0 ; i < neighborEntry ; i++){
|
||||
for(int j = 0 ; j < ADDR_LENGTH ; j++){
|
||||
Serial.printf("%02x", neighborTable[i].address[j]);
|
||||
}
|
||||
Serial.printf(" %3d ", neighborTable[i].metric);
|
||||
Serial.printf("\n");
|
||||
}
|
||||
Serial.printf("\n");
|
||||
}
|
||||
|
||||
void printRoutingTable(){
|
||||
|
||||
Serial.printf("\n");
|
||||
Serial.printf("Routing Table: total routes %d\n", routeEntry);
|
||||
for( int i = 0 ; i < routeEntry ; i++){
|
||||
Serial.printf("%d hops from ", routeTable[i].distance);
|
||||
for(int j = 0 ; j < ADDR_LENGTH ; j++){
|
||||
Serial.printf("%02x", routeTable[i].destination[j]);
|
||||
}
|
||||
Serial.printf(" via ");
|
||||
for(int j = 0 ; j < ADDR_LENGTH ; j++){
|
||||
Serial.printf("%02x", routeTable[i].nextHop[j]);
|
||||
}
|
||||
Serial.printf(" metric %3d ", routeTable[i].metric);
|
||||
Serial.printf("\n");
|
||||
}
|
||||
Serial.printf("\n\n");
|
||||
}
|
||||
|
||||
void printAddress(uint8_t address[ADDR_LENGTH]){
|
||||
for( int i = 0 ; i < ADDR_LENGTH; i++){
|
||||
Serial.printf("%02x", address[i]);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t calculatePacketLoss(int entry, uint8_t sequence){
|
||||
|
||||
uint8_t packet_loss;
|
||||
uint8_t sequence_diff = sequence - neighborTable[entry].lastReceived;
|
||||
if(sequence_diff == 0){
|
||||
// this is first packet received from neighbor
|
||||
// assume perfect packet success
|
||||
neighborTable[entry].packet_success = 0xFF;
|
||||
packet_loss = 0x00;
|
||||
}else if(sequence_diff == 1){
|
||||
// do not decrease packet success rate
|
||||
packet_loss = 0x00;
|
||||
}else if(sequence_diff > 1 && sequence_diff < 16){
|
||||
// decrease packet success rate by difference
|
||||
packet_loss = 0x10 * sequence_diff;
|
||||
}else if(sequence_diff > 16){
|
||||
// no packet received recently
|
||||
// assume complete pakcet loss
|
||||
packet_loss = 0xFF;
|
||||
}
|
||||
return packet_loss;
|
||||
}
|
||||
|
||||
uint8_t calculateMetric(int entry, uint8_t sequence, struct Metadata metadata){
|
||||
|
||||
float weightedPacketSuccess = ((float) neighborTable[entry].packet_success)*packetSuccessWeight;
|
||||
float weightedRandomness = ((float) metadata.randomness)*randomMetricWeight;
|
||||
//float weightedRSSI = ((float) metadata.rssi)*RSSIWeight;
|
||||
//float weightedSNR = ((float) metadata.snr)*SNRWeight;
|
||||
uint8_t metric = weightedPacketSuccess+weightedRandomness;
|
||||
debug_printf("weighted packet success: %3f\n", weightedPacketSuccess);
|
||||
debug_printf("weighted randomness: %3f\n", weightedRandomness);
|
||||
//debug_printf("weighted RSSI: %3f\n", weightedRSSI);
|
||||
//debug_printf("weighted SNR: %3f\n", weightedSNR);
|
||||
debug_printf("metric calculated: %3d\n", metric);
|
||||
return metric;
|
||||
}
|
||||
|
||||
int checkNeighborTable(struct NeighborTableEntry neighbor){
|
||||
|
||||
int entry = routeEntry;
|
||||
for( int i = 0 ; i < neighborEntry ; i++){
|
||||
//had to use memcmp instead of strcmp?
|
||||
if(memcmp(neighbor.address, neighborTable[i].address, sizeof(neighbor.address)) == 0){
|
||||
entry = i;
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
int checkRoutingTable(struct RoutingTableEntry route){
|
||||
|
||||
int entry = routeEntry; // assume this is a new route
|
||||
for( int i = 0 ; i < routeEntry ; i++){
|
||||
if(memcmp(route.destination, _localAddress, sizeof(route.destination)) == 0){
|
||||
//this is me don't add to routing table
|
||||
//debug_printf("this route is my local address\n");
|
||||
entry = -1;
|
||||
return entry;
|
||||
}else
|
||||
if(memcmp(route.destination, routeTable[i].destination, sizeof(route.destination)) == 0){
|
||||
if(memcmp(route.nextHop, routeTable[i].nextHop, sizeof(route.nextHop)) == 0){
|
||||
// already have this exact route, update metric
|
||||
entry = i;
|
||||
return entry;
|
||||
}else{
|
||||
// already have this destination, but via a different neighbor
|
||||
if(route.distance < routeTable[i].distance){
|
||||
// replace route if distance is better
|
||||
entry = i;
|
||||
}else
|
||||
if(route.distance == routeTable[i].distance){
|
||||
if(route.metric > routeTable[i].metric){
|
||||
// replace route if distance is equal and metric is better
|
||||
entry = i;
|
||||
}else{
|
||||
entry = -1;
|
||||
}
|
||||
}else{
|
||||
// ignore route if distance and metric are worse
|
||||
entry = -1;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
int updateNeighborTable(struct NeighborTableEntry neighbor, int entry){
|
||||
|
||||
memset(&neighborTable[entry], 0, sizeof(neighborTable[entry]));
|
||||
memcpy(&neighborTable[entry], &neighbor, sizeof(neighborTable[entry]));
|
||||
if(entry == neighborEntry){
|
||||
neighborEntry++;
|
||||
debug_printf("new neighbor found: ");
|
||||
}else{
|
||||
debug_printf("neighbor updated! ");
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
int updateRouteTable(struct RoutingTableEntry route, int entry){
|
||||
|
||||
memset(&routeTable[entry], 0, sizeof(routeTable[entry]));
|
||||
memcpy(&routeTable[entry], &route, sizeof(routeTable[entry]));
|
||||
if(entry == routeEntry){
|
||||
routeEntry++;
|
||||
debug_printf("new route found! ");
|
||||
}else{
|
||||
debug_printf("route updated! ");
|
||||
}
|
||||
printAddress(routeTable[entry].destination);
|
||||
debug_printf("\n");
|
||||
return entry;
|
||||
}
|
||||
|
||||
int selectRoute(struct Packet packet){
|
||||
|
||||
int entry = -1;
|
||||
for( int i = 0 ; i < routeEntry ; i++){
|
||||
if(memcmp(packet.destination, routeTable[i].destination, sizeof(packet.destination)) == 0){
|
||||
entry = i;
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
void retransmitRoutedPacket(struct Packet packet, struct RoutingTableEntry route){
|
||||
|
||||
// decrement ttl
|
||||
packet.ttl--;
|
||||
Serial.printf("retransmitting\n");
|
||||
uint8_t data[240];
|
||||
int dataLength = 0;
|
||||
for( int i = 0 ; i < ADDR_LENGTH ; i++){
|
||||
data[dataLength] = route.nextHop[i];
|
||||
dataLength++;
|
||||
}
|
||||
struct Packet newMessage = buildPacket(packet.ttl, packet.source, packet.destination, packet.sequence, packet.type, data, dataLength);
|
||||
|
||||
// queue packet to be transmitted
|
||||
pushToBuffer(newMessage);
|
||||
}
|
||||
|
||||
int parseHelloPacket(struct Packet packet, struct Metadata metadata){
|
||||
|
||||
struct NeighborTableEntry neighbor;
|
||||
memcpy(neighbor.address, packet.source, sizeof(neighbor.address));
|
||||
int n_entry = checkNeighborTable(neighbor);
|
||||
neighbor.lastReceived = packet.sequence;
|
||||
uint8_t packet_loss = calculatePacketLoss(n_entry, packet.sequence);
|
||||
neighbor.packet_success = neighborTable[n_entry].packet_success - packet_loss;
|
||||
uint8_t metric = calculateMetric(n_entry, packet.sequence, metadata);
|
||||
neighbor.metric = metric;
|
||||
updateNeighborTable(neighbor, n_entry);
|
||||
|
||||
struct RoutingTableEntry route;
|
||||
memcpy(route.destination, packet.source, ADDR_LENGTH);
|
||||
memcpy(route.nextHop, packet.source, ADDR_LENGTH);
|
||||
route.distance = 1;
|
||||
route.metric = neighborTable[n_entry].metric;
|
||||
int r_entry = checkRoutingTable(route);
|
||||
if(r_entry == -1){
|
||||
debug_printf("do nothing, already have better route to ");
|
||||
printAddress(route.destination);
|
||||
debug_printf("\n");
|
||||
}else{
|
||||
//if(routeEntry <= 30){
|
||||
updateRouteTable(route, r_entry);
|
||||
//}
|
||||
}
|
||||
return n_entry;
|
||||
}
|
||||
|
||||
int parseRoutingPacket(struct Packet packet, struct Metadata metadata){
|
||||
int numberOfRoutes = (packet.totalLength - HEADER_LENGTH) / (ADDR_LENGTH+2);
|
||||
debug_printf("routes in packet: %d\n", numberOfRoutes);
|
||||
|
||||
int n_entry = parseHelloPacket(packet, metadata);
|
||||
|
||||
for( int i = 0 ; i < numberOfRoutes ; i++){
|
||||
struct RoutingTableEntry route;
|
||||
memcpy(route.destination, packet.data + (ADDR_LENGTH+2)*i, ADDR_LENGTH);
|
||||
memcpy(route.nextHop, packet.source, ADDR_LENGTH);
|
||||
route.distance = packet.data[(ADDR_LENGTH+2)*i + ADDR_LENGTH];
|
||||
route.distance++; // add a hop to distance
|
||||
float metric = (float) packet.data[(ADDR_LENGTH+2)*i + ADDR_LENGTH+1];
|
||||
|
||||
int entry = checkRoutingTable(route);
|
||||
if(entry == -1){
|
||||
debug_printf("do nothing, already have route to ");
|
||||
printAddress(route.destination);
|
||||
debug_printf("\n");
|
||||
}else{
|
||||
// average neighbor metric with rest of route metric
|
||||
float hopRatio = 1/((float)route.distance);
|
||||
metric = ((float) neighborTable[n_entry].metric)*(hopRatio) + ((float)route.metric)*(1-hopRatio);
|
||||
route.metric = (uint8_t) metric;
|
||||
//if(routeEntry <= 30){
|
||||
updateRouteTable(route, entry);
|
||||
//}
|
||||
}
|
||||
}
|
||||
return numberOfRoutes;
|
||||
}
|
||||
|
||||
void parseChatPacket(struct Packet packet){
|
||||
|
||||
if(memcmp(packet.destination, _localAddress, sizeof(packet.destination)) == 0){
|
||||
Serial.printf("this message is for me\n");
|
||||
return;
|
||||
}
|
||||
uint8_t nextHop[ADDR_LENGTH];
|
||||
memcpy(nextHop, packet.data, sizeof(nextHop));
|
||||
if(memcmp(nextHop, _localAddress, sizeof(nextHop)) == 0){
|
||||
Serial.printf("I am the next hop ");
|
||||
int entry = selectRoute(packet);
|
||||
if(entry == -1){
|
||||
Serial.printf(" but I don't have a route\n");
|
||||
}else{
|
||||
Serial.printf(" and I have a route RETRANSMIT\n");
|
||||
retransmitRoutedPacket(packet, routeTable[entry]);
|
||||
}
|
||||
}else{
|
||||
Serial.printf("I am not the next hop, packet dropped\n");
|
||||
}
|
||||
}
|
||||
|
||||
struct Packet packet_received(char* data, size_t len) {
|
||||
|
||||
data[len] = '\0';
|
||||
|
||||
// convert ASCII data to pure bytes
|
||||
uint8_t* byteData = ( uint8_t* ) data;
|
||||
|
||||
// randomly generate RSSI and SNR values
|
||||
// see https://github.com/sudomesh/disaster-radio-simulator/issues/3
|
||||
//uint8_t packet_rssi = rand() % (256 - 128) + 128;
|
||||
//uint8_t packet_snr = rand() % (256 - 128) + 128;
|
||||
// articial packet loss
|
||||
//uint8_t packet_randomness = rand() % (256 - 128) + 128;
|
||||
|
||||
|
||||
struct Metadata metadata;
|
||||
struct Packet packet = {
|
||||
byteData[0],
|
||||
byteData[1],
|
||||
byteData[2], byteData[3], byteData[4], byteData[5], byteData[6], byteData[7],
|
||||
byteData[8], byteData[9], byteData[10], byteData[11], byteData[12], byteData[13],
|
||||
byteData[14],
|
||||
byteData[15],
|
||||
};
|
||||
memcpy(packet.data, byteData + HEADER_LENGTH, packet.totalLength-HEADER_LENGTH);
|
||||
|
||||
//printPacketInfo(packet);
|
||||
|
||||
switch(packet.type){
|
||||
case 'h' :
|
||||
// hello packet;
|
||||
parseHelloPacket(packet, metadata);
|
||||
//printNeighborTable();
|
||||
break;
|
||||
case 'r':
|
||||
// routing packet;
|
||||
//parseHelloPacket(packet, metadata);
|
||||
parseRoutingPacket(packet, metadata);
|
||||
//printRoutingTable();
|
||||
break;
|
||||
case 'c' :
|
||||
// chat packet
|
||||
parseChatPacket(packet);
|
||||
//Serial.printf("this is a chat message\n");
|
||||
break;
|
||||
case 'm' :
|
||||
Serial.printf("this is a map message\n");
|
||||
break;
|
||||
default :
|
||||
printPacketInfo(packet);
|
||||
Serial.printf("message type not found\n");
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
long transmitHello(long interval, long lastTime){
|
||||
|
||||
long newLastTime = 0;
|
||||
if (getTime() - lastTime > interval) {
|
||||
uint8_t data[240] = "Hola";
|
||||
int dataLength = 4;
|
||||
//TODO: add randomness to message to avoid hashisng issues
|
||||
uint8_t destination[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
struct Packet helloMessage = buildPacket(1, _localAddress, destination, _messageCount, 'h', data, dataLength);
|
||||
sendPacket(helloMessage);
|
||||
newLastTime = getTime();
|
||||
}
|
||||
return newLastTime;
|
||||
}
|
||||
|
||||
long transmitRoutes(long interval, long lastTime){
|
||||
|
||||
long newLastTime = 0;
|
||||
if (getTime() - lastTime > interval) {
|
||||
uint8_t data[240];
|
||||
int dataLength = 0;
|
||||
Serial.printf("transmitting routes\r\n");
|
||||
debug_printf("number of routes before transmit: %d\n", routeEntry);
|
||||
int routesPerPacket = routeEntry;
|
||||
if (routeEntry >= MAX_ROUTES_PER_PACKET-1){
|
||||
routesPerPacket = MAX_ROUTES_PER_PACKET-1;
|
||||
}
|
||||
// random select without replacement of routes
|
||||
for( int i = 0 ; i < routesPerPacket ; i++){
|
||||
for( int j = 0 ; j < ADDR_LENGTH ; j++){
|
||||
data[dataLength] = routeTable[i].destination[j];
|
||||
dataLength++;
|
||||
}
|
||||
data[dataLength] = routeTable[i].distance; //distance
|
||||
dataLength++;
|
||||
data[dataLength] = routeTable[i].metric;
|
||||
dataLength++;
|
||||
}
|
||||
debug_printf("Sending data: ");
|
||||
for(int i = 0 ; i < dataLength ; i++){
|
||||
debug_printf("%02x ", data[i]);
|
||||
}
|
||||
debug_printf("\n");
|
||||
uint8_t destination[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
struct Packet routeMessage = buildPacket(1, _localAddress, destination, _messageCount, 'r', data, dataLength);
|
||||
printPacketInfo(routeMessage);
|
||||
sendPacket(routeMessage);
|
||||
newLastTime = getTime();
|
||||
}
|
||||
return newLastTime;
|
||||
}
|
||||
|
||||
long transmitToRandomRoute(long interval, long lastTime){
|
||||
long newLastTime = 0;
|
||||
if (getTime() - lastTime > interval) {
|
||||
if (routeEntry == 0){
|
||||
Serial.printf("trying to send but I have no routes ");
|
||||
newLastTime = getTime();
|
||||
return newLastTime;
|
||||
}
|
||||
int choose = rand()%routeEntry;
|
||||
uint8_t destination[ADDR_LENGTH];
|
||||
memcpy(destination, &routeTable[choose].destination, sizeof(destination));
|
||||
|
||||
Serial.printf("trying to send a random message to ");
|
||||
for( int j = 0 ; j < ADDR_LENGTH ; j++){
|
||||
Serial.printf("%02x", routeTable[choose].destination[j]);
|
||||
}
|
||||
Serial.printf(" via ");
|
||||
for( int j = 0 ; j < ADDR_LENGTH ; j++){
|
||||
Serial.printf("%02x", routeTable[choose].nextHop[j]);
|
||||
}
|
||||
Serial.printf("\n");
|
||||
|
||||
uint8_t data[240];
|
||||
int dataLength = 0;
|
||||
for( int i = 0 ; i < ADDR_LENGTH ; i++){
|
||||
data[dataLength] = routeTable[choose].nextHop[i];
|
||||
dataLength++;
|
||||
}
|
||||
struct Packet randomMessage = buildPacket(32, _localAddress, destination, _messageCount, 'c', data, dataLength);
|
||||
sendPacket(randomMessage);
|
||||
_messageCount++;
|
||||
newLastTime = getTime();
|
||||
}
|
||||
return newLastTime;
|
||||
}
|
||||
|
||||
117
firmware/routing.h
Normal file
117
firmware/routing.h
Normal file
@@ -0,0 +1,117 @@
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define LORA
|
||||
#define DEBUG 0
|
||||
#define HEADER_LENGTH 16
|
||||
#define SHA1_LENGTH 40
|
||||
#define ADDR_LENGTH 6
|
||||
#define MAX_ROUTES_PER_PACKET 30
|
||||
#define ASYNC_TX 1;
|
||||
|
||||
int getTime();
|
||||
|
||||
int simulationTime(int realTime);
|
||||
int helloInterval();
|
||||
int routeInterval();
|
||||
int messageInterval();
|
||||
int discoveryTimeout();
|
||||
int learningTimeout();
|
||||
int maxRandomDelay();
|
||||
|
||||
struct Metadata {
|
||||
uint8_t rssi;
|
||||
uint8_t snr;
|
||||
uint8_t randomness;
|
||||
};
|
||||
|
||||
struct Packet {
|
||||
uint8_t ttl;
|
||||
uint8_t totalLength;
|
||||
uint8_t source[ADDR_LENGTH];
|
||||
uint8_t destination[ADDR_LENGTH];
|
||||
uint8_t sequence;
|
||||
uint8_t type;
|
||||
uint8_t data[240];
|
||||
};
|
||||
|
||||
struct RoutedMessage {
|
||||
uint8_t nextHop[6];
|
||||
uint8_t data[234];
|
||||
};
|
||||
|
||||
struct NeighborTableEntry{
|
||||
uint8_t address[ADDR_LENGTH];
|
||||
uint8_t lastReceived;
|
||||
uint8_t packet_success;
|
||||
uint8_t metric;
|
||||
};
|
||||
|
||||
struct RoutingTableEntry{
|
||||
uint8_t destination[ADDR_LENGTH];
|
||||
uint8_t nextHop[ADDR_LENGTH];
|
||||
uint8_t distance;
|
||||
uint8_t lastReceived;
|
||||
uint8_t metric;
|
||||
};
|
||||
|
||||
uint8_t messageCount();
|
||||
int setLocalAddress(char* macString);
|
||||
uint8_t* localAddress();
|
||||
|
||||
int isHashNew(char incoming[SHA1_LENGTH]);
|
||||
|
||||
int send_packet(char* data, int len);
|
||||
|
||||
int debug_printf(const char* format, ...);
|
||||
|
||||
int sendPacket(struct Packet packet);
|
||||
|
||||
void pushToBuffer(struct Packet packet);
|
||||
|
||||
struct Packet popFromBuffer();
|
||||
|
||||
void checkBuffer();
|
||||
|
||||
struct Packet buildPacket( uint8_t ttl, uint8_t src[6], uint8_t dest[6], uint8_t sequence, uint8_t type, uint8_t data[240], uint8_t dataLength);
|
||||
|
||||
void printMetadata(struct Metadata metadata);
|
||||
|
||||
void printPacketInfo(struct Packet packet);
|
||||
|
||||
void printNeighborTable();
|
||||
|
||||
void printRoutingTable();
|
||||
|
||||
void printAddress(uint8_t address[ADDR_LENGTH]);
|
||||
|
||||
//uint8_t calculatePacketLoss(int entry, uint8_t sequence);
|
||||
|
||||
//uint8_t calculateMetric(int entry, uint8_t sequence, struct Metadata metadata);
|
||||
|
||||
//int checkNeighborTable(struct NeighborTableEntry neighbor);
|
||||
|
||||
//int checkRoutingTable(struct RoutingTableEntry route);
|
||||
|
||||
//int updateNeighborTable(struct NeighborTableEntry neighbor, int entry);
|
||||
|
||||
//int updateRouteTable(struct RoutingTableEntry route, int entry);
|
||||
|
||||
//int selectRoute(struct Packet packet);
|
||||
|
||||
//void retransmitRoutedPacket(struct Packet packet, struct RoutingTableEntry route);
|
||||
|
||||
//int parseHelloPacket(struct Packet packet, struct Metadata metadata);
|
||||
|
||||
//int parseRoutingPacket(struct Packet packet, struct Metadata metadata);
|
||||
|
||||
struct Packet packet_received(char* data, size_t len);
|
||||
|
||||
long transmitHello(long interval, long lastTime);
|
||||
|
||||
long transmitRoutes(long interval, long lastTime);
|
||||
|
||||
long transmitToRandomRoute(long interval, long lastTime);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user