2023-05-11 21:27:36 +02:00
|
|
|
// MIT License
|
|
|
|
//
|
|
|
|
// Copyright (c) 2016-2022 Mark Qvist / unsigned.io
|
|
|
|
// C# Port (c) 2023 Michael Faragher / betweentheborders.com
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
|
|
// copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
// SOFTWARE.
|
|
|
|
|
|
|
|
// This is considered pre-alpha of a minimum viable product. No warranties are provided and compatibility is not assured.
|
|
|
|
|
|
|
|
namespace RNS
|
|
|
|
{
|
|
|
|
public class Reticulum
|
|
|
|
{
|
|
|
|
public const int MTU = 500;
|
|
|
|
const int MAX_QUEUED_ANNOUNCES = 16384;
|
|
|
|
const int QUEUED_ANNOUNCE_LIFE = 60 * 60 * 24;
|
|
|
|
|
|
|
|
public const int ANNOUNCE_CAP = 2;
|
|
|
|
|
|
|
|
|
|
|
|
const int MINIMUM_BITRATE = 500;
|
|
|
|
|
|
|
|
|
|
|
|
public const int DEFAULT_PER_HOP_TIMEOUT = 6;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public const int TRUNCATED_HASHLENGTH = 128;
|
|
|
|
|
|
|
|
public const int HEADER_MINSIZE = 2 + 1 + (TRUNCATED_HASHLENGTH / 8) * 1;
|
|
|
|
public const int HEADER_MAXSIZE = 2 + 1 + (TRUNCATED_HASHLENGTH / 8) * 2;
|
|
|
|
public const int IFAC_MIN_SIZE = 1;
|
|
|
|
byte[] IFAC_SALT = ParseHexToByteArray("adf54d882c9a9b80771eb4995d702d4a3e733391b2a0f53f416d9f907e55cff8");
|
|
|
|
|
|
|
|
int MDU = MTU - HEADER_MAXSIZE - IFAC_MIN_SIZE;
|
|
|
|
|
|
|
|
int RESOURCE_CACHE = 24 * 60 * 60;
|
|
|
|
int JOB_INTERVAL = 5 * 60;
|
|
|
|
int CLEAN_INTERVAL = 15 * 60;
|
|
|
|
int PERSIST_INTERVAL = 60 * 60 * 12;
|
|
|
|
|
|
|
|
// router = None
|
|
|
|
// config = None //ToDo FixMe
|
|
|
|
|
|
|
|
// # The default configuration path will be expanded to a directory
|
|
|
|
//# named ".reticulum" inside the current users home directory
|
|
|
|
public string userdir = Environment.SpecialFolder.UserProfile.ToString();
|
|
|
|
string configdir = "";
|
|
|
|
string configpath = "";
|
|
|
|
string storagepath = "";
|
|
|
|
string cachepath = "";
|
|
|
|
|
|
|
|
|
|
|
|
public static byte[] ParseHexToByteArray(string S)
|
|
|
|
{
|
|
|
|
byte[] buffer = new byte[S.Length / 2];
|
|
|
|
int i = 0;
|
|
|
|
while (i < buffer.Length)
|
|
|
|
{
|
|
|
|
buffer[i] = byte.Parse(S.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
public class Packet
|
|
|
|
{
|
|
|
|
byte HeaderA;
|
|
|
|
byte Hops;
|
|
|
|
byte Context;
|
|
|
|
byte[] AddressA = new byte[16];
|
|
|
|
byte[] AddressB = new byte[16];
|
|
|
|
byte[] DataBuffer = new byte[465];
|
|
|
|
byte[] Data;
|
|
|
|
byte[] IFAC = new byte[64];
|
|
|
|
byte PropagationType;
|
|
|
|
byte DestinationType;
|
|
|
|
byte PacketType;
|
|
|
|
int DataLength;
|
|
|
|
bool TypeTwoHeader;
|
|
|
|
const byte IFAC_Header = 0b10000000;
|
|
|
|
const byte Header_Type_Header = 0b01000000;
|
|
|
|
const byte Propagation_Type_Header = 0b00110000;
|
|
|
|
const byte Destination_Type_Header = 0b00001100;
|
|
|
|
const byte Packet_Type_Header = 0b00000011;
|
|
|
|
bool IFAC_Flag;
|
|
|
|
|
|
|
|
int Position;
|
|
|
|
public Packet(byte[] Payload, Interface Inter)
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
HeaderA = Payload[0];
|
|
|
|
Hops = Payload[1];
|
|
|
|
|
|
|
|
Position = 2;
|
|
|
|
|
|
|
|
IFAC_Flag = ((HeaderA & IFAC_Header) == 0b10000000) ? true : false;
|
|
|
|
TypeTwoHeader = ((HeaderA & Header_Type_Header) == 0b01000000) ? true : false;
|
|
|
|
PropagationType = (byte)((HeaderA & Propagation_Type_Header) >> 4);
|
|
|
|
DestinationType = (byte)((HeaderA & Destination_Type_Header) >> 2);
|
|
|
|
PacketType = (byte)(HeaderA & Packet_Type_Header);
|
|
|
|
|
|
|
|
if (IFAC_Flag)
|
|
|
|
{
|
|
|
|
if (Inter.ifac_size > 0)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < Inter.ifac_size; i++)
|
|
|
|
{
|
|
|
|
IFAC[i] = Payload[Position];
|
|
|
|
Position++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
|
|
{
|
|
|
|
AddressA[i] = Payload[Position];
|
|
|
|
Position++;
|
|
|
|
}
|
|
|
|
if (TypeTwoHeader)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
|
|
{
|
|
|
|
AddressB[i] = Payload[Position];
|
|
|
|
Position++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Context = Payload[Position];
|
|
|
|
Position++;
|
|
|
|
DataLength = Payload.Length - Position;
|
|
|
|
Data = new byte[DataLength];
|
|
|
|
for(int i = 0; i < DataLength; i++)
|
|
|
|
{
|
|
|
|
Data[i] = Payload[Position];
|
|
|
|
Position++;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
public void Verbose()
|
|
|
|
{
|
|
|
|
Console.WriteLine("Packet contents:");
|
|
|
|
Console.WriteLine("IFAC: "+IFAC_Flag.ToString());
|
|
|
|
if (IFAC_Flag) {
|
|
|
|
Console.WriteLine(" Length: "+IFAC.Length.ToString());
|
|
|
|
Console.WriteLine(" "+IFAC.ToString());
|
|
|
|
}
|
|
|
|
string buffer = TypeTwoHeader ? "2" : "1";
|
|
|
|
Console.WriteLine("Header Type: "+buffer);
|
|
|
|
Console.WriteLine("Propagation Type: "+PropagationType.ToString()+" ("+Transport.PropagationType[PropagationType]+")");
|
|
|
|
Console.WriteLine("Destination Type: " + DestinationType.ToString() + " ("+Transport.DestinationType[DestinationType]+")");
|
|
|
|
Console.WriteLine("Packet Type: " + PacketType.ToString() + " (" + Transport.PacketType[PacketType] + ")");
|
|
|
|
Console.WriteLine("Hops: " + Hops);
|
|
|
|
Console.Write("Address: ");
|
|
|
|
foreach(byte B in AddressA)
|
|
|
|
{
|
|
|
|
Console.Write(B.ToString("X") + " ");
|
|
|
|
}
|
|
|
|
Console.WriteLine();
|
|
|
|
if (TypeTwoHeader)
|
|
|
|
{
|
|
|
|
Console.Write("Address 2: ");
|
|
|
|
foreach (byte B in AddressB)
|
|
|
|
{
|
|
|
|
Console.Write(B.ToString("X") + " ");
|
|
|
|
}
|
|
|
|
Console.WriteLine() ;
|
|
|
|
}
|
|
|
|
Console.WriteLine("Context: " + Context.ToString("X"));
|
|
|
|
Console.WriteLine("Data Length: " + DataLength);
|
|
|
|
Console.Write("Data Content: ");
|
|
|
|
foreach(byte B in Data)
|
|
|
|
{
|
|
|
|
Console.Write(B.ToString("X")+" ");
|
|
|
|
}
|
|
|
|
Console.WriteLine();
|
|
|
|
Console.WriteLine("End packet");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2023-10-07 08:06:59 +02:00
|
|
|
|
|
|
|
public static class Util
|
|
|
|
{
|
|
|
|
public static string PrettyHexRep(byte[] data)
|
|
|
|
{
|
|
|
|
string buffer = "<";
|
|
|
|
foreach(byte b in data)
|
|
|
|
{
|
|
|
|
buffer += b.ToString("X2");
|
|
|
|
}
|
|
|
|
buffer += ">";
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static byte[] UTF8_to_Bytes(string Input)
|
|
|
|
{
|
|
|
|
return System.Text.Encoding.UTF8.GetBytes(Input);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static byte[] TruncateHash(byte[] data, int length, bool fromEnd = true)
|
|
|
|
{
|
|
|
|
byte[] hash = new byte[length];
|
|
|
|
int index = 0;
|
|
|
|
if (fromEnd)
|
|
|
|
{
|
|
|
|
index = data.Length - length;
|
|
|
|
}
|
|
|
|
Array.Copy(data, index, hash, 0, length);
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
}
|
2023-05-11 21:27:36 +02:00
|
|
|
}
|