Move mailer details into a separate table

This commit is contained in:
2023-07-07 23:59:04 +10:00
parent ad4ea699a5
commit ccdce6bb62
12 changed files with 274 additions and 112 deletions

View File

@@ -87,12 +87,12 @@ abstract class Protocol
protected const O_YES = 1<<5;
// Session Status
protected const S_OK = 0;
public const S_OK = 0;
protected const S_NODIAL = 1;
protected const S_REDIAL = 2;
protected const S_BUSY = 3;
protected const S_FAILURE = 4;
protected const S_MASK = 7;
public const S_MASK = 7;
protected const S_HOLDR = 8;
protected const S_HOLDX = 16;
protected const S_HOLDA = 32;
@@ -324,10 +324,10 @@ abstract class Protocol
* @param int $type
* @param SocketClient $client
* @param Address|null $o
* @return void
* @return int
* @throws \Exception
*/
public function session(int $type,SocketClient $client,Address $o=NULL): void
public function session(int $type,SocketClient $client,Address $o=NULL): int
{
if ($o->exists)
Log::withContext(['ftn'=>$o->ftn]);
@@ -370,7 +370,7 @@ abstract class Protocol
if ($rc < 0) {
Log::error(sprintf('%s:! Unable to start EMSI [%d]',self::LOGKEY,$rc));
return;
return self::S_FAILURE;
}
case self::SESSION_EMSI:
@@ -389,14 +389,13 @@ abstract class Protocol
Log::debug(sprintf('%s:- Starting ZMODEM',self::LOGKEY));
$this->client->speed = self::TCP_SPEED;
$this->originate = FALSE;
$this->protocol_session();
return;
return $this->protocol_session();
default:
Log::error(sprintf('%s:! Unsupported session type [%d]',self::LOGKEY,$type));
return;
return self::S_FAILURE;
}
// @todo Unlock outbounds
@@ -453,6 +452,8 @@ abstract class Protocol
// @todo Optional after session includes mail event
// if ($this->node->start_time && $this->setup->cfg('CFG_AFTERMAIL')) {}
return $rc;
}
/* SE_* flags determine our session processing status, at any point in time */

View File

@@ -194,16 +194,16 @@ final class DNS extends BaseProtocol
$ao = Address::findFTN(sprintf('%d:%d/%d.%d@%s',$z,$n,$f,$p,$d));
// Check we have the right record
if ((! $ao) || (! $ao->system->mailer_address) || (($rootdn !== self::TLD) && ((! $ao->zone->domain->dnsdomain) || ($ao->zone->domain->dnsdomain !== $d.'.'.$rootdn)))) {
if ((! $ao) || (! $ao->system->address) || (($rootdn !== self::TLD) && ((! $ao->zone->domain->dnsdomain) || ($ao->zone->domain->dnsdomain !== $d.'.'.$rootdn)))) {
Log::alert(sprintf('%s:= No DNS record for [%d:%d/%d.%d@%s]',self::LOGKEY,$z,$n,$f,$p,$d));
return $this->nameerr();
}
Log::debug(sprintf('%s:= Returning [%s] for DNS query [%s]',self::LOGKEY,$ao->system->mailer_address,$ao->ftn));
Log::debug(sprintf('%s:= Returning [%s] for DNS query [%s]',self::LOGKEY,$ao->system->address,$ao->ftn));
return $this->reply(
self::DNS_NOERROR,
[serialize($this->domain_split($ao->system->mailer_address)) => self::DNS_TYPE_CNAME]);
[serialize($this->domain_split($ao->system->address)) => self::DNS_TYPE_CNAME]);
// Other attributes return NOTIMPL
default:

View File

@@ -6,7 +6,7 @@ use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\Log;
use App\Models\Address;
use App\Models\{Address,Mailer};
use App\Jobs\AddressPoll as Job;
class CommBinkpSend extends Command
@@ -25,6 +25,8 @@ class CommBinkpSend extends Command
*/
protected $description = 'BINKP send';
private const ID = 'BINKP';
/**
* Execute the console command.
*
@@ -34,10 +36,12 @@ class CommBinkpSend extends Command
{
Log::info('CBS:- Call BINKP send');
$mo = Mailer::where('name',self::ID)->singleOrFail();
$ao = Address::findFTN($this->argument('ftn'));
if (! $ao)
throw new ModelNotFoundException('Unknown node: '.$this->argument('ftn'));
Job::dispatchSync($ao);
Job::dispatchSync($ao,$mo);
}
}

View File

@@ -6,7 +6,7 @@ use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\Log;
use App\Models\Address;
use App\Models\{Address,Mailer};
use App\Jobs\AddressPoll as Job;
class CommEMSISend extends Command
@@ -25,6 +25,8 @@ class CommEMSISend extends Command
*/
protected $description = 'EMSI send';
private const ID = 'EMSI';
/**
* Execute the console command.
*
@@ -32,12 +34,14 @@ class CommEMSISend extends Command
*/
public function handle(): void
{
Log::info('Call EMSI send');
Log::info('CES:- Call EMSI send');
$mo = Mailer::where('name',self::ID)->singleOrFail();
$ao = Address::findFTN($this->argument('ftn'));
if (! $ao)
throw new ModelNotFoundException('Unknown node: '.$this->argument('ftn'));
Job::dispatchSync($ao);
Job::dispatchSync($ao,$mo);
}
}

View File

@@ -276,11 +276,17 @@ class SystemController extends Controller
$this->authorize('update',$o);
if ($request->post()) {
foreach (['name','location','sysop','hold','phone','address','port','active','method','notes','mailer_type','mailer_address','mailer_port','zt_id','pkt_type'] as $key)
foreach (['name','location','sysop','hold','phone','address','port','active','method','notes','zt_id','pkt_type'] as $key)
$o->{$key} = $request->post($key);
$o->save();
$mailers = collect($request->post('mailer_details'))
->filter(function($item) { return $item['port']; })
->transform(function($item) { $item['active'] = Arr::get($item,'active',FALSE); return $item; });
$o->mailers()->sync($mailers);
return redirect()->action([self::class,'home']);
}
@@ -687,7 +693,7 @@ class SystemController extends Controller
if (! $o->exist) {
$o->sysop = Auth::user()->name;
foreach (['name','zt_id','location','mailer_type','mailer_address','mailer_port','phone','method','address','port'] as $item)
foreach (['name','zt_id','location','phone','method','address','port'] as $item)
if ($request->{$item})
$o->{$item} = $request->{$item};

View File

@@ -56,9 +56,8 @@ class SystemRegister extends FormRequest
'address' => 'nullable|regex:/^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$/i',
'port' => 'nullable|digits_between:2,5',
'method' => 'nullable|numeric',
'mailer_type' => 'nullable|numeric',
'mailer_address' => 'nullable|regex:/^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$/i',
'mailer_port' => 'nullable|digits_between:2,5',
'mailer_details.*' => 'nullable|array',
'mailer_details.*.port' => 'nullable|digits_between:2,5',
'zt_id' => 'nullable|size:10|regex:/^([A-Fa-f0-9]){10}$/|unique:systems,zt_id,'.($this->so->exists ? $this->so->id : 0),
'pkt_type' => ['required',Rule::in(array_keys(Packet::PACKET_TYPES))],
] : [],

View File

@@ -9,10 +9,11 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use App\Classes\Protocol;
use App\Classes\Protocol\{Binkp,EMSI};
use App\Classes\Sock\SocketClient;
use App\Classes\Sock\SocketException;
use App\Models\{Address,Setup};
use App\Models\{Address,Mailer,Setup};
class AddressPoll implements ShouldQueue
{
@@ -21,11 +22,12 @@ class AddressPoll implements ShouldQueue
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private Address $ao;
private ?Mailer $mo;
public function __construct(Address $ao)
public function __construct(Address $ao,Mailer $mo=NULL)
{
// Some checks
$this->ao = $ao;
$this->mo = $mo;
}
/**
@@ -33,34 +35,49 @@ class AddressPoll implements ShouldQueue
*/
public function handle()
{
if ((! $this->ao->system->mailer_address) || (! $this->ao->system->mailer_port))
if (! $this->ao->system->mailer_preferred->count() || ($this->mo && (! $this->ao->system->mailer_preferred->find($this->mo))))
throw new \Exception(sprintf('Unable to poll [%s] missing mailer details',$this->ao->ftn));
try {
$client = SocketClient::create($this->ao->system->mailer_address,$this->ao->system->mailer_port);
} catch (SocketException $e) {
Log::error(sprintf('%s:! Unable to connect to [%s]: %s',self::LOGKEY,$this->ao->ftn,$e->getMessage()));
abort(500);
}
foreach ($this->ao->system->mailer_preferred as $o) {
// If we chose a protocol, skip to find the mailer details for it
if ($this->mo && ($o->id !== $this->mo->id))
continue;
switch ($this->ao->system->mailer_type) {
case Setup::O_BINKP:
$o = new Binkp(Setup::findOrFail(config('app.id')));
$o->session(Binkp::SESSION_BINKP,$client,$this->ao);
Log::info(sprintf('%s:- Starting a [%s] session to [%s:%d]',self::LOGKEY,$o->name,$this->ao->system->address,$o->pivot->port));
try {
$client = SocketClient::create($this->ao->system->address,$o->pivot->port);
} catch (SocketException $e) {
Log::error(sprintf('%s:! Unable to connect to [%s]: %s',self::LOGKEY,$this->ao->ftn,$e->getMessage()));
abort(500);
}
switch ($o->name) {
case 'BINKP':
$s = new Binkp(Setup::findOrFail(config('app.id')));
$session = Binkp::SESSION_BINKP;
break;
case 'EMSI':
$s = new EMSI(Setup::findOrFail(config('app.id')));
$session = EMSI::SESSION_AUTO;
break;
default:
throw new \Exception(sprintf('Node [%s] has a mailer type that is unhandled',$this->ao->ftn));
}
if (($s->session($session,$client,$this->ao) & Protocol::S_MASK) === Protocol::S_OK) {
Log::info(sprintf('%s:= Connection ended successfully with [%s]',self::LOGKEY,$client->address_remote));
break;
case Setup::O_EMSI:
$o = new EMSI(Setup::findOrFail(config('app.id')));
$o->session(EMSI::SESSION_AUTO,$client,$this->ao);
break;
default:
throw new \Exception(sprintf('Node [%s] has a mailer type that is unhandled',$this->ao->ftn));
} else {
Log::alert(sprintf('%s:! Connection failed to [%s]',self::LOGKEY,$client->address_remote));
}
}
Log::info(sprintf('%s:Connection ended: %s',self::LOGKEY,$client->address_remote));
}
}

31
app/Models/Mailer.php Normal file
View File

@@ -0,0 +1,31 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Mailer extends Model
{
public $timestamps = FALSE;
private const SORTORDER = [
'BINKP'=>1,
'EMSI'=>2,
];
/* RELATIONS */
public function system()
{
return $this->belongsTo(System::class);
}
/* SCOPES */
public function scopePreferred($query)
{
return $query
->orderBy('priority','ASC')
->where('mailer_system.active',TRUE);
}
}

View File

@@ -48,6 +48,18 @@ class System extends Model
->active();
}
public function mailers()
{
return $this->belongsToMany(Mailer::class)
->withPivot(['last_poll','port','attempts','active']);
}
public function mailer_preferred()
{
return $this->mailers()
->preferred();
}
public function logs()
{
return $this->hasMany(SystemLog::class);
@@ -119,11 +131,11 @@ class System extends Model
public function getAccessMailerAttribute(): string
{
switch ($this->mailer_type) {
case Setup::O_BINKP: return sprintf('binkp://%s:%s',$this->mailer_address,$this->mailer_port);
case Setup::O_EMSI: return sprintf('emsi://%s:%s',$this->mailer_address,$this->mailer_port);
switch (($x=$this->mailer_preferred()->first())?->name) {
case 'BINKP': return sprintf('binkp://%s:%s',$this->address,$x->pivot->port);
case 'EMSI': return sprintf('emsi://%s:%s',$this->address,$x->pivot->port);
default:
return $this->mailer_type ? sprintf('%s:%s',$this->address,$this->port) : 'No mailer available.';
return $x?->name ? sprintf('%s:%s',$this->address,$x->pivot->port) : 'No mailer available.';
}
}