Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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