X-Git-Url: http://git.sourceforge.jp/view?p=ffftp%2Fffftp.git;a=blobdiff_plain;f=socket.c;h=7ae66ab733395f5f8fa89263196d50a2e42d7aa8;hp=b3d41638948e2079af8227b01fff51ff2acd3e40;hb=e9a6d523e00faf31fcec49598aaea96681d5b53c;hpb=46cb6ad4eea69835e1aab2d29ed9c8117a6d516b diff --git a/socket.c b/socket.c index b3d4163..7ae66ab 100644 --- a/socket.c +++ b/socket.c @@ -28,6 +28,8 @@ /============================================================================*/ #define STRICT +// IPv6対応 +#include #include #include #include @@ -45,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 @@ -77,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 @@ -271,6 +274,8 @@ static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LP break; case WM_ASYNC_DBASE : + // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり + RegistAsyncTableDbase((HANDLE)wParam); // スレッド衝突のバグ修正 WaitForSingleObject(hAsyncTblAccMutex, INFINITE); for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++) @@ -291,31 +296,6 @@ static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LP break; } } - // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり - if(Pos == MAX_SIGNAL_ENTRY_DBASE) - { - for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++) - { - if(SignalDbase[Pos].Async == 0) - { - SignalDbase[Pos].Async = (HANDLE)wParam; - SignalDbase[Pos].Done = 0; - SignalDbase[Pos].ErrorDb = 0; - if(HIWORD(lParam) != 0) - { - SignalDbase[Pos].ErrorDb = 1; -#if DBG_MSG - DoPrintf("##### SignalDatabase: error"); -#endif - } - SignalDbase[Pos].Done = 1; -#if DBG_MSG - DoPrintf("##### SignalDatabase: Done"); -#endif - break; - } - } - } // スレッド衝突のバグ修正 ReleaseMutex(hAsyncTblAccMutex); break; @@ -354,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; @@ -377,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; @@ -385,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; @@ -401,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; } @@ -665,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; @@ -676,9 +658,56 @@ struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *Canc DoPrintf("# Start gethostbyname"); #endif Ret = NULL; - *CancelCheckWork = NO; + // 同時接続対応 +// *CancelCheckWork = NO; - hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len); + // UTF-8対応 +// hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len); + hAsync = WSAAsyncGetHostByNameM(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len); + 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 +} + + +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); @@ -738,13 +767,16 @@ int do_closesocket(SOCKET s) #endif CancelCheckWork = NO; + // スレッド衝突のバグ修正 + WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0); + 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) @@ -755,10 +787,12 @@ int do_closesocket(SOCKET s) Ret = 0; } - WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0); + // スレッド衝突のバグ修正 +// WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0); if(BackgrndMessageProc() == YES) CancelCheckWork = YES; - UnRegistAsyncTable(s); + // スレッド衝突のバグ修正 +// UnRegistAsyncTable(s); #if DBG_MSG DoPrintf("# Exit close"); @@ -783,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) @@ -874,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; @@ -890,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 @@ -903,7 +930,9 @@ SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen) DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE"); #endif RegistAsyncTable(Ret2); - if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR) + // 高速化のためFD_READとFD_WRITEを使用しない +// if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR) + if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT) == SOCKET_ERROR) { do_closesocket(Ret2); Ret2 = INVALID_SOCKET; @@ -957,7 +986,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; @@ -966,29 +996,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)) { @@ -1000,7 +1031,7 @@ 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(); @@ -1054,7 +1085,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; @@ -1064,36 +1096,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)) { @@ -1105,7 +1141,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 @@ -1151,6 +1187,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 @@ -1168,7 +1218,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(); } @@ -1177,3 +1227,19 @@ int CheckClosedAndReconnect(void) +// 同時接続対応 +int CheckClosedAndReconnectTrnSkt(SOCKET *Skt, int *CancelCheckWork) +{ + int Error; + int Sts; + +//SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + + Sts = FFFTP_SUCCESS; + if(AskAsyncDone(*Skt, &Error, FD_CLOSE) == YES) + { + Sts = ReConnectTrnSkt(Skt, CancelCheckWork); + } + return(Sts); +} +