OSDN Git Service

Fix bugs of hanging on exit.
[ffftp/ffftp.git] / socket.c
1 /*=============================================================================\r
2 *\r
3 *                                                                       ソケット\r
4 *\r
5 ===============================================================================\r
6 / Copyright (C) 1997-2007 Sota. All rights reserved.\r
7 /\r
8 / Redistribution and use in source and binary forms, with or without \r
9 / modification, are permitted provided that the following conditions \r
10 / are met:\r
11 /\r
12 /  1. Redistributions of source code must retain the above copyright \r
13 /     notice, this list of conditions and the following disclaimer.\r
14 /  2. Redistributions in binary form must reproduce the above copyright \r
15 /     notice, this list of conditions and the following disclaimer in the \r
16 /     documentation and/or other materials provided with the distribution.\r
17 /\r
18 / THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR \r
19 / IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES \r
20 / OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
21 / IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, \r
22 / INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
23 / BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF \r
24 / USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
25 / ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
26 / (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF \r
27 / THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
28 /============================================================================*/\r
29 \r
30 #define STRICT\r
31 // IPv6対応\r
32 #include <winsock2.h>\r
33 #include <windows.h>\r
34 #include <stdio.h>\r
35 #include <stdlib.h>\r
36 #include <string.h>\r
37 #include <time.h>\r
38 #include <windowsx.h>\r
39 #include <commctrl.h>\r
40 \r
41 #include "common.h"\r
42 #include "resource.h"\r
43 \r
44 #define USE_THIS        1\r
45 #define DBG_MSG         0\r
46 \r
47 \r
48 \r
49 \r
50 // Winsock2で定義される定数と名前が重複し値が異なるため使用不可\r
51 //#define FD_CONNECT_BIT                0x0001\r
52 //#define FD_CLOSE_BIT          0x0002\r
53 //#define FD_ACCEPT_BIT         0x0004\r
54 //#define FD_READ_BIT                   0x0008\r
55 //#define FD_WRITE_BIT          0x0010\r
56 \r
57 \r
58 \r
59 \r
60 \r
61 typedef struct {\r
62         SOCKET Socket;\r
63         int FdConnect;\r
64         int FdClose;\r
65         int FdAccept;\r
66         int FdRead;\r
67         int FdWrite;\r
68         int Error;\r
69 } ASYNCSIGNAL;\r
70 \r
71 \r
72 typedef struct {\r
73         HANDLE Async;\r
74         int Done;\r
75         int ErrorDb;\r
76 } ASYNCSIGNALDATABASE;\r
77 \r
78 \r
79 // スレッド衝突のバグ修正\r
80 // 念のためテーブルを増量\r
81 //#define MAX_SIGNAL_ENTRY              10\r
82 //#define MAX_SIGNAL_ENTRY_DBASE        5\r
83 #define MAX_SIGNAL_ENTRY                16\r
84 #define MAX_SIGNAL_ENTRY_DBASE  16\r
85 \r
86 \r
87 \r
88 \r
89 /*===== プロトタイプ =====*/\r
90 \r
91 static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);\r
92 static int AskAsyncDone(SOCKET s, int *Error, int Mask);\r
93 static int AskAsyncDoneDbase(HANDLE Async, int *Error);\r
94 static int RegistAsyncTable(SOCKET s);\r
95 static int RegistAsyncTableDbase(HANDLE Async);\r
96 static int UnRegistAsyncTable(SOCKET s);\r
97 static int UnRegistAsyncTableDbase(HANDLE Async);\r
98 \r
99 \r
100 /*===== 外部参照 =====*/\r
101 \r
102 extern int TimeOut;\r
103 \r
104 \r
105 /*===== ローカルなワーク =====*/\r
106 \r
107 static const char SocketWndClass[] = "FFFTPSocketWnd";\r
108 static HWND hWndSocket;\r
109 \r
110 static ASYNCSIGNAL Signal[MAX_SIGNAL_ENTRY];\r
111 static ASYNCSIGNALDATABASE SignalDbase[MAX_SIGNAL_ENTRY_DBASE];\r
112 \r
113 //static HANDLE hAsyncTblAccMutex;\r
114 // スレッド衝突のバグ修正\r
115 static HANDLE hAsyncTblAccMutex;\r
116 \r
117 \r
118 \r
119 \r
120 \r
121 /*----- \r
122 *\r
123 *       Parameter\r
124 *\r
125 *       Return Value\r
126 *               int ステータス\r
127 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
128 *----------------------------------------------------------------------------*/\r
129 \r
130 int MakeSocketWin(HWND hWnd, HINSTANCE hInst)\r
131 {\r
132         int i;\r
133         int Sts;\r
134         WNDCLASSEX wClass;\r
135 \r
136         wClass.cbSize        = sizeof(WNDCLASSEX);\r
137         wClass.style         = 0;\r
138         wClass.lpfnWndProc   = SocketWndProc;\r
139         wClass.cbClsExtra    = 0;\r
140         wClass.cbWndExtra    = 0;\r
141         wClass.hInstance     = hInst;\r
142         wClass.hIcon         = NULL;\r
143         wClass.hCursor       = NULL;\r
144         wClass.hbrBackground = (HBRUSH)CreateSolidBrush(GetSysColor(COLOR_INFOBK));\r
145         wClass.lpszMenuName  = NULL;\r
146         wClass.lpszClassName = SocketWndClass;\r
147         wClass.hIconSm       = NULL;\r
148         RegisterClassEx(&wClass);\r
149 \r
150         Sts = FFFTP_FAIL;\r
151         hWndSocket = CreateWindowEx(0, SocketWndClass, NULL,\r
152                         WS_BORDER | WS_POPUP,\r
153                         0, 0, 0, 0,\r
154                         hWnd, NULL, hInst, NULL);\r
155 \r
156         if(hWndSocket != NULL)\r
157         {\r
158 //              hAsyncTblAccMutex = CreateMutex(NULL, FALSE, NULL);\r
159 \r
160                 // スレッド衝突のバグ修正\r
161 //              for(i = 0; i < MAX_SIGNAL_ENTRY; i++)\r
162 //                      Signal[i].Socket = INVALID_SOCKET;\r
163 //              for(i = 0; i < MAX_SIGNAL_ENTRY_DBASE; i++)\r
164 //                      SignalDbase[i].Async = 0;\r
165                 if(hAsyncTblAccMutex = CreateMutex(NULL, FALSE, NULL))\r
166                 {\r
167                         for(i = 0; i < MAX_SIGNAL_ENTRY; i++)\r
168                                 Signal[i].Socket = INVALID_SOCKET;\r
169                         for(i = 0; i < MAX_SIGNAL_ENTRY_DBASE; i++)\r
170                                 SignalDbase[i].Async = 0;\r
171                 }\r
172                 Sts = FFFTP_SUCCESS;\r
173         }\r
174         return(Sts);\r
175 }\r
176 \r
177 \r
178 /*----- \r
179 *\r
180 *       Parameter\r
181 *               なし\r
182 *\r
183 *       Return Value\r
184 *               なし\r
185 *----------------------------------------------------------------------------*/\r
186 \r
187 void DeleteSocketWin(void)\r
188 {\r
189 //      CloseHandle(hAsyncTblAccMutex);\r
190         // スレッド衝突のバグ修正\r
191         CloseHandle(hAsyncTblAccMutex);\r
192         hAsyncTblAccMutex = NULL;\r
193 \r
194         if(hWndSocket != NULL)\r
195                 DestroyWindow(hWndSocket);\r
196         return;\r
197 }\r
198 \r
199 \r
200 /*----- \r
201 *\r
202 *       Parameter\r
203 *               HWND hWnd : ウインドウハンドル\r
204 *               UINT message : メッセージ番号\r
205 *               WPARAM wParam : メッセージの WPARAM 引数\r
206 *               LPARAM lParam : メッセージの LPARAM 引数\r
207 *\r
208 *       Return Value\r
209 *               BOOL TRUE/FALSE\r
210 *----------------------------------------------------------------------------*/\r
211 \r
212 static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
213 {\r
214         int Pos;\r
215 \r
216         switch(message)\r
217         {\r
218                 case WM_ASYNC_SOCKET :\r
219                         // スレッド衝突のバグ修正\r
220                         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
221                         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
222                         {\r
223                                 if(Signal[Pos].Socket == (SOCKET)wParam)\r
224                                 {\r
225                                         Signal[Pos].Error = WSAGETSELECTERROR(lParam);\r
226 #if DBG_MSG\r
227                                         if(WSAGETSELECTERROR(lParam) != 0)\r
228                                                 DoPrintf("####### Signal: error (%d)", WSAGETSELECTERROR(lParam));\r
229 #endif\r
230 \r
231                                         switch(WSAGETSELECTEVENT(lParam))\r
232                                         {\r
233                                                 case FD_CONNECT :\r
234                                                         Signal[Pos].FdConnect = 1;\r
235 #if DBG_MSG\r
236                                                         DoPrintf("####### Signal: connect (S=%x)", Signal[Pos].Socket);\r
237 #endif\r
238                                                         break;\r
239 \r
240                                                 case FD_CLOSE :\r
241                                                         Signal[Pos].FdClose = 1;\r
242 #if DBG_MSG\r
243                                                         DoPrintf("####### Signal: close (S=%x)", Signal[Pos].Socket);\r
244 #endif\r
245 //SetTaskMsg("####### Signal: close (%d) (S=%x)", Pos, Signal[Pos].Socket);\r
246                                                         break;\r
247 \r
248                                                 case FD_ACCEPT :\r
249                                                         Signal[Pos].FdAccept = 1;\r
250 #if DBG_MSG\r
251                                                         DoPrintf("####### Signal: accept (S=%x)", Signal[Pos].Socket);\r
252 #endif\r
253                                                         break;\r
254 \r
255                                                 case FD_READ :\r
256                                                         Signal[Pos].FdRead = 1;\r
257 #if DBG_MSG\r
258                                                         DoPrintf("####### Signal: read (S=%x)", Signal[Pos].Socket);\r
259 #endif\r
260                                                         break;\r
261 \r
262                                                 case FD_WRITE :\r
263                                                         Signal[Pos].FdWrite = 1;\r
264 #if DBG_MSG\r
265                                                         DoPrintf("####### Signal: write (S=%x)", Signal[Pos].Socket);\r
266 #endif\r
267                                                         break;\r
268                                         }\r
269                                         break;\r
270                                 }\r
271                         }\r
272                         // スレッド衝突のバグ修正\r
273                         ReleaseMutex(hAsyncTblAccMutex);\r
274                         break;\r
275 \r
276                 case WM_ASYNC_DBASE :\r
277                         // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり\r
278                         RegistAsyncTableDbase((HANDLE)wParam);\r
279                         // スレッド衝突のバグ修正\r
280                         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
281                         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
282                         {\r
283                                 if(SignalDbase[Pos].Async == (HANDLE)wParam)\r
284                                 {\r
285                                         if(HIWORD(lParam) != 0)\r
286                                         {\r
287                                                 SignalDbase[Pos].ErrorDb = 1;\r
288 #if DBG_MSG\r
289                                                 DoPrintf("##### SignalDatabase: error");\r
290 #endif\r
291                                         }\r
292                                         SignalDbase[Pos].Done = 1;\r
293 #if DBG_MSG\r
294                                         DoPrintf("##### SignalDatabase: Done");\r
295 #endif\r
296                                         break;\r
297                                 }\r
298                         }\r
299                         // スレッド衝突のバグ修正\r
300                         ReleaseMutex(hAsyncTblAccMutex);\r
301                         break;\r
302 \r
303                 default :\r
304                         return(DefWindowProc(hWnd, message, wParam, lParam));\r
305         }\r
306     return(0);\r
307 }\r
308 \r
309 \r
310 \r
311 \r
312 /*----- \r
313 *\r
314 *       Parameter\r
315 *               \r
316 *\r
317 *       Return Value\r
318 *               \r
319 *----------------------------------------------------------------------------*/\r
320 \r
321 static int AskAsyncDone(SOCKET s, int *Error, int Mask)\r
322 {\r
323         int Sts;\r
324         int Pos;\r
325 \r
326         // スレッド衝突のバグ修正\r
327         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
328         Sts = NO;\r
329         *Error = 0;\r
330         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
331         {\r
332                 if(Signal[Pos].Socket == s)\r
333                 {\r
334                         *Error = Signal[Pos].Error;\r
335                         if(Signal[Pos].Error != 0)\r
336                                 Sts = YES;\r
337                         if((Mask & FD_CONNECT) && (Signal[Pos].FdConnect != 0))\r
338                         {\r
339                                 Sts = YES;\r
340 #if DBG_MSG\r
341                                 DoPrintf("### Ask: connect (Sts=%d, Error=%d)", Sts, *Error);\r
342 #endif\r
343                         }\r
344                         if((Mask & FD_CLOSE) && (Signal[Pos].FdClose != 0))\r
345 //                      if(Mask & FD_CLOSE)\r
346                         {\r
347                                 Sts = YES;\r
348 #if DBG_MSG\r
349                                 DoPrintf("### Ask: close (Sts=%d, Error=%d)", Sts, *Error);\r
350 #endif\r
351                         }\r
352                         if((Mask & FD_ACCEPT) && (Signal[Pos].FdAccept != 0))\r
353                         {\r
354                                 Signal[Pos].FdAccept = 0;\r
355                                 Sts = YES;\r
356 #if DBG_MSG\r
357                                 DoPrintf("### Ask: accept (Sts=%d, Error=%d)", Sts, *Error);\r
358 #endif\r
359                         }\r
360                         if((Mask & FD_READ) && (Signal[Pos].FdRead != 0))\r
361                         {\r
362                                 Signal[Pos].FdRead = 0;\r
363                                 Sts = YES;\r
364 #if DBG_MSG\r
365                                 DoPrintf("### Ask: read (Sts=%d, Error=%d)", Sts, *Error);\r
366 #endif\r
367                         }\r
368                         if((Mask & FD_WRITE) && (Signal[Pos].FdWrite != 0))\r
369                         {\r
370                                 Signal[Pos].FdWrite = 0;\r
371                                 Sts = YES;\r
372 #if DBG_MSG\r
373                                 DoPrintf("### Ask: write (Sts=%d, Error=%d)", Sts, *Error);\r
374 #endif\r
375                         }\r
376                         break;\r
377                 }\r
378         }\r
379         // スレッド衝突のバグ修正\r
380         ReleaseMutex(hAsyncTblAccMutex);\r
381 \r
382         if(Pos == MAX_SIGNAL_ENTRY)\r
383         {\r
384                 if(Mask & FD_CLOSE)\r
385                 {\r
386                                 Sts = YES;\r
387                 }\r
388                 else\r
389                 {\r
390                         MessageBox(GetMainHwnd(), "AskAsyncDone called with unregisterd socket.", "FFFTP inner error", MB_OK);\r
391                         exit(1);\r
392                 }\r
393         }\r
394         return(Sts);\r
395 }\r
396 \r
397 \r
398 /*----- \r
399 *\r
400 *       Parameter\r
401 *               \r
402 *\r
403 *       Return Value\r
404 *               \r
405 *----------------------------------------------------------------------------*/\r
406 \r
407 static int AskAsyncDoneDbase(HANDLE Async, int *Error)\r
408 {\r
409         int Sts;\r
410         int Pos;\r
411 \r
412         // スレッド衝突のバグ修正\r
413         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
414         Sts = NO;\r
415         *Error = 0;\r
416         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
417         {\r
418                 if(SignalDbase[Pos].Async == Async)\r
419                 {\r
420                         if(SignalDbase[Pos].Done != 0)\r
421                         {\r
422                                 *Error = SignalDbase[Pos].ErrorDb;\r
423                                 Sts = YES;\r
424 #if DBG_MSG\r
425                                 DoPrintf("### Ask: Dbase (Sts=%d, Error=%d)", Sts, *Error);\r
426 #endif\r
427                         }\r
428                         break;\r
429                 }\r
430         }\r
431         // スレッド衝突のバグ修正\r
432         ReleaseMutex(hAsyncTblAccMutex);\r
433 \r
434         if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
435         {\r
436                 MessageBox(GetMainHwnd(), "AskAsyncDoneDbase called with unregisterd handle.", "FFFTP inner error", MB_OK);\r
437                 exit(1);\r
438         }\r
439         return(Sts);\r
440 }\r
441 \r
442 \r
443 \r
444 /*----- \r
445 *\r
446 *       Parameter\r
447 *               \r
448 *\r
449 *       Return Value\r
450 *               \r
451 *----------------------------------------------------------------------------*/\r
452 \r
453 static int RegistAsyncTable(SOCKET s)\r
454 {\r
455         int Sts;\r
456         int Pos;\r
457 \r
458         // スレッド衝突のバグ修正\r
459         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
460         Sts = NO;\r
461         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
462         {\r
463                 if(Signal[Pos].Socket == s)\r
464                 {\r
465                         // 強制的に閉じられたソケットがあると重複する可能性あり\r
466 //                      MessageBox(GetMainHwnd(), "Async socket already registerd.", "FFFTP inner error", MB_OK);\r
467 //                      break;\r
468                         Signal[Pos].Socket = INVALID_SOCKET;\r
469                 }\r
470         }\r
471         // スレッド衝突のバグ修正\r
472         ReleaseMutex(hAsyncTblAccMutex);\r
473 \r
474         if(Pos == MAX_SIGNAL_ENTRY)\r
475         {\r
476                 // スレッド衝突のバグ修正\r
477                 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
478                 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
479                 {\r
480                         if(Signal[Pos].Socket == INVALID_SOCKET)\r
481                         {\r
482 \r
483 //SetTaskMsg("############### Regist socket (%d)", Pos);\r
484 \r
485                                 Signal[Pos].Socket = s;\r
486                                 Signal[Pos].Error = 0;\r
487                                 Signal[Pos].FdConnect = 0;\r
488                                 Signal[Pos].FdClose = 0;\r
489                                 Signal[Pos].FdAccept = 0;\r
490                                 Signal[Pos].FdRead = 0;\r
491                                 Signal[Pos].FdWrite = 0;\r
492                                 Sts = YES;\r
493                                 break;\r
494                         }\r
495                 }\r
496                 // スレッド衝突のバグ修正\r
497                 ReleaseMutex(hAsyncTblAccMutex);\r
498 \r
499                 if(Pos == MAX_SIGNAL_ENTRY)\r
500                 {\r
501                         MessageBox(GetMainHwnd(), "No more async regist space.", "FFFTP inner error", MB_OK);\r
502                         exit(1);\r
503                 }\r
504         }\r
505 \r
506         return(Sts);\r
507 }\r
508 \r
509 \r
510 /*----- \r
511 *\r
512 *       Parameter\r
513 *               \r
514 *\r
515 *       Return Value\r
516 *               \r
517 *----------------------------------------------------------------------------*/\r
518 \r
519 static int RegistAsyncTableDbase(HANDLE Async)\r
520 {\r
521         int Sts;\r
522         int Pos;\r
523 \r
524         // スレッド衝突のバグ修正\r
525         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
526         Sts = NO;\r
527         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
528         {\r
529                 if(SignalDbase[Pos].Async == Async)\r
530                 {\r
531                         // 強制的に閉じられたハンドルがあると重複する可能性あり\r
532 //                      MessageBox(GetMainHwnd(), "Async handle already registerd.", "FFFTP inner error", MB_OK);\r
533                         // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり\r
534                         break;\r
535                 }\r
536         }\r
537         // スレッド衝突のバグ修正\r
538         ReleaseMutex(hAsyncTblAccMutex);\r
539 \r
540         if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
541         {\r
542                 // スレッド衝突のバグ修正\r
543                 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
544                 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
545                 {\r
546                         if(SignalDbase[Pos].Async == 0)\r
547                         {\r
548 \r
549 //SetTaskMsg("############### Regist dbase (%d)", Pos);\r
550 \r
551                                 SignalDbase[Pos].Async = Async;\r
552                                 SignalDbase[Pos].Done = 0;\r
553                                 SignalDbase[Pos].ErrorDb = 0;\r
554                                 Sts = YES;\r
555                                 break;\r
556                         }\r
557                 }\r
558                 // スレッド衝突のバグ修正\r
559                 ReleaseMutex(hAsyncTblAccMutex);\r
560 \r
561                 if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
562                 {\r
563                         MessageBox(GetMainHwnd(), "No more async dbase regist space.", "FFFTP inner error", MB_OK);\r
564                         exit(1);\r
565                 }\r
566         }\r
567 \r
568         return(Sts);\r
569 }\r
570 \r
571 \r
572 /*----- \r
573 *\r
574 *       Parameter\r
575 *               \r
576 *\r
577 *       Return Value\r
578 *               \r
579 *----------------------------------------------------------------------------*/\r
580 \r
581 static int UnRegistAsyncTable(SOCKET s)\r
582 {\r
583         int Sts;\r
584         int Pos;\r
585 \r
586         // スレッド衝突のバグ修正\r
587         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
588         Sts = NO;\r
589         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
590         {\r
591                 if(Signal[Pos].Socket == s)\r
592                 {\r
593 \r
594 //SetTaskMsg("############### UnRegist socket (%d)", Pos);\r
595 \r
596                         Signal[Pos].Socket = INVALID_SOCKET;\r
597                         Sts = YES;\r
598                         break;\r
599                 }\r
600         }\r
601         // スレッド衝突のバグ修正\r
602         ReleaseMutex(hAsyncTblAccMutex);\r
603         return(Sts);\r
604 }\r
605 \r
606 \r
607 /*----- \r
608 *\r
609 *       Parameter\r
610 *               \r
611 *\r
612 *       Return Value\r
613 *               \r
614 *----------------------------------------------------------------------------*/\r
615 \r
616 static int UnRegistAsyncTableDbase(HANDLE Async)\r
617 {\r
618         int Sts;\r
619         int Pos;\r
620 \r
621         // スレッド衝突のバグ修正\r
622         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
623         Sts = NO;\r
624         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
625         {\r
626                 if(SignalDbase[Pos].Async == Async)\r
627                 {\r
628 \r
629 //SetTaskMsg("############### UnRegist dbase (%d)", Pos);\r
630 \r
631                         SignalDbase[Pos].Async = 0;\r
632                         Sts = YES;\r
633                         break;\r
634                 }\r
635         }\r
636         // スレッド衝突のバグ修正\r
637         ReleaseMutex(hAsyncTblAccMutex);\r
638         return(Sts);\r
639 }\r
640 \r
641 \r
642 \r
643 \r
644 \r
645 \r
646 \r
647 \r
648 // IPv6対応\r
649 //struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *CancelCheckWork)\r
650 struct hostent *do_gethostbynameIPv4(const char *Name, char *Buf, int Len, int *CancelCheckWork)\r
651 {\r
652 #if USE_THIS\r
653         struct hostent *Ret;\r
654         HANDLE hAsync;\r
655         int Error;\r
656 \r
657 #if DBG_MSG\r
658         DoPrintf("# Start gethostbyname");\r
659 #endif\r
660         Ret = NULL;\r
661         // 同時接続対応\r
662 //      *CancelCheckWork = NO;\r
663 \r
664         // UTF-8対応\r
665 //      hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
666         hAsync = WSAAsyncGetHostByNameM(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
667         if(hAsync != NULL)\r
668         {\r
669                 RegistAsyncTableDbase(hAsync);\r
670                 while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))\r
671                 {\r
672                         Sleep(1);\r
673                         if(BackgrndMessageProc() == YES)\r
674                                 *CancelCheckWork = YES;\r
675                 }\r
676 \r
677                 if(*CancelCheckWork == YES)\r
678                 {\r
679                         WSACancelAsyncRequest(hAsync);\r
680                 }\r
681                 else if(Error == 0)\r
682                 {\r
683                         Ret = (struct hostent *)Buf;\r
684                 }\r
685                 UnRegistAsyncTableDbase(hAsync);\r
686         }\r
687         return(Ret);\r
688 #else\r
689         return(gethostbyname(Name));\r
690 #endif\r
691 }\r
692 \r
693 \r
694 struct hostent *do_gethostbynameIPv6(const char *Name, char *Buf, int Len, int *CancelCheckWork)\r
695 {\r
696 #if USE_THIS\r
697         struct hostent *Ret;\r
698         HANDLE hAsync;\r
699         int Error;\r
700 \r
701 #if DBG_MSG\r
702         DoPrintf("# Start gethostbyname");\r
703 #endif\r
704         Ret = NULL;\r
705         // 同時接続対応\r
706 //      *CancelCheckWork = NO;\r
707 \r
708         // UTF-8対応\r
709 //      hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
710         hAsync = WSAAsyncGetHostByNameIPv6M(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len, AF_INET6);\r
711         if(hAsync != NULL)\r
712         {\r
713                 RegistAsyncTableDbase(hAsync);\r
714                 while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))\r
715                 {\r
716                         Sleep(1);\r
717                         if(BackgrndMessageProc() == YES)\r
718                                 *CancelCheckWork = YES;\r
719                 }\r
720 \r
721                 if(*CancelCheckWork == YES)\r
722                 {\r
723                         WSACancelAsyncRequest(hAsync);\r
724                 }\r
725                 else if(Error == 0)\r
726                 {\r
727                         Ret = (struct hostent *)Buf;\r
728                 }\r
729                 UnRegistAsyncTableDbase(hAsync);\r
730         }\r
731         return(Ret);\r
732 #else\r
733         return(gethostbyname(Name));\r
734 #endif\r
735 }\r
736 \r
737 \r
738 \r
739 \r
740 \r
741 SOCKET do_socket(int af, int type, int protocol)\r
742 {\r
743         SOCKET Ret;\r
744 \r
745         Ret = socket(af, type, protocol);\r
746         if(Ret != INVALID_SOCKET)\r
747         {\r
748                 RegistAsyncTable(Ret);\r
749         }\r
750 #if DBG_MSG\r
751         DoPrintf("# do_socket (S=%x)", Ret);\r
752 #endif\r
753         return(Ret);\r
754 }\r
755 \r
756 \r
757 \r
758 int do_closesocket(SOCKET s)\r
759 {\r
760 #if USE_THIS\r
761         int Ret;\r
762         int Error;\r
763         int CancelCheckWork;\r
764 \r
765 #if DBG_MSG\r
766         DoPrintf("# Start close (S=%x)", s);\r
767 #endif\r
768         CancelCheckWork = NO;\r
769 \r
770         // スレッド衝突のバグ修正\r
771         WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
772         UnRegistAsyncTable(s);\r
773         // FTPS対応\r
774 //      Ret = closesocket(s);\r
775         Ret = FTPS_closesocket(s);\r
776         if(Ret == SOCKET_ERROR)\r
777         {\r
778                 Error = 0;\r
779                 while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CLOSE) != YES))\r
780                 {\r
781                         Sleep(1);\r
782                         if(BackgrndMessageProc() == YES)\r
783                                 CancelCheckWork = YES;\r
784                 }\r
785 \r
786                 if((CancelCheckWork == NO) && (Error == 0))\r
787                         Ret = 0;\r
788         }\r
789 \r
790         // スレッド衝突のバグ修正\r
791 //      WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
792         if(BackgrndMessageProc() == YES)\r
793                 CancelCheckWork = YES;\r
794         // スレッド衝突のバグ修正\r
795 //      UnRegistAsyncTable(s);\r
796 \r
797 #if DBG_MSG\r
798         DoPrintf("# Exit close");\r
799 #endif\r
800         return(Ret);\r
801 #else\r
802         return(closesocket(s));\r
803 #endif\r
804 }\r
805 \r
806 \r
807 \r
808 \r
809 \r
810 \r
811 int do_connect(SOCKET s, const struct sockaddr *name, int namelen, int *CancelCheckWork)\r
812 {\r
813 #if USE_THIS\r
814         int Ret;\r
815         int Error;\r
816 \r
817 #if DBG_MSG\r
818         DoPrintf("# Start connect (S=%x)", s);\r
819 #endif\r
820         // 同時接続対応\r
821 //      *CancelCheckWork = NO;\r
822 \r
823 #if DBG_MSG\r
824         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
825 #endif\r
826         // 高速化のためFD_READとFD_WRITEを使用しない\r
827 //      Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
828         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT);\r
829         if(Ret != SOCKET_ERROR)\r
830         {\r
831                 Ret = connect(s, name, namelen);\r
832                 if(Ret == SOCKET_ERROR)\r
833                 {\r
834                         do\r
835                         {\r
836                                 Error = 0;\r
837                                 while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CONNECT) != YES))\r
838                                 {\r
839                                         Sleep(1);\r
840                                         if(BackgrndMessageProc() == YES)\r
841                                                 *CancelCheckWork = YES;\r
842                                 }\r
843 \r
844                                 if(*CancelCheckWork == YES)\r
845                                         break;\r
846                                 if(Error == 0)\r
847                                         Ret = 0;\r
848                                 else\r
849                                 {\r
850 //                                      Error = WSAGetLastError();\r
851                                         DoPrintf("#### Connect: Error=%d", Error);\r
852                                 }\r
853                         }\r
854                         while((Ret != 0) && (Error == WSAEWOULDBLOCK));\r
855                 }\r
856         }\r
857         else\r
858                 DoPrintf("#### Connect: AsyncSelect error (%d)", WSAGetLastError());\r
859 \r
860 #if DBG_MSG\r
861         DoPrintf("# Exit connect (%d)", Ret);\r
862 #endif\r
863         return(Ret);\r
864 #else\r
865         return(connect(s, name, namelen));\r
866 #endif\r
867 }\r
868 \r
869 \r
870 \r
871 \r
872 \r
873 int do_listen(SOCKET s, int backlog)\r
874 {\r
875         int Ret;\r
876 \r
877         Ret = 1;\r
878 #if DBG_MSG\r
879         DoPrintf("# Start listen (S=%x)", s);\r
880         DoPrintf("## Async set: FD_CLOSE|FD_ACCEPT");\r
881 #endif\r
882 \r
883         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CLOSE | FD_ACCEPT);\r
884         if(Ret != SOCKET_ERROR)\r
885                 Ret = listen(s, backlog);\r
886 \r
887 #if DBG_MSG\r
888         DoPrintf("# Exit listen (%d)", Ret);\r
889 #endif\r
890         return(Ret);\r
891 }\r
892 \r
893 \r
894 \r
895 SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen)\r
896 {\r
897 #if USE_THIS\r
898         SOCKET Ret2;\r
899         int CancelCheckWork;\r
900         int Error;\r
901 \r
902 #if DBG_MSG\r
903         DoPrintf("# Start accept (S=%x)", s);\r
904 #endif\r
905         CancelCheckWork = NO;\r
906         Ret2 = INVALID_SOCKET;\r
907         Error = 0;\r
908 \r
909         while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_ACCEPT) != YES))\r
910         {\r
911                 if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)\r
912                 {\r
913                         Error = 1;\r
914                         break;\r
915                 }\r
916                 Sleep(1);\r
917                 if(BackgrndMessageProc() == YES)\r
918                         CancelCheckWork = YES;\r
919         }\r
920 \r
921         if((CancelCheckWork == NO) && (Error == 0))\r
922         {\r
923                 do\r
924                 {\r
925                         Ret2 = accept(s, addr, addrlen);\r
926                         if(Ret2 != INVALID_SOCKET)\r
927                         {\r
928 #if DBG_MSG\r
929                                 DoPrintf("## do_sccept (S=%x)", Ret2);\r
930                                 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
931 #endif\r
932                                 RegistAsyncTable(Ret2);\r
933                                 // 高速化のためFD_READとFD_WRITEを使用しない\r
934 //                              if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR)\r
935                                 if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT) == SOCKET_ERROR)\r
936                                 {\r
937                                         do_closesocket(Ret2);\r
938                                         Ret2 = INVALID_SOCKET;\r
939                                 }\r
940                                 break;\r
941                         }\r
942                         Error = WSAGetLastError();\r
943                         Sleep(1);\r
944                         if(BackgrndMessageProc() == YES)\r
945                                 break;\r
946                 }\r
947                 while(Error == WSAEWOULDBLOCK);\r
948         }\r
949 \r
950 #if DBG_MSG\r
951         DoPrintf("# Exit accept");\r
952 #endif\r
953         return(Ret2);\r
954 #else\r
955         return(accept(s, addr, addrlen));\r
956 #endif\r
957 }\r
958 \r
959 \r
960 \r
961 \r
962 /*----- recv相当の関数 --------------------------------------------------------\r
963 *\r
964 *       Parameter\r
965 *               SOCKET s : ソケット\r
966 *               char *buf : データを読み込むバッファ\r
967 *               int len : 長さ\r
968 *               int flags : recvに与えるフラグ\r
969 *               int *TimeOutErr : タイムアウトしたかどうかを返すワーク\r
970 *\r
971 *       Return Value\r
972 *               int : recvの戻り値と同じ\r
973 *\r
974 *       Note\r
975 *               タイムアウトの時は TimeOut=YES、Ret=SOCKET_ERROR になる\r
976 *----------------------------------------------------------------------------*/\r
977 int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
978 {\r
979 #if USE_THIS\r
980         int Ret;\r
981         time_t StartTime;\r
982         time_t ElapseTime;\r
983         int Error;\r
984 \r
985 #if DBG_MSG\r
986         DoPrintf("# Start recv (S=%x)", s);\r
987 #endif\r
988         *TimeOutErr = NO;\r
989         // 同時接続対応\r
990 //      *CancelCheckWork = NO;\r
991         Ret = SOCKET_ERROR;\r
992         Error = 0;\r
993 \r
994         if(TimeOut != 0)\r
995                 time(&StartTime);\r
996 \r
997         // FTPS対応\r
998         // OpenSSLでは受信確認はFD_READが複数回受信される可能性がある\r
999 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ) != YES))\r
1000         // 短時間にFD_READが2回以上通知される対策\r
1001 //      while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ) != YES))\r
1002 //      {\r
1003 //              if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)\r
1004 //              {\r
1005 //                      Ret = 0;\r
1006 //                      break;\r
1007 //              }\r
1008 //              Sleep(1);\r
1009 //              if(BackgrndMessageProc() == YES)\r
1010 //                      *CancelCheckWork = YES;\r
1011 //              else if(TimeOut != 0)\r
1012 //              {\r
1013 //                      time(&ElapseTime);\r
1014 //                      ElapseTime -= StartTime;\r
1015 //                      if(ElapseTime >= TimeOut)\r
1016 //                      {\r
1017 //                              DoPrintf("do_recv timed out");\r
1018 //                              *TimeOutErr = YES;\r
1019 //                              *CancelCheckWork = YES;\r
1020 //                      }\r
1021 //              }\r
1022 //      }\r
1023 \r
1024         if(/*(Ret != 0) && */(Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
1025         {\r
1026                 do\r
1027                 {\r
1028 #if DBG_MSG\r
1029                         DoPrintf("## recv()");\r
1030 #endif\r
1031 \r
1032                         // FTPS対応\r
1033 //                      Ret = recv(s, buf, len, flags);\r
1034                         Ret = FTPS_recv(s, buf, len, flags);\r
1035                         if(Ret != SOCKET_ERROR)\r
1036                                 break;\r
1037                         Error = WSAGetLastError();\r
1038                         Sleep(1);\r
1039                         if(BackgrndMessageProc() == YES)\r
1040                                 break;\r
1041                         // FTPS対応\r
1042                         // 受信確認をバイパスしたためここでタイムアウトの確認\r
1043                         if(BackgrndMessageProc() == YES)\r
1044                                 *CancelCheckWork = YES;\r
1045                         else if(TimeOut != 0)\r
1046                         {\r
1047                                 time(&ElapseTime);\r
1048                                 ElapseTime -= StartTime;\r
1049                                 if(ElapseTime >= TimeOut)\r
1050                                 {\r
1051                                         DoPrintf("do_recv timed out");\r
1052                                         *TimeOutErr = YES;\r
1053                                         *CancelCheckWork = YES;\r
1054                                 }\r
1055                         }\r
1056                         if(*CancelCheckWork == YES)\r
1057                                 break;\r
1058                 }\r
1059                 while(Error == WSAEWOULDBLOCK);\r
1060         }\r
1061 \r
1062         if(BackgrndMessageProc() == YES)\r
1063                 Ret = SOCKET_ERROR;\r
1064 \r
1065 #if DBG_MSG\r
1066         DoPrintf("# Exit recv (%d)", Ret);\r
1067 #endif\r
1068         return(Ret);\r
1069 #else\r
1070         return(recv(s, buf, len, flags));\r
1071 #endif\r
1072 }\r
1073 \r
1074 \r
1075 \r
1076 int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
1077 {\r
1078 #if USE_THIS\r
1079         int Ret;\r
1080         time_t StartTime;\r
1081         time_t ElapseTime;\r
1082         int Error;\r
1083 \r
1084 #if DBG_MSG\r
1085         DoPrintf("# Start send (S=%x)", s);\r
1086 #endif\r
1087         *TimeOutErr = NO;\r
1088         // 同時接続対応\r
1089 //      *CancelCheckWork = NO;\r
1090         Ret = SOCKET_ERROR;\r
1091         Error = 0;\r
1092 \r
1093         if(TimeOut != 0)\r
1094                 time(&StartTime);\r
1095 \r
1096 #if DBG_MSG\r
1097         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
1098 #endif\r
1099         // Windows 2000でFD_WRITEが通知されないことがあるバグ修正\r
1100         // 毎回通知されたのはNT 4.0までのバグであり仕様ではない\r
1101         // XP以降は互換性のためか毎回通知される\r
1102 //      WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
1103         if(BackgrndMessageProc() == YES)\r
1104                 *CancelCheckWork = YES;\r
1105 \r
1106         // FTPS対応\r
1107         // 送信バッファの空き確認には影響しないが念のため\r
1108 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE) != YES))\r
1109         // Windows 2000でFD_WRITEが通知されないことがあるバグ修正\r
1110 //      while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE) != YES))\r
1111 //      {\r
1112 //              if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)\r
1113 //              {\r
1114 //                      Error = 1;\r
1115 //                      break;\r
1116 //              }\r
1117 //\r
1118 //              Sleep(1);\r
1119 //              if(BackgrndMessageProc() == YES)\r
1120 //                      *CancelCheckWork = YES;\r
1121 //              else if(TimeOut != 0)\r
1122 //              {\r
1123 //                      time(&ElapseTime);\r
1124 //                      ElapseTime -= StartTime;\r
1125 //                      if(ElapseTime >= TimeOut)\r
1126 //                      {\r
1127 //                              DoPrintf("do_write timed out");\r
1128 //                              *TimeOutErr = YES;\r
1129 //                              *CancelCheckWork = YES;\r
1130 //                      }\r
1131 //              }\r
1132 //      }\r
1133 \r
1134         if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
1135         {\r
1136                 do\r
1137                 {\r
1138 #if DBG_MSG\r
1139                         DoPrintf("## send()");\r
1140 #endif\r
1141 \r
1142                         // FTPS対応\r
1143 //                      Ret = send(s, buf, len, flags);\r
1144                         Ret = FTPS_send(s, buf, len, flags);\r
1145                         if(Ret != SOCKET_ERROR)\r
1146                         {\r
1147 #if DBG_MSG\r
1148                                 DoPrintf("## send() OK");\r
1149 #endif\r
1150                                 break;\r
1151                         }\r
1152                         Error = WSAGetLastError();\r
1153                         Sleep(1);\r
1154                         if(BackgrndMessageProc() == YES)\r
1155                                 break;\r
1156                         // FTPS対応\r
1157                         // 送信バッファ確認をバイパスしたためここでタイムアウトの確認\r
1158                         if(BackgrndMessageProc() == YES)\r
1159                                 *CancelCheckWork = YES;\r
1160                         else if(TimeOut != 0)\r
1161                         {\r
1162                                 time(&ElapseTime);\r
1163                                 ElapseTime -= StartTime;\r
1164                                 if(ElapseTime >= TimeOut)\r
1165                                 {\r
1166                                         DoPrintf("do_recv timed out");\r
1167                                         *TimeOutErr = YES;\r
1168                                         *CancelCheckWork = YES;\r
1169                                 }\r
1170                         }\r
1171                         if(*CancelCheckWork == YES)\r
1172                                 break;\r
1173                 }\r
1174                 while(Error == WSAEWOULDBLOCK);\r
1175         }\r
1176 \r
1177         if(BackgrndMessageProc() == YES)\r
1178                 Ret = SOCKET_ERROR;\r
1179 \r
1180 #if DBG_MSG\r
1181         DoPrintf("# Exit send (%d)", Ret);\r
1182 #endif\r
1183         return(Ret);\r
1184 #else\r
1185         return(send(s, buf, len, flags));\r
1186 #endif\r
1187 }\r
1188 \r
1189 \r
1190 // 同時接続対応\r
1191 void RemoveReceivedData(SOCKET s)\r
1192 {\r
1193         char buf[1024];\r
1194         int len;\r
1195 //      int Error;\r
1196         while((len = FTPS_recv(s, buf, sizeof(buf), MSG_PEEK)) > 0)\r
1197         {\r
1198 //              AskAsyncDone(s, &Error, FD_READ);\r
1199                 FTPS_recv(s, buf, len, 0);\r
1200         }\r
1201 }\r
1202 \r
1203 \r
1204 /*----- \r
1205 *\r
1206 *       Parameter\r
1207 *\r
1208 *       Return Value\r
1209 *               int ステータス\r
1210 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1211 *----------------------------------------------------------------------------*/\r
1212 \r
1213 int CheckClosedAndReconnect(void)\r
1214 {\r
1215         int Error;\r
1216         int Sts;\r
1217 \r
1218 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");\r
1219 \r
1220         Sts = FFFTP_SUCCESS;\r
1221         if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE) == YES)\r
1222         {\r
1223                 Sts = ReConnectCmdSkt();\r
1224         }\r
1225         return(Sts);\r
1226 }\r
1227 \r
1228 \r
1229 \r
1230 // 同時接続対応\r
1231 int CheckClosedAndReconnectTrnSkt(SOCKET *Skt, int *CancelCheckWork)\r
1232 {\r
1233         int Error;\r
1234         int Sts;\r
1235 \r
1236 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");\r
1237 \r
1238         Sts = FFFTP_SUCCESS;\r
1239         if(AskAsyncDone(*Skt, &Error, FD_CLOSE) == YES)\r
1240         {\r
1241                 Sts = ReConnectTrnSkt(Skt, CancelCheckWork);\r
1242         }\r
1243         return(Sts);\r
1244 }\r
1245 \r