diff --git a/app/Classes/Protocol/EMSI.php b/app/Classes/Protocol/EMSI.php index 089f52d..8ab6a10 100644 --- a/app/Classes/Protocol/EMSI.php +++ b/app/Classes/Protocol/EMSI.php @@ -35,8 +35,8 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface private const EMSI_NAK = self::EMSI_BEG.'NAKEEC3'; private const EMSI_HBT = self::EMSI_BEG.'HBTEAEE'; - private const CR = "\r"; - private const NL = "\n"; + private const CR = "\x0d"; // \r + private const NL = "\x0a"; // \n; private const DEL = "\x08"; /* FEATURES */ @@ -58,7 +58,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface private const EMSI_LOG_OUT = 1; /* FREQs flags */ - private const FR_NOTHANDLED = (-1); + private const FR_NOTHANDLED = -1; private const FR_NOTAVAILABLE = 0; private const FR_AVAILABLE = 1; @@ -224,17 +224,19 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface 'XA' // Nodelist Flags ); - // TRAF - netmail/echomail traffic size (bytes) - $makedata .= sprintf('{TRAF}{%lX %lX}',$this->send->mail_size,$this->send->size); + // TRAF - netmail & files size (bytes) + $makedata .= sprintf('{TRAF}{%lX %lX}',$this->send->mail_size,$this->send->files_size); // MOH# - Mail On Hold - bytes waiting - $makedata .= sprintf('{MOH#}{[%lX]}',$this->send->mail_size); + $makedata .= sprintf('{MOH#}{[%lX]}',$this->send->total_size); // EMD5 - MD5 unique string // Transaction Number (Time in local time) $makedata .= sprintf('{TRX#}{[%lX]}',Carbon::now()->timestamp+Carbon::now($this->node->node_timezone)->offset); + // FREQ Time - NRQ (No Requests if this is not defined) + $makedata .= sprintf('{OHFR}{Always! CM}'); $makedata .= sprintf('{TZUTC}{[%+05d]}',-10*60); // @todo Not sure what OHFR is for @@ -506,9 +508,9 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface */ private function emsi_recv(int $mode): int { - Log::debug(sprintf('%s:+ emsi_recv',self::LOGKEY)); + Log::debug(sprintf('%s:+ EMSI receive handshake',self::LOGKEY)); - Log::debug(sprintf('%s: - STEP 1',self::LOGKEY)); + Log::debug(sprintf('%s: - STEP 1',self::LOGKEY)); /* * Step 1 * +-+------------------------------------------------------------------+ @@ -523,7 +525,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface do { step2: - Log::debug(sprintf('%s: - STEP 2',self::LOGKEY)); + Log::debug(sprintf('%s: - STEP 2',self::LOGKEY)); /* Step 2 +-+------------------------------------------------------------------+ :2: Increment Tries : @@ -554,7 +556,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface $this->client->buffer_flush(5); step3: - Log::debug(sprintf('%s: - STEP 3',self::LOGKEY)); + Log::debug(sprintf('%s: - STEP 3',self::LOGKEY)); /* Step 3 * +-+------------------------------------------------------------------+ * :3: T1=20 seconds : @@ -564,7 +566,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface $t1 = $this->client->timer_set(20); step4: - Log::debug(sprintf('%s: - STEP 4',self::LOGKEY)); + Log::debug(sprintf('%s: - STEP 4',self::LOGKEY)); /* Step 4 +-+------------------------------------------------------------------+ :4: Wait for EMSI sequence until EMSI_HBT or EMSI_DAT or any of the : @@ -610,7 +612,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface if (($ch === ord(self::CR)) || ($ch === ord(self::NL))) { if (! strncmp($p,self::EMSI_HBT,self::EMSI_SEQ_LEN)) { - Log::debug(sprintf('%s: - Received EMSI_HBT',self::LOGKEY)); + Log::debug(sprintf('%s:- Received EMSI_HBT',self::LOGKEY)); goto step3; } @@ -618,7 +620,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface if (! strncmp($p,self::EMSI_DAT,10)) { Log::debug(sprintf('%s:- Received EMSI_DAT',self::LOGKEY)); - Log::debug(sprintf('%s: - STEP 5',self::LOGKEY)); + Log::debug(sprintf('%s: - STEP 5',self::LOGKEY)); /* Step 5 +-+------------------------------------------------------------------+ :5: Receive EMSI_DAT packet : @@ -636,7 +638,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface $this->client->buffer_add(self::EMSI_ACK.self::CR); $this->client->buffer_flush(5); - Log::debug(sprintf('%s: - STEP 6',self::LOGKEY)); + Log::debug(sprintf('%s: - STEP 6',self::LOGKEY)); /* Step 6 +-+------------------------------------------------------------------+ :6: Received EMSI_DAT packet OK, exit. : @@ -646,7 +648,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface return self::OK; } else { - Log::debug(sprintf('%s: - EMSI_DAT didnt parse',self::LOGKEY)); + Log::error(sprintf('%s:! EMSI_DAT didnt parse',self::LOGKEY)); goto step2; } @@ -657,11 +659,11 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface } else { if (strlen($p) >= self::EMSI_BUF) { - Log::warning(sprintf('%s: ! EMSI_DAT packet too long.',self::LOGKEY)); + Log::warning(sprintf('%s:! EMSI_DAT packet too long.',self::LOGKEY)); $rew = strstr($p,self::EMSI_BEG,TRUE); if ($rew && $rew != $p) { - Log::notice(sprintf('%s: - Got EMSI_DAT at offset [%d].',self::LOGKEY,strlen($rew))); + Log::notice(sprintf('%s:- Got EMSI_DAT at offset [%d].',self::LOGKEY,strlen($rew))); $p = substr($p,strlen($rew)); } @@ -685,7 +687,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface */ private function emsi_send(): int { - Log::debug(sprintf('%s:+ EMSI send',self::LOGKEY)); + Log::debug(sprintf('%s:+ EMSI transmit Handshake',self::LOGKEY)); Log::debug(sprintf('%s: - STEP 1',self::LOGKEY)); /* Step 1 @@ -721,7 +723,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface :3: T2=20 seconds : +-+------------------------------------------------------------------+ */ - Log::debug(sprintf('%s: - STEP 3',self::LOGKEY)); + Log::debug(sprintf('%s: - STEP 3',self::LOGKEY)); $t2 = $this->client->timer_set(20); /* Step 4 @@ -739,7 +741,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface : : If any other sequence received, go to step 2. : +-+------------------------------------------------------------------+ */ - Log::debug(sprintf('%s: - STEP 4',self::LOGKEY)); + Log::debug(sprintf('%s: - STEP 4',self::LOGKEY)); while (! $this->client->timer_expired($t1)) { $ch = $this->client->read_ch(max( 1,min($this->client->timer_rest($t1),$this->client->timer_rest($t2)))); // Log::debug(sprintf('%s: - Got (%x) {%03d} (%c)',__METHOD__,$ch,$ch,$ch)); @@ -763,7 +765,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface continue; if (! strncmp($p,self::EMSI_DAT,10)) { - Log::warning(sprintf('%s: - Got unexpected EMSI_DAT - Argus?',self::LOGKEY)); + Log::warning(sprintf('%s:! Got unexpected EMSI_DAT - Argus?',self::LOGKEY)); $this->client->buffer_add(self::EMSI_ACK); $this->client->buffer_add(self::EMSI_ACK); $this->client->buffer_flush(1); @@ -771,12 +773,12 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface $t2 = $this->client->timer_set($this->client->timer_rest($t2) >> 2); } else if (! strncmp($p,self::EMSI_REQ,self::EMSI_SEQ_LEN)) { - Log::notice(sprintf('%s: - Got EMSI_REQ - skipping...',self::LOGKEY),['p'=>$p]); + Log::notice(sprintf('%s:- Got EMSI_REQ - skipping...',self::LOGKEY),['p'=>$p]); } else if (! strncmp($p,self::EMSI_ACK,self::EMSI_SEQ_LEN)) { - Log::debug(sprintf('%s: - Got EMSI_ACK',self::LOGKEY)); + Log::debug(sprintf('%s:- Got EMSI_ACK',self::LOGKEY)); - Log::debug(sprintf('%s: - STEP 5',self::LOGKEY)); + Log::debug(sprintf('%s: - STEP 5',self::LOGKEY)); /* Step 5 +-+------------------------------------------------------------------+ :5: Received EMSI_ACK, exit. : @@ -796,7 +798,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface $p .= chr($ch); } else { - Log::warning(sprintf('%s: ! EMSI packet too long',self::LOGKEY)); + Log::warning(sprintf('%s:! EMSI packet too long',self::LOGKEY)); } } } /* goto step4; */ @@ -825,7 +827,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface protected function protocol_init(): int { if ($this->DEBUG) - Log::debug(sprintf('%s:+ protocol_init',self::LOGKEY)); + Log::debug(sprintf('%s:+ Starting EMSI Protocol INIT',self::LOGKEY)); $got = 0; $tries = 0; @@ -851,7 +853,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface while (TRUE) { $ch = $this->client->read_ch(max( 1,min($this->client->timer_rest($t1),$this->client->timer_rest($t2)))); if ($this->DEBUG) - Log::debug(sprintf('%s: - Got [%x] (%c)',self::LOGKEY,$ch,$ch)); + Log::debug(sprintf('%s:- Got [%x] (%c)',self::LOGKEY,$ch,$ch)); if (($ch != self::TIMEOUT) && ($ch < 0)) return $ch; @@ -870,7 +872,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface if (++$tries > 10) return self::TIMEOUT; - Log::debug(sprintf('%s: - Sending EMSI_INQ (Try %d of 10)...',self::LOGKEY,$tries)); + Log::debug(sprintf('%s:- Sending EMSI_INQ (Try %d of 10)...',self::LOGKEY,$tries)); $this->client->buffer_add(self::EMSI_INQ.self::CR); } @@ -885,7 +887,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface if (($ch === ord(self::CR)) || ($ch === ord(self::NL))) { if (strstr($p,self::EMSI_REQ)) { - Log::info(sprintf('%s: - Got EMSI_REQ',self::LOGKEY)); + Log::info(sprintf('%s:- Got EMSI_REQ',self::LOGKEY)); if ($gotreq++) return self::OK; @@ -893,7 +895,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface $this->client->buffer_flush(5); } elseif ($p && strstr($p,self::EMSI_BEG) && strstr($p,self::EMSI_ARGUS1)) { - Log::info(sprintf('%s: - Got Intro [%s]',self::LOGKEY,$p)); + Log::info(sprintf('%s:- Got Intro [%s]',self::LOGKEY,$p)); } continue; @@ -917,7 +919,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface while (! $this->client->timer_expired($t1)) { $ch = $this->client->read_ch(max( 1,min($this->client->timer_rest($t1),$this->client->timer_rest($t2)))); if ($this->DEBUG) - Log::debug(sprintf('%s: - Got [%x] (%c)',self::LOGKEY,$ch,$ch)); + Log::debug(sprintf('%s:- Got [%x] (%c)',self::LOGKEY,$ch,$ch)); if (($ch != self::TIMEOUT) && ($ch < 0)) return $ch; @@ -946,7 +948,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface $got = 0; if (strstr($p, self::EMSI_INQ)) { - Log::info(sprintf('%s: - Got EMSI_REQ',self::LOGKEY)); + Log::info(sprintf('%s:- Got EMSI_REQ',self::LOGKEY)); return self::OK; } @@ -973,14 +975,14 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface { // @todo introduce emsi_init() to perform the job of protocol_init. Only needs to be done when we originate a session - Log::debug(sprintf('%s:+ Starting EMSI Protocol Session',self::LOGKEY)); + Log::debug(sprintf('%s:+ Starting EMSI Protocol SESSION',self::LOGKEY)); $was_req = 0; $got_req = 0; // Outbound session if ($this->originate) { - Log::debug(sprintf('%s: - Outbound session',self::LOGKEY)); + Log::debug(sprintf('%s:- Outbound session',self::LOGKEY)); $this->optionSet(self::O_PUA); //$emsi_lo |= ($this->is_freq_available() <= self::FR_NOTAVAILABLE ) ? self::O_NRQ : $emsi_lo; @@ -992,11 +994,11 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface if ($rc < 0) return (self::S_REDIAL|self::S_ADDTRY); - Log::info(sprintf('%s: - Starting outbound EMSI session to [%s]',self::LOGKEY,$this->client->address_remote)); + Log::info(sprintf('%s:- Starting outbound EMSI session to [%s]',self::LOGKEY,$this->client->address_remote)); // Inbound session } else { - Log::debug(sprintf('%s: - Inbound session',self::LOGKEY)); + Log::debug(sprintf('%s:- Inbound session',self::LOGKEY)); $rc = $this->emsi_recv(self::SM_INBOUND); if ($rc < 0) { @@ -1005,7 +1007,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface return (self::S_REDIAL|self::S_ADDTRY); } - Log::info(sprintf('%s: - Starting inbound EMSI session from [%s]',self::LOGKEY,$this->client->address_remote)); + Log::info(sprintf('%s:- Starting inbound EMSI session from [%s]',self::LOGKEY,$this->client->address_remote)); if ($this->node->aka_authed) { $xproto = $this->is_freq_available(); @@ -1016,7 +1018,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface foreach ($this->protocols as $p => $key) { if ($this->node->optionGet($key)) { - Log::debug(sprintf('%s: - Remote supports [%s] (%x)',self::LOGKEY,$p,$key)); + Log::debug(sprintf('%s:- Remote supports [%s] (%x)',self::LOGKEY,$p,$key)); $this->optionSet($key); } } @@ -1033,7 +1035,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface // @todo Lock Node AKAs - Log::info(sprintf('%s: - We have %lu%s mail, %lu%s files',self::LOGKEY,$this->send->mail_size,'b',$this->send->files_size,'b')); + Log::info(sprintf('%s:- We have [%lu%s] mail, [%lu%s] files',self::LOGKEY,$this->send->mail_size,'b',$this->send->files_size,'b')); $proto = $this->originate ? $this->node->optionGet(self::P_MASK) : $this->optionGet(self::P_MASK); @@ -1084,9 +1086,9 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface $xproto = ($this->optionGet(self::O_RH1) && ($this->node->optionGet(self::O_RH1))); $x = (substr($t,1,1) === 'H' && $xproto ) ? 'x' : ''; - Log::info(sprintf('%s: = Using [%s]',self::LOGKEY,$t)); + Log::info(sprintf('%s:- Using [%s]',self::LOGKEY,$t)); - Log::debug(sprintf('%s: = Options: %s%s%s%s%s%s%s%s%s%s%s', + Log::debug(sprintf('%s:/ Options: %s%s%s%s%s%s%s%s%s%s%s', self::LOGKEY,$x,$t, ($this->node->optionGet(self::O_LST)) ? '/LST' : '', ($this->node->optionGet(self::O_PWD)) ? '/PWD' : '', @@ -1179,7 +1181,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface */ private function wazoorecv(int $zap): bool { - Log::debug(sprintf('%s:+ wazoorecv',self::LOGKEY)); + Log::debug(sprintf('%s:+ Start WAZOO Receive',self::LOGKEY)); // @todo If the node is not defined in the DB node->address is NULL. Need to figure out how to handle those nodes. $rc = (new Zmodem)->zmodem_receive($this->client,$zap,$this->recv,$this->node->address); diff --git a/app/Classes/Protocol/Zmodem.php b/app/Classes/Protocol/Zmodem.php index 9f44701..60d1688 100644 --- a/app/Classes/Protocol/Zmodem.php +++ b/app/Classes/Protocol/Zmodem.php @@ -13,6 +13,15 @@ use App\Interfaces\Zmodem as ZmodemInterface; use App\Models\Address; use App\Traits\CRC as CRCTrait; +/** + * ZModem File Transfer protocol + * + * NOTES: + * + If a data packet follows a HEX header, it is protected with CRC-16. + * + A hex header begins with the sequence ZPAD, ZPAD, ZDLE, ZHEX. [2a 2a 18 42] + * + Type byte(2), 4 flag bytes(8), 2 bytes CRC16(4) + * + An XON character is appended to all HEX packets except ZACK and ZFIN. [11] + */ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface { private const LOGKEY = 'Z--'; @@ -28,7 +37,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface /* Special characters */ private const ZPAD = 0x2a; //* /* 052 Padding character begins frames */ - private const ZDLE = 0x18; /* Ctrl-X ZmodemReceive escape - `ala BISYNC DLE */ + private const ZDLE = 0x18; /* ZDLE - Zmodem Data Link Escape: Ctrl-X ZmodemReceive escape - `ala BISYNC DLE \030 */ private const ZDLEE = (self::ZDLE^0x40); /* Escaped ZDLE as transmitted */ private const ZDEL = 0x7f; /* DEL character */ private const ZBIN = 0x41; //A /* Binary frame indicator (CRC-16) */ @@ -41,26 +50,26 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface private const ZVBINR32 = 0x64; //d /* RLE packed Binary frame with 32 bit FCS and v.header */ private const ZRESC = 0x7e; /* RLE flag/escape character */ - private const ZRQINIT = 0; /* Request receive init */ - private const ZRINIT = 1; /* Receive init */ - private const ZSINIT = 2; /* Send init sequence (optional) */ - private const ZACK = 3; /* ACK to above */ - private const ZFILE = 4; /* File name from sender */ - public const ZSKIP = 5; /* To sender: skip this file */ - private const ZNAK = 6; /* Last packet was garbled */ - private const ZABORT = 7; /* Abort batch transfers */ - private const ZFIN = 8; /* Finish session */ - private const ZRPOS = 9; /* Resume data trans at this position */ - private const ZDATA = 10; /* Data packet(s) follow */ - private const ZEOF = 11; /* End of file */ - public const ZFERR = 12; /* Fatal Read or Write error Detected (we use for refuse -- suspend) */ - private const ZCRC = 13; /* Request for file CRC and response */ - private const ZCHALLENGE = 14; /* Receiver's Challenge */ - private const ZCOMPL = 15; /* Request is complete */ - private const ZCAN = 16; /* Other end canned session with CAN*5 */ - private const ZFREECNT = 17; /* Request for free bytes on filesystem (OK, we always send unlimited) */ - private const ZCOMMAND = 18; /* Command from sending program (NOT SUPPORTED!) */ - private const ZSTDERR = 19; /* Output to standard error, data follows (NOT SUPPORTED!) */ + private const ZRQINIT = 0x00; /* Request receive init */ + private const ZRINIT = 0x01; /* Receive init */ + private const ZSINIT = 0x02; /* Send init sequence (optional) */ + private const ZACK = 0x03; /* ACK to above */ + private const ZFILE = 0x04; /* File name from sender */ + public const ZSKIP = 0x05; /* To sender: skip this file */ + private const ZNAK = 0x06; /* Last packet was garbled */ + private const ZABORT = 0x07; /* Abort batch transfers */ + private const ZFIN = 0x08; /* Finish session */ + private const ZRPOS = 0x09; /* Resume data trans at this position */ + private const ZDATA = 0x0a; /* Data packet(s) follow */ + private const ZEOF = 0x0b; /* End of file */ + public const ZFERR = 0x0c; /* Fatal Read or Write error Detected (we use for refuse -- suspend) */ + private const ZCRC = 0x0d; /* Request for file CRC and response */ + private const ZCHALLENGE = 0x0e; /* Receiver's Challenge */ + private const ZCOMPL = 0x0f; /* Request is complete */ + private const ZCAN = 0x10; /* Other end canned session with CAN*5 */ + private const ZFREECNT = 0x11; /* Request for free bytes on filesystem (OK, we always send unlimited) */ + private const ZCOMMAND = 0x12; /* Command from sending program (NOT SUPPORTED!) */ + private const ZSTDERR = 0x13; /* Output to standard error, data follows (NOT SUPPORTED!) */ private const ZCRCE = 0x68; //h /* CRC next, frame ends, header packet follows */ private const ZCRCG = 0x69; //i /* CRC next, frame continues nonstop */ @@ -237,7 +246,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface break; default: - Log::error(sprintf('%s: ! init Strange cancap [%d]',self::LOGKEY,$canzap)); + Log::error(sprintf('%s:! Strange canzap during init [%d]',self::LOGKEY,$canzap)); } /* Maximum block size -- by protocol, may be reduced by window size later */ @@ -294,7 +303,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface */ public function zmodem_receive(SocketClient $client,int $canzap,Receive $recv,Address $ao): int { - Log::debug(sprintf('%s:+ zmodem_receive [%d]',self::LOGKEY,$canzap)); + Log::debug(sprintf('%s:+ Starting ZModem Receive [%d]',self::LOGKEY,$canzap)); $opts = $this->init($client,$canzap); @@ -341,23 +350,23 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface } else { switch ($this->recv->open()) { case self::FOP_SKIP: - Log::info(sprintf('%s: = zmodem_receive Skip this file [%s]',self::LOGKEY,$this->recv->name)); + Log::info(sprintf('%s: = zmodem_receive Skip this file [%s]',self::LOGKEY,$this->recv->nameas)); $frame = self::ZSKIP; break; case self::FOP_SUSPEND: - Log::info(sprintf('%s: = zmodem_receive Suspend this file [%s]',self::LOGKEY,$this->recv->name)); + Log::info(sprintf('%s: = zmodem_receive Suspend this file [%s]',self::LOGKEY,$this->recv->nameas)); $frame = self::ZFERR; break; case self::FOP_CONT: case self::FOP_OK: - Log::info(sprintf('%s: = zmodem_receive Receving [%s] from [%d]',self::LOGKEY,$this->recv->name,$this->recv->filepos)); + Log::info(sprintf('%s: = zmodem_receive Receving [%s] from [%d]',self::LOGKEY,$this->recv->nameas,$this->recv->pos)); $frame = self::ZRINIT; - switch (($rc=$this->ls_zrecvfile($recv->filepos))) { + switch (($rc=$this->ls_zrecvfile($recv->pos))) { case self::ZFERR: Log::debug(sprintf('%s: = zmodem_receive ZFERR',self::LOGKEY)); $this->recv->close(); @@ -671,7 +680,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface /* There was no ZDLE in stream, try to read one */ if (! $this->ls_GotZDLE) { do { - if (($c = $this->ls_readcanned($timeout)) < 0) + if (($c=$this->ls_readcanned($timeout)) < 0) return $c; /* Check for unescaped XON/XOFF */ @@ -696,7 +705,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface /* We will be here only in case of DLE */ /* We have data */ - if (($c = $this->ls_readcanned($timeout)) >= 0) { + if (($c=$this->ls_readcanned($timeout)) >= 0) { $this->ls_GotZDLE = 0; switch ($c) { @@ -843,7 +852,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface */ private function ls_zdonereceiver(): int { - Log::debug(sprintf('%s:+ ls_zdonereceiver',self::LOGKEY)); + Log::debug(sprintf('%s:+ Finished Receiving',self::LOGKEY)); $trys = 0; $retransmit = 1; @@ -887,7 +896,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface break; default: - Log::error(sprintf('%s: ? ls_zdonereceiver Something strange [%d]',self::LOGKEY,$rc)); + Log::error(sprintf('%s:! Unexpected read from client [%d]',self::LOGKEY,$rc)); if ($rc < 0) return $rc; @@ -897,7 +906,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface } while ($trys < 10); - Log::error(sprintf('%s:? ls_zdonereceiver Something strange [%d]',self::LOGKEY,$rc)); + Log::error(sprintf('%s:! Finished Receiving, we should have returned earlier [%d]',self::LOGKEY,$rc)); return $rc; } @@ -1358,6 +1367,8 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface } /** + * Prepare to receive next file (and, any be skip or refuse current file) + * * @param int $frame * @param int $first * @return int @@ -1365,7 +1376,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface */ private function ls_zrecvfinfo(int $frame,int $first,Address $ao): int { - Log::debug(sprintf('%s:+ ls_zrecvfinfo - Frame [%d], First [%d]',self::LOGKEY,$frame,$first)); + Log::debug(sprintf('%s:+ Preparing to receive file - Frame [%d], First [%d]',self::LOGKEY,$frame,$first)); $trys = 0; $retransmit = ($frame != self::ZRINIT); @@ -1389,12 +1400,12 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface do { if ($retransmit) { - if ($frame != self::ZRINIT) { + if ($frame !== self::ZRINIT) { if (($rc=$this->ls_zsendhhdr($frame,$this->ls_storelong($this->ls_SerialNum))) < 0) return $rc; } - Log::debug(sprintf('%s: - ls_zrecvfinfo ZRINIT',self::LOGKEY)); + Log::debug(sprintf('%s: - ZRINIT',self::LOGKEY)); $txHdr = []; $txHdr[self::LSZ_P0] = ($win&0xff); @@ -1409,6 +1420,8 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface $trys++; } + dump(['ls_rxHdr'=>hex_dump(join('',$this->ls_rxHdr))]); + switch (($rc=$this->ls_zrecvhdr($this->ls_rxHdr,$this->ls_HeaderTimeout))) { /* Send ZRINIT again */ case self::ZRQINIT: @@ -1527,15 +1540,23 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface return self::TIMEOUT; } + /** + * Receive a header + * + * @param array $hdr + * @param int $timeout + * @return int + * @throws SocketException + */ private function ls_zrecvhdr(array &$hdr,int $timeout): int { if ($this->DEBUG) - Log::debug(sprintf('%s:+ ls_zrecvhdr with [%d] timeout',self::LOGKEY,$timeout)); + Log::debug(sprintf('%s:+ Receive header with [%d] timeout',self::LOGKEY,$timeout)); $state = self::rhInit; $readmode = self::rm7BIT; - static $frametype = self::ERROR; /* Frame type */ + static $frametype = self::ERROR; /* Frame type */ static $crcl = 2; /* Length of CRC (CRC16 is default) */ static $crcgot = 0; /* Number of CRC bytes already got */ static $incrc = 0; /* Calculated CRC */ @@ -1547,7 +1568,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface if ($state === self::rhInit) { if ($this->DEBUG) - Log::debug(sprintf('%s: - ls_zrecvhdr Init State',self::LOGKEY)); + Log::debug(sprintf('%s:- ls_zrecvhdr Init State',self::LOGKEY)); $frametype = self::ERROR; $crc = 0; @@ -1559,27 +1580,30 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface $readmode = self::rm7BIT; } - while ($rc = $this->client->hasData($timeout)) { + while ($rc=$this->client->hasData($timeout)) { if ($this->DEBUG) - Log::debug(sprintf('%s: - ls_zrecvhdr hasData - readmode [%d] - Garbage [%d]',self::LOGKEY,$readmode,$garbage)); + Log::debug(sprintf('%s:- ls_zrecvhdr hasData - readmode [%d], garbage chars [%d], state [%d]',self::LOGKEY,$readmode,$garbage,$state)); switch ($readmode) { case self::rm8BIT: $c = $this->ls_readcanned($timeout); break; + case self::rm7BIT: $c = $this->ls_read7bit($timeout); break; + case self::rmZDLE: $c = $this->ls_readzdle($timeout); break; + case self::rmHEX: $c = $this->ls_readhex($timeout); break; } if ($this->DEBUG) - Log::debug(sprintf('%s: - ls_zrecvhdr %s [%x] (%c)',self::LOGKEY,$readmode,$c,$c)); + Log::debug(sprintf('%s: - ls_zrecvhdr [%x] (%c)',self::LOGKEY,$c,$c)); /* Here is error */ if ($c < 0) @@ -1588,9 +1612,6 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface /* Strip high bits */ $c &= 0xff; - if ($this->DEBUG) - Log::debug(sprintf('%s: = ls_zrecvhdr %x (%d)',self::LOGKEY,$c,$state)); - switch ($state) { case self::rhInit: if ($c === self::ZPAD) @@ -1697,7 +1718,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface case self::rhBYTE: if ($this->DEBUG) - Log::debug(sprintf('%s: - ls_zrecvhdr [%02x] (%d)',self::LOGKEY,$c,$got)); + Log::debug(sprintf('%s: / ls_zrecvhdr [%02x] (%d)',self::LOGKEY,$c,$got)); $hdr[$got] = $c; @@ -1710,7 +1731,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface case self::rhCRC: if ($this->DEBUG) - Log::debug(sprintf('%s: - ls_zrecvhdr [%02x] (%d|%d)',self::LOGKEY,$c,$crcgot+1,$got)); + Log::debug(sprintf('%s: %% ls_zrecvhdr [%02x] (%d|%d)',self::LOGKEY,$c,$crcgot+1,$got)); if ($crcl === 2) { $crc <<= 8; @@ -1720,30 +1741,30 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface $crc |= ($c << ($crcgot*8)); } - /* Crc finished */ + /* CRC finished */ if ($crcl === ++$crcgot) { $state = self::rhInit; $garbage = 0; if ($crcl === 2) { - if (($this->ls_Protocol&self::LSZ_OPTCRC32) && ($readmode != self::rmHEX)) - Log::error(sprintf('%s: - ls_zrecvhdr was CRC32, got CRC16 binary header',self::LOGKEY)); + if (($this->ls_Protocol&self::LSZ_OPTCRC32) && ($readmode !== self::rmHEX)) + Log::error(sprintf('%s:! ls_zrecvhdr was CRC32, got CRC16 binary header',self::LOGKEY)); $crc &= 0xffff; - if ($readmode != self::rmHEX) + if ($readmode !== self::rmHEX) $this->ls_Protocol &= (~self::LSZ_OPTCRC32); } else { if (! ($this->ls_Protocol&self::LSZ_OPTCRC32)) - Log::error(sprintf('%s: - ls_zrecvhdr was CRC16, got CRC32 binary header',self::LOGKEY)); + Log::error(sprintf('%s:! ls_zrecvhdr was CRC16, got CRC32 binary header',self::LOGKEY)); $incrc = $this->CRC32_FINISH($incrc); $this->ls_Protocol |= self::LSZ_OPTCRC32; } if ($this->DEBUG) - Log::debug(sprintf('%s: - ls_zrecvhdr CRC%d got %08x - calculated %08x',self::LOGKEY,(($crcl==2) ? 16 : 32),$incrc,$crc)); + Log::debug(sprintf('%s:- ls_zrecvhdr CRC%d got [%08x] - calculated [%08x]',self::LOGKEY,(($crcl==2) ? 16 : 32),$incrc,$crc)); if ($incrc != $crc) return self::LSZ_BADCRC; @@ -1768,10 +1789,10 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface case self::CR: case self::CR|0x80: if ($this->DEBUG) - Log::debug(sprintf('%s:? ls_zrecvhdr rhCR, ignoring any remaining chars [%d]',self::LOGKEY,$c)); + Log::debug(sprintf('%s:? ls_zrecvhdr rhCR, ignoring any remaining chars [%x]',self::LOGKEY,$c)); - /* At this point, most implementations ignore checking for the remaining chars */ - return $frametype; + /* At this point, most implementations ignore checking for the remaining chars */ + return $frametype; /* Ok, UNIX-like EOL */ case self::LF: @@ -1782,12 +1803,12 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface case self::XON: case self::XON|0x80: if ($this->DEBUG) - Log::debug(sprintf('%s:? ls_zrecvhdr rhCR, got XON without CR/LF [%d]',self::LOGKEY,$c)); + Log::debug(sprintf('%s:? ls_zrecvhdr rhCR, got XON without CR/LF [%x]',self::LOGKEY,$c)); - return $frametype; + return $frametype; default: - Log::error(sprintf('%s:? ls_zrecvhdr Something strange [%d]',self::LOGKEY,$c)); + Log::error(sprintf('%s:? ls_zrecvhdr Something strange [%x]',self::LOGKEY,$c)); return self::LSZ_BADCRC; } @@ -1803,7 +1824,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface break; default: - Log::error(sprintf('%s:? ls_zrecvhdr Something strange [%d]',self::LOGKEY,$c)); + Log::error(sprintf('%s:? ls_zrecvhdr Something strange [%x]',self::LOGKEY,$c)); return self::LSZ_BADCRC; } @@ -1828,7 +1849,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface return $frametype; default: - Log::error(sprintf('%s:! ls_zrecvhdr rhXON unexpcted [%d]',self::LOGKEY,$c)); + Log::error(sprintf('%s:! ls_zrecvhdr rhXON unexpcted [%x]',self::LOGKEY,$c)); return self::LSZ_BADCRC; } @@ -1961,7 +1982,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface $this->ls_txLastACK = $newpos; if (! $send->seek($newpos)) { - Log::error(sprintf('%s:! ZRPOS to [%ld] seek error',self::LOGKEY,$send->filepos)); + Log::error(sprintf('%s:! ZRPOS to [%ld] seek error',self::LOGKEY,$send->pos)); return self::ERROR; } @@ -2117,15 +2138,15 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface */ private function ls_zsendfile(Send $send,int $sernum,int $fileleft,int $bytesleft): int { - Log::debug(sprintf('%s:+ ls_zsendfile [%s]',self::LOGKEY,$send->name)); + Log::debug(sprintf('%s:+ ls_zsendfile [%s]',self::LOGKEY,$send->nameas)); $trys = 0; $needack = 0; - switch (($rc = $this->ls_zsendfinfo($send,$sernum,$send->filepos,$fileleft,$bytesleft))) { + switch (($rc = $this->ls_zsendfinfo($send,$sernum,$send->pos,$fileleft,$bytesleft))) { /* Ok, It's OK! */ case self::ZRPOS: - Log::debug(sprintf('%s: - ls_zsendfile ZRPOS to [%d]',self::LOGKEY,$send->filepos)); + Log::debug(sprintf('%s: - ls_zsendfile ZRPOS to [%d]',self::LOGKEY,$send->pos)); break; /* Skip it */ @@ -2165,9 +2186,9 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface /* We need to send ZDATA if previous frame was ZCRCW Also, frame will be ZCRCW, if it is after RPOS */ if ($frame === self::ZCRCW) { - Log::debug(sprintf('%s: - ls_zsendfile send ZDATA at [%d]',self::LOGKEY,$send->filepos)); + Log::debug(sprintf('%s: - ls_zsendfile send ZDATA at [%d]',self::LOGKEY,$send->pos)); - if (($rc=$this->ls_zsendbhdr(self::ZDATA,$this->ls_storelong($send->filepos))) < 0) + if (($rc=$this->ls_zsendbhdr(self::ZDATA,$this->ls_storelong($send->pos))) < 0) return $rc; } @@ -2200,7 +2221,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface break; case self::sfBuffered: - if (($send->filepos + strlen($txbuf)) > $this->ls_txLastACK + $this->ls_txWinSize) { + if (($send->pos + strlen($txbuf)) > $this->ls_txLastACK + $this->ls_txWinSize) { $frame = self::ZCRCW; /* Last sub-frame in buffer */ } else { @@ -2218,7 +2239,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface $trys = 0; do { - $needack = (self::ZCRCW === $frame) || ($this->ls_txWinSize && ($send->filepos > $this->ls_txLastACK + $this->ls_txWinSize)); + $needack = (self::ZCRCW === $frame) || ($this->ls_txWinSize && ($send->pos > $this->ls_txLastACK + $this->ls_txWinSize)); switch (($rc=$this->ls_zrecvhdr($this->ls_rxHdr,$needack ? $this->ls_HeaderTimeout : 0))) { // @todo set timeout to 5 for debugging wtih POP /* They don't need this file */ @@ -2281,8 +2302,8 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface /* Here is window, and we send more than window without ACK*/ /* Frame was ZCRCW and here is no ACK for it */ /* trys less than 10 */ - (($this->ls_txWinSize && ($send->filepos>($this->ls_txLastACK+$this->ls_txWinSize))) - || ((self::ZCRCW === $frame) && ($send->filepos>$this->ls_txLastACK))) + (($this->ls_txWinSize && ($send->pos>($this->ls_txLastACK+$this->ls_txWinSize))) + || ((self::ZCRCW === $frame) && ($send->pos>$this->ls_txLastACK))) && ++$trys < 10); if ($trys >= 10) @@ -2301,7 +2322,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface /* Ok, if here is EOF, send it and wait for ZRINIT or ZRPOS */ /* We do it here, because we coulde receive ZRPOS as answer */ if ($send->feof()) { - if (($rc=$this->ls_zsendhhdr(self::ZEOF,$this->ls_storelong($send->filepos))) < 0) + if (($rc=$this->ls_zsendhhdr(self::ZEOF,$this->ls_storelong($send->pos))) < 0) return $rc; $trys = 0; @@ -2382,7 +2403,7 @@ final class Zmodem extends Protocol implements CRCInterface,ZmodemInterface */ private function ls_zsendfinfo(Send $send,int $sernum,int $pos,int $fileleft,int $bytesleft): int { - Log::debug(sprintf('%s:+ ls_zsendfinfo [%s]',self::LOGKEY,$send->name)); + Log::debug(sprintf('%s:+ ls_zsendfinfo [%s]',self::LOGKEY,$send->nameas)); $trys = 0; $retransmit = 1;