Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

497 lines
14 KiB

  1. #include "mbftpch.h"
  2. #if defined(TEST_PLUGABLE) && defined(_DEBUG)
  3. #include "plugable.h"
  4. #include "iplgxprt.h"
  5. #include "it120xprt.h"
  6. #include "nullmdm.h"
  7. extern HINSTANCE g_hDllInst;
  8. #define PLUGABLE_PORT_NUMBER 522 // ULS server port number
  9. IT120PluggableTransport *g_pPluggableTransport = NULL;
  10. #ifdef USE_SOCKET
  11. SOCKET g_hListenSocket = INVALID_SOCKET;
  12. #endif
  13. typedef struct
  14. {
  15. LPSTR pszHostName;
  16. #ifdef USE_SOCKET
  17. SOCKET hSocket;
  18. #else
  19. CNullModem *pModem;
  20. #endif
  21. HANDLE hevtRead;
  22. HANDLE hevtWrite;
  23. HANDLE hevtClose;
  24. char szConnID[64];
  25. }
  26. HOST_INFO;
  27. #define NUM_HOSTS 2
  28. #define TOP_PROVIDER_ID 0
  29. ULONG g_nMyHostID = (ULONG) -1;
  30. HOST_INFO g_aHostInfo[NUM_HOSTS];
  31. char g_szMyHostName[64];
  32. PLUGXPRT_PARAMETERS g_PluggableParams;
  33. #ifdef USE_SOCKET
  34. SOCKET CreateListenSocket(HWND hwnd);
  35. SOCKET CreateConnectSocket(HWND hwnd, LPSTR pszHostName);
  36. #else
  37. CNullModem * CreateListenModem(void);
  38. void CloseListenModem(CNullModem *p);
  39. CNullModem * CreateConnectModem(LPSTR pszHostName);
  40. void CloseConnectModem(CNullModem *p);
  41. #endif
  42. void OnPluggableBegin(HWND hwnd)
  43. {
  44. #ifdef USE_SOCKET
  45. WSADATA wsa_data;
  46. WORD version_requested = MAKEWORD (1,1);
  47. int error = ::WSAStartup(version_requested, &wsa_data);
  48. ASSERT(error == 0);
  49. g_hListenSocket = INVALID_SOCKET;
  50. #endif
  51. ::ZeroMemory(g_aHostInfo, sizeof(g_aHostInfo));
  52. g_aHostInfo[0].pszHostName = "lonchanc";
  53. g_aHostInfo[1].pszHostName = "lon1";
  54. // g_aHostInfo[2].pszHostName = "lonchanc_nt";
  55. for (ULONG i = 0; i < NUM_HOSTS; i++)
  56. {
  57. g_aHostInfo[i].szConnID[0] = '\0';
  58. #ifdef USE_SOCKET
  59. g_aHostInfo[i].hSocket = INVALID_SOCKET;
  60. #else
  61. g_aHostInfo[i].pModem = NULL;
  62. #endif
  63. g_aHostInfo[i].hevtRead = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  64. g_aHostInfo[i].hevtWrite = ::CreateEvent(NULL, FALSE, FALSE, NULL);;
  65. g_aHostInfo[i].hevtClose = ::CreateEvent(NULL, FALSE, FALSE, NULL);;
  66. ASSERT(g_aHostInfo[i].hevtRead && g_aHostInfo[i].hevtWrite && g_aHostInfo[i].hevtClose);
  67. }
  68. T120Error rc = ::T120_CreatePluggableTransport(&g_pPluggableTransport);
  69. ASSERT(T120_NO_ERROR == rc);
  70. g_pPluggableTransport->ResetConnCounter();
  71. g_pPluggableTransport->DisableWinsock();
  72. gethostname(g_szMyHostName, 64);
  73. TRACE_OUT(("OnPluggableScript: HostName=%s", g_szMyHostName));
  74. for (i = 0; i < NUM_HOSTS; i++)
  75. {
  76. if (! ::lstrcmpi(g_aHostInfo[i].pszHostName, g_szMyHostName))
  77. {
  78. g_nMyHostID = i;
  79. break;
  80. }
  81. }
  82. ASSERT(i < NUM_HOSTS);
  83. ASSERT(g_nMyHostID < NUM_HOSTS);
  84. ::ZeroMemory(&g_PluggableParams, sizeof(g_PluggableParams));
  85. g_PluggableParams.cbStructSize = sizeof(g_PluggableParams);
  86. g_PluggableParams.dwFlags = PSTN_PARAM__CALL_CONTROL |
  87. PSTN_PARAM__READ_FILE_BUFFER_SIZE |
  88. PSTN_PARAM__PHYSICAL_LAYER_SEND_BUFFER_SIZE |
  89. PSTN_PARAM__PHSYICAL_LAYER_RECV_BUFFER_SIZE |
  90. PSTN_PARAM__MAX_T200_TIMEOUT_COUNT_IN_Q922 |
  91. PSTN_PARAM__T203_TIMEOUT_IN_Q922;
  92. g_PluggableParams.eCallControl = PLUGXPRT_PSTN_CALL_CONTROL_MANUAL;
  93. g_PluggableParams.cbReadFileBufferSize = 10240; // 10K
  94. g_PluggableParams.cbPhysicalLayerSendBufferSize = 1024; // 1K
  95. g_PluggableParams.cbPhysicalLayerReceiveBufferSize = 10240; // 10K
  96. g_PluggableParams.cMaximumT200TimeoutsInQ922 = 5;
  97. g_PluggableParams.nT203TimeoutInQ922 = 600;
  98. if (TOP_PROVIDER_ID == g_nMyHostID)
  99. {
  100. for (i = 0; i < NUM_HOSTS; i++)
  101. {
  102. if (i != g_nMyHostID)
  103. {
  104. #ifdef USE_SOCKET
  105. g_aHostInfo[i].hSocket = ::CreateConnectSocket(hwnd, g_aHostInfo[i].pszHostName);
  106. ASSERT(INVALID_SOCKET != g_aHostInfo[i].hSocket);
  107. #else
  108. g_aHostInfo[i].pModem = ::CreateConnectModem(g_aHostInfo[i].pszHostName);
  109. ASSERT(NULL != g_aHostInfo[i].pModem);
  110. #endif
  111. HANDLE hCommLink = NULL;
  112. #ifdef USE_SOCKET
  113. BOOL fRet = ::DuplicateHandle(::GetCurrentProcess(), (HANDLE) g_aHostInfo[i].hSocket,
  114. #else
  115. BOOL fRet = ::DuplicateHandle(::GetCurrentProcess(), g_aHostInfo[i].pModem->GetCommLink(),
  116. #endif
  117. ::GetCurrentProcess(), &hCommLink,
  118. 0, FALSE, DUPLICATE_SAME_ACCESS);
  119. ASSERT(fRet);
  120. rc = g_pPluggableTransport->CreateConnection(
  121. g_aHostInfo[i].szConnID,
  122. PLUGXPRT_CALLER, // caller
  123. hCommLink,
  124. g_aHostInfo[i].hevtRead,
  125. g_aHostInfo[i].hevtWrite,
  126. g_aHostInfo[i].hevtClose,
  127. FRAMING_LEGACY_PSTN,
  128. &g_PluggableParams);
  129. ASSERT(T120_NO_ERROR == rc);
  130. }
  131. }
  132. }
  133. else
  134. {
  135. #ifdef USE_SOCKET
  136. g_hListenSocket = ::CreateListenSocket(hwnd);
  137. #else
  138. g_aHostInfo[i].pModem = ::CreateListenModem();
  139. ASSERT(NULL != g_aHostInfo[i].pModem);
  140. HANDLE hCommLink = NULL;
  141. BOOL fRet = ::DuplicateHandle(::GetCurrentProcess(), g_aHostInfo[i].pModem->GetCommLink(),
  142. ::GetCurrentProcess(), &hCommLink,
  143. 0, FALSE, DUPLICATE_SAME_ACCESS);
  144. ASSERT(fRet);
  145. T120Error rc = g_pPluggableTransport->CreateConnection(
  146. g_aHostInfo[i].szConnID,
  147. PLUGXPRT_CALLEE, // callee
  148. hCommLink,
  149. g_aHostInfo[i].hevtRead,
  150. g_aHostInfo[i].hevtWrite,
  151. g_aHostInfo[i].hevtClose,
  152. FRAMING_LEGACY_PSTN,
  153. &g_PluggableParams);
  154. ASSERT(T120_NO_ERROR == rc);
  155. #endif
  156. }
  157. }
  158. void OnPluggableEnd(void)
  159. {
  160. #ifdef USE_SOCKET
  161. if (INVALID_SOCKET != g_hListenSocket)
  162. {
  163. ::closesocket(g_hListenSocket);
  164. }
  165. for (ULONG i = 0; i < NUM_HOSTS; i++)
  166. {
  167. if (INVALID_SOCKET != g_aHostInfo[i].hSocket)
  168. {
  169. ::closesocket(g_aHostInfo[i].hSocket);
  170. }
  171. }
  172. #else
  173. for (ULONG i = 0; i < NUM_HOSTS; i++)
  174. {
  175. if (i != g_nMyHostID)
  176. {
  177. CloseConnectModem(g_aHostInfo[i].pModem);
  178. }
  179. else
  180. {
  181. CloseListenModem(g_aHostInfo[i].pModem);
  182. }
  183. g_aHostInfo[i].pModem = NULL;
  184. }
  185. #endif
  186. g_pPluggableTransport->EnableWinsock();
  187. g_pPluggableTransport->ReleaseInterface();
  188. g_pPluggableTransport = NULL;
  189. #ifdef USE_SOCKET
  190. ::WSACleanup();
  191. #endif
  192. }
  193. LRESULT OnPluggableSocket(HWND hwnd, WPARAM wParam, LPARAM lParam)
  194. {
  195. #ifdef USE_SOCKET
  196. /* This message is generated by WinSock */
  197. SOCKET hSocket = (SOCKET) wParam;
  198. ULONG event = WSAGETSELECTEVENT(lParam);
  199. ULONG error = WSAGETSELECTERROR(lParam);
  200. ULONG nIdx = (ULONG) -1;
  201. if (hSocket != g_hListenSocket)
  202. {
  203. for (ULONG i = 0; i < NUM_HOSTS; i++)
  204. {
  205. if (hSocket == g_aHostInfo[i].hSocket)
  206. {
  207. nIdx = i;
  208. break;
  209. }
  210. }
  211. ASSERT(nIdx < NUM_HOSTS);
  212. }
  213. else
  214. {
  215. nIdx = TOP_PROVIDER_ID;
  216. }
  217. /* We disconnect whenever a socket command generates an error message */
  218. if (error)
  219. {
  220. TRACE_OUT(("OnPluggableSocket: error %d on socket (%d). Event: %d", error, hSocket, event));
  221. }
  222. /* We get FD_CLOSE when the socket is closed by the remote site. */
  223. if (event & FD_CLOSE)
  224. {
  225. TRACE_OUT(("OnPluggableSocket FD_CLOSE(%d)", hSocket));
  226. ::SetEvent(g_aHostInfo[nIdx].hevtClose);
  227. }
  228. /* We get FD_READ when there is data available for us to read. */
  229. if (event & FD_READ)
  230. {
  231. TRACE_OUT(("OnPluggableSocket FD_READ(%d)", hSocket));
  232. ::SetEvent(g_aHostInfo[nIdx].hevtRead);
  233. }
  234. /* We get FD_WRITE when there is space available to write data to WinSock */
  235. if (event & FD_WRITE)
  236. {
  237. TRACE_OUT(("OnPluggableSocket FD_WRITE(%d)", hSocket));
  238. ::SetEvent(g_aHostInfo[nIdx].hevtWrite);
  239. }
  240. /* We get FD_CONNECT when connecting to a remote site */
  241. if (event & FD_CONNECT)
  242. {
  243. TRACE_OUT(("OnPluggableSocket FD_CONNECT(%d)", hSocket));
  244. // ::SetEvent(g_aHostInfo[nIdx].hevtWrite);
  245. }
  246. /* We get FD_ACCEPT when a remote site is connecting with us */
  247. if (event & FD_ACCEPT)
  248. {
  249. TRACE_OUT(("OnPluggableSocket FD_ACCEPT(%d)", hSocket));
  250. ASSERT(nIdx == TOP_PROVIDER_ID);
  251. SOCKADDR_IN socket_control;
  252. int size = sizeof(socket_control);
  253. g_aHostInfo[nIdx].hSocket = ::accept(g_hListenSocket, (struct sockaddr *) &socket_control, &size);
  254. ASSERT(INVALID_SOCKET != g_aHostInfo[nIdx].hSocket);
  255. int nRet = ::WSAAsyncSelect(g_aHostInfo[nIdx].hSocket, hwnd,
  256. WM_PLUGABLE_SOCKET,
  257. FD_READ | FD_WRITE | FD_CLOSE | FD_CONNECT);
  258. ASSERT(SOCKET_ERROR != nRet);
  259. HANDLE hCommLink = NULL;
  260. BOOL fRet = ::DuplicateHandle(::GetCurrentProcess(), (HANDLE) g_aHostInfo[nIdx].hSocket,
  261. ::GetCurrentProcess(), &hCommLink,
  262. 0, FALSE, DUPLICATE_SAME_ACCESS);
  263. ASSERT(fRet);
  264. T120Error rc = g_pPluggableTransport->CreateConnection(
  265. g_aHostInfo[nIdx].szConnID,
  266. PLUGXPRT_CALLEE, // callee
  267. hCommLink,
  268. g_aHostInfo[nIdx].hevtRead,
  269. g_aHostInfo[nIdx].hevtWrite,
  270. g_aHostInfo[nIdx].hevtClose,
  271. FRAMING_LEGACY_PSTN,
  272. &g_PluggableParams);
  273. ASSERT(T120_NO_ERROR == rc);
  274. // ::SetEvent(g_aHostInfo[nIdx].hevtWrite);
  275. }
  276. #endif
  277. return 0;
  278. }
  279. /*
  280. * void CreateListenSocket (VOID)
  281. *
  282. * Functional Description
  283. * This function sets up a listening socket.
  284. * returns INVALID_SOCKET if there is any error.
  285. */
  286. #ifdef USE_SOCKET
  287. SOCKET CreateListenSocket(HWND hwnd)
  288. {
  289. SOCKADDR_IN socket_control;
  290. SOCKET socket_number;
  291. // Create the listening socket.
  292. socket_number = ::socket(AF_INET, SOCK_STREAM, 0);
  293. ASSERT(INVALID_SOCKET != socket_number);
  294. // The listen socket only waits for FD_ACCEPT msgs.
  295. int nRet = ::WSAAsyncSelect(socket_number, hwnd, WM_PLUGABLE_SOCKET, FD_ACCEPT);
  296. ASSERT(SOCKET_ERROR != nRet);
  297. /*
  298. * Load the socket control structure with the parameters necessary.
  299. * - Internet socket
  300. * - Let it assign any address to this socket
  301. * - Assign our port number
  302. */
  303. socket_control.sin_family = AF_INET;
  304. socket_control.sin_addr.s_addr = INADDR_ANY;
  305. socket_control.sin_port = htons ( PLUGABLE_PORT_NUMBER );
  306. /* Issue the bind call */
  307. nRet = ::bind(socket_number, (LPSOCKADDR) &socket_control, sizeof(SOCKADDR_IN));
  308. ASSERT(SOCKET_ERROR != nRet);
  309. /*
  310. * Issue a listen to WinSock to tell it we are willing to accept calls.
  311. * This is a non-blocking listen, therefore we will receive FD_ACCEPT
  312. * if someone is trying to call us.
  313. */
  314. nRet =::listen(socket_number, 3 /* LISTEN_QUEUE_SIZE */);
  315. ASSERT(SOCKET_ERROR != nRet);
  316. return socket_number;
  317. }
  318. #else
  319. CNullModem * CreateListenModem(void)
  320. {
  321. DBG_SAVE_FILE_LINE
  322. CNullModem *p = new CNullModem(g_hDllInst);
  323. ASSERT(NULL != p);
  324. TPhysicalError rc;
  325. rc = p->TPhysInitialize(NULL, 1);
  326. ASSERT(TPHYS_SUCCESS == rc);
  327. rc = p->TPhysConnectRequest("COM1");
  328. ASSERT(TPHYS_SUCCESS == rc);
  329. rc = p->TPhysListen();
  330. ASSERT(TPHYS_SUCCESS == rc);
  331. return p;
  332. }
  333. void CloseListenModem(CNullModem *p)
  334. {
  335. if (NULL != p)
  336. {
  337. TPhysicalError rc;
  338. rc = p->TPhysUnlisten();
  339. ASSERT(TPHYS_SUCCESS == rc);
  340. rc = p->TPhysDisconnect();
  341. ASSERT(TPHYS_SUCCESS == rc);
  342. rc = p->TPhysTerminate();
  343. ASSERT(TPHYS_SUCCESS == rc);
  344. delete p;
  345. }
  346. }
  347. #endif
  348. #ifdef USE_SOCKET
  349. SOCKET CreateConnectSocket(HWND hwnd, LPSTR pszHostName)
  350. {
  351. SOCKET socket_number;
  352. u_short uPort = PLUGABLE_PORT_NUMBER;
  353. PHOSTENT phe = NULL;
  354. SOCKADDR_IN socket_control;
  355. DWORD dwIPAddress;
  356. socket_number = ::socket(AF_INET, SOCK_STREAM, 0);
  357. ASSERT(INVALID_SOCKET != socket_number);
  358. /* Enable Tx and Rx messages to the window */
  359. int nRet = ::WSAAsyncSelect(socket_number, hwnd, WM_PLUGABLE_SOCKET,
  360. FD_READ | FD_WRITE | FD_CLOSE);
  361. ASSERT(SOCKET_ERROR != nRet);
  362. // fill in other info in SockAddr
  363. ::ZeroMemory(&socket_control, sizeof(socket_control));
  364. socket_control.sin_family = AF_INET;
  365. socket_control.sin_port = htons (PLUGABLE_PORT_NUMBER);
  366. // get server's IP address
  367. dwIPAddress = ::inet_addr(pszHostName);
  368. if (dwIPAddress != INADDR_NONE)
  369. {
  370. *((PDWORD) &socket_control.sin_addr) = dwIPAddress;
  371. }
  372. else
  373. {
  374. phe = ::gethostbyname(pszHostName);
  375. ASSERT(NULL != phe);
  376. ::CopyMemory(&socket_control.sin_addr, phe->h_addr, phe->h_length);
  377. }
  378. /* Attempt a connection to the remote site */
  379. nRet = ::connect(socket_number, (const struct sockaddr *) &socket_control, sizeof(socket_control));
  380. ASSERT(SOCKET_ERROR != nRet || WSAEWOULDBLOCK == ::WSAGetLastError());
  381. return socket_number;
  382. }
  383. #else
  384. CNullModem * CreateConnectModem(LPSTR pszHostName)
  385. {
  386. DBG_SAVE_FILE_LINE
  387. CNullModem *p = new CNullModem(g_hDllInst);
  388. ASSERT(NULL != p);
  389. TPhysicalError rc;
  390. rc = p->TPhysInitialize(NULL, 1);
  391. ASSERT(TPHYS_SUCCESS == rc);
  392. rc = p->TPhysConnectRequest("COM1");
  393. ASSERT(TPHYS_SUCCESS == rc);
  394. rc = p->TPhysListen();
  395. ASSERT(TPHYS_SUCCESS == rc);
  396. return p;
  397. }
  398. void CloseConnectModem(CNullModem *p)
  399. {
  400. if (NULL != p)
  401. {
  402. TPhysicalError rc;
  403. rc = p->TPhysUnlisten();
  404. ASSERT(TPHYS_SUCCESS == rc);
  405. rc = p->TPhysDisconnect();
  406. ASSERT(TPHYS_SUCCESS == rc);
  407. rc = p->TPhysTerminate();
  408. ASSERT(TPHYS_SUCCESS == rc);
  409. delete p;
  410. }
  411. }
  412. #endif
  413. #endif // TEST_PLUGABLE