BINKP responding to incoming netmail pings

This commit is contained in:
Deon George
2021-07-18 22:10:21 +10:00
parent 7bb3e12f66
commit 9dcfe6b17d
19 changed files with 145 additions and 54 deletions

View File

@@ -256,6 +256,8 @@ class Message extends FTNBase
return Arr::get($this->header,$key);
case 'message':
case 'tearline':
case 'origin':
case 'subject':
case 'user_to':
case 'user_from':
@@ -280,6 +282,8 @@ class Message extends FTNBase
case 'header':
case 'intl':
case 'message':
case 'tearline':
case 'origin':
case 'msgid':
case 'subject':
case 'user_from':
@@ -307,6 +311,10 @@ class Message extends FTNBase
$class = get_class($this);
foreach ($properties as $property) {
// Dont serialize the validation error
if ($property->name == 'errors')
continue;
if ($property->isStatic()) {
continue;
}
@@ -672,7 +680,7 @@ class Message extends FTNBase
],[
'user_from' => 'required|min:1|max:'.self::USER_FROM_LEN,
'user_to' => 'required|min:1|max:'.self::USER_TO_LEN,
'subject' => 'required|max:'.self::SUBJECT_LEN,
'subject' => 'present|max:'.self::SUBJECT_LEN,
'onode' => ['required',new TwoByteInteger],
'dnode' => ['required',new TwoByteInteger],
'onet' => ['required',new TwoByteInteger],

View File

@@ -55,11 +55,13 @@ class Packet extends FTNBase
public File $file; // Packet filename
public Collection $messages; // Messages in the Packet
private string $name; // Packet name
public function __construct(Address $o=NULL)
{
$this->messages = collect();
$this->domain = NULL;
$this->name = sprintf('%08x',Carbon::now()->timestamp);
// If we are creating an outbound packet, we need to set our header
if ($o)
@@ -95,6 +97,7 @@ class Packet extends FTNBase
throw new InvalidPacketException('Not a type 2 packet: '.$version);
$o = new self;
$o->name = (string)$file;
$o->header = unpack(self::unpackheader(self::v2header),$header);
$x = fread($f,2);
@@ -217,6 +220,10 @@ class Packet extends FTNBase
else
return '2e';
// Packet name:
case 'name':
return $this->{$key};
default:
throw new \Exception('Unknown key: '.$key);
}

View File

@@ -4,6 +4,7 @@ namespace App\Classes\FTN\Process;
use Carbon\Carbon;
use Carbon\CarbonInterface;
use Illuminate\Support\Facades\Log;
use App\Classes\FTN\{Message,Process};
use App\Models\{Netmail,Setup};
@@ -26,6 +27,8 @@ final class Ping extends Process
if (strtolower($msg->user_to) !== 'ping')
return FALSE;
Log::info(sprintf('Processing PING message from (%s) [%s]',$msg->user_from,$msg->fftn));
$reply = sprintf("Your ping was received here on %s and it took %s to get here.\r",
Carbon::now()->toDateTimeString(),
$msg->date->diffForHumans(['parts'=>3,'syntax'=>CarbonInterface::DIFF_ABSOLUTE])
@@ -46,7 +49,7 @@ final class Ping extends Process
$o->msg = static::format_msg($reply);
$o->reply = $msg->msgid;
$o->tagline = '... My ping pong opponent was not happy with my serve. He kept returning it.';
$o->tagline = 'My ping pong opponent was not happy with my serve. He kept returning it.';
$o->tearline = sprintf('--- %s (%s)',Setup::PRODUCT_NAME,(new Setup)->version);
$o->save();

View File

@@ -94,7 +94,7 @@ class Item
throw new Exception('Invalid request for key: '.$key);
case 'recvas':
return '/tmp/'.$this->file_name; // @todo this should be inbound temp
return $this->file_name;
case 'sendas':
return basename($this->file_name);
@@ -114,6 +114,7 @@ class Item
static $ext = ['su','mo','tu','we','th','fr','sa','req'];
$x = strrchr($this->file_name,'.');
if (! $x || (strlen(substr($x,1)) != 3))
return self::IS_FILE;

View File

@@ -20,7 +20,7 @@ class Mail extends Item
switch ($action) {
case self::I_SEND:
$this->file = $mail;
$this->file_name = sprintf('%08X.PKT',Carbon::now()->timestamp);
$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

View File

@@ -5,8 +5,13 @@ namespace App\Classes\File;
use Exception;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use App\Classes\FTN\Packet;
use App\Jobs\ProcessPacket;
use App\Models\Address;
/**
* Object representing the files we are receiving
*
@@ -16,12 +21,14 @@ use Symfony\Component\HttpFoundation\File\Exception\FileException;
*/
final class Receive extends Item
{
private Address $ao;
private Collection $list;
private ?Item $receiving;
private mixed $f; // File descriptor
private int $start; // Time we started receiving
private int $file_pos; // Current write pointer
private string $file; // Local filename for file received
public function __construct()
{
@@ -86,8 +93,29 @@ final class Receive extends Item
fclose($this->f);
$this->file_pos = 0;
$this->receiving = NULL;
$this->f = NULL;
// If we received a packet, we'll dispatch a job to process it
switch ($this->receiving->file_type) {
case self::IS_PKT:
Log::info(sprintf('%s: - Processing mail packet [%s]',__METHOD__,$this->file));
foreach (Packet::open(new File($this->file),$this->ao->zone->domain)->messages as $msg) {
Log::info(sprintf('%s: - Mail from [%s] to [%s]',__METHOD__,$msg->fftn,$msg->tftn));
// @todo Quick check that the packet should be processed by us.
// @todo validate that the packet's zone is in the domain.
// Dispatch job.
ProcessPacket::dispatchSync($msg);
}
break;
default:
Log::debug(sprintf('%s: - Leaving file [%s] in the inbound dir',__METHOD__,$this->file));
}
$this->receiving = NULL;
}
/**
@@ -97,7 +125,7 @@ final class Receive extends Item
* @return bool
* @throws Exception
*/
public function open(bool $check=FALSE): bool
public function open(Address $ao,bool $check=FALSE): bool
{
Log::debug(sprintf('%s: + Start [%d]',__METHOD__,$check));
@@ -112,11 +140,13 @@ final class Receive extends Item
if (! $this->receiving)
throw new Exception('No files currently receiving');
$this->ao = $ao;
$this->file_pos = 0;
$this->start = time();
$this->file = sprintf('storage/app/%s/%04X-%s',config('app.fido'),$this->ao->id,$this->receiving->recvas);
Log::debug(sprintf('%s: - Opening [%s]',__METHOD__,$this->receiving->recvas));
$this->f = fopen($this->receiving->recvas,'wb');
Log::debug(sprintf('%s: - Opening [%s]',__METHOD__,$this->file));
$this->f = fopen($this->file,'wb');
if (! $this->f) {
Log::error(sprintf('%s: ! Unable to open file [%s] for writing',__METHOD__,$this->receiving->file_name));
return 3; // @todo change to const

View File

@@ -46,7 +46,7 @@ final class Send extends Item
{
switch ($key) {
case 'fd':
return is_resource($this->f);
return is_resource($this->f) ?: $this->f;
case 'file_count':
return $this->list
@@ -228,8 +228,11 @@ final class Send extends Item
public function mail(Address $ao): void
{
// Netmail
if ($x=$ao->getNetmail())
if ($x=$ao->getNetmail()) {
Log::debug(sprintf('%s: - Netmail(s) added for sending to [%s]',__METHOD__,$ao->ftn));
$this->packets->push(new Mail($x,self::I_SEND));
}
}
/**

View File

@@ -52,6 +52,9 @@ class Node
public function __get($key)
{
switch ($key) {
case 'address':
return ($x=$this->ftns_authed)->count() ? $x->first() : $this->ftns->first();
// Number of AKAs the remote has
case 'aka_num':
return $this->ftns->count();
@@ -117,6 +120,7 @@ class Node
}
$this->ftns->push($value);
break;
case 'system':

View File

@@ -102,7 +102,7 @@ final class Binkp extends BaseProtocol
if (! parent::onConnect($client)) {
$this->session(self::SESSION_BINKP,$client,(new Address));
$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;
@@ -133,9 +133,9 @@ final class Binkp extends BaseProtocol
$this->msgs(self::BPM_NUL,
sprintf('OPT%s%s%s%s%s%s',
($this->setup->opt_nda) ? ' NDA' : '',
($this->setup->opt_nr&self::O_WANT) ? ' NR' : '',
($this->setup->opt_nd&self::O_THEY) ? ' ND' : '',
($this->setup->opt_mb&self::O_WANT) ? ' MB' : '',
($this->setup->opt_nr&self::O_WANT) ? ' NR' : '',
($this->setup->opt_nd&self::O_THEY) ? ' ND' : '',
($this->setup->opt_mb&self::O_WANT) ? ' MB' : '',
($this->setup->opt_cr&self::O_WE) ? ' CRYPT' : '',
($this->setup->opt_cht&self::O_WANT) ? ' CHAT' : ''));
}
@@ -622,8 +622,11 @@ final class Binkp extends BaseProtocol
// @todo lock nodes
$this->node->ftn = $o;
// @todo Find files for node
$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);
}
Log::info(sprintf('%s: = Node has [%lu] mail and [%lu] files - [%lu] items',__METHOD__,$this->send->mail_size,$this->send->file_size,$this->send->total_count));
@@ -706,7 +709,13 @@ final class Binkp extends BaseProtocol
$this->sessionClear(self::SE_DELAYEOB);
if (! $this->send->total_count && $this->sessionGet(self::SE_NOFILES)) {
// @todo See if we need to send anything else, based on what we just recevied
// Add our mail to the queue if we have authenticated
if ($this->node->aka_authed)
foreach ($this->node->aka_remote as $ao) {
Log::debug(sprintf('%s: - Checking for any new mail to [%s]',__METHOD__,$ao->ftn));
$this->send->mail($ao);
}
if ($this->send->total_count)
$this->sessionClear(self::SE_NOFILES);
}
@@ -760,7 +769,7 @@ final class Binkp extends BaseProtocol
&& $this->recv->size == Arr::get($file,'file.size')
&& $this->recv->filepos == $file['offs'])
{
$this->recv->open($file['offs']<0);
$this->recv->open($this->node->address,$file['offs']<0);
return 1;
}
@@ -768,7 +777,7 @@ final class Binkp extends BaseProtocol
$this->recv->new($file['file']);
try {
switch ($this->recv->open($file['offs']<0)) {
switch ($this->recv->open($this->node->address,$file['offs']<0)) {
case self::FOP_ERROR:
Log::error(sprintf('%s: ! File Error',__METHOD__));

View File

@@ -1154,7 +1154,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
{
Log::debug(sprintf('%s: + Start',__METHOD__));
$rc = (new Zmodem)->zmodem_receive($this->client,$zap,$this->recv,$this->setup->inbound);
$rc = (new Zmodem)->zmodem_receive($this->client,$zap,$this->recv);
return ($rc == self::RCDO || $rc == self::ERROR);
}

View File

@@ -274,7 +274,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
$rc = $this->zmodem_senddone();
} else {
$rc = $this->zmodem_receive($this->client,$proto,$this->recv,'.');
$rc = $this->zmodem_receive($this->client,$proto,$this->recv);
}
return $rc;
@@ -285,13 +285,12 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
*
* @param SocketClient $client
* @param Receive $recv
* @param string $dir
* @param int $canzap
* @return int
*/
public function zmodem_receive(SocketClient $client,int $canzap,Receive $recv,string $dir): int
public function zmodem_receive(SocketClient $client,int $canzap,Receive $recv,Address $ao): int
{
Log::debug(sprintf('%s: + Start [%d] into dir [%s]',__METHOD__,$canzap,$dir));
Log::debug(sprintf('%s: + Start [%d]',__METHOD__,$canzap));
$opts = $this->init($client,$canzap);
@@ -336,7 +335,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface
$frame = self::ZSKIP;
} else {
switch ($this->recv->open()) {
switch ($this->recv->open($ao)) {
case self::FOP_SKIP:
Log::info(sprintf('%s: = Skip this file [%s]',__METHOD__,$this->recv->name));
$frame = self::ZSKIP;