Skip to content

Commit

Permalink
telnet: best-effort skip of command data
Browse files Browse the repository at this point in the history
usually a good idea for clients like PuTTY, since these are sent by default
in the very first packet even before user types anything else
also restore iac+eof handling, which call close() on the stream

resolve #2563
resolve #2606
  • Loading branch information
mcspr committed Jun 15, 2024
1 parent 11489d2 commit fa7c187
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `SENSOR_PUBLISH_ADDRESS` build w/ Core 2.7.4 [#2594](https://github.com/xoseperez/espurna/issues/2594)
- SoftwareSerial swapped TX & RX in configuration [#2592](https://github.com/xoseperez/espurna/issues/2592)
- InfluxDB using internal ID instead of public one [#2585](https://github.com/xoseperez/espurna/issues/2585)
- Restore previously removed real telnet command packet workarounds, allow PuTTY to authenticate [#2563](https://github.com/xoseperez/espurna/issues/2563), [#2606](https://github.com/xoseperez/espurna/issues/2606)
- Sensor filter fixes and consistent number of output values [#2543](https://github.com/xoseperez/espurna/issues/2543)

### Changed
Expand Down
56 changes: 56 additions & 0 deletions code/espurna/telnet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,57 @@ String address_string(Address address) {
return IPAddress(address.ip).toString() + ':' + String(address.port, 10);
}

// clean-up pcb data stream until telnet data ends
bool process_rfc854(pbuf* pb) {
static constexpr uint8_t Iac { 0xff };

static constexpr uint8_t Will { 0xfb };
static constexpr uint8_t Wont { 0xfc };
static constexpr uint8_t Do { 0xfd };
static constexpr uint8_t Dont { 0xfe };

static constexpr uint8_t Eof { 0xec };

auto* ptr = reinterpret_cast<uint8_t*>(pb->payload);
uint16_t len { pb->len };

bool out { true };

while (out && (len >= 2)) {
switch (ptr[0]) {
case Iac:
switch (ptr[1]) {
case Will:
case Wont:
case Do:
case Dont:
if (len >= 3) {
ptr += 3;
len -= 3;
continue;
}

break;

case Eof:
len = 0;
out = false;
ptr = nullptr;
break;
}

break;
}

break;
}

pb->len = len;
pb->payload = ptr;

return out;
}

// tracks the provided TCP `pcb`, cannot instantiate one by itself
class Client {
public:
Expand Down Expand Up @@ -587,6 +638,11 @@ class Client {
// socat, netcat, etc. usually send a single packet per line.
// Otherwise, try to buffer it and everything else in the chain.
for (auto it = pb; it != nullptr; it = it->next) {
// In case connection happens from an actual telnet client
if (!process_rfc854(pb)) {
return close();
}

auto view = line_view(it);
if (_line_buffer.size()) {
goto next;
Expand Down

0 comments on commit fa7c187

Please sign in to comment.