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
42 #include "resource.h"
\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
76 } ASYNCSIGNALDATABASE;
\r
81 //#define MAX_SIGNAL_ENTRY 10
\r
82 //#define MAX_SIGNAL_ENTRY_DBASE 5
\r
83 #define MAX_SIGNAL_ENTRY 16
\r
84 #define MAX_SIGNAL_ENTRY_DBASE 16
\r
89 /*===== プロトタイプ =====*/
\r
91 static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
\r
92 static int AskAsyncDone(SOCKET s, int *Error, int Mask);
\r
93 static int AskAsyncDoneDbase(HANDLE Async, int *Error);
\r
94 static int RegistAsyncTable(SOCKET s);
\r
95 static int RegistAsyncTableDbase(HANDLE Async);
\r
96 static int UnRegistAsyncTable(SOCKET s);
\r
97 static int UnRegistAsyncTableDbase(HANDLE Async);
\r
100 /*===== 外部参照 =====*/
\r
102 extern int TimeOut;
\r
105 /*===== ローカルなワーク =====*/
\r
107 static const char SocketWndClass[] = "FFFTPSocketWnd";
\r
108 static HWND hWndSocket;
\r
110 static ASYNCSIGNAL Signal[MAX_SIGNAL_ENTRY];
\r
111 static ASYNCSIGNALDATABASE SignalDbase[MAX_SIGNAL_ENTRY_DBASE];
\r
113 //static HANDLE hAsyncTblAccMutex;
\r
115 static HANDLE hAsyncTblAccMutex;
\r
127 * FFFTP_SUCCESS/FFFTP_FAIL
\r
128 *----------------------------------------------------------------------------*/
\r
130 int MakeSocketWin(HWND hWnd, HINSTANCE hInst)
\r
136 wClass.cbSize = sizeof(WNDCLASSEX);
\r
138 wClass.lpfnWndProc = SocketWndProc;
\r
139 wClass.cbClsExtra = 0;
\r
140 wClass.cbWndExtra = 0;
\r
141 wClass.hInstance = hInst;
\r
142 wClass.hIcon = NULL;
\r
143 wClass.hCursor = NULL;
\r
144 wClass.hbrBackground = (HBRUSH)CreateSolidBrush(GetSysColor(COLOR_INFOBK));
\r
145 wClass.lpszMenuName = NULL;
\r
146 wClass.lpszClassName = SocketWndClass;
\r
147 wClass.hIconSm = NULL;
\r
148 RegisterClassEx(&wClass);
\r
151 hWndSocket = CreateWindowEx(0, SocketWndClass, NULL,
\r
152 WS_BORDER | WS_POPUP,
\r
154 hWnd, NULL, hInst, NULL);
\r
156 if(hWndSocket != NULL)
\r
158 // hAsyncTblAccMutex = CreateMutex(NULL, FALSE, NULL);
\r
161 // for(i = 0; i < MAX_SIGNAL_ENTRY; i++)
\r
162 // Signal[i].Socket = INVALID_SOCKET;
\r
163 // for(i = 0; i < MAX_SIGNAL_ENTRY_DBASE; i++)
\r
164 // SignalDbase[i].Async = 0;
\r
165 if(hAsyncTblAccMutex = CreateMutex(NULL, FALSE, NULL))
\r
167 for(i = 0; i < MAX_SIGNAL_ENTRY; i++)
\r
168 Signal[i].Socket = INVALID_SOCKET;
\r
169 for(i = 0; i < MAX_SIGNAL_ENTRY_DBASE; i++)
\r
170 SignalDbase[i].Async = 0;
\r
172 Sts = FFFTP_SUCCESS;
\r
185 *----------------------------------------------------------------------------*/
\r
187 void DeleteSocketWin(void)
\r
189 // CloseHandle(hAsyncTblAccMutex);
\r
191 CloseHandle(hAsyncTblAccMutex);
\r
192 hAsyncTblAccMutex = NULL;
\r
194 if(hWndSocket != NULL)
\r
195 DestroyWindow(hWndSocket);
\r
203 * HWND hWnd : ウインドウハンドル
\r
204 * UINT message : メッセージ番号
\r
205 * WPARAM wParam : メッセージの WPARAM 引数
\r
206 * LPARAM lParam : メッセージの LPARAM 引数
\r
210 *----------------------------------------------------------------------------*/
\r
212 static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
218 case WM_ASYNC_SOCKET :
\r
220 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
221 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
223 if(Signal[Pos].Socket == (SOCKET)wParam)
\r
225 Signal[Pos].Error = WSAGETSELECTERROR(lParam);
\r
227 if(WSAGETSELECTERROR(lParam) != 0)
\r
228 DoPrintf("####### Signal: error (%d)", WSAGETSELECTERROR(lParam));
\r
231 switch(WSAGETSELECTEVENT(lParam))
\r
234 Signal[Pos].FdConnect = 1;
\r
236 DoPrintf("####### Signal: connect (S=%x)", Signal[Pos].Socket);
\r
241 Signal[Pos].FdClose = 1;
\r
243 DoPrintf("####### Signal: close (S=%x)", Signal[Pos].Socket);
\r
245 //SetTaskMsg("####### Signal: close (%d) (S=%x)", Pos, Signal[Pos].Socket);
\r
249 Signal[Pos].FdAccept = 1;
\r
251 DoPrintf("####### Signal: accept (S=%x)", Signal[Pos].Socket);
\r
256 Signal[Pos].FdRead = 1;
\r
258 DoPrintf("####### Signal: read (S=%x)", Signal[Pos].Socket);
\r
263 Signal[Pos].FdWrite = 1;
\r
265 DoPrintf("####### Signal: write (S=%x)", Signal[Pos].Socket);
\r
273 ReleaseMutex(hAsyncTblAccMutex);
\r
276 case WM_ASYNC_DBASE :
\r
277 // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり
\r
278 RegistAsyncTableDbase((HANDLE)wParam);
\r
280 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
281 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)
\r
283 if(SignalDbase[Pos].Async == (HANDLE)wParam)
\r
285 if(HIWORD(lParam) != 0)
\r
287 SignalDbase[Pos].ErrorDb = 1;
\r
289 DoPrintf("##### SignalDatabase: error");
\r
292 SignalDbase[Pos].Done = 1;
\r
294 DoPrintf("##### SignalDatabase: Done");
\r
300 ReleaseMutex(hAsyncTblAccMutex);
\r
304 return(DefWindowProc(hWnd, message, wParam, lParam));
\r
319 *----------------------------------------------------------------------------*/
\r
321 static int AskAsyncDone(SOCKET s, int *Error, int Mask)
\r
327 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
330 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
332 if(Signal[Pos].Socket == s)
\r
334 *Error = Signal[Pos].Error;
\r
335 if(Signal[Pos].Error != 0)
\r
337 if((Mask & FD_CONNECT) && (Signal[Pos].FdConnect != 0))
\r
341 DoPrintf("### Ask: connect (Sts=%d, Error=%d)", Sts, *Error);
\r
344 if((Mask & FD_CLOSE) && (Signal[Pos].FdClose != 0))
\r
345 // if(Mask & FD_CLOSE)
\r
349 DoPrintf("### Ask: close (Sts=%d, Error=%d)", Sts, *Error);
\r
352 if((Mask & FD_ACCEPT) && (Signal[Pos].FdAccept != 0))
\r
354 Signal[Pos].FdAccept = 0;
\r
357 DoPrintf("### Ask: accept (Sts=%d, Error=%d)", Sts, *Error);
\r
360 if((Mask & FD_READ) && (Signal[Pos].FdRead != 0))
\r
362 Signal[Pos].FdRead = 0;
\r
365 DoPrintf("### Ask: read (Sts=%d, Error=%d)", Sts, *Error);
\r
368 if((Mask & FD_WRITE) && (Signal[Pos].FdWrite != 0))
\r
370 Signal[Pos].FdWrite = 0;
\r
373 DoPrintf("### Ask: write (Sts=%d, Error=%d)", Sts, *Error);
\r
380 ReleaseMutex(hAsyncTblAccMutex);
\r
382 if(Pos == MAX_SIGNAL_ENTRY)
\r
384 if(Mask & FD_CLOSE)
\r
390 MessageBox(GetMainHwnd(), "AskAsyncDone called with unregisterd socket.", "FFFTP inner error", MB_OK);
\r
405 *----------------------------------------------------------------------------*/
\r
407 static int AskAsyncDoneDbase(HANDLE Async, int *Error)
\r
413 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
416 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)
\r
418 if(SignalDbase[Pos].Async == Async)
\r
420 if(SignalDbase[Pos].Done != 0)
\r
422 *Error = SignalDbase[Pos].ErrorDb;
\r
425 DoPrintf("### Ask: Dbase (Sts=%d, Error=%d)", Sts, *Error);
\r
432 ReleaseMutex(hAsyncTblAccMutex);
\r
434 if(Pos == MAX_SIGNAL_ENTRY_DBASE)
\r
436 MessageBox(GetMainHwnd(), "AskAsyncDoneDbase called with unregisterd handle.", "FFFTP inner error", MB_OK);
\r
451 *----------------------------------------------------------------------------*/
\r
453 static int RegistAsyncTable(SOCKET s)
\r
459 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
461 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
463 if(Signal[Pos].Socket == s)
\r
465 // 強制的に閉じられたソケットがあると重複する可能性あり
\r
466 // MessageBox(GetMainHwnd(), "Async socket already registerd.", "FFFTP inner error", MB_OK);
\r
468 Signal[Pos].Socket = INVALID_SOCKET;
\r
472 ReleaseMutex(hAsyncTblAccMutex);
\r
474 if(Pos == MAX_SIGNAL_ENTRY)
\r
477 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
478 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
480 if(Signal[Pos].Socket == INVALID_SOCKET)
\r
483 //SetTaskMsg("############### Regist socket (%d)", Pos);
\r
485 Signal[Pos].Socket = s;
\r
486 Signal[Pos].Error = 0;
\r
487 Signal[Pos].FdConnect = 0;
\r
488 Signal[Pos].FdClose = 0;
\r
489 Signal[Pos].FdAccept = 0;
\r
490 Signal[Pos].FdRead = 0;
\r
491 Signal[Pos].FdWrite = 0;
\r
497 ReleaseMutex(hAsyncTblAccMutex);
\r
499 if(Pos == MAX_SIGNAL_ENTRY)
\r
501 MessageBox(GetMainHwnd(), "No more async regist space.", "FFFTP inner error", MB_OK);
\r
517 *----------------------------------------------------------------------------*/
\r
519 static int RegistAsyncTableDbase(HANDLE Async)
\r
525 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
527 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)
\r
529 if(SignalDbase[Pos].Async == Async)
\r
531 // 強制的に閉じられたハンドルがあると重複する可能性あり
\r
532 // MessageBox(GetMainHwnd(), "Async handle already registerd.", "FFFTP inner error", MB_OK);
\r
533 // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり
\r
538 ReleaseMutex(hAsyncTblAccMutex);
\r
540 if(Pos == MAX_SIGNAL_ENTRY_DBASE)
\r
543 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
544 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
546 if(SignalDbase[Pos].Async == 0)
\r
549 //SetTaskMsg("############### Regist dbase (%d)", Pos);
\r
551 SignalDbase[Pos].Async = Async;
\r
552 SignalDbase[Pos].Done = 0;
\r
553 SignalDbase[Pos].ErrorDb = 0;
\r
559 ReleaseMutex(hAsyncTblAccMutex);
\r
561 if(Pos == MAX_SIGNAL_ENTRY_DBASE)
\r
563 MessageBox(GetMainHwnd(), "No more async dbase regist space.", "FFFTP inner error", MB_OK);
\r
579 *----------------------------------------------------------------------------*/
\r
581 static int UnRegistAsyncTable(SOCKET s)
\r
587 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
589 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
591 if(Signal[Pos].Socket == s)
\r
594 //SetTaskMsg("############### UnRegist socket (%d)", Pos);
\r
596 Signal[Pos].Socket = INVALID_SOCKET;
\r
602 ReleaseMutex(hAsyncTblAccMutex);
\r
614 *----------------------------------------------------------------------------*/
\r
616 static int UnRegistAsyncTableDbase(HANDLE Async)
\r
622 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
624 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)
\r
626 if(SignalDbase[Pos].Async == Async)
\r
629 //SetTaskMsg("############### UnRegist dbase (%d)", Pos);
\r
631 SignalDbase[Pos].Async = 0;
\r
637 ReleaseMutex(hAsyncTblAccMutex);
\r
649 //struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *CancelCheckWork)
\r
650 struct hostent *do_gethostbynameIPv4(const char *Name, char *Buf, int Len, int *CancelCheckWork)
\r
653 struct hostent *Ret;
\r
658 DoPrintf("# Start gethostbyname");
\r
662 // *CancelCheckWork = NO;
\r
665 // hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);
\r
666 hAsync = WSAAsyncGetHostByNameM(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);
\r
669 RegistAsyncTableDbase(hAsync);
\r
670 while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))
\r
673 if(BackgrndMessageProc() == YES)
\r
674 *CancelCheckWork = YES;
\r
677 if(*CancelCheckWork == YES)
\r
679 WSACancelAsyncRequest(hAsync);
\r
681 else if(Error == 0)
\r
683 Ret = (struct hostent *)Buf;
\r
685 UnRegistAsyncTableDbase(hAsync);
\r
689 return(gethostbyname(Name));
\r
694 struct hostent *do_gethostbynameIPv6(const char *Name, char *Buf, int Len, int *CancelCheckWork)
\r
697 struct hostent *Ret;
\r
702 DoPrintf("# Start gethostbyname");
\r
706 // *CancelCheckWork = NO;
\r
709 // hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);
\r
710 hAsync = WSAAsyncGetHostByNameIPv6M(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len, AF_INET6);
\r
713 RegistAsyncTableDbase(hAsync);
\r
714 while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))
\r
717 if(BackgrndMessageProc() == YES)
\r
718 *CancelCheckWork = YES;
\r
721 if(*CancelCheckWork == YES)
\r
723 WSACancelAsyncRequest(hAsync);
\r
725 else if(Error == 0)
\r
727 Ret = (struct hostent *)Buf;
\r
729 UnRegistAsyncTableDbase(hAsync);
\r
733 return(gethostbyname(Name));
\r
741 SOCKET do_socket(int af, int type, int protocol)
\r
745 Ret = socket(af, type, protocol);
\r
746 if(Ret != INVALID_SOCKET)
\r
748 RegistAsyncTable(Ret);
\r
751 DoPrintf("# do_socket (S=%x)", Ret);
\r
758 int do_closesocket(SOCKET s)
\r
763 int CancelCheckWork;
\r
766 DoPrintf("# Start close (S=%x)", s);
\r
768 CancelCheckWork = NO;
\r
771 WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);
\r
772 UnRegistAsyncTable(s);
\r
774 // Ret = closesocket(s);
\r
775 Ret = FTPS_closesocket(s);
\r
776 if(Ret == SOCKET_ERROR)
\r
779 while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CLOSE) != YES))
\r
782 if(BackgrndMessageProc() == YES)
\r
783 CancelCheckWork = YES;
\r
786 if((CancelCheckWork == NO) && (Error == 0))
\r
791 // WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);
\r
792 if(BackgrndMessageProc() == YES)
\r
793 CancelCheckWork = YES;
\r
795 // UnRegistAsyncTable(s);
\r
798 DoPrintf("# Exit close");
\r
802 return(closesocket(s));
\r
811 int do_connect(SOCKET s, const struct sockaddr *name, int namelen, int *CancelCheckWork)
\r
818 DoPrintf("# Start connect (S=%x)", s);
\r
821 // *CancelCheckWork = NO;
\r
824 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");
\r
826 // 高速化のためFD_READとFD_WRITEを使用しない
\r
827 // Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);
\r
828 Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT);
\r
829 if(Ret != SOCKET_ERROR)
\r
831 Ret = connect(s, name, namelen);
\r
832 if(Ret == SOCKET_ERROR)
\r
837 while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CONNECT) != YES))
\r
840 if(BackgrndMessageProc() == YES)
\r
841 *CancelCheckWork = YES;
\r
844 if(*CancelCheckWork == YES)
\r
850 // Error = WSAGetLastError();
\r
851 DoPrintf("#### Connect: Error=%d", Error);
\r
854 while((Ret != 0) && (Error == WSAEWOULDBLOCK));
\r
858 DoPrintf("#### Connect: AsyncSelect error (%d)", WSAGetLastError());
\r
861 DoPrintf("# Exit connect (%d)", Ret);
\r
865 return(connect(s, name, namelen));
\r
873 int do_listen(SOCKET s, int backlog)
\r
879 DoPrintf("# Start listen (S=%x)", s);
\r
880 DoPrintf("## Async set: FD_CLOSE|FD_ACCEPT");
\r
883 Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CLOSE | FD_ACCEPT);
\r
884 if(Ret != SOCKET_ERROR)
\r
885 Ret = listen(s, backlog);
\r
888 DoPrintf("# Exit listen (%d)", Ret);
\r
895 SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
\r
899 int CancelCheckWork;
\r
903 DoPrintf("# Start accept (S=%x)", s);
\r
905 CancelCheckWork = NO;
\r
906 Ret2 = INVALID_SOCKET;
\r
909 while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_ACCEPT) != YES))
\r
911 if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)
\r
917 if(BackgrndMessageProc() == YES)
\r
918 CancelCheckWork = YES;
\r
921 if((CancelCheckWork == NO) && (Error == 0))
\r
925 Ret2 = accept(s, addr, addrlen);
\r
926 if(Ret2 != INVALID_SOCKET)
\r
929 DoPrintf("## do_sccept (S=%x)", Ret2);
\r
930 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");
\r
932 RegistAsyncTable(Ret2);
\r
933 // 高速化のためFD_READとFD_WRITEを使用しない
\r
934 // if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR)
\r
935 if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT) == SOCKET_ERROR)
\r
937 do_closesocket(Ret2);
\r
938 Ret2 = INVALID_SOCKET;
\r
942 Error = WSAGetLastError();
\r
944 if(BackgrndMessageProc() == YES)
\r
947 while(Error == WSAEWOULDBLOCK);
\r
951 DoPrintf("# Exit accept");
\r
955 return(accept(s, addr, addrlen));
\r
962 /*----- recv相当の関数 --------------------------------------------------------
\r
966 * char *buf : データを読み込むバッファ
\r
968 * int flags : recvに与えるフラグ
\r
969 * int *TimeOutErr : タイムアウトしたかどうかを返すワーク
\r
972 * int : recvの戻り値と同じ
\r
975 * タイムアウトの時は TimeOut=YES、Ret=SOCKET_ERROR になる
\r
976 *----------------------------------------------------------------------------*/
\r
977 int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)
\r
986 DoPrintf("# Start recv (S=%x)", s);
\r
990 // *CancelCheckWork = NO;
\r
991 Ret = SOCKET_ERROR;
\r
998 // OpenSSLでは受信確認はFD_READが複数回受信される可能性がある
\r
999 // while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ) != YES))
\r
1000 // 短時間にFD_READが2回以上通知される対策
\r
1001 // while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ) != YES))
\r
1003 // if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)
\r
1009 // if(BackgrndMessageProc() == YES)
\r
1010 // *CancelCheckWork = YES;
\r
1011 // else if(TimeOut != 0)
\r
1013 // time(&ElapseTime);
\r
1014 // ElapseTime -= StartTime;
\r
1015 // if(ElapseTime >= TimeOut)
\r
1017 // DoPrintf("do_recv timed out");
\r
1018 // *TimeOutErr = YES;
\r
1019 // *CancelCheckWork = YES;
\r
1024 if(/*(Ret != 0) && */(Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))
\r
1029 DoPrintf("## recv()");
\r
1033 // Ret = recv(s, buf, len, flags);
\r
1034 Ret = FTPS_recv(s, buf, len, flags);
\r
1035 if(Ret != SOCKET_ERROR)
\r
1037 Error = WSAGetLastError();
\r
1039 if(BackgrndMessageProc() == YES)
\r
1042 // 受信確認をバイパスしたためここでタイムアウトの確認
\r
1043 if(BackgrndMessageProc() == YES)
\r
1044 *CancelCheckWork = YES;
\r
1045 else if(TimeOut != 0)
\r
1047 time(&ElapseTime);
\r
1048 ElapseTime -= StartTime;
\r
1049 if(ElapseTime >= TimeOut)
\r
1051 DoPrintf("do_recv timed out");
\r
1052 *TimeOutErr = YES;
\r
1053 *CancelCheckWork = YES;
\r
1056 if(*CancelCheckWork == YES)
\r
1059 while(Error == WSAEWOULDBLOCK);
\r
1062 if(BackgrndMessageProc() == YES)
\r
1063 Ret = SOCKET_ERROR;
\r
1066 DoPrintf("# Exit recv (%d)", Ret);
\r
1070 return(recv(s, buf, len, flags));
\r
1076 int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)
\r
1081 time_t ElapseTime;
\r
1085 DoPrintf("# Start send (S=%x)", s);
\r
1089 // *CancelCheckWork = NO;
\r
1090 Ret = SOCKET_ERROR;
\r
1097 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");
\r
1099 // Windows 2000でFD_WRITEが通知されないことがあるバグ修正
\r
1100 // 毎回通知されたのはNT 4.0までのバグであり仕様ではない
\r
1101 // XP以降は互換性のためか毎回通知される
\r
1102 // WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);
\r
1103 if(BackgrndMessageProc() == YES)
\r
1104 *CancelCheckWork = YES;
\r
1107 // 送信バッファの空き確認には影響しないが念のため
\r
1108 // while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE) != YES))
\r
1109 // Windows 2000でFD_WRITEが通知されないことがあるバグ修正
\r
1110 // while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE) != YES))
\r
1112 // if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)
\r
1119 // if(BackgrndMessageProc() == YES)
\r
1120 // *CancelCheckWork = YES;
\r
1121 // else if(TimeOut != 0)
\r
1123 // time(&ElapseTime);
\r
1124 // ElapseTime -= StartTime;
\r
1125 // if(ElapseTime >= TimeOut)
\r
1127 // DoPrintf("do_write timed out");
\r
1128 // *TimeOutErr = YES;
\r
1129 // *CancelCheckWork = YES;
\r
1134 if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))
\r
1139 DoPrintf("## send()");
\r
1143 // Ret = send(s, buf, len, flags);
\r
1144 Ret = FTPS_send(s, buf, len, flags);
\r
1145 if(Ret != SOCKET_ERROR)
\r
1148 DoPrintf("## send() OK");
\r
1152 Error = WSAGetLastError();
\r
1154 if(BackgrndMessageProc() == YES)
\r
1157 // 送信バッファ確認をバイパスしたためここでタイムアウトの確認
\r
1158 if(BackgrndMessageProc() == YES)
\r
1159 *CancelCheckWork = YES;
\r
1160 else if(TimeOut != 0)
\r
1162 time(&ElapseTime);
\r
1163 ElapseTime -= StartTime;
\r
1164 if(ElapseTime >= TimeOut)
\r
1166 DoPrintf("do_recv timed out");
\r
1167 *TimeOutErr = YES;
\r
1168 *CancelCheckWork = YES;
\r
1171 if(*CancelCheckWork == YES)
\r
1174 while(Error == WSAEWOULDBLOCK);
\r
1177 if(BackgrndMessageProc() == YES)
\r
1178 Ret = SOCKET_ERROR;
\r
1181 DoPrintf("# Exit send (%d)", Ret);
\r
1185 return(send(s, buf, len, flags));
\r
1191 void RemoveReceivedData(SOCKET s)
\r
1196 while((len = FTPS_recv(s, buf, sizeof(buf), MSG_PEEK)) > 0)
\r
1198 // AskAsyncDone(s, &Error, FD_READ);
\r
1199 FTPS_recv(s, buf, len, 0);
\r
1210 * FFFTP_SUCCESS/FFFTP_FAIL
\r
1211 *----------------------------------------------------------------------------*/
\r
1213 int CheckClosedAndReconnect(void)
\r
1218 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
\r
1220 Sts = FFFTP_SUCCESS;
\r
1221 if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE) == YES)
\r
1223 Sts = ReConnectCmdSkt();
\r
1231 int CheckClosedAndReconnectTrnSkt(SOCKET *Skt, int *CancelCheckWork)
\r
1236 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
\r
1238 Sts = FFFTP_SUCCESS;
\r
1239 if(AskAsyncDone(*Skt, &Error, FD_CLOSE) == YES)
\r
1241 Sts = ReConnectTrnSkt(Skt, CancelCheckWork);
\r