www/js/client.js
// Do telnet negotiations for 'buf' and return the plain text only.
Do telnet negotiations for 'buf' and return the plain text only.
Do telnet negotiations for ' buf ' and return the plain text only .
function doTelnetNegotions(sock, buf) {
  var IAC  = '\xff'; 
  var DONT = '\xfe'; 
  var DO   = '\xfd'; 
  var WONT = '\xfc'; 
  var WILL = '\xfb'; 
  var SB   = '\xfa'; 
  var SE   = '\xf0'; 
  var EOR  = '\xef'; 
  var TELOPT_ECHO     = '\x01'; 
  var TELOPT_STATUS   = '\x05'; 
  var TELOPT_TTYPE    = '\x18'; 
  var TELOPT_EOR      = '\x19'; 
  var TELOPT_TSPEED   = '\x20'; 
  var TELOPT_LINEMODE = '\x22'; 
  var TELOPT_XDISPLOC = '\x23'; 
  var TELOPT_ENVIRON  = '\x24'; 
  var TELOPT_CHARSET  = '\x2a'; 
  var TELOPT_GMCP     = '\xc9'; 
  var TELQUAL_IS      = '\x00'; 
  var TELQUAL_SEND    = '\x01'; 
  var tty_neg_types = ['dumb','ansi','xterm','xterm-256color','xterm-direct'];
  var strippedBuf = '';
  buf = pending + buf;
  pending = '';
  var len = buf.length;
  if(len>0){
    var oldIacIdx = 0;
    var newIacIdx = 0;
    while((newIacIdx=buf.indexOf(IAC,oldIacIdx))>=0){
      strippedBuf+=buf.substr(oldIacIdx, newIacIdx-oldIacIdx);
      if (newIacIdx < len && buf[newIacIdx + 1] == EOR) {
        var startOfPrompt = strippedBuf.lastIndexOf('\n', len);
        var prmpt = strippedBuf.substr(startOfPrompt+1);
        if (prmpt.length > 0) {
          if (startOfPrompt<0) strippedBuf = '';
          else strippedBuf = strippedBuf.substr(0, startOfPrompt+1);
          $('#prompt').html(ansi_up.ansi_to_html(prmpt));
        }
        oldIacIdx = newIacIdx+2;
      } 
      else if(newIacIdx+2 >= len) {
        pending = buf.substr(newIacIdx);
        oldIacIdx = len;
      }
      else {
        switch(buf[newIacIdx+1]){
          case DONT:
            oldIacIdx = newIacIdx+3;
            break;
          case DO:
            switch(buf[newIacIdx+2]){
              case TELOPT_TTYPE:
                if(sock) sock.emit('stream', IAC+WILL+TELOPT_TTYPE);
                tty_neg_index = 0; 
                break;
              case TELOPT_TSPEED:
              case TELOPT_LINEMODE:
              case TELOPT_XDISPLOC:
              case TELOPT_ENVIRON:
              default:
                if(sock) sock.emit('stream', IAC+WONT+buf.substr(newIacIdx+2,1));
                break;
            }
            oldIacIdx = newIacIdx+3;
            break;
          case WONT:
            switch(buf[newIacIdx+2]){
              case TELOPT_ECHO:
                leavePWMode();
                if(sock) sock.emit('stream', IAC+DONT+TELOPT_ECHO);
                break;
              default:
                if(sock) sock.emit('stream', IAC+DONT+buf.substr(newIacIdx+2,1));
                break;
            }
            oldIacIdx = newIacIdx+3;
            break;
          case WILL:
            switch(buf[newIacIdx+2]){
              case TELOPT_EOR:
                if(sock) sock.emit('stream', IAC+DO+TELOPT_EOR);
                break;
              case TELOPT_ECHO:
                enterPWMode();
                if(sock) sock.emit('stream', IAC+DO+TELOPT_ECHO);
                break;
              case TELOPT_GMCP:
                if(sock) sock.emit('stream', IAC+DO+TELOPT_GMCP);
                if(sock) sock.emit('stream', IAC+SB+TELOPT_GMCP+getGMCPHello()+IAC+SE);
                break;
              default:
                if(sock) sock.emit('stream', IAC+DONT+buf.substr(newIacIdx+2,1));
                break;
            }
            oldIacIdx = newIacIdx+3;
            break;
          case SB:
            var endSubNegIdx=buf.indexOf(SE, newIacIdx+2);
            if(endSubNegIdx<0) {
              pending = buf.substr(newIacIdx);
              oldIacIdx = len;
            } else {
              if (buf[newIacIdx+2]==TELOPT_GMCP){
                doGMCPReceive(sock, buf.substr(newIacIdx+3, endSubNegIdx-(newIacIdx+4)));
              }
              else if (buf[newIacIdx+2]==TELOPT_TTYPE && buf[newIacIdx+3]==TELQUAL_SEND){
                if(sock) sock.emit('stream', IAC+SB+TELOPT_TTYPE+TELQUAL_IS+tty_neg_types[tty_neg_index]+IAC+SE);
                if (tty_neg_index+1 < tty_neg_types.length) tty_neg_index = tty_neg_index + 1;
              }
              else {
                console.log('Don\'t understand: [IAC+SB+('+buf.charCodeAt(newIacIdx+2)+')...]');
              }
              oldIacIdx = endSubNegIdx+1;
            }
            break;
          default:
            console.log('Don\'t understand: [IAC+('+buf.charCodeAt(newIacIdx+1)+')+('+buf.charCodeAt(newIacIdx+2)+')...]\n');
            oldIacIdx = newIacIdx+3;
            break;
        }
      }
    }
    if(oldIacIdx+1<len) strippedBuf+=buf.substr(oldIacIdx, len-oldIacIdx);
  }
  return strippedBuf;
}
function doTelnetNegotions ( sock , buf ) { var IAC = '\xff' ; var DONT = '\xfe' ; var DO = '\xfd' ; var WONT = '\xfc' ; var WILL = '\xfb' ; var SB = '\xfa' ; var SE = '\xf0' ; var EOR = '\xef' ; var TELOPT_ECHO = '\x01' ; var TELOPT_STATUS = '\x05' ; var TELOPT_TTYPE = '\x18' ; var TELOPT_EOR = '\x19' ; var TELOPT_TSPEED = '\x20' ; var TELOPT_LINEMODE = '\x22' ; var TELOPT_XDISPLOC = '\x23' ; var TELOPT_ENVIRON = '\x24' ; var TELOPT_CHARSET = '\x2a' ; var TELOPT_GMCP = '\xc9' ; var TELQUAL_IS = '\x00' ; var TELQUAL_SEND = '\x01' ; var tty_neg_types = [ 'dumb' , 'ansi' , 'xterm' , 'xterm-256color' , 'xterm-direct' ] ; var strippedBuf = '' ; buf = pending + buf ; pending = '' ; var len = buf . length ; if ( len > 0 ) { var oldIacIdx = 0 ; var newIacIdx = 0 ; while ( ( newIacIdx = buf . indexOf ( IAC , oldIacIdx ) ) >= 0 ) { strippedBuf += buf . substr ( oldIacIdx , newIacIdx - oldIacIdx ) ; if ( newIacIdx < len && buf [ newIacIdx + 1 ] == EOR ) { var startOfPrompt = strippedBuf . lastIndexOf ( '\n' , len ) ; var prmpt = strippedBuf . substr ( startOfPrompt + 1 ) ; if ( prmpt . length > 0 ) { if ( startOfPrompt < 0 ) strippedBuf = '' ; else strippedBuf = strippedBuf . substr ( 0 , startOfPrompt + 1 ) ; $ ( '#prompt' ) . html ( ansi_up . ansi_to_html ( prmpt ) ) ; } oldIacIdx = newIacIdx + 2 ; } else if ( newIacIdx + 2 >= len ) { pending = buf . substr ( newIacIdx ) ; oldIacIdx = len ; } else { switch ( buf [ newIacIdx + 1 ] ) { case DONT : oldIacIdx = newIacIdx + 3 ; break ; case DO : switch ( buf [ newIacIdx + 2 ] ) { case TELOPT_TTYPE : if ( sock ) sock . emit ( 'stream' , IAC + WILL + TELOPT_TTYPE ) ; tty_neg_index = 0 ; break ; case TELOPT_TSPEED : case TELOPT_LINEMODE : case TELOPT_XDISPLOC : case TELOPT_ENVIRON : default : if ( sock ) sock . emit ( 'stream' , IAC + WONT + buf . substr ( newIacIdx + 2 , 1 ) ) ; break ; } oldIacIdx = newIacIdx + 3 ; break ; case WONT : switch ( buf [ newIacIdx + 2 ] ) { case TELOPT_ECHO : leavePWMode ( ) ; if ( sock ) sock . emit ( 'stream' , IAC + DONT + TELOPT_ECHO ) ; break ; default : if ( sock ) sock . emit ( 'stream' , IAC + DONT + buf . substr ( newIacIdx + 2 , 1 ) ) ; break ; } oldIacIdx = newIacIdx + 3 ; break ; case WILL : switch ( buf [ newIacIdx + 2 ] ) { case TELOPT_EOR : if ( sock ) sock . emit ( 'stream' , IAC + DO + TELOPT_EOR ) ; break ; case TELOPT_ECHO : enterPWMode ( ) ; if ( sock ) sock . emit ( 'stream' , IAC + DO + TELOPT_ECHO ) ; break ; case TELOPT_GMCP : if ( sock ) sock . emit ( 'stream' , IAC + DO + TELOPT_GMCP ) ; if ( sock ) sock . emit ( 'stream' , IAC + SB + TELOPT_GMCP + getGMCPHello ( ) + IAC + SE ) ; break ; default : if ( sock ) sock . emit ( 'stream' , IAC + DONT + buf . substr ( newIacIdx + 2 , 1 ) ) ; break ; } oldIacIdx = newIacIdx + 3 ; break ; case SB : var endSubNegIdx = buf . indexOf ( SE , newIacIdx + 2 ) ; if ( endSubNegIdx < 0 ) { pending = buf . substr ( newIacIdx ) ; oldIacIdx = len ; } else { if ( buf [ newIacIdx + 2 ] == TELOPT_GMCP ) { doGMCPReceive ( sock , buf . substr ( newIacIdx + 3 , endSubNegIdx - ( newIacIdx + 4 ) ) ) ; } else if ( buf [ newIacIdx + 2 ] == TELOPT_TTYPE && buf [ newIacIdx + 3 ] == TELQUAL_SEND ) { if ( sock ) sock . emit ( 'stream' , IAC + SB + TELOPT_TTYPE + TELQUAL_IS + tty_neg_types [ tty_neg_index ] + IAC + SE ) ; if ( tty_neg_index + 1 < tty_neg_types . length ) tty_neg_index = tty_neg_index + 1 ; } else { console . log ( 'Don\'t understand: [IAC+SB+(' + buf . charCodeAt ( newIacIdx + 2 ) + ')...]' ) ; } oldIacIdx = endSubNegIdx + 1 ; } break ; default : console . log ( 'Don\'t understand: [IAC+(' + buf . charCodeAt ( newIacIdx + 1 ) + ')+(' + buf . charCodeAt ( newIacIdx + 2 ) + ')...]\n' ) ; oldIacIdx = newIacIdx + 3 ; break ; } } } if ( oldIacIdx + 1 < len ) strippedBuf += buf . substr ( oldIacIdx , len - oldIacIdx ) ; } return strippedBuf ; }
Do telnet negotiations for 'buf' and return the plain text only.
Do telnet negotiations for ' buf ' and return the plain text only .
// TELNET protocol // 255 // 254 // 253 // 252 // 251 // 250 sub negotiation // 240 end sub negotiation // 239 End Of Record // TELNET options (WL relevant) //  1 //  5 // 24 // 25 // 32 // 34 // 35 // 36 // 42 // 201 -> http://www.gammon.com.au/gmcp // sub-option qualifiers // IS option // SEND option // TTYPE negotiaion // receive buffer // Copy first part of strippedBuf and skip IACs // IAC+EOR is only 2 bytes  // truncate strippedBuf //console.log('PRMPT [' + prmpt+']\n'); // Skip the IAC+EOR in the buffer // Everything should be (at least) 3 bytes long. // save incomplete telnet negotiation for later processing // do all complete messages // we are 'xterm' and will use this (see SB below) // reset // not yet //case TELOPT_CHARSET: //  if(sock) sock.emit('stream', IAC+WILL+TELOPT_CHARSET); //  break; // we WONT do anything else. So just reply all DO by WONT // enable local echo! // if the server WONT to do something anymore, tell it, this is fine. // No EOR support! //if(sock) sock.emit('stream', IAC+DONT+TELOPT_EOR); // disable local echo! // use GMCP // send Hello immediately // we DONT accept anything else. So just reply all WILL by DONT // save incomplete telnet negotiation for later processing // Received GMCP message! // Server wants us to send TTYPE, we count up tty_neg_index until it's end // if there something left (or no IAC at all), append rest of buffer