Skip to content

feat(telnet): implement telnet protocol support #135

@jonwiggins

Description

@jonwiggins

Summary

Implement the telnet protocol (RFC 854) so that telnet:// URLs work as a drop-in replacement for curl's telnet support.

What Needs to Be Implemented

Protocol handler (crates/liburlx/src/protocol/telnet.rs)

  • Raw TCP bidirectional pipe: telnet is essentially a raw TCP connection with optional negotiation
  • IAC escaping on send: any 0xFF byte in upload data must be doubled (0xFF0xFF 0xFF) per RFC 854
  • IAC stripping on receive: parse and strip telnet command sequences from received data:
    • 3-byte commands: IAC WILL/WONT/DO/DONT <option> (255, 251-254, option)
    • Subnegotiation: IAC SB ... IAC SE (255 250 ... 255 240)
    • Escaped literal: IAC IAC → single 0xFF
  • Negotiation responses: respond to server-initiated negotiation (WILL → DONT, DO → WONT for simplicity, or accept BINARY/SGA)
  • Upload support: send data from --upload-file (file or - for stdin) to the server
  • Timeout support: --max-time / -m should trigger exit code 28 on timeout

Wiring

  • crates/liburlx/src/protocol/mod.rs: add pub mod telnet;
  • crates/liburlx/src/easy.rs (scheme dispatch ~line 6328): add "telnet" arm before the fallback scheme => case
  • crates/urlx-cli/src/args.rs (protocol list ~line 210): add telnet to the protocols vec in --version output. This is critical — the curl test runner checks --version output for telnet in the Protocols line and skips all telnet tests if it's missing.
  • --telnet-option / -t CLI flag (args.rs line 2370): currently accepted but ignored. Wire it through to the protocol handler for options like TTYPE=vt100, XDISPLOC=, NEW_ENV=var,val

Reference

  • curl's implementation: vendor/curl/lib/telnet.c (~1600 lines, but much of it is platform-specific poll loop code)
  • curl's telnet constants: vendor/curl/lib/arpa_telnet.h
  • Telnet negotiation test server: vendor/curl/tests/negtelnetserver.py
  • telnet is already in KNOWN_SCHEMES in crates/liburlx/src/url.rs (line 405) with default port 23

Acceptance Criteria — Curl Tests

The following curl tests must pass after implementation:

Test Description Server Key behavior
1326 TELNET to HTTP server (stdin upload) http telnet://host:port --upload-file - sends stdin bytes verbatim; verifies protocol output matches
1327 TELNET file upload http telnet://host:port -T file.txt uploads file contents verbatim
1452 Basic TELNET negotiation telnet (negtelnetserver.py) telnet://host:port --upload-file - with actual telnet negotiation; verifies echoed data on stdout
1548 TELNET read stdin without upload file http -m 1 telnet://host:port — expected to timeout with exit code 28

Tests 1326 and 1327 are currently skipped because telnet is not in the --version Protocols line. Tests 1452 and 1548 are beyond the current test range (1-1400) but should also pass.

No regressions: all 1,302 currently-passing tests must continue to pass.

Non-Goals

  • telnet over TLS (telnets://) — curl doesn't support this either
  • Interactive terminal mode — curl's telnet is batch-oriented (upload data, read response)

Metadata

Metadata

Assignees

No one assigned

    Labels

    optioAssigned to Optio AI agent

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions