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
31 #include <windows.h>
\r
36 #include <windowsx.h>
\r
37 #include <commctrl.h>
\r
40 #include "resource.h"
\r
42 #include "punycode.h"
\r
50 #define FD_CONNECT_BIT 0x0001
\r
51 #define FD_CLOSE_BIT 0x0002
\r
52 #define FD_ACCEPT_BIT 0x0004
\r
53 #define FD_READ_BIT 0x0008
\r
54 #define FD_WRITE_BIT 0x0010
\r
75 } ASYNCSIGNALDATABASE;
\r
80 //#define MAX_SIGNAL_ENTRY 10
\r
81 //#define MAX_SIGNAL_ENTRY_DBASE 5
\r
82 #define MAX_SIGNAL_ENTRY 100
\r
83 #define MAX_SIGNAL_ENTRY_DBASE 50
\r
88 /*===== プロトタイプ =====*/
\r
90 static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
\r
91 static int AskAsyncDone(SOCKET s, int *Error, int Mask);
\r
92 static int AskAsyncDoneDbase(HANDLE Async, int *Error);
\r
93 static int RegistAsyncTable(SOCKET s);
\r
94 static int RegistAsyncTableDbase(HANDLE Async);
\r
95 static int UnRegistAsyncTable(SOCKET s);
\r
96 static int UnRegistAsyncTableDbase(HANDLE Async);
\r
98 static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen);
\r
101 /*===== 外部参照 =====*/
\r
103 extern int TimeOut;
\r
106 /*===== ローカルなワーク =====*/
\r
108 static const char SocketWndClass[] = "FFFTPSocketWnd";
\r
109 static HWND hWndSocket;
\r
111 static ASYNCSIGNAL Signal[MAX_SIGNAL_ENTRY];
\r
112 static ASYNCSIGNALDATABASE SignalDbase[MAX_SIGNAL_ENTRY_DBASE];
\r
114 //static HANDLE hAsyncTblAccMutex;
\r
116 static HANDLE hAsyncTblAccMutex;
\r
128 * FFFTP_SUCCESS/FFFTP_FAIL
\r
129 *----------------------------------------------------------------------------*/
\r
131 int MakeSocketWin(HWND hWnd, HINSTANCE hInst)
\r
137 wClass.cbSize = sizeof(WNDCLASSEX);
\r
139 wClass.lpfnWndProc = SocketWndProc;
\r
140 wClass.cbClsExtra = 0;
\r
141 wClass.cbWndExtra = 0;
\r
142 wClass.hInstance = hInst;
\r
143 wClass.hIcon = NULL;
\r
144 wClass.hCursor = NULL;
\r
145 wClass.hbrBackground = (HBRUSH)CreateSolidBrush(GetSysColor(COLOR_INFOBK));
\r
146 wClass.lpszMenuName = NULL;
\r
147 wClass.lpszClassName = SocketWndClass;
\r
148 wClass.hIconSm = NULL;
\r
149 RegisterClassEx(&wClass);
\r
152 hWndSocket = CreateWindowEx(0, SocketWndClass, NULL,
\r
153 WS_BORDER | WS_POPUP,
\r
155 hWnd, NULL, hInst, NULL);
\r
157 if(hWndSocket != NULL)
\r
159 // hAsyncTblAccMutex = CreateMutex(NULL, FALSE, NULL);
\r
162 // for(i = 0; i < MAX_SIGNAL_ENTRY; i++)
\r
163 // Signal[i].Socket = INVALID_SOCKET;
\r
164 // for(i = 0; i < MAX_SIGNAL_ENTRY_DBASE; i++)
\r
165 // SignalDbase[i].Async = 0;
\r
166 if(hAsyncTblAccMutex = CreateMutex(NULL, FALSE, NULL))
\r
168 for(i = 0; i < MAX_SIGNAL_ENTRY; i++)
\r
169 Signal[i].Socket = INVALID_SOCKET;
\r
170 for(i = 0; i < MAX_SIGNAL_ENTRY_DBASE; i++)
\r
171 SignalDbase[i].Async = 0;
\r
173 Sts = FFFTP_SUCCESS;
\r
186 *----------------------------------------------------------------------------*/
\r
188 void DeleteSocketWin(void)
\r
190 // CloseHandle(hAsyncTblAccMutex);
\r
192 CloseHandle(hAsyncTblAccMutex);
\r
193 hAsyncTblAccMutex = NULL;
\r
195 if(hWndSocket != NULL)
\r
196 DestroyWindow(hWndSocket);
\r
204 * HWND hWnd : ウインドウハンドル
\r
205 * UINT message : メッセージ番号
\r
206 * WPARAM wParam : メッセージの WPARAM 引数
\r
207 * LPARAM lParam : メッセージの LPARAM 引数
\r
211 *----------------------------------------------------------------------------*/
\r
213 static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
\r
219 case WM_ASYNC_SOCKET :
\r
221 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
222 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
224 if(Signal[Pos].Socket == (SOCKET)wParam)
\r
226 Signal[Pos].Error = WSAGETSELECTERROR(lParam);
\r
228 if(WSAGETSELECTERROR(lParam) != 0)
\r
229 DoPrintf("####### Signal: error (%d)", WSAGETSELECTERROR(lParam));
\r
232 switch(WSAGETSELECTEVENT(lParam))
\r
235 Signal[Pos].FdConnect = 1;
\r
237 DoPrintf("####### Signal: connect (S=%x)", Signal[Pos].Socket);
\r
242 Signal[Pos].FdClose = 1;
\r
244 DoPrintf("####### Signal: close (S=%x)", Signal[Pos].Socket);
\r
246 //SetTaskMsg("####### Signal: close (%d) (S=%x)", Pos, Signal[Pos].Socket);
\r
250 Signal[Pos].FdAccept = 1;
\r
252 DoPrintf("####### Signal: accept (S=%x)", Signal[Pos].Socket);
\r
257 Signal[Pos].FdRead = 1;
\r
259 DoPrintf("####### Signal: read (S=%x)", Signal[Pos].Socket);
\r
264 Signal[Pos].FdWrite = 1;
\r
266 DoPrintf("####### Signal: write (S=%x)", Signal[Pos].Socket);
\r
274 ReleaseMutex(hAsyncTblAccMutex);
\r
277 case WM_ASYNC_DBASE :
\r
278 // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり
\r
279 RegistAsyncTableDbase((HANDLE)wParam);
\r
281 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
282 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)
\r
284 if(SignalDbase[Pos].Async == (HANDLE)wParam)
\r
286 if(HIWORD(lParam) != 0)
\r
288 SignalDbase[Pos].ErrorDb = 1;
\r
290 DoPrintf("##### SignalDatabase: error");
\r
293 SignalDbase[Pos].Done = 1;
\r
295 DoPrintf("##### SignalDatabase: Done");
\r
301 ReleaseMutex(hAsyncTblAccMutex);
\r
305 return(DefWindowProc(hWnd, message, wParam, lParam));
\r
320 *----------------------------------------------------------------------------*/
\r
322 static int AskAsyncDone(SOCKET s, int *Error, int Mask)
\r
328 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
331 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
333 if(Signal[Pos].Socket == s)
\r
335 *Error = Signal[Pos].Error;
\r
336 if(Signal[Pos].Error != 0)
\r
338 if((Mask & FD_CONNECT_BIT) && (Signal[Pos].FdConnect != 0))
\r
342 DoPrintf("### Ask: connect (Sts=%d, Error=%d)", Sts, *Error);
\r
345 if((Mask & FD_CLOSE_BIT) && (Signal[Pos].FdClose != 0))
\r
346 // if(Mask & FD_CLOSE_BIT)
\r
350 DoPrintf("### Ask: close (Sts=%d, Error=%d)", Sts, *Error);
\r
353 if((Mask & FD_ACCEPT_BIT) && (Signal[Pos].FdAccept != 0))
\r
355 Signal[Pos].FdAccept = 0;
\r
358 DoPrintf("### Ask: accept (Sts=%d, Error=%d)", Sts, *Error);
\r
361 if((Mask & FD_READ_BIT) && (Signal[Pos].FdRead != 0))
\r
363 Signal[Pos].FdRead = 0;
\r
366 DoPrintf("### Ask: read (Sts=%d, Error=%d)", Sts, *Error);
\r
369 if((Mask & FD_WRITE_BIT) && (Signal[Pos].FdWrite != 0))
\r
371 Signal[Pos].FdWrite = 0;
\r
374 DoPrintf("### Ask: write (Sts=%d, Error=%d)", Sts, *Error);
\r
381 ReleaseMutex(hAsyncTblAccMutex);
\r
383 if(Pos == MAX_SIGNAL_ENTRY)
\r
385 if(Mask & FD_CLOSE_BIT)
\r
391 MessageBox(GetMainHwnd(), "AskAsyncDone called with unregisterd socket.", "FFFTP inner error", MB_OK);
\r
406 *----------------------------------------------------------------------------*/
\r
408 static int AskAsyncDoneDbase(HANDLE Async, int *Error)
\r
414 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
417 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)
\r
419 if(SignalDbase[Pos].Async == Async)
\r
421 if(SignalDbase[Pos].Done != 0)
\r
423 *Error = SignalDbase[Pos].ErrorDb;
\r
426 DoPrintf("### Ask: Dbase (Sts=%d, Error=%d)", Sts, *Error);
\r
433 ReleaseMutex(hAsyncTblAccMutex);
\r
435 if(Pos == MAX_SIGNAL_ENTRY_DBASE)
\r
437 MessageBox(GetMainHwnd(), "AskAsyncDoneDbase called with unregisterd handle.", "FFFTP inner error", MB_OK);
\r
452 *----------------------------------------------------------------------------*/
\r
454 static int RegistAsyncTable(SOCKET s)
\r
460 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
462 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
464 if(Signal[Pos].Socket == s)
\r
466 // 強制的に閉じられたソケットがあると重複する可能性あり
\r
467 // MessageBox(GetMainHwnd(), "Async socket already registerd.", "FFFTP inner error", MB_OK);
\r
469 Signal[Pos].Socket = INVALID_SOCKET;
\r
473 ReleaseMutex(hAsyncTblAccMutex);
\r
475 if(Pos == MAX_SIGNAL_ENTRY)
\r
478 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
479 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
481 if(Signal[Pos].Socket == INVALID_SOCKET)
\r
484 //SetTaskMsg("############### Regist socket (%d)", Pos);
\r
486 Signal[Pos].Socket = s;
\r
487 Signal[Pos].Error = 0;
\r
488 Signal[Pos].FdConnect = 0;
\r
489 Signal[Pos].FdClose = 0;
\r
490 Signal[Pos].FdAccept = 0;
\r
491 Signal[Pos].FdRead = 0;
\r
492 Signal[Pos].FdWrite = 0;
\r
498 ReleaseMutex(hAsyncTblAccMutex);
\r
500 if(Pos == MAX_SIGNAL_ENTRY)
\r
502 MessageBox(GetMainHwnd(), "No more async regist space.", "FFFTP inner error", MB_OK);
\r
518 *----------------------------------------------------------------------------*/
\r
520 static int RegistAsyncTableDbase(HANDLE Async)
\r
526 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
528 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)
\r
530 if(SignalDbase[Pos].Async == Async)
\r
532 // 強制的に閉じられたハンドルがあると重複する可能性あり
\r
533 // MessageBox(GetMainHwnd(), "Async handle already registerd.", "FFFTP inner error", MB_OK);
\r
534 // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり
\r
539 ReleaseMutex(hAsyncTblAccMutex);
\r
541 if(Pos == MAX_SIGNAL_ENTRY_DBASE)
\r
544 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
545 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
547 if(SignalDbase[Pos].Async == 0)
\r
550 //SetTaskMsg("############### Regist dbase (%d)", Pos);
\r
552 SignalDbase[Pos].Async = Async;
\r
553 SignalDbase[Pos].Done = 0;
\r
554 SignalDbase[Pos].ErrorDb = 0;
\r
560 ReleaseMutex(hAsyncTblAccMutex);
\r
562 if(Pos == MAX_SIGNAL_ENTRY_DBASE)
\r
564 MessageBox(GetMainHwnd(), "No more async dbase regist space.", "FFFTP inner error", MB_OK);
\r
580 *----------------------------------------------------------------------------*/
\r
582 static int UnRegistAsyncTable(SOCKET s)
\r
588 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
590 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)
\r
592 if(Signal[Pos].Socket == s)
\r
595 //SetTaskMsg("############### UnRegist socket (%d)", Pos);
\r
597 Signal[Pos].Socket = INVALID_SOCKET;
\r
603 ReleaseMutex(hAsyncTblAccMutex);
\r
615 *----------------------------------------------------------------------------*/
\r
617 static int UnRegistAsyncTableDbase(HANDLE Async)
\r
623 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);
\r
625 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)
\r
627 if(SignalDbase[Pos].Async == Async)
\r
630 //SetTaskMsg("############### UnRegist dbase (%d)", Pos);
\r
632 SignalDbase[Pos].Async = 0;
\r
638 ReleaseMutex(hAsyncTblAccMutex);
\r
649 struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *CancelCheckWork)
\r
652 struct hostent *Ret;
\r
657 DoPrintf("# Start gethostbyname");
\r
661 // *CancelCheckWork = NO;
\r
664 // hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);
\r
665 hAsync = WSAAsyncGetHostByNameM(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);
\r
668 RegistAsyncTableDbase(hAsync);
\r
669 while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))
\r
672 if(BackgrndMessageProc() == YES)
\r
673 *CancelCheckWork = YES;
\r
676 if(*CancelCheckWork == YES)
\r
678 WSACancelAsyncRequest(hAsync);
\r
680 else if(Error == 0)
\r
682 Ret = (struct hostent *)Buf;
\r
684 UnRegistAsyncTableDbase(hAsync);
\r
688 return(gethostbyname(Name));
\r
696 SOCKET do_socket(int af, int type, int protocol)
\r
700 Ret = socket(af, type, protocol);
\r
701 if(Ret != INVALID_SOCKET)
\r
703 RegistAsyncTable(Ret);
\r
706 DoPrintf("# do_socket (S=%x)", Ret);
\r
713 int do_closesocket(SOCKET s)
\r
718 int CancelCheckWork;
\r
721 DoPrintf("# Start close (S=%x)", s);
\r
723 CancelCheckWork = NO;
\r
726 WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);
\r
727 UnRegistAsyncTable(s);
\r
729 // Ret = closesocket(s);
\r
730 Ret = closesocketS(s);
\r
731 if(Ret == SOCKET_ERROR)
\r
734 while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CLOSE_BIT) != YES))
\r
737 if(BackgrndMessageProc() == YES)
\r
738 CancelCheckWork = YES;
\r
741 if((CancelCheckWork == NO) && (Error == 0))
\r
746 // WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);
\r
747 if(BackgrndMessageProc() == YES)
\r
748 CancelCheckWork = YES;
\r
750 // UnRegistAsyncTable(s);
\r
753 DoPrintf("# Exit close");
\r
757 return(closesocket(s));
\r
766 int do_connect(SOCKET s, const struct sockaddr *name, int namelen, int *CancelCheckWork)
\r
773 DoPrintf("# Start connect (S=%x)", s);
\r
776 // *CancelCheckWork = NO;
\r
779 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");
\r
781 Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);
\r
782 if(Ret != SOCKET_ERROR)
\r
784 Ret = connect(s, name, namelen);
\r
785 if(Ret == SOCKET_ERROR)
\r
790 while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CONNECT_BIT) != YES))
\r
793 if(BackgrndMessageProc() == YES)
\r
794 *CancelCheckWork = YES;
\r
797 if(*CancelCheckWork == YES)
\r
803 // Error = WSAGetLastError();
\r
804 DoPrintf("#### Connect: Error=%d", Error);
\r
807 while((Ret != 0) && (Error == WSAEWOULDBLOCK));
\r
811 DoPrintf("#### Connect: AsyncSelect error (%d)", WSAGetLastError());
\r
814 DoPrintf("# Exit connect (%d)", Ret);
\r
818 return(connect(s, name, namelen));
\r
826 int do_listen(SOCKET s, int backlog)
\r
832 DoPrintf("# Start listen (S=%x)", s);
\r
833 DoPrintf("## Async set: FD_CLOSE|FD_ACCEPT");
\r
836 Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CLOSE | FD_ACCEPT);
\r
837 if(Ret != SOCKET_ERROR)
\r
838 Ret = listen(s, backlog);
\r
841 DoPrintf("# Exit listen (%d)", Ret);
\r
848 SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
\r
852 int CancelCheckWork;
\r
856 DoPrintf("# Start accept (S=%x)", s);
\r
858 CancelCheckWork = NO;
\r
859 Ret2 = INVALID_SOCKET;
\r
862 while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_ACCEPT_BIT) != YES))
\r
864 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)
\r
870 if(BackgrndMessageProc() == YES)
\r
871 CancelCheckWork = YES;
\r
874 if((CancelCheckWork == NO) && (Error == 0))
\r
878 Ret2 = accept(s, addr, addrlen);
\r
879 if(Ret2 != INVALID_SOCKET)
\r
882 DoPrintf("## do_sccept (S=%x)", Ret2);
\r
883 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");
\r
885 RegistAsyncTable(Ret2);
\r
886 if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR)
\r
888 do_closesocket(Ret2);
\r
889 Ret2 = INVALID_SOCKET;
\r
893 Error = WSAGetLastError();
\r
895 if(BackgrndMessageProc() == YES)
\r
898 while(Error == WSAEWOULDBLOCK);
\r
902 DoPrintf("# Exit accept");
\r
906 return(accept(s, addr, addrlen));
\r
913 /*----- recv相当の関数 --------------------------------------------------------
\r
917 * char *buf : データを読み込むバッファ
\r
919 * int flags : recvに与えるフラグ
\r
920 * int *TimeOutErr : タイムアウトしたかどうかを返すワーク
\r
923 * int : recvの戻り値と同じ
\r
926 * タイムアウトの時は TimeOut=YES、Ret=SOCKET_ERROR になる
\r
927 *----------------------------------------------------------------------------*/
\r
928 int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)
\r
937 DoPrintf("# Start recv (S=%x)", s);
\r
941 // *CancelCheckWork = NO;
\r
942 Ret = SOCKET_ERROR;
\r
949 // OpenSSLでは受信確認はFD_READが複数回受信される可能性がある
\r
950 // while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ_BIT) != YES))
\r
951 while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ_BIT) != YES))
\r
953 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)
\r
959 if(BackgrndMessageProc() == YES)
\r
960 *CancelCheckWork = YES;
\r
961 else if(TimeOut != 0)
\r
964 ElapseTime -= StartTime;
\r
965 if(ElapseTime >= TimeOut)
\r
967 DoPrintf("do_recv timed out");
\r
969 *CancelCheckWork = YES;
\r
974 if(/*(Ret != 0) && */(Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))
\r
979 DoPrintf("## recv()");
\r
983 // Ret = recv(s, buf, len, flags);
\r
984 Ret = recvS(s, buf, len, flags);
\r
985 if(Ret != SOCKET_ERROR)
\r
987 Error = WSAGetLastError();
\r
989 if(BackgrndMessageProc() == YES)
\r
992 // 受信確認をバイパスしたためここでタイムアウトの確認
\r
993 if(BackgrndMessageProc() == YES)
\r
994 *CancelCheckWork = YES;
\r
995 else if(TimeOut != 0)
\r
998 ElapseTime -= StartTime;
\r
999 if(ElapseTime >= TimeOut)
\r
1001 DoPrintf("do_recv timed out");
\r
1002 *TimeOutErr = YES;
\r
1003 *CancelCheckWork = YES;
\r
1006 if(*CancelCheckWork == YES)
\r
1009 while(Error == WSAEWOULDBLOCK);
\r
1012 if(BackgrndMessageProc() == YES)
\r
1013 Ret = SOCKET_ERROR;
\r
1016 DoPrintf("# Exit recv (%d)", Ret);
\r
1020 return(recv(s, buf, len, flags));
\r
1026 int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)
\r
1031 time_t ElapseTime;
\r
1035 DoPrintf("# Start send (S=%x)", s);
\r
1039 // *CancelCheckWork = NO;
\r
1040 Ret = SOCKET_ERROR;
\r
1047 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");
\r
1049 // Windows 2000でFD_WRITEが通知されないことがあるバグ修正
\r
1050 // 毎回通知されたのはNT 4.0までのバグであり仕様ではない
\r
1051 // XP以降は互換性のためか毎回通知される
\r
1052 // WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);
\r
1053 if(BackgrndMessageProc() == YES)
\r
1054 *CancelCheckWork = YES;
\r
1057 // 送信バッファの空き確認には影響しないが念のため
\r
1058 // while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))
\r
1059 // Windows 2000でFD_WRITEが通知されないことがあるバグ修正
\r
1060 // while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))
\r
1062 // if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)
\r
1069 // if(BackgrndMessageProc() == YES)
\r
1070 // *CancelCheckWork = YES;
\r
1071 // else if(TimeOut != 0)
\r
1073 // time(&ElapseTime);
\r
1074 // ElapseTime -= StartTime;
\r
1075 // if(ElapseTime >= TimeOut)
\r
1077 // DoPrintf("do_write timed out");
\r
1078 // *TimeOutErr = YES;
\r
1079 // *CancelCheckWork = YES;
\r
1084 if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))
\r
1089 DoPrintf("## send()");
\r
1093 // Ret = send(s, buf, len, flags);
\r
1094 Ret = sendS(s, buf, len, flags);
\r
1095 if(Ret != SOCKET_ERROR)
\r
1098 DoPrintf("## send() OK");
\r
1102 Error = WSAGetLastError();
\r
1104 if(BackgrndMessageProc() == YES)
\r
1107 // 送信バッファ確認をバイパスしたためここでタイムアウトの確認
\r
1108 if(BackgrndMessageProc() == YES)
\r
1109 *CancelCheckWork = YES;
\r
1110 else if(TimeOut != 0)
\r
1112 time(&ElapseTime);
\r
1113 ElapseTime -= StartTime;
\r
1114 if(ElapseTime >= TimeOut)
\r
1116 DoPrintf("do_recv timed out");
\r
1117 *TimeOutErr = YES;
\r
1118 *CancelCheckWork = YES;
\r
1121 if(*CancelCheckWork == YES)
\r
1124 while(Error == WSAEWOULDBLOCK);
\r
1127 if(BackgrndMessageProc() == YES)
\r
1128 Ret = SOCKET_ERROR;
\r
1131 DoPrintf("# Exit send (%d)", Ret);
\r
1135 return(send(s, buf, len, flags));
\r
1141 void RemoveReceivedData(SOCKET s)
\r
1146 while((len = recvS(s, buf, sizeof(buf), MSG_PEEK)) >= 0)
\r
1148 AskAsyncDone(s, &Error, FD_READ_BIT);
\r
1149 recvS(s, buf, len, 0);
\r
1160 * FFFTP_SUCCESS/FFFTP_FAIL
\r
1161 *----------------------------------------------------------------------------*/
\r
1163 int CheckClosedAndReconnect(void)
\r
1168 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
\r
1170 Sts = FFFTP_SUCCESS;
\r
1171 if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE_BIT) == YES)
\r
1173 Sts = ReConnectCmdSkt();
\r
1182 static BOOL ConvertStringToPunycode(LPSTR Output, DWORD Count, LPCSTR Input)
\r
1185 punycode_uint* pUnicode;
\r
1188 LPCSTR InputString;
\r
1189 punycode_uint Length;
\r
1190 punycode_uint OutputLength;
\r
1192 if(pUnicode = malloc(sizeof(punycode_uint) * strlen(Input)))
\r
1196 InputString = Input;
\r
1198 while(*InputString != '\0')
\r
1201 if((*InputString & 0x80) == 0x00)
\r
1202 *p |= (punycode_uint)*InputString & 0x7f;
\r
1203 else if((*InputString & 0xe0) == 0xc0)
\r
1204 *p |= (punycode_uint)*InputString & 0x1f;
\r
1205 else if((*InputString & 0xf0) == 0xe0)
\r
1206 *p |= (punycode_uint)*InputString & 0x0f;
\r
1207 else if((*InputString & 0xf8) == 0xf0)
\r
1208 *p |= (punycode_uint)*InputString & 0x07;
\r
1209 else if((*InputString & 0xfc) == 0xf8)
\r
1210 *p |= (punycode_uint)*InputString & 0x03;
\r
1211 else if((*InputString & 0xfe) == 0xfc)
\r
1212 *p |= (punycode_uint)*InputString & 0x01;
\r
1214 while((*InputString & 0xc0) == 0x80)
\r
1217 *p |= (punycode_uint)*InputString & 0x3f;
\r
1227 if(Count >= strlen("xn--") + 1)
\r
1229 strcpy(Output, "xn--");
\r
1230 OutputLength = Count - strlen("xn--");
\r
1231 if(punycode_encode(Length, pUnicode, NULL, (punycode_uint*)&OutputLength, Output + strlen("xn--")) == punycode_success)
\r
1233 Output[strlen("xn--") + OutputLength] = '\0';
\r
1242 if(Count >= strlen(Input) + 1)
\r
1244 strcpy(Output, Input);
\r
1251 static BOOL ConvertNameToPunycode(LPSTR Output, LPCSTR Input)
\r
1260 Length = strlen(Input);
\r
1261 if(pm0 = AllocateStringM(Length + 1))
\r
1263 if(pm1 = AllocateStringM(Length * 4 + 1))
\r
1265 strcpy(pm0, Input);
\r
1269 if(pNext = strchr(p, '.'))
\r
1274 if(ConvertStringToPunycode(pm1, Length * 4, p))
\r
1275 strcat(Output, pm1);
\r
1277 strcat(Output, ".");
\r
1281 FreeDuplicatedString(pm1);
\r
1283 FreeDuplicatedString(pm0);
\r
1288 static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen)
\r
1292 if(pa0 = AllocateStringA(strlen(name) * 4))
\r
1294 if(ConvertNameToPunycode(pa0, name))
\r
1295 r = WSAAsyncGetHostByName(hWnd, wMsg, pa0, buf, buflen);
\r
1297 FreeDuplicatedString(pa0);
\r