OSDN Git Service

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