1 /*=============================================================================
\r
5 ===============================================================================
\r
6 / Copyright (C) 1997-2007 Sota. All rights reserved.
\r
8 / Redistribution and use in source and binary forms, with or without
\r
9 / modification, are permitted provided that the following conditions
\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
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
32 #include <winsock2.h>
\r
33 #include <windows.h>
\r
38 #include <windowsx.h>
\r
39 #include <commctrl.h>
\r
41 #include <natupnp.h>
\r
44 #include "resource.h"
\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
72 struct sockaddr_in HostAddrIPv4;
\r
73 struct sockaddr_in SocksAddrIPv4;
\r
74 struct sockaddr_in6 HostAddrIPv6;
\r
75 struct sockaddr_in6 SocksAddrIPv6;
\r
84 } ASYNCSIGNALDATABASE;
\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
97 /*===== プロトタイプ =====*/
\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
108 /*===== 外部参照 =====*/
\r
110 extern int TimeOut;
\r
113 /*===== ローカルなワーク =====*/
\r
115 static const char SocketWndClass[] = "FFFTPSocketWnd";
\r
116 static HWND hWndSocket;
\r
118 static ASYNCSIGNAL Signal[MAX_SIGNAL_ENTRY];
\r
119 static ASYNCSIGNALDATABASE SignalDbase[MAX_SIGNAL_ENTRY_DBASE];
\r
121 //static HANDLE hAsyncTblAccMutex;
\r
123 static HANDLE hAsyncTblAccMutex;
\r
126 IUPnPNAT* pUPnPNAT;
\r
127 IStaticPortMappingCollection* pUPnPMap;
\r
138 * FFFTP_SUCCESS/FFFTP_FAIL
\r
139 *----------------------------------------------------------------------------*/
\r
141 int MakeSocketWin(HWND hWnd, HINSTANCE hInst)
\r
147 wClass.cbSize = sizeof(WNDCLASSEX);
\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
162 hWndSocket = CreateWindowEx(0, SocketWndClass, NULL,
\r
163 WS_BORDER | WS_POPUP,
\r
165 hWnd, NULL, hInst, NULL);
\r
167 if(hWndSocket != NULL)
\r
169 // hAsyncTblAccMutex = CreateMutex(NULL, FALSE, NULL);
\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
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
183 Sts = FFFTP_SUCCESS;
\r
196 *----------------------------------------------------------------------------*/
\r
198 void DeleteSocketWin(void)
\r
200 // CloseHandle(hAsyncTblAccMutex);
\r
202 CloseHandle(hAsyncTblAccMutex);
\r
203 hAsyncTblAccMutex = NULL;
\r
205 if(hWndSocket != NULL)
\r
206 DestroyWindow(hWndSocket);
\r
214 * HWND hWnd : ウインドウハンドル
\r
215 * UINT message : メッセージ番号
\r
216 * WPARAM wParam : メッセージの WPARAM 引数
\r
217 * LPARAM lParam : メッセージの LPARAM 引数
\r
221 *----------------------------------------------------------------------------*/
\r
223 static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
229 case WM_ASYNC_SOCKET :
\r
231 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
232 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
234 if(Signal[Pos].Socket == (SOCKET)wParam)
\r
236 Signal[Pos].Error = WSAGETSELECTERROR(lParam);
\r
238 if(WSAGETSELECTERROR(lParam) != 0)
\r
239 DoPrintf("####### Signal: error (%d)", WSAGETSELECTERROR(lParam));
\r
242 switch(WSAGETSELECTEVENT(lParam))
\r
245 Signal[Pos].FdConnect = 1;
\r
247 DoPrintf("####### Signal: connect (S=%x)", Signal[Pos].Socket);
\r
252 Signal[Pos].FdClose = 1;
\r
254 DoPrintf("####### Signal: close (S=%x)", Signal[Pos].Socket);
\r
256 //SetTaskMsg("####### Signal: close (%d) (S=%x)", Pos, Signal[Pos].Socket);
\r
260 Signal[Pos].FdAccept = 1;
\r
262 DoPrintf("####### Signal: accept (S=%x)", Signal[Pos].Socket);
\r
267 Signal[Pos].FdRead = 1;
\r
269 DoPrintf("####### Signal: read (S=%x)", Signal[Pos].Socket);
\r
274 Signal[Pos].FdWrite = 1;
\r
276 DoPrintf("####### Signal: write (S=%x)", Signal[Pos].Socket);
\r
284 ReleaseMutex(hAsyncTblAccMutex);
\r
287 case WM_ASYNC_DBASE :
\r
288 // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり
\r
289 RegisterAsyncTableDbase((HANDLE)wParam);
\r
291 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
292 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)
\r
294 if(SignalDbase[Pos].Async == (HANDLE)wParam)
\r
296 if(HIWORD(lParam) != 0)
\r
298 SignalDbase[Pos].ErrorDb = 1;
\r
300 DoPrintf("##### SignalDatabase: error");
\r
303 SignalDbase[Pos].Done = 1;
\r
305 DoPrintf("##### SignalDatabase: Done");
\r
311 ReleaseMutex(hAsyncTblAccMutex);
\r
315 return(DefWindowProc(hWnd, message, wParam, lParam));
\r
330 *----------------------------------------------------------------------------*/
\r
332 static int AskAsyncDone(SOCKET s, int *Error, int Mask)
\r
338 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
341 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
343 if(Signal[Pos].Socket == s)
\r
345 *Error = Signal[Pos].Error;
\r
346 if(Signal[Pos].Error != 0)
\r
348 if((Mask & FD_CONNECT) && (Signal[Pos].FdConnect != 0))
\r
352 DoPrintf("### Ask: connect (Sts=%d, Error=%d)", Sts, *Error);
\r
355 if((Mask & FD_CLOSE) && (Signal[Pos].FdClose != 0))
\r
356 // if(Mask & FD_CLOSE)
\r
360 DoPrintf("### Ask: close (Sts=%d, Error=%d)", Sts, *Error);
\r
363 if((Mask & FD_ACCEPT) && (Signal[Pos].FdAccept != 0))
\r
365 Signal[Pos].FdAccept = 0;
\r
368 DoPrintf("### Ask: accept (Sts=%d, Error=%d)", Sts, *Error);
\r
371 if((Mask & FD_READ) && (Signal[Pos].FdRead != 0))
\r
373 Signal[Pos].FdRead = 0;
\r
376 DoPrintf("### Ask: read (Sts=%d, Error=%d)", Sts, *Error);
\r
379 if((Mask & FD_WRITE) && (Signal[Pos].FdWrite != 0))
\r
381 Signal[Pos].FdWrite = 0;
\r
384 DoPrintf("### Ask: write (Sts=%d, Error=%d)", Sts, *Error);
\r
391 ReleaseMutex(hAsyncTblAccMutex);
\r
393 if(Pos == MAX_SIGNAL_ENTRY)
\r
395 if(Mask & FD_CLOSE)
\r
401 MessageBox(GetMainHwnd(), "AskAsyncDone called with unregisterd socket.", "FFFTP inner error", MB_OK);
\r
416 *----------------------------------------------------------------------------*/
\r
418 static int AskAsyncDoneDbase(HANDLE Async, int *Error)
\r
424 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
427 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)
\r
429 if(SignalDbase[Pos].Async == Async)
\r
431 if(SignalDbase[Pos].Done != 0)
\r
433 *Error = SignalDbase[Pos].ErrorDb;
\r
436 DoPrintf("### Ask: Dbase (Sts=%d, Error=%d)", Sts, *Error);
\r
443 ReleaseMutex(hAsyncTblAccMutex);
\r
445 if(Pos == MAX_SIGNAL_ENTRY_DBASE)
\r
447 MessageBox(GetMainHwnd(), "AskAsyncDoneDbase called with unregisterd handle.", "FFFTP inner error", MB_OK);
\r
462 *----------------------------------------------------------------------------*/
\r
464 static int RegisterAsyncTable(SOCKET s)
\r
470 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
472 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
474 if(Signal[Pos].Socket == s)
\r
476 // 強制的に閉じられたソケットがあると重複する可能性あり
\r
477 // MessageBox(GetMainHwnd(), "Async socket already registerd.", "FFFTP inner error", MB_OK);
\r
479 Signal[Pos].Socket = INVALID_SOCKET;
\r
483 ReleaseMutex(hAsyncTblAccMutex);
\r
485 if(Pos == MAX_SIGNAL_ENTRY)
\r
488 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
489 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
491 if(Signal[Pos].Socket == INVALID_SOCKET)
\r
494 //SetTaskMsg("############### Regist socket (%d)", Pos);
\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
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
514 ReleaseMutex(hAsyncTblAccMutex);
\r
516 if(Pos == MAX_SIGNAL_ENTRY)
\r
518 MessageBox(GetMainHwnd(), "No more async regist space.", "FFFTP inner error", MB_OK);
\r
534 *----------------------------------------------------------------------------*/
\r
536 static int RegisterAsyncTableDbase(HANDLE Async)
\r
542 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
544 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)
\r
546 if(SignalDbase[Pos].Async == Async)
\r
548 // 強制的に閉じられたハンドルがあると重複する可能性あり
\r
549 // MessageBox(GetMainHwnd(), "Async handle already registerd.", "FFFTP inner error", MB_OK);
\r
550 // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり
\r
555 ReleaseMutex(hAsyncTblAccMutex);
\r
557 if(Pos == MAX_SIGNAL_ENTRY_DBASE)
\r
560 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
561 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
563 if(SignalDbase[Pos].Async == 0)
\r
566 //SetTaskMsg("############### Regist dbase (%d)", Pos);
\r
568 SignalDbase[Pos].Async = Async;
\r
569 SignalDbase[Pos].Done = 0;
\r
570 SignalDbase[Pos].ErrorDb = 0;
\r
576 ReleaseMutex(hAsyncTblAccMutex);
\r
578 if(Pos == MAX_SIGNAL_ENTRY_DBASE)
\r
580 MessageBox(GetMainHwnd(), "No more async dbase regist space.", "FFFTP inner error", MB_OK);
\r
596 *----------------------------------------------------------------------------*/
\r
598 static int UnregisterAsyncTable(SOCKET s)
\r
604 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
606 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
608 if(Signal[Pos].Socket == s)
\r
611 //SetTaskMsg("############### UnRegist socket (%d)", Pos);
\r
613 Signal[Pos].Socket = INVALID_SOCKET;
\r
619 ReleaseMutex(hAsyncTblAccMutex);
\r
631 *----------------------------------------------------------------------------*/
\r
633 static int UnregisterAsyncTableDbase(HANDLE Async)
\r
639 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
641 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)
\r
643 if(SignalDbase[Pos].Async == Async)
\r
646 //SetTaskMsg("############### UnRegist dbase (%d)", Pos);
\r
648 SignalDbase[Pos].Async = 0;
\r
654 ReleaseMutex(hAsyncTblAccMutex);
\r
661 int SetAsyncTableDataIPv4(SOCKET s, struct sockaddr_in* Host, struct sockaddr_in* Socks)
\r
666 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
668 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
670 if(Signal[Pos].Socket == s)
\r
673 memcpy(&Signal[Pos].HostAddrIPv4, Host, sizeof(struct sockaddr_in));
\r
675 memcpy(&Signal[Pos].SocksAddrIPv4, Socks, sizeof(struct sockaddr_in));
\r
680 ReleaseMutex(hAsyncTblAccMutex);
\r
685 int SetAsyncTableDataIPv6(SOCKET s, struct sockaddr_in6* Host, struct sockaddr_in6* Socks)
\r
690 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
692 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
694 if(Signal[Pos].Socket == s)
\r
697 memcpy(&Signal[Pos].HostAddrIPv6, Host, sizeof(struct sockaddr_in6));
\r
699 memcpy(&Signal[Pos].SocksAddrIPv6, Socks, sizeof(struct sockaddr_in6));
\r
704 ReleaseMutex(hAsyncTblAccMutex);
\r
709 int SetAsyncTableDataMapPort(SOCKET s, int Port)
\r
714 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
716 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
718 if(Signal[Pos].Socket == s)
\r
720 Signal[Pos].MapPort = Port;
\r
725 ReleaseMutex(hAsyncTblAccMutex);
\r
730 int GetAsyncTableDataIPv4(SOCKET s, struct sockaddr_in* Host, struct sockaddr_in* Socks)
\r
735 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
737 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
739 if(Signal[Pos].Socket == s)
\r
742 memcpy(Host, &Signal[Pos].HostAddrIPv4, sizeof(struct sockaddr_in));
\r
744 memcpy(Socks, &Signal[Pos].SocksAddrIPv4, sizeof(struct sockaddr_in));
\r
749 ReleaseMutex(hAsyncTblAccMutex);
\r
754 int GetAsyncTableDataIPv6(SOCKET s, struct sockaddr_in6* Host, struct sockaddr_in6* Socks)
\r
759 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
761 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
763 if(Signal[Pos].Socket == s)
\r
766 memcpy(Host, &Signal[Pos].HostAddrIPv6, sizeof(struct sockaddr_in6));
\r
768 memcpy(Socks, &Signal[Pos].SocksAddrIPv6, sizeof(struct sockaddr_in6));
\r
773 ReleaseMutex(hAsyncTblAccMutex);
\r
778 int GetAsyncTableDataMapPort(SOCKET s, int* Port)
\r
783 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
785 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
787 if(Signal[Pos].Socket == s)
\r
789 *Port = Signal[Pos].MapPort;
\r
794 ReleaseMutex(hAsyncTblAccMutex);
\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
810 struct hostent *Ret;
\r
815 DoPrintf("# Start gethostbyname");
\r
819 // *CancelCheckWork = NO;
\r
822 // hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);
\r
823 hAsync = WSAAsyncGetHostByNameM(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);
\r
826 RegisterAsyncTableDbase(hAsync);
\r
827 while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))
\r
830 if(BackgrndMessageProc() == YES)
\r
831 *CancelCheckWork = YES;
\r
834 if(*CancelCheckWork == YES)
\r
836 WSACancelAsyncRequest(hAsync);
\r
838 else if(Error == 0)
\r
840 Ret = (struct hostent *)Buf;
\r
842 UnregisterAsyncTableDbase(hAsync);
\r
846 return(gethostbyname(Name));
\r
851 struct hostent *do_gethostbynameIPv6(const char *Name, char *Buf, int Len, int *CancelCheckWork)
\r
854 struct hostent *Ret;
\r
859 DoPrintf("# Start gethostbyname");
\r
863 // *CancelCheckWork = NO;
\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
870 RegisterAsyncTableDbase(hAsync);
\r
871 while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))
\r
874 if(BackgrndMessageProc() == YES)
\r
875 *CancelCheckWork = YES;
\r
878 if(*CancelCheckWork == YES)
\r
880 WSACancelAsyncRequestIPv6(hAsync);
\r
882 else if(Error == 0)
\r
884 Ret = (struct hostent *)Buf;
\r
886 UnregisterAsyncTableDbase(hAsync);
\r
890 return(gethostbyname(Name));
\r
898 SOCKET do_socket(int af, int type, int protocol)
\r
902 Ret = socket(af, type, protocol);
\r
903 if(Ret != INVALID_SOCKET)
\r
905 RegisterAsyncTable(Ret);
\r
908 DoPrintf("# do_socket (S=%x)", Ret);
\r
915 int do_closesocket(SOCKET s)
\r
920 int CancelCheckWork;
\r
923 DoPrintf("# Start close (S=%x)", s);
\r
925 CancelCheckWork = NO;
\r
928 WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);
\r
929 UnregisterAsyncTable(s);
\r
931 // Ret = closesocket(s);
\r
932 Ret = FTPS_closesocket(s);
\r
933 if(Ret == SOCKET_ERROR)
\r
936 while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CLOSE) != YES))
\r
939 if(BackgrndMessageProc() == YES)
\r
940 CancelCheckWork = YES;
\r
943 if((CancelCheckWork == NO) && (Error == 0))
\r
948 // WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);
\r
949 if(BackgrndMessageProc() == YES)
\r
950 CancelCheckWork = YES;
\r
952 // UnregisterAsyncTable(s);
\r
955 DoPrintf("# Exit close");
\r
959 return(closesocket(s));
\r
968 int do_connect(SOCKET s, const struct sockaddr *name, int namelen, int *CancelCheckWork)
\r
975 DoPrintf("# Start connect (S=%x)", s);
\r
978 // *CancelCheckWork = NO;
\r
981 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");
\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
988 Ret = connect(s, name, namelen);
\r
989 if(Ret == SOCKET_ERROR)
\r
994 while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CONNECT) != YES))
\r
997 if(BackgrndMessageProc() == YES)
\r
998 *CancelCheckWork = YES;
\r
1001 if(*CancelCheckWork == YES)
\r
1007 // Error = WSAGetLastError();
\r
1008 DoPrintf("#### Connect: Error=%d", Error);
\r
1011 while((Ret != 0) && (Error == WSAEWOULDBLOCK));
\r
1015 DoPrintf("#### Connect: AsyncSelect error (%d)", WSAGetLastError());
\r
1018 DoPrintf("# Exit connect (%d)", Ret);
\r
1022 return(connect(s, name, namelen));
\r
1030 int do_listen(SOCKET s, int backlog)
\r
1036 DoPrintf("# Start listen (S=%x)", s);
\r
1037 DoPrintf("## Async set: FD_CLOSE|FD_ACCEPT");
\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
1045 DoPrintf("# Exit listen (%d)", Ret);
\r
1052 SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
\r
1056 int CancelCheckWork;
\r
1060 DoPrintf("# Start accept (S=%x)", s);
\r
1062 CancelCheckWork = NO;
\r
1063 Ret2 = INVALID_SOCKET;
\r
1066 while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_ACCEPT) != YES))
\r
1068 if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)
\r
1074 if(BackgrndMessageProc() == YES)
\r
1075 CancelCheckWork = YES;
\r
1078 if((CancelCheckWork == NO) && (Error == 0))
\r
1082 Ret2 = accept(s, addr, addrlen);
\r
1083 if(Ret2 != INVALID_SOCKET)
\r
1086 DoPrintf("## do_sccept (S=%x)", Ret2);
\r
1087 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");
\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
1094 do_closesocket(Ret2);
\r
1095 Ret2 = INVALID_SOCKET;
\r
1099 Error = WSAGetLastError();
\r
1101 if(BackgrndMessageProc() == YES)
\r
1104 while(Error == WSAEWOULDBLOCK);
\r
1108 DoPrintf("# Exit accept");
\r
1112 return(accept(s, addr, addrlen));
\r
1119 /*----- recv相当の関数 --------------------------------------------------------
\r
1123 * char *buf : データを読み込むバッファ
\r
1125 * int flags : recvに与えるフラグ
\r
1126 * int *TimeOutErr : タイムアウトしたかどうかを返すワーク
\r
1129 * int : recvの戻り値と同じ
\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
1139 time_t ElapseTime;
\r
1143 DoPrintf("# Start recv (S=%x)", s);
\r
1147 // *CancelCheckWork = NO;
\r
1148 Ret = SOCKET_ERROR;
\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
1160 // if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)
\r
1166 // if(BackgrndMessageProc() == YES)
\r
1167 // *CancelCheckWork = YES;
\r
1168 // else if(TimeOut != 0)
\r
1170 // time(&ElapseTime);
\r
1171 // ElapseTime -= StartTime;
\r
1172 // if(ElapseTime >= TimeOut)
\r
1174 // DoPrintf("do_recv timed out");
\r
1175 // *TimeOutErr = YES;
\r
1176 // *CancelCheckWork = YES;
\r
1181 if(/*(Ret != 0) && */(Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))
\r
1186 DoPrintf("## recv()");
\r
1190 // Ret = recv(s, buf, len, flags);
\r
1191 Ret = FTPS_recv(s, buf, len, flags);
\r
1192 if(Ret != SOCKET_ERROR)
\r
1194 Error = WSAGetLastError();
\r
1196 if(BackgrndMessageProc() == YES)
\r
1199 // 受信確認をバイパスしたためここでタイムアウトの確認
\r
1200 if(BackgrndMessageProc() == YES)
\r
1201 *CancelCheckWork = YES;
\r
1202 else if(TimeOut != 0)
\r
1204 time(&ElapseTime);
\r
1205 ElapseTime -= StartTime;
\r
1206 if(ElapseTime >= TimeOut)
\r
1208 DoPrintf("do_recv timed out");
\r
1209 *TimeOutErr = YES;
\r
1210 *CancelCheckWork = YES;
\r
1213 if(*CancelCheckWork == YES)
\r
1216 while(Error == WSAEWOULDBLOCK);
\r
1219 if(BackgrndMessageProc() == YES)
\r
1220 Ret = SOCKET_ERROR;
\r
1223 DoPrintf("# Exit recv (%d)", Ret);
\r
1227 return(recv(s, buf, len, flags));
\r
1233 int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)
\r
1238 time_t ElapseTime;
\r
1242 DoPrintf("# Start send (S=%x)", s);
\r
1246 // *CancelCheckWork = NO;
\r
1247 Ret = SOCKET_ERROR;
\r
1254 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");
\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
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
1269 // if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)
\r
1276 // if(BackgrndMessageProc() == YES)
\r
1277 // *CancelCheckWork = YES;
\r
1278 // else if(TimeOut != 0)
\r
1280 // time(&ElapseTime);
\r
1281 // ElapseTime -= StartTime;
\r
1282 // if(ElapseTime >= TimeOut)
\r
1284 // DoPrintf("do_write timed out");
\r
1285 // *TimeOutErr = YES;
\r
1286 // *CancelCheckWork = YES;
\r
1291 if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))
\r
1296 DoPrintf("## send()");
\r
1300 // Ret = send(s, buf, len, flags);
\r
1301 Ret = FTPS_send(s, buf, len, flags);
\r
1302 if(Ret != SOCKET_ERROR)
\r
1305 DoPrintf("## send() OK");
\r
1309 Error = WSAGetLastError();
\r
1311 if(BackgrndMessageProc() == YES)
\r
1314 // 送信バッファ確認をバイパスしたためここでタイムアウトの確認
\r
1315 if(BackgrndMessageProc() == YES)
\r
1316 *CancelCheckWork = YES;
\r
1317 else if(TimeOut != 0)
\r
1319 time(&ElapseTime);
\r
1320 ElapseTime -= StartTime;
\r
1321 if(ElapseTime >= TimeOut)
\r
1323 DoPrintf("do_recv timed out");
\r
1324 *TimeOutErr = YES;
\r
1325 *CancelCheckWork = YES;
\r
1328 if(*CancelCheckWork == YES)
\r
1331 while(Error == WSAEWOULDBLOCK);
\r
1334 if(BackgrndMessageProc() == YES)
\r
1335 Ret = SOCKET_ERROR;
\r
1338 DoPrintf("# Exit send (%d)", Ret);
\r
1342 return(send(s, buf, len, flags));
\r
1348 void RemoveReceivedData(SOCKET s)
\r
1353 while((len = FTPS_recv(s, buf, sizeof(buf), MSG_PEEK)) > 0)
\r
1355 // AskAsyncDone(s, &Error, FD_READ);
\r
1356 FTPS_recv(s, buf, len, 0);
\r
1365 if(CoCreateInstance(&CLSID_UPnPNAT, NULL, CLSCTX_ALL, &IID_IUPnPNAT, (void**)&pUPnPNAT) == S_OK)
\r
1367 if(pUPnPNAT->lpVtbl->get_StaticPortMappingCollection(pUPnPNAT, &pUPnPMap) == S_OK)
\r
1368 Sts = FFFTP_SUCCESS;
\r
1375 if(pUPnPMap != NULL)
\r
1376 pUPnPMap->lpVtbl->Release(pUPnPMap);
\r
1378 if(pUPnPNAT != NULL)
\r
1379 pUPnPNAT->lpVtbl->Release(pUPnPNAT);
\r
1383 int IsUPnPLoaded()
\r
1387 if(pUPnPNAT != NULL && pUPnPMap != NULL)
\r
1392 int AddPortMapping(char* Adrs, int Port)
\r
1399 IStaticPortMapping* pPortMap;
\r
1401 MtoW(Tmp1, 40, Adrs, -1);
\r
1402 if((Tmp2 = SysAllocString(Tmp1)) != NULL)
\r
1404 if((Tmp3 = SysAllocString(L"TCP")) != NULL)
\r
1406 if((Tmp4 = SysAllocString(L"FFFTP")) != NULL)
\r
1408 if(pUPnPMap->lpVtbl->Add(pUPnPMap, Port, Tmp3, Port, Tmp2, VARIANT_TRUE, Tmp4, &pPortMap) == S_OK)
\r
1410 Sts = FFFTP_SUCCESS;
\r
1411 pPortMap->lpVtbl->Release(pPortMap);
\r
1413 SysFreeString(Tmp4);
\r
1415 SysFreeString(Tmp3);
\r
1417 SysFreeString(Tmp2);
\r
1422 int RemovePortMapping(int Port)
\r
1427 if((Tmp = SysAllocString(L"TCP")) != NULL)
\r
1429 if(pUPnPMap->lpVtbl->Remove(pUPnPMap, Port, Tmp) == S_OK)
\r
1430 Sts = FFFTP_SUCCESS;
\r
1431 SysFreeString(Tmp);
\r
1443 * FFFTP_SUCCESS/FFFTP_FAIL
\r
1444 *----------------------------------------------------------------------------*/
\r
1446 int CheckClosedAndReconnect(void)
\r
1451 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
\r
1453 Sts = FFFTP_SUCCESS;
\r
1454 if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE) == YES)
\r
1456 Sts = ReConnectCmdSkt();
\r
1464 int CheckClosedAndReconnectTrnSkt(SOCKET *Skt, int *CancelCheckWork)
\r
1469 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
\r
1471 Sts = FFFTP_SUCCESS;
\r
1472 if(AskAsyncDone(*Skt, &Error, FD_CLOSE) == YES)
\r
1474 Sts = ReConnectTrnSkt(Skt, CancelCheckWork);
\r