clrghouz/app/Jobs/PacketProcess.php
Deon George 81f59dcbb8
All checks were successful
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 42s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 1m50s
Create Docker Image / Final Docker Image Manifest (push) Successful in 11s
Remove EncodeUTF8 infavour of using attribute casting only. The implementation of EncodeUTF8 was not correct, essentially removing any previous casting causing issues when saving a record.
2024-06-01 10:46:02 +10:00

192 lines
6.8 KiB
PHP

<?php
namespace App\Jobs;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Storage;
use League\Flysystem\UnableToMoveFile;
use App\Classes\File;
use App\Classes\FTN\Packet;
use App\Exceptions\InvalidPacketException;
use App\Models\{Domain,Echomail,Netmail};
use App\Notifications\Netmails\PacketPasswordInvalid;
class PacketProcess implements ShouldQueue
{
private const LOGKEY = 'JPP';
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private string $filename;
private Domain $do;
private Carbon $rcvd_time;
private bool $interactive;
private bool $nobot;
public function __construct(string $filename,Domain $do,bool $interactive=TRUE,Carbon $rcvd_time=NULL,bool $nobot=FALSE)
{
$this->filename = $filename;
$this->do = $do;
$this->interactive = $interactive;
$this->rcvd_time = $rcvd_time ?: Carbon::now();
$this->nobot = $nobot;
}
public function __get($key): mixed
{
switch ($key) {
case 'jobname':
return $this->filename;
default:
return NULL;
}
}
/**
* When calling MessageProcess - we assume that the packet is from a valid source, and
* the destination (netmail/echomail) is also valid
*/
public function handle()
{
Log::info(sprintf('%s:- Processing mail [%s]',self::LOGKEY,$this->filename));
$fs = Storage::disk(config('fido.local_disk'));
// @todo Catch files that we cannot process, eg: ARJ bundles.
try {
$f = new File($fs->path($this->filename));
$processed = FALSE;
foreach ($f as $packet) {
$pkt = Packet::process($packet,Arr::get(stream_get_meta_data($packet),'uri'),$f->itemSize(),$this->do);
// Check that the packet is from a system that is defined in the DB
if (! $pkt->fftn) {
Log::error(sprintf('%s:! Packet [%s] is not from a system we know about? [%s]',self::LOGKEY,$this->filename,$pkt->fftn_t));
break;
}
if (! our_nodes($pkt->fftn->zone->domain)->contains($pkt->fftn)) {
Log::error(sprintf('%s:! Packet [%s] is from a system that is not configured with us? [%s] for [%s]',self::LOGKEY,$this->filename,$pkt->fftn_t,$this->do->name));
// @todo Notification::route('netmail',$pkt->fftn)->notify(new UnexpectedPacketFromYou($this->filename));
// @todo Parse the packet for netmails and process them. We'll only accept netmails to us, and ignore all others
break;
}
// Check the packet is to our address, if not we'll reject it.
if (! our_address($pkt->tftn->zone->domain)->contains($pkt->tftn)) {
Log::error(sprintf('%s:! Packet [%s] is not to our address? [%s]',self::LOGKEY,$this->filename,$pkt->tftn->ftn));
// @todo Notification::route('netmail',$pkt->fftn)->notify(new UnexpectedPacketToUs($this->filename));
break;
}
// Check the packet password
if (strtoupper($pkt->fftn->session('pktpass')) !== strtoupper($pkt->password)) {
Log::error(sprintf('%s:! Packet from [%s] with password [%s] is invalid.',self::LOGKEY,$pkt->fftn->ftn,$pkt->password));
Notification::route('netmail',$pkt->fftn)->notify(new PacketPasswordInvalid($pkt->password,$f->pktName()));
break;
}
Log::info(sprintf('%s:- Packet has [%d] messages',self::LOGKEY,$pkt->count()));
// Queue messages if there are too many in the packet.
if ($queue = ($pkt->count() > config('fido.queue_msgs')))
Log::info(sprintf('%s:- Messages will be sent to the queue for processing',self::LOGKEY));
$count = 0;
foreach ($pkt as $msg) {
if ($msg instanceof Netmail)
Log::info(sprintf('%s:- Netmail from [%s] to [%s]',self::LOGKEY,$msg->fftn->ftn,$msg->tftn->ftn));
elseif ($msg instanceof Echomail)
Log::info(sprintf('%s:- Echomail from [%s]',self::LOGKEY,$msg->fftn->ftn));
if ($msg->errors->count()) {
Log::error(sprintf('%s:! Message [%s] has [%d] errors, unable to process',self::LOGKEY,$msg->msgid,$msg->errors->count()));
continue;
}
$msg->set_sender = $pkt->fftn->withoutRelations();
// Record receiving packet and sender
$msg->set_pkt = $f->pktName();
$msg->set_recvtime = $this->rcvd_time;
if ($queue || (! $this->interactive))
Log::info(sprintf('%s:! Message [%s] will be sent to the queue to process',self::LOGKEY,$msg->msgid));
//dump(['msg'=>$msg]);
Log::debug('***',['a']);
try {
// Dispatch job.
if ($queue || (! $this->interactive))
MessageProcess::dispatch($msg->withoutRelations(),$this->nobot);
else
MessageProcess::dispatchSync($msg->withoutRelations(),$this->nobot);
Log::debug('***',['b']);
$count++;
} catch (\Exception $e) {
Log::debug('***',['c']);
Log::error(sprintf('%s:! Got error [%s] dispatching message [%s] (%d:%s-%s).',self::LOGKEY,get_class($e),$msg->msgid,$e->getLine(),$e->getFile(),$e->getMessage()));
}
}
if ($count === $pkt->count())
$processed = TRUE;
}
if (! $processed) {
Log::alert(sprintf('%s:- Not deleting packet [%s], it doesnt seem to be processed?',self::LOGKEY,$this->filename));
} else {
// If we want to keep the packet, we could do that logic here
if (config('fido.packet_keep')) {
$dir = sprintf('%s/%s/%s/%s',config('fido.dir'),($x=Carbon::now())->format('Y'),$x->format('m'),$x->format('d'));
Log::debug(sprintf('%s:- Moving processed packet [%s] to [%s]',self::LOGKEY,$this->filename,$dir));
try {
if ($fs->makeDirectory($dir)) {
$fs->move($this->filename,$x=sprintf('%s/%s',$dir,$f->itemName()));
Log::info(sprintf('%s:- Moved processed packet [%s] to [%s]',self::LOGKEY,$this->filename,$x));
} else
Log::error(sprintf('%s:! Unable to create dir [%s]',self::LOGKEY,$dir));
} catch (UnableToMoveFile $e) {
Log::error(sprintf('%s:! Unable to move packet [%s] to [%s] (%s)',self::LOGKEY,$this->filename,$dir,$e->getMessage()));
} catch (\Exception $e) {
Log::error(sprintf('%s:! Failed moving packet [%s] to [%s] (%s)',self::LOGKEY,$this->filename,$dir,$e->getMessage()));
}
} else {
Log::debug(sprintf('%s:- Deleting processed packet [%s]',self::LOGKEY,$this->filename));
$fs->delete($this->filename);
}
}
} catch (InvalidPacketException $e) {
Log::error(sprintf('%s:- Not deleting packet [%s], as it generated an InvalidPacketException',self::LOGKEY,$this->filename),['e'=>$e->getMessage()]);
} catch (\Exception $e) {
Log::error(sprintf('%s:- Not deleting packet [%s], as it generated an uncaught exception',self::LOGKEY,$this->filename),['e'=>$e->getMessage(),'l'=>$e->getLine(),'f'=>$e->getFile()]);
}
}
}