Compare commits
3 Commits
8bf58f3daa
...
001618d719
Author | SHA1 | Date | |
---|---|---|---|
001618d719 | |||
bba6f93fbc | |||
1c270025cf |
@ -70,7 +70,7 @@ class HubStats extends Dynamic
|
|||||||
|
|
||||||
$header = "| %-12s | %4d | %3d | %3d | %16s | %5s | %5s |\r\n";
|
$header = "| %-12s | %4d | %3d | %3d | %16s | %5s | %5s |\r\n";
|
||||||
|
|
||||||
$output = sprintf("Hub Status for [%s] as at [%s]\r\n",our_address($this->ao->zone->domain,$this->ao)->ftn,$date);
|
$output = sprintf("Hub Status for [%s] as at [%s]\r\n",our_address($this->ao)->ftn,$date);
|
||||||
$output .= "\r";
|
$output .= "\r";
|
||||||
$output .= "+--------------+------+-----+-----+------------------+-------+-------+\r\n";
|
$output .= "+--------------+------+-----+-----+------------------+-------+-------+\r\n";
|
||||||
$output .= "| FTN | ECHO | NET |FILES| LAST SESSION | MODE |AUTOHLD|\r\n";
|
$output .= "| FTN | ECHO | NET |FILES| LAST SESSION | MODE |AUTOHLD|\r\n";
|
||||||
|
@ -90,7 +90,7 @@ class Tic extends FTNBase
|
|||||||
if (! $this->to)
|
if (! $this->to)
|
||||||
throw new \Exception('No to address defined');
|
throw new \Exception('No to address defined');
|
||||||
|
|
||||||
$sysaddress = our_address($this->to->zone->domain,$this->to);
|
$sysaddress = our_address($this->to);
|
||||||
|
|
||||||
$result = collect();
|
$result = collect();
|
||||||
|
|
||||||
|
32
app/Console/Commands/Debug/AddressCheck.php
Normal file
32
app/Console/Commands/Debug/AddressCheck.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands\Debug;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
use App\Models\Address;
|
||||||
|
|
||||||
|
class AddressCheck extends Command
|
||||||
|
{
|
||||||
|
protected $signature = 'debug:address:check'
|
||||||
|
.' {ftn : FTN}';
|
||||||
|
|
||||||
|
protected $description = 'Check the addresses we use for a node';
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$o = Address::findFTN($this->argument('ftn'));
|
||||||
|
|
||||||
|
if (! $o) {
|
||||||
|
$this->error(sprintf('Address: %s doesnt exist?',$this->argument('ftn')));
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info(sprintf('Address: %s',$o->ftn));
|
||||||
|
$this->info(sprintf('Uplink: %s',$o->parent()?->ftn));
|
||||||
|
$this->info(sprintf('Our Address: %s',our_address($o)?->ftn));
|
||||||
|
$this->info(sprintf('Domain Addresses: %s',our_address($o->zone->domain)->pluck('ftn4d')->join(',')));
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands\Debug;
|
||||||
|
|
||||||
use App\Models\{Domain};
|
|
||||||
use App\Models\Address;
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
use App\Models\{Address,Domain};
|
||||||
|
|
||||||
class ZoneCheck extends Command
|
class ZoneCheck extends Command
|
||||||
{
|
{
|
||||||
protected $signature = 'zone:check'
|
protected $signature = 'debug:zone:check'
|
||||||
.' {domain : Domain Name}'
|
.' {domain : Domain Name}'
|
||||||
.' {--Z|zone= : Zone}';
|
.' {--Z|zone= : Zone}';
|
||||||
|
|
||||||
@ -25,12 +25,13 @@ class ZoneCheck extends Command
|
|||||||
$this->warn('Zone: '.$zo->zone_id);
|
$this->warn('Zone: '.$zo->zone_id);
|
||||||
$this->info(sprintf('- Our address(es): %s',our_address($do)->pluck('ftn4d')->join(',')));
|
$this->info(sprintf('- Our address(es): %s',our_address($do)->pluck('ftn4d')->join(',')));
|
||||||
|
|
||||||
$this->table(['id','ftn','role','parent','region_id','host_id','hub_id','system','notes'],$zo->addresses()->FTNorder()->active()->with(['system'])->get()->transform(function($item) {
|
$this->table(['id','ftn','role','parent','our_address','region_id','host_id','hub_id','system','notes'],$zo->addresses()->FTNorder()->active()->with(['system'])->get()->transform(function($item) {
|
||||||
return [
|
return [
|
||||||
'id'=>$item->id,
|
'id'=>$item->id,
|
||||||
'ftn'=>$item->ftn4d,
|
'ftn'=>$item->ftn4d,
|
||||||
'role'=>$item->role_name,
|
'role'=>$item->role_name,
|
||||||
'parent'=>$item->parent()?->ftn4d,
|
'parent'=>($x=$item->parent())?->ftn4d,
|
||||||
|
'our_address'=>$x ? our_address($item->parent())->ftn4d : '',
|
||||||
'region_id'=>$item->region_id,
|
'region_id'=>$item->region_id,
|
||||||
'host_id'=>$item->host_id,
|
'host_id'=>$item->host_id,
|
||||||
'hub_id'=>$item->hub_id,
|
'hub_id'=>$item->hub_id,
|
@ -14,14 +14,41 @@ use App\Classes\FTN\{Message,Packet};
|
|||||||
use App\Exceptions\InvalidFTNException;
|
use App\Exceptions\InvalidFTNException;
|
||||||
use App\Traits\ScopeActive;
|
use App\Traits\ScopeActive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This represents an FTN AKA.
|
||||||
|
*
|
||||||
|
* If an address is active, it belongs to the system. There can only be 1 active FTN (z:h/n.p@d)
|
||||||
|
* If an address is not active, it belonged to the system at a point in time in the past.
|
||||||
|
*
|
||||||
|
* If an address is validated, we know that the system is using the address (we've confirmed that during a session).
|
||||||
|
* Any mail for that address will be delivered.
|
||||||
|
*
|
||||||
|
* If an address is not validated, and the session password matches, validate the address.
|
||||||
|
* If the session password doesnt match, treat the address as foreign (dont deliver, unless we originate netmail)
|
||||||
|
*
|
||||||
|
* Session:
|
||||||
|
* + address not active
|
||||||
|
* ++ address validated (shouldnt be the case)
|
||||||
|
* ++ address not validated
|
||||||
|
*
|
||||||
|
* + address active
|
||||||
|
* ++ address validated (give mail/files)
|
||||||
|
* ++ address not validated - validate if the password is correct
|
||||||
|
*
|
||||||
|
* Mail in (from)
|
||||||
|
* ++ address not validated, do not process
|
||||||
|
* ++ address validated, process
|
||||||
|
*
|
||||||
|
* Mail out (to)
|
||||||
|
* ++ address validated, deliver
|
||||||
|
* ++ address not validated, only deliver netmail if we originate the call
|
||||||
|
*/
|
||||||
class Address extends Model
|
class Address extends Model
|
||||||
{
|
{
|
||||||
use ScopeActive,SoftDeletes;
|
use ScopeActive,SoftDeletes;
|
||||||
|
|
||||||
private const LOGKEY = 'MA-';
|
private const LOGKEY = 'MA-';
|
||||||
|
|
||||||
protected $with = ['zone'];
|
|
||||||
|
|
||||||
// http://ftsc.org/docs/frl-1028.002
|
// http://ftsc.org/docs/frl-1028.002
|
||||||
public const ftn_regex = '(\d+):(\d+)/(\d+)(?:\.(\d+))?(?:@([a-zA-Z0-9\-_~]{0,8}))?';
|
public const ftn_regex = '(\d+):(\d+)/(\d+)(?:\.(\d+))?(?:@([a-zA-Z0-9\-_~]{0,8}))?';
|
||||||
|
|
||||||
@ -30,9 +57,9 @@ class Address extends Model
|
|||||||
public const NODE_NC = 1<<2; // Host
|
public const NODE_NC = 1<<2; // Host
|
||||||
public const NODE_HC = 1<<3; // Hub
|
public const NODE_HC = 1<<3; // Hub
|
||||||
public const NODE_ACTIVE = 1<<4; // Node
|
public const NODE_ACTIVE = 1<<4; // Node
|
||||||
public const NODE_PVT = 1<<5; // Pvt
|
public const NODE_PVT = 1<<5; // Pvt (we dont have address information) @todo
|
||||||
public const NODE_HOLD = 1<<6; // Hold
|
public const NODE_HOLD = 1<<6; // Hold (user has requested hold, we havent heard from the node for 7 days @todo
|
||||||
public const NODE_DOWN = 1<<7; // Down
|
public const NODE_DOWN = 1<<7; // Down we havent heard from the node for 30 days @todo
|
||||||
public const NODE_POINT = 1<<8; // Point
|
public const NODE_POINT = 1<<8; // Point
|
||||||
public const NODE_UNKNOWN = 1<<15; // Unknown
|
public const NODE_UNKNOWN = 1<<15; // Unknown
|
||||||
public const NODE_ALL = 0xFFF; // Mask to catch all nodes
|
public const NODE_ALL = 0xFFF; // Mask to catch all nodes
|
||||||
@ -802,7 +829,7 @@ class Address extends Model
|
|||||||
public function getPacket(Collection $msgs,string $passwd=NULL): ?Packet
|
public function getPacket(Collection $msgs,string $passwd=NULL): ?Packet
|
||||||
{
|
{
|
||||||
$s = Setup::findOrFail(config('app.id'));
|
$s = Setup::findOrFail(config('app.id'));
|
||||||
$ao = our_address($this->zone->domain,$this);
|
$ao = our_address($this);
|
||||||
|
|
||||||
// If we dont match on the address, we cannot pack mail for that system
|
// If we dont match on the address, we cannot pack mail for that system
|
||||||
if (! $ao) {
|
if (! $ao) {
|
||||||
@ -811,8 +838,7 @@ class Address extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get packet type
|
// Get packet type
|
||||||
$type = collect(Packet::PACKET_TYPES)->get($this->system->pkt_type ?: config('fido.packet_default'));
|
$o = $ao->system->packet();
|
||||||
$o = new $type;
|
|
||||||
$o->addressHeader($ao,$this,$passwd);
|
$o->addressHeader($ao,$this,$passwd);
|
||||||
|
|
||||||
// $oo = Netmail/Echomail Model
|
// $oo = Netmail/Echomail Model
|
||||||
|
@ -214,7 +214,7 @@ final class Echomail extends Model implements Packet
|
|||||||
{
|
{
|
||||||
Log::info(sprintf('%s:+ Bundling [%s]',self::LOGKEY,$this->id));
|
Log::info(sprintf('%s:+ Bundling [%s]',self::LOGKEY,$this->id));
|
||||||
|
|
||||||
$sysaddress = our_address($this->fftn->zone->domain,$this->fftn);
|
$sysaddress = our_address($this->fftn);
|
||||||
|
|
||||||
if (! $sysaddress)
|
if (! $sysaddress)
|
||||||
throw new \Exception(sprintf('%s:! We dont have an address in this network? (%s)',self::LOGKEY,$this->fftn->zone->domain->name));
|
throw new \Exception(sprintf('%s:! We dont have an address in this network? (%s)',self::LOGKEY,$this->fftn->zone->domain->name));
|
||||||
|
@ -210,7 +210,7 @@ final class Netmail extends Model implements Packet
|
|||||||
// Add our address to the VIA line
|
// Add our address to the VIA line
|
||||||
$via->push(
|
$via->push(
|
||||||
sprintf('%s @%s.UTC %s %d.%d/%s %s',
|
sprintf('%s @%s.UTC %s %d.%d/%s %s',
|
||||||
our_address($this->fftn->zone->domain,$this->fftn)->ftn3d,
|
our_address($this->fftn)->ftn3d,
|
||||||
Carbon::now()->utc()->format('Ymd.His'),
|
Carbon::now()->utc()->format('Ymd.His'),
|
||||||
str_replace(' ','_',Setup::PRODUCT_NAME),
|
str_replace(' ','_',Setup::PRODUCT_NAME),
|
||||||
Setup::PRODUCT_VERSION_MAJ,
|
Setup::PRODUCT_VERSION_MAJ,
|
||||||
|
@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
use App\Classes\FTN\Packet;
|
||||||
use App\Jobs\AddressPoll;
|
use App\Jobs\AddressPoll;
|
||||||
|
|
||||||
class System extends Model
|
class System extends Model
|
||||||
@ -249,6 +250,17 @@ class System extends Model
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the packet that this system uses
|
||||||
|
*
|
||||||
|
* @return Packet
|
||||||
|
*/
|
||||||
|
public function packet(): Packet
|
||||||
|
{
|
||||||
|
return new (collect(Packet::PACKET_TYPES)
|
||||||
|
->get($this->pkt_type ?: config('fido.packet_default')));
|
||||||
|
}
|
||||||
|
|
||||||
public function poll(): ?Job
|
public function poll(): ?Job
|
||||||
{
|
{
|
||||||
return Job::where('queue',AddressPoll::QUEUE)
|
return Job::where('queue',AddressPoll::QUEUE)
|
||||||
|
@ -60,7 +60,7 @@ abstract class Echomails extends Notification //implements ShouldQueue
|
|||||||
$o->datetime = Carbon::now();
|
$o->datetime = Carbon::now();
|
||||||
$o->tzoffset = $o->datetime->utcOffset();
|
$o->tzoffset = $o->datetime->utcOffset();
|
||||||
|
|
||||||
$o->fftn_id = ($x=our_address($mo->fboss_o->zone->domain,$mo->fboss_o))->id;
|
$o->fftn_id = ($x=our_address($mo->fboss_o))->id;
|
||||||
$o->flags = (Message::FLAG_LOCAL);
|
$o->flags = (Message::FLAG_LOCAL);
|
||||||
|
|
||||||
$o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
|
$o->tearline = sprintf('%s (%04X)',Setup::PRODUCT_NAME,Setup::PRODUCT_ID);
|
||||||
|
@ -48,6 +48,7 @@ abstract class Netmails extends Notification //implements ShouldQueue
|
|||||||
|
|
||||||
protected function setupNetmail(object $notifiable): Netmail
|
protected function setupNetmail(object $notifiable): Netmail
|
||||||
{
|
{
|
||||||
|
// @todo Redirect netmails to Hubs or higher to the admin
|
||||||
$ao = $notifiable->routeNotificationFor(static::via);
|
$ao = $notifiable->routeNotificationFor(static::via);
|
||||||
|
|
||||||
$o = new Netmail;
|
$o = new Netmail;
|
||||||
@ -57,7 +58,7 @@ abstract class Netmails extends Notification //implements ShouldQueue
|
|||||||
$o->datetime = Carbon::now();
|
$o->datetime = Carbon::now();
|
||||||
$o->tzoffset = $o->datetime->utcOffset();
|
$o->tzoffset = $o->datetime->utcOffset();
|
||||||
|
|
||||||
$o->fftn_id = our_address($ao->zone->domain,$ao)->id;
|
$o->fftn_id = our_address($ao)->id;
|
||||||
$o->tftn_id = $ao->id;
|
$o->tftn_id = $ao->id;
|
||||||
$o->flags = (Message::FLAG_LOCAL|Message::FLAG_PRIVATE);
|
$o->flags = (Message::FLAG_LOCAL|Message::FLAG_PRIVATE);
|
||||||
$o->cost = 0;
|
$o->cost = 0;
|
||||||
|
@ -16,7 +16,7 @@ trait MsgID
|
|||||||
{
|
{
|
||||||
// Only create a MSGID for locally generated content
|
// Only create a MSGID for locally generated content
|
||||||
if ((! $this->exists) && ($this->flags & Message::FLAG_LOCAL) && (is_null(Arr::get($this->attributes,'msgid')))) {
|
if ((! $this->exists) && ($this->flags & Message::FLAG_LOCAL) && (is_null(Arr::get($this->attributes,'msgid')))) {
|
||||||
$ftn = our_address($this->fftn->zone->domain,$this->fftn);
|
$ftn = our_address($this->fftn);
|
||||||
$this->attributes['msgid'] = sprintf('%s %08x',$ftn->ftn4d,timew());
|
$this->attributes['msgid'] = sprintf('%s %08x',$ftn->ftn4d,timew());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
use App\Models\{Address,Domain,Setup,Zone};
|
use App\Models\{Address,Domain,Setup};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate CCITT-CRC16 checksum
|
* Calculate CCITT-CRC16 checksum
|
||||||
@ -83,13 +83,14 @@ if (! function_exists('hexstr')) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return our addresses.
|
* Return our addresses.
|
||||||
* If zone provided, limit the list to those within the zone
|
* If domain provided, limit the list to those within the domain - returning a Collection::class
|
||||||
|
* If address provided, return our address that would be used for the provided address - return Address::class
|
||||||
*
|
*
|
||||||
* @param Domain|NULL $do Limit the addresses for the specific domain
|
* @param Domain|Address|null $o - Domain or Address
|
||||||
* @param Address|null $ao If address is presented, show the address we use when talking to that address
|
|
||||||
* @return Collection|Address|NULL
|
* @return Collection|Address|NULL
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
function our_address(Domain $do=NULL,Address $ao=NULL): Collection|Address|NULL
|
function our_address(Domain|Address $o=NULL): Collection|Address|NULL
|
||||||
{
|
{
|
||||||
static $so = NULL;
|
static $so = NULL;
|
||||||
static $our = NULL;
|
static $our = NULL;
|
||||||
@ -102,15 +103,32 @@ function our_address(Domain $do=NULL,Address $ao=NULL): Collection|Address|NULL
|
|||||||
$our = $so->system->akas;
|
$our = $so->system->akas;
|
||||||
}
|
}
|
||||||
|
|
||||||
$filter = $our;
|
// If we dont have any addresses
|
||||||
if ($do)
|
if ($our->count() === 0)
|
||||||
$filter = $our->filter(function($item) use ($do) { return $item->zone->domain_id === $do->id; })->sortBy('role');
|
return NULL;
|
||||||
|
|
||||||
// If we are looking for a specific address, and there is only 1 result, return it, otherwise return what we have
|
// We havent asked for an address/domain, so we'll return them all.
|
||||||
if ($ao && config('fido.strict') && ($x=$filter->filter(function($item) use ($ao) { return $item->role <= $ao->role; })->sortBy('role'))->count())
|
if (is_null($o))
|
||||||
$filter = $x;
|
return $our;
|
||||||
|
|
||||||
return $ao ? $filter->last() : ($do ? $filter : $our);
|
// We are requesting a list of addresses for a Domain, or a specific Address, and we have more than 1
|
||||||
|
switch (get_class($o)) {
|
||||||
|
case Address::class:
|
||||||
|
$filter = $our->filter(function($item) use ($o) { return $item->zone->domain_id === $o->zone->domain_id; })->sortBy('role');
|
||||||
|
|
||||||
|
// If we are looking for a specific address, and there is only 1 result, return it, otherwise return what we have
|
||||||
|
if (config('fido.strict') && ($x=$filter->filter(function($item) use ($o) { return $item->role <= $o->role; })->sortBy('role'))->count())
|
||||||
|
$filter = $x;
|
||||||
|
|
||||||
|
return $filter->last();
|
||||||
|
|
||||||
|
case Domain::class:
|
||||||
|
return $our->filter(function($item) use ($o) { return $item->zone->domain_id === $o->id; })->sortBy('role');
|
||||||
|
|
||||||
|
// We shouldnt get here
|
||||||
|
default:
|
||||||
|
throw new Exception('Unhandled class: '.get_class($o));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user