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                         // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり\r
275                         RegistAsyncTableDbase((HANDLE)wParam);\r
276                         // スレッド衝突のバグ修正\r
277                         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
278                         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
279                         {\r
280                                 if(SignalDbase[Pos].Async == (HANDLE)wParam)\r
281                                 {\r
282                                         if(HIWORD(lParam) != 0)\r
283                                         {\r
284                                                 SignalDbase[Pos].ErrorDb = 1;\r
285 #if DBG_MSG\r
286                                                 DoPrintf("##### SignalDatabase: error");\r
287 #endif\r
288                                         }\r
289                                         SignalDbase[Pos].Done = 1;\r
290 #if DBG_MSG\r
291                                         DoPrintf("##### SignalDatabase: Done");\r
292 #endif\r
293                                         break;\r
294                                 }\r
295                         }\r
296                         // スレッド衝突のバグ修正\r
297                         ReleaseMutex(hAsyncTblAccMutex);\r
298                         break;\r
299 \r
300                 default :\r
301                         return(DefWindowProc(hWnd, message, wParam, lParam));\r
302         }\r
303     return(0);\r
304 }\r
305 \r
306 \r
307 \r
308 \r
309 /*----- \r
310 *\r
311 *       Parameter\r
312 *               \r
313 *\r
314 *       Return Value\r
315 *               \r
316 *----------------------------------------------------------------------------*/\r
317 \r
318 static int AskAsyncDone(SOCKET s, int *Error, int Mask)\r
319 {\r
320         int Sts;\r
321         int Pos;\r
322 \r
323         // スレッド衝突のバグ修正\r
324         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
325         Sts = NO;\r
326         *Error = 0;\r
327         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
328         {\r
329                 if(Signal[Pos].Socket == s)\r
330                 {\r
331                         *Error = Signal[Pos].Error;\r
332                         if(Signal[Pos].Error != 0)\r
333                                 Sts = YES;\r
334                         if((Mask & FD_CONNECT_BIT) && (Signal[Pos].FdConnect != 0))\r
335                         {\r
336                                 Sts = YES;\r
337 #if DBG_MSG\r
338                                 DoPrintf("### Ask: connect (Sts=%d, Error=%d)", Sts, *Error);\r
339 #endif\r
340                         }\r
341                         if((Mask & FD_CLOSE_BIT) && (Signal[Pos].FdClose != 0))\r
342 //                      if(Mask & FD_CLOSE_BIT)\r
343                         {\r
344                                 Sts = YES;\r
345 #if DBG_MSG\r
346                                 DoPrintf("### Ask: close (Sts=%d, Error=%d)", Sts, *Error);\r
347 #endif\r
348                         }\r
349                         if((Mask & FD_ACCEPT_BIT) && (Signal[Pos].FdAccept != 0))\r
350                         {\r
351                                 Signal[Pos].FdAccept = 0;\r
352                                 Sts = YES;\r
353 #if DBG_MSG\r
354                                 DoPrintf("### Ask: accept (Sts=%d, Error=%d)", Sts, *Error);\r
355 #endif\r
356                         }\r
357                         if((Mask & FD_READ_BIT) && (Signal[Pos].FdRead != 0))\r
358                         {\r
359                                 Signal[Pos].FdRead = 0;\r
360                                 Sts = YES;\r
361 #if DBG_MSG\r
362                                 DoPrintf("### Ask: read (Sts=%d, Error=%d)", Sts, *Error);\r
363 #endif\r
364                         }\r
365                         if((Mask & FD_WRITE_BIT) && (Signal[Pos].FdWrite != 0))\r
366                         {\r
367                                 Signal[Pos].FdWrite = 0;\r
368                                 Sts = YES;\r
369 #if DBG_MSG\r
370                                 DoPrintf("### Ask: write (Sts=%d, Error=%d)", Sts, *Error);\r
371 #endif\r
372                         }\r
373                         break;\r
374                 }\r
375         }\r
376         // スレッド衝突のバグ修正\r
377         ReleaseMutex(hAsyncTblAccMutex);\r
378 \r
379         if(Pos == MAX_SIGNAL_ENTRY)\r
380         {\r
381                 if(Mask & FD_CLOSE_BIT)\r
382                 {\r
383                                 Sts = YES;\r
384                 }\r
385                 else\r
386                 {\r
387                         MessageBox(GetMainHwnd(), "AskAsyncDone called with unregisterd socket.", "FFFTP inner error", MB_OK);\r
388                         exit(1);\r
389                 }\r
390         }\r
391         return(Sts);\r
392 }\r
393 \r
394 \r
395 /*----- \r
396 *\r
397 *       Parameter\r
398 *               \r
399 *\r
400 *       Return Value\r
401 *               \r
402 *----------------------------------------------------------------------------*/\r
403 \r
404 static int AskAsyncDoneDbase(HANDLE Async, int *Error)\r
405 {\r
406         int Sts;\r
407         int Pos;\r
408 \r
409         // スレッド衝突のバグ修正\r
410         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
411         Sts = NO;\r
412         *Error = 0;\r
413         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
414         {\r
415                 if(SignalDbase[Pos].Async == Async)\r
416                 {\r
417                         if(SignalDbase[Pos].Done != 0)\r
418                         {\r
419                                 *Error = SignalDbase[Pos].ErrorDb;\r
420                                 Sts = YES;\r
421 #if DBG_MSG\r
422                                 DoPrintf("### Ask: Dbase (Sts=%d, Error=%d)", Sts, *Error);\r
423 #endif\r
424                         }\r
425                         break;\r
426                 }\r
427         }\r
428         // スレッド衝突のバグ修正\r
429         ReleaseMutex(hAsyncTblAccMutex);\r
430 \r
431         if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
432         {\r
433                 MessageBox(GetMainHwnd(), "AskAsyncDoneDbase called with unregisterd handle.", "FFFTP inner error", MB_OK);\r
434                 exit(1);\r
435         }\r
436         return(Sts);\r
437 }\r
438 \r
439 \r
440 \r
441 /*----- \r
442 *\r
443 *       Parameter\r
444 *               \r
445 *\r
446 *       Return Value\r
447 *               \r
448 *----------------------------------------------------------------------------*/\r
449 \r
450 static int RegistAsyncTable(SOCKET s)\r
451 {\r
452         int Sts;\r
453         int Pos;\r
454 \r
455         // スレッド衝突のバグ修正\r
456         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
457         Sts = NO;\r
458         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
459         {\r
460                 if(Signal[Pos].Socket == s)\r
461                 {\r
462                         // 強制的に閉じられたソケットがあると重複する可能性あり\r
463 //                      MessageBox(GetMainHwnd(), "Async socket already registerd.", "FFFTP inner error", MB_OK);\r
464 //                      break;\r
465                         Signal[Pos].Socket = INVALID_SOCKET;\r
466                 }\r
467         }\r
468         // スレッド衝突のバグ修正\r
469         ReleaseMutex(hAsyncTblAccMutex);\r
470 \r
471         if(Pos == MAX_SIGNAL_ENTRY)\r
472         {\r
473                 // スレッド衝突のバグ修正\r
474                 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
475                 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
476                 {\r
477                         if(Signal[Pos].Socket == INVALID_SOCKET)\r
478                         {\r
479 \r
480 //SetTaskMsg("############### Regist socket (%d)", Pos);\r
481 \r
482                                 Signal[Pos].Socket = s;\r
483                                 Signal[Pos].Error = 0;\r
484                                 Signal[Pos].FdConnect = 0;\r
485                                 Signal[Pos].FdClose = 0;\r
486                                 Signal[Pos].FdAccept = 0;\r
487                                 Signal[Pos].FdRead = 0;\r
488                                 Signal[Pos].FdWrite = 0;\r
489                                 Sts = YES;\r
490                                 break;\r
491                         }\r
492                 }\r
493                 // スレッド衝突のバグ修正\r
494                 ReleaseMutex(hAsyncTblAccMutex);\r
495 \r
496                 if(Pos == MAX_SIGNAL_ENTRY)\r
497                 {\r
498                         MessageBox(GetMainHwnd(), "No more async regist space.", "FFFTP inner error", MB_OK);\r
499                         exit(1);\r
500                 }\r
501         }\r
502 \r
503         return(Sts);\r
504 }\r
505 \r
506 \r
507 /*----- \r
508 *\r
509 *       Parameter\r
510 *               \r
511 *\r
512 *       Return Value\r
513 *               \r
514 *----------------------------------------------------------------------------*/\r
515 \r
516 static int RegistAsyncTableDbase(HANDLE Async)\r
517 {\r
518         int Sts;\r
519         int Pos;\r
520 \r
521         // スレッド衝突のバグ修正\r
522         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
523         Sts = NO;\r
524         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
525         {\r
526                 if(SignalDbase[Pos].Async == Async)\r
527                 {\r
528                         // 強制的に閉じられたハンドルがあると重複する可能性あり\r
529 //                      MessageBox(GetMainHwnd(), "Async handle already registerd.", "FFFTP inner error", MB_OK);\r
530                         // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり\r
531                         break;\r
532                 }\r
533         }\r
534         // スレッド衝突のバグ修正\r
535         ReleaseMutex(hAsyncTblAccMutex);\r
536 \r
537         if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
538         {\r
539                 // スレッド衝突のバグ修正\r
540                 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
541                 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
542                 {\r
543                         if(SignalDbase[Pos].Async == 0)\r
544                         {\r
545 \r
546 //SetTaskMsg("############### Regist dbase (%d)", Pos);\r
547 \r
548                                 SignalDbase[Pos].Async = Async;\r
549                                 SignalDbase[Pos].Done = 0;\r
550                                 SignalDbase[Pos].ErrorDb = 0;\r
551                                 Sts = YES;\r
552                                 break;\r
553                         }\r
554                 }\r
555                 // スレッド衝突のバグ修正\r
556                 ReleaseMutex(hAsyncTblAccMutex);\r
557 \r
558                 if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
559                 {\r
560                         MessageBox(GetMainHwnd(), "No more async dbase regist space.", "FFFTP inner error", MB_OK);\r
561                         exit(1);\r
562                 }\r
563         }\r
564 \r
565         return(Sts);\r
566 }\r
567 \r
568 \r
569 /*----- \r
570 *\r
571 *       Parameter\r
572 *               \r
573 *\r
574 *       Return Value\r
575 *               \r
576 *----------------------------------------------------------------------------*/\r
577 \r
578 static int UnRegistAsyncTable(SOCKET s)\r
579 {\r
580         int Sts;\r
581         int Pos;\r
582 \r
583         // スレッド衝突のバグ修正\r
584         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
585         Sts = NO;\r
586         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
587         {\r
588                 if(Signal[Pos].Socket == s)\r
589                 {\r
590 \r
591 //SetTaskMsg("############### UnRegist socket (%d)", Pos);\r
592 \r
593                         Signal[Pos].Socket = INVALID_SOCKET;\r
594                         Sts = YES;\r
595                         break;\r
596                 }\r
597         }\r
598         // スレッド衝突のバグ修正\r
599         ReleaseMutex(hAsyncTblAccMutex);\r
600         return(Sts);\r
601 }\r
602 \r
603 \r
604 /*----- \r
605 *\r
606 *       Parameter\r
607 *               \r
608 *\r
609 *       Return Value\r
610 *               \r
611 *----------------------------------------------------------------------------*/\r
612 \r
613 static int UnRegistAsyncTableDbase(HANDLE Async)\r
614 {\r
615         int Sts;\r
616         int Pos;\r
617 \r
618         // スレッド衝突のバグ修正\r
619         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
620         Sts = NO;\r
621         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
622         {\r
623                 if(SignalDbase[Pos].Async == Async)\r
624                 {\r
625 \r
626 //SetTaskMsg("############### UnRegist dbase (%d)", Pos);\r
627 \r
628                         SignalDbase[Pos].Async = 0;\r
629                         Sts = YES;\r
630                         break;\r
631                 }\r
632         }\r
633         // スレッド衝突のバグ修正\r
634         ReleaseMutex(hAsyncTblAccMutex);\r
635         return(Sts);\r
636 }\r
637 \r
638 \r
639 \r
640 \r
641 \r
642 \r
643 \r
644 \r
645 struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *CancelCheckWork)\r
646 {\r
647 #if USE_THIS\r
648         struct hostent *Ret;\r
649         HANDLE hAsync;\r
650         int Error;\r
651 \r
652 #if DBG_MSG\r
653         DoPrintf("# Start gethostbyname");\r
654 #endif\r
655         Ret = NULL;\r
656         *CancelCheckWork = NO;\r
657 \r
658         hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
659         if(hAsync != NULL)\r
660         {\r
661                 RegistAsyncTableDbase(hAsync);\r
662                 while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))\r
663                 {\r
664                         Sleep(1);\r
665                         if(BackgrndMessageProc() == YES)\r
666                                 *CancelCheckWork = YES;\r
667                 }\r
668 \r
669                 if(*CancelCheckWork == YES)\r
670                 {\r
671                         WSACancelAsyncRequest(hAsync);\r
672                 }\r
673                 else if(Error == 0)\r
674                 {\r
675                         Ret = (struct hostent *)Buf;\r
676                 }\r
677                 UnRegistAsyncTableDbase(hAsync);\r
678         }\r
679         return(Ret);\r
680 #else\r
681         return(gethostbyname(Name));\r
682 #endif\r
683 }\r
684 \r
685 \r
686 \r
687 \r
688 \r
689 SOCKET do_socket(int af, int type, int protocol)\r
690 {\r
691         SOCKET Ret;\r
692 \r
693         Ret = socket(af, type, protocol);\r
694         if(Ret != INVALID_SOCKET)\r
695         {\r
696                 RegistAsyncTable(Ret);\r
697         }\r
698 #if DBG_MSG\r
699         DoPrintf("# do_socket (S=%x)", Ret);\r
700 #endif\r
701         return(Ret);\r
702 }\r
703 \r
704 \r
705 \r
706 int do_closesocket(SOCKET s)\r
707 {\r
708 #if USE_THIS\r
709         int Ret;\r
710         int Error;\r
711         int CancelCheckWork;\r
712 \r
713 #if DBG_MSG\r
714         DoPrintf("# Start close (S=%x)", s);\r
715 #endif\r
716         CancelCheckWork = NO;\r
717 \r
718         // スレッド衝突のバグ修正\r
719         WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
720         UnRegistAsyncTable(s);\r
721         // FTPS対応\r
722 //      Ret = closesocket(s);\r
723         Ret = closesocketS(s);\r
724         if(Ret == SOCKET_ERROR)\r
725         {\r
726                 Error = 0;\r
727                 while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CLOSE_BIT) != YES))\r
728                 {\r
729                         Sleep(1);\r
730                         if(BackgrndMessageProc() == YES)\r
731                                 CancelCheckWork = YES;\r
732                 }\r
733 \r
734                 if((CancelCheckWork == NO) && (Error == 0))\r
735                         Ret = 0;\r
736         }\r
737 \r
738         // スレッド衝突のバグ修正\r
739 //      WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
740         if(BackgrndMessageProc() == YES)\r
741                 CancelCheckWork = YES;\r
742         // スレッド衝突のバグ修正\r
743 //      UnRegistAsyncTable(s);\r
744 \r
745 #if DBG_MSG\r
746         DoPrintf("# Exit close");\r
747 #endif\r
748         return(Ret);\r
749 #else\r
750         return(closesocket(s));\r
751 #endif\r
752 }\r
753 \r
754 \r
755 \r
756 \r
757 \r
758 \r
759 int do_connect(SOCKET s, const struct sockaddr *name, int namelen, int *CancelCheckWork)\r
760 {\r
761 #if USE_THIS\r
762         int Ret;\r
763         int Error;\r
764 \r
765 #if DBG_MSG\r
766         DoPrintf("# Start connect (S=%x)", s);\r
767 #endif\r
768         *CancelCheckWork = NO;\r
769 \r
770 #if DBG_MSG\r
771         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
772 #endif\r
773         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
774         if(Ret != SOCKET_ERROR)\r
775         {\r
776                 // FTPS対応\r
777 //              Ret = connect(s, name, namelen);\r
778                 if(AskCryptMode() == CRYPT_FTPIS)\r
779                         Ret = connectS(s, name, namelen);\r
780                 else\r
781                         Ret = connect(s, name, namelen);\r
782                 if(Ret == SOCKET_ERROR)\r
783                 {\r
784                         do\r
785                         {\r
786                                 Error = 0;\r
787                                 while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CONNECT_BIT) != YES))\r
788                                 {\r
789                                         Sleep(1);\r
790                                         if(BackgrndMessageProc() == YES)\r
791                                                 *CancelCheckWork = YES;\r
792                                 }\r
793 \r
794                                 if(*CancelCheckWork == YES)\r
795                                         break;\r
796                                 if(Error == 0)\r
797                                         Ret = 0;\r
798                                 else\r
799                                 {\r
800 //                                      Error = WSAGetLastError();\r
801                                         DoPrintf("#### Connect: Error=%d", Error);\r
802                                 }\r
803                         }\r
804                         while((Ret != 0) && (Error == WSAEWOULDBLOCK));\r
805                 }\r
806         }\r
807         else\r
808                 DoPrintf("#### Connect: AsyncSelect error (%d)", WSAGetLastError());\r
809 \r
810 #if DBG_MSG\r
811         DoPrintf("# Exit connect (%d)", Ret);\r
812 #endif\r
813         return(Ret);\r
814 #else\r
815         return(connect(s, name, namelen));\r
816 #endif\r
817 }\r
818 \r
819 \r
820 \r
821 \r
822 \r
823 int do_listen(SOCKET s, int backlog)\r
824 {\r
825         int Ret;\r
826 \r
827         Ret = 1;\r
828 #if DBG_MSG\r
829         DoPrintf("# Start listen (S=%x)", s);\r
830         DoPrintf("## Async set: FD_CLOSE|FD_ACCEPT");\r
831 #endif\r
832 \r
833         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CLOSE | FD_ACCEPT);\r
834         if(Ret != SOCKET_ERROR)\r
835                 Ret = listen(s, backlog);\r
836 \r
837 #if DBG_MSG\r
838         DoPrintf("# Exit listen (%d)", Ret);\r
839 #endif\r
840         return(Ret);\r
841 }\r
842 \r
843 \r
844 \r
845 SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen)\r
846 {\r
847 #if USE_THIS\r
848         SOCKET Ret2;\r
849         int CancelCheckWork;\r
850         int Error;\r
851 \r
852 #if DBG_MSG\r
853         DoPrintf("# Start accept (S=%x)", s);\r
854 #endif\r
855         CancelCheckWork = NO;\r
856         Ret2 = INVALID_SOCKET;\r
857         Error = 0;\r
858 \r
859         while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_ACCEPT_BIT) != YES))\r
860         {\r
861                 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
862                 {\r
863                         Error = 1;\r
864                         break;\r
865                 }\r
866                 Sleep(1);\r
867                 if(BackgrndMessageProc() == YES)\r
868                         CancelCheckWork = YES;\r
869         }\r
870 \r
871         if((CancelCheckWork == NO) && (Error == 0))\r
872         {\r
873                 do\r
874                 {\r
875                         // FTPS対応\r
876 //                      Ret2 = accept(s, addr, addrlen);\r
877                         if(AskCryptMode() == CRYPT_FTPIS)\r
878                                 Ret2 = acceptS(s, addr, addrlen);\r
879                         else\r
880                                 Ret2 = accept(s, addr, addrlen);\r
881                         if(Ret2 != INVALID_SOCKET)\r
882                         {\r
883 #if DBG_MSG\r
884                                 DoPrintf("## do_sccept (S=%x)", Ret2);\r
885                                 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
886 #endif\r
887                                 RegistAsyncTable(Ret2);\r
888                                 if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR)\r
889                                 {\r
890                                         do_closesocket(Ret2);\r
891                                         Ret2 = INVALID_SOCKET;\r
892                                 }\r
893                                 break;\r
894                         }\r
895                         Error = WSAGetLastError();\r
896                         Sleep(1);\r
897                         if(BackgrndMessageProc() == YES)\r
898                                 break;\r
899                 }\r
900                 while(Error == WSAEWOULDBLOCK);\r
901         }\r
902 \r
903 #if DBG_MSG\r
904         DoPrintf("# Exit accept");\r
905 #endif\r
906         return(Ret2);\r
907 #else\r
908         return(accept(s, addr, addrlen));\r
909 #endif\r
910 }\r
911 \r
912 \r
913 \r
914 \r
915 /*----- recv相当の関数 --------------------------------------------------------\r
916 *\r
917 *       Parameter\r
918 *               SOCKET s : ソケット\r
919 *               char *buf : データを読み込むバッファ\r
920 *               int len : 長さ\r
921 *               int flags : recvに与えるフラグ\r
922 *               int *TimeOutErr : タイムアウトしたかどうかを返すワーク\r
923 *\r
924 *       Return Value\r
925 *               int : recvの戻り値と同じ\r
926 *\r
927 *       Note\r
928 *               タイムアウトの時は TimeOut=YES、Ret=SOCKET_ERROR になる\r
929 *----------------------------------------------------------------------------*/\r
930 int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
931 {\r
932 #if USE_THIS\r
933         int Ret;\r
934         time_t StartTime;\r
935         time_t ElapseTime;\r
936         int Error;\r
937 \r
938 #if DBG_MSG\r
939         DoPrintf("# Start recv (S=%x)", s);\r
940 #endif\r
941         *TimeOutErr = NO;\r
942         *CancelCheckWork = NO;\r
943         Ret = SOCKET_ERROR;\r
944         Error = 0;\r
945 \r
946         if(TimeOut != 0)\r
947                 time(&StartTime);\r
948 \r
949         // FTPS対応\r
950         // OpenSSLでは受信確認はFD_READが複数回受信される可能性がある\r
951 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ_BIT) != YES))\r
952         while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ_BIT) != YES))\r
953         {\r
954                 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
955                 {\r
956                         Ret = 0;\r
957                         break;\r
958                 }\r
959                 Sleep(1);\r
960                 if(BackgrndMessageProc() == YES)\r
961                         *CancelCheckWork = YES;\r
962                 else if(TimeOut != 0)\r
963                 {\r
964                         time(&ElapseTime);\r
965                         ElapseTime -= StartTime;\r
966                         if(ElapseTime >= TimeOut)\r
967                         {\r
968                                 DoPrintf("do_recv timed out");\r
969                                 *TimeOutErr = YES;\r
970                                 *CancelCheckWork = YES;\r
971                         }\r
972                 }\r
973         }\r
974 \r
975         if(/*(Ret != 0) && */(Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
976         {\r
977                 do\r
978                 {\r
979 #if DBG_MSG\r
980                         DoPrintf("## recv()");\r
981 #endif\r
982 \r
983                         // FTPS対応\r
984 //                      Ret = recv(s, buf, len, flags);\r
985                         Ret = recvS(s, buf, len, flags);\r
986                         if(Ret != SOCKET_ERROR)\r
987                                 break;\r
988                         Error = WSAGetLastError();\r
989                         Sleep(1);\r
990                         if(BackgrndMessageProc() == YES)\r
991                                 break;\r
992                         // FTPS対応\r
993                         // 受信確認をバイパスしたためここでタイムアウトの確認\r
994                         if(BackgrndMessageProc() == YES)\r
995                                 *CancelCheckWork = YES;\r
996                         else if(TimeOut != 0)\r
997                         {\r
998                                 time(&ElapseTime);\r
999                                 ElapseTime -= StartTime;\r
1000                                 if(ElapseTime >= TimeOut)\r
1001                                 {\r
1002                                         DoPrintf("do_recv timed out");\r
1003                                         *TimeOutErr = YES;\r
1004                                         *CancelCheckWork = YES;\r
1005                                 }\r
1006                         }\r
1007                         if(*CancelCheckWork == YES)\r
1008                                 break;\r
1009                 }\r
1010                 while(Error == WSAEWOULDBLOCK);\r
1011         }\r
1012 \r
1013         if(BackgrndMessageProc() == YES)\r
1014                 Ret = SOCKET_ERROR;\r
1015 \r
1016 #if DBG_MSG\r
1017         DoPrintf("# Exit recv (%d)", Ret);\r
1018 #endif\r
1019         return(Ret);\r
1020 #else\r
1021         return(recv(s, buf, len, flags));\r
1022 #endif\r
1023 }\r
1024 \r
1025 \r
1026 \r
1027 int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
1028 {\r
1029 #if USE_THIS\r
1030         int Ret;\r
1031         time_t StartTime;\r
1032         time_t ElapseTime;\r
1033         int Error;\r
1034 \r
1035 #if DBG_MSG\r
1036         DoPrintf("# Start send (S=%x)", s);\r
1037 #endif\r
1038         *TimeOutErr = NO;\r
1039         *CancelCheckWork = NO;\r
1040         Ret = SOCKET_ERROR;\r
1041         Error = 0;\r
1042 \r
1043         if(TimeOut != 0)\r
1044                 time(&StartTime);\r
1045 \r
1046 #if DBG_MSG\r
1047         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
1048 #endif\r
1049         WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
1050         if(BackgrndMessageProc() == YES)\r
1051                 *CancelCheckWork = YES;\r
1052 \r
1053         // FTPS対応\r
1054         // 送信バッファの空き確認には影響しないが念のため\r
1055 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
1056         while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
1057         {\r
1058                 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
1059                 {\r
1060                         Error = 1;\r
1061                         break;\r
1062                 }\r
1063 \r
1064                 Sleep(1);\r
1065                 if(BackgrndMessageProc() == YES)\r
1066                         *CancelCheckWork = YES;\r
1067                 else if(TimeOut != 0)\r
1068                 {\r
1069                         time(&ElapseTime);\r
1070                         ElapseTime -= StartTime;\r
1071                         if(ElapseTime >= TimeOut)\r
1072                         {\r
1073                                 DoPrintf("do_write timed out");\r
1074                                 *TimeOutErr = YES;\r
1075                                 *CancelCheckWork = YES;\r
1076                         }\r
1077                 }\r
1078         }\r
1079 \r
1080         if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
1081         {\r
1082                 do\r
1083                 {\r
1084 #if DBG_MSG\r
1085                         DoPrintf("## send()");\r
1086 #endif\r
1087 \r
1088                         // FTPS対応\r
1089 //                      Ret = send(s, buf, len, flags);\r
1090                         Ret = sendS(s, buf, len, flags);\r
1091                         if(Ret != SOCKET_ERROR)\r
1092                         {\r
1093 #if DBG_MSG\r
1094                                 DoPrintf("## send() OK");\r
1095 #endif\r
1096                                 break;\r
1097                         }\r
1098                         Error = WSAGetLastError();\r
1099                         Sleep(1);\r
1100                         if(BackgrndMessageProc() == YES)\r
1101                                 break;\r
1102                         // FTPS対応\r
1103                         // 送信バッファ確認をバイパスしたためここでタイムアウトの確認\r
1104                         if(BackgrndMessageProc() == YES)\r
1105                                 *CancelCheckWork = YES;\r
1106                         else if(TimeOut != 0)\r
1107                         {\r
1108                                 time(&ElapseTime);\r
1109                                 ElapseTime -= StartTime;\r
1110                                 if(ElapseTime >= TimeOut)\r
1111                                 {\r
1112                                         DoPrintf("do_recv timed out");\r
1113                                         *TimeOutErr = YES;\r
1114                                         *CancelCheckWork = YES;\r
1115                                 }\r
1116                         }\r
1117                         if(*CancelCheckWork == YES)\r
1118                                 break;\r
1119                 }\r
1120                 while(Error == WSAEWOULDBLOCK);\r
1121         }\r
1122 \r
1123         if(BackgrndMessageProc() == YES)\r
1124                 Ret = SOCKET_ERROR;\r
1125 \r
1126 #if DBG_MSG\r
1127         DoPrintf("# Exit send (%d)", Ret);\r
1128 #endif\r
1129         return(Ret);\r
1130 #else\r
1131         return(send(s, buf, len, flags));\r
1132 #endif\r
1133 }\r
1134 \r
1135 \r
1136 /*----- \r
1137 *\r
1138 *       Parameter\r
1139 *\r
1140 *       Return Value\r
1141 *               int ステータス\r
1142 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1143 *----------------------------------------------------------------------------*/\r
1144 \r
1145 int CheckClosedAndReconnect(void)\r
1146 {\r
1147         int Error;\r
1148         int Sts;\r
1149 \r
1150 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");\r
1151 \r
1152         Sts = FFFTP_SUCCESS;\r
1153         if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE_BIT) == YES)\r
1154         {\r
1155                 Sts = ReConnectCmdSkt();\r
1156         }\r
1157         return(Sts);\r
1158 }\r
1159 \r
1160 \r
1161 \r