Start of processing packets - implemented PING Responce to Netmail
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user