WIP: Fixes, optimizations, and more Transport

Changed all time references to use decimal seconds to match Python
reference implementation.
Fixed memory issues caused by storing references to objects instead of
copies.
More implementation of Transport logic.
This is the first build that fully implements end-to-end path finding
and routing.
This commit is contained in:
attermann 2023-12-02 08:52:45 -07:00
parent ea7b4603ed
commit 642486ac7e
28 changed files with 958 additions and 261 deletions

View file

@ -4,6 +4,15 @@
#include <memory>
#ifndef ARDUINO
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#endif
using namespace RNS;
using namespace RNS::Interfaces;
@ -25,29 +34,53 @@ def get_broadcast_for_if(name):
UDPInterface::UDPInterface(const char* name /*= "UDPInterface"*/) : Interface(name) {
IN(true);
//OUT(false);
OUT(true);
bitrate(BITRATE_GUESS);
}
void UDPInterface::start() {
UDPInterface::UDPInterface(const char* wifi_ssid, const char* wifi_password, int local_port, const char* local_host /*=nullptr*/, const char* name /*= "UDPInterface"*/) : Interface(name),
_local_port(local_port)
{
IN(true);
OUT(true);
bitrate(BITRATE_GUESS);
if (wifi_ssid != nullptr) {
_wifi_ssid = wifi_ssid;
}
if (wifi_password != nullptr) {
_wifi_password = wifi_password;
}
if (local_host != nullptr) {
_local_host = local_host;
}
}
/*virtual*/ UDPInterface::~UDPInterface() {
stop();
}
bool UDPInterface::start() {
online(false);
#ifdef ARDUINO
// Connect to the WiFi network
WiFi.begin(ssid, pwd);
WiFi.begin(_wifi_ssid.c_str(), _wifi_password.c_str());
Serial.println("");
// Wait for WiFi network connection to complete
Serial.print("Connecting to ");
Serial.print(ssid);
Serial.print(_wifi_ssid.c_str());
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.println(_wifi_ssid.c_str());
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
@ -86,10 +119,78 @@ void UDPInterface::start() {
*/
// This initializes udp and transfer buffer
udp.begin(udpPort);
udp.begin(_local_port);
#else
// resolve local host
struct in_addr local_addr;
if (inet_aton(_local_host.c_str(), &local_addr) == 0) {
struct hostent* host_ent = gethostbyname(_local_host.c_str());
if (host_ent == nullptr || host_ent->h_addr_list[0] == nullptr) {
error("Unable to resolve local host " + std::string(_local_host));
return false;
}
_local_address = *((in_addr_t*)(host_ent->h_addr_list[0]));
}
else {
_local_address = local_addr.s_addr;
}
// resolve remote host
struct in_addr remote_addr;
if (inet_aton(_remote_host.c_str(), &remote_addr) == 0) {
struct hostent* host_ent = gethostbyname(_remote_host.c_str());
if (host_ent == nullptr || host_ent->h_addr_list[0] == nullptr) {
error("Unable to resolve remote host " + std::string(_remote_host));
return false;
}
_remote_address = *((in_addr_t*)(host_ent->h_addr_list[0]));
}
else {
_remote_address = remote_addr.s_addr;
}
// open udp socket
extreme("Opening UDP socket");
_socket = socket( PF_INET, SOCK_DGRAM, 0 );
if (_socket < 0) {
error("Unable to create socket with error " + std::to_string(errno));
return false;
}
// enable broadcast
int broadcast = 1;
setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
// bind to udp socket for listening
info("Binding UDP socket " + std::to_string(_socket) + " to " + std::string(_local_host) + ":" + std::to_string(_local_port));
sockaddr_in bind_addr;
bind_addr.sin_family = AF_INET;
bind_addr.sin_addr.s_addr = _local_address;
bind_addr.sin_port = htons(_local_port);
if (bind(_socket, (struct sockaddr*)&bind_addr, sizeof(bind_addr)) == -1) {
close(_socket);
_socket = -1;
error("Unable to bind socket with error " + std::to_string(errno));
return false;
}
#endif
online(true);
return true;
}
void UDPInterface::stop() {
#ifdef ARDUINO
#else
if (_socket > -1) {
close(_socket);
_socket = -1;
}
#endif
online(false);
}
void UDPInterface::loop() {
@ -98,10 +199,22 @@ void UDPInterface::loop() {
// Check for incoming packet
#ifdef ARDUINO
udp.parsePacket();
size_t len = udp.read(buffer.writable(Type::Reticulum::MTU), Type::Reticulum::MTU);
size_t len = udp.read(_buffer.writable(Type::Reticulum::MTU), Type::Reticulum::MTU);
if (len > 0) {
buffer.resize(len);
processIncoming(buffer);
_buffer.resize(len);
processIncoming(_buffer);
}
#else
size_t available = 0;
ioctl(_socket, FIONREAD, &available);
if (available > 0) {
size_t len = read(_socket, _buffer.writable(available), available);
if (len > 0) {
if (len < available) {
_buffer.resize(len);
}
processIncoming(_buffer);
}
}
#endif
}
@ -109,20 +222,26 @@ void UDPInterface::loop() {
/*virtual*/ void UDPInterface::processIncoming(const Bytes& data) {
debug("UDPInterface.processIncoming: data: " + data.toHex());
//debug("UDPInterface.processIncoming: text: " + data.toString());
Interface::processIncoming(data);
}
/*virtual*/ void UDPInterface::processOutgoing(const Bytes& data) {
debug("UDPInterface.processOutgoing: data: " + data.toHex());
debug("UDPInterface.processOutgoing: text: " + data.toString());
try {
if (online()) {
// Send packet
#ifdef ARDUINO
udp.beginPacket(udpAddress, udpPort);
udp.beginPacket(_remote_host.c_str(), _remote_port);
udp.write(data.data(), data.size());
udp.endPacket();
#else
extreme("Sending UDP packet to " + std::string(_remote_host) + ":" + std::to_string(_remote_port));
sockaddr_in sock_addr;
sock_addr.sin_family = AF_INET;
sock_addr.sin_addr.s_addr = _remote_address;
sock_addr.sin_port = htons(_remote_port);
int sent = sendto(_socket, data.data(), data.size(), 0, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
extreme("Sent " + std::to_string(sent) + " bytes to " + std::string(_remote_host) + ":" + std::to_string(_remote_port));
#endif
}