Autodetect Telnet IAC modes, and if in binary mode esc 0xff chars
All checks were successful
Create Docker Image / Build Docker Image (x86_64) (push) Successful in 37s
Create Docker Image / Build Docker Image (arm64) (push) Successful in 1m34s
Create Docker Image / Final Docker Image Manifest (push) Successful in 10s

This commit is contained in:
2025-01-30 23:18:49 +11:00
parent 52961e2403
commit b1eaec3271
3 changed files with 167 additions and 5 deletions

View File

@@ -197,6 +197,7 @@ final class SocketClient {
return match ($key) {
'address_remote', 'port_remote' => $this->{$key},
'cps', 'speed' => Arr::get($this->session,$key),
'iac_bin' => Arr::get($this->session,$key),
'rx_free' => self::RX_BUF_SIZE-$this->rx_left,
'rx_left' => strlen($this->rx_buf),
'tx_free' => self::TX_BUF_SIZE-strlen($this->tx_buf),
@@ -210,6 +211,7 @@ final class SocketClient {
switch ($key) {
case 'cps':
case 'speed':
case 'iac_bin':
$this->session[$key] = $value;
break;
@@ -428,11 +430,45 @@ final class SocketClient {
Log::debug(sprintf('%s:- Returning [%d] chars from the RX buffer',self::LOGKEY,$len));
$result = substr($this->rx_buf,0,$len);
$this->rx_buf = substr($this->rx_buf,strlen($result));
if ($flags !== MSG_PEEK)
$this->rx_buf = substr($this->rx_buf,strlen($result));
return $result;
// In case we are in Telnet Binary Mode
if ($this->iac_bin) {
if (self::DEBUG)
Log::debug(sprintf('%s:- Telnet IAC Binary Mode, looking for ff ff',self::LOGKEY),['result'=>hex_dump($result)]);
// if the last char is ff, we need to get the next char
if (str_ends_with($result,"\xff")) {
if (self::DEBUG)
Log::debug(sprintf('%s: - We have a hit',self::LOGKEY));
// If we have it in our buffer, just get it
if ($this->rx_left) {
$result .= substr($this->rx_buf,0,1);
$this->rx_buf = substr($this->rx_buf,1);
// Else put everything back into rx_buf, and increase len by 1
} else {
$this->rx_buf = $result;
$len++;
$result = '';
}
}
if (strlen($result) > 1)
$result = str_replace("\xff\xff","\xff",$result);
if (strlen($result))
return $result;
} else
return $result;
}
if (self::DEBUG)
Log::debug(sprintf('%s:- Buffer doesnt have [%d] chars, it only has [%d], or it ends with 0xff',self::LOGKEY,$len,strlen($this->rx_buf)),['rx_buf'=>hex_dump($this->rx_buf)]);
if ($timeout && (! $this->hasData($timeout)))
throw new SocketException(SocketException::SOCKET_TIMEOUT,$timeout);
@@ -486,13 +522,19 @@ final class SocketClient {
}
}
if ($flags === MSG_PEEK) {
Log::debug(sprintf('%s:- Returning [%d] chars as a result of a PEEK operation, buffer would have [%d], but still has [%d]',self::LOGKEY,$len,strlen($this->rx_buf.$buf),strlen($this->rx_buf)),['rx_buf'=>hex_dump($this->rx_buf),'buf'=>hex_dump($buf)]);
return substr($this->rx_buf.$buf,0,$len);
}
$this->rx_buf .= $buf;
if (self::DEBUG)
Log::debug(sprintf('%s:- Added [%d] chars to the RX buffer',self::LOGKEY,strlen($buf)),['rx_buf'=>hex_dump($this->rx_buf)]);
// Loop again and return the data, now that it is in the RX buffer
return $this->read($timeout,$len);
return $this->read($timeout,$len,$flags);
}
/**
@@ -511,6 +553,9 @@ final class SocketClient {
else
throw new SocketException(SocketException::SOCKET_TIMEOUT,$timeout);
if (self::DEBUG)
Log::debug(sprintf('%s:+ read_ch [%c] (%x)',self::LOGKEY,$ch,ord($ch)));
return ord($ch);
}
@@ -549,6 +594,11 @@ final class SocketClient {
if (self::DEBUG)
Log::debug(sprintf('%s:- Sending [%d] chars [%s]',self::LOGKEY,strlen($message),Str::limit($message,15)));
if ($this->iac_bin) {
Log::debug(sprintf('%s:- IAC_BIN mode, looking for 0xff',self::LOGKEY));
$message = str_replace("\xff","\xff\xff",$message);
}
switch ($this->type) {
case SOCK_STREAM:
return socket_write($this->connection,$message,strlen($message));