Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/ttcomtester/teraterm/teraterm/telnet.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10521 - (show annotations) (download) (as text)
Fri Jan 20 16:03:38 2023 UTC (13 months, 2 weeks ago) by zmatsuo
File MIME type: text/x-csrc
File size: 18657 byte(s)
add communication test tool
1 /*
2 * Copyright (C) 1994-1998 T. Teranishi
3 * (C) 2007- TeraTerm Project
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /* TERATERM.EXE, TELNET routines */
31
32 #include "teraterm.h"
33 #include "tttypes.h"
34 #include <stdio.h>
35 #include <string.h>
36 #include "ttcommon.h"
37 #include "ttwinman.h"
38 #include "commlib.h"
39 #include <time.h>
40 #include <process.h>
41
42 #include "telnet.h"
43 #include "asprintf.h"
44 #include "tt_res.h"
45
46 int TelStatus;
47
48 enum OptStatus {No, Yes, WantNo, WantYes};
49 enum OptQue {Empty, Opposite};
50
51 typedef struct {
52 BOOL Accept;
53 enum OptStatus Status;
54 enum OptQue Que;
55 } TelOpt;
56 typedef TelOpt *PTelOpt;
57
58 typedef struct {
59 TelOpt MyOpt[MaxTelOpt+1];
60 TelOpt HisOpt[MaxTelOpt+1];
61 BYTE SubOptBuff[51];
62 int SubOptCount;
63 BOOL SubOptIAC;
64 BOOL ChangeWinSize;
65 POINT WinSize;
66 HANDLE LogFile;
67 } TelRec;
68 typedef TelRec *PTelRec;
69
70 static TelRec tr;
71
72 static HANDLE keepalive_thread = INVALID_HANDLE_VALUE;
73 static HWND keepalive_dialog = NULL;
74 static int nop_interval = 0;
75
76 static void TelSendNOP();
77 static void TelStopKeepAliveThread();
78
79 /**
80 * @retval ���������o�C�g��
81 */
82 static UINT win16_lwrite(HANDLE hFile, const char*buf, UINT length)
83 {
84 DWORD NumberOfBytesWritten;
85 BOOL result = WriteFile(hFile, buf, length, &NumberOfBytesWritten, NULL);
86 if (result == FALSE) {
87 return 0;
88 }
89 return NumberOfBytesWritten;
90 }
91
92 static void DefaultTelRec(void)
93 {
94 int i;
95
96 for (i=0 ; i <= MaxTelOpt ; i++) {
97 tr.MyOpt[i].Accept = FALSE;
98 tr.MyOpt[i].Status = No;
99 tr.MyOpt[i].Que = Empty;
100 tr.HisOpt[i].Accept = FALSE;
101 tr.HisOpt[i].Status = No;
102 tr.HisOpt[i].Que = Empty;
103 }
104
105 tr.SubOptCount = 0;
106 tr.SubOptIAC = FALSE;
107 tr.ChangeWinSize = FALSE;
108 }
109
110 void InitTelnet(void)
111 {
112 TelStatus = TelIdle;
113
114 DefaultTelRec();
115 tr.MyOpt[BINARY].Accept = TRUE;
116 tr.HisOpt[BINARY].Accept = TRUE;
117 tr.MyOpt[SGA].Accept = TRUE;
118 tr.HisOpt[SGA].Accept = TRUE;
119 tr.HisOpt[ECHO].Accept = TRUE;
120 tr.MyOpt[TERMTYPE].Accept = TRUE;
121 tr.MyOpt[TERMSPEED].Accept = TRUE;
122 tr.MyOpt[NAWS].Accept = TRUE;
123 tr.HisOpt[NAWS].Accept = TRUE;
124 tr.WinSize.x = ts.TerminalWidth;
125 tr.WinSize.y = ts.TerminalHeight;
126
127 if ((ts.LogFlag & LOG_TEL) != 0) {
128 wchar_t *full_path = NULL;
129 awcscats(&full_path, ts.LogDirW, L"\\", L"TELNET.LOG", NULL);
130 tr.LogFile = CreateFileW(full_path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
131 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
132 free(full_path);
133 } else
134 tr.LogFile = 0;
135 }
136
137 void EndTelnet(void)
138 {
139 if (tr.LogFile) {
140 CloseHandle(tr.LogFile);
141 tr.LogFile = 0;
142 }
143
144 TelStopKeepAliveThread();
145 }
146
147 static void TelWriteLog1(BYTE b)
148 {
149 BYTE Temp[3];
150 BYTE Ch;
151
152 Temp[0] = 0x20;
153 Ch = b / 16;
154 if (Ch <= 9)
155 Ch = Ch + 0x30;
156 else
157 Ch = Ch + 0x37;
158 Temp[1] = Ch;
159
160 Ch = b & 15;
161 if (Ch <= 9)
162 Ch = Ch + 0x30;
163 else
164 Ch = Ch + 0x37;
165 Temp[2] = Ch;
166 win16_lwrite(tr.LogFile, Temp, 3);
167 }
168
169 static void TelWriteLog(PCHAR Buf, int C)
170 {
171 int i;
172
173 win16_lwrite(tr.LogFile, "\015\012>", 3);
174 for (i = 0 ; i<= C-1 ; i++)
175 TelWriteLog1(Buf[i]);
176 }
177
178 static void SendBack(BYTE a, BYTE b)
179 {
180 BYTE Str3[3];
181
182 Str3[0] = IAC;
183 Str3[1] = a;
184 Str3[2] = b;
185 CommRawOut(&cv, Str3, 3);
186 if (tr.LogFile)
187 TelWriteLog(Str3, 3);
188 }
189
190 static void SendWinSize(void)
191 {
192 int i;
193 BYTE TmpBuff[21];
194
195 i = 0;
196
197 TmpBuff[i++] = IAC;
198 TmpBuff[i++] = SB;
199 TmpBuff[i++] = NAWS;
200
201 if (HIBYTE(tr.WinSize.x) == IAC) {
202 TmpBuff[i++] = IAC;
203 }
204 TmpBuff[i++] = HIBYTE(tr.WinSize.x);
205
206 if (LOBYTE(tr.WinSize.x) == IAC) {
207 TmpBuff[i++] = IAC;
208 }
209 TmpBuff[i++] = LOBYTE(tr.WinSize.x);
210
211 if (HIBYTE(tr.WinSize.y) == IAC) {
212 TmpBuff[i++] = IAC;
213 }
214 TmpBuff[i++] = HIBYTE(tr.WinSize.y);
215
216 if (LOBYTE(tr.WinSize.y) == IAC) {
217 TmpBuff[i++] = IAC;
218 }
219 TmpBuff[i++] = LOBYTE(tr.WinSize.y);
220
221 TmpBuff[i++] = IAC;
222 TmpBuff[i++] = SE;
223
224 CommRawOut(&cv, TmpBuff, i);
225 if (tr.LogFile)
226 TelWriteLog(TmpBuff, i);
227 }
228
229 static void ParseTelIAC(BYTE b)
230 {
231 switch (b) {
232 case SE: break;
233 case NOP:
234 case DM:
235 case BREAK:
236 case IP:
237 case AO:
238 case AYT:
239 case EC:
240 case EL:
241 case GOAHEAD:
242 TelStatus = TelIdle;
243 break;
244 case SB:
245 TelStatus = TelSB;
246 tr.SubOptCount = 0;
247 break;
248 case WILLTEL:
249 TelStatus = TelWill;
250 break;
251 case WONTTEL:
252 TelStatus = TelWont;
253 break;
254 case DOTEL:
255 TelStatus = TelDo;
256 break;
257 case DONTTEL:
258 TelStatus = TelDont;
259 break;
260 case IAC:
261 TelStatus = TelIdle;
262 break;
263 default:
264 TelStatus = TelIdle;
265 }
266 }
267
268 static void ParseTelSB(BYTE b)
269 {
270 BYTE TmpStr[51];
271 int i;
272
273 if (tr.SubOptIAC) {
274 tr.SubOptIAC = FALSE;
275 switch (b) {
276 case SE:
277 if (tr.SubOptCount <= 1) {
278 // �p�����[�^������ Sub Option ���������v����������������������
279 tr.SubOptCount = 0;
280 TelStatus = TelIdle;
281 return ;
282 }
283
284 switch (tr.SubOptBuff[0]) {
285 case TERMTYPE:
286 if ((tr.MyOpt[TERMTYPE].Status == Yes) && (tr.SubOptBuff[1] == 1)) {
287 _snprintf_s(TmpStr, sizeof(TmpStr), _TRUNCATE, "%c%c%c%c%s%c%c",
288 IAC, SB, TERMTYPE, 0, ts.TermType, IAC, SE);
289 // 4 �o�C�g���� 0 �����������A������������������
290 i = strlen(TmpStr + 4) + 4;
291 CommRawOut(&cv, TmpStr, i);
292
293 if (tr.LogFile)
294 TelWriteLog(TmpStr, i);
295 }
296 break;
297
298 case NAWS:
299 if ( /* (tr.HisOpt[NAWS].Status == Yes) && */ (tr.SubOptCount >= 5)) {
300 tr.WinSize.x = tr.SubOptBuff[1]*256 + tr.SubOptBuff[2];
301 tr.WinSize.y = tr.SubOptBuff[3]*256 + tr.SubOptBuff[4];
302 tr.ChangeWinSize = TRUE;
303 }
304 break;
305
306 case TERMSPEED:
307 if ((tr.MyOpt[TERMSPEED].Status == Yes) && (tr.SubOptBuff[1] == 1)) {
308 _snprintf_s(TmpStr, sizeof(TmpStr), _TRUNCATE,
309 "%c%c%c%c%d,%d%c%c", IAC, SB, TERMSPEED, 0,
310 ts.TerminalInputSpeed, ts.TerminalOutputSpeed, IAC, SE);
311 // 4 �o�C�g���� 0 �����������A������������������
312 i = strlen(TmpStr + 4) + 4;
313 CommRawOut(&cv, TmpStr, i);
314
315 if (tr.LogFile)
316 TelWriteLog(TmpStr, i);
317 }
318 break;
319 }
320
321 tr.SubOptCount = 0;
322 TelStatus = TelIdle;
323 return ;
324
325 case IAC:
326 /*
327 * �A������ IAC ���l�� 255 ���f�[�^����������
328 * ������������������ SubOptBuff ���f�[�^�����������������A
329 * �������������s������
330 */
331 break;
332
333 default:
334 /*
335 * �T�u�I�v�V������������ TELNET �R�}���h������������������
336 * ���������������B�����������f�[�^�������������������B
337 */
338 if (tr.SubOptCount >= sizeof(tr.SubOptBuff)-1) {
339 tr.SubOptCount = 0;
340 TelStatus = TelIdle;
341 return;
342 }
343 else {
344 tr.SubOptBuff[tr.SubOptCount] = IAC;
345 tr.SubOptCount++;
346 }
347 }
348 }
349 else if (b==IAC) {
350 tr.SubOptIAC = TRUE;
351 return;
352 }
353
354 if (tr.SubOptCount >= sizeof(tr.SubOptBuff)-1) {
355 tr.SubOptCount = 0;
356 tr.SubOptIAC = FALSE;
357 TelStatus = TelIdle;
358 }
359 else {
360 tr.SubOptBuff[tr.SubOptCount] = b;
361 tr.SubOptCount++;
362 }
363 }
364
365 static void ParseTelWill(BYTE b)
366 {
367 if (b <= MaxTelOpt) {
368 switch (tr.HisOpt[b].Status) {
369 case No:
370 if (tr.HisOpt[b].Accept) {
371 SendBack(DOTEL, b);
372 tr.HisOpt[b].Status = Yes;
373 }
374 else {
375 SendBack(DONTTEL, b);
376 }
377 break;
378
379 case WantNo:
380 switch (tr.HisOpt[b].Que) {
381 case Empty:
382 tr.HisOpt[b].Status = No;
383 break;
384 case Opposite:
385 tr.HisOpt[b].Status = Yes;
386 break;
387 }
388 break;
389
390 case WantYes:
391 switch (tr.HisOpt[b].Que) {
392 case Empty:
393 tr.HisOpt[b].Status = Yes;
394 break;
395 case Opposite:
396 tr.HisOpt[b].Status = WantNo;
397 tr.HisOpt[b].Que = Empty;
398 SendBack(DONTTEL, b);
399 break;
400 }
401 break;
402
403 default:
404 break;
405 }
406 }
407 else {
408 SendBack(DONTTEL, b);
409 }
410
411 switch (b) {
412 case ECHO:
413 if (ts.TelEcho) {
414 switch (tr.HisOpt[ECHO].Status) {
415 case Yes:
416 ts.LocalEcho = 0;
417 break;
418 case No:
419 ts.LocalEcho = 1;
420 break;
421 default:
422 break;
423 }
424 }
425 if (tr.HisOpt[ECHO].Status == Yes) {
426 cv.TelLineMode = FALSE;
427 }
428 break;
429
430 case SGA:
431 if (tr.HisOpt[SGA].Status == Yes) {
432 cv.TelLineMode = FALSE;
433 }
434 break;
435
436 case BINARY:
437 switch (tr.HisOpt[BINARY].Status) {
438 case Yes:
439 cv.TelBinRecv = TRUE;
440 break;
441 case No:
442 cv.TelBinRecv = FALSE;
443 break;
444 default:
445 break;
446 }
447 break;
448
449 default:
450 break;
451 }
452 TelStatus = TelIdle;
453 }
454
455 static void ParseTelWont(BYTE b)
456 {
457 if (b <= MaxTelOpt) {
458 switch (tr.HisOpt[b].Status) {
459 case Yes:
460 tr.HisOpt[b].Status = No;
461 SendBack(DONTTEL, b);
462 break;
463
464 case WantNo:
465 switch (tr.HisOpt[b].Que) {
466 case Empty:
467 tr.HisOpt[b].Status = No;
468 break;
469 case Opposite:
470 tr.HisOpt[b].Status = WantYes;
471 tr.HisOpt[b].Que = Empty;
472 SendBack(DOTEL, b);
473 break;
474 }
475 break;
476
477 case WantYes:
478 switch (tr.HisOpt[b].Que) {
479 case Empty:
480 tr.HisOpt[b].Status = No;
481 break;
482 case Opposite:
483 tr.HisOpt[b].Status = No;
484 tr.HisOpt[b].Que = Empty;
485 break;
486 }
487 break;
488
489 default:
490 break;
491 }
492 }
493 else {
494 SendBack(DONTTEL, b);
495 }
496
497 switch (b) {
498 case ECHO:
499 if (ts.TelEcho) {
500 switch (tr.HisOpt[ECHO].Status) {
501 case Yes:
502 ts.LocalEcho = 0;
503 break;
504 case No:
505 ts.LocalEcho = 1;
506 break;
507 default:
508 break;
509 }
510 }
511 if (tr.HisOpt[ECHO].Status == Yes) {
512 cv.TelLineMode = FALSE;
513 }
514 break;
515
516 case BINARY:
517 switch (tr.HisOpt[BINARY].Status) {
518 case Yes:
519 cv.TelBinRecv = TRUE;
520 break;
521 case No:
522 cv.TelBinRecv = FALSE;
523 break;
524 default:
525 break;
526 }
527 break;
528
529 default:
530 break;
531 }
532 TelStatus = TelIdle;
533 }
534
535 static void ParseTelDo(BYTE b)
536 {
537 if (b <= MaxTelOpt) {
538 switch (tr.MyOpt[b].Status) {
539 case No:
540 if (tr.MyOpt[b].Accept) {
541 tr.MyOpt[b].Status = Yes;
542 SendBack(WILLTEL, b);
543 }
544 else {
545 SendBack(WONTTEL, b);
546 }
547 break;
548
549 case WantNo:
550 switch (tr.MyOpt[b].Que) {
551 case Empty:
552 tr.MyOpt[b].Status = No;
553 break;
554 case Opposite:
555 tr.MyOpt[b].Status = Yes;
556 break;
557 }
558 break;
559
560 case WantYes:
561 switch (tr.MyOpt[b].Que) {
562 case Empty:
563 tr.MyOpt[b].Status = Yes;
564 break;
565 case Opposite:
566 tr.MyOpt[b].Status = WantNo;
567 tr.MyOpt[b].Que = Empty;
568 SendBack(WONTTEL, b);
569 break;
570 }
571 break;
572
573 default:
574 break;
575 }
576 }
577 else {
578 SendBack(WONTTEL, b);
579 }
580
581 switch (b) {
582 case BINARY:
583 switch (tr.MyOpt[BINARY].Status) {
584 case Yes:
585 cv.TelBinSend = TRUE;
586 break;
587 case No:
588 cv.TelBinSend = FALSE;
589 break;
590 default:
591 break;
592 }
593 break;
594
595 case NAWS:
596 if (tr.MyOpt[NAWS].Status==Yes)
597 SendWinSize();
598 break;
599
600 case SGA:
601 if (tr.MyOpt[SGA].Status==Yes)
602 cv.TelLineMode = FALSE;
603 break;
604
605 default:
606 break;
607 }
608 TelStatus = TelIdle;
609 }
610
611 static void ParseTelDont(BYTE b)
612 {
613 if (b <= MaxTelOpt) {
614 switch (tr.MyOpt[b].Status) {
615 case Yes:
616 tr.MyOpt[b].Status = No;
617 SendBack(WONTTEL, b);
618 break;
619
620 case WantNo:
621 switch (tr.MyOpt[b].Que) {
622 case Empty:
623 tr.MyOpt[b].Status = No;
624 break;
625 case Opposite:
626 tr.MyOpt[b].Status = WantYes;
627 tr.MyOpt[b].Que = Empty;
628 SendBack(WILLTEL, b);
629 break;
630 }
631 break;
632
633 case WantYes:
634 switch (tr.MyOpt[b].Que) {
635 case Empty:
636 tr.MyOpt[b].Status = No;
637 break;
638 case Opposite:
639 tr.MyOpt[b].Status = No;
640 tr.MyOpt[b].Que = Empty;
641 break;
642 }
643 break;
644
645 default:
646 break;
647 }
648 }
649 else {
650 SendBack(WONTTEL, b);
651 }
652
653 switch (b) {
654 case BINARY:
655 switch (tr.MyOpt[BINARY].Status) {
656 case Yes:
657 cv.TelBinSend = TRUE;
658 break;
659 case No:
660 cv.TelBinSend = FALSE;
661 break;
662 default:
663 break;
664 }
665 break;
666
667 default:
668 break;
669 }
670 TelStatus = TelIdle;
671 }
672
673 void ParseTel(BOOL *Size, int *nx, int *ny)
674 {
675 BYTE b;
676 int c;
677
678 c = CommReadRawByte(&cv, &b);
679
680 while ((c>0) && (cv.TelMode)) {
681 if (tr.LogFile) {
682 if (TelStatus==TelIAC) {
683 win16_lwrite(tr.LogFile, "\015\012<", 3);
684 TelWriteLog1(0xff);
685 }
686 TelWriteLog1(b);
687 }
688
689 tr.ChangeWinSize = FALSE;
690
691 switch (TelStatus) {
692 case TelIAC: ParseTelIAC(b); break;
693 case TelSB: ParseTelSB(b); break;
694 case TelWill: ParseTelWill(b); break;
695 case TelWont: ParseTelWont(b); break;
696 case TelDo: ParseTelDo(b); break;
697 case TelDont: ParseTelDont(b); break;
698 case TelNop: TelStatus = TelIdle; break;
699 }
700 if (TelStatus == TelIdle) cv.TelMode = FALSE;
701
702 if (cv.TelMode) c = CommReadRawByte(&cv, &b);
703 }
704
705 *Size = tr.ChangeWinSize;
706 *nx = tr.WinSize.x;
707 *ny = tr.WinSize.y;
708 }
709
710 void TelEnableHisOpt(BYTE b)
711 {
712 if (b <= MaxTelOpt) {
713 switch (tr.HisOpt[b].Status) {
714 case No:
715 tr.HisOpt[b].Status = WantYes;
716 SendBack(DOTEL, b);
717 break;
718
719 case WantNo:
720 if (tr.HisOpt[b].Que==Empty)
721 tr.HisOpt[b].Que = Opposite;
722 break;
723
724 case WantYes:
725 if (tr.HisOpt[b].Que==Opposite)
726 tr.HisOpt[b].Que = Empty;
727 break;
728
729 default:
730 break;
731 }
732 }
733 }
734
735 static void TelDisableHisOpt(BYTE b)
736 {
737 if (b <= MaxTelOpt) {
738 switch (tr.HisOpt[b].Status) {
739 case Yes:
740 tr.HisOpt[b].Status = WantNo;
741 SendBack(DONTTEL, b);
742 break;
743
744 case WantNo:
745 if (tr.HisOpt[b].Que==Opposite)
746 tr.HisOpt[b].Que = Empty;
747 break;
748
749 case WantYes:
750 if (tr.HisOpt[b].Que==Empty)
751 tr.HisOpt[b].Que = Opposite;
752 break;
753
754 default:
755 break;
756 }
757 }
758 }
759
760 void TelEnableMyOpt(BYTE b)
761 {
762 if (b <= MaxTelOpt) {
763 switch (tr.MyOpt[b].Status) {
764 case No:
765 tr.MyOpt[b].Status = WantYes;
766 SendBack(WILLTEL, b);
767 break;
768
769 case WantNo:
770 if (tr.MyOpt[b].Que==Empty)
771 tr.MyOpt[b].Que = Opposite;
772 break;
773
774 case WantYes:
775 if (tr.MyOpt[b].Que==Opposite)
776 tr.MyOpt[b].Que = Empty;
777 break;
778
779 default:
780 break;
781 }
782 }
783 }
784
785 static void TelDisableMyOpt(BYTE b)
786 {
787 if (b <= MaxTelOpt) {
788 switch (tr.MyOpt[b].Status) {
789 case Yes:
790 tr.MyOpt[b].Status = WantNo;
791 SendBack(WONTTEL, b);
792 break;
793
794 case WantNo:
795 if (tr.MyOpt[b].Que==Opposite)
796 tr.MyOpt[b].Que = Empty;
797 break;
798
799 case WantYes:
800 if (tr.MyOpt[b].Que==Empty)
801 tr.MyOpt[b].Que = Opposite;
802 break;
803
804 default:
805 break;
806 }
807 }
808 }
809
810 void TelInformWinSize(int nx, int ny)
811 {
812 if ((tr.MyOpt[NAWS].Status==Yes) &&
813 (nx != tr.WinSize.x || ny != tr.WinSize.y))
814 {
815 tr.WinSize.x = nx;
816 tr.WinSize.y = ny;
817 SendWinSize();
818 }
819 }
820
821 void TelSendAYT(void)
822 {
823 BYTE Str[2];
824
825 Str[0] = IAC;
826 Str[1] = AYT;
827 CommRawOut(&cv, Str, 2);
828 CommSend(&cv);
829 if (tr.LogFile)
830 TelWriteLog(Str, 2);
831 }
832
833 void TelSendBreak(void)
834 {
835 BYTE Str[2];
836
837 Str[0] = IAC;
838 Str[1] = BREAK;
839 CommRawOut(&cv, Str, 2);
840 CommSend(&cv);
841 if (tr.LogFile)
842 TelWriteLog(Str, 2);
843 }
844
845 void TelChangeEcho(void)
846 {
847 if (ts.LocalEcho==0)
848 TelEnableHisOpt(ECHO);
849 else
850 TelDisableHisOpt(ECHO);
851 }
852
853 static void TelSendNOP(void)
854 {
855 BYTE Str[2];
856
857 Str[0] = IAC;
858 Str[1] = NOP;
859 CommRawOut(&cv, Str, 2);
860 CommSend(&cv);
861 if (tr.LogFile)
862 TelWriteLog(Str, 2);
863 }
864
865 #define WM_SEND_HEARTBEAT (WM_USER + 1)
866
867 static INT_PTR CALLBACK telnet_heartbeat_dlg_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
868 {
869 switch (msg) {
870 case WM_INITDIALOG:
871 return FALSE;
872
873 case WM_SEND_HEARTBEAT:
874 TelSendNOP();
875 return TRUE;
876 break;
877
878 case WM_COMMAND:
879 switch (LOWORD(wp)) {
880 case IDOK:
881 return TRUE;
882 case IDCANCEL:
883 EndDialog(hWnd, 0);
884 return TRUE;
885 default:
886 return FALSE;
887 }
888 break;
889
890 case WM_CLOSE:
891 // close�{�^���������������� window ���������������������B
892 return TRUE;
893
894 case WM_DESTROY:
895 return TRUE;
896
897 default:
898 return FALSE;
899 }
900 return TRUE;
901 }
902
903
904 static unsigned _stdcall TelKeepAliveThread(void *dummy)
905 {
906 static int instance = 0;
907
908 if (instance > 0)
909 return 0;
910 instance++;
911
912 while (cv.Open && nop_interval > 0) {
913 if (time(NULL) >= cv.LastSendTime + nop_interval) {
914 SendMessage(keepalive_dialog, WM_SEND_HEARTBEAT, 0, 0);
915 }
916
917 Sleep(100);
918 }
919 instance--;
920 return 0;
921 }
922
923 void TelStartKeepAliveThread(void)
924 {
925 unsigned tid;
926
927 if (ts.TelKeepAliveInterval > 0) {
928 nop_interval = ts.TelKeepAliveInterval;
929
930 // ���[�h���X�_�C�A���O������ (2007.12.26 yutaka)
931 keepalive_dialog = CreateDialog(hInst, MAKEINTRESOURCE(IDD_BROADCAST_DIALOG),
932 HVTWin, telnet_heartbeat_dlg_proc);
933
934 keepalive_thread = (HANDLE)_beginthreadex(NULL, 0, TelKeepAliveThread, NULL, 0, &tid);
935 if (keepalive_thread == 0) {
936 keepalive_thread = INVALID_HANDLE_VALUE;
937 nop_interval = 0;
938 }
939 }
940 }
941
942 static void TelStopKeepAliveThread(void)
943 {
944 if (keepalive_thread != INVALID_HANDLE_VALUE) {
945 nop_interval = 0;
946 WaitForSingleObject(keepalive_thread, INFINITE);
947 CloseHandle(keepalive_thread);
948 keepalive_thread = INVALID_HANDLE_VALUE;
949
950 DestroyWindow(keepalive_dialog);
951 }
952 }
953
954 void TelUpdateKeepAliveInterval(void)
955 {
956 if (cv.Open && cv.TelFlag && ts.TCPPort==ts.TelPort) {
957 if (ts.TelKeepAliveInterval > 0 && keepalive_thread == INVALID_HANDLE_VALUE)
958 TelStartKeepAliveThread();
959 else if (ts.TelKeepAliveInterval == 0 && keepalive_thread != INVALID_HANDLE_VALUE)
960 TelStopKeepAliveThread();
961 else
962 nop_interval = ts.TelKeepAliveInterval;
963 }
964 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26