ProtocolRx.cpp
上传用户:yuanwufei9
上传日期:2007-01-09
资源大小:21k
文件大小:13k
源码类别:

Telnet客户端

开发平台:

Visual C++

  1. // ProtocolRx.cpp: implementation of the CProtocolRx class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "Telnet.h"
  6. #include "ProtocolRx.h"
  7. #ifdef _DEBUG
  8. #undef THIS_FILE
  9. static char THIS_FILE[]=__FILE__;
  10. #define new DEBUG_NEW
  11. #endif
  12. //////////////////////////////////////////////////////////////////////
  13. // Construction/Destruction
  14. //////////////////////////////////////////////////////////////////////
  15. extern HANDLE stdin1;
  16. extern HANDLE stdout1;
  17. extern HANDLE stderr1;
  18. void nvt(SOCKET server,unsigned char data);
  19. enum _ansi_state
  20. {
  21.   as_normal,
  22.   as_esc,
  23.   as_esc1
  24. };
  25. static sa = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  26. char codebuf[256];
  27. unsigned char codeptr;
  28. #define NUM_CODEC 6
  29. typedef void (*LPCODEPROC)(char*);
  30. void ansi_set_screen_attribute(char* buffer);
  31. void ansi_set_position(char* buffer);
  32. void ansi_erase_screen(char* buffer);
  33. void ansi_move_up(char* buffer);
  34. void ansi(SOCKET server,unsigned char data);
  35. void ansi_erase_line(char* buffer);
  36. void ddww_error(SOCKET server,_verb verb,_option option);
  37. void ddww_echo(SOCKET server,_verb verb, _option option);
  38. void ddww_supp(SOCKET server,_verb verb,_option option); //Suppress GA
  39. void ddww_term(SOCKET server,_verb verb,_option option); //Subnegotiate terminal type
  40. void sbproc_term(SOCKET server,unsigned char data);
  41. struct 
  42. {
  43.   unsigned char cmd;
  44.   LPCODEPROC proc;
  45. } codec[NUM_CODEC] = {
  46.   {'m',ansi_set_screen_attribute},
  47.   {'H',ansi_set_position},
  48.   {'K',ansi_erase_line},
  49.   {'J',ansi_erase_screen},
  50.   {'A',ansi_move_up},
  51.   {0,0}
  52. };
  53. CProtocolRx::CProtocolRx()
  54. {
  55. }
  56. CProtocolRx::~CProtocolRx()
  57. {
  58. }
  59. #define NUL     0
  60. #define BEL     7
  61. #define BS      8
  62. #define HT      9
  63. #define LF     10
  64. #define VT     11
  65. #define FF     12
  66. #define CR     13
  67. #define SE    240
  68. #define NOP   241
  69. #define DM    242
  70. #define BRK   243
  71. #define IP    244
  72. #define AO    245
  73. #define AYT   246
  74. #define EC    247
  75. #define EL    248
  76. #define GA    249
  77. #define SB    250
  78. #define WILL  251
  79. #define WONT  252
  80. #define DO    253
  81. #define DONT  254
  82. #define IAC   255
  83. int option_error(_verb,_option,int,SOCKET);
  84. typedef void(*LPOPTIONPROC)(SOCKET,_verb,_option);
  85. typedef void(*LPDATAPROC)(SOCKET,unsigned char data);
  86. inline void yesreply(SOCKET server, _verb verb,_option option)
  87. {
  88.   unsigned char buf[3];
  89.   buf[0] = IAC;
  90.   buf[1] = (verb==verb_do)?WILL:(verb==verb_dont)?WONT:(verb==verb_will)?DO:DONT;
  91.   buf[2] = (unsigned char)option;
  92.   send(server,(char*)buf,3,0);
  93. }
  94. inline void noreply(SOCKET server, _verb verb,_option option)
  95. {
  96.   unsigned char buf[3];
  97.   buf[0] = IAC;
  98.   buf[1] = (verb==verb_do)?WONT:(verb==verb_dont)?WILL:(verb==verb_will)?DONT:DO;
  99.   buf[2] = (unsigned char)option;
  100.   send(server,(char*)buf,3,0);
  101. }
  102. inline void askfor(SOCKET server, _verb verb,_option option)
  103. {
  104.   unsigned char buf[3];
  105.   buf[0] = IAC;
  106.   buf[1] = (unsigned char)verb;
  107.   buf[2] = (unsigned char)option;
  108.   send(server,(char*)buf,3,0);
  109. }
  110. void ddww_error(SOCKET server,_verb verb,_option option)
  111. {
  112. #ifdef _DEBUG
  113.   char tmp[256];
  114.   wsprintf(tmp,"Unknown Option Code: %s, %in",(verb==verb_do)?"DO":(verb==verb_dont)?"DON'T":(verb==verb_will)?"WILL":"WONT",(int)option);
  115.   OutputDebugString(tmp);
  116. #endif
  117.   switch(verb)
  118.   {
  119.   case verb_will: 
  120.     noreply(server,verb,option);
  121.     break;
  122.   case verb_wont:
  123.     return;
  124.   case verb_do:
  125.     noreply(server,verb,option);
  126.     break;
  127.   case verb_dont:
  128.     return;
  129.   }
  130. }
  131. void ddww_echo(SOCKET server,_verb verb, _option option)
  132. {
  133.   DWORD mode;
  134.   GetConsoleMode(stdin1,&mode); // ENABLE_ECHO_INPUT
  135.   
  136.   int set = !(mode & ENABLE_ECHO_INPUT);
  137.   switch(verb)
  138.   {
  139.   case verb_will: // server wants to echo stuff
  140.     if(set) return; //don't confirm - already set.
  141.     SetConsoleMode(stdin1,mode & (~ENABLE_ECHO_INPUT));
  142.     break;
  143.   case verb_wont: // server don't want to echo
  144.     if(!set) return; //don't confirm - already unset.
  145.     SetConsoleMode(stdin1,mode | ENABLE_ECHO_INPUT);
  146.     break;
  147.   case verb_do:   // server wants me to loopback
  148.     noreply(server,verb,option);
  149.     return;
  150.   case verb_dont: // server doesn't want me to echo
  151.     break;        // don't bother to reply - I don't
  152.   }
  153.   yesreply(server,verb,option);
  154. }
  155. void ddww_supp(SOCKET server,_verb verb,_option option) //Suppress GA
  156. {
  157.   DWORD mode;
  158.   GetConsoleMode(stdin1,&mode); // ENABLE_LINE_INPUT
  159.   
  160.   int set = !(mode & ENABLE_LINE_INPUT);
  161.   switch(verb)
  162.   {
  163.   case verb_will: // server wants to suppress GA's
  164.     if(set) break; //don't confirm - already set.
  165.     SetConsoleMode(stdin1,mode & (~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT)));
  166.     askfor(server,verb_do,TOPT_SUPP);
  167.     askfor(server,verb_will,TOPT_SUPP);
  168.     askfor(server,verb_do,TOPT_ECHO);
  169.     break;
  170.   case verb_wont: // server wants to send GA's 
  171.     if(!set) break; //don't confirm - already unset.
  172.     SetConsoleMode(stdin1,mode | ENABLE_LINE_INPUT);
  173.     askfor(server,verb_dont,TOPT_SUPP);
  174.     askfor(server,verb_wont,TOPT_SUPP);
  175.     break;
  176.   case verb_do:   // server wants me to suppress GA's
  177.     if(set) break;
  178.     askfor(server,verb_do,TOPT_SUPP);
  179.     break;
  180.   case verb_dont: // server wants me to send GA's
  181.     if(!set) break;
  182.     askfor(server,verb_dont,TOPT_SUPP);
  183.     break;
  184.   }
  185. }
  186. ///////////////////////////////////////////////////////////////////////////////
  187. // Option TERMINAL-TYPE
  188. void ddww_term(SOCKET server,_verb verb,_option option) //Subnegotiate terminal type
  189. {
  190.   switch(verb)
  191.   {
  192.   case verb_will:
  193.     noreply(server,verb,option); // I don't want terminal info
  194.     break;
  195.   case verb_wont:
  196.     //dat be cool - its not going to send. no need to confirm
  197.     break;
  198.   case verb_do:
  199.     yesreply(server,verb,option); //I'll send it when asked
  200.     break;
  201.   case verb_dont://Ok - I won't
  202.     break;
  203.   }
  204. }
  205. // TERMINAL TYPE subnegotation
  206. enum
  207. {
  208.   SB_TERM_IS = 0,
  209.   SB_TERM_SEND = 1
  210. };
  211. #define NUM_TERMINALS 2
  212. struct
  213. {
  214.   char* name;
  215.   LPDATAPROC termproc;
  216.   //pre requsites.
  217. } terminal[NUM_TERMINALS] = {
  218.   { "NVT", nvt }, 
  219.   { "ANSI", ansi }
  220. };
  221. int term_index = 0;
  222. void sbproc_term(SOCKET server,unsigned char data)
  223. {
  224.   if(data == SB_TERM_SEND)
  225.   {
  226.     if(term_index == NUM_TERMINALS)
  227.       term_index = 0;
  228.     else
  229.       term_index++;
  230.     char buf[16]; //pls limit 
  231.     buf[0] = IAC;
  232.     buf[1] = SB;
  233.     buf[2] = TOPT_TERM;
  234.     buf[3] = SB_TERM_IS;
  235.     lstrcpy(&buf[4],terminal[(term_index==NUM_TERMINALS)?(NUM_TERMINALS-1):term_index].name);
  236.     int nlen = lstrlen(&buf[4]);
  237.     buf[4+nlen] = IAC;
  238.     buf[5+nlen] = SE;
  239.     send(server,buf,4+nlen+2,0);
  240.   }
  241. }
  242. ///////////////////////////////////////////////////////////////////////////////
  243. struct
  244. {
  245.   _option option;
  246.   LPOPTIONPROC OptionProc;
  247.   LPDATAPROC DataProc;
  248. }  ol[] = {
  249.   {TOPT_ECHO,   ddww_echo,  NULL},
  250.   {TOPT_SUPP,   ddww_supp,  NULL},
  251.   {TOPT_TERM,   ddww_term,  sbproc_term},
  252.   {TOPT_ERROR,  ddww_error, NULL}
  253. };
  254. void CProtocolRx::TelentProtcol(SOCKET server,unsigned char code)
  255. {
  256. //These vars are the finite state
  257.   static int state = state_data;
  258.   static _verb verb = verb_sb;
  259.   static LPDATAPROC DataProc = terminal[(term_index==NUM_TERMINALS)?(NUM_TERMINALS-1):term_index].termproc;
  260. //Decide what to do (state based)
  261.   switch(state)
  262.   {
  263.   case state_data:
  264.     switch(code)
  265.     {
  266.     case IAC: state = state_code; break;
  267.     default: DataProc(server,code);
  268.     }
  269.     break;
  270.   case state_code:
  271.     state = state_data;
  272.     switch(code)
  273.     {
  274.     // State transition back to data
  275.     case IAC: 
  276.       DataProc(server,code);
  277.       break;
  278.     // Code state transitions back to data
  279.     case SE:
  280.       DataProc = terminal[(term_index==NUM_TERMINALS)?(NUM_TERMINALS-1):term_index].termproc;
  281.       break;
  282.     case NOP:
  283.       break;
  284.     case DM:
  285.       break;
  286.     case BRK:
  287.       break;
  288.     case IP:
  289.       break;
  290.     case AO:
  291.       break;
  292.     case AYT:
  293.       break;
  294.     case EC:
  295.       break;
  296.     case EL:
  297.       break;
  298.     case GA:
  299.       break;
  300.     // Transitions to option state
  301.     case SB:
  302.       verb = verb_sb;
  303.       state = state_option;
  304.       break;
  305.     case WILL:
  306.       verb = verb_will;
  307.       state = state_option;
  308.       break;
  309.     case WONT:
  310.       verb = verb_wont;
  311.       state = state_option;
  312.       break;
  313.     case DO:
  314.       verb = verb_do;
  315.       state = state_option;
  316.       break;
  317.     case DONT:
  318.       verb = verb_dont;
  319.       state = state_option;
  320.       break;
  321.     }
  322.     break;
  323.   case state_option:
  324.     state = state_data;
  325.     //Find the option entry
  326.     for(
  327.       int i = 0;
  328.       ol[i].option != TOPT_ERROR && ol[i].option != code;
  329.       i++);
  330.     //Do some verb specific stuff
  331.     if(verb == verb_sb)
  332.       DataProc = ol[i].DataProc;
  333.     else
  334.       ol[i].OptionProc(server,verb,(_option)code);
  335.     break;
  336.   }
  337. }
  338. void nvt(SOCKET server,unsigned char data)
  339. {
  340.   DWORD z;
  341.   switch(data)
  342.   {
  343.   case 0:  //eat null codes.
  344.     break;
  345.   default: //Send all else to the console.
  346.     WriteConsole(stdout1,&data,1,&z,NULL);
  347.     break;
  348.   }
  349. }
  350. void ansi_set_screen_attribute(char* buffer)
  351. {
  352.   while(*buffer)
  353.   {
  354.     switch(*buffer++)
  355.     {
  356.     case '0': //Normal
  357.       sa = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
  358.       break;
  359.     case '1': //Hign Intensity
  360.       sa |= FOREGROUND_INTENSITY;
  361.       break;
  362.     case '4': //Underscore
  363.       break;
  364.     case '5': //Blink.
  365.       sa |= BACKGROUND_INTENSITY;
  366.       break;
  367.     case '7':
  368.       sa = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
  369.       break;
  370.     case '8':
  371.       sa = 0;
  372.       break;
  373.     case '3':
  374.       sa = sa & (BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY) |
  375.         (*buffer & 1)?FOREGROUND_RED:0 |
  376.         (*buffer & 2)?FOREGROUND_GREEN:0 |
  377.         (*buffer & 4)?FOREGROUND_BLUE:0;
  378.       if(*buffer)
  379.         buffer++;
  380.       break;
  381.     case '6':
  382.       sa = sa & (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY) |
  383.         (*buffer & 1)?BACKGROUND_RED:0 |
  384.         (*buffer & 2)?BACKGROUND_GREEN:0 |
  385.         (*buffer & 4)?BACKGROUND_BLUE:0;
  386.       if(*buffer)
  387.         buffer++;
  388.       break;
  389.     }
  390.     if(*buffer && *buffer == ';')
  391.       buffer++;
  392.   }
  393.   SetConsoleTextAttribute(stdout1,sa);
  394. }
  395. void ansi_erase_line(char* buffer)
  396. {
  397.   int act = 0;
  398.   while(*buffer)
  399.   {
  400.     act = (*buffer++) - '0';
  401.   }
  402.   CONSOLE_SCREEN_BUFFER_INFO csbi;
  403.   GetConsoleScreenBufferInfo(stdout1,&csbi);
  404.   COORD pos;
  405.   DWORD n;
  406.   switch(act)
  407.   {
  408.   case 0: //erase to end of line
  409.     pos.X = csbi.dwCursorPosition.X;
  410.     pos.Y = csbi.dwCursorPosition.Y;
  411.     n = csbi.dwSize.X - csbi.dwCursorPosition.X;
  412.     break;
  413.   case 1: //erase from beginning
  414.     pos.X = 0;
  415.     pos.Y = csbi.dwCursorPosition.Y;
  416.     n = csbi.dwCursorPosition.X;
  417.     break;
  418.   case 2: // erase whole line
  419.     pos.X = 0;
  420.     pos.Y = csbi.dwCursorPosition.Y;
  421.     n = csbi.dwSize.X;
  422.     break;
  423.   }
  424.   DWORD w;
  425.   FillConsoleOutputCharacter(stdout1,' ',n,pos,&w);
  426. }
  427. void ansi_set_position(char* buffer)
  428. {
  429.   COORD pos = {0,0};
  430.   // Grab line
  431.   while(*buffer && *buffer != ';')
  432.     pos.Y = pos.Y*10 + *buffer++ - '0';
  433.   if(*buffer)
  434.     buffer++;
  435.   // Grab y
  436.   while(*buffer && *buffer != ';')
  437.     pos.X = pos.X*10 + *buffer++ - '0';
  438.   (pos.X)?pos.X--:0;
  439.   (pos.Y)?pos.Y--:0;
  440.   SetConsoleCursorPosition(stdout1,pos);
  441.  
  442. }
  443. void ansi_erase_screen(char* buffer)
  444. {
  445.   int act = 0;
  446.   while(*buffer)
  447.   {
  448.     act = (*buffer++) - '0';
  449.   }
  450.   CONSOLE_SCREEN_BUFFER_INFO csbi;
  451.   GetConsoleScreenBufferInfo(stdout1,&csbi);
  452.   COORD pos;
  453.   DWORD n;
  454.   switch(act)
  455.   {
  456.   case 0:
  457.     pos.X = csbi.dwCursorPosition.X;
  458.     pos.Y = csbi.dwCursorPosition.Y;
  459.     n = csbi.dwSize.X*csbi.dwSize.Y;
  460.     break;
  461.   case 2:
  462.     pos.X = 0;
  463.     pos.Y = 0;
  464.     n = csbi.dwSize.X*csbi.dwSize.Y;
  465.     break;
  466.   }
  467.   DWORD w;
  468.   FillConsoleOutputCharacter(stdout1,' ',n,pos,&w);
  469.   SetConsoleCursorPosition(stdout1,pos);
  470. }
  471. void ansi_move_up(char* buffer)
  472. {
  473.   int cnt = *buffer?0:1;
  474.   while(*buffer)
  475.   {
  476.     cnt = cnt*10 + (*buffer++) - '0';
  477.   }
  478.   COORD pos;
  479.   CONSOLE_SCREEN_BUFFER_INFO csbi;
  480.   GetConsoleScreenBufferInfo(stdout1,&csbi);
  481.   pos.X = csbi.dwCursorPosition.X;
  482.   pos.Y = ((csbi.dwCursorPosition.Y-cnt)>=0)?(csbi.dwCursorPosition.Y-cnt):0;
  483.   SetConsoleCursorPosition(stdout1,pos);
  484. }
  485. void ansi(SOCKET server,unsigned char data)
  486. {
  487.   static _ansi_state state = as_normal;
  488.   DWORD z;
  489.   switch( state)
  490.   {
  491.   case as_normal:
  492.     switch(data)
  493.     {
  494.     case 0:  //eat null codes.
  495.       break;
  496.     case 27: //ANSI esc.
  497.       state = as_esc;
  498.       break;
  499.     default: //Send all else to the console.
  500.       WriteConsole(stdout1,&data,1,&z,NULL);
  501.       break;
  502.     }
  503.     break;
  504.   case as_esc:
  505.     state = as_esc1;
  506.     codeptr=0;
  507.     codebuf[codeptr] = 0;
  508.     break;
  509.   case as_esc1:
  510.     if(data > 64)
  511.     {
  512.       codebuf[codeptr] = 0;
  513.       for(int i=0; codec[i].cmd && codec[i].cmd != data; i++);
  514.       if(codec[i].proc)
  515.         codec[i].proc(codebuf);
  516. #ifdef _DEBUG
  517.       else
  518.       {
  519.         char buf[256];
  520.         wsprintf(buf,"Unknown Ansi code:'%c' (%s)n",data,codebuf);
  521.         OutputDebugString(buf);
  522.       }
  523. #endif
  524.       state = as_normal;
  525.     }
  526.     else
  527.       codebuf[codeptr++] = data;
  528.     break;
  529.   }
  530. }