IO::Socket::Telnet - transparent telnet negotiation for IO::Socket::INET
use IO::Socket::Telnet; my $socket = IO::Socket::Telnet->new(PeerAddr => 'random.server.org'); while (1) { $socket->send(scalar <>); defined $socket->recv(my $x, 4096) or die $!; print $x; }
Telnet is a simple protocol that sits on top of TCP/IP. It handles the negotiation of various options, both about the connection itself (ECHO) and the setup of both sides of the party (NAWS, TTYPE).
This is a wrapper around IO::Socket::INET that both strips out the telnet escape sequences and lets you handle the negotiation in a high-level manner.
There is currently no interface for defining callbacks. This will be rectified very soon. The module as it stands is still useful for stripping out telnet escape sequences.
This module is likely missing large parts of the telnet spec. Please let me know if you need particular things implemented. Failing test cases are the best bug reports!
Negotiation in IO::Socket::Telnet is achieved in two ways. By responding to callbacks and by initiating it yourself.
There are two types of callback: one for the simple IAC <DO|DONT|WILL|WONT> <option> negotiation, and the other for the more complicated IAC SB <stuff> IAC SE.
You can define a simple callback by using
$socket->telnet_simple_callback(\&your_callback);
The callback receives two arguments: the socket itself and a human-readable version of the option that is being negotiated. For example, if the server sends "IAC DO ECHO", then the second option will be "DO ECHO". This aims to facilitate the use of regular expressions on the options. If the telnet library doesn't know the name of the particular option being negotiated, it will return its character number instead. Only the first 50 or so characters are assigned meaning in the telnet spec, so if the server sends "IAC WILL chr(63)" then your callback will receive "WILL 63" as its argument.
The callback can return a few different values:
These will be interpreted as responding to the other server. They will be packaged into the regular telnet escape codes for you.
These correspond with "DO", "DONT", "WILL", and "WONT" in the obvious way. Zero will return the negation of the input (so WILL generates DONT, WONT generates DO, etc). One returns the affirmative of the input (so WILL generates DO, WONT generates DONT, etc).
undef
A return value of undef will be interpreted by IO::Socket::Telnet as "do the best you can". Generally this is equivalent to returning "DONT" or "WONT" to everything but it may change in the future. This is also the default when no callback it set.
IO::Socket::Telnet
The empty string will be interpreted as "do not respond to this negotiation." (Yes, all three canonical false values have different meanings!)
Any other return value is sent straight across the socket. This assumes you know what you're doing. Perhaps working around the limitations/ignorance of this module? :)
The complex callback is not specced yet. Right now you receive the raw subnegotiation buffer (if this means nothing to you, then run. RUN!) but there are plans to prettify this input when able. For example, NAWS (negotiate about window size) will probably just hand you the dimensions ($X, $Y) instead of chr($X).chr(0).chr($Y).chr(0).
The four basic option types (DO, DONT, WILL, WONT) each have individual methods (both lowercase and uppercase form). They each take one argument: either the name of the option ('ECHO'), or the character code of the option (chr(1) for ECHO).
There is currently no "easy" way to send complex negotiation. This will be rectified soon. At the very least I want a method that lets you wrap an arbitrary subnegotiation and have it be escaped and packaged correctly.
You must use the $socket->recv(...) method call form. recv($socket, ...) will not invoke the necessary methods. You can use print $socket ... because print currently has no special semantics.
$socket->recv(...)
recv($socket, ...)
print $socket ...
print
This library does not yet attempt to "remember" negotiations. This means that if you connect with some other client that has the same limitation, you'll likely negotiate infinitely. Thankfully most people aren't terrible like I am. This limitation (endless negotiation, not people being good) will be fixed soon. Honest!
Net::Telnet has a similar purpose, to interact via telnet with someone else. The major difference is that Net::Telnet tries to be Expect to some degree as well. This is fine if that's what you need to do, but the author of IO::Socket::Telnet wants to play NetHack on a remote server, and Net::Telnet doesn't help him very much. I think I have a better negotiation interface as well. :)
Net::Telnet, IO::Socket::INET, IO::Socket, IO::Handle
Shawn M Moore, sartak@gmail.com
sartak@gmail.com
Copyright 2007, 2009 Shawn M Moore.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install IO::Socket::Telnet, copy and paste the appropriate command in to your terminal.
cpanm
cpanm IO::Socket::Telnet
CPAN shell
perl -MCPAN -e shell install IO::Socket::Telnet
For more information on module installation, please visit the detailed CPAN module installation guide.