OSDN Git Service

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