wertert has asked for the wisdom of the Perl Monks concerning the following question:

Following up on a post a few days ago (node 67578) I am working on a 'telnet passthrough'. This is a process that connects to a server via telnet ( net::telnet) and also offers a standard socket ( io::socket ) for other users to connect to. Key presses are then passed from the socket to the telnet session and responses copied back. I developed the following on unix and it seems to work. I am surprised at that fact..... $switch is a telnet object (see switchConnect()) and I do
print $switch $byte # prints one byte to the telnet connection. + Confirmed as written by checking DUMP file sysread($switch, $byte2, 1) # reads in one byte from the telnet inp +ut buffer.
Can someone explaing why this works as $switch is not a filehandle. Now for the big problem. I have to get this running on a windows system running activeperl v5.6.1. Copied it over and everything has stopped working. boo hoo. the line from above has to be swapped to something like
-print $switch $byte +$switch->put($byte); ( telnet method )
and the whole child/parent thing seems to stop working or deadlock. If I replace
-while (sysread($switch, $byte2, 1)) -{ - print $client $byte2; -} +sleep(50)
in the parent section things seem to start going again but obviously nothing it now coming back from the telnet console. What is going on ?? here's the program
#!/opt/DKBperl/bin/perl $|=1; use IO::Socket; use Net::Telnet; #pass4.pl <switchname> <port> my($switch)=switchConnect($ARGV[0]); my($server) = IO::Socket::INET->new( Proto => 'tcp', LocalPort => $ARGV[1], Listen => SOMAXCONN, Reuse => 1); die "can't setup server" unless $server; while ($client = $server->accept()) { if (!defined($child_pid = fork())) { die "cannot fork: $!"; } if($child_pid) { print "I'm the parent $child_pid\n"; # REPLY # accept input from the telnet connection (switch) and copi +es it to heroix (io::socket) while (sysread($switch, $byte2, 1)) { print $client $byte2; } kill("TERM" => $kidpid); # send SIGTERM to child exit 0; } else { print "I'm the child $child_pid\n"; # accept input from heroix (io::socket) and copies it to +the telnet connection (switch) $client->autoflush(1); while (sysread($client, $byte, 1)) { $num=ord($byte); if($num==127) {$num=8}; print $switch chr($num); } print "child exiting\n"; } } sub switchConnect { my($switchName)=@_; $t = new Net::Telnet()->new( input_log => "tmp/in", dump_log => "tmp/dump", Timeout => 10, output_log => "tmp/out", errmode => 'return'); print("Attempting to open switch $switchName.."); $t->open(host=>$switchName); if(!$t->waitfor('/login:/')) { print "$hsgname seems engaged- exiting code 10\n"; exit(10); } $t->print("admin"); $t->waitfor('/Password:/'); $t->print("santest1"); if(!$t->waitfor('/\>/')) { print "Timeout on the password. Is the password correct for $ +hsgname ? - exiting code 11\n"; exit(11); } print "..ok\n"; return $t; }

update (broquaint): added a ending </b> tag and put a <readmore> tag before the main section of code

Replies are listed 'Best First'.
Re: telnet passthrough 2
by robartes (Priest) on Nov 12, 2002 at 11:11 UTC
    One of your questions I can answer for now: $switch is a filehandle (or more specifically, a socket). $switch is returned from sub switchConnect, where it is initialised as a Net::Telnet instance. Net::Telnet->new returns an instance of IO::Socket, which is a socket, which is a filehandle (well, respects filehandle semantics).

    As to why your code fails to work on Win32/ActivePerl, I don't know (and have no way nearby to find out or test).

    CU
    Robartes-

Re: telnet passthrough 2
by pg (Canon) on Nov 12, 2002 at 17:01 UTC
    Not try to figure out what is wrong with your code. Just want to memtion one point, you called the autoflush func on the socket, which is no longer needed, autoflush is now the default behavior. Well, obviously it does not cause problem, if you call it explicitly.
Re: telnet passthrough 2
by iburrell (Chaplain) on Nov 12, 2002 at 17:08 UTC
    You might be running into problems with fork() on Windows. ActivePerl emulates fork but it isn't the most reliable thing.

    Also, why are you reading a single byte at a time with sysread? You can read as much as you can into one buffer. On sockets, sysread will return the available data and not wait until the entire length is read. That way you cut down on the number of system calls without worrying about blocking. Do you really mean to have only one telnet session?

    Also, you should be using use strict and use warnings. You should also use lexical (my) variables instead of global variables.