Start of processing packets - implemented PING Responce to Netmail

This commit is contained in:
Deon George
2021-07-16 00:54:23 +10:00
parent fe2784f98f
commit a0d3c8d8ab
22 changed files with 1256 additions and 442 deletions

View File

@@ -9,12 +9,10 @@ use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\File\File;
use App\Classes\FTN as FTNBase;
use App\Models\Software;
use App\Traits\GetNode;
use App\Models\{Address,Domain,Setup,Software};
class Packet extends FTNBase
{
//use GetNode;
private const LOGKEY = 'PKT';
private const HEADER_LEN = 0x3a;
@@ -22,10 +20,6 @@ class Packet extends FTNBase
private const BLOCKSIZE = 1024;
private const PACKED_MSG_HEADER_LEN = 0x22;
public File $file; // Packet filename
public Collection $messages; // Messages in the Packet
private array $header; // Packet Header
// V2 Packet Header (2/2e/2+)
private const v2header = [
'onode' => [0x00,'v',2], // Originating Node
@@ -54,17 +48,113 @@ class Packet extends FTNBase
'dzone' => [0x30,'v',2], // Destination Zone (Not used 2)
'opoint' => [0x32,'v',2], // Originating Point (Not used 2)
'dpoint' => [0x34,'v',2], // Destination Point (Not used 2)
'proddata' => [0x36,'A4',4], // ProdData (Not used 2) // FSC-39/FSC-48
'proddata' => [0x36,'a4',4], // ProdData (Not used 2) // FSC-39/FSC-48
];
public function __construct(File $file)
private array $header; // Packet Header
public File $file; // Packet filename
public Collection $messages; // Messages in the Packet
public function __construct(Address $o=NULL)
{
$this->messages = collect();
$this->domain = NULL;
if ($file) {
$this->file = $file;
$this->open($file);
// If we are creating an outbound packet, we need to set our header
if ($o)
$this->newHeader($o);
}
/**
* Open a packet file
*
* @param File $file
* @param Domain|null $domain
* @return Packet
* @throws InvalidPacketException
*/
public static function open(File $file,Domain $domain=NULL): self
{
Log::debug(sprintf('%s:Opening Packet [%s]',self::LOGKEY,$file));
$f = fopen($file,'r');
$fstat = fstat($f);
// PKT Header
$header = fread($f,self::HEADER_LEN);
Log::debug(sprintf("%s:\n%s",self::LOGKEY,hex_dump($header)));
// Could not read header
if (strlen($header) != self::HEADER_LEN)
throw new InvalidPacketException(sprintf('Length of header [%d] too short'.strlen($header)));
// Not a type 2 packet
$version = Arr::get(unpack('vv',substr($header,self::VERSION_OFFSET)),'v');
if ($version != 2)
throw new InvalidPacketException('Not a type 2 packet: '.$version);
$o = new self;
$o->header = unpack(self::unpackheader(self::v2header),$header);
$x = fread($f,2);
// End of Packet?
if (strlen($x) == 2 and $x == "\00\00")
return new self;
// Messages start with 02H 00H
if (strlen($x) == 2 AND $x != "\02\00")
throw new InvalidPacketException('Not a valid packet: '.bin2hex($x));
// No message attached
else if (! strlen($x))
throw new InvalidPacketException('No message in packet: '.bin2hex($x));
$buf_ptr = 0;
$message = '';
$readbuf = '';
while ($buf_ptr || (! feof($f) && ($readbuf=fread($f,self::BLOCKSIZE)))) {
// A message header is atleast 0x22 chars long
if (strlen($readbuf) < self::PACKED_MSG_HEADER_LEN) {
$message .= $readbuf;
$buf_ptr = 0;
continue;
} elseif (strlen($message) < self::PACKED_MSG_HEADER_LEN) {
$addchars = self::PACKED_MSG_HEADER_LEN-strlen($message);
$message .= substr($readbuf,$buf_ptr,$addchars);
$buf_ptr += $addchars;
}
// If we didnt find a packet end, perhaps there are no more
if (($end=strpos($readbuf,"\x00\x02\x00",$buf_ptr)) === FALSE) {
$end = strpos($readbuf,"\x00\x00\x00",$buf_ptr);
}
// See if we have found the end of the packet, if not read more.
if ($end === FALSE && (ftell($f) < $fstat['size'])) {
$message .= substr($readbuf,$buf_ptr);
$buf_ptr = 0;
continue;
} else {
$message .= substr($readbuf,$buf_ptr,$end-$buf_ptr);
$buf_ptr = $end+3;
if ($buf_ptr >= strlen($readbuf))
$buf_ptr = 0;
}
// Look for the next message
$o->parseMessage($message,$domain);
$message = '';
}
return $o;
}
/**
@@ -132,31 +222,14 @@ class Packet extends FTNBase
}
}
// @note - messages in this object have the same next destination
// @todo To rework
/*
/**
* Return the packet
*
* @return string
* @throws \Exception
*/
public function __toString(): string
{
// @todo - is this appropriate to set here
$this->date = now();
$this->pktsrc = (string)$this->get_node(ftn_address_split('10:1/5.0'),TRUE);
// @todo
if ($this->messages->first()->type == 'echomail')
$this->pktdst = (string)$this->messages->first()->fqfa->uplink;
else
$this->pktdst = (string)$this->messages->first()->fqda->uplink;
$this->software['prodcode-lo'] = 0x00;
$this->software['prodcode-hi'] = 0xde;
$this->software['rev-maj'] = 0x00;
$this->software['rev-min'] = 0x01;
// Type 2+ Packet
$this->cap['valid'] = 0x0100;
$this->cap['word'] = 0x0001;
$this->pktver = 0x0002;
$return = $this->createHeader();
foreach ($this->messages as $o)
@@ -166,143 +239,101 @@ class Packet extends FTNBase
return $return;
}
*/
/**
* Create our message packet header
* @todo To rework
*/
/*
private function createHeader(): string
{
try {
$a = pack(join('',collect($this->pack1)->pluck(1)->toArray()),
$a = pack(join('',collect(self::v2header)->pluck(1)->toArray()),
$this->ff,
$this->tf,
$this->date->year,
$this->date->month,
$this->date->day,
$this->date->hour,
$this->date->minute,
$this->date->second,
$this->baud,
$this->pktver,
$this->fn, // @todo if point, this needs to be 0xff
Arr::get($this->header,'y'),
Arr::get($this->header,'m'),
Arr::get($this->header,'d'),
Arr::get($this->header,'H'),
Arr::get($this->header,'M'),
Arr::get($this->header,'S'),
Arr::get($this->header,'baud',0),
Arr::get($this->header,'pktver',2),
$this->fn, // @todo if point, this needs to be 0xff
$this->tn,
$this->software['prodcode-lo'], // @todo change to this software
$this->software['rev-maj'] // @todo change to this software
);
$b = pack(join('',collect($this->pack2)->pluck(1)->toArray()),
0x0000, // @note: Type 2 packet this is $this->sz,
0x0000, // @note: Type 2 packet this is $this->dz,
0x0000, // Filler $this->>sn if message to point.
$this->cap['valid'], // @todo to check
$this->software['prodcode-hi'], // @todo change to this software
$this->software['rev-min'], // @todo change to this software
$this->cap['word'], // @todo to check
Arr::get($this->header,'prodcode-lo',(Setup::PRODUCT_ID & 0xff)),
Arr::get($this->header,'prodrev-maj',Setup::PRODUCT_VERSION_MAJ),
$this->password,
$this->fz,
$this->tz,
$this->fp, // @note: point address, type 2+ packets
$this->tp // @note: point address, type 2+ packets
Arr::get($this->header,'filler',''),
Arr::get($this->header,'capvalid',1<<0),
Arr::get($this->header,'prodcode-hi',(Setup::PRODUCT_ID >> 8) & 0xff),
Arr::get($this->header,'prodrev-min',Setup::PRODUCT_VERSION_MIN),
Arr::get($this->header,'capword',1<<0),
$this->fz,
$this->tz,
$this->fp,
$this->tp,
Arr::get($this->header,'proddata','AB8D'),
);
return $a.pack('a8',strtoupper($this->password)).$b."mbse"; // @todo change to this software
return $a;
} catch (\Exception $e) {
return $e->getMessage();
}
}
public function addMessage(FTNMessage $o)
/**
* Add a netmail message to this packet
*
* @param Message $o
*/
public function addNetmail(Message $o): void
{
// @todo Check that this message is for the same uplink.
$this->messages->push($o);
}
*/
/**
* Open a packet file
* When creating a new packet, set the header.
*
* @param string $file
* @throws InvalidPacketException
* @param array $header
*/
private function open(string $file)
private function newHeader(Address $o): void
{
Log::debug(sprintf('%s:Opening Packet [%s]',self::LOGKEY,$file));
$date = Carbon::now();
$ao = Setup::findOrFail(config('app.id'))->system->match($o);
$f = fopen($file,'r');
$fstat = fstat($f);
// Create Header
$this->header = [
'onode' => $ao->node_id, // Originating Node
'dnode' => $o->node_id, // Destination Node
'y' => $date->format('Y'), // Year
'm' => $date->format('m')-1, // Month
'd' => $date->format('d'), // Day
'H' => $date->format('H'), // Hour
'M' => $date->format('i'), // Minute
'S' => $date->format('s'), // Second
'onet' => $ao->host_id ?: $ao->region_id, // Originating Net (0xffff when origPoint !=0 2+)
'dnet' => $o->host_id ?: $o->region_id, // Destination Net
'password' => $o->session('pktpass'), // Packet Password
'qozone' => $ao->zone->zone_id,
'qdzone' => $o->zone->zone_id,
'ozone' => $ao->zone->zone_id, // Originating Zone (Not used 2)
'dzone' => $o->zone->zone_id, // Destination Zone (Not used 2)
'opoint' => $ao->point_id, // Originating Point (Not used 2)
'dpoint' => $o->point_id, // Destination Point (Not used 2)
];
}
// PKT Header
$header = fread($f,self::HEADER_LEN);
Log::debug(sprintf("%s:\n%s",self::LOGKEY,hex_dump($header)));
// Could not read header
if (strlen($header) != self::HEADER_LEN)
throw new InvalidPacketException(sprintf('Length of header [%d] too short'.strlen($header)));
// Not a type 2 packet
$version = Arr::get(unpack('vv',substr($header,self::VERSION_OFFSET)),'v');
if ($version != 2)
throw new InvalidPacketException('Not a type 2 packet: '.$version);
$this->header = unpack($this->unpackheader(self::v2header),$header);
$x = fread($f,2);
// End of Packet?
if (strlen($x) == 2 and $x == "\00\00")
return;
// Messages start with 02H 00H
if (strlen($x) == 2 AND $x != "\02\00")
throw new InvalidPacketException('Not a valid packet: '.bin2hex($x));
// No message attached
else if (! strlen($x))
throw new InvalidPacketException('No message in packet: '.bin2hex($x));
$buf_ptr = 0;
$message = '';
$readbuf = '';
while ($buf_ptr || (! feof($f) && ($readbuf=fread($f,self::BLOCKSIZE)))) {
// A message header is atleast 0x22 chars long
if (strlen($readbuf) < self::PACKED_MSG_HEADER_LEN) {
$message .= $readbuf;
$buf_ptr = 0;
continue;
} elseif (strlen($message) < self::PACKED_MSG_HEADER_LEN) {
$addchars = self::PACKED_MSG_HEADER_LEN-strlen($message);
$message .= substr($readbuf,$buf_ptr,$addchars);
$buf_ptr += $addchars;
}
// If we didnt find a packet end, perhaps there are no more
if (($end=strpos($readbuf,"\x00\x02\x00",$buf_ptr)) === FALSE)
$end = strpos($readbuf,"\x00\x00\x00",$buf_ptr);
// See if we have found the end of the packet, if not read more.
if ($end === FALSE && (ftell($f) < $fstat['size'])) {
$message .= substr($readbuf,$buf_ptr);
$buf_ptr = 0;
continue;
} else {
$message .= substr($readbuf,$buf_ptr,$end-$buf_ptr);
$buf_ptr += $end-$buf_ptr+3;
if ($buf_ptr >= strlen($readbuf))
$buf_ptr = 0;
}
// Look for the next message
$this->messages->push(new Message($message));
$message = '';
}
/**
* Parse a message in a mail packet
*
* @param string $message
* @param Domain $domain
* @throws \Exception
*/
public function parseMessage(string $message,Domain $domain=NULL): void
{
$this->messages->push(Message::parseMessage($message,$domain));
}
}