Transfering netmail via EMSI
This commit is contained in:
parent
6ce4e64cb6
commit
1fa566b26c
@ -195,7 +195,7 @@ class Message extends FTNBase
|
|||||||
|
|
||||||
if (($x=$o->validate($domain))->fails()) {
|
if (($x=$o->validate($domain))->fails()) {
|
||||||
Log::debug('Message fails validation',['result'=>$x->errors()]);
|
Log::debug('Message fails validation',['result'=>$x->errors()]);
|
||||||
throw new \Exception('Message validation fails:'.join(' ',$x->errors()->all()));
|
//throw new \Exception('Message validation fails:'.join(' ',$x->errors()->all()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $o;
|
return $o;
|
||||||
@ -249,7 +249,7 @@ class Message extends FTNBase
|
|||||||
|
|
||||||
case 'date':
|
case 'date':
|
||||||
return Carbon::createFromFormat('d M y H:i:s O',
|
return Carbon::createFromFormat('d M y H:i:s O',
|
||||||
sprintf('%s %s',chop(Arr::get($this->header,$key)),($x=$this->kludge->get('tzutc')) < 0 ? $x : '+'.$x));
|
sprintf('%s %s',chop(Arr::get($this->header,$key)),(is_null($x=$this->kludge->get('tzutc')) || ($x < 0)) ? $x : '+'.$x));
|
||||||
|
|
||||||
case 'flags':
|
case 'flags':
|
||||||
case 'cost': return Arr::get($this->header,$key);
|
case 'cost': return Arr::get($this->header,$key);
|
||||||
|
@ -230,12 +230,17 @@ class Packet extends FTNBase
|
|||||||
*/
|
*/
|
||||||
public function __toString(): string
|
public function __toString(): string
|
||||||
{
|
{
|
||||||
|
// Cache the packet creation
|
||||||
|
static $return = NULL;
|
||||||
|
|
||||||
|
if (is_null($return)) {
|
||||||
$return = $this->createHeader();
|
$return = $this->createHeader();
|
||||||
|
|
||||||
foreach ($this->messages as $o)
|
foreach ($this->messages as $o)
|
||||||
$return .= "\02\00".(string)$o;
|
$return .= "\02\00".(string)$o;
|
||||||
|
|
||||||
$return .= "\00\00";
|
$return .= "\00\00";
|
||||||
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
@ -296,7 +301,7 @@ class Packet extends FTNBase
|
|||||||
/**
|
/**
|
||||||
* When creating a new packet, set the header.
|
* When creating a new packet, set the header.
|
||||||
*
|
*
|
||||||
* @param array $header
|
* @param Address $o
|
||||||
*/
|
*/
|
||||||
private function newHeader(Address $o): void
|
private function newHeader(Address $o): void
|
||||||
{
|
{
|
||||||
@ -329,8 +334,8 @@ class Packet extends FTNBase
|
|||||||
* Parse a message in a mail packet
|
* Parse a message in a mail packet
|
||||||
*
|
*
|
||||||
* @param string $message
|
* @param string $message
|
||||||
* @param Domain $domain
|
* @param Domain|null $domain
|
||||||
* @throws \Exception
|
* @throws InvalidPacketException
|
||||||
*/
|
*/
|
||||||
public function parseMessage(string $message,Domain $domain=NULL): void
|
public function parseMessage(string $message,Domain $domain=NULL): void
|
||||||
{
|
{
|
||||||
|
@ -21,7 +21,7 @@ abstract class Process
|
|||||||
*/
|
*/
|
||||||
protected static function format_msg(string $text): string
|
protected static function format_msg(string $text): string
|
||||||
{
|
{
|
||||||
$msg = utf8_decode(join("\n",static::msg_header()))."\n";
|
$msg = utf8_decode(join("\r",static::msg_header()))."\r";
|
||||||
$c = 0;
|
$c = 0;
|
||||||
$offset = 0;
|
$offset = 0;
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ abstract class Process
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Look for a return
|
// Look for a return
|
||||||
$return = strpos($text,"\n",$offset);
|
$return = strpos($text,"\r",$offset);
|
||||||
|
|
||||||
if ($return !== FALSE)
|
if ($return !== FALSE)
|
||||||
$return -= $offset;
|
$return -= $offset;
|
||||||
@ -55,13 +55,13 @@ abstract class Process
|
|||||||
$subtext = substr($text,$offset,$space);
|
$subtext = substr($text,$offset,$space);
|
||||||
}
|
}
|
||||||
|
|
||||||
$msg .= $ll.$subtext."\n";
|
$msg .= $ll.$subtext."\r";
|
||||||
$offset += strlen($subtext)+1;
|
$offset += strlen($subtext)+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case our text is shorter than the loo
|
// In case our text is shorter than the loo
|
||||||
for ($c; $c<count(static::$logo);$c++)
|
for ($c; $c<count(static::$logo);$c++)
|
||||||
$msg .= utf8_decode(Arr::get(static::$logo,$c))."\n";
|
$msg .= utf8_decode(Arr::get(static::$logo,$c))."\r";
|
||||||
|
|
||||||
return $msg;
|
return $msg;
|
||||||
}
|
}
|
||||||
|
@ -26,17 +26,18 @@ final class Ping extends Process
|
|||||||
if (strtolower($msg->user_to) !== 'ping')
|
if (strtolower($msg->user_to) !== 'ping')
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
$reply = sprintf("Your ping was received here on %s and it took %s to get here.\n",
|
$reply = sprintf("Your ping was received here on %s and it took %s to get here.\r",
|
||||||
Carbon::now()->toDateTimeString(),
|
Carbon::now()->toDateTimeString(),
|
||||||
$msg->date->diffForHumans(['parts'=>3,'syntax'=>CarbonInterface::DIFF_ABSOLUTE])
|
$msg->date->diffForHumans(['parts'=>3,'syntax'=>CarbonInterface::DIFF_ABSOLUTE])
|
||||||
);
|
);
|
||||||
|
|
||||||
$reply .= "\n";
|
$reply .= "\r";
|
||||||
$reply .= "Your message travelled along this path to get here:\n";
|
$reply .= "\r";
|
||||||
|
$reply .= "Your message travelled along this path on the way here:\r";
|
||||||
foreach ($msg->via as $path)
|
foreach ($msg->via as $path)
|
||||||
$reply .= sprintf(" * %s\n",$path);
|
$reply .= sprintf(" * %s\r",$path);
|
||||||
|
|
||||||
$o = new Netmail();
|
$o = new Netmail;
|
||||||
$o->to = $msg->user_from;
|
$o->to = $msg->user_from;
|
||||||
$o->from = Setup::PRODUCT_NAME;
|
$o->from = Setup::PRODUCT_NAME;
|
||||||
$o->subject = 'Ping Reply';
|
$o->subject = 'Ping Reply';
|
||||||
|
38
app/Classes/File/Mail.php
Normal file
38
app/Classes/File/Mail.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Classes\File;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
use App\Classes\FTN\Packet;
|
||||||
|
|
||||||
|
class Mail extends Item
|
||||||
|
{
|
||||||
|
private Packet $file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function __construct(Packet $mail,int $action)
|
||||||
|
{
|
||||||
|
$this->action |= $action;
|
||||||
|
|
||||||
|
switch ($action) {
|
||||||
|
case self::I_SEND:
|
||||||
|
$this->file = $mail;
|
||||||
|
$this->file_name = sprintf('%08X.PKT',Carbon::now()->timestamp);
|
||||||
|
$this->file_size = strlen($mail);
|
||||||
|
$this->file_mtime = Carbon::now()->timestamp; // @todo This timestamp should be consistent incase of retries
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new \Exception('Unknown action: '.$action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function read(int $start,int $length): string
|
||||||
|
{
|
||||||
|
return substr((string)$this->file,$start,$length);
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,8 @@ use Illuminate\Support\Collection;
|
|||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use League\Flysystem\UnreadableFileException;
|
use League\Flysystem\UnreadableFileException;
|
||||||
|
|
||||||
|
use App\Models\Address;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object representing the files we are sending
|
* Object representing the files we are sending
|
||||||
*
|
*
|
||||||
@ -24,6 +26,7 @@ final class Send extends Item
|
|||||||
{
|
{
|
||||||
private Collection $list;
|
private Collection $list;
|
||||||
private ?Item $sending;
|
private ?Item $sending;
|
||||||
|
private Collection $packets;
|
||||||
|
|
||||||
private mixed $f; // File descriptor
|
private mixed $f; // File descriptor
|
||||||
private int $start; // Time we started sending
|
private int $start; // Time we started sending
|
||||||
@ -33,6 +36,7 @@ final class Send extends Item
|
|||||||
{
|
{
|
||||||
// Initialise our variables
|
// Initialise our variables
|
||||||
$this->list = collect();
|
$this->list = collect();
|
||||||
|
$this->packets = collect();
|
||||||
$this->sending = NULL;
|
$this->sending = NULL;
|
||||||
$this->file_pos = 0;
|
$this->file_pos = 0;
|
||||||
$this->f = NULL;
|
$this->f = NULL;
|
||||||
@ -60,12 +64,14 @@ final class Send extends Item
|
|||||||
case 'mail_count':
|
case 'mail_count':
|
||||||
return $this->list
|
return $this->list
|
||||||
->filter(function($item) { return $item->isType(self::IS_ARC|self::IS_PKT); })
|
->filter(function($item) { return $item->isType(self::IS_ARC|self::IS_PKT); })
|
||||||
->count();
|
->count()
|
||||||
|
+ $this->packets->count();
|
||||||
|
|
||||||
case 'mail_size':
|
case 'mail_size':
|
||||||
return $this->list
|
return $this->list
|
||||||
->filter(function($item) { return $item->isType(self::IS_ARC|self::IS_PKT); })
|
->filter(function($item) { return $item->isType(self::IS_ARC|self::IS_PKT); })
|
||||||
->sum(function($item) { return $item->file_size; });
|
->sum(function($item) { return $item->file_size; })
|
||||||
|
+ $this->packets->sum(function($item) { return $item->file_size; });
|
||||||
|
|
||||||
case 'sendas':
|
case 'sendas':
|
||||||
return $this->sending ? $this->sending->{$key} : NULL;
|
return $this->sending ? $this->sending->{$key} : NULL;
|
||||||
@ -77,22 +83,32 @@ final class Send extends Item
|
|||||||
|
|
||||||
case 'total_sent':
|
case 'total_sent':
|
||||||
return $this->list
|
return $this->list
|
||||||
|
->filter(function($item) { return ($item->action & self::I_SEND) && $item->sent === TRUE; })
|
||||||
|
->count()
|
||||||
|
+ $this->packets
|
||||||
->filter(function($item) { return ($item->action & self::I_SEND) && $item->sent === TRUE; })
|
->filter(function($item) { return ($item->action & self::I_SEND) && $item->sent === TRUE; })
|
||||||
->count();
|
->count();
|
||||||
|
|
||||||
case 'total_sent_bytes':
|
case 'total_sent_bytes':
|
||||||
return $this->list
|
return $this->list
|
||||||
|
->filter(function($item) { return ($item->action & self::I_SEND) && $item->sent === TRUE; })
|
||||||
|
->sum(function($item) { return $item->file_size; })
|
||||||
|
+ $this->packets
|
||||||
->filter(function($item) { return ($item->action & self::I_SEND) && $item->sent === TRUE; })
|
->filter(function($item) { return ($item->action & self::I_SEND) && $item->sent === TRUE; })
|
||||||
->sum(function($item) { return $item->file_size; });
|
->sum(function($item) { return $item->file_size; });
|
||||||
|
|
||||||
case 'total_count':
|
case 'total_count':
|
||||||
return $this->list
|
return $this->list
|
||||||
|
->filter(function($item) { return ($item->action & self::I_SEND) && $item->sent === FALSE; })
|
||||||
|
->count()
|
||||||
|
+ $this->packets
|
||||||
->filter(function($item) { return ($item->action & self::I_SEND) && $item->sent === FALSE; })
|
->filter(function($item) { return ($item->action & self::I_SEND) && $item->sent === FALSE; })
|
||||||
->count();
|
->count();
|
||||||
|
|
||||||
case 'total_size':
|
case 'total_size':
|
||||||
return $this->list
|
return $this->list
|
||||||
->sum(function($item) { return $item->file_size; });
|
->sum(function($item) { return $item->file_size; })
|
||||||
|
+ $this->packets->sum(function($item) { return $item->file_size; });
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Exception('Unknown key: '.$key);
|
throw new Exception('Unknown key: '.$key);
|
||||||
@ -143,7 +159,9 @@ final class Send extends Item
|
|||||||
Log::debug(sprintf('%s: - Closing [%s], sent in [%d]',__METHOD__,$this->sending->file_name,$end));
|
Log::debug(sprintf('%s: - Closing [%s], sent in [%d]',__METHOD__,$this->sending->file_name,$end));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! $this->sending instanceof Mail)
|
||||||
fclose($this->f);
|
fclose($this->f);
|
||||||
|
|
||||||
$this->sending = NULL;
|
$this->sending = NULL;
|
||||||
$this->file_pos = 0;
|
$this->file_pos = 0;
|
||||||
$this->f = NULL;
|
$this->f = NULL;
|
||||||
@ -156,7 +174,7 @@ final class Send extends Item
|
|||||||
*/
|
*/
|
||||||
public function feof(): bool
|
public function feof(): bool
|
||||||
{
|
{
|
||||||
return feof($this->f);
|
return ($this->sending instanceof Mail) ? ($this->file_pos == $this->size) : feof($this->f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -169,6 +187,18 @@ final class Send extends Item
|
|||||||
{
|
{
|
||||||
Log::debug(sprintf('%s: + Start',__METHOD__));
|
Log::debug(sprintf('%s: + Start',__METHOD__));
|
||||||
|
|
||||||
|
// If we have mail, we'll send that first
|
||||||
|
if ($this->sending = $this->packets
|
||||||
|
->filter(function($item) { return ($item->action & self::I_SEND) && $item->sent === FALSE; })
|
||||||
|
->first())
|
||||||
|
{
|
||||||
|
$this->file_pos = 0;
|
||||||
|
$this->start = time();
|
||||||
|
$this->f = TRUE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
$this->sending = $this->list
|
$this->sending = $this->list
|
||||||
->filter(function($item) { return ($item->action & self::I_SEND) && $item->sent === FALSE; })
|
->filter(function($item) { return ($item->action & self::I_SEND) && $item->sent === FALSE; })
|
||||||
->first();
|
->first();
|
||||||
@ -189,6 +219,19 @@ final class Send extends Item
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add our mail to the send queue
|
||||||
|
*
|
||||||
|
* @param Address $ao
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function mail(Address $ao): void
|
||||||
|
{
|
||||||
|
// Netmail
|
||||||
|
if ($x=$ao->getNetmail())
|
||||||
|
$this->packets->push(new Mail($x,self::I_SEND));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read bytes of the sending file
|
* Read bytes of the sending file
|
||||||
*
|
*
|
||||||
@ -202,7 +245,13 @@ final class Send extends Item
|
|||||||
if (! $this->f)
|
if (! $this->f)
|
||||||
throw new Exception('No file open for read');
|
throw new Exception('No file open for read');
|
||||||
|
|
||||||
|
// We are sending mail
|
||||||
|
if ($this->sending instanceof Mail) {
|
||||||
|
$data = $this->sending->read($this->file_pos,$length);
|
||||||
|
} else {
|
||||||
$data = fread($this->f,$length);
|
$data = fread($this->f,$length);
|
||||||
|
}
|
||||||
|
|
||||||
$this->file_pos += strlen($data);
|
$this->file_pos += strlen($data);
|
||||||
Log::debug(sprintf('%s: - Read [%d] bytes, file pos now [%d]',__METHOD__,strlen($data),$this->file_pos));
|
Log::debug(sprintf('%s: - Read [%d] bytes, file pos now [%d]',__METHOD__,strlen($data),$this->file_pos));
|
||||||
|
|
||||||
@ -224,7 +273,13 @@ final class Send extends Item
|
|||||||
if (! $this->f)
|
if (! $this->f)
|
||||||
throw new Exception('No file open for seek');
|
throw new Exception('No file open for seek');
|
||||||
|
|
||||||
|
if ($this->sending instanceof Mail) {
|
||||||
|
$rc = ($pos < $this->size) ? $pos : $this->size;
|
||||||
|
|
||||||
|
} else {
|
||||||
$rc = (fseek($this->f,$pos,SEEK_SET) === 0);
|
$rc = (fseek($this->f,$pos,SEEK_SET) === 0);
|
||||||
|
}
|
||||||
|
|
||||||
if ($rc)
|
if ($rc)
|
||||||
$this->file_pos = $pos;
|
$this->file_pos = $pos;
|
||||||
|
|
||||||
|
@ -33,12 +33,14 @@ class Node
|
|||||||
|
|
||||||
private Collection $ftns; // The FTNs of the remote system
|
private Collection $ftns; // The FTNs of the remote system
|
||||||
private Collection $ftns_authed; // The FTNs we have validated
|
private Collection $ftns_authed; // The FTNs we have validated
|
||||||
|
private bool $authed; // Have we authenticated the remote.
|
||||||
|
|
||||||
private int $options; // This nodes capabilities/options
|
private int $options; // This nodes capabilities/options
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->options = 0;
|
$this->options = 0;
|
||||||
|
$this->authed = FALSE;
|
||||||
$this->start_time = Carbon::now();
|
$this->start_time = Carbon::now();
|
||||||
$this->ftns = collect();
|
$this->ftns = collect();
|
||||||
$this->ftns_authed = collect();
|
$this->ftns_authed = collect();
|
||||||
@ -54,16 +56,20 @@ class Node
|
|||||||
case 'aka_num':
|
case 'aka_num':
|
||||||
return $this->ftns->count();
|
return $this->ftns->count();
|
||||||
|
|
||||||
// Number of AKAs we have validated
|
// The authenticated remote addresses
|
||||||
|
case 'aka_remote':
|
||||||
|
return $this->ftns_authed;
|
||||||
|
|
||||||
|
// Have we authenticated the remote
|
||||||
case 'aka_authed':
|
case 'aka_authed':
|
||||||
return $this->ftns_authed->count();
|
return $this->authed;
|
||||||
|
|
||||||
case 'ftn':
|
case 'ftn':
|
||||||
return ($x=$this->ftns->first()) ? $x->ftn : 'Unknown';
|
return ($x=$this->ftns->first()) ? $x->ftn : 'Unknown';
|
||||||
|
|
||||||
// The nodes password
|
// The nodes password
|
||||||
case 'password':
|
case 'password':
|
||||||
return ($this->ftns_authed->count() && ($x=$this->ftns_authed->first()->session('sespass'))) ? $x : '-';
|
return ($this->ftns->count() && ($x=$this->ftns->first()->session('sespass'))) ? $x : '-';
|
||||||
|
|
||||||
// Return how long our session has been connected
|
// Return how long our session has been connected
|
||||||
case 'session_time':
|
case 'session_time':
|
||||||
@ -163,6 +169,7 @@ class Node
|
|||||||
$o->system->last_session = Carbon::now();
|
$o->system->last_session = Carbon::now();
|
||||||
$o->system->save();
|
$o->system->save();
|
||||||
$this->ftns_authed->push($o);
|
$this->ftns_authed->push($o);
|
||||||
|
$this->authed = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,6 +231,10 @@ class Node
|
|||||||
*/
|
*/
|
||||||
public function originate_check(): bool
|
public function originate_check(): bool
|
||||||
{
|
{
|
||||||
|
// If we have already authed, we wont do it again
|
||||||
|
if ($this->authed)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
if ($this->ftns_authed->count() !== 1 || ! $this->ftns->count())
|
if ($this->ftns_authed->count() !== 1 || ! $this->ftns->count())
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -233,6 +244,7 @@ class Node
|
|||||||
if ($item->ftn == $ftn) {
|
if ($item->ftn == $ftn) {
|
||||||
$item->system->last_session = Carbon::now();
|
$item->system->last_session = Carbon::now();
|
||||||
$item->system->save();
|
$item->system->save();
|
||||||
|
$this->authed = TRUE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}) !== FALSE;
|
}) !== FALSE;
|
||||||
|
@ -12,11 +12,6 @@ use App\Models\{Address,Setup};
|
|||||||
|
|
||||||
abstract class Protocol
|
abstract class Protocol
|
||||||
{
|
{
|
||||||
// Our product code
|
|
||||||
// @todo Move These to a config file
|
|
||||||
protected const product_code = 'AB8D';
|
|
||||||
public const setup = 1;
|
|
||||||
|
|
||||||
// Enable extra debugging
|
// Enable extra debugging
|
||||||
protected bool $DEBUG = FALSE;
|
protected bool $DEBUG = FALSE;
|
||||||
|
|
||||||
@ -254,9 +249,6 @@ abstract class Protocol
|
|||||||
$this->client->speed = SocketClient::TCP_SPEED;
|
$this->client->speed = SocketClient::TCP_SPEED;
|
||||||
$this->originate = FALSE;
|
$this->originate = FALSE;
|
||||||
|
|
||||||
// @todo While Debugging
|
|
||||||
$this->send->add('/tmp/aa');
|
|
||||||
|
|
||||||
return $this->protocol_session();
|
return $this->protocol_session();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -9,7 +9,7 @@ use Illuminate\Support\Facades\Log;
|
|||||||
use App\Classes\Protocol as BaseProtocol;
|
use App\Classes\Protocol as BaseProtocol;
|
||||||
use App\Classes\Sock\SocketClient;
|
use App\Classes\Sock\SocketClient;
|
||||||
use App\Classes\Sock\SocketException;
|
use App\Classes\Sock\SocketException;
|
||||||
use App\Models\Address;
|
use App\Models\{Address,Setup};
|
||||||
use App\Interfaces\CRC as CRCInterface;
|
use App\Interfaces\CRC as CRCInterface;
|
||||||
use App\Interfaces\Zmodem as ZmodemInterface;
|
use App\Interfaces\Zmodem as ZmodemInterface;
|
||||||
use App\Traits\CRC as CRCTrait;
|
use App\Traits\CRC as CRCTrait;
|
||||||
@ -82,7 +82,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
if (! parent::onConnect($client)) {
|
if (! parent::onConnect($client)) {
|
||||||
$this->session(self::SESSION_AUTO,$client,(new Address));
|
$this->session(self::SESSION_AUTO,$client,(new Address));
|
||||||
$this->client->close();
|
$this->client->close();
|
||||||
Log::info(sprintf('%s: = End - Connection closed [%s]',__METHOD__,$client->getAddress()));
|
Log::info(sprintf('%s: = End - Connection closed [%s]',__METHOD__,$client->address_remote));
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -191,7 +191,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
|
|
||||||
// Mailer Details
|
// Mailer Details
|
||||||
$makedata .= sprintf('{%s}{%s}{%s}{%s}',
|
$makedata .= sprintf('{%s}{%s}{%s}{%s}',
|
||||||
self::product_code,
|
Setup::product_id(),
|
||||||
config('app.name'),
|
config('app.name'),
|
||||||
$this->setup->version,
|
$this->setup->version,
|
||||||
'#000000' // Serial Numbers
|
'#000000' // Serial Numbers
|
||||||
@ -346,7 +346,12 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
} else {
|
} else {
|
||||||
$this->node->optionSet(self::O_PWD);
|
$this->node->optionSet(self::O_PWD);
|
||||||
Log::info(sprintf('%s: - Remote Authed [%d] AKAs',__METHOD__,$c));
|
Log::info(sprintf('%s: - Remote Authed [%d] AKAs',__METHOD__,$c));
|
||||||
$this->send->add('/tmp/aa');
|
|
||||||
|
// Add our mail to the queue if we have authenticated
|
||||||
|
if ($this->node->aka_authed)
|
||||||
|
foreach ($this->node->aka_remote as $ao) {
|
||||||
|
$this->send->mail($ao);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Link codes */
|
/* Link codes */
|
||||||
@ -961,9 +966,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
if ($rc < 0)
|
if ($rc < 0)
|
||||||
return (self::S_REDIAL|self::S_ADDTRY);
|
return (self::S_REDIAL|self::S_ADDTRY);
|
||||||
|
|
||||||
Log::info(sprintf('%s: - Starting outbound EMSI session to [%s]',__METHOD__,$this->client->getAddress()));
|
Log::info(sprintf('%s: - Starting outbound EMSI session to [%s]',__METHOD__,$this->client->address_remote));
|
||||||
|
|
||||||
// @todo Lock Node AKAs
|
|
||||||
|
|
||||||
// Inbound session
|
// Inbound session
|
||||||
} else {
|
} else {
|
||||||
@ -975,9 +978,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
return (self::S_REDIAL|self::S_ADDTRY);
|
return (self::S_REDIAL|self::S_ADDTRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::info(sprintf('%s: - Starting inbound EMSI session from [%s]',__METHOD__,$this->client->getAddress()));
|
Log::info(sprintf('%s: - Starting inbound EMSI session from [%s]',__METHOD__,$this->client->address_remote));
|
||||||
|
|
||||||
// @todo Lock Node AKAs
|
|
||||||
|
|
||||||
if ($this->node->aka_authed) {
|
if ($this->node->aka_authed) {
|
||||||
$xproto = $this->is_freq_available();
|
$xproto = $this->is_freq_available();
|
||||||
@ -1003,6 +1004,8 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
return (self::S_REDIAL|self::S_ADDTRY);
|
return (self::S_REDIAL|self::S_ADDTRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @todo Lock Node AKAs
|
||||||
|
|
||||||
Log::info(sprintf('%s: - We have %lu%s mail, %lu%s files',__METHOD__,$this->send->mail_size,'b',$this->send->file_size,'b'));
|
Log::info(sprintf('%s: - We have %lu%s mail, %lu%s files',__METHOD__,$this->send->mail_size,'b',$this->send->file_size,'b'));
|
||||||
|
|
||||||
$proto = $this->originate ? $this->node->optionGet(self::P_MASK) : $this->optionGet(self::P_MASK);
|
$proto = $this->originate ? $this->node->optionGet(self::P_MASK) : $this->optionGet(self::P_MASK);
|
||||||
@ -1172,6 +1175,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
|
|||||||
if (! $z->zmodem_sendinit($this->client,$zap) && $this->send->total_count)
|
if (! $z->zmodem_sendinit($this->client,$zap) && $this->send->total_count)
|
||||||
$z->zmodem_sendfile($this->send);
|
$z->zmodem_sendfile($this->send);
|
||||||
|
|
||||||
|
Log::debug(sprintf('%s: - Finished sending',__METHOD__));
|
||||||
return ($z->zmodem_senddone()<0);
|
return ($z->zmodem_senddone()<0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -500,13 +500,14 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
{
|
{
|
||||||
Log::debug(sprintf('%s: + Start',__METHOD__));
|
Log::debug(sprintf('%s: + Start',__METHOD__));
|
||||||
|
|
||||||
|
while ($send->total_count && $send->open()) {
|
||||||
try {
|
try {
|
||||||
$send->open();
|
|
||||||
$rc = $this->ls_zsendfile($send,$this->ls_SerialNum++,$send->total_count,$send->total_size);
|
$rc = $this->ls_zsendfile($send,$this->ls_SerialNum++,$send->total_count,$send->total_size);
|
||||||
|
|
||||||
switch ($rc) {
|
switch ($rc) {
|
||||||
case self::LSZ_OK:
|
case self::LSZ_OK:
|
||||||
$send->close(TRUE);
|
$send->close(TRUE);
|
||||||
|
break;
|
||||||
|
|
||||||
case self::ZSKIP:
|
case self::ZSKIP:
|
||||||
case self::ZFERR:
|
case self::ZFERR:
|
||||||
@ -524,6 +525,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
|
|||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
Log::error(sprintf('%s: ! Error [%s]',__METHOD__,$e->getMessage()));
|
Log::error(sprintf('%s: ! Error [%s]',__METHOD__,$e->getMessage()));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return self::OK;
|
return self::OK;
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,18 @@ use Illuminate\Support\Str;
|
|||||||
* Class SocketClient
|
* Class SocketClient
|
||||||
*
|
*
|
||||||
* @package App\Classes\Sock
|
* @package App\Classes\Sock
|
||||||
* @property int speed
|
|
||||||
* @property int cps
|
* @property int cps
|
||||||
|
* @property int speed
|
||||||
*/
|
*/
|
||||||
final class SocketClient {
|
final class SocketClient {
|
||||||
// For deep debugging
|
// For deep debugging
|
||||||
private bool $DEBUG = FALSE;
|
private bool $DEBUG = FALSE;
|
||||||
|
|
||||||
private \Socket $connection;
|
private \Socket $connection;
|
||||||
private string $address = '';
|
private string $address_local = '';
|
||||||
private int $port = 0;
|
private int $port_local = 0;
|
||||||
|
private string $address_remote = '';
|
||||||
|
private int $port_remote = 0;
|
||||||
|
|
||||||
// Our session state
|
// Our session state
|
||||||
private array $session = [];
|
private array $session = [];
|
||||||
@ -52,14 +54,19 @@ final class SocketClient {
|
|||||||
private string $rx_buf = '';
|
private string $rx_buf = '';
|
||||||
|
|
||||||
public function __construct (\Socket $connection,int $speed=self::TCP_SPEED) {
|
public function __construct (\Socket $connection,int $speed=self::TCP_SPEED) {
|
||||||
socket_getsockname($connection,$this->address,$this->port);
|
socket_getsockname($connection,$this->address_local,$this->port_local);
|
||||||
Log::info(sprintf('%s: + Connection from [%s] on port [%d]',__METHOD__,$this->address,$this->port));
|
socket_getpeername($connection,$this->address_remote,$this->port_remote);
|
||||||
|
Log::info(sprintf('%s: + Connection from [%s] on port [%d]',__METHOD__,$this->address_remote,$this->port_remote));
|
||||||
|
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __get($key) {
|
public function __get($key) {
|
||||||
switch ($key) {
|
switch ($key) {
|
||||||
|
case 'address_remote':
|
||||||
|
case 'port_remote':
|
||||||
|
return $this->{$key};
|
||||||
|
|
||||||
case 'cps':
|
case 'cps':
|
||||||
case 'speed':
|
case 'speed':
|
||||||
return Arr::get($this->session,$key);
|
return Arr::get($this->session,$key);
|
||||||
@ -244,6 +251,7 @@ final class SocketClient {
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* @todo change to __get()
|
* @todo change to __get()
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function getAddress(): string
|
public function getAddress(): string
|
||||||
{
|
{
|
||||||
@ -255,6 +263,7 @@ final class SocketClient {
|
|||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
* @todo change to __get()
|
* @todo change to __get()
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function getPort(): int
|
public function getPort(): int
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,6 @@ class EMSISend extends Command
|
|||||||
$o = new EMSI(Setup::findOrFail(config('app.id')));
|
$o = new EMSI(Setup::findOrFail(config('app.id')));
|
||||||
$o->session(EMSI::SESSION_AUTO,$client,$no);
|
$o->session(EMSI::SESSION_AUTO,$client,$no);
|
||||||
|
|
||||||
Log::info(sprintf('Connection ended: %s',$client->getAddress()),['m'=>__METHOD__]);
|
Log::info(sprintf('Connection ended: %s',$client->address_remote),['m'=>__METHOD__]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,8 @@ class Address extends Model
|
|||||||
return $this->hasMany(self::class,'hub_id','id');
|
return $this->hasMany(self::class,'hub_id','id');
|
||||||
|
|
||||||
case 'node':
|
case 'node':
|
||||||
return NULL;
|
// Nodes dont have children, but must return a relationship instance
|
||||||
|
return $this->hasOne(self::class,NULL,'void');
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Exception('Unknown role: '.$this->role);
|
throw new Exception('Unknown role: '.$this->role);
|
||||||
@ -151,12 +152,15 @@ class Address extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get netmail for this node (including it's children)
|
* Get netmail for this node (including it's children)
|
||||||
|
*
|
||||||
|
* @return Packet|null
|
||||||
*/
|
*/
|
||||||
public function getNetmail(): Packet
|
public function getNetmail(): ?Packet
|
||||||
{
|
{
|
||||||
|
if (($x=Netmail::whereIn('tftn_id',$this->children->pluck('id')->push($this->id)))->count()) {
|
||||||
$o = new Packet($this);
|
$o = new Packet($this);
|
||||||
|
|
||||||
foreach (Netmail::whereIn('tftn_id',$this->children->pluck('id')->push($this->id))->get() as $oo) {
|
foreach ($x->get() as $oo) {
|
||||||
$o->addNetmail($oo->packet());
|
$o->addNetmail($oo->packet());
|
||||||
|
|
||||||
// @todo We need to mark the netmail as sent
|
// @todo We need to mark the netmail as sent
|
||||||
@ -165,6 +169,9 @@ class Address extends Model
|
|||||||
return $o;
|
return $o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a string and split it out as an FTN array
|
* Parse a string and split it out as an FTN array
|
||||||
*
|
*
|
||||||
|
@ -21,7 +21,8 @@ class Netmail extends Model
|
|||||||
{
|
{
|
||||||
return $this
|
return $this
|
||||||
->setConnection('pgsql')
|
->setConnection('pgsql')
|
||||||
->belongsTo(Address::class);
|
->belongsTo(Address::class)
|
||||||
|
->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tftn()
|
public function tftn()
|
||||||
@ -52,6 +53,8 @@ class Netmail extends Model
|
|||||||
{
|
{
|
||||||
$o = new Message;
|
$o = new Message;
|
||||||
|
|
||||||
|
// @todo Dont bundle mail to nodes that have been disabled, or addresses that have been deleted
|
||||||
|
|
||||||
$o->header = [
|
$o->header = [
|
||||||
'onode' => $this->fftn->node_id,
|
'onode' => $this->fftn->node_id,
|
||||||
'dnode' => $this->tftn->node_id,
|
'dnode' => $this->tftn->node_id,
|
||||||
@ -88,6 +91,9 @@ class Netmail extends Model
|
|||||||
// @todo Point handling FMPT/TOPT
|
// @todo Point handling FMPT/TOPT
|
||||||
$o->intl = sprintf('%s %s',$this->tftn->ftn3d,$this->fftn->ftn3d);
|
$o->intl = sprintf('%s %s',$this->tftn->ftn3d,$this->fftn->ftn3d);
|
||||||
|
|
||||||
|
// TZUTC
|
||||||
|
$o->kludge->put('tzutc',str_replace('+','',$this->created_at->getOffsetString('')));
|
||||||
|
|
||||||
return $o;
|
return $o;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -42,9 +42,21 @@ class Setup extends Model
|
|||||||
public const PRODUCT_VERSION_MAJ = 0;
|
public const PRODUCT_VERSION_MAJ = 0;
|
||||||
public const PRODUCT_VERSION_MIN = 0;
|
public const PRODUCT_VERSION_MIN = 0;
|
||||||
|
|
||||||
|
public const hexdigitslower = '0123456789abcdef';
|
||||||
|
|
||||||
// Our non model attributes and values
|
// Our non model attributes and values
|
||||||
private array $internal = [];
|
private array $internal = [];
|
||||||
|
|
||||||
|
public static function product_id(int $c=self::PRODUCT_ID): string
|
||||||
|
{
|
||||||
|
$x = substr(static::hexdigitslower,($c&0xf000)>>12,1);
|
||||||
|
$x .= substr(static::hexdigitslower,($c&0x0f00)>>8,1);
|
||||||
|
$x .= substr(static::hexdigitslower,($c&0x00f0)>>4,1);
|
||||||
|
$x .= substr(static::hexdigitslower,($c&0x000f),1);
|
||||||
|
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
|
||||||
/* RELATIONS */
|
/* RELATIONS */
|
||||||
|
|
||||||
public function system()
|
public function system()
|
||||||
|
Loading…
Reference in New Issue
Block a user