OSDN Git Service

Add support displaying a progress bar on the taskbar (Windows 7 or later only).
[ffftp/ffftp.git] / socket.c
index db7b69f..80f3889 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -37,6 +37,8 @@
 #include <time.h>\r
 #include <windowsx.h>\r
 #include <commctrl.h>\r
+// UPnP対応\r
+#include <natupnp.h>\r
 \r
 #include "common.h"\r
 #include "resource.h"\r
@@ -66,6 +68,12 @@ typedef struct {
        int FdRead;\r
        int FdWrite;\r
        int Error;\r
+       // ソケットにデータを付与\r
+       struct sockaddr_in HostAddrIPv4;\r
+       struct sockaddr_in SocksAddrIPv4;\r
+       struct sockaddr_in6 HostAddrIPv6;\r
+       struct sockaddr_in6 SocksAddrIPv6;\r
+       int MapPort;\r
 } ASYNCSIGNAL;\r
 \r
 \r
@@ -91,10 +99,10 @@ typedef struct {
 static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);\r
 static int AskAsyncDone(SOCKET s, int *Error, int Mask);\r
 static int AskAsyncDoneDbase(HANDLE Async, int *Error);\r
-static int RegistAsyncTable(SOCKET s);\r
-static int RegistAsyncTableDbase(HANDLE Async);\r
-static int UnRegistAsyncTable(SOCKET s);\r
-static int UnRegistAsyncTableDbase(HANDLE Async);\r
+static int RegisterAsyncTable(SOCKET s);\r
+static int RegisterAsyncTableDbase(HANDLE Async);\r
+static int UnregisterAsyncTable(SOCKET s);\r
+static int UnregisterAsyncTableDbase(HANDLE Async);\r
 \r
 \r
 /*===== 外部参照 =====*/\r
@@ -114,6 +122,9 @@ static ASYNCSIGNALDATABASE SignalDbase[MAX_SIGNAL_ENTRY_DBASE];
 // スレッド衝突のバグ修正\r
 static HANDLE hAsyncTblAccMutex;\r
 \r
+// UPnP対応\r
+IUPnPNAT* pUPnPNAT;\r
+IStaticPortMappingCollection* pUPnPMap;\r
 \r
 \r
 \r
@@ -275,7 +286,7 @@ static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LP
 \r
                case WM_ASYNC_DBASE :\r
                        // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり\r
-                       RegistAsyncTableDbase((HANDLE)wParam);\r
+                       RegisterAsyncTableDbase((HANDLE)wParam);\r
                        // スレッド衝突のバグ修正\r
                        WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
                        for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
@@ -450,7 +461,7 @@ static int AskAsyncDoneDbase(HANDLE Async, int *Error)
 *              \r
 *----------------------------------------------------------------------------*/\r
 \r
-static int RegistAsyncTable(SOCKET s)\r
+static int RegisterAsyncTable(SOCKET s)\r
 {\r
        int Sts;\r
        int Pos;\r
@@ -489,6 +500,12 @@ static int RegistAsyncTable(SOCKET s)
                                Signal[Pos].FdAccept = 0;\r
                                Signal[Pos].FdRead = 0;\r
                                Signal[Pos].FdWrite = 0;\r
+                               // ソケットにデータを付与\r
+                               memset(&Signal[Pos].HostAddrIPv4, 0, sizeof(struct sockaddr_in));\r
+                               memset(&Signal[Pos].SocksAddrIPv4, 0, sizeof(struct sockaddr_in));\r
+                               memset(&Signal[Pos].HostAddrIPv6, 0, sizeof(struct sockaddr_in6));\r
+                               memset(&Signal[Pos].SocksAddrIPv6, 0, sizeof(struct sockaddr_in6));\r
+                               Signal[Pos].MapPort = 0;\r
                                Sts = YES;\r
                                break;\r
                        }\r
@@ -516,7 +533,7 @@ static int RegistAsyncTable(SOCKET s)
 *              \r
 *----------------------------------------------------------------------------*/\r
 \r
-static int RegistAsyncTableDbase(HANDLE Async)\r
+static int RegisterAsyncTableDbase(HANDLE Async)\r
 {\r
        int Sts;\r
        int Pos;\r
@@ -578,7 +595,7 @@ static int RegistAsyncTableDbase(HANDLE Async)
 *              \r
 *----------------------------------------------------------------------------*/\r
 \r
-static int UnRegistAsyncTable(SOCKET s)\r
+static int UnregisterAsyncTable(SOCKET s)\r
 {\r
        int Sts;\r
        int Pos;\r
@@ -613,7 +630,7 @@ static int UnRegistAsyncTable(SOCKET s)
 *              \r
 *----------------------------------------------------------------------------*/\r
 \r
-static int UnRegistAsyncTableDbase(HANDLE Async)\r
+static int UnregisterAsyncTableDbase(HANDLE Async)\r
 {\r
        int Sts;\r
        int Pos;\r
@@ -639,6 +656,146 @@ static int UnRegistAsyncTableDbase(HANDLE Async)
 }\r
 \r
 \r
+// ソケットにデータを付与\r
+\r
+int SetAsyncTableDataIPv4(SOCKET s, struct sockaddr_in* Host, struct sockaddr_in* Socks)\r
+{\r
+       int Sts;\r
+       int Pos;\r
+\r
+       WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
+       Sts = NO;\r
+       for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
+       {\r
+               if(Signal[Pos].Socket == s)\r
+               {\r
+                       if(Host != NULL)\r
+                               memcpy(&Signal[Pos].HostAddrIPv4, Host, sizeof(struct sockaddr_in));\r
+                       if(Socks != NULL)\r
+                               memcpy(&Signal[Pos].SocksAddrIPv4, Socks, sizeof(struct sockaddr_in));\r
+                       Sts = YES;\r
+                       break;\r
+               }\r
+       }\r
+       ReleaseMutex(hAsyncTblAccMutex);\r
+\r
+       return(Sts);\r
+}\r
+\r
+int SetAsyncTableDataIPv6(SOCKET s, struct sockaddr_in6* Host, struct sockaddr_in6* Socks)\r
+{\r
+       int Sts;\r
+       int Pos;\r
+\r
+       WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
+       Sts = NO;\r
+       for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
+       {\r
+               if(Signal[Pos].Socket == s)\r
+               {\r
+                       if(Host != NULL)\r
+                               memcpy(&Signal[Pos].HostAddrIPv6, Host, sizeof(struct sockaddr_in6));\r
+                       if(Socks != NULL)\r
+                               memcpy(&Signal[Pos].SocksAddrIPv6, Socks, sizeof(struct sockaddr_in6));\r
+                       Sts = YES;\r
+                       break;\r
+               }\r
+       }\r
+       ReleaseMutex(hAsyncTblAccMutex);\r
+\r
+       return(Sts);\r
+}\r
+\r
+int SetAsyncTableDataMapPort(SOCKET s, int Port)\r
+{\r
+       int Sts;\r
+       int Pos;\r
+\r
+       WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
+       Sts = NO;\r
+       for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
+       {\r
+               if(Signal[Pos].Socket == s)\r
+               {\r
+                       Signal[Pos].MapPort = Port;\r
+                       Sts = YES;\r
+                       break;\r
+               }\r
+       }\r
+       ReleaseMutex(hAsyncTblAccMutex);\r
+\r
+       return(Sts);\r
+}\r
+\r
+int GetAsyncTableDataIPv4(SOCKET s, struct sockaddr_in* Host, struct sockaddr_in* Socks)\r
+{\r
+       int Sts;\r
+       int Pos;\r
+\r
+       WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
+       Sts = NO;\r
+       for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
+       {\r
+               if(Signal[Pos].Socket == s)\r
+               {\r
+                       if(Host != NULL)\r
+                               memcpy(Host, &Signal[Pos].HostAddrIPv4, sizeof(struct sockaddr_in));\r
+                       if(Socks != NULL)\r
+                               memcpy(Socks, &Signal[Pos].SocksAddrIPv4, sizeof(struct sockaddr_in));\r
+                       Sts = YES;\r
+                       break;\r
+               }\r
+       }\r
+       ReleaseMutex(hAsyncTblAccMutex);\r
+\r
+       return(Sts);\r
+}\r
+\r
+int GetAsyncTableDataIPv6(SOCKET s, struct sockaddr_in6* Host, struct sockaddr_in6* Socks)\r
+{\r
+       int Sts;\r
+       int Pos;\r
+\r
+       WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
+       Sts = NO;\r
+       for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
+       {\r
+               if(Signal[Pos].Socket == s)\r
+               {\r
+                       if(Host != NULL)\r
+                               memcpy(Host, &Signal[Pos].HostAddrIPv6, sizeof(struct sockaddr_in6));\r
+                       if(Socks != NULL)\r
+                               memcpy(Socks, &Signal[Pos].SocksAddrIPv6, sizeof(struct sockaddr_in6));\r
+                       Sts = YES;\r
+                       break;\r
+               }\r
+       }\r
+       ReleaseMutex(hAsyncTblAccMutex);\r
+\r
+       return(Sts);\r
+}\r
+\r
+int GetAsyncTableDataMapPort(SOCKET s, int* Port)\r
+{\r
+       int Sts;\r
+       int Pos;\r
+\r
+       WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
+       Sts = NO;\r
+       for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
+       {\r
+               if(Signal[Pos].Socket == s)\r
+               {\r
+                       *Port = Signal[Pos].MapPort;\r
+                       Sts = YES;\r
+                       break;\r
+               }\r
+       }\r
+       ReleaseMutex(hAsyncTblAccMutex);\r
+\r
+       return(Sts);\r
+}\r
+\r
 \r
 \r
 \r
@@ -666,7 +823,7 @@ struct hostent *do_gethostbynameIPv4(const char *Name, char *Buf, int Len, int *
        hAsync = WSAAsyncGetHostByNameM(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
        if(hAsync != NULL)\r
        {\r
-               RegistAsyncTableDbase(hAsync);\r
+               RegisterAsyncTableDbase(hAsync);\r
                while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))\r
                {\r
                        Sleep(1);\r
@@ -682,7 +839,7 @@ struct hostent *do_gethostbynameIPv4(const char *Name, char *Buf, int Len, int *
                {\r
                        Ret = (struct hostent *)Buf;\r
                }\r
-               UnRegistAsyncTableDbase(hAsync);\r
+               UnregisterAsyncTableDbase(hAsync);\r
        }\r
        return(Ret);\r
 #else\r
@@ -710,7 +867,7 @@ struct hostent *do_gethostbynameIPv6(const char *Name, char *Buf, int Len, int *
        hAsync = WSAAsyncGetHostByNameIPv6M(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len, AF_INET6);\r
        if(hAsync != NULL)\r
        {\r
-               RegistAsyncTableDbase(hAsync);\r
+               RegisterAsyncTableDbase(hAsync);\r
                while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))\r
                {\r
                        Sleep(1);\r
@@ -720,13 +877,13 @@ struct hostent *do_gethostbynameIPv6(const char *Name, char *Buf, int Len, int *
 \r
                if(*CancelCheckWork == YES)\r
                {\r
-                       WSACancelAsyncRequest(hAsync);\r
+                       WSACancelAsyncRequestIPv6(hAsync);\r
                }\r
                else if(Error == 0)\r
                {\r
                        Ret = (struct hostent *)Buf;\r
                }\r
-               UnRegistAsyncTableDbase(hAsync);\r
+               UnregisterAsyncTableDbase(hAsync);\r
        }\r
        return(Ret);\r
 #else\r
@@ -745,7 +902,7 @@ SOCKET do_socket(int af, int type, int protocol)
        Ret = socket(af, type, protocol);\r
        if(Ret != INVALID_SOCKET)\r
        {\r
-               RegistAsyncTable(Ret);\r
+               RegisterAsyncTable(Ret);\r
        }\r
 #if DBG_MSG\r
        DoPrintf("# do_socket (S=%x)", Ret);\r
@@ -769,7 +926,7 @@ int do_closesocket(SOCKET s)
 \r
        // スレッド衝突のバグ修正\r
        WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
-       UnRegistAsyncTable(s);\r
+       UnregisterAsyncTable(s);\r
        // FTPS対応\r
 //     Ret = closesocket(s);\r
        Ret = FTPS_closesocket(s);\r
@@ -792,7 +949,7 @@ int do_closesocket(SOCKET s)
        if(BackgrndMessageProc() == YES)\r
                CancelCheckWork = YES;\r
        // スレッド衝突のバグ修正\r
-//     UnRegistAsyncTable(s);\r
+//     UnregisterAsyncTable(s);\r
 \r
 #if DBG_MSG\r
        DoPrintf("# Exit close");\r
@@ -929,8 +1086,10 @@ SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
                                DoPrintf("## do_sccept (S=%x)", Ret2);\r
                                DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
 #endif\r
-                               RegistAsyncTable(Ret2);\r
-                               if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR)\r
+                               RegisterAsyncTable(Ret2);\r
+                               // 高速化のためFD_READとFD_WRITEを使用しない\r
+//                             if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR)\r
+                               if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT) == SOCKET_ERROR)\r
                                {\r
                                        do_closesocket(Ret2);\r
                                        Ret2 = INVALID_SOCKET;\r
@@ -1190,14 +1349,90 @@ void RemoveReceivedData(SOCKET s)
 {\r
        char buf[1024];\r
        int len;\r
-       int Error;\r
-       while((len = FTPS_recv(s, buf, sizeof(buf), MSG_PEEK)) >= 0)\r
+//     int Error;\r
+       while((len = FTPS_recv(s, buf, sizeof(buf), MSG_PEEK)) > 0)\r
        {\r
-               AskAsyncDone(s, &Error, FD_READ);\r
+//             AskAsyncDone(s, &Error, FD_READ);\r
                FTPS_recv(s, buf, len, 0);\r
        }\r
 }\r
 \r
+// UPnP対応\r
+int LoadUPnP()\r
+{\r
+       int Sts;\r
+       Sts = FFFTP_FAIL;\r
+       if(CoCreateInstance(&CLSID_UPnPNAT, NULL, CLSCTX_ALL, &IID_IUPnPNAT, (void**)&pUPnPNAT) == S_OK)\r
+       {\r
+               if(pUPnPNAT->lpVtbl->get_StaticPortMappingCollection(pUPnPNAT, &pUPnPMap) == S_OK)\r
+                       Sts = FFFTP_SUCCESS;\r
+       }\r
+       return Sts;\r
+}\r
+\r
+void FreeUPnP()\r
+{\r
+       if(pUPnPMap != NULL)\r
+               pUPnPMap->lpVtbl->Release(pUPnPMap);\r
+       pUPnPMap = NULL;\r
+       if(pUPnPNAT != NULL)\r
+               pUPnPNAT->lpVtbl->Release(pUPnPNAT);\r
+       pUPnPNAT = NULL;\r
+}\r
+\r
+int IsUPnPLoaded()\r
+{\r
+       int Sts;\r
+       Sts = NO;\r
+       if(pUPnPNAT != NULL && pUPnPMap != NULL)\r
+               Sts = YES;\r
+       return Sts;\r
+}\r
+\r
+int AddPortMapping(char* Adrs, int Port)\r
+{\r
+       int Sts;\r
+       WCHAR Tmp1[40];\r
+       BSTR Tmp2;\r
+       BSTR Tmp3;\r
+       BSTR Tmp4;\r
+       IStaticPortMapping* pPortMap;\r
+       Sts = FFFTP_FAIL;\r
+       MtoW(Tmp1, 40, Adrs, -1);\r
+       if((Tmp2 = SysAllocString(Tmp1)) != NULL)\r
+       {\r
+               if((Tmp3 = SysAllocString(L"TCP")) != NULL)\r
+               {\r
+                       if((Tmp4 = SysAllocString(L"FFFTP")) != NULL)\r
+                       {\r
+                               if(pUPnPMap->lpVtbl->Add(pUPnPMap, Port, Tmp3, Port, Tmp2, VARIANT_TRUE, Tmp4, &pPortMap) == S_OK)\r
+                               {\r
+                                       Sts = FFFTP_SUCCESS;\r
+                                       pPortMap->lpVtbl->Release(pPortMap);\r
+                               }\r
+                               SysFreeString(Tmp4);\r
+                       }\r
+                       SysFreeString(Tmp3);\r
+               }\r
+               SysFreeString(Tmp2);\r
+       }\r
+       return Sts;\r
+}\r
+\r
+int RemovePortMapping(int Port)\r
+{\r
+       int Sts;\r
+       BSTR Tmp;\r
+       Sts = FFFTP_FAIL;\r
+       if((Tmp = SysAllocString(L"TCP")) != NULL)\r
+       {\r
+               if(pUPnPMap->lpVtbl->Remove(pUPnPMap, Port, Tmp) == S_OK)\r
+                       Sts = FFFTP_SUCCESS;\r
+               SysFreeString(Tmp);\r
+       }\r
+       return Sts;\r
+}\r
+\r
 \r
 /*----- \r
 *\r
@@ -1225,3 +1460,19 @@ int CheckClosedAndReconnect(void)
 \r
 \r
 \r
+// 同時接続対応\r
+int CheckClosedAndReconnectTrnSkt(SOCKET *Skt, int *CancelCheckWork)\r
+{\r
+       int Error;\r
+       int Sts;\r
+\r
+//SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");\r
+\r
+       Sts = FFFTP_SUCCESS;\r
+       if(AskAsyncDone(*Skt, &Error, FD_CLOSE) == YES)\r
+       {\r
+               Sts = ReConnectTrnSkt(Skt, CancelCheckWork);\r
+       }\r
+       return(Sts);\r
+}\r
+\r