You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Sebb (JIRA)" <ji...@apache.org> on 2010/07/11 01:24:51 UTC

[jira] Updated: (NET-89) [net] TelnetClient broken for binary transmissions + solution

     [ https://issues.apache.org/jira/browse/NET-89?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Sebb updated NET-89:
--------------------

    Description: 
TelnetClient does not handle correctly binary transmissions in two places:

First in TelnetClient#_connectAction_() the telnet input and output streams are
wrapped in the NetASCII streams to handle net vs platform line separator
conversion which breaks the binary data. My quick solution was to simply remove
those two wrapping streams. A more general solution might be to provide access
to the unfilterer stream with methods like getUnfilteredInputStream and
getUnfilteredOutputStream or to dynamically stop the NetASCII stream from
'corrupting' the stream when a TelnetOption.BINARY option is negotiated.

Also, in TelnetInoutStream#__read() there is a bug in the __receiveState
handling for the _STATE_IAC state. When a second consecutive IAC (0x255) is
received to encode the single 0x255 character, read does not return 0x255 but
instead move on to reading the next char in the stream.

The current code reads:

{code}
case _STATE_IAC:
    switch (ch)
    {
    case TelnetCommand.WILL:
        __receiveState = _STATE_WILL;
        continue;
    case TelnetCommand.WONT:
        __receiveState = _STATE_WONT;
        continue;
    case TelnetCommand.DO:
        __receiveState = _STATE_DO;
        continue;
    case TelnetCommand.DONT:
        __receiveState = _STATE_DONT;
        continue;
    /* TERMINAL-TYPE option (start)*/
    case TelnetCommand.SB:
        __suboption_count = 0;
        __receiveState = _STATE_SB;
        continue;
    /* TERMINAL-TYPE option (end)*/
    case TelnetCommand.IAC:
        __receiveState = _STATE_DATA;
        break;
    default:
        break;
    }
    __receiveState = _STATE_DATA;
    continue;
case _STATE_WILL:
{code}

but it should be:

{code}
case _STATE_IAC:
    switch (ch)
    {
    case TelnetCommand.WILL:
        __receiveState = _STATE_WILL;
        continue;
    case TelnetCommand.WONT:
        __receiveState = _STATE_WONT;
        continue;
    case TelnetCommand.DO:
        __receiveState = _STATE_DO;
        continue;
    case TelnetCommand.DONT:
        __receiveState = _STATE_DONT;
        continue;
    /* TERMINAL-TYPE option (start)*/
    case TelnetCommand.SB:
        __suboption_count = 0;
        __receiveState = _STATE_SB;
        continue;
    /* TERMINAL-TYPE option (end)*/
    case TelnetCommand.IAC:
        __receiveState = _STATE_DATA;
        break; // exit to enclosing switch to return from read
    default:
        __receiveState = _STATE_DATA;           
        continue; // move on the next char
    }
    break; // exit and return from read
case _STATE_WILL:
{code}

I'll provide patches for this.
Colin.

  was:
TelnetClient does not handle correctly binary transmissions in two places:

First in TelnetClient#_connectAction_() the telnet input and output streams are
wrapped in the NetASCII streams to handle net vs platform line separator
conversion which breaks the binary data. My quick solution was to simply remove
those two wrapping streams. A more general solution might be to provide access
to the unfilterer stream with methods like getUnfilteredInputStream and
getUnfilteredOutputStream or to dynamically stop the NetASCII stream from
'corrupting' the stream when a TelnetOption.BINARY option is negotiated.

Also, in TelnetInoutStream#__read() there is a bug in the __receiveState
handling for the _STATE_IAC state. When a second consecutive IAC (0x255) is
received to encode the single 0x255 character, read does not return 0x255 but
instead move on to reading the next char in the stream.

The current code reads:

case _STATE_IAC:
    switch (ch)
    {
    case TelnetCommand.WILL:
        __receiveState = _STATE_WILL;
        continue;
    case TelnetCommand.WONT:
        __receiveState = _STATE_WONT;
        continue;
    case TelnetCommand.DO:
        __receiveState = _STATE_DO;
        continue;
    case TelnetCommand.DONT:
        __receiveState = _STATE_DONT;
        continue;
    /* TERMINAL-TYPE option (start)*/
    case TelnetCommand.SB:
        __suboption_count = 0;
        __receiveState = _STATE_SB;
        continue;
    /* TERMINAL-TYPE option (end)*/
    case TelnetCommand.IAC:
        __receiveState = _STATE_DATA;
        break;
    default:
        break;
    }
    __receiveState = _STATE_DATA;
    continue;
case _STATE_WILL:

but it should be:

case _STATE_IAC:
    switch (ch)
    {
    case TelnetCommand.WILL:
        __receiveState = _STATE_WILL;
        continue;
    case TelnetCommand.WONT:
        __receiveState = _STATE_WONT;
        continue;
    case TelnetCommand.DO:
        __receiveState = _STATE_DO;
        continue;
    case TelnetCommand.DONT:
        __receiveState = _STATE_DONT;
        continue;
    /* TERMINAL-TYPE option (start)*/
    case TelnetCommand.SB:
        __suboption_count = 0;
        __receiveState = _STATE_SB;
        continue;
    /* TERMINAL-TYPE option (end)*/
    case TelnetCommand.IAC:
        __receiveState = _STATE_DATA;
        break; // exit to enclosing switch to return from read
    default:
        __receiveState = _STATE_DATA;           
        continue; // move on the next char
    }
    break; // exit and return from read
case _STATE_WILL:

I'll provide patches for this.
Colin.


Add code markers to make code easier to read.

> [net] TelnetClient broken for binary transmissions + solution
> -------------------------------------------------------------
>
>                 Key: NET-89
>                 URL: https://issues.apache.org/jira/browse/NET-89
>             Project: Commons Net
>          Issue Type: Bug
>         Environment: Operating System: All
> Platform: All
>            Reporter: Colin Surprenant
>
> TelnetClient does not handle correctly binary transmissions in two places:
> First in TelnetClient#_connectAction_() the telnet input and output streams are
> wrapped in the NetASCII streams to handle net vs platform line separator
> conversion which breaks the binary data. My quick solution was to simply remove
> those two wrapping streams. A more general solution might be to provide access
> to the unfilterer stream with methods like getUnfilteredInputStream and
> getUnfilteredOutputStream or to dynamically stop the NetASCII stream from
> 'corrupting' the stream when a TelnetOption.BINARY option is negotiated.
> Also, in TelnetInoutStream#__read() there is a bug in the __receiveState
> handling for the _STATE_IAC state. When a second consecutive IAC (0x255) is
> received to encode the single 0x255 character, read does not return 0x255 but
> instead move on to reading the next char in the stream.
> The current code reads:
> {code}
> case _STATE_IAC:
>     switch (ch)
>     {
>     case TelnetCommand.WILL:
>         __receiveState = _STATE_WILL;
>         continue;
>     case TelnetCommand.WONT:
>         __receiveState = _STATE_WONT;
>         continue;
>     case TelnetCommand.DO:
>         __receiveState = _STATE_DO;
>         continue;
>     case TelnetCommand.DONT:
>         __receiveState = _STATE_DONT;
>         continue;
>     /* TERMINAL-TYPE option (start)*/
>     case TelnetCommand.SB:
>         __suboption_count = 0;
>         __receiveState = _STATE_SB;
>         continue;
>     /* TERMINAL-TYPE option (end)*/
>     case TelnetCommand.IAC:
>         __receiveState = _STATE_DATA;
>         break;
>     default:
>         break;
>     }
>     __receiveState = _STATE_DATA;
>     continue;
> case _STATE_WILL:
> {code}
> but it should be:
> {code}
> case _STATE_IAC:
>     switch (ch)
>     {
>     case TelnetCommand.WILL:
>         __receiveState = _STATE_WILL;
>         continue;
>     case TelnetCommand.WONT:
>         __receiveState = _STATE_WONT;
>         continue;
>     case TelnetCommand.DO:
>         __receiveState = _STATE_DO;
>         continue;
>     case TelnetCommand.DONT:
>         __receiveState = _STATE_DONT;
>         continue;
>     /* TERMINAL-TYPE option (start)*/
>     case TelnetCommand.SB:
>         __suboption_count = 0;
>         __receiveState = _STATE_SB;
>         continue;
>     /* TERMINAL-TYPE option (end)*/
>     case TelnetCommand.IAC:
>         __receiveState = _STATE_DATA;
>         break; // exit to enclosing switch to return from read
>     default:
>         __receiveState = _STATE_DATA;           
>         continue; // move on the next char
>     }
>     break; // exit and return from read
> case _STATE_WILL:
> {code}
> I'll provide patches for this.
> Colin.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.