ttelhndl.cpp
上传用户:tigerk9
上传日期:2020-03-10
资源大小:237k
文件大小:16k
源码类别:

Telnet客户端

开发平台:

Visual C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //Telnet Win32 : an ANSI telnet client.
  3. //Copyright (C) 1998  Paul Brannan
  4. //Copyright (C) 1998  I.Ioannou
  5. //Copyright (C) 1997  Brad Johnson
  6. //
  7. //This program is free software; you can redistribute it and/or
  8. //modify it under the terms of the GNU General Public License
  9. //as published by the Free Software Foundation; either version 2
  10. //of the License, or (at your option) any later version.
  11. //
  12. //This program is distributed in the hope that it will be useful,
  13. //but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. //GNU General Public License for more details.
  16. //
  17. //You should have received a copy of the GNU General Public License
  18. //along with this program; if not, write to the Free Software
  19. //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. //
  21. //I.Ioannou
  22. //roryt@hol.gr
  23. //
  24. ///////////////////////////////////////////////////////////////////////////
  25. ///////////////////////////////////////////////////////////////////////////////
  26. //
  27. // Module: ttelhndl.cpp
  28. //
  29. // Contents: Telnet Handler
  30. //
  31. // Product: telnet
  32. //
  33. // Revisions: August 30, 1998 Paul Brannan <pbranna@clemson.edu>
  34. //            June 15, 1998   pbranna@clemson.edu (Paul Brannan)
  35. //
  36. //            This is code originally from tnnet.cpp and ansiprsr.cpp
  37. //
  38. ///////////////////////////////////////////////////////////////////////////////
  39. #include <string.h>
  40. #include "ttelhndl.h"
  41. #include "telnet.h"
  42. #include "tnconfig.h"
  43. #include "tparams.h"
  44. int naws_string(char *buf, int width, int height);
  45. // This helps make the code more readable (Paul Brannan 1/1/99)
  46. #ifdef DEBUG_TELOPT
  47. #define TELOPT_PRINTD(x) printit(x);
  48. #define TELOPT_PRINTD2(x,n) {
  49. static char buf[20];
  50. printit(s);
  51. printit(" ");
  52. itoa(d, buf, 10);
  53. printit(buf);
  54. printit("n");
  55. }
  56. #else
  57. #define TELOPT_PRINTD(x) ;
  58. #define TELOPT_PRINTD2(x,n) ;
  59. #endif
  60. // A new print function for debugging (Paul Brannan 5/15/98)
  61. #ifdef DEBUG_TELOPT
  62. void TTelnetHandler::print_telopt(const char *s, int d) {
  63. static char buf[20];
  64. printit(s);
  65. printit(" ");
  66. itoa(d, buf, 10);
  67. printit(buf);
  68. printit("n");
  69. }
  70. #endif
  71. TTelnetHandler::TTelnetHandler(TNetwork &RefNetwork, TConsole &RefConsole,
  72.    TParser &RefParser):
  73. Network(RefNetwork), Console(RefConsole), Parser(RefParser) {
  74. init();
  75. // Paul Brannan 9/13/98
  76. dwBuffer = ini.get_buffer_size();
  77. szBuffer = new char [dwBuffer];
  78. Network.SetNawsFunc(NULL);
  79. }
  80. void TTelnetHandler::init() {
  81. iTermSet = 0;
  82. bInBinaryRx = 0;
  83. bInBinaryTx = 0;
  84. bInEchoTx = 0;
  85. bInEchoRx = 0;
  86. Network.set_local_echo(1);
  87. }
  88. TTelnetHandler::~TTelnetHandler() {
  89. delete[] szBuffer;
  90. }
  91. int TTelnetHandler::escapeIAC(char *buf, int length){
  92. // The size of buffer must be greater than 2 * length to ensure no memory
  93. // out of bounds errors.  The 0xff is escaped into 0xff 0xff.
  94. char * temp;
  95. temp = new char [length * 2];
  96. int current=0;
  97. for (int x=0; x < length; x++){
  98. if (buf[x] == (signed char)IAC)
  99. temp[current++]=(char)IAC;
  100. temp[current++]=buf[x];
  101. }
  102. memcpy( buf, temp, current);
  103. delete [] temp;
  104. return current;
  105. }
  106. // This lets us get rid of all the printf's (Paul Brannan 5/15/98)
  107. void TTelnetHandler::SendIAC(char c) {
  108. static char buf[2] = {IAC};
  109. buf[1] = c;
  110. Network.WriteString(buf, 2);
  111. }
  112. void TTelnetHandler::SendIAC(char c1, char c2) {
  113. static char buf[3] = {IAC};
  114. buf[1] = c1; buf[2] = c2;
  115. Network.WriteString(buf, 3);
  116. }
  117. void TTelnetHandler::SendIACParams(char c) {
  118. static char buf[2];
  119. buf[0] = c;
  120. static int length = escapeIAC(buf, 1);
  121. Network.WriteString(buf, length);
  122. }
  123. void TTelnetHandler::SendIACParams(char c1, char c2) {
  124. static char buf[4];
  125. buf[0] = c1; buf[1] = c2;
  126. static int length = escapeIAC(buf, 2);
  127. Network.WriteString(buf, length);
  128. }
  129. int naws_string(char *b, int width, int height) {
  130. int l = 0;
  131. unsigned char *buf = (unsigned char *)b;
  132. union {
  133. char szResponse[2];
  134. int n;
  135. };
  136. buf[l++] = IAC;
  137. buf[l++] = SB;
  138. buf[l++] = TELOPT_NAWS;
  139. n = width;
  140. buf[l] = szResponse[1];
  141. if(buf[l-1] == IAC) buf[l++] = IAC;
  142. buf[l++] = szResponse[0];
  143. if(buf[l-1] == IAC) buf[l++] = IAC;
  144. n = height;
  145. buf[l++] = szResponse[1];
  146. if(buf[l-1] == IAC) buf[l++] = IAC;
  147. buf[l++] = szResponse[0];
  148. if(buf[l-1] == IAC) buf[l++] = IAC;
  149. buf[l++] = IAC;
  150. buf[l++] = SE;
  151. return l;
  152. }
  153. //  Ioannou 29 May 1998 : Something strange happens with
  154. //  Borland compiler at this point when it passes the arguments
  155. //  to SendIACParams. It always sends 80 lines to the server !!!
  156. //  There seems to be a bug with optimization (the disassemble shows
  157. //  that it uses an address plus 0xa than the right one).
  158. //  This turns them off for this point.
  159. #ifdef __BORLANDC__
  160. #pragma -O-
  161. #endif
  162. // Removed old printf code that was commented out to clean this function
  163. // up a bit (Paul brannan 6/15/98)
  164. char* TTelnetHandler::ParseIAC(char* pszBuffer, char* pszBufferEnd)
  165. {
  166. // int n,l;
  167. // char szResponse[40];
  168. //  Ioannou 29 May 1998 : I prefer the union redefinitions
  169. //  than the typecasting (used with them from Pascal and Cobol :-) )
  170. //  FIX ME !!!! Shall we use the winsock routines instead ?
  171. union {
  172. char szResponse[2];
  173. int n;
  174. };
  175. // Added support for user-defined term name (Paul Brannan 5/13/98)
  176. #define LASTTERM 4
  177. const char *pszTerms[] =  {ini.get_term(), "ANSI","DEC-VT100","DEC-VT52","UNKNOWN"};
  178. if(!iTermSet && (pszTerms[0] == 0 || *pszTerms[0] == 0)) iTermSet++;
  179. if (pszBuffer + 2 < pszBufferEnd) {
  180. switch ((unsigned char)pszBuffer[1]) {
  181. ///////////////// DO ////////////////////
  182. case DO:
  183. {
  184. switch (pszBuffer[2]){
  185. case TELOPT_BINARY:
  186. TELOPT_PRINTD("RCVD DO TELOPT_BINARYn");
  187. if (!bInBinaryRx){
  188. SendIAC(WILL, TELOPT_BINARY);
  189. bInBinaryRx = 1;
  190. TELOPT_PRINTD("SENT WILL TELOPT_BINARYn");
  191. }
  192. break;
  193. case TELOPT_ECHO:
  194. // we shouldn't echo for the server! (Paul Brannan 5/30/98)
  195. TELOPT_PRINTD2("RCVD DO TELOPT_ECHO", pszBuffer[2]);
  196. SendIAC(WONT, TELOPT_ECHO);
  197. TELOPT_PRINTD("SENT WONT TELOPT_ECHOn");
  198. break;
  199. case TELOPT_TTYPE:
  200. TELOPT_PRINTD("RCVD DO TELOPT_TTYPEn");
  201. SendIAC(WILL, TELOPT_TTYPE);
  202. TELOPT_PRINTD("SENT WILL TELOPT_TTYPEn");
  203. break;
  204. case TELOPT_NAWS:
  205. TELOPT_PRINTD("RCVD DO TELOPT_NAWSn");
  206. SendIAC(WILL, TELOPT_NAWS);
  207. SendIAC(SB, TELOPT_NAWS);
  208. Network.SetNawsFunc(naws_string);
  209. n = Console.GetWidth();
  210. SendIACParams(szResponse[1],szResponse [0]);
  211. n = Console.GetHeight();
  212. SendIACParams(szResponse[1],szResponse[0]);
  213. SendIAC(SE);
  214. TELOPT_PRINTD("SENT WILL TELOPT_NAWSn");
  215. break;
  216. case TELOPT_XDISPLOC:
  217. TELOPT_PRINTD("RCVD DO TELOPT_XDISPLOCn");
  218. SendIAC(WILL, TELOPT_XDISPLOC);
  219. TELOPT_PRINTD("SENT WILL TELOPT_XDISPLOCn");
  220. printit("Retrieving IP...");
  221. break;
  222. default:
  223. TELOPT_PRINTD2("RCVD DO", pszBuffer[2]);
  224. SendIAC(WONT, pszBuffer[2]);
  225. TELOPT_PRINTD2("SENT WONT", pszBuffer[2]);
  226. break;
  227. }
  228. if (pszBuffer + 2 < pszBufferEnd)
  229. pszBuffer += 3;
  230. break;
  231. }
  232. ///////////////// WILL ////////////////////
  233. case WILL:
  234. {
  235. switch ((unsigned char)pszBuffer[2]){
  236. case TELOPT_BINARY:
  237. TELOPT_PRINTD("RCVD WILL TELOPT_BINARYn");
  238. if (!bInBinaryTx){
  239. SendIAC(DO, TELOPT_BINARY);
  240. bInBinaryTx = 1;
  241. TELOPT_PRINTD("SENT DO TELOPT_BINARYn");
  242. }
  243. break;
  244. case TELOPT_ECHO:
  245. TELOPT_PRINTD2("RCVD WILL TELOPT_ECHO", pszBuffer[2]);
  246. if(!bInEchoRx) {
  247. SendIAC(DO, TELOPT_ECHO);
  248. bInEchoRx = 1;
  249. Network.set_local_echo(0); // Paul Brannan 8/25/98
  250. if(iWillSGA) Network.set_line_mode(0);
  251. TELOPT_PRINTD2("SENT DO TELOPT_ECHO", pszBuffer[2]);
  252. if(Network.get_local_echo()) Network.set_line_mode(0);
  253. }
  254. break;
  255. // Suppress Go Ahead (Paul Brannan 12/31/98)
  256. case TELOPT_SGA:
  257. TELOPT_PRINTD("RCVD WILL TELOPT_SGAn");
  258. if(!iWillSGA) {
  259. SendIAC(DO, TELOPT_SGA);
  260. if(bInEchoRx) Network.set_line_mode(0);
  261. iWillSGA = 1;
  262. TELOPT_PRINTD("SENT DO TELOPT_SGAn");
  263. }
  264. break;
  265. ////added 1/28/97
  266. default:
  267. TELOPT_PRINTD2("RCVD WILL", pszBuffer[2]);
  268. SendIAC(DONT, pszBuffer[2]);
  269. TELOPT_PRINTD2("SENT DONT", pszBuffer[2]);
  270. break;
  271. ////
  272. }
  273. if (pszBuffer + 2 < pszBufferEnd)
  274. pszBuffer += 3;
  275. break;
  276. }
  277. ///////////////// WONT ////////////////////
  278. case WONT:
  279. {
  280. switch ((unsigned char)pszBuffer[2]){
  281. case TELOPT_ECHO:
  282. TELOPT_PRINTD("RCVD WONT TELOPT_ECHOn");
  283. if (bInEchoRx){
  284. SendIAC(DONT, TELOPT_ECHO);
  285. // bInBinaryRx = 0;
  286. bInEchoRx = 0; // Paul Brannan 8/25/98
  287. Network.set_local_echo(1);
  288. Network.set_line_mode(0);
  289. TELOPT_PRINTD("SENT DONT TELOPT_ECHOn");
  290. }
  291. break;
  292. // Suppress Go Ahead (Paul Brannan 12/31/98)
  293. case TELOPT_SGA:
  294. TELOPT_PRINTD("RCVD WONT TELOPT_SGAn");
  295. if(iWillSGA) {
  296. SendIAC(DONT, TELOPT_SGA);
  297. Network.set_line_mode(0);
  298. iWillSGA = 0;
  299. TELOPT_PRINTD("SENT DONT TELOPT_SGAn");
  300. }
  301. break;
  302. default:
  303. TELOPT_PRINTD2("RCVD WONT", pszBuffer[2]);
  304. break;
  305. }
  306. if (pszBuffer + 2 < pszBufferEnd)
  307. pszBuffer += 3;
  308. break;
  309. }
  310. ///////////////// DONT ////////////////////
  311. case DONT:
  312. {
  313. switch ((unsigned char)pszBuffer[2]){
  314. case TELOPT_ECHO:
  315. TELOPT_PRINTD("RCVD DONT TELOPT_ECHOn");
  316. if (bInEchoTx){
  317. SendIAC(WONT, TELOPT_ECHO);
  318. bInEchoTx = 0;
  319. TELOPT_PRINTD("SENT WONT TELOPT_ECHOn");
  320. }
  321. break;
  322. case TELOPT_NAWS:
  323. TELOPT_PRINTD("RCVD DONT TELOPT_NAWSn");
  324. SendIAC(WONT, TELOPT_NAWS);
  325. Network.SetNawsFunc(naws_string);
  326. TELOPT_PRINTD("SENT WONT TELOPT_NAWSn");
  327. break;
  328. default:
  329. TELOPT_PRINTD2("RCVD DONT", pszBuffer[2]);
  330. break;
  331. }
  332. if (pszBuffer + 2 < pszBufferEnd)
  333. pszBuffer += 3;
  334. break;
  335. }
  336. ///////////////// SB ////////////////////
  337. case SB:
  338. {
  339. switch ((unsigned char)pszBuffer[2]){
  340. case TELOPT_TTYPE:
  341. if (pszBuffer + 5 < pszBufferEnd) {
  342. TELOPT_PRINTD("RCVD SB TELOPT_TTYPEn");
  343. if (pszBuffer[3] == 1){
  344. TELOPT_PRINTD("SENT SB TT");
  345. TELOPT_PRINTD(pszTerms[iTermSet]);
  346. TELOPT_PRINTD("n");
  347. SendIAC(SB, TELOPT_TTYPE);
  348. SendIACParams(0);
  349. Network.WriteString(pszTerms[iTermSet], strlen(pszTerms[iTermSet]));
  350. SendIAC(SE);
  351. if (iTermSet < LASTTERM )
  352. iTermSet+=1;
  353. }
  354. if (pszBuffer + 5 < pszBufferEnd)
  355. pszBuffer += 6;
  356. }
  357. break;
  358. case TELOPT_XDISPLOC:
  359. if(pszBuffer + 5 < pszBufferEnd) {
  360. TELOPT_PRINTD("RCVD SB XDISPLOCn");
  361. SendIAC(SB, TELOPT_XDISPLOC);
  362. TELOPT_PRINTD("SENT SB XDISPLOC");
  363. SendIACParams(0);
  364. if(Network.GetLocalAddress()) Network.WriteString(Network.GetLocalAddress(),
  365. strlen(Network.GetLocalAddress()));
  366. TELOPT_PRINTD(Network.GetLocalAddress());
  367. TELOPT_PRINTD("n");
  368. SendIAC(SE);
  369. if (pszBuffer + 5 < pszBufferEnd)
  370. pszBuffer += 6;
  371. }
  372. break;
  373. default: break;
  374. }
  375. break;
  376. }
  377. default:
  378. pszBuffer += 2;
  379. break;
  380. }
  381. }
  382. return pszBuffer;
  383. }
  384. #ifdef __BORLANDC__
  385. // bring bug optimazations
  386. #pragma -O.
  387. #endif
  388. // This is the code from TANSIParser::ParseBuffer.  It parses out IACs, and
  389. // then calls TParser::ParseBuffer to do the terminal emulation.
  390. // (Paul Brannan 6/15/98)
  391. // Hopefully eliminating the unnecessary copying should speed things up a
  392. // little.  (Paul Brannan 6/28/98)
  393. char* TTelnetHandler::ParseBuffer(char* pszBuffer, char* pszBufferEnd){
  394. char *pszResult;
  395. char *pszHead = pszBuffer;
  396. if(Network.get_net_type() == TN_NETSOCKET) {
  397. while (pszBuffer < pszBufferEnd) {
  398. // if IAC then parse IAC
  399. if((unsigned char) *pszBuffer == IAC) {
  400. // check for escaped IAC
  401. if((pszBufferEnd >= pszBuffer + 1) &&
  402. (unsigned char)*(pszBuffer + 1) == IAC) {
  403. // we move data at the front of the buffer to the end so
  404. // that if we only have IACs we won't return pszBuffer
  405. // even though we did parse something.  Returning
  406. // pszBuffer is an error condition.
  407. memmove(pszHead + 1, pszHead, pszBuffer - pszHead);
  408. pszBuffer+=2;
  409. pszHead++;
  410. }
  411. // parse the IAC
  412. else {
  413. pszResult = ParseIAC(pszBuffer, pszBufferEnd);
  414. if(pszBuffer == pszResult) return pszBuffer;
  415. // see above regarding moving from front to end.
  416. memmove(pszHead + (pszResult - pszBuffer), pszHead,
  417. pszBuffer - pszHead);
  418. pszHead += (pszResult - pszBuffer);
  419. pszBuffer = pszResult;
  420. }
  421. }
  422. // else copy char over to ANSI buffer
  423. else {
  424. pszBuffer++;
  425. }
  426. }
  427. // Not a socket connection, so don't parse out IACs.
  428. // (Paul Brannan 3/19/99)
  429. } else {
  430. pszBuffer = pszBufferEnd;
  431. }
  432. return(Parser.ParseBuffer(pszHead, pszBuffer));
  433. }
  434. // telProcessNetwork calls the member function TTelnetHandler::Go, since
  435. // TTelnetHandler::Go is not a static function, and cannot be called with
  436. // CreateThread().  (Paul Brannan 6/15/98)
  437. DWORD telProcessNetwork(LPVOID pvParams) {
  438. TelThreadParams *pParams = (TelThreadParams *)pvParams;
  439. return pParams->TelHandler.Go(&pParams->p);
  440. }
  441. // This function is what used to be telProcessNetwork (Paul Brannan 6/15/98)
  442. DWORD TTelnetHandler::Go(LPVOID pvParams)
  443. {
  444. NetParams *pParams = (NetParams *)pvParams;
  445. // No longer a need to copy pParams-> socket and create an instance
  446. // of TANSIParser (Paul Brannan 6/15/98)
  447. Console.sync(); // Sync with the parser so the cursor is positioned
  448. Parser.Init(); // Reset the parser (Paul Brannan 9/19/98)
  449. init(); // Turn on local echo (Paul Brannan 9/19/98)
  450. *pParams->bNetFinished = 0;
  451. char* pszHead = szBuffer;
  452. char* pszTail = szBuffer;
  453. while (!*pParams->bNetFinish) {
  454. // Get data from Socket
  455. *pParams->bNetPaused = 1;  //Pause
  456. int Result = Network.ReadString(pszTail, (szBuffer + dwBuffer) - pszTail);
  457. // Speed up mouse by not going into loop (Paul Brannan 8/10/98)
  458. // while(*pParams->bNetPause && !*pParams->bNetFinish) *pParams->bNetPaused = 1;  //Pause
  459. if(WaitForSingleObject(pParams->hPause, 0) == WAIT_OBJECT_0)
  460. WaitForSingleObject(pParams->hUnPause, INFINITE);
  461. *pParams->bNetPaused = 0;  //UnPause
  462. if (Result <= 0 || Result > dwBuffer ){
  463. break;
  464. }
  465. pszTail += Result;
  466. // Process the buffer
  467. char* pszNewHead = pszHead;
  468. do {
  469. // Speed up mouse by not going into loop (Paul Brannan 8/10/98)
  470. if(WaitForSingleObject(pParams->hPause, 0) == WAIT_OBJECT_0) {
  471. *pParams->bNetPaused = 1;
  472. WaitForSingleObject(pParams->hUnPause, INFINITE);
  473. *pParams->bNetPaused = 0;
  474. }
  475. pszHead = pszNewHead;
  476. pszNewHead = ParseBuffer(pszHead, pszTail); // Parse buffer
  477. } while ((pszNewHead != pszHead) && (pszNewHead < pszTail) && !*pParams->bNetFinish);
  478. pszHead = pszNewHead;
  479. // When we reach the end of the buffer, move contents to the
  480. // beginning of the buffer to get free space at the end.
  481. if (pszTail == (szBuffer + dwBuffer)) {
  482. memmove(szBuffer, pszHead, pszTail - pszHead);
  483. pszTail = szBuffer + (pszTail - pszHead);
  484. pszHead = szBuffer;
  485. }
  486. }
  487. SetEvent(pParams->hExit);
  488. printm(0, FALSE, MSG_TERMBYREM);
  489. *pParams->bNetPaused = 1;  //Pause
  490. *pParams->bNetFinished = 1;
  491. return 0;
  492. }