1#include "main-header.h"
3#include "espressif/esp8266_flash.h"
4#include "user_app_exe.h"
9static long last_run = 0;
10static long last_announce_sent = 0;
12static void routing_update(
const struct command *com, uint8_t signal_indicator);
13static void peer_update(
int added,
struct hostroute *host);
15#define ROUTING_EVENT_LOOP_INTERVAL 30
16#define ROUTING_ANNOUNCE_INTERVAL 120
39#define HOSTROUTE_ENTRIES 40
46#define MAX_ROUTE_AGE_SECONDS 600
48static struct hostroute knownhosts[HOSTROUTE_ENTRIES];
51const char *decisionname(
int decision);
58 memset(&knownhosts, 0,
sizeof(knownhosts));
64 if (device == SOURCE_WIFI) {
65 return esp8266_is_enabled();
66 }
else if (device == SOURCE_SERIAL) {
69 return isonline_by_type(device);
72void bridge_packet(
struct command *com) {
73 if (!config_get_flag(CONFIG_FLAGS_ROUTING_ENABLED)) {
74 printf(
"bridging of packets disabled\r\n");
78 if (com->
flags & COMFLAGS_FORWARDED) {
79 printf(
"Not bridging packet. Flag FORWARDED is set already\r\n");
89 for (i = 0; i < 5; i++) {
95byte get_routing_debug() {
98void set_routing_debug(
byte b) {
100 printf(
"Routing debug set to %i\r\n", debug);
112 if (!is_command_valid(com)) {
117 printf(
"***** ROUTING DEBUG (new packet received) *****\r\n");
121 routing_update(com, signal_indicator);
129 if (com->
com == 12) {
130 if ((r == BROADCAST) && (com->
sender == CLOUD_SERVER)) {
142 }
else if (t == BROADCAST) {
146 }
else if (t == CLOUD_SERVER) {
153 routing_error(com, e);
157 }
else if (r == BROADCAST) {
159 if ((t == me) || (t == BROADCAST)) {
166 }
else if (r == CLOUD_SERVER) {
177 if ((action == 0) && (com->
sender == CLOUD_SERVER) && (r == me)) {
178 routing_error(com, 63);
180 printf(
"Routing decision completed: %s (%i) from %N to %N (via %N)\r\n", decisionname(action), (
int)action, com->
sender, com->
target, com->
recipient);
185const char *decisionname(
int decision) {
188 }
else if (decision == 1) {
190 }
else if (decision == 2) {
192 }
else if (decision == 3) {
207 for (i = 0; i < HOSTROUTE_ENTRIES; i++) {
208 if (knownhosts[i].
host != 0) {
223 for (i = 0; i < HOSTROUTE_ENTRIES; i++) {
224 if (knownhosts[i].
host != 0) {
226 return &knownhosts[i];
242 for (i = 0; i < HOSTROUTE_ENTRIES; i++) {
243 if (knownhosts[i].
host == 0) {
244 return &knownhosts[i];
253static int is_older_than(
long now,
long actual,
int maxage) {
255 return ((now - actual) > maxage) ? 1 : 0;
266 long now = mculib_get_seconds_since_boot();
268 for (i = 0; i < HOSTROUTE_ENTRIES; i++) {
270 if (
host->host == 0) {
274 peer_update(0,
host);
289 for (i = 0; i < HOSTROUTE_ENTRIES; i++) {
290 if (knownhosts[i].device != sourcedev) {
293 if (knownhosts[i].
host == nodeid) {
294 return &knownhosts[i];
298 for (i = 0; i < HOSTROUTE_ENTRIES; i++) {
299 if (knownhosts[i].device != sourcedev) {
302 if (nodeid == CLOUD_SERVER) {
303 if (knownhosts[i].hops_to_server > 0) {
304 return &knownhosts[i];
321 for (i = 0; i < HOSTROUTE_ENTRIES; i++) {
322 cur = &knownhosts[i];
332 if (cur->
host == nodeid) {
341 if ((res == NULL) && (nodeid == CLOUD_SERVER)) {
342 for (i = 0; i < HOSTROUTE_ENTRIES; i++) {
343 cur = &knownhosts[i];
347 if (cur->hops_to_server > 0) {
363 for (i = 0; i < com->
argctr; i++) {
364 long nid = ascii_parse_hex((
const byte *)
get_arg((
struct command *)com, i), 8, NULL);
365 printf(
"Route request reply from %N for %N\r\n", com->
sender, nid);
370 IPLOG(
"Routing table overflow!\r\n");
376 host->lastseen = mculib_get_seconds_since_boot();
377 IPLOG(
"New cat: %N on (%i)\r\n", (
void *)
host->host,
host->device);
388static void routing_update(
const struct command *com, uint8_t signal_indicator) {
397 if (com->
com != 23) {
402 IPLOG(
"Routing table overflow!\r\n");
407 host->lastseen = mculib_get_seconds_since_boot();
408 IPLOG(
"New cat: %N on (%i)\r\n", (
void *)
host->host,
host->device);
409 host->signal_indicator = signal_indicator;
413 host->signal_indicator = signal_indicator;
418 }
else if (com->
sourcedev == SOURCE_SERIAL) {
422 if (com->
sender != CLOUD_SERVER) {
427 if (com->
com == 23) {
429 host->hops_to_server = (byte)b;
433 printf(
"Updated routing table entry host=%p\r\n", (
void *)
host->host);
435 host->lastseen = mculib_get_seconds_since_boot();
440void routing_event_loop() {
441 long now = mculib_get_seconds_since_boot();
443 if (mculib_has_time_passed(ROUTING_EVENT_LOOP_INTERVAL, &last_run)) {
444 print_node_id(config_get_ram_struct()->nodeid);
447 int iv = ROUTING_ANNOUNCE_INTERVAL;
453 if (mculib_has_time_passed(iv, &last_announce_sent)) {
454 send_routing_update_now();
455 last_announce_sent = now;
459void send_routing_update_now() {
463 printf(
"routing: sending periodic announcements now\r\n");
465 if (esp8266_is_enabled()) {
471 com->sourcedev = SOURCE_WIFI;
473 com->target = 0xFFFFFFFF;
474 com->recipient = 0xFFFFFFFF;
475 com->flags = COMFLAGS_ACK | COMFLAGS_SUCCESS;
476 if (config_get_flag(CONFIG_FLAGS_POWER_SAVE)) {
477 com->flags |= COMFLAGS_POWERSAVE;
491 com->sourcedev = SOURCE_RADIO;
493 com->target = 0xFFFFFFFF;
494 com->recipient = 0xFFFFFFFF;
496 com->flags = COMFLAGS_ACK | COMFLAGS_SUCCESS;
497 if (config_get_flag(CONFIG_FLAGS_POWER_SAVE)) {
507 if (isready_by_type(SOURCE_RADIO)) {
508 com->sourcedev = SOURCE_RADIO;
511 if (isready_by_type(SOURCE_LORA)) {
512 com->sourcedev = SOURCE_LORA;
516 printf(
"Send_command failed: %i\r\n", xr);
527 if (esp_cloud_is_connected()) {
543 long now = mculib_get_seconds_since_boot();
545 printf(
"==== routing table ====\r\n");
547 for (i = 0; i < HOSTROUTE_ENTRIES; i++) {
548 host = &knownhosts[i];
549 if (
host->host == 0) {
552 printf(
"Host: %p, nexthop: %p, dev: %i, type: %i, server: %i, lastseen: %i secs, sigind: %i\r\n",
553 (
void *)
host->host, (
void *)
host->nexthop,
556 (
int)knownhosts[i].hops_to_server,
557 (
int)(now -
host->lastseen),
558 (
int)
host->signal_indicator
561 printf(
"==== end routing table ====\r\n");
591void routing_error(
struct command *f_com,
int errorcode) {
600 snprintf(tbuf,
sizeof(tbuf),
"t=1");
602 snprintf(tbuf,
sizeof(tbuf),
"fw=%i", errorcode);
604 snprintf(tbuf,
sizeof(tbuf),
"rcpt=0x%N", f_com->
recipient);
606 snprintf(tbuf,
sizeof(tbuf),
"tgt=0x%N", f_com->
target);
608 snprintf(tbuf,
sizeof(tbuf),
"seq=%i", f_com->
index);
617static void peer_update(
int added,
struct hostroute *host) {
627 snprintf(tbuf,
sizeof(tbuf),
"t=2");
629 snprintf(tbuf,
sizeof(tbuf),
"t=3");
632 snprintf(tbuf,
sizeof(tbuf),
"peer=0x%N", host->
host);
634 snprintf(tbuf,
sizeof(tbuf),
"device=%i", host->device);
636 snprintf(tbuf,
sizeof(tbuf),
"sigind=%i", host->signal_indicator);
642void r_on_new_node(
struct hostroute *host) {
643 if (user_app_executable()) {
644 invoke_on_new_node(host);
646 peer_update(1, host);
definitions of routing table structures
void routing_print_table()
print routing table
struct hostroute * routing_find_route(const long nodeid, const byte sourcedev)
find specific hostroute to target or NULL if none known special case, if we ask for a route to server...
int send_command(struct command *com)
send a command to another module (or broadcast)
void free_command(struct command *com)
free a command
int deliver_command(struct command *com, pkt_callback)
deliver a command to a module
void routing_init()
called when we power-up
void remove_stale_routes()
"old" routes are being removed this is the route garbage collector
void command_add_arg(struct command *com, const char *format,...)
adds an arg to a partially initialised command structure
struct hostroute * routing_find_host(const long nodeid)
find route to host or NULL if none known
long get_my_node_id()
get the id of my node
struct hostroute * routing_get_node_by_index(const int index)
finds a nodeid by index. [0...n]
int esp8266_is_accespoint()
returns !=0 if we are currently an accesspoint
int send_command_reply(struct command *com, byte flags)
send a reply to a command
int routing_count_nodes()
determine number of nodes known
int is_device_online(int device)
return 1 if the specified device is online and routing
void process_command(struct command *com)
command is parsed, now execute it
struct hostroute * routing_find_empty_slot()
finds an empty slot in our routing entry list
byte got_new_packet(struct command *com, uint8_t signal_indicator)
stack received a new packet (signal indicator is a 0-255 byte value, interface specific)
byte get_hops_to_server()
how many hops to the server?
int send_command_one_arg(int command, long target, const byte *arg1, int arg1len)
helper function to quickly and easily send a command somewhere return 0 if ok, else errorcode
void command_print(struct command *com)
prints a command in human readable format to serial console
struct command * alloc_command()
allocate a free command
int command_add_binary_arg(struct command *com, const int len, const byte *srcbuf)
adds a binary parameter to command returns 0 if ok otherwise errorcode
int forward_packet(struct command *com)
a command is forwarded to target based on our hostroutes
const char * get_arg(const struct command *com, int index)
given an argument by index[0..n], will return a pointer to the bytearray (excluding the fieldtype) th...
#define MAX_ROUTE_AGE_SECONDS
any route that has not been used or seen for longer than this is subject to removal (the garbage coll...
void routing_request_reply(const struct command *com)
we call this when we receive a reply to a routing request this adds or updates a new route
definitions of routing table structures