Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2476 - (show annotations) (download) (as text)
Mon Apr 14 17:35:50 2008 UTC (16 years ago) by maya
Original Path: teraterm/trunk/teraterm/commlib.c
File MIME type: text/x-csrc
File size: 27945 byte(s)
ファイル移動に伴う修正

1 /* Tera Term
2 Copyright(C) 1994-1998 T. Teranishi
3 All rights reserved. */
4 /* IPv6 modification is Copyright (C) 2000, 2001 Jun-ya KATO <kato@win6.jp> */
5
6 /* TERATERM.EXE, Communication routines */
7 #include "teraterm.h"
8 #include "tttypes.h"
9 #include "tt_res.h"
10 #include <process.h>
11
12 #include "ttcommon.h"
13 #include "ttwsk.h"
14 #include "ttlib.h"
15 #include "ttplug.h" /* TTPLUG */
16
17 #include "commlib.h"
18 #ifndef NO_INET6
19 #include <winsock2.h>
20 #include <ws2tcpip.h>
21 #include <stdio.h> /* for _snprintf() */
22 #include "WSAAsyncGetAddrInfo.h"
23 #endif /* NO_INET6 */
24 #include <time.h>
25
26 static SOCKET OpenSocket(PComVar);
27 static void AsyncConnect(PComVar);
28 static int CloseSocket(SOCKET);
29
30 /* create socket */
31 static SOCKET OpenSocket(PComVar cv)
32 {
33 cv->s = cv->res->ai_family;
34 cv->s = Psocket(cv->res->ai_family, cv->res->ai_socktype, cv->res->ai_protocol);
35 return cv->s;
36 }
37
38 /* connect with asynchronous mode */
39 static void AsyncConnect(PComVar cv)
40 {
41 int Err;
42 BOOL BBuf;
43 BBuf = TRUE;
44 /* set synchronous mode */
45 PWSAAsyncSelect(cv->s,cv->HWin,0,0);
46 Psetsockopt(cv->s,(int)SOL_SOCKET,SO_OOBINLINE,(char FAR *)&BBuf,sizeof(BBuf));
47 /* set asynchronous mode */
48 PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMOPEN, FD_CONNECT);
49
50 // �z�X�g���������������������������A�����I���\�P�b�g���N���[�Y�����A
51 // �����������L�����Z���������B�l��0�������������������B
52 // (2007.1.11 yutaka)
53 if (*cv->ConnetingTimeout > 0) {
54 SetTimer(cv->HWin, IdCancelConnectTimer, *cv->ConnetingTimeout * 1000, NULL);
55 }
56
57 /* WM_USER_COMMOPEN occurs, CommOpen is called, then CommStart is called */
58 Err = Pconnect(cv->s, cv->res->ai_addr, cv->res->ai_addrlen);
59 if (Err != 0) {
60 Err = PWSAGetLastError();
61 if (Err == WSAEWOULDBLOCK)
62 {
63 /* Do nothing */
64 } else if (Err!=0 ) {
65 PostMessage(cv->HWin, WM_USER_COMMOPEN,0,
66 MAKELONG(FD_CONNECT,Err));
67 }
68 }
69 }
70
71 /* close socket */
72 static int CloseSocket(SOCKET s)
73 {
74 return Pclosesocket(s);
75 }
76
77 #define CommInQueSize 8192
78 #define CommOutQueSize 2048
79 #define CommXonLim 2048
80 #define CommXoffLim 2048
81
82 #define READENDNAME "ReadEnd"
83 #define WRITENAME "Write"
84 #define READNAME "Read"
85 #define PRNWRITENAME "PrnWrite"
86
87 static HANDLE ReadEnd;
88 static OVERLAPPED wol, rol;
89
90 // Winsock async operation handle
91 static HANDLE HAsync=0;
92
93 BOOL TCPIPClosed = TRUE;
94
95 /* Printer port handle for
96 direct pass-thru printing */
97 static HANDLE PrnID = INVALID_HANDLE_VALUE;
98 static BOOL LPTFlag;
99
100 // Initialize ComVar.
101 // This routine is called only once
102 // by the initialization procedure of Tera Term.
103 void CommInit(PComVar cv)
104 {
105 cv->Open = FALSE;
106 cv->Ready = FALSE;
107
108 // log-buffer variables
109 cv->HLogBuf = 0;
110 cv->HBinBuf = 0;
111 cv->LogBuf = NULL;
112 cv->BinBuf = NULL;
113 cv->LogPtr = 0;
114 cv->LStart = 0;
115 cv->LCount = 0;
116 cv->BinPtr = 0;
117 cv->BStart = 0;
118 cv->BCount = 0;
119 cv->DStart = 0;
120 cv->DCount = 0;
121 cv->BinSkip = 0;
122 cv->FilePause = 0;
123 cv->ProtoFlag = FALSE;
124 /* message flag */
125 cv->NoMsg = 0;
126 }
127
128 /* reset a serial port which is already open */
129 void CommResetSerial(PTTSet ts, PComVar cv, BOOL ClearBuff)
130 {
131 DCB dcb;
132 DWORD DErr;
133 COMMTIMEOUTS ctmo;
134
135 if (! cv->Open ||
136 (cv->PortType != IdSerial)) return;
137
138 ClearCommError(cv->ComID,&DErr,NULL);
139 SetupComm(cv->ComID,CommInQueSize,CommOutQueSize);
140 /* flush input and output buffers */
141 if (ClearBuff)
142 PurgeComm(cv->ComID, PURGE_TXABORT | PURGE_RXABORT |
143 PURGE_TXCLEAR | PURGE_RXCLEAR);
144
145 memset(&ctmo,0,sizeof(ctmo));
146 ctmo.ReadIntervalTimeout = MAXDWORD;
147 ctmo.WriteTotalTimeoutConstant = 500;
148 SetCommTimeouts(cv->ComID,&ctmo);
149 cv->InBuffCount = 0;
150 cv->InPtr = 0;
151 cv->OutBuffCount = 0;
152 cv->OutPtr = 0;
153
154 cv->DelayPerChar = ts->DelayPerChar;
155 cv->DelayPerLine = ts->DelayPerLine;
156
157 memset(&dcb,0,sizeof(DCB));
158 dcb.DCBlength = sizeof(DCB);
159 switch (ts->Baud) {
160 case IdBaud110: dcb.BaudRate = 110; break;
161 case IdBaud300: dcb.BaudRate = 300; break;
162 case IdBaud600: dcb.BaudRate = 600; break;
163 case IdBaud1200: dcb.BaudRate = 1200; break;
164 case IdBaud2400: dcb.BaudRate = 2400; break;
165 case IdBaud4800: dcb.BaudRate = 4800; break;
166 case IdBaud9600: dcb.BaudRate = 9600; break;
167 case IdBaud14400: dcb.BaudRate = 14400; break;
168 case IdBaud19200: dcb.BaudRate = 19200; break;
169 case IdBaud38400: dcb.BaudRate = 38400; break;
170 case IdBaud57600: dcb.BaudRate = 57600; break;
171 case IdBaud115200: dcb.BaudRate = 115200; break;
172 // add (2005.11.30 yutaka)
173 case IdBaud230400: dcb.BaudRate = 230400; break;
174 case IdBaud460800: dcb.BaudRate = 460800; break;
175 case IdBaud921600: dcb.BaudRate = 921600; break;
176 }
177 dcb.fBinary = TRUE;
178 switch (ts->Parity) {
179 case IdParityEven:
180 dcb.fParity = TRUE;
181 dcb.Parity = EVENPARITY;
182 break;
183 case IdParityOdd:
184 dcb.fParity = TRUE;
185 dcb.Parity = ODDPARITY;
186 break;
187 case IdParityNone:
188 dcb.Parity = NOPARITY;
189 break;
190 }
191
192 dcb.fDtrControl = DTR_CONTROL_ENABLE;
193 dcb.fRtsControl = RTS_CONTROL_ENABLE;
194 switch (ts->Flow) {
195 case IdFlowX:
196 dcb.fOutX = TRUE;
197 dcb.fInX = TRUE;
198 dcb.XonLim = CommXonLim;
199 dcb.XoffLim = CommXoffLim;
200 dcb.XonChar = XON;
201 dcb.XoffChar = XOFF;
202 break;
203 case IdFlowHard:
204 dcb.fOutxCtsFlow = TRUE;
205 dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
206 break;
207 }
208
209 switch (ts->DataBit) {
210 case IdDataBit7: dcb.ByteSize = 7; break;
211 case IdDataBit8: dcb.ByteSize = 8; break;
212 }
213 switch (ts->StopBit) {
214 case IdStopBit1: dcb.StopBits = ONESTOPBIT; break;
215 case IdStopBit2: dcb.StopBits = TWOSTOPBITS; break;
216 }
217
218 SetCommState(cv->ComID, &dcb);
219
220 /* enable receive request */
221 SetCommMask(cv->ComID,0);
222 SetCommMask(cv->ComID,EV_RXCHAR);
223 }
224
225 void CommOpen(HWND HW, PTTSet ts, PComVar cv)
226 {
227 #ifdef NO_INET6
228 int Err;
229 #endif /* NO_INET6 */
230 char ErrMsg[21];
231 char P[50];
232
233 MSG Msg;
234 #ifndef NO_INET6
235 ADDRINFO hints;
236 char pname[NI_MAXSERV];
237 #else
238 char HEntBuff[MAXGETHOSTSTRUCT];
239 u_long addr;
240 SOCKADDR_IN saddr;
241 #endif /* NO_INET6 */
242
243 BOOL InvalidHost;
244 #ifdef NO_INET6
245 BOOL BBuf;
246 #endif /* NO_INET6 */
247
248 char uimsg[MAX_UIMSG];
249
250 /* initialize ComVar */
251 cv->InBuffCount = 0;
252 cv->InPtr = 0;
253 cv->OutBuffCount = 0;
254 cv->OutPtr = 0;
255 cv->HWin = HW;
256 cv->Ready = FALSE;
257 cv->Open = FALSE;
258 cv->PortType = ts->PortType;
259 cv->ComPort = 0;
260 cv->RetryCount = 0;
261 #ifndef NO_INET6
262 cv->RetryWithOtherProtocol = TRUE;
263 #endif /* NO_INET6 */
264 cv->s = INVALID_SOCKET;
265 cv->ComID = INVALID_HANDLE_VALUE;
266 cv->CanSend = TRUE;
267 cv->RRQ = FALSE;
268 cv->SendKanjiFlag = FALSE;
269 cv->SendCode = IdASCII;
270 cv->EchoKanjiFlag = FALSE;
271 cv->EchoCode = IdASCII;
272 cv->Language = ts->Language;
273 cv->CRSend = ts->CRSend;
274 cv->KanjiCodeEcho = ts->KanjiCode;
275 cv->JIS7KatakanaEcho = ts->JIS7Katakana;
276 cv->KanjiCodeSend = ts->KanjiCodeSend;
277 cv->JIS7KatakanaSend = ts->JIS7KatakanaSend;
278 cv->KanjiIn = ts->KanjiIn;
279 cv->KanjiOut = ts->KanjiOut;
280 cv->RussHost = ts->RussHost;
281 cv->RussClient = ts->RussClient;
282 cv->DelayFlag = TRUE;
283 cv->DelayPerChar = ts->DelayPerChar;
284 cv->DelayPerLine = ts->DelayPerLine;
285 cv->TelBinRecv = FALSE;
286 cv->TelBinSend = FALSE;
287 cv->TelFlag = FALSE;
288 cv->TelMode = FALSE;
289 cv->IACFlag = FALSE;
290 cv->TelCRFlag = FALSE;
291 cv->TelCRSend = FALSE;
292 cv->TelCRSendEcho = FALSE;
293 cv->TelAutoDetect = ts->TelAutoDetect; /* TTPLUG */
294 cv->Locale = ts->Locale;
295 cv->CodePage = &ts->CodePage;
296 cv->ConnetingTimeout = &ts->ConnectingTimeout;
297 cv->LastSendTime = time(NULL);
298
299 if ((ts->PortType!=IdSerial) && (strlen(ts->HostName)==0))
300 {
301 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
302 return;
303 }
304
305 switch (ts->PortType) {
306 case IdTCPIP:
307 cv->TelFlag = (ts->Telnet > 0);
308 if (! LoadWinsock())
309 {
310 if (cv->NoMsg==0)
311 {
312 get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile);
313 get_lang_msg("MSG_WINSOCK_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot use winsock", ts->UILanguageFile);
314 MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION);
315 }
316 InvalidHost = TRUE;
317 }
318 else {
319 TTXOpenTCP(); /* TTPLUG */
320 cv->Open = TRUE;
321 #ifndef NO_INET6
322 /* resolving address */
323 memset(&hints, 0, sizeof(hints));
324 hints.ai_family = ts->ProtocolFamily;
325 hints.ai_socktype = SOCK_STREAM;
326 hints.ai_protocol = IPPROTO_TCP;
327 _snprintf_s(pname, sizeof(pname), _TRUNCATE, "%d", ts->TCPPort);
328
329 HAsync = WSAAsyncGetAddrInfo(HW, WM_USER_GETHOST,
330 ts->HostName, pname, &hints, &cv->res0);
331 if (HAsync == 0)
332 InvalidHost = TRUE;
333 else {
334 cv->ComPort = 1; // set "getting host" flag
335 // (see CVTWindow::OnSysCommand())
336 do {
337 if (GetMessage(&Msg,0,0,0))
338 {
339 if ((Msg.hwnd==HW) &&
340 ((Msg.message == WM_SYSCOMMAND) &&
341 ((Msg.wParam & 0xfff0) == SC_CLOSE) ||
342 (Msg.message == WM_COMMAND) &&
343 (LOWORD(Msg.wParam) == ID_FILE_EXIT) ||
344 (Msg.message == WM_CLOSE)))
345 { /* Exit when the user closes Tera Term */
346 PWSACancelAsyncRequest(HAsync);
347 CloseHandle(HAsync);
348 HAsync = 0;
349 cv->ComPort = 0; // clear "getting host" flag
350 PostMessage(HW,Msg.message,Msg.wParam,Msg.lParam);
351 return;
352 }
353 if (Msg.message != WM_USER_GETHOST)
354 { /* Prosess messages */
355 TranslateMessage(&Msg);
356 DispatchMessage(&Msg);
357 }
358 }
359 else {
360 return;
361 }
362 } while (Msg.message!=WM_USER_GETHOST);
363 cv->ComPort = 0; // clear "getting host" flag
364 CloseHandle(HAsync);
365 HAsync = 0;
366 InvalidHost = WSAGETASYNCERROR(Msg.lParam) != 0;
367 }
368 } /* if (!LoadWinsock()) */
369
370 if (InvalidHost)
371 {
372 if (cv->NoMsg==0)
373 {
374 get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile);
375 get_lang_msg("MSG_INVALID_HOST_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Invalid host", ts->UILanguageFile);
376 MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION);
377 }
378 goto BreakSC;
379 }
380 for (cv->res = cv->res0; cv->res; cv->res = cv->res->ai_next) {
381 cv->s = OpenSocket(cv);
382 if (cv->s == INVALID_SOCKET) {
383 CloseSocket(cv->s);
384 continue;
385 }
386 /* start asynchronous connect */
387 AsyncConnect(cv);
388 break; /* break for-loop immediately */
389 }
390 break;
391 #else
392 if ((ts->HostName[0] >= 0x30) && (ts->HostName[0] <= 0x39))
393 {
394 addr = Pinet_addr(ts->HostName);
395 InvalidHost = (addr == 0xffffffff);
396 }
397 else {
398 HAsync = PWSAAsyncGetHostByName(HW,WM_USER_GETHOST,
399 ts->HostName,HEntBuff,sizeof(HEntBuff));
400 if (HAsync == 0)
401 InvalidHost = TRUE;
402 else {
403 cv->ComPort = 1; // set "getting host" flag
404 // (see CVTWindow::OnSysCommand())
405 do {
406 if (GetMessage(&Msg,0,0,0))
407 {
408 if ((Msg.hwnd==HW) &&
409 ((Msg.message == WM_SYSCOMMAND) &&
410 ((Msg.wParam & 0xfff0) == SC_CLOSE) ||
411 (Msg.message == WM_COMMAND) &&
412 (LOWORD(Msg.wParam) == ID_FILE_EXIT) ||
413 (Msg.message == WM_CLOSE)))
414 { /* Exit when the user closes Tera Term */
415 PWSACancelAsyncRequest(HAsync);
416 HAsync = 0;
417 cv->ComPort = 0; // clear "getting host" flag
418 PostMessage(HW,Msg.message,Msg.wParam,Msg.lParam);
419 return;
420 }
421 if (Msg.message != WM_USER_GETHOST)
422 { /* Prosess messages */
423 TranslateMessage(&Msg);
424 DispatchMessage(&Msg);
425 }
426 }
427 else {
428 return;
429 }
430 } while (Msg.message!=WM_USER_GETHOST);
431 cv->ComPort = 0; // clear "getting host" flag
432 HAsync = 0;
433 InvalidHost = WSAGETASYNCERROR(Msg.lParam) != 0;
434 if (! InvalidHost)
435 {
436 if (((PHOSTENT)HEntBuff)->h_addr_list != NULL)
437 memcpy(&addr,
438 ((PHOSTENT)HEntBuff)->h_addr_list[0],sizeof(addr));
439 else
440 InvalidHost = TRUE;
441 }
442 }
443
444 }
445
446 if (InvalidHost)
447 {
448 if (cv->NoMsg==0)
449 MessageBox(cv->HWin,"Invalid host",ErrorCaption,
450 MB_TASKMODAL | MB_ICONEXCLAMATION);
451 }
452 else {
453 cv->s= Psocket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
454 if (cv->s==INVALID_SOCKET)
455 {
456 InvalidHost = TRUE;
457 if (cv->NoMsg==0)
458 MessageBox(cv->HWin,ErrorCantConn,ErrorCaption,
459 MB_TASKMODAL | MB_ICONEXCLAMATION);
460 }
461 else {
462 BBuf = TRUE;
463 Psetsockopt(cv->s,(int)SOL_SOCKET,SO_OOBINLINE,(char FAR *)&BBuf,sizeof(BBuf));
464
465 PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMOPEN, FD_CONNECT);
466 saddr.sin_family = AF_INET;
467 saddr.sin_port = Phtons(ts->TCPPort);
468 saddr.sin_addr.s_addr = addr;
469 memset(saddr.sin_zero,0,8);
470
471 Err = Pconnect(cv->s,(LPSOCKADDR)&saddr,sizeof(saddr));
472 if (Err!=0 ) Err = PWSAGetLastError();
473 if (Err==WSAEWOULDBLOCK )
474 {
475 /* Do nothing */
476 }
477 else if (Err!=0 )
478 PostMessage(cv->HWin, WM_USER_COMMOPEN,0,
479 MAKELONG(FD_CONNECT,Err));
480 }
481 }
482 }
483 break;
484 #endif /* NO_INET6 */
485
486 case IdSerial:
487 _snprintf_s(P, sizeof(P), _TRUNCATE, "COM%d", ts->ComPort);
488 strncpy_s(ErrMsg, sizeof(ErrMsg),P, _TRUNCATE);
489 strncpy_s(P, sizeof(P),"\\\\.\\", _TRUNCATE);
490 strncat_s(P, sizeof(P),ErrMsg, _TRUNCATE);
491 cv->ComID =
492 CreateFile(P,GENERIC_READ | GENERIC_WRITE,
493 0,NULL,OPEN_EXISTING,
494 FILE_FLAG_OVERLAPPED,NULL);
495 if (cv->ComID == INVALID_HANDLE_VALUE )
496 {
497
498 get_lang_msg("MSG_CANTOEPN_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot open %s", ts->UILanguageFile);
499 _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, ts->UIMsg, &P[4]);
500
501 if (cv->NoMsg==0)
502 {
503 get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile);
504 MessageBox(cv->HWin,ErrMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION);
505 }
506 InvalidHost = TRUE;
507 }
508 else {
509 cv->Open = TRUE;
510 cv->ComPort = ts->ComPort;
511 CommResetSerial(ts, cv, ts->ClearComBuffOnOpen);
512 if (!ts->ClearComBuffOnOpen)
513 cv->RRQ = TRUE;
514
515 /* notify to VT window that Comm Port is open */
516 PostMessage(cv->HWin, WM_USER_COMMOPEN, 0, 0);
517 InvalidHost = FALSE;
518
519 SetCOMFlag(ts->ComPort);
520 }
521 break; /* end of "case IdSerial:" */
522
523 case IdFile:
524 cv->ComID = CreateFile(ts->HostName,GENERIC_READ,0,NULL,
525 OPEN_EXISTING,0,NULL);
526 InvalidHost = (cv->ComID == INVALID_HANDLE_VALUE);
527 if (InvalidHost)
528 {
529 if (cv->NoMsg==0)
530 {
531 get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile);
532 get_lang_msg("MSG_CANTOEPN_FILE_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot open file", ts->UILanguageFile);
533 MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION);
534 }
535 }
536 else {
537 cv->Open = TRUE;
538 PostMessage(cv->HWin, WM_USER_COMMOPEN, 0, 0);
539 }
540 break;
541 } /* end of "switch" */
542
543 #ifndef NO_INET6
544 BreakSC:
545 #endif /* NO_INET6 */
546 if (InvalidHost)
547 {
548 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
549 if ( (ts->PortType==IdTCPIP) && cv->Open )
550 {
551 if ( cv->s!=INVALID_SOCKET ) Pclosesocket(cv->s);
552 FreeWinsock();
553 }
554 return;
555 }
556 }
557
558 void CommThread(void *arg)
559 {
560 DWORD Evt;
561 PComVar cv = (PComVar)arg;
562 DWORD DErr;
563 HANDLE REnd;
564 char Temp[20];
565
566 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READENDNAME, cv->ComPort);
567 REnd = OpenEvent(EVENT_ALL_ACCESS,FALSE, Temp);
568 while (TRUE) {
569 if (WaitCommEvent(cv->ComID,&Evt,NULL))
570 {
571 if (! cv->Ready) _endthread();
572 if (! cv->RRQ)
573 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_READ);
574 WaitForSingleObject(REnd,INFINITE);
575 }
576 else {
577 if (! cv->Ready) _endthread();
578 ClearCommError(cv->ComID,&DErr,NULL);
579 }
580 }
581 }
582
583 void CommStart(PComVar cv, LONG lParam, PTTSet ts)
584 {
585 char ErrMsg[31];
586 char Temp[20];
587 char uimsg[MAX_UIMSG];
588
589 if (! cv->Open ) return;
590 if ( cv->Ready ) return;
591
592 // �L�����Z���^�C�}�����������������B�������A�������_�� WM_TIMER �����������������\���������B
593 if (*cv->ConnetingTimeout > 0) {
594 KillTimer(cv->HWin, IdCancelConnectTimer);
595 }
596
597 switch (cv->PortType) {
598 case IdTCPIP:
599 ErrMsg[0] = 0;
600 switch (HIWORD(lParam)) {
601 case WSAECONNREFUSED:
602 get_lang_msg("MSG_COMM_REFUSE_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Connection refused", ts->UILanguageFile);
603 _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "%s", ts->UIMsg);
604 break;
605 case WSAENETUNREACH:
606 get_lang_msg("MSG_COMM_REACH_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Network cannot be reached", ts->UILanguageFile);
607 _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "%s", ts->UIMsg);
608 break;
609 case WSAETIMEDOUT:
610 get_lang_msg("MSG_COMM_CONNECT_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Connection timed out", ts->UILanguageFile);
611 _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "%s", ts->UIMsg);
612 break;
613 default:
614 get_lang_msg("MSG_COMM_TIMEOUT_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Cannot connect the host", ts->UILanguageFile);
615 _snprintf_s(ErrMsg, sizeof(ErrMsg), _TRUNCATE, "%s", ts->UIMsg);
616 }
617 if (HIWORD(lParam)>0)
618 {
619 #ifndef NO_INET6
620 /* connect() failed */
621 if (cv->res->ai_next != NULL) {
622 /* try to connect with other protocol */
623 CloseSocket(cv->s);
624 for (cv->res = cv->res->ai_next; cv->res; cv->res = cv->res->ai_next) {
625 cv->s = OpenSocket(cv);
626 if (cv->s == INVALID_SOCKET) {
627 CloseSocket(cv->s);
628 continue;
629 }
630 AsyncConnect(cv);
631 cv->Ready = FALSE;
632 cv->RetryWithOtherProtocol = TRUE; /* retry with other procotol */
633 return;
634 }
635 } else {
636 /* trying with all protocol family are failed */
637 if (cv->NoMsg==0)
638 {
639 get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile);
640 MessageBox(cv->HWin,ErrMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION);
641 }
642 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
643 cv->RetryWithOtherProtocol = FALSE;
644 return;
645 }
646 #else
647 if (cv->NoMsg==0)
648 MessageBox(cv->HWin,ErrMsg,ErrorCaption,
649 MB_TASKMODAL | MB_ICONEXCLAMATION);
650 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
651 return;
652 #endif /* NO_INET6 */
653 }
654
655 #ifndef NO_INET6
656 /* here is connection established */
657 cv->RetryWithOtherProtocol = FALSE;
658 #endif /* NO_INET6 */
659 PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMNOTIFY, FD_READ | FD_OOB | FD_CLOSE);
660 TCPIPClosed = FALSE;
661 break;
662
663 case IdSerial:
664 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READENDNAME, cv->ComPort);
665 ReadEnd = CreateEvent(NULL,FALSE,FALSE,Temp);
666 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", WRITENAME, cv->ComPort);
667 memset(&wol,0,sizeof(OVERLAPPED));
668 wol.hEvent = CreateEvent(NULL,TRUE,TRUE,Temp);
669 _snprintf_s(Temp, sizeof(Temp), _TRUNCATE, "%s%d", READNAME, cv->ComPort);
670 memset(&rol,0,sizeof(OVERLAPPED));
671 rol.hEvent = CreateEvent(NULL,TRUE,FALSE,Temp);
672
673 /* create the receiver thread */
674 if (_beginthread(CommThread,0,cv) == -1)
675 {
676 get_lang_msg("MSG_TT_ERROR", uimsg, sizeof(uimsg), "Tera Term: Error", ts->UILanguageFile);
677 get_lang_msg("MSG_TT_ERROR", ts->UIMsg, sizeof(ts->UIMsg), "Can't create thread", ts->UILanguageFile);
678 MessageBox(cv->HWin,ts->UIMsg,uimsg,MB_TASKMODAL | MB_ICONEXCLAMATION);
679 }
680 break;
681 case IdFile: cv->RRQ = TRUE; break;
682 }
683 cv->Ready = TRUE;
684 }
685
686 BOOL CommCanClose(PComVar cv)
687 { // check if data remains in buffer
688 if (! cv->Open) return TRUE;
689 if (cv->InBuffCount>0) return FALSE;
690 if ((cv->HLogBuf!=NULL) &&
691 ((cv->LCount>0) ||
692 (cv->DCount>0))) return FALSE;
693 if ((cv->HBinBuf!=NULL) &&
694 (cv->BCount>0)) return FALSE;
695 return TRUE;
696 }
697
698 void CommClose(PComVar cv)
699 {
700 if ( ! cv->Open ) return;
701 cv->Open = FALSE;
702
703 /* disable event message posting & flush buffer */
704 cv->RRQ = FALSE;
705 cv->Ready = FALSE;
706 cv->InPtr = 0;
707 cv->InBuffCount = 0;
708 cv->OutPtr = 0;
709 cv->OutBuffCount = 0;
710
711 /* close port & release resources */
712 switch (cv->PortType) {
713 case IdTCPIP:
714 if (HAsync!=0)
715 PWSACancelAsyncRequest(HAsync);
716 HAsync = 0;
717 #ifndef NO_INET6
718 freeaddrinfo(cv->res0);
719 #endif /* NO_INET6 */
720 if ( cv->s!=INVALID_SOCKET )
721 Pclosesocket(cv->s);
722 cv->s = INVALID_SOCKET;
723 TTXCloseTCP(); /* TTPLUG */
724 FreeWinsock();
725 break;
726 case IdSerial:
727 if ( cv->ComID != INVALID_HANDLE_VALUE )
728 {
729 CloseHandle(ReadEnd);
730 CloseHandle(wol.hEvent);
731 CloseHandle(rol.hEvent);
732 PurgeComm(cv->ComID,
733 PURGE_TXABORT | PURGE_RXABORT |
734 PURGE_TXCLEAR | PURGE_RXCLEAR);
735 EscapeCommFunction(cv->ComID,CLRDTR);
736 SetCommMask(cv->ComID,0);
737 CloseHandle(cv->ComID);
738 ClearCOMFlag(cv->ComPort);
739 }
740 break;
741 case IdFile:
742 if (cv->ComID != INVALID_HANDLE_VALUE)
743 CloseHandle(cv->ComID);
744 break;
745 }
746 cv->ComID = INVALID_HANDLE_VALUE;
747 cv->PortType = 0;
748 }
749
750 void CommProcRRQ(PComVar cv)
751 {
752 if ( ! cv->Ready ) return;
753 /* disable receive request */
754 switch (cv->PortType) {
755 case IdTCPIP:
756 if (! TCPIPClosed)
757 PWSAAsyncSelect(cv->s,cv->HWin,WM_USER_COMMNOTIFY, FD_OOB | FD_CLOSE);
758 break;
759 case IdSerial:
760 break;
761 }
762 cv->RRQ = TRUE;
763 CommReceive(cv);
764 }
765
766 void CommReceive(PComVar cv)
767 {
768 DWORD C;
769 DWORD DErr;
770
771 if (! cv->Ready || ! cv->RRQ ||
772 (cv->InBuffCount>=InBuffSize)) return;
773
774 /* Compact buffer */
775 if ((cv->InBuffCount>0) && (cv->InPtr>0))
776 {
777 memmove(cv->InBuff,&(cv->InBuff[cv->InPtr]),cv->InBuffCount);
778 cv->InPtr = 0;
779 }
780
781 if (cv->InBuffCount<InBuffSize)
782 {
783 switch (cv->PortType) {
784 case IdTCPIP:
785 C = Precv(cv->s, &(cv->InBuff[cv->InBuffCount]),
786 InBuffSize-cv->InBuffCount, 0);
787 if (C == SOCKET_ERROR)
788 {
789 C = 0;
790 PWSAGetLastError();
791 }
792 cv->InBuffCount = cv->InBuffCount + C;
793 break;
794 case IdSerial:
795 do {
796 ClearCommError(cv->ComID,&DErr,NULL);
797 if (! ReadFile(cv->ComID,&(cv->InBuff[cv->InBuffCount]),
798 InBuffSize-cv->InBuffCount,&C,&rol))
799 {
800 if (GetLastError() == ERROR_IO_PENDING)
801 {
802 if (WaitForSingleObject(rol.hEvent, 1000) !=
803 WAIT_OBJECT_0)
804 C = 0;
805 else
806 GetOverlappedResult(cv->ComID,&rol,&C,FALSE);
807 }
808 else
809 C = 0;
810 }
811 cv->InBuffCount = cv->InBuffCount + C;
812 } while ((C!=0) && (cv->InBuffCount<InBuffSize));
813 ClearCommError(cv->ComID,&DErr,NULL);
814 break;
815 case IdFile:
816 ReadFile(cv->ComID,&(cv->InBuff[cv->InBuffCount]),
817 InBuffSize-cv->InBuffCount,&C,NULL);
818 cv->InBuffCount = cv->InBuffCount + C;
819 break;
820 }
821 }
822
823 if (cv->InBuffCount==0)
824 {
825 switch (cv->PortType) {
826 case IdTCPIP:
827 if (! TCPIPClosed)
828 PWSAAsyncSelect(cv->s,cv->HWin,
829 WM_USER_COMMNOTIFY, FD_READ | FD_OOB | FD_CLOSE);
830 break;
831 case IdSerial:
832 cv->RRQ = FALSE;
833 SetEvent(ReadEnd);
834 return;
835 case IdFile:
836 PostMessage(cv->HWin, WM_USER_COMMNOTIFY, 0, FD_CLOSE);
837 break;
838 }
839 cv->RRQ = FALSE;
840
841 }
842 }
843
844 void CommSend(PComVar cv)
845 {
846 int delay;
847 COMSTAT Stat;
848 BYTE LineEnd;
849 int C, D, Max;
850 DWORD DErr;
851
852 if ((! cv->Open) || (! cv->Ready))
853 {
854 cv->OutBuffCount = 0;
855 return;
856 }
857
858 if ((cv->OutBuffCount == 0) || (! cv->CanSend)) return;
859
860 /* Max num of bytes to be written */
861 switch (cv->PortType) {
862 case IdTCPIP:
863 if (TCPIPClosed) cv->OutBuffCount = 0;
864 Max = cv->OutBuffCount;
865 break;
866 case IdSerial:
867 ClearCommError(cv->ComID,&DErr,&Stat);
868 Max = OutBuffSize - Stat.cbOutQue;
869 break;
870 case IdFile: Max = cv->OutBuffCount;
871 break;
872 }
873
874 if ( Max<=0 ) return;
875 if ( Max > cv->OutBuffCount ) Max = cv->OutBuffCount;
876
877 if (cv->PortType == IdTCPIP && cv->TelFlag) {
878 cv->LastSendTime = time(NULL);
879 }
880
881 C = Max;
882 delay = 0;
883
884 if ( cv->DelayFlag && (cv->PortType==IdSerial) )
885 {
886 if ( cv->DelayPerLine > 0 )
887 {
888 if ( cv->CRSend==IdCR ) LineEnd = 0x0d;
889 else LineEnd = 0x0a;
890 C = 1;
891 if ( cv->DelayPerChar==0 )
892 while ((C<Max) && (cv->OutBuff[cv->OutPtr+C-1]!=LineEnd))
893 C++;
894 if ( cv->OutBuff[cv->OutPtr+C-1]==LineEnd )
895 delay = cv->DelayPerLine;
896 else delay = cv->DelayPerChar;
897 }
898 else if ( cv->DelayPerChar > 0 )
899 {
900 C = 1;
901 delay = cv->DelayPerChar;
902 }
903 }
904
905 /* Write to comm driver/Winsock */
906 switch (cv->PortType) {
907 case IdTCPIP:
908 D = Psend(cv->s, &(cv->OutBuff[cv->OutPtr]), C, 0);
909 if ( D==SOCKET_ERROR ) /* if error occurs */
910 {
911 PWSAGetLastError(); /* Clear error */
912 D = 0;
913 }
914 break;
915
916 case IdSerial:
917 if (! WriteFile(cv->ComID,&(cv->OutBuff[cv->OutPtr]),C,(LPDWORD)&D,&wol))
918 {
919 if (GetLastError() == ERROR_IO_PENDING)
920 {
921 if (WaitForSingleObject(wol.hEvent,1000) !=
922 WAIT_OBJECT_0)
923 D = C; /* Time out, ignore data */
924 else
925 GetOverlappedResult(cv->ComID,&wol,(LPDWORD)&D,FALSE);
926 }
927 else /* I/O error */
928 D = C; /* ignore error */
929 }
930 ClearCommError(cv->ComID,&DErr,&Stat);
931 break;
932 case IdFile: D = C; break;
933 }
934
935 cv->OutBuffCount = cv->OutBuffCount - D;
936 if ( cv->OutBuffCount==0 )
937 cv->OutPtr = 0;
938 else
939 cv->OutPtr = cv->OutPtr + D;
940
941 if ( (C==D) && (delay>0) )
942 {
943 cv->CanSend = FALSE;
944 SetTimer(cv->HWin, IdDelayTimer, delay, NULL);
945 }
946 }
947
948 void CommSendBreak(PComVar cv)
949 /* for only serial ports */
950 {
951 MSG DummyMsg;
952
953 if ( ! cv->Ready ) return;
954
955 switch (cv->PortType) {
956 case IdSerial:
957 /* Set com port into a break state */
958 SetCommBreak(cv->ComID);
959
960 /* pause for 1 sec */
961 if (SetTimer(cv->HWin, IdBreakTimer, 1000, NULL) != 0)
962 GetMessage(&DummyMsg,cv->HWin,WM_TIMER,WM_TIMER);
963
964 /* Set com port into the nonbreak state */
965 ClearCommBreak(cv->ComID);
966 break;
967 }
968 }
969
970 void CommLock(PTTSet ts, PComVar cv, BOOL Lock)
971 {
972 BYTE b;
973 DWORD Func;
974
975 if (! cv->Ready) return;
976 if ((cv->PortType==IdTCPIP) ||
977 (cv->PortType==IdSerial) &&
978 (ts->Flow!=IdFlowHard))
979 {
980 if (Lock)
981 b = XOFF;
982 else
983 b = XON;
984 CommBinaryOut(cv,&b,1);
985 }
986 else if ((cv->PortType==IdSerial) &&
987 (ts->Flow==IdFlowHard))
988 {
989 if (Lock)
990 Func = CLRRTS;
991 else
992 Func = SETRTS;
993 EscapeCommFunction(cv->ComID,Func);
994 }
995 }
996
997 int GetCommSerialBaudRate(int id)
998 {
999 switch (id) {
1000 case IdBaud110:
1001 return 110;
1002 case IdBaud300:
1003 case IdBaud600:
1004 case IdBaud1200:
1005 case IdBaud2400:
1006 case IdBaud4800:
1007 case IdBaud9600:
1008 return 300 << (id - IdBaud110 -1);
1009 case IdBaud14400:
1010 return 14400;
1011 case IdBaud19200:
1012 return 19200;
1013 case IdBaud38400:
1014 return 38400;
1015 case IdBaud57600:
1016 case IdBaud115200:
1017 case IdBaud230400:
1018 case IdBaud460800:
1019 case IdBaud921600:
1020 return 57600 << (id - IdBaud38400 -1);
1021 }
1022
1023 return 0;
1024 }
1025
1026 BOOL PrnOpen(PCHAR DevName)
1027 {
1028 char Temp[MAXPATHLEN];
1029 DCB dcb;
1030 DWORD DErr;
1031 COMMTIMEOUTS ctmo;
1032
1033 strncpy_s(Temp, sizeof(Temp),DevName, _TRUNCATE);
1034 Temp[4] = 0; // COMn or LPTn
1035 LPTFlag = (Temp[0]=='L') ||
1036 (Temp[0]=='l');
1037 PrnID =
1038 CreateFile(Temp,GENERIC_WRITE,
1039 0,NULL,OPEN_EXISTING,
1040 0,NULL);
1041 if (PrnID == INVALID_HANDLE_VALUE) return FALSE;
1042
1043 if (GetCommState(PrnID,&dcb))
1044 {
1045 BuildCommDCB(DevName,&dcb);
1046 SetCommState(PrnID,&dcb);
1047 }
1048 ClearCommError(PrnID,&DErr,NULL);
1049 if (! LPTFlag)
1050 SetupComm(PrnID,0,CommOutQueSize);
1051 /* flush output buffer */
1052 PurgeComm(PrnID, PURGE_TXABORT |
1053 PURGE_TXCLEAR);
1054 memset(&ctmo,0,sizeof(ctmo));
1055 ctmo.WriteTotalTimeoutConstant = 1000;
1056 SetCommTimeouts(PrnID,&ctmo);
1057 if (! LPTFlag)
1058 EscapeCommFunction(PrnID,SETDTR);
1059 return TRUE;
1060 }
1061
1062 int PrnWrite(PCHAR b, int c)
1063 {
1064 int d;
1065 DWORD DErr;
1066 COMSTAT Stat;
1067
1068 if (PrnID == INVALID_HANDLE_VALUE )
1069 return c;
1070
1071 ClearCommError(PrnID,&DErr,&Stat);
1072 if (! LPTFlag &&
1073 (OutBuffSize - (int)Stat.cbOutQue < c))
1074 c = OutBuffSize - Stat.cbOutQue;
1075 if (c<=0) return 0;
1076 if (! WriteFile(PrnID,b,c,(LPDWORD)&d,NULL))
1077 d = 0;
1078 ClearCommError(PrnID,&DErr,NULL);
1079 return d;
1080 }
1081
1082 void PrnCancel()
1083 {
1084 PurgeComm(PrnID,
1085 PURGE_TXABORT | PURGE_TXCLEAR);
1086 PrnClose();
1087 }
1088
1089 void PrnClose()
1090 {
1091 if (PrnID != INVALID_HANDLE_VALUE)
1092 {
1093 if (!LPTFlag)
1094 EscapeCommFunction(PrnID,CLRDTR);
1095 CloseHandle(PrnID);
1096 }
1097 PrnID = INVALID_HANDLE_VALUE;
1098 }

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