#include "mbftpch.h" #if defined(TEST_PLUGABLE) && defined(_DEBUG) #include "plugable.h" #include "iplgxprt.h" #include "it120xprt.h" #include "nullmdm.h" extern HINSTANCE g_hDllInst; #define PLUGABLE_PORT_NUMBER 522 // ULS server port number IT120PluggableTransport *g_pPluggableTransport = NULL; #ifdef USE_SOCKET SOCKET g_hListenSocket = INVALID_SOCKET; #endif typedef struct { LPSTR pszHostName; #ifdef USE_SOCKET SOCKET hSocket; #else CNullModem *pModem; #endif HANDLE hevtRead; HANDLE hevtWrite; HANDLE hevtClose; char szConnID[64]; } HOST_INFO; #define NUM_HOSTS 2 #define TOP_PROVIDER_ID 0 ULONG g_nMyHostID = (ULONG) -1; HOST_INFO g_aHostInfo[NUM_HOSTS]; char g_szMyHostName[64]; PLUGXPRT_PARAMETERS g_PluggableParams; #ifdef USE_SOCKET SOCKET CreateListenSocket(HWND hwnd); SOCKET CreateConnectSocket(HWND hwnd, LPSTR pszHostName); #else CNullModem * CreateListenModem(void); void CloseListenModem(CNullModem *p); CNullModem * CreateConnectModem(LPSTR pszHostName); void CloseConnectModem(CNullModem *p); #endif void OnPluggableBegin(HWND hwnd) { #ifdef USE_SOCKET WSADATA wsa_data; WORD version_requested = MAKEWORD (1,1); int error = ::WSAStartup(version_requested, &wsa_data); ASSERT(error == 0); g_hListenSocket = INVALID_SOCKET; #endif ::ZeroMemory(g_aHostInfo, sizeof(g_aHostInfo)); g_aHostInfo[0].pszHostName = "lonchanc"; g_aHostInfo[1].pszHostName = "lon1"; // g_aHostInfo[2].pszHostName = "lonchanc_nt"; for (ULONG i = 0; i < NUM_HOSTS; i++) { g_aHostInfo[i].szConnID[0] = '\0'; #ifdef USE_SOCKET g_aHostInfo[i].hSocket = INVALID_SOCKET; #else g_aHostInfo[i].pModem = NULL; #endif g_aHostInfo[i].hevtRead = ::CreateEvent(NULL, FALSE, FALSE, NULL); g_aHostInfo[i].hevtWrite = ::CreateEvent(NULL, FALSE, FALSE, NULL);; g_aHostInfo[i].hevtClose = ::CreateEvent(NULL, FALSE, FALSE, NULL);; ASSERT(g_aHostInfo[i].hevtRead && g_aHostInfo[i].hevtWrite && g_aHostInfo[i].hevtClose); } T120Error rc = ::T120_CreatePluggableTransport(&g_pPluggableTransport); ASSERT(T120_NO_ERROR == rc); g_pPluggableTransport->ResetConnCounter(); g_pPluggableTransport->DisableWinsock(); gethostname(g_szMyHostName, 64); TRACE_OUT(("OnPluggableScript: HostName=%s", g_szMyHostName)); for (i = 0; i < NUM_HOSTS; i++) { if (! ::lstrcmpi(g_aHostInfo[i].pszHostName, g_szMyHostName)) { g_nMyHostID = i; break; } } ASSERT(i < NUM_HOSTS); ASSERT(g_nMyHostID < NUM_HOSTS); ::ZeroMemory(&g_PluggableParams, sizeof(g_PluggableParams)); g_PluggableParams.cbStructSize = sizeof(g_PluggableParams); g_PluggableParams.dwFlags = PSTN_PARAM__CALL_CONTROL | PSTN_PARAM__READ_FILE_BUFFER_SIZE | PSTN_PARAM__PHYSICAL_LAYER_SEND_BUFFER_SIZE | PSTN_PARAM__PHSYICAL_LAYER_RECV_BUFFER_SIZE | PSTN_PARAM__MAX_T200_TIMEOUT_COUNT_IN_Q922 | PSTN_PARAM__T203_TIMEOUT_IN_Q922; g_PluggableParams.eCallControl = PLUGXPRT_PSTN_CALL_CONTROL_MANUAL; g_PluggableParams.cbReadFileBufferSize = 10240; // 10K g_PluggableParams.cbPhysicalLayerSendBufferSize = 1024; // 1K g_PluggableParams.cbPhysicalLayerReceiveBufferSize = 10240; // 10K g_PluggableParams.cMaximumT200TimeoutsInQ922 = 5; g_PluggableParams.nT203TimeoutInQ922 = 600; if (TOP_PROVIDER_ID == g_nMyHostID) { for (i = 0; i < NUM_HOSTS; i++) { if (i != g_nMyHostID) { #ifdef USE_SOCKET g_aHostInfo[i].hSocket = ::CreateConnectSocket(hwnd, g_aHostInfo[i].pszHostName); ASSERT(INVALID_SOCKET != g_aHostInfo[i].hSocket); #else g_aHostInfo[i].pModem = ::CreateConnectModem(g_aHostInfo[i].pszHostName); ASSERT(NULL != g_aHostInfo[i].pModem); #endif HANDLE hCommLink = NULL; #ifdef USE_SOCKET BOOL fRet = ::DuplicateHandle(::GetCurrentProcess(), (HANDLE) g_aHostInfo[i].hSocket, #else BOOL fRet = ::DuplicateHandle(::GetCurrentProcess(), g_aHostInfo[i].pModem->GetCommLink(), #endif ::GetCurrentProcess(), &hCommLink, 0, FALSE, DUPLICATE_SAME_ACCESS); ASSERT(fRet); rc = g_pPluggableTransport->CreateConnection( g_aHostInfo[i].szConnID, PLUGXPRT_CALLER, // caller hCommLink, g_aHostInfo[i].hevtRead, g_aHostInfo[i].hevtWrite, g_aHostInfo[i].hevtClose, FRAMING_LEGACY_PSTN, &g_PluggableParams); ASSERT(T120_NO_ERROR == rc); } } } else { #ifdef USE_SOCKET g_hListenSocket = ::CreateListenSocket(hwnd); #else g_aHostInfo[i].pModem = ::CreateListenModem(); ASSERT(NULL != g_aHostInfo[i].pModem); HANDLE hCommLink = NULL; BOOL fRet = ::DuplicateHandle(::GetCurrentProcess(), g_aHostInfo[i].pModem->GetCommLink(), ::GetCurrentProcess(), &hCommLink, 0, FALSE, DUPLICATE_SAME_ACCESS); ASSERT(fRet); T120Error rc = g_pPluggableTransport->CreateConnection( g_aHostInfo[i].szConnID, PLUGXPRT_CALLEE, // callee hCommLink, g_aHostInfo[i].hevtRead, g_aHostInfo[i].hevtWrite, g_aHostInfo[i].hevtClose, FRAMING_LEGACY_PSTN, &g_PluggableParams); ASSERT(T120_NO_ERROR == rc); #endif } } void OnPluggableEnd(void) { #ifdef USE_SOCKET if (INVALID_SOCKET != g_hListenSocket) { ::closesocket(g_hListenSocket); } for (ULONG i = 0; i < NUM_HOSTS; i++) { if (INVALID_SOCKET != g_aHostInfo[i].hSocket) { ::closesocket(g_aHostInfo[i].hSocket); } } #else for (ULONG i = 0; i < NUM_HOSTS; i++) { if (i != g_nMyHostID) { CloseConnectModem(g_aHostInfo[i].pModem); } else { CloseListenModem(g_aHostInfo[i].pModem); } g_aHostInfo[i].pModem = NULL; } #endif g_pPluggableTransport->EnableWinsock(); g_pPluggableTransport->ReleaseInterface(); g_pPluggableTransport = NULL; #ifdef USE_SOCKET ::WSACleanup(); #endif } LRESULT OnPluggableSocket(HWND hwnd, WPARAM wParam, LPARAM lParam) { #ifdef USE_SOCKET /* This message is generated by WinSock */ SOCKET hSocket = (SOCKET) wParam; ULONG event = WSAGETSELECTEVENT(lParam); ULONG error = WSAGETSELECTERROR(lParam); ULONG nIdx = (ULONG) -1; if (hSocket != g_hListenSocket) { for (ULONG i = 0; i < NUM_HOSTS; i++) { if (hSocket == g_aHostInfo[i].hSocket) { nIdx = i; break; } } ASSERT(nIdx < NUM_HOSTS); } else { nIdx = TOP_PROVIDER_ID; } /* We disconnect whenever a socket command generates an error message */ if (error) { TRACE_OUT(("OnPluggableSocket: error %d on socket (%d). Event: %d", error, hSocket, event)); } /* We get FD_CLOSE when the socket is closed by the remote site. */ if (event & FD_CLOSE) { TRACE_OUT(("OnPluggableSocket FD_CLOSE(%d)", hSocket)); ::SetEvent(g_aHostInfo[nIdx].hevtClose); } /* We get FD_READ when there is data available for us to read. */ if (event & FD_READ) { TRACE_OUT(("OnPluggableSocket FD_READ(%d)", hSocket)); ::SetEvent(g_aHostInfo[nIdx].hevtRead); } /* We get FD_WRITE when there is space available to write data to WinSock */ if (event & FD_WRITE) { TRACE_OUT(("OnPluggableSocket FD_WRITE(%d)", hSocket)); ::SetEvent(g_aHostInfo[nIdx].hevtWrite); } /* We get FD_CONNECT when connecting to a remote site */ if (event & FD_CONNECT) { TRACE_OUT(("OnPluggableSocket FD_CONNECT(%d)", hSocket)); // ::SetEvent(g_aHostInfo[nIdx].hevtWrite); } /* We get FD_ACCEPT when a remote site is connecting with us */ if (event & FD_ACCEPT) { TRACE_OUT(("OnPluggableSocket FD_ACCEPT(%d)", hSocket)); ASSERT(nIdx == TOP_PROVIDER_ID); SOCKADDR_IN socket_control; int size = sizeof(socket_control); g_aHostInfo[nIdx].hSocket = ::accept(g_hListenSocket, (struct sockaddr *) &socket_control, &size); ASSERT(INVALID_SOCKET != g_aHostInfo[nIdx].hSocket); int nRet = ::WSAAsyncSelect(g_aHostInfo[nIdx].hSocket, hwnd, WM_PLUGABLE_SOCKET, FD_READ | FD_WRITE | FD_CLOSE | FD_CONNECT); ASSERT(SOCKET_ERROR != nRet); HANDLE hCommLink = NULL; BOOL fRet = ::DuplicateHandle(::GetCurrentProcess(), (HANDLE) g_aHostInfo[nIdx].hSocket, ::GetCurrentProcess(), &hCommLink, 0, FALSE, DUPLICATE_SAME_ACCESS); ASSERT(fRet); T120Error rc = g_pPluggableTransport->CreateConnection( g_aHostInfo[nIdx].szConnID, PLUGXPRT_CALLEE, // callee hCommLink, g_aHostInfo[nIdx].hevtRead, g_aHostInfo[nIdx].hevtWrite, g_aHostInfo[nIdx].hevtClose, FRAMING_LEGACY_PSTN, &g_PluggableParams); ASSERT(T120_NO_ERROR == rc); // ::SetEvent(g_aHostInfo[nIdx].hevtWrite); } #endif return 0; } /* * void CreateListenSocket (VOID) * * Functional Description * This function sets up a listening socket. * returns INVALID_SOCKET if there is any error. */ #ifdef USE_SOCKET SOCKET CreateListenSocket(HWND hwnd) { SOCKADDR_IN socket_control; SOCKET socket_number; // Create the listening socket. socket_number = ::socket(AF_INET, SOCK_STREAM, 0); ASSERT(INVALID_SOCKET != socket_number); // The listen socket only waits for FD_ACCEPT msgs. int nRet = ::WSAAsyncSelect(socket_number, hwnd, WM_PLUGABLE_SOCKET, FD_ACCEPT); ASSERT(SOCKET_ERROR != nRet); /* * Load the socket control structure with the parameters necessary. * - Internet socket * - Let it assign any address to this socket * - Assign our port number */ socket_control.sin_family = AF_INET; socket_control.sin_addr.s_addr = INADDR_ANY; socket_control.sin_port = htons ( PLUGABLE_PORT_NUMBER ); /* Issue the bind call */ nRet = ::bind(socket_number, (LPSOCKADDR) &socket_control, sizeof(SOCKADDR_IN)); ASSERT(SOCKET_ERROR != nRet); /* * Issue a listen to WinSock to tell it we are willing to accept calls. * This is a non-blocking listen, therefore we will receive FD_ACCEPT * if someone is trying to call us. */ nRet =::listen(socket_number, 3 /* LISTEN_QUEUE_SIZE */); ASSERT(SOCKET_ERROR != nRet); return socket_number; } #else CNullModem * CreateListenModem(void) { DBG_SAVE_FILE_LINE CNullModem *p = new CNullModem(g_hDllInst); ASSERT(NULL != p); TPhysicalError rc; rc = p->TPhysInitialize(NULL, 1); ASSERT(TPHYS_SUCCESS == rc); rc = p->TPhysConnectRequest("COM1"); ASSERT(TPHYS_SUCCESS == rc); rc = p->TPhysListen(); ASSERT(TPHYS_SUCCESS == rc); return p; } void CloseListenModem(CNullModem *p) { if (NULL != p) { TPhysicalError rc; rc = p->TPhysUnlisten(); ASSERT(TPHYS_SUCCESS == rc); rc = p->TPhysDisconnect(); ASSERT(TPHYS_SUCCESS == rc); rc = p->TPhysTerminate(); ASSERT(TPHYS_SUCCESS == rc); delete p; } } #endif #ifdef USE_SOCKET SOCKET CreateConnectSocket(HWND hwnd, LPSTR pszHostName) { SOCKET socket_number; u_short uPort = PLUGABLE_PORT_NUMBER; PHOSTENT phe = NULL; SOCKADDR_IN socket_control; DWORD dwIPAddress; socket_number = ::socket(AF_INET, SOCK_STREAM, 0); ASSERT(INVALID_SOCKET != socket_number); /* Enable Tx and Rx messages to the window */ int nRet = ::WSAAsyncSelect(socket_number, hwnd, WM_PLUGABLE_SOCKET, FD_READ | FD_WRITE | FD_CLOSE); ASSERT(SOCKET_ERROR != nRet); // fill in other info in SockAddr ::ZeroMemory(&socket_control, sizeof(socket_control)); socket_control.sin_family = AF_INET; socket_control.sin_port = htons (PLUGABLE_PORT_NUMBER); // get server's IP address dwIPAddress = ::inet_addr(pszHostName); if (dwIPAddress != INADDR_NONE) { *((PDWORD) &socket_control.sin_addr) = dwIPAddress; } else { phe = ::gethostbyname(pszHostName); ASSERT(NULL != phe); ::CopyMemory(&socket_control.sin_addr, phe->h_addr, phe->h_length); } /* Attempt a connection to the remote site */ nRet = ::connect(socket_number, (const struct sockaddr *) &socket_control, sizeof(socket_control)); ASSERT(SOCKET_ERROR != nRet || WSAEWOULDBLOCK == ::WSAGetLastError()); return socket_number; } #else CNullModem * CreateConnectModem(LPSTR pszHostName) { DBG_SAVE_FILE_LINE CNullModem *p = new CNullModem(g_hDllInst); ASSERT(NULL != p); TPhysicalError rc; rc = p->TPhysInitialize(NULL, 1); ASSERT(TPHYS_SUCCESS == rc); rc = p->TPhysConnectRequest("COM1"); ASSERT(TPHYS_SUCCESS == rc); rc = p->TPhysListen(); ASSERT(TPHYS_SUCCESS == rc); return p; } void CloseConnectModem(CNullModem *p) { if (NULL != p) { TPhysicalError rc; rc = p->TPhysUnlisten(); ASSERT(TPHYS_SUCCESS == rc); rc = p->TPhysDisconnect(); ASSERT(TPHYS_SUCCESS == rc); rc = p->TPhysTerminate(); ASSERT(TPHYS_SUCCESS == rc); delete p; } } #endif #endif // TEST_PLUGABLE