OSDN Git Service

Fix bugs of playing sound.
[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                         Signal[Pos].Socket = INVALID_SOCKET;\r
488                         break;\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         if(AskCryptMode() == CRYPT_FTPES || AskCryptMode() == CRYPT_FTPIS)\r
744                 Ret = closesocketS(s);\r
745         else\r
746                 Ret = closesocketS(s);\r
747         if(Ret == SOCKET_ERROR)\r
748         {\r
749                 Error = 0;\r
750                 while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CLOSE_BIT) != YES))\r
751                 {\r
752                         Sleep(1);\r
753                         if(BackgrndMessageProc() == YES)\r
754                                 CancelCheckWork = YES;\r
755                 }\r
756 \r
757                 if((CancelCheckWork == NO) && (Error == 0))\r
758                         Ret = 0;\r
759         }\r
760 \r
761         WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
762         if(BackgrndMessageProc() == YES)\r
763                 CancelCheckWork = YES;\r
764         UnRegistAsyncTable(s);\r
765 \r
766 #if DBG_MSG\r
767         DoPrintf("# Exit close");\r
768 #endif\r
769         return(Ret);\r
770 #else\r
771         return(closesocket(s));\r
772 #endif\r
773 }\r
774 \r
775 \r
776 \r
777 \r
778 \r
779 \r
780 int do_connect(SOCKET s, const struct sockaddr *name, int namelen, int *CancelCheckWork)\r
781 {\r
782 #if USE_THIS\r
783         int Ret;\r
784         int Error;\r
785 \r
786 #if DBG_MSG\r
787         DoPrintf("# Start connect (S=%x)", s);\r
788 #endif\r
789         *CancelCheckWork = NO;\r
790 \r
791 #if DBG_MSG\r
792         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
793 #endif\r
794         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
795         if(Ret != SOCKET_ERROR)\r
796         {\r
797                 // FTPS対応\r
798 //              Ret = connect(s, name, namelen);\r
799                 if(AskCryptMode() == CRYPT_FTPIS)\r
800                         Ret = connectS(s, name, namelen);\r
801                 else\r
802                         Ret = connect(s, name, namelen);\r
803                 if(Ret == SOCKET_ERROR)\r
804                 {\r
805                         do\r
806                         {\r
807                                 Error = 0;\r
808                                 while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CONNECT_BIT) != YES))\r
809                                 {\r
810                                         Sleep(1);\r
811                                         if(BackgrndMessageProc() == YES)\r
812                                                 *CancelCheckWork = YES;\r
813                                 }\r
814 \r
815                                 if(*CancelCheckWork == YES)\r
816                                         break;\r
817                                 if(Error == 0)\r
818                                         Ret = 0;\r
819                                 else\r
820                                 {\r
821 //                                      Error = WSAGetLastError();\r
822                                         DoPrintf("#### Connect: Error=%d", Error);\r
823                                 }\r
824                         }\r
825                         while((Ret != 0) && (Error == WSAEWOULDBLOCK));\r
826                 }\r
827         }\r
828         else\r
829                 DoPrintf("#### Connect: AsyncSelect error (%d)", WSAGetLastError());\r
830 \r
831 #if DBG_MSG\r
832         DoPrintf("# Exit connect (%d)", Ret);\r
833 #endif\r
834         return(Ret);\r
835 #else\r
836         return(connect(s, name, namelen));\r
837 #endif\r
838 }\r
839 \r
840 \r
841 \r
842 \r
843 \r
844 int do_listen(SOCKET s, int backlog)\r
845 {\r
846         int Ret;\r
847 \r
848         Ret = 1;\r
849 #if DBG_MSG\r
850         DoPrintf("# Start listen (S=%x)", s);\r
851         DoPrintf("## Async set: FD_CLOSE|FD_ACCEPT");\r
852 #endif\r
853 \r
854         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CLOSE | FD_ACCEPT);\r
855         if(Ret != SOCKET_ERROR)\r
856                 Ret = listen(s, backlog);\r
857 \r
858 #if DBG_MSG\r
859         DoPrintf("# Exit listen (%d)", Ret);\r
860 #endif\r
861         return(Ret);\r
862 }\r
863 \r
864 \r
865 \r
866 SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen)\r
867 {\r
868 #if USE_THIS\r
869         SOCKET Ret2;\r
870         int CancelCheckWork;\r
871         int Error;\r
872 \r
873 #if DBG_MSG\r
874         DoPrintf("# Start accept (S=%x)", s);\r
875 #endif\r
876         CancelCheckWork = NO;\r
877         Ret2 = INVALID_SOCKET;\r
878         Error = 0;\r
879 \r
880         while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_ACCEPT_BIT) != YES))\r
881         {\r
882                 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
883                 {\r
884                         Error = 1;\r
885                         break;\r
886                 }\r
887                 Sleep(1);\r
888                 if(BackgrndMessageProc() == YES)\r
889                         CancelCheckWork = YES;\r
890         }\r
891 \r
892         if((CancelCheckWork == NO) && (Error == 0))\r
893         {\r
894                 do\r
895                 {\r
896                         // FTPS対応\r
897 //                      Ret2 = accept(s, addr, addrlen);\r
898                         if(AskCryptMode() == CRYPT_FTPIS)\r
899                                 Ret2 = acceptS(s, addr, addrlen);\r
900                         else\r
901                                 Ret2 = accept(s, addr, addrlen);\r
902                         if(Ret2 != INVALID_SOCKET)\r
903                         {\r
904 #if DBG_MSG\r
905                                 DoPrintf("## do_sccept (S=%x)", Ret2);\r
906                                 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
907 #endif\r
908                                 RegistAsyncTable(Ret2);\r
909                                 if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR)\r
910                                 {\r
911                                         do_closesocket(Ret2);\r
912                                         Ret2 = INVALID_SOCKET;\r
913                                 }\r
914                                 break;\r
915                         }\r
916                         Error = WSAGetLastError();\r
917                         Sleep(1);\r
918                         if(BackgrndMessageProc() == YES)\r
919                                 break;\r
920                 }\r
921                 while(Error == WSAEWOULDBLOCK);\r
922         }\r
923 \r
924 #if DBG_MSG\r
925         DoPrintf("# Exit accept");\r
926 #endif\r
927         return(Ret2);\r
928 #else\r
929         return(accept(s, addr, addrlen));\r
930 #endif\r
931 }\r
932 \r
933 \r
934 \r
935 \r
936 /*----- recv相当の関数 --------------------------------------------------------\r
937 *\r
938 *       Parameter\r
939 *               SOCKET s : ソケット\r
940 *               char *buf : データを読み込むバッファ\r
941 *               int len : 長さ\r
942 *               int flags : recvに与えるフラグ\r
943 *               int *TimeOutErr : タイムアウトしたかどうかを返すワーク\r
944 *\r
945 *       Return Value\r
946 *               int : recvの戻り値と同じ\r
947 *\r
948 *       Note\r
949 *               タイムアウトの時は TimeOut=YES、Ret=SOCKET_ERROR になる\r
950 *----------------------------------------------------------------------------*/\r
951 int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
952 {\r
953 #if USE_THIS\r
954         int Ret;\r
955         time_t StartTime;\r
956         time_t ElapseTime;\r
957         int Error;\r
958 \r
959 #if DBG_MSG\r
960         DoPrintf("# Start recv (S=%x)", s);\r
961 #endif\r
962         *TimeOutErr = NO;\r
963         *CancelCheckWork = NO;\r
964         Ret = SOCKET_ERROR;\r
965         Error = 0;\r
966 \r
967         if(TimeOut != 0)\r
968                 time(&StartTime);\r
969 \r
970         // FTPS対応\r
971         // OpenSSLでは受信確認はFD_READが複数回受信される可能性がある\r
972 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ_BIT) != YES))\r
973         while(AskCryptMode() == CRYPT_NONE && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ_BIT) != YES))\r
974         {\r
975                 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
976                 {\r
977                         Ret = 0;\r
978                         break;\r
979                 }\r
980                 Sleep(1);\r
981                 if(BackgrndMessageProc() == YES)\r
982                         *CancelCheckWork = YES;\r
983                 else if(TimeOut != 0)\r
984                 {\r
985                         time(&ElapseTime);\r
986                         ElapseTime -= StartTime;\r
987                         if(ElapseTime >= TimeOut)\r
988                         {\r
989                                 DoPrintf("do_recv timed out");\r
990                                 *TimeOutErr = YES;\r
991                                 *CancelCheckWork = YES;\r
992                         }\r
993                 }\r
994         }\r
995 \r
996         if(/*(Ret != 0) && */(Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
997         {\r
998                 do\r
999                 {\r
1000 #if DBG_MSG\r
1001                         DoPrintf("## recv()");\r
1002 #endif\r
1003 \r
1004                         // FTPS対応\r
1005 //                      Ret = recv(s, buf, len, flags);\r
1006                         if(AskCryptMode() == CRYPT_FTPES || AskCryptMode() == CRYPT_FTPIS)\r
1007                                 Ret = recvS(s, buf, len, flags);\r
1008                         else\r
1009                                 Ret = recv(s, buf, len, flags);\r
1010                         if(Ret != SOCKET_ERROR)\r
1011                                 break;\r
1012                         Error = WSAGetLastError();\r
1013                         Sleep(1);\r
1014                         if(BackgrndMessageProc() == YES)\r
1015                                 break;\r
1016                         // FTPS対応\r
1017                         // 受信確認をバイパスしたためここでタイムアウトの確認\r
1018                         if(AskCryptMode() == CRYPT_FTPES || AskCryptMode() == CRYPT_FTPIS)\r
1019                         {\r
1020                                 if(BackgrndMessageProc() == YES)\r
1021                                         *CancelCheckWork = YES;\r
1022                         }\r
1023                         else if(TimeOut != 0)\r
1024                         {\r
1025                                 time(&ElapseTime);\r
1026                                 ElapseTime -= StartTime;\r
1027                                 if(ElapseTime >= TimeOut)\r
1028                                 {\r
1029                                         DoPrintf("do_recv timed out");\r
1030                                         *TimeOutErr = YES;\r
1031                                         *CancelCheckWork = YES;\r
1032                                 }\r
1033                         }\r
1034                         if(*CancelCheckWork == YES)\r
1035                                 break;\r
1036                 }\r
1037                 while(Error == WSAEWOULDBLOCK);\r
1038         }\r
1039 \r
1040         if(BackgrndMessageProc() == YES)\r
1041                 Ret = SOCKET_ERROR;\r
1042 \r
1043 #if DBG_MSG\r
1044         DoPrintf("# Exit recv (%d)", Ret);\r
1045 #endif\r
1046         return(Ret);\r
1047 #else\r
1048         return(recv(s, buf, len, flags));\r
1049 #endif\r
1050 }\r
1051 \r
1052 \r
1053 \r
1054 int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
1055 {\r
1056 #if USE_THIS\r
1057         int Ret;\r
1058         time_t StartTime;\r
1059         time_t ElapseTime;\r
1060         int Error;\r
1061 \r
1062 #if DBG_MSG\r
1063         DoPrintf("# Start send (S=%x)", s);\r
1064 #endif\r
1065         *TimeOutErr = NO;\r
1066         *CancelCheckWork = NO;\r
1067         Ret = SOCKET_ERROR;\r
1068         Error = 0;\r
1069 \r
1070         if(TimeOut != 0)\r
1071                 time(&StartTime);\r
1072 \r
1073 #if DBG_MSG\r
1074         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
1075 #endif\r
1076         WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
1077         if(BackgrndMessageProc() == YES)\r
1078                 *CancelCheckWork = YES;\r
1079 \r
1080         // FTPS対応\r
1081         // 送信バッファの空き確認には影響しないが念のため\r
1082 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
1083         while(AskCryptMode() == CRYPT_NONE && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
1084         {\r
1085                 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
1086                 {\r
1087                         Error = 1;\r
1088                         break;\r
1089                 }\r
1090 \r
1091                 Sleep(1);\r
1092                 if(BackgrndMessageProc() == YES)\r
1093                         *CancelCheckWork = YES;\r
1094                 else if(TimeOut != 0)\r
1095                 {\r
1096                         time(&ElapseTime);\r
1097                         ElapseTime -= StartTime;\r
1098                         if(ElapseTime >= TimeOut)\r
1099                         {\r
1100                                 DoPrintf("do_write timed out");\r
1101                                 *TimeOutErr = YES;\r
1102                                 *CancelCheckWork = YES;\r
1103                         }\r
1104                 }\r
1105         }\r
1106 \r
1107         if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
1108         {\r
1109                 do\r
1110                 {\r
1111 #if DBG_MSG\r
1112                         DoPrintf("## send()");\r
1113 #endif\r
1114 \r
1115                         // FTPS対応\r
1116 //                      Ret = send(s, buf, len, flags);\r
1117                         if(AskCryptMode() == CRYPT_FTPES || AskCryptMode() == CRYPT_FTPIS)\r
1118                                 Ret = sendS(s, buf, len, flags);\r
1119                         else\r
1120                                 Ret = send(s, buf, len, flags);\r
1121                         if(Ret != SOCKET_ERROR)\r
1122                         {\r
1123 #if DBG_MSG\r
1124                                 DoPrintf("## send() OK");\r
1125 #endif\r
1126                                 break;\r
1127                         }\r
1128                         Error = WSAGetLastError();\r
1129                         Sleep(1);\r
1130                         if(BackgrndMessageProc() == YES)\r
1131                                 break;\r
1132                         // FTPS対応\r
1133                         // 送信バッファ確認をバイパスしたためここでタイムアウトの確認\r
1134                         if(AskCryptMode() == CRYPT_FTPES || AskCryptMode() == CRYPT_FTPIS)\r
1135                         {\r
1136                                 if(BackgrndMessageProc() == YES)\r
1137                                         *CancelCheckWork = YES;\r
1138                         }\r
1139                         else if(TimeOut != 0)\r
1140                         {\r
1141                                 time(&ElapseTime);\r
1142                                 ElapseTime -= StartTime;\r
1143                                 if(ElapseTime >= TimeOut)\r
1144                                 {\r
1145                                         DoPrintf("do_recv timed out");\r
1146                                         *TimeOutErr = YES;\r
1147                                         *CancelCheckWork = YES;\r
1148                                 }\r
1149                         }\r
1150                         if(*CancelCheckWork == YES)\r
1151                                 break;\r
1152                 }\r
1153                 while(Error == WSAEWOULDBLOCK);\r
1154         }\r
1155 \r
1156         if(BackgrndMessageProc() == YES)\r
1157                 Ret = SOCKET_ERROR;\r
1158 \r
1159 #if DBG_MSG\r
1160         DoPrintf("# Exit send (%d)", Ret);\r
1161 #endif\r
1162         return(Ret);\r
1163 #else\r
1164         return(send(s, buf, len, flags));\r
1165 #endif\r
1166 }\r
1167 \r
1168 \r
1169 /*----- \r
1170 *\r
1171 *       Parameter\r
1172 *\r
1173 *       Return Value\r
1174 *               int ステータス\r
1175 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1176 *----------------------------------------------------------------------------*/\r
1177 \r
1178 int CheckClosedAndReconnect(void)\r
1179 {\r
1180         int Error;\r
1181         int Sts;\r
1182 \r
1183 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");\r
1184 \r
1185         Sts = FFFTP_SUCCESS;\r
1186         if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE_BIT) == YES)\r
1187         {\r
1188                 Sts = ReConnectCmdSkt();\r
1189         }\r
1190         return(Sts);\r
1191 }\r
1192 \r
1193 \r
1194 \r