Show
Ignore:
Timestamp:
03/05/08 20:44:38 (5 years ago)
Author:
frsyuki
Message:

lang/actionscript/FxTerm: implemented Telnet protocol

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • lang/actionscript/FxTerm/trunk/Telnet.as

    r7300 r7506  
    1111        private var _socket:Socket; 
    1212        private var _buffer:ByteArray; 
    13         private var _state:int = 0; 
    1413        private var _active:Boolean = false; 
    1514 
    16         private static const WILL:int = 0xFB; // 251 - WILL (option code) 
    17         private static const WONT:int = 0xFC; // 252 - WON'T (option code) 
    18         private static const DO:int   = 0xFD; // 253 - DO (option code) 
    19         private static const DONT:int = 0xFE; // 254 - DON'T (option code) 
    20         private static const IAC:int  = 0xFF; // 255 - Interpret as Command (IAC) 
     15        private static const IAC:uint  = 255;  // interrupt as command 
     16        private static const WILL:uint = 251;  // I will use option 
     17        private static const WONT:uint = 252;  // I won't use option 
     18        private static const DO:uint   = 253;  // please, you use option 
     19        private static const DONT:uint = 254;  // you are not to use option 
     20        private static const SB:uint   = 250;  // interrupt as subnegotiation 
     21        private static const SE:uint   = 240;  // end subnegotiation 
     22 
     23        private static const SB_MAX_LENGTH:uint = 1024;  // FIXME 
     24 
     25        private var _istate:Function; 
     26 
     27        private var _partnerOptionHandler:Array; 
     28        private var _myOptionHandler:Array; 
     29        private var _sbHandler:Array; 
     30        private var _waitingWill:WaitingFlags; 
     31        private var _waitingDo:WaitingFlags; 
     32        private var _sbCommand:uint; 
     33        private var _sbBuffer:ByteArray; 
    2134 
    2235        // IDataOutput interface 
     
    2740                _buffer = new ByteArray(); 
    2841                _middleBuffer = new ByteArray(); 
    29                 var socket:Socket = _socket = new Socket(); 
    30                 socket.addEventListener(Event.CONNECT, connectHandler); 
    31                 socket.addEventListener(Event.CLOSE, closeHandler); 
    32                 socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); 
    33                 socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler); 
    34                 socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); 
     42 
     43                _partnerOptionHandler = new Array(); 
     44                _partnerOptionHandler.length = 256; 
     45                _myOptionHandler = new Array(); 
     46                _myOptionHandler.length = 256; 
     47                _sbHandler = new Array(); 
     48                _sbHandler.length = 256; 
     49                _waitingWill = new WaitingFlags(); 
     50                _waitingDo = new WaitingFlags(); 
     51                _sbBuffer = new ByteArray(); 
     52                _sbBuffer.endian = "bigEndian"; 
     53 
     54                _istate = istateNormal; 
     55 
     56                _socket = new Socket(); 
     57                _socket.addEventListener(Event.CONNECT, connectHandler); 
     58                _socket.addEventListener(Event.CLOSE, closeHandler); 
     59                _socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); 
     60                _socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler); 
     61                _socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); 
    3562        } 
    3663 
     
    91118        } 
    92119 
     120        /** 
     121         * @param handler  handler(cmd:uint, sw:Boolean, telnet:Telnet):void 
     122         */ 
     123        public function setPartnerOptionHandler(cmd:uint, handler:Function):void 
     124        { 
     125                _partnerOptionHandler[cmd] = handler; 
     126        } 
     127 
     128        /** 
     129         * @param handler  handler(cmd:uint, sw:Boolean, telnet:Telnet):void 
     130         */ 
     131        public function setMyOptionHandler(cmd:uint, handler:Function):void 
     132        { 
     133                _myOptionHandler[cmd] = handler; 
     134        } 
     135 
     136        /** 
     137         * @param handler  handler(cmd:uint, args:ByteArray, telnet:Telnet):void 
     138         */ 
     139        public function setSbHandler(cmd:uint, handler:Function):void 
     140        { 
     141                _sbHandler[cmd] = handler; 
     142        } 
     143 
     144 
    93145        private function connectHandler(event:Event):void 
    94146        { 
     
    114166        } 
    115167 
    116         private function socketDataHandler(ev:ProgressEvent):void 
     168 
     169        private function socketDataHandler(event:ProgressEvent):void 
    117170        { 
    118171                var socket:Socket = _socket; 
    119                 var buffer:ByteArray = _buffer; 
    120172                var beforeLength:uint = _buffer.length; 
    121                 var state:int = _state; 
     173 
    122174                var n:int = socket.bytesAvailable; 
    123                 while (--n >= 0) { 
    124                         var b:int = socket.readUnsignedByte(); 
    125                         switch (state) { 
    126                                 case 0: 
    127                                         if (b == IAC) { 
    128                                                 state = 1; 
    129                                         } else { 
    130                                                 buffer.writeByte(b); 
    131                                         } 
    132                                         break; 
    133                                 case 1: 
    134                                         if (b == DO) { 
    135                                                 state = 2; 
    136                                         } else { 
    137                                                 state = 0; 
    138                                         } 
    139                                         break; 
    140                                 case 2: 
    141                                         socket.writeByte(IAC); 
    142                                         socket.writeByte(WONT); 
    143                                         socket.writeByte(b); 
    144                                         socket.flush(); 
    145                                         state = 0; 
    146                                         break; 
    147                         } 
    148                 } 
    149                 _state = state; 
    150                 var event:Event = new ProgressEvent( 
     175                while(--n >= 0) {  
     176                        _istate(socket.readUnsignedByte()); 
     177                } 
     178 
     179                var ev:Event = new ProgressEvent( 
    151180                                ProgressEvent.PROGRESS, 
    152181                                false, 
    153182                                false, 
    154                                 buffer.length - beforeLength, 
    155                                 buffer.length 
     183                                _buffer.length - beforeLength, 
     184                                _buffer.length 
    156185                                ); 
    157                 dispatchEvent(event); 
    158         } 
    159  
     186                dispatchEvent(ev); 
     187        } 
     188 
     189        private function istateNormal(c:uint):void 
     190        { 
     191                switch(c) { 
     192                case IAC: 
     193                        _istate = istateIAC; 
     194                        break; 
     195                default: 
     196                        _buffer.writeByte(c); 
     197                        break; 
     198                } 
     199        } 
     200 
     201        private function istateIAC(c:uint):void 
     202        { 
     203                switch(c) { 
     204                case IAC: 
     205                        // IAC-escaped IAC. write one IAC 
     206                        _buffer.writeByte(IAC); 
     207                        _istate = istateNormal; 
     208                        break; 
     209                case WILL: 
     210                        _istate = istateWill; 
     211                        break; 
     212                case WONT: 
     213                        _istate = istateWont; 
     214                        break; 
     215                case DO: 
     216                        _istate = istateDo; 
     217                        break; 
     218                case DONT: 
     219                        _istate = istateDont; 
     220                        break; 
     221                case SB: 
     222                        // subnegotiation 
     223                        _istate = istateSb; 
     224                        break; 
     225                // FIXME there are many other telnet commands ... 
     226                //       NO, DM, AYT, ... 
     227                default: 
     228                        // broken or non-supported protocol 
     229                        _buffer.writeByte(IAC); 
     230                        _buffer.writeByte(c); 
     231                        _istate = istateNormal; 
     232                        break; 
     233                } 
     234        } 
     235 
     236 
     237        private function istateWill(c:uint):void 
     238        { 
     239                trace("will " + c); 
     240                if( _waitingWill.test(c) ) { 
     241                        // do (or maybe dont) is sent and receive will 
     242                        // the partner can use the option 
     243                        _waitingWill.reset(c); 
     244                        if( _partnerOptionHandler[c] ) { 
     245                                _partnerOptionHandler[c](c, true, this); 
     246                        } 
     247                } else { 
     248                        // the partner wants to use the option 
     249                        if( _partnerOptionHandler[c] ) { 
     250                                // the option is acceptable 
     251                                // the partner can use the option 
     252                                // reply DO 
     253                                _partnerOptionHandler[c](c, true, this); 
     254                                owrite3(IAC, DO, c); 
     255                        } else { 
     256                                // the option is not acceptable 
     257                                // reply DONT 
     258                                owrite3(IAC, DONT, c); 
     259                        } 
     260                } 
     261                _istate = istateNormal; 
     262        } 
     263 
     264        private function istateWont(c:uint):void 
     265        { 
     266                trace("wont " + c); 
     267                if( _waitingWill.test(c) ) { 
     268                        // do or dont is sent and receive wont 
     269                        // the partner can't use the option 
     270                        _waitingWill.reset(c); 
     271                } else { 
     272                        // I am required not to use the option 
     273                        // I can't use the option 
     274                        // reply wont 
     275                        if( _partnerOptionHandler[c] ) { 
     276                                _partnerOptionHandler[c](c, false, this); 
     277                        } 
     278                        owrite3(IAC, WONT, c); 
     279                } 
     280                _istate = istateNormal; 
     281        } 
     282 
     283        private function istateDo(c:uint):void 
     284        { 
     285                trace("do " + c); 
     286                if( _waitingDo.test(c) ) { 
     287                        // will (or maybe wont) is sent and receive do 
     288                        // I can use the option 
     289                        _waitingDo.reset(c); 
     290                        if( _myOptionHandler[c] ) { 
     291                                _myOptionHandler[c](c, true, this); 
     292                        } 
     293                } else { 
     294                        // I am required to use use the option 
     295                        if( _myOptionHandler[c] ) { 
     296                                // I support the option 
     297                                // I can use the option 
     298                                // reply will 
     299                                _myOptionHandler[c](c, true, this); 
     300                                owrite3(IAC, WILL, c); 
     301                        } else { 
     302                                // I don't support the option 
     303                                // reply wont 
     304                                owrite3(IAC, WONT, c); 
     305                        } 
     306                } 
     307                _istate = istateNormal; 
     308        } 
     309 
     310        private function istateDont(c:uint):void 
     311        { 
     312                trace("dont " + c); 
     313                if( _waitingDo.test(c) ) { 
     314                        // will is sent and receive dont 
     315                        // I can't use the option 
     316                        _waitingDo.reset(c); 
     317                        if( _myOptionHandler[c] ) { 
     318                                _myOptionHandler[c](c, false, this); 
     319                        } 
     320                } else { 
     321                        // the partner wants not to use the option 
     322                        // the partner can't use the option 
     323                        // reply dont 
     324                        if( _myOptionHandler[c] ) { 
     325                                _myOptionHandler[c](c, false, this); 
     326                        } 
     327                        owrite3(IAC, WONT, c); 
     328                } 
     329                _istate = istateNormal; 
     330        } 
     331 
     332        public function istateSb(c:uint):void 
     333        { 
     334                _sbCommand = c; 
     335                _sbBuffer.length = 0; 
     336                _istate = istateSbMessage; 
     337        } 
     338 
     339        public function istateSbMessage(c:uint):void 
     340        { 
     341                if( c == IAC ) { 
     342                        _istate = istateSbMeessageIAC; 
     343                } else { 
     344                        if( _sbBuffer.length > SB_MAX_LENGTH ) { 
     345                                // subnegotiation is too long 
     346                                _istate = istateNormal; 
     347                        } else { 
     348                                _sbBuffer.writeByte(c); 
     349                        } 
     350                } 
     351        } 
     352 
     353        public function istateSbMeessageIAC(c:uint):void 
     354        { 
     355                if( c == IAC ) { 
     356                        // IAC-escaped IAC. write one IAC 
     357                        if( _sbBuffer.length > SB_MAX_LENGTH ) { 
     358                                // subnegotiation is too long 
     359                                _istate = istateNormal; 
     360                        } else { 
     361                                _buffer.writeByte(c); 
     362                                _istate = istateSbMessage; 
     363                        } 
     364                } else if( c == SE ) { 
     365                        // end of subnegotiation 
     366                        if( _sbHandler[_sbCommand] ) { 
     367                                _sbBuffer.position = 0; 
     368                                _sbHandler[_sbCommand]( 
     369                                                _sbCommand, 
     370                                                _sbBuffer, 
     371                                                this ); 
     372                        } 
     373                        _istate = istateNormal; 
     374                } 
     375        } 
     376 
     377        private function owrite1(c1:uint):void 
     378        { 
     379                _socket.writeByte(c1); 
     380        } 
     381        private function owrite2(c1:uint, c2:uint):void 
     382        { 
     383                _socket.writeByte(c1); 
     384                _socket.writeByte(c2); 
     385        } 
     386        private function owrite3(c1:uint, c2:uint, c3:uint):void 
     387        { 
     388                _socket.writeByte(c1); 
     389                _socket.writeByte(c2); 
     390                _socket.writeByte(c3); 
     391        } 
    160392 
    161393        /** 
     
    259491                buffer.length = 0; 
    260492        } 
     493 
     494 
     495        public static const GA:uint             = 249;  // you may reverse the line 
     496        public static const EL:uint             = 248;  // erase the current line 
     497        public static const EC:uint             = 247;  // erase the current byteacter 
     498        public static const AYT:uint            = 246;  // are you there 
     499        public static const AO:uint             = 245;  // abort output--but let prog finish 
     500        public static const IP:uint             = 244;  // interrupt process--permanently 
     501        public static const BREAK:uint          = 243;  // break 
     502        public static const DM:uint             = 242;  // data mark--for connect. cleaning 
     503        public static const NOP:uint            = 241;  // nop 
     504        public static const EOR:uint            = 239;  // end of record (transparent mode) 
     505        public static const ABORT:uint          = 238;  // Abort process 
     506        public static const SUSP:uint           = 237;  // Suspend process 
     507        public static const xEOF:uint           = 236;  // End of file: EOF is already used... 
     508 
     509        public static const OPT_BINARY:uint     =   0;  // 8-bit data path 
     510        public static const OPT_ECHO:uint       =   1;  // echo 
     511        public static const OPT_RCP:uint        =   2;  // prepare to reconnect 
     512        public static const OPT_SGA:uint        =   3;  // suppress go ahead 
     513        public static const OPT_NAMS:uint       =   4;  // approximate message size 
     514        public static const OPT_STATUS:uint     =   5;  // give status 
     515        public static const OPT_TM:uint         =   6;  // timing mark 
     516        public static const OPT_RCTE:uint       =   7;  // remote controlled transmission and echo 
     517        public static const OPT_NAOL:uint       =   8;  // negotiate about output line width 
     518        public static const OPT_NAOP:uint       =   9;  // negotiate about output page size 
     519        public static const OPT_NAOCRD:uint     =  10;  // negotiate about CR disposition 
     520        public static const OPT_NAOHTS:uint     =  11;  // negotiate about horizontal tabstops 
     521        public static const OPT_NAOHTD:uint     =  12;  // negotiate about horizontal tab disposition 
     522        public static const OPT_NAOFFD:uint     =  13;  // negotiate about formfeed disposition 
     523        public static const OPT_NAOVTS:uint     =  14;  // negotiate about vertical tab stops 
     524        public static const OPT_NAOVTD:uint     =  15;  // negotiate about vertical tab disposition 
     525        public static const OPT_NAOLFD:uint     =  16;  // negotiate about output LF disposition 
     526        public static const OPT_XASCII:uint     =  17;  // extended ascic byteacter set 
     527        public static const OPT_LOGOUT:uint     =  18;  // force logout 
     528        public static const OPT_BM:uint         =  19;  // byte macro 
     529        public static const OPT_DET:uint        =  20;  // data entry terminal 
     530        public static const OPT_SUPDUP:uint     =  21;  // supdup protocol 
     531        public static const OPT_SUPDUPOUTPUT:uint = 22;  // supdup output 
     532        public static const OPT_SNDLOC:uint     =  23;  // send location 
     533        public static const OPT_TTYPE:uint      =  24;  // terminal type 
     534        public static const OPT_EOR:uint        =  25;  // end or record 
     535        public static const OPT_TUID:uint       =  26;  // TACACS user identification 
     536        public static const OPT_OUTMRK:uint     =  27;  // output marking 
     537        public static const OPT_TTYLOC:uint     =  28;  // terminal location number 
     538        public static const OPT_3270REGIME:uint =  29;  // 3270 regime 
     539        public static const OPT_X3PAD:uint      =  30;  // X.3 PAD 
     540        public static const OPT_NAWS:uint       =  31;  // window size 
     541        public static const OPT_TSPEED:uint     =  32;  // terminal speed 
     542        public static const OPT_LFLOW:uint      =  33;  // remote flow control 
     543        public static const OPT_LINEMODE:uint   =  34;  // Linemode option 
     544        public static const OPT_XDISPLOC:uint   =  35;  // X Display Location 
     545        public static const OPT_OLD_ENVIRON:uint= 36;  // Old - Environment variables 
     546        public static const OPT_AUTHENTICATION:uint = 37;  //  Authenticate 
     547        public static const OPT_ENCRYPT:uint    =  38;  // Encryption option 
     548        public static const OPT_NEW_ENVIRON:uint= 39;  // New - Environment variables 
     549        public static const OPT_TN3270E:uint    =  40;  // TN3270 enhancements 
     550        public static const OPT_XAUTH:uint      =  41;  //  
     551        public static const OPT_byteSET:uint    =  42;  // byteacter set 
     552        public static const OPT_RSP:uint        =  43;  // Remote serial port 
     553        public static const OPT_COM_PORT_OPTION:uint = 44;  //  Com port control 
     554        public static const OPT_SLE:uint        =  45;  // Suppress local echo 
     555        public static const OPT_STARTTLS:uint   =  46;  // Start TLS 
     556        public static const OPT_KERMIT:uint     =  47;  // Automatic Kermit file transfer 
     557        public static const OPT_SEND_URL:uint   =  48; 
     558        public static const OPT_FORWARD_X:uint  =  49; 
     559        public static const OPT_PRAGMA_LOGON:uint = 138; 
     560        public static const OPT_SSPI_LOGON:uint = 139; 
     561        public static const OPT_EXOPL:uint      = 255;  // extended-options-list 
     562        public static const OPT_PRAGMA_HEARTBEAT:uint = 140; 
     563 
    261564} 
    262565 
    263566} 
     567 
     568 
     569import flash.utils.ByteArray; 
     570class WaitingFlags { 
     571        private var _array:ByteArray; 
     572        public function WaitingFlags():void { 
     573                _array = new ByteArray(); 
     574                _array.length = 256; 
     575        } 
     576        public function test(i:uint):Boolean { 
     577                return _array[i] != 0; 
     578        } 
     579        public function reset(i:uint):void { 
     580                _array[i] = 0; 
     581        } 
     582        public function set(i:uint):void { 
     583                _array[i] = 1; 
     584        } 
     585}