OSDN Git Service

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