OSDN Git Service

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