in reply to Re^12: Can't decompress zlib compression stream with Compress:Zlib
in thread Can't decompress zlib compression stream with Compress:Zlib
Net::Telnet doesn't easily lend itself to subclassing, at least not in the way you want to use it. It calls the (private) subroutine _fillbuf as:
&_fillbuf($self, $s, 0);
... which will never respect inheritance.
Before copying and rewriting Net::Telnet in a more approachable manner, you can monkey-patch Net::Telnet instead of inheriting:
require Net::Telnet; { no warnings 'redefine'; *Net::Telnet::_fillbuf = sub { ... }; }; my $connectObj = Net::Telnet->new(); $connectObj->open( Host => 'iberiamud.mooo.com', Port => 5900, );
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^14: Can't decompress zlib compression stream with Compress:Zlib
by lesrol (Initiate) on Oct 11, 2016 at 16:52 UTC | |
Thanks. I have monkey patched the test script as you suggest, adding debug messages as suggested by pmqs. The first call to Compress::Zlib->inflate succeeds, and we see the expected 'Wrong password' message and a new prompt. Subsequent calls to Compress::Zlib->inflate fail
The new, improved test script:
| [reply] [d/l] [select] |
by pmqs (Friar) on Oct 11, 2016 at 19:49 UTC | |
Here is a question - do you expect the complete compressed buffer to be present in the sysread you do directly before the call to inflate ? Looking at the code I'm guessing that it isn't. Please correct me if that is wrong. So, assuming that is the case, the code in its current state has a number of problems. Firstly, the code doesn't explicitly handle the end of the compressed data stream at all. In this section of code you are using the absence of any data in $nout to flag an error. That isn't safe
You should instead be checking the value of $status returned from inflate. If you get Z_OK, inflate has succeeded and the content from the next sysread (when _fillbuff gets called again) can be fed to inflate. If you get Z_STREAM_END that signals the end of the compressed data stream, so the next sysread can't be fed to inflate (unless the telnet protocol allows multiple zlib streams). Any other status code means an error of some sort in the compressed data stream. One other issue you need to take care of when you get Z_STREAM_END is the presence of trailing data directly after the end of the zlib data stream (don't know the details of how telnet works with zlib, so I don't know if this will happen in practice). If there is trailing data the $buf variable will contain it (inflate will remove all compressed data from the buffer parameter you pass it). In this case I think you can deak with that by changing this line
to this
Next potential problem is pushback_buf. That looks like it is used to store data that hasn't been processed by the telnet protocol. The problem is that the data from sysread is prefixed by any pushback_buf that exists. If a previous call to __fillbuf made a call to inflate and the telnet module hasn't used up all of the data read, you end up trying to uncompress something that is prefixed with uncompressed data. | [reply] [d/l] [select] |
by lesrol (Initiate) on Oct 12, 2016 at 11:57 UTC | |
After implementing those changes, the script now works perfectly (as if by magic). I hardly have the words to express my thanks, so I'll settle for posting working code for the next poor sucker who tries to do the same thing.
| [reply] [d/l] |