Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/teraterm/teraterm/telnet.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6960 - (hide annotations) (download) (as text)
Tue Oct 24 17:53:34 2017 UTC (6 years, 5 months ago) by doda
File MIME type: text/x-csrc
File size: 17665 byte(s)
TELNET TERMINAL SPEED OPTION (RFC 1079) に対応 #37599

FreeBSD の telnetd に -D report オプションを指定した状態で、TERMINAL
SPEED OPTION を受け取っているのを確認。ただし TTY のスピードは変わらず。

設定は SSH と共通で TerminalSpeed を使用する。
Transmit / Receive は送信側 (Tera Term) から見た方向なので、

・Transmit = SSH TTY Mode ISPEED
・Receive  = SSH TTY Mode OSPEED

としている。
1 doda 6806 /*
2     * Copyright (C) 1994-1998 T. Teranishi
3     * (C) 2007-2017 TeraTerm Project
4     * All rights reserved.
5     *
6 doda 6841 * Redistribution and use in source and binary forms, with or without
7     * modification, are permitted provided that the following conditions
8     * are met:
9 doda 6806 *
10 doda 6841 * 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 doda 6806 *
18 doda 6841 * 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 doda 6806 */
29 maya 3227
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 "tt_res.h"
44    
45     int TelStatus;
46    
47     enum OptStatus {No, Yes, WantNo, WantYes};
48     enum OptQue {Empty, Opposite};
49    
50     typedef struct {
51     BOOL Accept;
52     enum OptStatus Status;
53     enum OptQue Que;
54     } TelOpt;
55     typedef TelOpt *PTelOpt;
56    
57     typedef struct {
58     TelOpt MyOpt[MaxTelOpt+1];
59     TelOpt HisOpt[MaxTelOpt+1];
60     BYTE SubOptBuff[51];
61     int SubOptCount;
62     BOOL SubOptIAC;
63     BOOL ChangeWinSize;
64     POINT WinSize;
65     int LogFile;
66     } TelRec;
67     typedef TelRec *PTelRec;
68    
69     static TelRec tr;
70    
71     static HANDLE keepalive_thread = (HANDLE)-1L;
72 doda 6435 static HWND keepalive_dialog = NULL;
73 maya 3227 int nop_interval = 0;
74    
75     void DefaultTelRec()
76     {
77     int i;
78    
79     for (i=0 ; i <= MaxTelOpt ; i++)
80     {
81     tr.MyOpt[i].Accept = FALSE;
82     tr.MyOpt[i].Status = No;
83     tr.MyOpt[i].Que = Empty;
84     tr.HisOpt[i].Accept = FALSE;
85     tr.HisOpt[i].Status = No;
86     tr.HisOpt[i].Que = Empty;
87     }
88    
89     tr.SubOptCount = 0;
90     tr.SubOptIAC = FALSE;
91     tr.ChangeWinSize = FALSE;
92     }
93    
94     void InitTelnet()
95     {
96     TelStatus = TelIdle;
97    
98     DefaultTelRec();
99     tr.MyOpt[BINARY].Accept = TRUE;
100     tr.HisOpt[BINARY].Accept = TRUE;
101     tr.MyOpt[SGA].Accept = TRUE;
102     tr.HisOpt[SGA].Accept = TRUE;
103     tr.HisOpt[ECHO].Accept = TRUE;
104     tr.MyOpt[TERMTYPE].Accept = TRUE;
105 doda 6960 tr.MyOpt[TERMSPEED].Accept = TRUE;
106 maya 3227 tr.MyOpt[NAWS].Accept = TRUE;
107     tr.HisOpt[NAWS].Accept = TRUE;
108     tr.WinSize.x = ts.TerminalWidth;
109     tr.WinSize.y = ts.TerminalHeight;
110    
111     if ((ts.LogFlag & LOG_TEL) != 0)
112     tr.LogFile = _lcreat("TELNET.LOG",0);
113     else
114     tr.LogFile = 0;
115     }
116    
117     void EndTelnet()
118     {
119     if (tr.LogFile != 0)
120     {
121     tr.LogFile = 0;
122     _lclose(tr.LogFile);
123     }
124    
125     TelStopKeepAliveThread();
126     }
127    
128     void TelWriteLog1(BYTE b)
129     {
130     BYTE Temp[3];
131     BYTE Ch;
132    
133     Temp[0] = 0x20;
134     Ch = b / 16;
135     if (Ch <= 9)
136     Ch = Ch + 0x30;
137     else
138     Ch = Ch + 0x37;
139     Temp[1] = Ch;
140    
141     Ch = b & 15;
142     if (Ch <= 9)
143     Ch = Ch + 0x30;
144     else
145     Ch = Ch + 0x37;
146     Temp[2] = Ch;
147     _lwrite(tr.LogFile,Temp,3);
148     }
149    
150     void TelWriteLog(PCHAR Buf, int C)
151     {
152     int i;
153    
154     _lwrite(tr.LogFile,"\015\012>",3);
155     for (i = 0 ; i<= C-1 ; i++)
156     TelWriteLog1(Buf[i]);
157     }
158    
159     void SendBack(BYTE a, BYTE b)
160     {
161     BYTE Str3[3];
162    
163     Str3[0] = IAC;
164     Str3[1] = a;
165     Str3[2] = b;
166     CommRawOut(&cv,Str3,3);
167     if (tr.LogFile!=0)
168     TelWriteLog(Str3,3);
169     }
170    
171     void SendWinSize()
172     {
173     int i;
174     BYTE TmpBuff[21];
175    
176     i = 0;
177    
178     TmpBuff[i] = IAC;
179     i++;
180     TmpBuff[i] = SB;
181     i++;
182     TmpBuff[i] = NAWS;
183     i++;
184     TmpBuff[i] = HIBYTE(tr.WinSize.x);
185     i++;
186     /* if (LOBYTE(tr.WinSize.x) == IAC)
187     {
188     tr.SendBackBuff[i] = IAC;
189     i++;
190     } */
191     TmpBuff[i] = LOBYTE(tr.WinSize.x);
192     i++;
193     TmpBuff[i] = HIBYTE(tr.WinSize.y);
194     i++;
195     /* if (LOBYTE(tr.WinSize.y) == IAC)
196     {
197     tr.SendBackBuff[i] = IAC;
198     i++;
199     } */
200     TmpBuff[i] = LOBYTE(tr.WinSize.y);
201     i++;
202     TmpBuff[i] = IAC;
203     i++;
204     TmpBuff[i]= SE;
205     i++;
206    
207     CommRawOut(&cv,TmpBuff,i);
208     if (tr.LogFile!=0)
209     TelWriteLog(TmpBuff,i);
210     }
211    
212     void ParseTelIAC(BYTE b)
213     {
214     switch (b) {
215     case SE: break;
216     case NOP:
217     case DM:
218     case BREAK:
219     case IP:
220     case AO:
221     case AYT:
222     case EC:
223     case EL:
224     case GOAHEAD:
225     TelStatus = TelIdle;
226     break;
227     case SB:
228     TelStatus = TelSB;
229     tr.SubOptCount = 0;
230     break;
231     case WILLTEL:
232     TelStatus = TelWill;
233     break;
234     case WONTTEL:
235     TelStatus = TelWont;
236     break;
237     case DOTEL:
238     TelStatus = TelDo;
239     break;
240     case DONTTEL:
241     TelStatus = TelDont;
242     break;
243     case IAC:
244     TelStatus = TelIdle;
245     break;
246     default:
247     TelStatus = TelIdle;
248     }
249     }
250    
251     void ParseTelSB(BYTE b)
252     {
253 doda 6959 BYTE TmpStr[51];
254     int i;
255 maya 3227
256 doda 6959 if (tr.SubOptIAC) {
257     tr.SubOptIAC = FALSE;
258     switch (b) {
259     case SE:
260     if ((tr.MyOpt[TERMTYPE].Status == Yes) &&
261     (tr.SubOptCount >= 2) &&
262     (tr.SubOptBuff[0] == TERMTYPE) &&
263     (tr.SubOptBuff[1] == 1))
264     {
265     _snprintf_s(TmpStr, sizeof(TmpStr), _TRUNCATE, "%c%c%c%c%s%c%c",
266     IAC, SB, TERMTYPE, 0, ts.TermType, IAC, SE);
267     // 4 �o�C�g���� 0 �����������A������������������
268     i = strlen(TmpStr + 4) + 4;
269     CommRawOut(&cv,TmpStr,i);
270 maya 3227
271 doda 6959 if (tr.LogFile!=0)
272     TelWriteLog(TmpStr,i);
273     }
274     else if ( /* (tr.HisOpt[NAWS].Status == Yes) && */
275     (tr.SubOptCount >= 5) &&
276     (tr.SubOptBuff[0] == NAWS))
277     {
278     tr.WinSize.x = tr.SubOptBuff[1]*256+ tr.SubOptBuff[2];
279     tr.WinSize.y = tr.SubOptBuff[3]*256+ tr.SubOptBuff[4];
280     tr.ChangeWinSize = TRUE;
281     }
282 doda 6960 else if ((tr.MyOpt[TERMSPEED].Status == Yes) &&
283     (tr.SubOptCount >= 2) &&
284     (tr.SubOptBuff[0] == TERMSPEED) &&
285     (tr.SubOptBuff[1] == 1))
286     {
287     _snprintf_s(TmpStr, sizeof(TmpStr),
288     _TRUNCATE,"%c%c%c%c%d,%d%c%c",
289     IAC, SB, TERMSPEED, 0,
290     ts.TerminalInputSpeed,
291     ts.TerminalOutputSpeed,
292     IAC,SE);
293     // 4 �o�C�g���� 0 �����������A������������������
294     i = strlen(TmpStr + 4) + 4;
295     CommRawOut(&cv, TmpStr, i);
296    
297     if (tr.LogFile)
298     TelWriteLog(TmpStr, i);
299     }
300 doda 6959 tr.SubOptCount = 0;
301     TelStatus = TelIdle;
302     return ;
303     /* case IAC: braek; */
304     default:
305     if (tr.SubOptCount >= sizeof(tr.SubOptBuff)-1) {
306     tr.SubOptCount = 0;
307     TelStatus = TelIdle;
308     return;
309     }
310     else {
311     tr.SubOptBuff[tr.SubOptCount] = IAC;
312     tr.SubOptCount++;
313     if (b==IAC) {
314     tr.SubOptIAC = TRUE;
315     return;
316     }
317     }
318     }
319 maya 3227 }
320 doda 6959 else if (b==IAC) {
321     tr.SubOptIAC = TRUE;
322     return;
323 maya 3227 }
324 doda 6959
325     if (tr.SubOptCount >= sizeof(tr.SubOptBuff)-1) {
326     tr.SubOptCount = 0;
327     tr.SubOptIAC = FALSE;
328     TelStatus = TelIdle;
329 maya 3227 }
330     else {
331 doda 6959 tr.SubOptBuff[tr.SubOptCount] = b;
332     tr.SubOptCount++;
333 maya 3227 }
334     }
335    
336     void ParseTelWill(BYTE b)
337     {
338     if (b <= MaxTelOpt)
339     {
340     switch (tr.HisOpt[b].Status) {
341     case No:
342     if (tr.HisOpt[b].Accept)
343     {
344     SendBack(DOTEL,b);
345     tr.HisOpt[b].Status = Yes;
346     }
347     else
348     SendBack(DONTTEL,b);
349     break;
350 doda 6435
351 maya 3227 case WantNo:
352     switch (tr.HisOpt[b].Que) {
353     case Empty:
354     tr.HisOpt[b].Status = No;
355     break;
356     case Opposite:
357     tr.HisOpt[b].Status = Yes;
358     break;
359     }
360     break;
361    
362     case WantYes:
363     switch (tr.HisOpt[b].Que) {
364     case Empty:
365     tr.HisOpt[b].Status = Yes;
366     break;
367     case Opposite:
368     tr.HisOpt[b].Status = WantNo;
369     tr.HisOpt[b].Que = Empty;
370     SendBack(DONTTEL,b);
371     break;
372     }
373     break;
374     }
375     }
376     else
377     SendBack(DONTTEL,b);
378    
379     switch (b) {
380     case ECHO:
381     if (ts.TelEcho>0)
382     switch (tr.HisOpt[ECHO].Status) {
383     case Yes:
384     ts.LocalEcho = 0;
385     break;
386     case No:
387     ts.LocalEcho = 1;
388     break;
389     }
390 doda 3531 if (tr.HisOpt[ECHO].Status == Yes) {
391     cv.TelLineMode = FALSE;
392     }
393 maya 3227 break;
394 doda 3530 case SGA:
395     if (tr.HisOpt[SGA].Status == Yes) {
396     cv.TelLineMode = FALSE;
397     }
398     break;
399 maya 3227 case BINARY:
400     switch (tr.HisOpt[BINARY].Status) {
401     case Yes:
402     cv.TelBinRecv = TRUE;
403     break;
404     case No:
405     cv.TelBinRecv = FALSE;
406     break;
407     }
408     break;
409     }
410     TelStatus = TelIdle;
411     }
412    
413     void ParseTelWont(BYTE b)
414     {
415     if (b <= MaxTelOpt)
416     {
417     switch (tr.HisOpt[b].Status) {
418     case Yes:
419     tr.HisOpt[b].Status = No;
420     SendBack(DONTTEL,b);
421     break;
422    
423     case WantNo:
424     switch (tr.HisOpt[b].Que) {
425     case Empty:
426     tr.HisOpt[b].Status = No;
427     break;
428     case Opposite:
429     tr.HisOpt[b].Status = WantYes;
430     tr.HisOpt[b].Que = Empty;
431     SendBack(DOTEL,b);
432     break;
433     }
434     break;
435    
436     case WantYes:
437     switch (tr.HisOpt[b].Que) {
438     case Empty:
439     tr.HisOpt[b].Status = No;
440     break;
441     case Opposite:
442     tr.HisOpt[b].Status = No;
443     tr.HisOpt[b].Que = Empty;
444     break;
445     }
446     break;
447     }
448     }
449     else
450     SendBack(DONTTEL,b);
451    
452     switch (b) {
453     case ECHO:
454     if (ts.TelEcho>0)
455     switch (tr.HisOpt[ECHO].Status) {
456     case Yes:
457     ts.LocalEcho = 0;
458     break;
459     case No:
460     ts.LocalEcho = 1;
461     break;
462     }
463     break;
464 doda 3531 if (tr.HisOpt[ECHO].Status == Yes) {
465     cv.TelLineMode = FALSE;
466     }
467 maya 3227 case BINARY:
468     switch (tr.HisOpt[BINARY].Status) {
469     case Yes:
470     cv.TelBinRecv = TRUE;
471     break;
472     case No:
473     cv.TelBinRecv = FALSE;
474     break;
475     }
476     break;
477     }
478     TelStatus = TelIdle;
479     }
480    
481     void ParseTelDo(BYTE b)
482     {
483     if (b <= MaxTelOpt)
484     {
485     switch (tr.MyOpt[b].Status) {
486     case No:
487     if (tr.MyOpt[b].Accept)
488     {
489     tr.MyOpt[b].Status = Yes;
490     SendBack(WILLTEL,b);
491     }
492     else
493     SendBack(WONTTEL,b);
494     break;
495    
496     case WantNo:
497     switch (tr.MyOpt[b].Que) {
498     case Empty:
499     tr.MyOpt[b].Status = No;
500     break;
501     case Opposite:
502     tr.MyOpt[b].Status = Yes;
503     break;
504     }
505     break;
506    
507     case WantYes:
508     switch (tr.MyOpt[b].Que) {
509     case Empty:
510     tr.MyOpt[b].Status = Yes;
511     break;
512     case Opposite:
513     tr.MyOpt[b].Status = WantNo;
514     tr.MyOpt[b].Que = Empty;
515     SendBack(WONTTEL,b);
516     break;
517     }
518     break;
519     }
520     }
521     else
522     SendBack(WONTTEL,b);
523    
524     switch (b) {
525     case BINARY:
526     switch (tr.MyOpt[BINARY].Status) {
527     case Yes:
528     cv.TelBinSend = TRUE;
529     break;
530     case No:
531     cv.TelBinSend = FALSE;
532     break;
533     }
534     break;
535     case NAWS:
536     if (tr.MyOpt[NAWS].Status==Yes)
537     SendWinSize();
538     break;
539 doda 3494 case SGA:
540     if (tr.MyOpt[SGA].Status==Yes)
541     cv.TelLineMode = FALSE;
542     break;
543 maya 3227 }
544     TelStatus = TelIdle;
545     }
546    
547     void ParseTelDont(BYTE b)
548     {
549     if (b <= MaxTelOpt)
550     {
551     switch (tr.MyOpt[b].Status) {
552     case Yes:
553     tr.MyOpt[b].Status = No;
554     SendBack(WONTTEL,b);
555     break;
556    
557     case WantNo:
558     switch (tr.MyOpt[b].Que) {
559     case Empty:
560     tr.MyOpt[b].Status = No;
561     break;
562     case Opposite:
563     tr.MyOpt[b].Status = WantYes;
564     tr.MyOpt[b].Que = Empty;
565     SendBack(WILLTEL,b);
566     break;
567     }
568     break;
569    
570     case WantYes:
571     switch (tr.MyOpt[b].Que) {
572     case Empty:
573     tr.MyOpt[b].Status = No;
574     break;
575     case Opposite:
576     tr.MyOpt[b].Status = No;
577     tr.MyOpt[b].Que = Empty;
578     break;
579     }
580     break;
581     }
582     }
583     else
584     SendBack(WONTTEL,b);
585    
586     switch (b) {
587     case BINARY:
588     switch (tr.MyOpt[BINARY].Status) {
589     case Yes:
590     cv.TelBinSend = TRUE;
591     break;
592     case No:
593     cv.TelBinSend = FALSE;
594     break;
595     }
596     break;
597     }
598     TelStatus = TelIdle;
599     }
600    
601     void ParseTel(BOOL *Size, int *nx, int *ny)
602     {
603     BYTE b;
604     int c;
605    
606     c = CommReadRawByte(&cv,&b);
607    
608     while ((c>0) && (cv.TelMode))
609     {
610     if (tr.LogFile!=0)
611     {
612     if (TelStatus==TelIAC)
613     {
614     _lwrite(tr.LogFile,"\015\012<",3);
615     TelWriteLog1(0xff);
616     }
617     TelWriteLog1(b);
618     }
619    
620     tr.ChangeWinSize = FALSE;
621    
622     switch (TelStatus) {
623     case TelIAC: ParseTelIAC(b); break;
624     case TelSB: ParseTelSB(b); break;
625     case TelWill: ParseTelWill(b); break;
626     case TelWont: ParseTelWont(b); break;
627     case TelDo: ParseTelDo(b); break;
628     case TelDont: ParseTelDont(b); break;
629     case TelNop: TelStatus = TelIdle; break;
630     }
631     if (TelStatus == TelIdle) cv.TelMode = FALSE;
632    
633     if (cv.TelMode) c = CommReadRawByte(&cv,&b);
634     }
635    
636     *Size = tr.ChangeWinSize;
637     *nx = tr.WinSize.x;
638     *ny = tr.WinSize.x;
639     }
640    
641     void TelEnableHisOpt(BYTE b)
642     {
643     if (b <= MaxTelOpt)
644     {
645     switch (tr.HisOpt[b].Status) {
646     case No:
647     tr.HisOpt[b].Status = WantYes;
648     SendBack(DOTEL,b);
649     break;
650    
651     case WantNo:
652     if (tr.HisOpt[b].Que==Empty)
653     tr.HisOpt[b].Que = Opposite;
654     break;
655    
656     case WantYes:
657     if (tr.HisOpt[b].Que==Opposite)
658     tr.HisOpt[b].Que = Empty;
659     break;
660     }
661     }
662     }
663    
664     void TelDisableHisOpt(BYTE b)
665     {
666     if (b <= MaxTelOpt)
667     {
668     switch (tr.HisOpt[b].Status) {
669     case Yes:
670     tr.HisOpt[b].Status = WantNo;
671     SendBack(DONTTEL,b);
672     break;
673    
674     case WantNo:
675     if (tr.HisOpt[b].Que==Opposite)
676     tr.HisOpt[b].Que = Empty;
677     break;
678    
679     case WantYes:
680     if (tr.HisOpt[b].Que==Empty)
681     tr.HisOpt[b].Que = Opposite;
682     break;
683     }
684     }
685     }
686    
687     void TelEnableMyOpt(BYTE b)
688     {
689     if (b <= MaxTelOpt)
690     {
691     switch (tr.MyOpt[b].Status) {
692     case No:
693     tr.MyOpt[b].Status = WantYes;
694     SendBack(WILLTEL,b);
695     break;
696    
697     case WantNo:
698     if (tr.MyOpt[b].Que==Empty)
699     tr.MyOpt[b].Que = Opposite;
700     break;
701    
702     case WantYes:
703     if (tr.MyOpt[b].Que==Opposite)
704     tr.MyOpt[b].Que = Empty;
705     break;
706     }
707     }
708     }
709    
710     void TelDisableMyOpt(BYTE b)
711     {
712     if (b <= MaxTelOpt)
713     {
714     switch (tr.MyOpt[b].Status) {
715     case Yes:
716     tr.MyOpt[b].Status = WantNo;
717     SendBack(WONTTEL,b);
718     break;
719    
720     case WantNo:
721     if (tr.MyOpt[b].Que==Opposite)
722     tr.MyOpt[b].Que = Empty;
723     break;
724    
725     case WantYes:
726     if (tr.MyOpt[b].Que==Empty)
727     tr.MyOpt[b].Que = Opposite;
728     break;
729     }
730     }
731     }
732    
733     void TelInformWinSize(int nx, int ny)
734     {
735     if ((tr.MyOpt[NAWS].Status==Yes) &&
736     ((nx!=tr.WinSize.x) ||
737     (ny!=tr.WinSize.y)))
738     {
739     tr.WinSize.x = nx;
740     tr.WinSize.y = ny;
741     SendWinSize();
742     }
743     }
744    
745     void TelSendAYT()
746     {
747     BYTE Str[2];
748    
749     Str[0] = IAC;
750     Str[1] = AYT;
751     CommRawOut(&cv,Str,2);
752     CommSend(&cv);
753     if (tr.LogFile!=0)
754     TelWriteLog(Str,2);
755     }
756    
757     void TelSendBreak()
758     {
759     BYTE Str[2];
760    
761     Str[0] = IAC;
762     Str[1] = BREAK;
763     CommRawOut(&cv,Str,2);
764     CommSend(&cv);
765     if (tr.LogFile!=0)
766     TelWriteLog(Str,2);
767     }
768    
769     void TelChangeEcho()
770     {
771     if (ts.LocalEcho==0)
772     TelEnableHisOpt(ECHO);
773     else
774     TelDisableHisOpt(ECHO);
775     }
776    
777     void TelSendNOP()
778     {
779     BYTE Str[2];
780    
781     Str[0] = IAC;
782     Str[1] = NOP;
783     CommRawOut(&cv,Str,2);
784     CommSend(&cv);
785     if (tr.LogFile!=0)
786     TelWriteLog(Str,2);
787     }
788    
789     #define WM_SEND_HEARTBEAT (WM_USER + 1)
790    
791     static LRESULT CALLBACK telnet_heartbeat_dlg_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
792     {
793    
794     switch (msg) {
795     case WM_INITDIALOG:
796     return FALSE;
797    
798     case WM_SEND_HEARTBEAT:
799     TelSendNOP();
800     return TRUE;
801     break;
802    
803     case WM_COMMAND:
804     switch (wp) {
805     }
806    
807     switch (LOWORD(wp)) {
808     case IDOK:
809     {
810     return TRUE;
811     }
812    
813     case IDCANCEL:
814     EndDialog(hWnd, 0);
815     return TRUE;
816     default:
817     return FALSE;
818     }
819     break;
820    
821     case WM_CLOSE:
822     // close�{�^���������������� window ���������������������B
823     return TRUE;
824    
825     case WM_DESTROY:
826     return TRUE;
827    
828     default:
829     return FALSE;
830     }
831     return TRUE;
832     }
833    
834    
835     static unsigned _stdcall TelKeepAliveThread(void *dummy) {
836     static int instance = 0;
837    
838     if (instance > 0)
839     return 0;
840     instance++;
841    
842     while (cv.Open && nop_interval > 0) {
843     if (time(NULL) >= cv.LastSendTime + nop_interval) {
844     SendMessage(keepalive_dialog, WM_SEND_HEARTBEAT, 0, 0);
845     }
846    
847     Sleep(100);
848     }
849     instance--;
850     return 0;
851     }
852    
853     void TelStartKeepAliveThread() {
854     unsigned tid;
855    
856     if (ts.TelKeepAliveInterval > 0) {
857     nop_interval = ts.TelKeepAliveInterval;
858    
859     // ���[�h���X�_�C�A���O������ (2007.12.26 yutaka)
860     keepalive_dialog = CreateDialog(hInst, MAKEINTRESOURCE(IDD_BROADCAST_DIALOG),
861     HVTWin, (DLGPROC)telnet_heartbeat_dlg_proc);
862    
863     keepalive_thread = (HANDLE)_beginthreadex(NULL, 0, TelKeepAliveThread, NULL, 0, &tid);
864     if (keepalive_thread == (HANDLE)-1) {
865     nop_interval = 0;
866     }
867     }
868     }
869    
870     void TelStopKeepAliveThread() {
871     if (keepalive_thread != (HANDLE)-1L) {
872     nop_interval = 0;
873     WaitForSingleObject(keepalive_thread, INFINITE);
874     CloseHandle(keepalive_thread);
875     keepalive_thread = (HANDLE)-1L;
876    
877     DestroyWindow(keepalive_dialog);
878     }
879     }
880    
881     void TelUpdateKeepAliveInterval() {
882     if (cv.Open && cv.TelFlag && ts.TCPPort==ts.TelPort) {
883     if (ts.TelKeepAliveInterval > 0 && keepalive_thread == (HANDLE)-1)
884     TelStartKeepAliveThread();
885     else if (ts.TelKeepAliveInterval == 0 && keepalive_thread != (HANDLE)-1)
886     TelStopKeepAliveThread();
887     else
888     nop_interval = ts.TelKeepAliveInterval;
889     }
890     }

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