X-Git-Url: http://git.sourceforge.jp/view?p=ffftp%2Fffftp.git;a=blobdiff_plain;f=socket.c;h=db7b69f34feed3c8f30855e4485761c30b5696e5;hp=f2b63f69add6bed7fcadf2c14c428b40e837a6f4;hb=b2a2988febaa229da876d5863ef4bfdf2decc29d;hpb=afd0daade7b7371f57f3b5f8a66b6b8bc640cd0e diff --git a/socket.c b/socket.c index f2b63f6..db7b69f 100644 --- a/socket.c +++ b/socket.c @@ -28,6 +28,8 @@ /============================================================================*/ #define STRICT +// IPv6対応 +#include #include #include #include @@ -38,8 +40,6 @@ #include "common.h" #include "resource.h" -// UTF-8対応 -#include "punycode.h" #define USE_THIS 1 #define DBG_MSG 0 @@ -47,11 +47,12 @@ -#define FD_CONNECT_BIT 0x0001 -#define FD_CLOSE_BIT 0x0002 -#define FD_ACCEPT_BIT 0x0004 -#define FD_READ_BIT 0x0008 -#define FD_WRITE_BIT 0x0010 +// Winsock2で定義される定数と名前が重複し値が異なるため使用不可 +//#define FD_CONNECT_BIT 0x0001 +//#define FD_CLOSE_BIT 0x0002 +//#define FD_ACCEPT_BIT 0x0004 +//#define FD_READ_BIT 0x0008 +//#define FD_WRITE_BIT 0x0010 @@ -79,8 +80,8 @@ typedef struct { // 念のためテーブルを増量 //#define MAX_SIGNAL_ENTRY 10 //#define MAX_SIGNAL_ENTRY_DBASE 5 -#define MAX_SIGNAL_ENTRY 100 -#define MAX_SIGNAL_ENTRY_DBASE 50 +#define MAX_SIGNAL_ENTRY 16 +#define MAX_SIGNAL_ENTRY_DBASE 16 @@ -94,8 +95,6 @@ static int RegistAsyncTable(SOCKET s); static int RegistAsyncTableDbase(HANDLE Async); static int UnRegistAsyncTable(SOCKET s); static int UnRegistAsyncTableDbase(HANDLE Async); -// UTF-8対応 -static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen); /*===== 外部参照 =====*/ @@ -335,22 +334,22 @@ static int AskAsyncDone(SOCKET s, int *Error, int Mask) *Error = Signal[Pos].Error; if(Signal[Pos].Error != 0) Sts = YES; - if((Mask & FD_CONNECT_BIT) && (Signal[Pos].FdConnect != 0)) + if((Mask & FD_CONNECT) && (Signal[Pos].FdConnect != 0)) { Sts = YES; #if DBG_MSG DoPrintf("### Ask: connect (Sts=%d, Error=%d)", Sts, *Error); #endif } - if((Mask & FD_CLOSE_BIT) && (Signal[Pos].FdClose != 0)) -// if(Mask & FD_CLOSE_BIT) + if((Mask & FD_CLOSE) && (Signal[Pos].FdClose != 0)) +// if(Mask & FD_CLOSE) { Sts = YES; #if DBG_MSG DoPrintf("### Ask: close (Sts=%d, Error=%d)", Sts, *Error); #endif } - if((Mask & FD_ACCEPT_BIT) && (Signal[Pos].FdAccept != 0)) + if((Mask & FD_ACCEPT) && (Signal[Pos].FdAccept != 0)) { Signal[Pos].FdAccept = 0; Sts = YES; @@ -358,7 +357,7 @@ static int AskAsyncDone(SOCKET s, int *Error, int Mask) DoPrintf("### Ask: accept (Sts=%d, Error=%d)", Sts, *Error); #endif } - if((Mask & FD_READ_BIT) && (Signal[Pos].FdRead != 0)) + if((Mask & FD_READ) && (Signal[Pos].FdRead != 0)) { Signal[Pos].FdRead = 0; Sts = YES; @@ -366,7 +365,7 @@ static int AskAsyncDone(SOCKET s, int *Error, int Mask) DoPrintf("### Ask: read (Sts=%d, Error=%d)", Sts, *Error); #endif } - if((Mask & FD_WRITE_BIT) && (Signal[Pos].FdWrite != 0)) + if((Mask & FD_WRITE) && (Signal[Pos].FdWrite != 0)) { Signal[Pos].FdWrite = 0; Sts = YES; @@ -382,7 +381,7 @@ static int AskAsyncDone(SOCKET s, int *Error, int Mask) if(Pos == MAX_SIGNAL_ENTRY) { - if(Mask & FD_CLOSE_BIT) + if(Mask & FD_CLOSE) { Sts = YES; } @@ -646,7 +645,9 @@ static int UnRegistAsyncTableDbase(HANDLE Async) -struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *CancelCheckWork) +// IPv6対応 +//struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *CancelCheckWork) +struct hostent *do_gethostbynameIPv4(const char *Name, char *Buf, int Len, int *CancelCheckWork) { #if USE_THIS struct hostent *Ret; @@ -657,7 +658,8 @@ struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *Canc DoPrintf("# Start gethostbyname"); #endif Ret = NULL; - *CancelCheckWork = NO; + // 同時接続対応 +// *CancelCheckWork = NO; // UTF-8対応 // hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len); @@ -689,6 +691,50 @@ struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *Canc } +struct hostent *do_gethostbynameIPv6(const char *Name, char *Buf, int Len, int *CancelCheckWork) +{ +#if USE_THIS + struct hostent *Ret; + HANDLE hAsync; + int Error; + +#if DBG_MSG + DoPrintf("# Start gethostbyname"); +#endif + Ret = NULL; + // 同時接続対応 +// *CancelCheckWork = NO; + + // UTF-8対応 +// hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len); + hAsync = WSAAsyncGetHostByNameIPv6M(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len, AF_INET6); + if(hAsync != NULL) + { + RegistAsyncTableDbase(hAsync); + while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES)) + { + Sleep(1); + if(BackgrndMessageProc() == YES) + *CancelCheckWork = YES; + } + + if(*CancelCheckWork == YES) + { + WSACancelAsyncRequest(hAsync); + } + else if(Error == 0) + { + Ret = (struct hostent *)Buf; + } + UnRegistAsyncTableDbase(hAsync); + } + return(Ret); +#else + return(gethostbyname(Name)); +#endif +} + + @@ -726,11 +772,11 @@ int do_closesocket(SOCKET s) UnRegistAsyncTable(s); // FTPS対応 // Ret = closesocket(s); - Ret = closesocketS(s); + Ret = FTPS_closesocket(s); if(Ret == SOCKET_ERROR) { Error = 0; - while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CLOSE_BIT) != YES)) + while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CLOSE) != YES)) { Sleep(1); if(BackgrndMessageProc() == YES) @@ -771,26 +817,24 @@ int do_connect(SOCKET s, const struct sockaddr *name, int namelen, int *CancelCh #if DBG_MSG DoPrintf("# Start connect (S=%x)", s); #endif - *CancelCheckWork = NO; + // 同時接続対応 +// *CancelCheckWork = NO; #if DBG_MSG DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE"); #endif - Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE); + // 高速化のためFD_READとFD_WRITEを使用しない +// Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE); + Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT); if(Ret != SOCKET_ERROR) { - // FTPS対応 -// Ret = connect(s, name, namelen); - if(AskCryptMode() == CRYPT_FTPIS) - Ret = connectS(s, name, namelen); - else - Ret = connect(s, name, namelen); + Ret = connect(s, name, namelen); if(Ret == SOCKET_ERROR) { do { Error = 0; - while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CONNECT_BIT) != YES)) + while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CONNECT) != YES)) { Sleep(1); if(BackgrndMessageProc() == YES) @@ -862,9 +906,9 @@ SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen) Ret2 = INVALID_SOCKET; Error = 0; - while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_ACCEPT_BIT) != YES)) + while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_ACCEPT) != YES)) { - if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES) + if(AskAsyncDone(s, &Error, FD_CLOSE) == YES) { Error = 1; break; @@ -878,12 +922,7 @@ SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen) { do { - // FTPS対応 -// Ret2 = accept(s, addr, addrlen); - if(AskCryptMode() == CRYPT_FTPIS) - Ret2 = acceptS(s, addr, addrlen); - else - Ret2 = accept(s, addr, addrlen); + Ret2 = accept(s, addr, addrlen); if(Ret2 != INVALID_SOCKET) { #if DBG_MSG @@ -945,7 +984,8 @@ int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *Cance DoPrintf("# Start recv (S=%x)", s); #endif *TimeOutErr = NO; - *CancelCheckWork = NO; + // 同時接続対応 +// *CancelCheckWork = NO; Ret = SOCKET_ERROR; Error = 0; @@ -954,29 +994,30 @@ int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *Cance // FTPS対応 // OpenSSLでは受信確認はFD_READが複数回受信される可能性がある -// while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ_BIT) != YES)) - while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ_BIT) != YES)) - { - if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES) - { - Ret = 0; - break; - } - Sleep(1); - if(BackgrndMessageProc() == YES) - *CancelCheckWork = YES; - else if(TimeOut != 0) - { - time(&ElapseTime); - ElapseTime -= StartTime; - if(ElapseTime >= TimeOut) - { - DoPrintf("do_recv timed out"); - *TimeOutErr = YES; - *CancelCheckWork = YES; - } - } - } +// while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ) != YES)) + // 短時間にFD_READが2回以上通知される対策 +// while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ) != YES)) +// { +// if(AskAsyncDone(s, &Error, FD_CLOSE) == YES) +// { +// Ret = 0; +// break; +// } +// Sleep(1); +// if(BackgrndMessageProc() == YES) +// *CancelCheckWork = YES; +// else if(TimeOut != 0) +// { +// time(&ElapseTime); +// ElapseTime -= StartTime; +// if(ElapseTime >= TimeOut) +// { +// DoPrintf("do_recv timed out"); +// *TimeOutErr = YES; +// *CancelCheckWork = YES; +// } +// } +// } if(/*(Ret != 0) && */(Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO)) { @@ -988,16 +1029,13 @@ int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *Cance // FTPS対応 // Ret = recv(s, buf, len, flags); - Ret = recvS(s, buf, len, flags); + Ret = FTPS_recv(s, buf, len, flags); if(Ret != SOCKET_ERROR) break; Error = WSAGetLastError(); Sleep(1); if(BackgrndMessageProc() == YES) break; - // 何故か一部のホストとWindows 2000の組み合わせで通信できないバグに暫定対応 - if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES) - break; // FTPS対応 // 受信確認をバイパスしたためここでタイムアウトの確認 if(BackgrndMessageProc() == YES) @@ -1045,7 +1083,8 @@ int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int DoPrintf("# Start send (S=%x)", s); #endif *TimeOutErr = NO; - *CancelCheckWork = NO; + // 同時接続対応 +// *CancelCheckWork = NO; Ret = SOCKET_ERROR; Error = 0; @@ -1055,36 +1094,40 @@ int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int #if DBG_MSG DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE"); #endif - WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE); + // Windows 2000でFD_WRITEが通知されないことがあるバグ修正 + // 毎回通知されたのはNT 4.0までのバグであり仕様ではない + // XP以降は互換性のためか毎回通知される +// WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE); if(BackgrndMessageProc() == YES) *CancelCheckWork = YES; // FTPS対応 // 送信バッファの空き確認には影響しないが念のため -// while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES)) - while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES)) - { - if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES) - { - Error = 1; - break; - } - - Sleep(1); - if(BackgrndMessageProc() == YES) - *CancelCheckWork = YES; - else if(TimeOut != 0) - { - time(&ElapseTime); - ElapseTime -= StartTime; - if(ElapseTime >= TimeOut) - { - DoPrintf("do_write timed out"); - *TimeOutErr = YES; - *CancelCheckWork = YES; - } - } - } +// while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE) != YES)) + // Windows 2000でFD_WRITEが通知されないことがあるバグ修正 +// while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE) != YES)) +// { +// if(AskAsyncDone(s, &Error, FD_CLOSE) == YES) +// { +// Error = 1; +// break; +// } +// +// Sleep(1); +// if(BackgrndMessageProc() == YES) +// *CancelCheckWork = YES; +// else if(TimeOut != 0) +// { +// time(&ElapseTime); +// ElapseTime -= StartTime; +// if(ElapseTime >= TimeOut) +// { +// DoPrintf("do_write timed out"); +// *TimeOutErr = YES; +// *CancelCheckWork = YES; +// } +// } +// } if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO)) { @@ -1096,7 +1139,7 @@ int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int // FTPS対応 // Ret = send(s, buf, len, flags); - Ret = sendS(s, buf, len, flags); + Ret = FTPS_send(s, buf, len, flags); if(Ret != SOCKET_ERROR) { #if DBG_MSG @@ -1108,9 +1151,6 @@ int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int Sleep(1); if(BackgrndMessageProc() == YES) break; - // 何故か一部のホストとWindows 2000の組み合わせで通信できないバグに暫定対応 - if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES) - break; // FTPS対応 // 送信バッファ確認をバイパスしたためここでタイムアウトの確認 if(BackgrndMessageProc() == YES) @@ -1145,6 +1185,20 @@ int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int } +// 同時接続対応 +void RemoveReceivedData(SOCKET s) +{ + char buf[1024]; + int len; + int Error; + while((len = FTPS_recv(s, buf, sizeof(buf), MSG_PEEK)) >= 0) + { + AskAsyncDone(s, &Error, FD_READ); + FTPS_recv(s, buf, len, 0); + } +} + + /*----- * * Parameter @@ -1162,7 +1216,7 @@ int CheckClosedAndReconnect(void) //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); Sts = FFFTP_SUCCESS; - if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE_BIT) == YES) + if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE) == YES) { Sts = ReConnectCmdSkt(); } @@ -1171,124 +1225,3 @@ int CheckClosedAndReconnect(void) -// UTF-8対応 - -static BOOL ConvertStringToPunycode(LPSTR Output, DWORD Count, LPCSTR Input) -{ - BOOL bResult; - punycode_uint* pUnicode; - punycode_uint* p; - BOOL bNeeded; - LPCSTR InputString; - punycode_uint Length; - punycode_uint OutputLength; - bResult = FALSE; - if(pUnicode = malloc(sizeof(punycode_uint) * strlen(Input))) - { - p = pUnicode; - bNeeded = FALSE; - InputString = Input; - Length = 0; - while(*InputString != '\0') - { - *p = 0; - if((*InputString & 0x80) == 0x00) - *p |= (punycode_uint)*InputString & 0x7f; - else if((*InputString & 0xe0) == 0xc0) - *p |= (punycode_uint)*InputString & 0x1f; - else if((*InputString & 0xf0) == 0xe0) - *p |= (punycode_uint)*InputString & 0x0f; - else if((*InputString & 0xf8) == 0xf0) - *p |= (punycode_uint)*InputString & 0x07; - else if((*InputString & 0xfc) == 0xf8) - *p |= (punycode_uint)*InputString & 0x03; - else if((*InputString & 0xfe) == 0xfc) - *p |= (punycode_uint)*InputString & 0x01; - InputString++; - while((*InputString & 0xc0) == 0x80) - { - *p = *p << 6; - *p |= (punycode_uint)*InputString & 0x3f; - InputString++; - } - if(*p >= 0x80) - bNeeded = TRUE; - p++; - Length++; - } - if(bNeeded) - { - if(Count >= strlen("xn--") + 1) - { - strcpy(Output, "xn--"); - OutputLength = Count - strlen("xn--"); - if(punycode_encode(Length, pUnicode, NULL, (punycode_uint*)&OutputLength, Output + strlen("xn--")) == punycode_success) - { - Output[strlen("xn--") + OutputLength] = '\0'; - bResult = TRUE; - } - } - } - free(pUnicode); - } - if(!bResult) - { - if(Count >= strlen(Input) + 1) - { - strcpy(Output, Input); - bResult = TRUE; - } - } - return bResult; -} - -static BOOL ConvertNameToPunycode(LPSTR Output, LPCSTR Input) -{ - BOOL bResult; - DWORD Length; - char* pm0; - char* pm1; - char* p; - char* pNext; - bResult = FALSE; - Length = strlen(Input); - if(pm0 = AllocateStringM(Length + 1)) - { - if(pm1 = AllocateStringM(Length * 4 + 1)) - { - strcpy(pm0, Input); - p = pm0; - while(p) - { - if(pNext = strchr(p, '.')) - { - *pNext = '\0'; - pNext++; - } - if(ConvertStringToPunycode(pm1, Length * 4, p)) - strcat(Output, pm1); - if(pNext) - strcat(Output, "."); - p = pNext; - } - bResult = TRUE; - FreeDuplicatedString(pm1); - } - FreeDuplicatedString(pm0); - } - return bResult; -} - -static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen) -{ - HANDLE r = NULL; - char* pa0 = NULL; - if(pa0 = AllocateStringA(strlen(name) * 4)) - { - if(ConvertNameToPunycode(pa0, name)) - r = WSAAsyncGetHostByName(hWnd, wMsg, pa0, buf, buflen); - } - FreeDuplicatedString(pa0); - return r; -} -