More complete rework of packet parsing and packet generation with 29710c

This commit is contained in:
2024-05-19 23:28:45 +10:00
parent 46f52dd56d
commit f279d85b08
43 changed files with 412 additions and 291 deletions

View File

@@ -12,9 +12,9 @@ use Illuminate\Validation\Validator as ValidatorResult;
use App\Classes\FTN as FTNBase;
use App\Exceptions\InvalidPacketException;
use App\Models\{Address,Domain,Echomail,Netmail,Zone};
use App\Models\{Address,Domain,Echomail,Netmail,Setup,Zone};
use App\Rules\{TwoByteInteger,TwoByteIntegerWithZero};
use App\Traits\{EncodeUTF8,ObjectIssetFix};
use App\Traits\ObjectIssetFix;
/**
* Class Message
@@ -91,6 +91,7 @@ class Message extends FTNBase
private array $header; // Message Header
private int $tzutc = 0; // TZUTC that needs to be converted to be used by Carbon @see self::kludges
private Echomail|Netmail $mo; // The object storing this packet message
private Address $us; // Our address for this message
/** @deprecated Not sure why this is needed? */
public bool $packed = FALSE; // Has the message been packed successfully
@@ -156,6 +157,7 @@ class Message extends FTNBase
{
$oo = new self($o->fftn->zone);
$oo->mo = $o;
$oo->us = our_address($o->tftn);
return $oo;
}
@@ -507,6 +509,8 @@ class Message extends FTNBase
*/
public function __toString(): string
{
$s = Setup::findOrFail(config('app.id'));
$return = pack(collect(self::HEADER)->pluck(1)->join(''),
$this->mo->fftn->node_id, // Originating Node
$this->mo->tftn->node_id, // Destination Node
@@ -521,22 +525,26 @@ class Message extends FTNBase
$return .= $this->mo->from."\00";
$return .= $this->mo->subject."\00";
if (($this->mo instanceof Netmail) && $this->mo->isFlagSet(self::FLAG_LOCAL)) {
// If there isnt an INTL kludge, we'll add it
if (! $this->mo->kludges->has('INTL'))
$this->mo->kludges->put('INTL',sprintf('%s %s',$this->mo->tftn->ftn3d,$this->mo->fftn->ftn3d));
if ((! $this->mo->kludges->has('FMPT')) && $this->mo->fftn->point_id)
$this->mo->kludges->put('FMPT',$this->mo->fftn->point_id);
if ((! $this->mo->kludges->has('TOPT')) && $this->mo->tftn->point_id)
$this->mo->kludges->put('TOPT',$this->mo->tftn->point_id);
}
if ($this->mo->isFlagSet(self::FLAG_LOCAL))
$this->mo->kludges->put('PID',sprintf('clrghouz %s',$s->version));
else
$this->mo->kludges->put('TID',sprintf('clrghouz %s',$s->version));
if ($this->mo instanceof Echomail)
$return .= sprintf("AREA:%s\r",strtoupper($this->mo->echoarea->name));
if ($this->mo instanceof Netmail) {
// @todo If the message is local, then our kludges are not in the msg itself, we'll add them
if ($this->isFlagSet(self::FLAG_LOCAL))
Log::debug(sprintf('%s:^ Local message, we may need to set our INTL/FMPT/TOPT',self::LOGKEY));
$return .= sprintf("\01INTL %s\r",$this->mo->kludges->get('INTL'));
if ($this->mo->kludges->has('FMPT'))
$return .= sprintf("\01FMPT %d\r",$this->mo->kludges->get('FMPT'));
if ($this->mo->kludges->has('TOPT'))
$return .= sprintf("\01TOPT %d\r",$this->mo->kludges->get('TOPT'));
}
// Add some kludges
$return .= sprintf("\01TZUTC: %s\r",str_replace('+','',$this->mo->date->getOffsetString('')));
@@ -551,11 +559,15 @@ class Message extends FTNBase
$return .= $this->mo->content;
if ($this->mo instanceof Netmail) {
// @todo automatically include our address in the path
foreach ($this->mo->path as $ao)
$return .= sprintf("\x01Via %s\r",$this->mo->via($ao));
// Add our address
$return .= sprintf("\x01Via %s @%s.UTC %s (%04X)\r",
$this->us->ftn3d,
Carbon::now()->format('Ymd.His'),
Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
} else {
// FTS-0004.001/FSC-0068.001 The message SEEN-BY lines
// FTS-0004.001/FSC-0068.001 The message PATH lines

View File

@@ -50,6 +50,20 @@ abstract class Packet extends FTNBase implements \Iterator, \Countable
protected Collection $messages; // Messages in the Packet
public Collection $errors; // Messages that fail validation
protected int $index; // Our array index
protected $pass_p = NULL; // Overwrite the packet password (when packing messages)
/* ABSTRACT */
/**
* This function is intended to be implemented in child classes to test if the packet
* is defined by the child object
*
* @see self::PACKET_TYPES
* @param string $header
* @return bool
*/
abstract public static function is_type(string $header): bool;
abstract protected function header(): string;
/* STATIC */
@@ -63,16 +77,6 @@ abstract class Packet extends FTNBase implements \Iterator, \Countable
return collect(static::HEADER)->sum(function($item) { return Arr::get($item,2); });
}
/**
* This function is intended to be implemented in child classes to test if the packet
* is defined by the child object
*
* @see self::PACKET_TYPES
* @param string $header
* @return bool
*/
abstract public static function is_type(string $header): bool;
/**
* Process a packet file
*
@@ -261,6 +265,9 @@ abstract class Packet extends FTNBase implements \Iterator, \Countable
case 'name':
return $this->{$key} ?: sprintf('%08x',timew());
case 'messages':
return $this->{$key};
default:
throw new \Exception('Unknown key: '.$key);
}
@@ -274,6 +281,12 @@ abstract class Packet extends FTNBase implements \Iterator, \Countable
*/
public function __toString(): string
{
if (empty($this->messages))
throw new InvalidPacketException('Refusing to make an empty packet');
if (empty($this->tftn_p) || empty($this->fftn_p))
throw new InvalidPacketException('Cannot generate a packet without a destination address');
$return = $this->header();
foreach ($this->messages as $o)
@@ -379,18 +392,18 @@ abstract class Packet extends FTNBase implements \Iterator, \Countable
/**
* Generate a packet
*
* @param Collection $msgs
* @return string
* @throws InvalidPacketException
*/
public function generate(Collection $msgs): string
public function generate(): string
{
return (string)$this;
}
public function mail(Collection $msgs): self
{
$this->messages = $msgs;
if (empty($this->tftn_p) || empty($this->fftn_p))
throw new InvalidPacketException('Cannot generate a packet without a destination address');
return (string)$this;
return $this;
}
/**
@@ -500,6 +513,20 @@ abstract class Packet extends FTNBase implements \Iterator, \Countable
$this->messages->push($msg);
}
/**
* Overwrite the packet password
*
* @param string|null $password
* @return self
*/
public function password(string $password=NULL): self
{
if ($password && (strlen($password) < 9))
$this->pass_p = $password;
return $this;
}
/** @deprecated Is this used? */
public function pluck(string $key): Collection
{

View File

@@ -59,11 +59,10 @@ final class FSC48 extends Packet
/**
* Create our message packet header
* // @todo add the ability to overwrite the password
*/
protected function header(): string
{
$oldest = $this->messages->sortBy(function($item) { return $item->datetime; })->last();
$oldest = $this->messages->sortBy('datetime')->last();
try {
return pack(collect(self::HEADER)->pluck(1)->join(''),
@@ -77,22 +76,22 @@ final class FSC48 extends Packet
$oldest->datetime->format('s'), // Second
0, // Baud
2, // Packet Version (should be 2)
$this->fftn_p->point_id ? 0xffff : $this->fftn_p->node_id, // Orig Net (0xFFFF when OrigPoint != 0)
$this->fftn_p->point_id ? 0xffff : $this->fftn_p->host_id, // Orig Net (0xFFFF when OrigPoint != 0)
$this->tftn_p->host_id, // Dest Net
(Setup::PRODUCT_ID & 0xff), // Product Code Lo
Setup::PRODUCT_VERSION_MAJ, // Product Version Major
$this->tftn_p->session('pktpass'), // Packet Password
$this->fftn_p->zone->zone_id, // Orig Zone
$this->tftn_p->zone->zone_id, // Dest Zone
$this->fftn_p->point_id ? $this->fftn_p->node_id : 0x00, // Aux Net
$this->pass_p ?: $this->tftn_p->session('pktpass'), // Packet Password
$this->fftn_p->zone->zone_id, // Orig Zone
$this->tftn_p->zone->zone_id, // Dest Zone
$this->fftn_p->point_id ? $this->fftn_p->host_id : 0x00, // Aux Net
1<<0, // fsc-0039.004 (copy of 0x2c)
((Setup::PRODUCT_ID >> 8) & 0xff), // Product Code Hi
Setup::PRODUCT_VERSION_MIN, // Product Version Minor
1<<0, // Capability Word
$this->fftn_p->zone->zone_id, // Orig Zone
$this->tftn_p->zone->zone_id, // Dest Zone
$this->fftn_p->point_id, // Orig Point
$this->tftn_p->point_id, // Dest Point
$this->fftn_p->zone->zone_id, // Orig Zone
$this->tftn_p->zone->zone_id, // Dest Zone
$this->fftn_p->point_id, // Orig Point
$this->tftn_p->point_id, // Dest Point
strtoupper(hexstr(Setup::PRODUCT_ID)), // ProdData
);

View File

@@ -9,11 +9,9 @@ use App\Models\{Echoarea,Echomail,Netmail};
*/
abstract class Process
{
public static function canProcess(string $echoarea): bool
public static function canProcess(Echoarea $eao): bool
{
$eao = Echoarea::where('name',$echoarea)->single();
return $eao && $eao->automsgs;
return $eao->automsgs;
}
/**

View File

@@ -27,9 +27,9 @@ final class Test extends Process
|| (! in_array(strtolower($mo->subject),self::testing)))
return FALSE;
Log::info(sprintf('%s:- Processing TEST message from (%s) [%s] in [%s]',self::LOGKEY,$msg->user_from,$msg->fftn,$msg->echoarea));
Log::info(sprintf('%s:- Processing TEST message from (%s) [%s] in [%s]',self::LOGKEY,$mo->from,$mo->fftn->ftn,$mo->echoarea->name));
Notification::route('echomail',$mo->echoarea)->notify(new TestNotification($msg));
Notification::route('echomail',$mo->echoarea->withoutRelations())->notify(new TestNotification($mo));
return TRUE;
}

View File

@@ -5,7 +5,8 @@ namespace App\Classes\FTN\Process\Netmail;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Log;
use App\Classes\FTN\{Message,Process};
use App\Classes\FTN\Process;
use App\Models\{Echomail,Netmail};
use App\Notifications\Netmails\Areafix as AreafixNotification;
use App\Notifications\Netmails\Areafix\NotConfiguredHere as AreafixNotConfiguredHereNotification;
@@ -18,18 +19,18 @@ final class Areafix extends Process
{
private const LOGKEY = 'RP-';
public static function handle(Message $msg): bool
public static function handle(Echomail|Netmail $mo): bool
{
if (strtolower($msg->user_to) !== 'areafix')
if (strtolower($mo->to) !== 'areafix')
return FALSE;
Log::info(sprintf('%s:- Processing AREAFIX message from (%s) [%s]',self::LOGKEY,$msg->user_from,$msg->fftn));
Log::info(sprintf('%s:- Processing AREAFIX message from (%s) [%s]',self::LOGKEY,$mo->from,$mo->fftn));
// If this is not a node we manage, then respond with a sorry can help you
if ($msg->fftn_o->system->sessions->count())
Notification::route('netmail',$msg->fftn_o)->notify(new AreafixNotification($msg));
if ($mo->fftn->system->sessions->count())
Notification::route('netmail',$mo->fftn)->notify(new AreafixNotification($mo));
else
Notification::route('netmail',$msg->fftn_o)->notify(new AreafixNotConfiguredHereNotification($msg));
Notification::route('netmail',$mo->fftn)->notify(new AreafixNotConfiguredHereNotification($mo));
return TRUE;
}

View File

@@ -5,7 +5,8 @@ namespace App\Classes\FTN\Process\Netmail;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Log;
use App\Classes\FTN\{Message,Process};
use App\Classes\FTN\Process;
use App\Models\{Echomail,Netmail};
use App\Notifications\Netmails\Ping as PingNotification;
/**
@@ -17,14 +18,14 @@ final class Ping extends Process
{
private const LOGKEY = 'RP-';
public static function handle(Message $msg): bool
public static function handle(Echomail|Netmail $mo): bool
{
if (strtolower($msg->user_to) !== 'ping')
if (strtolower($mo->to) !== 'ping')
return FALSE;
Log::info(sprintf('%s:- Processing PING message from (%s) [%s]',self::LOGKEY,$msg->user_from,$msg->fftn));
Log::info(sprintf('%s:- Processing PING message from (%s) [%s]',self::LOGKEY,$mo->from,$mo->fftn->ftn));
Notification::route('netmail',$msg->fftn_o)->notify(new PingNotification($msg));
Notification::route('netmail',$mo->fftn)->notify(new PingNotification($mo));
return TRUE;
}