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.

1897 lines
52 KiB

  1. #include "precomp.h"
  2. #include "plgxprt.h"
  3. // #undef TRACE_OUT
  4. // #define TRACE_OUT WARNING_OUT
  5. #define XPRT_CONN_ID_PREFIX "XPRT"
  6. #define XPRT_CONN_ID_PREFIX_LEN 4
  7. static UINT s_nConnID = 0;
  8. CPluggableTransport *g_pPluggableTransport = NULL;
  9. BOOL g_fWinsockDisabled = FALSE;
  10. BOOL g_fPluggableTransportInitialized = FALSE;
  11. DWORD g_dwPluggableTransportThreadID = 0;
  12. HANDLE g_hevtUpdatePluggableTransport = FALSE;
  13. CRITICAL_SECTION g_csTransport;
  14. ILegacyTransport *g_pLegacyTransport = NULL;
  15. HINSTANCE g_hlibMST123 = NULL;
  16. BOOL EnsurePluggableTransportThread(void);
  17. extern HWND TCP_Window_Handle;
  18. extern SOCKET Listen_Socket;
  19. extern SOCKET Listen_Socket_Secure;
  20. extern PTransportInterface g_Transport;
  21. extern UChar g_X224Header[];
  22. extern void CloseListenSocket(void);
  23. T120Error WINAPI T120_CreatePluggableTransport(IT120PluggableTransport **ppTransport)
  24. {
  25. if (NULL != ppTransport)
  26. {
  27. *ppTransport = NULL;
  28. if (NULL == g_pPluggableTransport)
  29. {
  30. if (g_fPluggableTransportInitialized)
  31. {
  32. DBG_SAVE_FILE_LINE
  33. *ppTransport = (CPluggableTransport *) new CPluggableTransport;
  34. if (NULL != *ppTransport)
  35. {
  36. if (EnsurePluggableTransportThread())
  37. {
  38. return T120_NO_ERROR;
  39. }
  40. else
  41. {
  42. (*ppTransport)->ReleaseInterface();
  43. *ppTransport = NULL;
  44. }
  45. }
  46. return T120_ALLOCATION_FAILURE;
  47. }
  48. return T120_NOT_INITIALIZED;
  49. }
  50. return T120_ALREADY_INITIALIZED;
  51. }
  52. return T120_INVALID_PARAMETER;
  53. }
  54. CPluggableConnection::CPluggableConnection
  55. (
  56. PLUGXPRT_CALL_TYPE eCaller,
  57. HANDLE hCommLink,
  58. HANDLE hevtRead,
  59. HANDLE hevtWrite,
  60. HANDLE hevtClose,
  61. PLUGXPRT_FRAMING eFraming,
  62. PLUGXPRT_PARAMETERS *pParams,
  63. T120Error *pRC
  64. )
  65. :
  66. CRefCount(MAKE_STAMP_ID('P','X','P','C')),
  67. m_eState(PLUGXPRT_UNKNOWN_STATE),
  68. m_eCaller(eCaller),
  69. m_hCommLink(hCommLink),
  70. m_hevtRead(hevtRead),
  71. m_hevtWrite(hevtWrite),
  72. m_hevtClose(hevtClose),
  73. m_eType(TRANSPORT_TYPE_PLUGGABLE_X224),
  74. m_pSocket(NULL),
  75. // Legacy tranport
  76. m_nLegacyLogicalHandle(0),
  77. // IO queue management for X.224 framing
  78. m_hevtPendingRead(NULL),
  79. m_hevtPendingWrite(NULL),
  80. m_fPendingReadDone(FALSE),
  81. m_cbPendingRead(0),
  82. m_pbPendingRead(NULL),
  83. m_cbPendingWrite(0),
  84. m_pbPendingWrite(NULL),
  85. m_OutBufQueue2(MAX_PLUGGABLE_OUT_BUF_SIZE)
  86. {
  87. TransportError err;
  88. BOOL fCaller = (PLUGXPRT_CALLER == eCaller);
  89. // X.224 only
  90. ::ZeroMemory(&m_OverlappedRead, sizeof(m_OverlappedRead));
  91. ::ZeroMemory(&m_OverlappedWrite, sizeof(m_OverlappedWrite));
  92. // assign connection ID
  93. ::EnterCriticalSection(&g_csTransport);
  94. if (s_nConnID > 0x7FFF)
  95. {
  96. s_nConnID = 0;
  97. }
  98. m_nConnID = ++s_nConnID;
  99. ::LeaveCriticalSection(&g_csTransport);
  100. // create connection ID string
  101. ::CreateConnString(GetConnID(), m_szConnID);
  102. // do framing specific initialization
  103. switch (eFraming)
  104. {
  105. case FRAMING_X224:
  106. m_eType = TRANSPORT_TYPE_PLUGGABLE_X224;
  107. m_hevtPendingRead = ::CreateEvent(NULL, TRUE, FALSE, NULL); /* manual reset */
  108. m_hevtPendingWrite = ::CreateEvent(NULL, TRUE, FALSE, NULL); /* manual reset */
  109. ASSERT(NULL != m_hevtPendingRead && NULL != m_hevtPendingWrite);
  110. *pRC = (NULL != m_hevtPendingRead && NULL != m_hevtPendingWrite)
  111. ? T120_NO_ERROR : T120_ALLOCATION_FAILURE;
  112. break;
  113. case FRAMING_LEGACY_PSTN:
  114. m_eType = TRANSPORT_TYPE_PLUGGABLE_PSTN;
  115. ASSERT(NULL != g_pLegacyTransport);
  116. err = g_pLegacyTransport->TCreateTransportStack(fCaller, m_hCommLink, m_hevtClose, pParams);
  117. ASSERT(TRANSPORT_NO_ERROR == err);
  118. *pRC = (TRANSPORT_NO_ERROR == err) ? T120_NO_ERROR : T120_NO_TRANSPORT_STACKS;
  119. break;
  120. default:
  121. ERROR_OUT(("CPluggableConnection: unknown framing %d", eFraming));
  122. *pRC = T120_INVALID_PARAMETER;
  123. break;
  124. }
  125. }
  126. CPluggableConnection::~CPluggableConnection(void)
  127. {
  128. if (NULL != m_pSocket)
  129. {
  130. ::freePluggableSocket(m_pSocket);
  131. m_pSocket = NULL;
  132. }
  133. Shutdown();
  134. if (TRANSPORT_TYPE_PLUGGABLE_PSTN == m_eType)
  135. {
  136. if (NULL != g_pLegacyTransport && NULL != m_hCommLink)
  137. {
  138. g_pLegacyTransport->TCloseTransportStack(m_hCommLink);
  139. }
  140. }
  141. if (NULL != m_hCommLink)
  142. {
  143. ::CloseHandle(m_hCommLink);
  144. }
  145. if (NULL != m_hevtRead)
  146. {
  147. ::CloseHandle(m_hevtRead);
  148. }
  149. if (NULL != m_hevtWrite)
  150. {
  151. ::CloseHandle(m_hevtWrite);
  152. }
  153. if (NULL != m_hevtClose)
  154. {
  155. ::CloseHandle(m_hevtClose);
  156. }
  157. if (NULL != m_hevtPendingRead)
  158. {
  159. ::CloseHandle(m_hevtPendingRead);
  160. }
  161. if (NULL != m_hevtPendingWrite)
  162. {
  163. ::CloseHandle(m_hevtPendingWrite);
  164. }
  165. }
  166. ULONG CreateConnString(int nConnID, char szConnID[])
  167. {
  168. return ::wsprintfA(szConnID, "%s: %u", XPRT_CONN_ID_PREFIX, nConnID);
  169. }
  170. UINT GetPluggableTransportConnID(LPCSTR pcszNodeAddress)
  171. {
  172. UINT nConnID = 0;
  173. char szName[T120_CONNECTION_ID_LENGTH];
  174. // make sure we have a clean buffer to start with
  175. ::ZeroMemory(szName, sizeof(szName));
  176. // copy the address string
  177. ::lstrcpynA(szName, pcszNodeAddress, T120_CONNECTION_ID_LENGTH);
  178. // make sure we have the semi-colon in place
  179. if (':' == szName[XPRT_CONN_ID_PREFIX_LEN])
  180. {
  181. // compare the prefix string
  182. szName[XPRT_CONN_ID_PREFIX_LEN] = '\0';
  183. if (! lstrcmpA(szName, XPRT_CONN_ID_PREFIX))
  184. {
  185. LPSTR psz = &szName[XPRT_CONN_ID_PREFIX_LEN+1];
  186. // get a space?
  187. if (' ' == *psz++)
  188. {
  189. // now, have a number
  190. if ('0' <= *psz && *psz <= '9')
  191. {
  192. while ('0' <= *psz && *psz <= '9')
  193. {
  194. nConnID = nConnID * 10 + (*psz++ - '0');
  195. }
  196. }
  197. }
  198. }
  199. }
  200. return nConnID;
  201. }
  202. BOOL IsValidPluggableTransportName(LPCSTR pcszNodeAddress)
  203. {
  204. return GetPluggableTransportConnID(pcszNodeAddress);
  205. }
  206. typedef BOOL (WINAPI *LPFN_CANCEL_IO) (HANDLE);
  207. void CPluggableConnection::Shutdown(void)
  208. {
  209. TRACE_OUT(("CPluggableConnection::Shutdown"));
  210. if (NULL != m_OverlappedRead.hEvent || NULL != m_OverlappedWrite.hEvent)
  211. {
  212. HINSTANCE hLib = ::LoadLibrary("kernel32.dll");
  213. if (NULL != hLib)
  214. {
  215. LPFN_CANCEL_IO pfnCancelIo = (LPFN_CANCEL_IO) ::GetProcAddress(hLib, "CancelIo");
  216. if (NULL != pfnCancelIo)
  217. {
  218. (*pfnCancelIo)(m_hCommLink);
  219. }
  220. ::FreeLibrary(hLib);
  221. }
  222. m_OverlappedRead.hEvent = NULL;
  223. m_OverlappedWrite.hEvent = NULL;
  224. }
  225. delete [] m_pbPendingRead;
  226. m_pbPendingRead = NULL;
  227. LPBYTE buffer;
  228. while (NULL != (buffer = m_OutBufQueue2.Get()))
  229. {
  230. delete [] buffer;
  231. }
  232. }
  233. T120Error CPluggableConnection::UpdateCommLink(HANDLE hCommLink)
  234. {
  235. T120Error rc;
  236. ::EnterCriticalSection(&g_csTransport);
  237. switch (m_eState)
  238. {
  239. case PLUGXPRT_UNKNOWN_STATE:
  240. case PLUGXPRT_DISCONNECTED:
  241. Shutdown();
  242. m_hCommLink = hCommLink;
  243. rc = T120_NO_ERROR;
  244. break;
  245. default:
  246. rc = T120_TRANSPORT_NOT_READY;
  247. break;
  248. }
  249. ::LeaveCriticalSection(&g_csTransport);
  250. return rc;
  251. }
  252. CPluggableTransport::CPluggableTransport(void)
  253. :
  254. CRefCount(MAKE_STAMP_ID('X','P','R','T')),
  255. m_pfnNotify(NULL),
  256. m_pContext(NULL)
  257. {
  258. g_pPluggableTransport = this;
  259. g_pLegacyTransport = NULL;
  260. }
  261. CPluggableTransport::~CPluggableTransport(void)
  262. {
  263. ::PostThreadMessage(g_dwPluggableTransportThreadID, WM_QUIT, 0, 0);
  264. CPluggableConnection *p;
  265. ::EnterCriticalSection(&g_csTransport);
  266. while (NULL != (p = m_PluggableConnectionList.Get()))
  267. {
  268. p->Release();
  269. }
  270. ::LeaveCriticalSection(&g_csTransport);
  271. if (NULL != g_pLegacyTransport)
  272. {
  273. g_pLegacyTransport->TCleanup();
  274. g_pLegacyTransport->ReleaseInterface();
  275. g_pLegacyTransport = NULL;
  276. }
  277. if (NULL != g_hlibMST123)
  278. {
  279. ::FreeLibrary(g_hlibMST123);
  280. g_hlibMST123 = NULL;
  281. }
  282. g_pPluggableTransport = NULL;
  283. }
  284. void CPluggableTransport::ReleaseInterface(void)
  285. {
  286. UnAdvise();
  287. CRefCount::Release();
  288. }
  289. T120Error CPluggableTransport::CreateConnection
  290. (
  291. char szConnID[], /* out */
  292. PLUGXPRT_CALL_TYPE eCaller,
  293. HANDLE hCommLink,
  294. HANDLE hevtRead,
  295. HANDLE hevtWrite,
  296. HANDLE hevtClose,
  297. PLUGXPRT_FRAMING eFraming,
  298. PLUGXPRT_PARAMETERS *pParams
  299. )
  300. {
  301. T120Error rc;
  302. if (FRAMING_LEGACY_PSTN == eFraming)
  303. {
  304. if (! EnsureLegacyTransportLoaded())
  305. {
  306. return T120_NO_TRANSPORT_STACKS;
  307. }
  308. }
  309. if (NULL != pParams)
  310. {
  311. if (sizeof(PLUGXPRT_PARAMETERS) != pParams->cbStructSize)
  312. {
  313. return T120_INVALID_PARAMETER;
  314. }
  315. }
  316. DBG_SAVE_FILE_LINE
  317. CPluggableConnection *p;
  318. p = new CPluggableConnection(eCaller, hCommLink, hevtRead, hevtWrite, hevtClose,
  319. eFraming, pParams, &rc);
  320. if (NULL != p && T120_NO_ERROR == rc)
  321. {
  322. ::lstrcpyA(szConnID, p->GetConnString());
  323. ::EnterCriticalSection(&g_csTransport);
  324. m_PluggableConnectionList.Append(p);
  325. ::LeaveCriticalSection(&g_csTransport);
  326. TransportConnection XprtConn;
  327. XprtConn.eType = p->GetType();
  328. XprtConn.nLogicalHandle = p->GetConnID();
  329. PSocket pSocket = ::newPluggableSocket(XprtConn);
  330. p->SetSocket(pSocket);
  331. ASSERT(NULL != pSocket);
  332. // update the events list to wait for in the plugable transport thread
  333. ::SetEvent(g_hevtUpdatePluggableTransport);
  334. return T120_NO_ERROR;
  335. }
  336. if (NULL != p)
  337. {
  338. p->Release();
  339. }
  340. else
  341. {
  342. rc = T120_ALLOCATION_FAILURE;
  343. }
  344. return rc;
  345. }
  346. T120Error CPluggableTransport::UpdateConnection
  347. (
  348. LPSTR pszConnID,
  349. HANDLE hCommLink
  350. )
  351. {
  352. BOOL fFound = FALSE;
  353. CPluggableConnection *p;
  354. T120Error rc = GCC_INVALID_TRANSPORT;
  355. ::EnterCriticalSection(&g_csTransport);
  356. m_PluggableConnectionList.Reset();
  357. while (NULL != (p = m_PluggableConnectionList.Iterate()))
  358. {
  359. if (! ::lstrcmpA(p->GetConnString(), pszConnID))
  360. {
  361. rc = p->UpdateCommLink(hCommLink);
  362. break;
  363. }
  364. }
  365. ::LeaveCriticalSection(&g_csTransport);
  366. // update the events list to wait for in the plugable transport thread
  367. ::SetEvent(g_hevtUpdatePluggableTransport);
  368. return rc;
  369. }
  370. T120Error CPluggableTransport::CloseConnection
  371. (
  372. LPSTR pszConnID
  373. )
  374. {
  375. CPluggableConnection *p;
  376. ::EnterCriticalSection(&g_csTransport);
  377. m_PluggableConnectionList.Reset();
  378. while (NULL != (p = m_PluggableConnectionList.Iterate()))
  379. {
  380. if (! ::lstrcmpA(p->GetConnString(), pszConnID))
  381. {
  382. m_PluggableConnectionList.Remove(p);
  383. break;
  384. }
  385. }
  386. ::LeaveCriticalSection(&g_csTransport);
  387. // update the events list to wait for in the plugable transport thread
  388. ::SetEvent(g_hevtUpdatePluggableTransport);
  389. if (NULL != p)
  390. {
  391. //
  392. // do real work here
  393. //
  394. p->Release();
  395. return T120_NO_ERROR;
  396. }
  397. return GCC_INVALID_TRANSPORT;
  398. }
  399. T120Error CPluggableTransport::EnableWinsock(void)
  400. {
  401. if (g_fWinsockDisabled)
  402. {
  403. g_fWinsockDisabled = FALSE;
  404. //
  405. // LONCHANC: create Listen_Socket if not done so...
  406. //
  407. if (INVALID_SOCKET == Listen_Socket)
  408. {
  409. Listen_Socket = ::CreateAndConfigureListenSocket();
  410. }
  411. }
  412. return T120_NO_ERROR;
  413. }
  414. T120Error CPluggableTransport::DisableWinsock(void)
  415. {
  416. if (! g_fWinsockDisabled)
  417. {
  418. g_fWinsockDisabled = TRUE;
  419. // close Listen_Socket...
  420. ::CloseListenSocket();
  421. }
  422. return T120_NO_ERROR;
  423. }
  424. void CPluggableTransport::Advise(LPFN_PLUGXPRT_CB pNotify, LPVOID pContext)
  425. {
  426. m_pfnNotify = pNotify;
  427. m_pContext = pContext;
  428. }
  429. void CPluggableTransport::UnAdvise(void)
  430. {
  431. m_pfnNotify = NULL;
  432. m_pContext = NULL;
  433. }
  434. void CPluggableTransport::ResetConnCounter(void)
  435. {
  436. s_nConnID = 0;
  437. }
  438. void CPluggableTransport::OnProtocolControl
  439. (
  440. TransportConnection XprtConn,
  441. PLUGXPRT_STATE eState,
  442. PLUGXPRT_RESULT eResult
  443. )
  444. {
  445. if (IS_PLUGGABLE(XprtConn))
  446. {
  447. WARNING_OUT(("CPluggableTransport::OnProtocolControl: socket (%d, %d) is doing %d with result %d",
  448. XprtConn.eType, XprtConn.nLogicalHandle, eState, eResult));
  449. if (NULL != m_pfnNotify)
  450. {
  451. CPluggableConnection *p = GetPluggableConnection(XprtConn.nLogicalHandle);
  452. if (NULL != p)
  453. {
  454. PLUGXPRT_MESSAGE Msg;
  455. Msg.eState = eState;
  456. Msg.pContext = m_pContext;
  457. Msg.pszConnID = p->GetConnString();
  458. // we only support X.224 level notifications
  459. Msg.eProtocol = PLUGXPRT_PROTOCOL_X224;
  460. Msg.eResult = eResult;
  461. (*m_pfnNotify)(&Msg);
  462. }
  463. }
  464. }
  465. }
  466. void OnProtocolControl
  467. (
  468. TransportConnection XprtConn,
  469. PLUGXPRT_STATE eState,
  470. PLUGXPRT_RESULT eResult
  471. )
  472. {
  473. if (NULL != g_pPluggableTransport)
  474. {
  475. g_pPluggableTransport->OnProtocolControl(XprtConn, eState, eResult);
  476. }
  477. }
  478. // called only in the plugable transport thread
  479. // already in the critical section
  480. ULONG CPluggableTransport::UpdateEvents(HANDLE *aHandles)
  481. {
  482. ULONG cHandles = 0;
  483. CPluggableConnection *p;
  484. ::EnterCriticalSection(&g_csTransport);
  485. m_PluggableConnectionList.Reset();
  486. while (NULL != (p = m_PluggableConnectionList.Iterate()))
  487. {
  488. if (TRANSPORT_TYPE_PLUGGABLE_X224 == p->GetType())
  489. {
  490. aHandles[cHandles++] = p->GetReadEvent();
  491. aHandles[cHandles++] = p->GetWriteEvent();
  492. aHandles[cHandles++] = p->GetCloseEvent();
  493. aHandles[cHandles++] = p->GetPendingReadEvent();
  494. aHandles[cHandles++] = p->GetPendingWriteEvent();
  495. }
  496. }
  497. ::LeaveCriticalSection(&g_csTransport);
  498. return cHandles;
  499. }
  500. // called only in the plugable transport thread
  501. // already in the critical section
  502. void CPluggableTransport::OnEventSignaled(HANDLE hevtSignaled)
  503. {
  504. CPluggableConnection *p;
  505. BOOL fPostMessage, fFound;
  506. WPARAM wParam;
  507. LPARAM lParam;
  508. ::EnterCriticalSection(&g_csTransport);
  509. m_PluggableConnectionList.Reset();
  510. while (NULL != (p = m_PluggableConnectionList.Iterate()))
  511. {
  512. fFound = TRUE;
  513. fPostMessage = FALSE;
  514. wParam = MAKE_PLUGXPRT_WPARAM(p->GetConnID(), p->GetType());
  515. if (hevtSignaled == p->GetReadEvent())
  516. {
  517. lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_READ, PLUGXPRT_RESULT_SUCCESSFUL);
  518. fPostMessage = TRUE;
  519. }
  520. else
  521. if (hevtSignaled == p->GetWriteEvent())
  522. {
  523. lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_WRITE, PLUGXPRT_RESULT_SUCCESSFUL);
  524. fPostMessage = TRUE;
  525. }
  526. else
  527. if (hevtSignaled == p->GetCloseEvent())
  528. {
  529. lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_CLOSE, PLUGXPRT_RESULT_SUCCESSFUL);
  530. fPostMessage = TRUE;
  531. }
  532. else
  533. {
  534. TransportConnection XprtConn;
  535. XprtConn.eType = p->GetType();
  536. XprtConn.nLogicalHandle = p->GetConnID();
  537. if (hevtSignaled == p->GetPendingReadEvent())
  538. {
  539. TRACE_OUT(("OnEventSignaled: PendingREAD(%d, %d)", p->GetType(), p->GetConnID()));
  540. if (p->OnPendingRead())
  541. {
  542. ::ResetEvent(hevtSignaled);
  543. // start next high-level read
  544. p->NotifyHighLevelRead();
  545. }
  546. }
  547. else
  548. if (hevtSignaled == p->GetPendingWriteEvent())
  549. {
  550. TRACE_OUT(("OnEventSignaled: PendingWRITE(%d, %d)", p->GetType(), p->GetConnID()));
  551. if (p->OnPendingWrite())
  552. {
  553. ::ResetEvent(hevtSignaled);
  554. // start next low-level write
  555. p->NotifyWriteEvent();
  556. }
  557. }
  558. else
  559. {
  560. fFound = FALSE;
  561. }
  562. }
  563. if (fPostMessage)
  564. {
  565. BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam);
  566. ASSERT(fRet);
  567. }
  568. if (fFound)
  569. {
  570. break;
  571. }
  572. } // while
  573. ::LeaveCriticalSection(&g_csTransport);
  574. ASSERT(NULL != p);
  575. }
  576. // called only in the plugable transport thread
  577. // already in the critical section
  578. void CPluggableTransport::OnEventAbandoned(HANDLE hevtSignaled)
  579. {
  580. CPluggableConnection *p;
  581. BOOL fFound;
  582. WPARAM wParam;
  583. LPARAM lParam;
  584. ::EnterCriticalSection(&g_csTransport);
  585. m_PluggableConnectionList.Reset();
  586. while (NULL != (p = m_PluggableConnectionList.Iterate()))
  587. {
  588. fFound = TRUE;
  589. wParam = MAKE_PLUGXPRT_WPARAM(p->GetConnID(), p->GetType());
  590. if (hevtSignaled == p->GetReadEvent())
  591. {
  592. lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_READ, PLUGXPRT_RESULT_ABANDONED);
  593. }
  594. else
  595. if (hevtSignaled == p->GetWriteEvent())
  596. {
  597. lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_WRITE, PLUGXPRT_RESULT_ABANDONED);
  598. }
  599. else
  600. if (hevtSignaled == p->GetCloseEvent())
  601. {
  602. lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_CLOSE, PLUGXPRT_RESULT_ABANDONED);
  603. }
  604. else
  605. if (hevtSignaled == p->GetPendingReadEvent())
  606. {
  607. lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_PENDING_EVENT, PLUGXPRT_RESULT_ABANDONED);
  608. }
  609. else
  610. if (hevtSignaled == p->GetPendingWriteEvent())
  611. {
  612. lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_PENDING_EVENT, PLUGXPRT_RESULT_ABANDONED);
  613. }
  614. else
  615. {
  616. fFound = FALSE;
  617. }
  618. if (fFound)
  619. {
  620. m_PluggableConnectionList.Remove(p);
  621. // update the events list to wait for in the plugable transport thread
  622. ::SetEvent(g_hevtUpdatePluggableTransport);
  623. BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam);
  624. ASSERT(fRet);
  625. break;
  626. }
  627. } // while
  628. ::LeaveCriticalSection(&g_csTransport);
  629. ASSERT(NULL != p);
  630. }
  631. CPluggableConnection * CPluggableTransport::GetPluggableConnection(PSocket pSocket)
  632. {
  633. CPluggableConnection *p;
  634. ::EnterCriticalSection(&g_csTransport);
  635. m_PluggableConnectionList.Reset();
  636. while (NULL != (p = m_PluggableConnectionList.Iterate()))
  637. {
  638. if (p->GetType() == pSocket->XprtConn.eType &&
  639. p->GetConnID() == pSocket->XprtConn.nLogicalHandle)
  640. {
  641. break;
  642. }
  643. }
  644. ::LeaveCriticalSection(&g_csTransport);
  645. return p;
  646. }
  647. CPluggableConnection * GetPluggableConnection(PSocket pSocket)
  648. {
  649. return (NULL != g_pPluggableTransport) ?
  650. g_pPluggableTransport->GetPluggableConnection(pSocket) :
  651. NULL;
  652. }
  653. CPluggableConnection * CPluggableTransport::GetPluggableConnection(UINT_PTR nConnID)
  654. {
  655. CPluggableConnection *p;
  656. ::EnterCriticalSection(&g_csTransport);
  657. m_PluggableConnectionList.Reset();
  658. while (NULL != (p = m_PluggableConnectionList.Iterate()))
  659. {
  660. if (p->GetConnID() == nConnID)
  661. {
  662. break;
  663. }
  664. }
  665. ::LeaveCriticalSection(&g_csTransport);
  666. return p;
  667. }
  668. CPluggableConnection * GetPluggableConnection(UINT_PTR nConnID)
  669. {
  670. return (NULL != g_pPluggableTransport) ?
  671. g_pPluggableTransport->GetPluggableConnection(nConnID) :
  672. NULL;
  673. }
  674. CPluggableConnection * CPluggableTransport::GetPluggableConnection(HANDLE hCommLink)
  675. {
  676. CPluggableConnection *p;
  677. ::EnterCriticalSection(&g_csTransport);
  678. m_PluggableConnectionList.Reset();
  679. while (NULL != (p = m_PluggableConnectionList.Iterate()))
  680. {
  681. if (p->GetCommLink() == hCommLink)
  682. {
  683. break;
  684. }
  685. }
  686. ::LeaveCriticalSection(&g_csTransport);
  687. return p;
  688. }
  689. CPluggableConnection * GetPluggableConnection(HANDLE hCommLink)
  690. {
  691. return (NULL != g_pPluggableTransport) ?
  692. g_pPluggableTransport->GetPluggableConnection(hCommLink) :
  693. NULL;
  694. }
  695. CPluggableConnection * CPluggableTransport::GetPluggableConnectionByLegacyHandle(LEGACY_HANDLE logical_handle)
  696. {
  697. CPluggableConnection *p;
  698. ::EnterCriticalSection(&g_csTransport);
  699. m_PluggableConnectionList.Reset();
  700. while (NULL != (p = m_PluggableConnectionList.Iterate()))
  701. {
  702. if (p->GetLegacyHandle() == logical_handle)
  703. {
  704. break;
  705. }
  706. }
  707. ::LeaveCriticalSection(&g_csTransport);
  708. return p;
  709. }
  710. CPluggableConnection * GetPluggableConnectionByLegacyHandle(LEGACY_HANDLE logical_handle)
  711. {
  712. return (NULL != g_pPluggableTransport) ?
  713. g_pPluggableTransport->GetPluggableConnectionByLegacyHandle(logical_handle) :
  714. NULL;
  715. }
  716. // called in ERNC ConfMgr's constructor
  717. BOOL InitializePluggableTransport(void)
  718. {
  719. if (! g_fPluggableTransportInitialized)
  720. {
  721. g_fWinsockDisabled = FALSE;
  722. g_hevtUpdatePluggableTransport = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  723. if (NULL != g_hevtUpdatePluggableTransport)
  724. {
  725. g_fPluggableTransportInitialized = TRUE;
  726. }
  727. }
  728. return g_fPluggableTransportInitialized;
  729. }
  730. // called in ERNC ConfMgr's destructor
  731. void CleanupPluggableTransport(void)
  732. {
  733. if (g_fPluggableTransportInitialized)
  734. {
  735. g_fPluggableTransportInitialized = FALSE;
  736. if (g_dwPluggableTransportThreadID)
  737. {
  738. ::PostThreadMessage(g_dwPluggableTransportThreadID, WM_QUIT, 0, 0);
  739. }
  740. ::EnterCriticalSection(&g_csTransport);
  741. if (NULL != g_hevtUpdatePluggableTransport)
  742. {
  743. ::CloseHandle(g_hevtUpdatePluggableTransport);
  744. }
  745. ::LeaveCriticalSection(&g_csTransport);
  746. }
  747. }
  748. DWORD __stdcall PluggableTransportThreadProc(LPVOID lpv)
  749. {
  750. MSG msg;
  751. BOOL fContinueMainLoop = TRUE;
  752. DWORD nEventSignaled;
  753. ULONG cEvents;
  754. HANDLE aEvents[MAX_PLUGXPRT_CONNECTIONS * MAX_PLUGXPRT_EVENTS + 1];
  755. // signaling that the work hread has been started.
  756. ::SetEvent((HANDLE) lpv);
  757. // set up initial event list, the first entry always for update event
  758. cEvents = 1;
  759. aEvents[0] = g_hevtUpdatePluggableTransport;
  760. ::SetEvent(g_hevtUpdatePluggableTransport);
  761. // main loop
  762. while (fContinueMainLoop)
  763. {
  764. // process any possible window and thread messages
  765. while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  766. {
  767. if (WM_QUIT != msg.message)
  768. {
  769. ::DispatchMessage(&msg);
  770. }
  771. else
  772. {
  773. fContinueMainLoop = FALSE;
  774. break;
  775. }
  776. }
  777. if (fContinueMainLoop)
  778. {
  779. nEventSignaled = ::MsgWaitForMultipleObjects(cEvents, aEvents, FALSE, INFINITE, QS_ALLINPUT);
  780. ::EnterCriticalSection(&g_csTransport);
  781. if (NULL != g_pPluggableTransport)
  782. {
  783. switch (nEventSignaled)
  784. {
  785. case WAIT_OBJECT_0:
  786. // update the event list
  787. cEvents = 1 + g_pPluggableTransport->UpdateEvents(&aEvents[1]);
  788. break;
  789. case WAIT_TIMEOUT:
  790. // impossible, do nothing
  791. break;
  792. default:
  793. if (WAIT_OBJECT_0 + 1 <= nEventSignaled && nEventSignaled < WAIT_OBJECT_0 + cEvents)
  794. {
  795. g_pPluggableTransport->OnEventSignaled(aEvents[nEventSignaled - WAIT_OBJECT_0]);
  796. }
  797. else
  798. if (WAIT_ABANDONED_0 + 1 <= nEventSignaled && nEventSignaled < WAIT_ABANDONED_0 + cEvents)
  799. {
  800. g_pPluggableTransport->OnEventAbandoned(aEvents[nEventSignaled - WAIT_OBJECT_0]);
  801. }
  802. break;
  803. }
  804. }
  805. else
  806. {
  807. fContinueMainLoop = FALSE;
  808. }
  809. ::LeaveCriticalSection(&g_csTransport);
  810. }
  811. } // while
  812. g_dwPluggableTransportThreadID = 0;
  813. return 0;
  814. }
  815. BOOL EnsurePluggableTransportThread(void)
  816. {
  817. BOOL fRet = TRUE;
  818. if (! g_dwPluggableTransportThreadID)
  819. {
  820. fRet = FALSE;
  821. HANDLE hSync = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  822. if (NULL != hSync)
  823. {
  824. HANDLE hThread = ::CreateThread(NULL, 0, PluggableTransportThreadProc, hSync, 0,
  825. &g_dwPluggableTransportThreadID);
  826. if (NULL != hThread)
  827. {
  828. ::WaitForSingleObject(hSync, 5000); // 5 second
  829. ::CloseHandle(hThread);
  830. fRet = TRUE;
  831. }
  832. ::CloseHandle(hSync);
  833. }
  834. }
  835. return fRet;
  836. }
  837. #if defined(TEST_PLUGGABLE) && defined(_DEBUG)
  838. LPCSTR FakeNodeAddress(LPCSTR pcszNodeAddress)
  839. {
  840. char szAddr[64];
  841. ::lstrcpyA(szAddr, pcszNodeAddress);
  842. for (LPSTR psz = &szAddr[0]; *psz; psz++)
  843. {
  844. if (*psz == ':')
  845. {
  846. *psz = '\0';
  847. break;
  848. }
  849. }
  850. if (! ::lstrcmp(szAddr, "157.59.12.93"))
  851. {
  852. pcszNodeAddress = "XPRT: 1";
  853. }
  854. else
  855. if (! ::lstrcmp(szAddr, "157.59.13.194"))
  856. {
  857. pcszNodeAddress = "XPRT: 2";
  858. }
  859. else
  860. if (! ::lstrcmp(szAddr, "157.59.10.198"))
  861. {
  862. pcszNodeAddress = "XPRT: 1";
  863. }
  864. else
  865. {
  866. ASSERT(0);
  867. }
  868. return pcszNodeAddress;
  869. }
  870. #endif
  871. int SubmitPluggableRead(PSocket pSocket, LPBYTE buffer, int length, PLUGXPRT_RESULT *plug_rc)
  872. {
  873. TRACE_OUT(("SubmitPluggableRead"));
  874. int nRet = SOCKET_ERROR;
  875. *plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
  876. CPluggableConnection *p = ::GetPluggableConnection(pSocket);
  877. if (NULL != p)
  878. {
  879. nRet = p->Read(buffer, length, plug_rc);
  880. }
  881. else
  882. {
  883. WARNING_OUT(("SubmitPluggableRead: no such conn ID=%d", pSocket->XprtConn.nLogicalHandle));
  884. }
  885. return nRet;
  886. }
  887. int CPluggableConnection::Read(LPBYTE buffer, int length, PLUGXPRT_RESULT *plug_rc)
  888. {
  889. int cbRecv = SOCKET_ERROR;
  890. *plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
  891. ::EnterCriticalSection(&g_csTransport);
  892. if (NULL != m_OverlappedRead.hEvent)
  893. {
  894. // handle low-level pending read first
  895. if (m_fPendingReadDone)
  896. {
  897. // copy the data from internal buffer to external buffer
  898. if (length <= m_cbPendingRead)
  899. {
  900. // get as requested
  901. cbRecv = length;
  902. ::CopyMemory(buffer, m_pbPendingRead, length);
  903. m_cbPendingRead -= length;
  904. if (m_cbPendingRead <= 0)
  905. {
  906. CleanupReadState();
  907. }
  908. else
  909. {
  910. // move the memory, do not use copymemory due to overlap
  911. int cb = m_cbPendingRead;
  912. LPBYTE pbDst = m_pbPendingRead;
  913. LPBYTE pbSrc = &m_pbPendingRead[length];
  914. while (cb--)
  915. {
  916. *pbDst++ = *pbSrc++;
  917. }
  918. }
  919. }
  920. else
  921. {
  922. // only get partial data
  923. cbRecv = m_cbPendingRead;
  924. ::CopyMemory(buffer, m_pbPendingRead, m_cbPendingRead);
  925. CleanupReadState();
  926. }
  927. // start next high-level read
  928. NotifyHighLevelRead();
  929. }
  930. }
  931. else
  932. {
  933. if (SetupReadState(length))
  934. {
  935. TRACE_OUT(("CPluggableConnection::Read: ReadFile(%d)", m_cbPendingRead));
  936. DWORD dwRead = 0;
  937. if (! ::ReadFile(m_hCommLink,
  938. m_pbPendingRead,
  939. m_cbPendingRead,
  940. &dwRead,
  941. &m_OverlappedRead))
  942. {
  943. DWORD dwErr = ::GetLastError();
  944. if (ERROR_HANDLE_EOF != dwErr && ERROR_IO_PENDING != dwErr)
  945. {
  946. WARNING_OUT(("CPluggableConnection::Read: ReadFile failed, err=%d", dwErr));
  947. CleanupReadState();
  948. // disconnect at next tick
  949. NotifyReadFailure();
  950. *plug_rc = PLUGXPRT_RESULT_READ_FAILED;
  951. }
  952. }
  953. else
  954. {
  955. // do nothing, treat it as WSAEWOULDBLOCK
  956. }
  957. }
  958. else
  959. {
  960. ERROR_OUT(("CPluggableConnection::Read: failed to allocate memory (%d)", length));
  961. // out of memory, try later
  962. // do nothing, treat it as WSAEWOULDBLOCK
  963. }
  964. }
  965. ::LeaveCriticalSection(&g_csTransport);
  966. return cbRecv;
  967. }
  968. BOOL CPluggableConnection::OnPendingRead(void)
  969. {
  970. TRACE_OUT(("CPluggableConnection::OnPendingRead"));
  971. BOOL fRet = FALSE;
  972. ::EnterCriticalSection(&g_csTransport);
  973. if (NULL != m_OverlappedRead.hEvent)
  974. {
  975. DWORD cbRead = 0;
  976. if (::GetOverlappedResult(m_hCommLink, &m_OverlappedRead, &cbRead, FALSE))
  977. {
  978. if ((int) cbRead == m_cbPendingRead)
  979. {
  980. TRACE_OUT(("CPluggableConnection::OnPendingRead: Received %d bytes (required %d bytes) on socket (%d, %d).",
  981. cbRead, m_cbPendingRead, m_eType, m_nConnID));
  982. }
  983. else
  984. {
  985. WARNING_OUT(("CPluggableConnection::OnPendingRead: Received %d bytes (required %d bytes) on socket (%d, %d).",
  986. cbRead, m_cbPendingRead, m_eType, m_nConnID));
  987. }
  988. m_cbPendingRead = cbRead; // in case cbRead is smaller
  989. m_fPendingReadDone = TRUE;
  990. fRet = TRUE; // turn off event
  991. }
  992. else
  993. {
  994. DWORD dwErr = ::GetLastError();
  995. if (ERROR_IO_INCOMPLETE == dwErr)
  996. {
  997. ASSERT(! cbRead);
  998. }
  999. else
  1000. {
  1001. TRACE_OUT(("CPluggableConnection::OnPendingRead: read failed %d", dwErr));
  1002. fRet = TRUE; // turn off event
  1003. // disconnect at next tick
  1004. NotifyReadFailure();
  1005. }
  1006. }
  1007. }
  1008. else
  1009. {
  1010. ERROR_OUT(("CPluggableConnection::OnPendingRead: no pending read event handle."));
  1011. fRet = TRUE; // turn off event
  1012. }
  1013. ::LeaveCriticalSection(&g_csTransport);
  1014. return fRet;
  1015. }
  1016. void CPluggableConnection::NotifyHighLevelRead(void)
  1017. {
  1018. WPARAM wParam = MAKE_PLUGXPRT_WPARAM(m_nConnID, m_eType);
  1019. LPARAM lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_HIGH_LEVEL_READ, PLUGXPRT_RESULT_SUCCESSFUL);
  1020. BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam);
  1021. ASSERT(fRet);
  1022. }
  1023. void CPluggableConnection::NotifyReadFailure(void)
  1024. {
  1025. WPARAM wParam = MAKE_PLUGXPRT_WPARAM(m_nConnID, m_eType);
  1026. LPARAM lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_READ, PLUGXPRT_RESULT_READ_FAILED);
  1027. BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam);
  1028. ASSERT(fRet);
  1029. }
  1030. void CPluggableConnection::NotifyWriteEvent(void)
  1031. {
  1032. WPARAM wParam = MAKE_PLUGXPRT_WPARAM(m_nConnID, m_eType);
  1033. LPARAM lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_WRITE, PLUGXPRT_RESULT_SUCCESSFUL);
  1034. BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam);
  1035. ASSERT(fRet);
  1036. }
  1037. void CPluggableConnection::NotifyHighLevelWrite(void)
  1038. {
  1039. WPARAM wParam = MAKE_PLUGXPRT_WPARAM(m_nConnID, m_eType);
  1040. LPARAM lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_HIGH_LEVEL_WRITE, PLUGXPRT_RESULT_SUCCESSFUL);
  1041. BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam);
  1042. ASSERT(fRet);
  1043. }
  1044. void CPluggableConnection::NotifyWriteFailure(void)
  1045. {
  1046. WPARAM wParam = MAKE_PLUGXPRT_WPARAM(m_nConnID, m_eType);
  1047. LPARAM lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_WRITE, PLUGXPRT_RESULT_WRITE_FAILED);
  1048. BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam);
  1049. ASSERT(fRet);
  1050. }
  1051. LPBYTE DuplicateBuffer(LPBYTE buffer, UINT length)
  1052. {
  1053. // DBG_SAVE_FILE_LINE
  1054. LPBYTE new_buffer = new BYTE[length];
  1055. if (NULL != new_buffer)
  1056. {
  1057. ::CopyMemory(new_buffer, buffer, length);
  1058. }
  1059. return new_buffer;
  1060. }
  1061. int SubmitPluggableWrite(PSocket pSocket, LPBYTE buffer, int length, PLUGXPRT_RESULT *plug_rc)
  1062. {
  1063. TRACE_OUT(("SubmitPluggableWrite"));
  1064. int nRet = SOCKET_ERROR;
  1065. *plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
  1066. CPluggableConnection *p = ::GetPluggableConnection(pSocket);
  1067. if (NULL != p)
  1068. {
  1069. nRet = p->Write(buffer, length, plug_rc);
  1070. }
  1071. else
  1072. {
  1073. WARNING_OUT(("SubmitPluggableWrite: no such conn ID=%d", pSocket->XprtConn.nLogicalHandle));
  1074. }
  1075. return nRet;
  1076. }
  1077. int CPluggableConnection::Write(LPBYTE buffer, int length, PLUGXPRT_RESULT *plug_rc)
  1078. {
  1079. TRACE_OUT(("CPluggableConnection::Write"));
  1080. int cbSent = SOCKET_ERROR;
  1081. *plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
  1082. ::EnterCriticalSection(&g_csTransport);
  1083. if (m_OutBufQueue2.GetCount() < MAX_PLUGGABLE_OUT_BUF_SIZE) // x4K
  1084. {
  1085. DBG_SAVE_FILE_LINE
  1086. buffer = ::DuplicateBuffer(buffer, length);
  1087. if (NULL != buffer)
  1088. {
  1089. cbSent = length;
  1090. m_OutBufQueue2.Append(length, buffer);
  1091. if (1 == m_OutBufQueue2.GetCount())
  1092. {
  1093. TRACE_OUT(("CPluggableConnection::Write: the only item in the queue"));
  1094. WriteTheFirst();
  1095. #if 0 // avoid another tick
  1096. // start next low-level write
  1097. WPARAM wParam = MAKE_PLUGXPRT_WPARAM(m_nConnID, m_eType);
  1098. LPARAM lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_WRITE, PLUGXPRT_RESULT_SUCCESSFUL);
  1099. BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam);
  1100. ASSERT(fRet);
  1101. #endif
  1102. }
  1103. else
  1104. {
  1105. TRACE_OUT(("CPluggableConnection::Write: more items in the queue"));
  1106. }
  1107. }
  1108. else
  1109. {
  1110. ERROR_OUT(("CPluggableConnection::Write: failed to allocate memory (%d)", length));
  1111. // out of memory, try later
  1112. // do nothing, treat it as WSAEWOULDBLOCK
  1113. }
  1114. }
  1115. ::LeaveCriticalSection(&g_csTransport);
  1116. return cbSent;
  1117. }
  1118. void CPluggableConnection::WriteTheFirst(void)
  1119. {
  1120. int length;
  1121. LPBYTE buffer;
  1122. TRACE_OUT(("CPluggableConnection::WriteTheFirst"));
  1123. ::EnterCriticalSection(&g_csTransport);
  1124. if (NULL == m_OverlappedWrite.hEvent)
  1125. {
  1126. length = 0;
  1127. buffer = m_OutBufQueue2.PeekHead(&length);
  1128. if (NULL != buffer)
  1129. {
  1130. ::ZeroMemory(&m_OverlappedWrite, sizeof(m_OverlappedWrite));
  1131. m_OverlappedWrite.hEvent = m_hevtPendingWrite;
  1132. m_pbPendingWrite = buffer;
  1133. m_cbPendingWrite = length;
  1134. TRACE_OUT(("CPluggableConnection::WriteTheFirst: WriteFile(%d)", length));
  1135. DWORD cbWritten = 0;
  1136. if (! ::WriteFile(m_hCommLink, buffer, length, &cbWritten, &m_OverlappedWrite))
  1137. {
  1138. DWORD dwErr = ::GetLastError();
  1139. if (ERROR_IO_PENDING != dwErr)
  1140. {
  1141. ERROR_OUT(("CPluggableConnection::WriteTheFirst: WriteFile failed, err=%d", dwErr));
  1142. CleanupWriteState();
  1143. m_OutBufQueue2.Get(); // dequeue the buffer which cannot be sent
  1144. NotifyWriteFailure();
  1145. }
  1146. else
  1147. {
  1148. // we are still in pending
  1149. // repeat the write event
  1150. NotifyWriteEvent();
  1151. }
  1152. }
  1153. }
  1154. else
  1155. {
  1156. TRACE_OUT(("CPluggableConnection::WriteTheFirst: queue is empty"));
  1157. // no more low-level write
  1158. m_pbPendingWrite = NULL;
  1159. CleanupWriteState();
  1160. // start next high-level write
  1161. NotifyHighLevelWrite();
  1162. }
  1163. }
  1164. else
  1165. {
  1166. TRACE_OUT(("CPluggableConnection::WriteTheFirst: still pending"));
  1167. // we are still in write pending, wake up the pending write
  1168. OnPendingWrite(); // check for pending write result
  1169. NotifyWriteEvent();
  1170. }
  1171. ::LeaveCriticalSection(&g_csTransport);
  1172. }
  1173. void PluggableWriteTheFirst(TransportConnection XprtConn)
  1174. {
  1175. if (IS_PLUGGABLE(XprtConn))
  1176. {
  1177. CPluggableConnection *p = ::GetPluggableConnection(XprtConn.nLogicalHandle);
  1178. if (NULL != p)
  1179. {
  1180. p->WriteTheFirst();
  1181. }
  1182. else
  1183. {
  1184. ERROR_OUT(("PluggableWriteTheFirst: no such conn ID=%d", XprtConn.nLogicalHandle));
  1185. }
  1186. }
  1187. else
  1188. {
  1189. ERROR_OUT(("PluggableWriteTheFirst: not plugable connection"));
  1190. }
  1191. }
  1192. void PluggableShutdown(TransportConnection XprtConn)
  1193. {
  1194. if (IS_PLUGGABLE(XprtConn))
  1195. {
  1196. CPluggableConnection *p = ::GetPluggableConnection(XprtConn.nLogicalHandle);
  1197. if (NULL != p)
  1198. {
  1199. p->Shutdown();
  1200. }
  1201. else
  1202. {
  1203. ERROR_OUT(("PluggableShutdown: no such conn ID=%d", XprtConn.nLogicalHandle));
  1204. }
  1205. }
  1206. else
  1207. {
  1208. ERROR_OUT(("PluggableShutdown: not plugable connection"));
  1209. }
  1210. }
  1211. BOOL CPluggableConnection::OnPendingWrite(void)
  1212. {
  1213. TRACE_OUT(("CPluggableConnection::OnPendingWrite"));
  1214. BOOL fRet = FALSE;
  1215. BOOL fStartNextWrite = FALSE;
  1216. ::EnterCriticalSection(&g_csTransport);
  1217. if (NULL != m_OverlappedWrite.hEvent)
  1218. {
  1219. DWORD cbWritten = 0;
  1220. if (::GetOverlappedResult(m_hCommLink, &m_OverlappedWrite, &cbWritten, FALSE))
  1221. {
  1222. TRACE_OUT(("CPluggableConnection::OnPendingWrite: Sent %d bytes (required %d bytes) on socket (%d, %d).",
  1223. cbWritten, m_cbPendingWrite, m_eType, m_nConnID));
  1224. if (cbWritten >= (DWORD) m_cbPendingWrite)
  1225. {
  1226. ASSERT(cbWritten == (DWORD) m_cbPendingWrite);
  1227. // remove the item from the queue
  1228. int length = 0;
  1229. LPBYTE buffer = m_OutBufQueue2.Get(&length);
  1230. ASSERT(length == m_cbPendingWrite);
  1231. ASSERT(buffer == m_pbPendingWrite);
  1232. CleanupWriteState();
  1233. fRet = TRUE; // turn off event
  1234. }
  1235. else
  1236. {
  1237. ERROR_OUT(("CPluggableConnection::OnPendingWrite: unexpected error, less data written %d (required %d)",
  1238. cbWritten, m_cbPendingWrite));
  1239. NotifyWriteFailure();
  1240. fRet = TRUE; // turn off event
  1241. }
  1242. }
  1243. else
  1244. {
  1245. DWORD dwErr = ::GetLastError();
  1246. if (ERROR_IO_INCOMPLETE == dwErr)
  1247. {
  1248. ASSERT(! cbWritten);
  1249. }
  1250. else
  1251. {
  1252. ERROR_OUT(("CPluggableConnection::OnPendingWrite: failed to write, err=%d", dwErr));
  1253. NotifyWriteFailure();
  1254. fRet = TRUE; // turn off event
  1255. }
  1256. }
  1257. }
  1258. else
  1259. {
  1260. // it is very possible that we hit this many times
  1261. fRet = TRUE;
  1262. }
  1263. ::LeaveCriticalSection(&g_csTransport);
  1264. return fRet;
  1265. }
  1266. BOOL CPluggableConnection::SetupReadState(int length)
  1267. {
  1268. DBG_SAVE_FILE_LINE
  1269. LPBYTE buffer = new BYTE[length];
  1270. if (NULL != buffer)
  1271. {
  1272. m_pbPendingRead = buffer;
  1273. m_cbPendingRead = length;
  1274. m_fPendingReadDone = FALSE;
  1275. ::ZeroMemory(&m_OverlappedRead, sizeof(m_OverlappedRead));
  1276. m_OverlappedRead.hEvent = m_hevtPendingRead;
  1277. }
  1278. else
  1279. {
  1280. CleanupReadState();
  1281. }
  1282. return (NULL != buffer);
  1283. }
  1284. void CPluggableConnection::CleanupReadState(void)
  1285. {
  1286. delete [] m_pbPendingRead;
  1287. m_pbPendingRead = NULL;
  1288. m_cbPendingRead = 0;
  1289. m_fPendingReadDone = FALSE;
  1290. ::ZeroMemory(&m_OverlappedRead, sizeof(m_OverlappedRead));
  1291. }
  1292. void CPluggableConnection::CleanupWriteState(void)
  1293. {
  1294. delete [] m_pbPendingWrite;
  1295. m_pbPendingWrite = NULL;
  1296. m_cbPendingWrite = 0;
  1297. ::ZeroMemory(&m_OverlappedWrite, sizeof(m_OverlappedWrite));
  1298. }
  1299. TransportError CALLBACK LegacyTransportCallback(ULONG nMsg, void *Param1, void *Param2)
  1300. {
  1301. if (Param2 == g_pPluggableTransport)
  1302. {
  1303. BOOL fPostMsg = FALSE;
  1304. WPARAM wParam = 0;
  1305. CPluggableConnection *p;
  1306. switch (nMsg)
  1307. {
  1308. case TRANSPORT_CONNECT_INDICATION:
  1309. TRACE_OUT(("LegacyTransportCallback::TRANSPORT_CONNECT_INDICATION"));
  1310. {
  1311. LegacyTransportID *pID = (LegacyTransportID *) Param1;
  1312. p = ::GetPluggableConnection(pID->hCommLink);
  1313. if (NULL != p)
  1314. {
  1315. p->SetLegacyHandle(pID->logical_handle);
  1316. {
  1317. PSocket pSocket = p->GetSocket();
  1318. ASSERT(NULL != pSocket);
  1319. if (NULL != pSocket)
  1320. {
  1321. pSocket->State = SOCKET_CONNECTED;
  1322. wParam = MAKE_PLUGXPRT_WPARAM(p->GetConnID(), TRANSPORT_TYPE_PLUGGABLE_PSTN);
  1323. fPostMsg = TRUE;
  1324. }
  1325. }
  1326. }
  1327. }
  1328. break;
  1329. case TRANSPORT_CONNECT_CONFIRM:
  1330. TRACE_OUT(("LegacyTransportCallback::TRANSPORT_CONNECT_CONFIRM"));
  1331. {
  1332. LegacyTransportID *pID = (LegacyTransportID *) Param1;
  1333. p = ::GetPluggableConnection(pID->hCommLink);
  1334. if (NULL != p)
  1335. {
  1336. ASSERT(p->GetLegacyHandle() == pID->logical_handle);
  1337. {
  1338. PSocket pSocket = p->GetSocket();
  1339. ASSERT(NULL != pSocket);
  1340. if (NULL != pSocket)
  1341. {
  1342. pSocket->State = X224_CONNECTED;
  1343. wParam = MAKE_PLUGXPRT_WPARAM(p->GetConnID(), TRANSPORT_TYPE_PLUGGABLE_PSTN);
  1344. fPostMsg = TRUE;
  1345. }
  1346. }
  1347. }
  1348. }
  1349. break;
  1350. case TRANSPORT_DISCONNECT_INDICATION:
  1351. TRACE_OUT(("LegacyTransportCallback::TRANSPORT_DISCONNECT_INDICATION"));
  1352. {
  1353. LegacyTransportID *pID = (LegacyTransportID *) Param1;
  1354. TransportConnection XprtConn;
  1355. XprtConn.eType = TRANSPORT_TYPE_PLUGGABLE_PSTN;
  1356. p = ::GetPluggableConnectionByLegacyHandle(pID->logical_handle);
  1357. if (NULL != p)
  1358. {
  1359. XprtConn.nLogicalHandle = p->GetConnID();
  1360. }
  1361. ::OnProtocolControl(XprtConn, PLUGXPRT_DISCONNECTED);
  1362. fPostMsg = FALSE;
  1363. }
  1364. break;
  1365. case TRANSPORT_DATA_INDICATION:
  1366. TRACE_OUT(("LegacyTransportCallback::TRANSPORT_DATA_INDICATION"));
  1367. {
  1368. //
  1369. // This piece of data does not have X.224 framing
  1370. //
  1371. LegacyTransportData *pData = (LegacyTransportData *) Param1;
  1372. TRACE_OUT(("LegacyTransportCallback::pbData=0x%x, cbDataSize=%d", pData->pbData, pData->cbDataSize));
  1373. if (NULL != g_Transport)
  1374. {
  1375. DBG_SAVE_FILE_LINE
  1376. TransportData *td = new TransportData;
  1377. if (NULL != td)
  1378. {
  1379. td->transport_connection.eType = TRANSPORT_TYPE_PLUGGABLE_PSTN;
  1380. p = ::GetPluggableConnectionByLegacyHandle(pData->logical_handle);
  1381. if (NULL != p)
  1382. {
  1383. ULONG cbTotalSize = PROTOCOL_OVERHEAD_X224 + pData->cbDataSize;
  1384. td->transport_connection.nLogicalHandle = p->GetConnID();
  1385. DBG_SAVE_FILE_LINE
  1386. td->memory = ::AllocateMemory(NULL, cbTotalSize, RECV_PRIORITY);
  1387. if (NULL != td->memory)
  1388. {
  1389. td->user_data = td->memory->GetPointer();
  1390. td->user_data_length = cbTotalSize;
  1391. // take care of the X.224 header
  1392. ::CopyMemory(td->user_data, g_X224Header, PROTOCOL_OVERHEAD_X224);
  1393. AddRFCSize(td->user_data, cbTotalSize);
  1394. // take care of the data
  1395. ::CopyMemory(td->user_data + PROTOCOL_OVERHEAD_X224, pData->pbData, pData->cbDataSize);
  1396. wParam = (WPARAM) td;
  1397. fPostMsg = TRUE;
  1398. }
  1399. else
  1400. {
  1401. ERROR_OUT(("LegacyTransportCallback: failed to allocate memory, size=%d", cbTotalSize));
  1402. }
  1403. }
  1404. }
  1405. else
  1406. {
  1407. ERROR_OUT(("LegacyTransportCallback: failed to allocate TransportData"));
  1408. }
  1409. }
  1410. }
  1411. break;
  1412. default:
  1413. wParam = (WPARAM) Param1;
  1414. fPostMsg = TRUE;
  1415. break;
  1416. }
  1417. if (fPostMsg)
  1418. {
  1419. BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_PSTN, wParam, nMsg);
  1420. ASSERT(fRet);
  1421. }
  1422. }
  1423. return TRANSPORT_NO_ERROR;
  1424. }
  1425. void HandlePSTNCallback(WPARAM wParam, LPARAM lParam)
  1426. {
  1427. if (NULL != g_pPluggableTransport)
  1428. {
  1429. CPluggableConnection *p;
  1430. switch (lParam)
  1431. {
  1432. case TRANSPORT_CONNECT_INDICATION:
  1433. TRACE_OUT(("HandlePSTNCallback::TRANSPORT_CONNECT_INDICATION"));
  1434. if (NULL != g_Transport)
  1435. {
  1436. TransportConnection XprtConn;
  1437. XprtConn.nLogicalHandle = PLUGXPRT_WPARAM_TO_ID(wParam);
  1438. XprtConn.eType = (TransportType) PLUGXPRT_WPARAM_TO_TYPE(wParam);
  1439. ::OnProtocolControl(XprtConn, PLUGXPRT_CONNECTED);
  1440. g_Transport->ConnectIndication(XprtConn);
  1441. }
  1442. break;
  1443. case TRANSPORT_CONNECT_CONFIRM:
  1444. TRACE_OUT(("HandlePSTNCallback::TRANSPORT_CONNECT_CONFIRM"));
  1445. if (NULL != g_Transport)
  1446. {
  1447. TransportConnection XprtConn;
  1448. XprtConn.nLogicalHandle = PLUGXPRT_WPARAM_TO_ID(wParam);
  1449. XprtConn.eType = (TransportType) PLUGXPRT_WPARAM_TO_TYPE(wParam);
  1450. ::OnProtocolControl(XprtConn, PLUGXPRT_CONNECTED);
  1451. g_Transport->ConnectConfirm(XprtConn);
  1452. }
  1453. break;
  1454. case TRANSPORT_DATA_INDICATION:
  1455. TRACE_OUT(("HandlePSTNCallback::TRANSPORT_DATA_INDICATION"));
  1456. {
  1457. TransportData *td = (TransportData *) wParam;
  1458. if (NULL != g_Transport)
  1459. {
  1460. g_Transport->DataIndication(td);
  1461. }
  1462. delete td;
  1463. }
  1464. break;
  1465. case TRANSPORT_BUFFER_EMPTY_INDICATION:
  1466. TRACE_OUT(("HandlePSTNCallback::TRANSPORT_BUFFER_EMPTY_INDICATION"));
  1467. {
  1468. LEGACY_HANDLE logical_handle = (LEGACY_HANDLE) wParam;
  1469. TransportConnection XprtConn;
  1470. XprtConn.eType = TRANSPORT_TYPE_PLUGGABLE_PSTN;
  1471. p = ::GetPluggableConnectionByLegacyHandle(logical_handle);
  1472. if (NULL != p)
  1473. {
  1474. XprtConn.nLogicalHandle = p->GetConnID();
  1475. g_Transport->BufferEmptyIndication(XprtConn);
  1476. }
  1477. }
  1478. break;
  1479. default:
  1480. ERROR_OUT(("HandlePSTNCallback: unknown message=%d", lParam));
  1481. break;
  1482. }
  1483. }
  1484. }
  1485. BOOL CPluggableTransport::EnsureLegacyTransportLoaded(void)
  1486. {
  1487. if (NULL == g_pLegacyTransport)
  1488. {
  1489. g_hlibMST123 = ::LoadLibrary("MST123.DLL");
  1490. if (NULL != g_hlibMST123)
  1491. {
  1492. LPFN_T123_CreateTransportInterface pfn = (LPFN_T123_CreateTransportInterface)
  1493. ::GetProcAddress(g_hlibMST123, LPSTR_T123_CreateTransportInterface);
  1494. if (NULL != pfn)
  1495. {
  1496. TransportError rc = (*pfn)(&g_pLegacyTransport);
  1497. if (TRANSPORT_NO_ERROR == rc)
  1498. {
  1499. ASSERT(NULL != g_pLegacyTransport);
  1500. // start to call initialize
  1501. rc = g_pLegacyTransport->TInitialize(LegacyTransportCallback, this);
  1502. ASSERT(TRANSPORT_NO_ERROR == rc);
  1503. if (TRANSPORT_NO_ERROR == rc)
  1504. {
  1505. return TRUE;
  1506. }
  1507. g_pLegacyTransport->TCleanup();
  1508. g_pLegacyTransport->ReleaseInterface();
  1509. g_pLegacyTransport = NULL;
  1510. }
  1511. }
  1512. ::FreeLibrary(g_hlibMST123);
  1513. g_hlibMST123 = NULL;
  1514. }
  1515. return FALSE;
  1516. }
  1517. return TRUE;
  1518. }
  1519. TransportError CPluggableConnection::TConnectRequest(void)
  1520. {
  1521. TRACE_OUT(("CPluggableConnection::TConnectRequest"));
  1522. TransportError rc = TRANSPORT_NO_PLUGGABLE_CONNECTION;
  1523. if (NULL != g_pLegacyTransport)
  1524. {
  1525. TransportConnection XprtConn;
  1526. XprtConn.eType = m_eType;
  1527. XprtConn.nLogicalHandle = m_nConnID;
  1528. ::OnProtocolControl(XprtConn, PLUGXPRT_CONNECTING);
  1529. rc = g_pLegacyTransport->TConnectRequest(&m_nLegacyLogicalHandle, m_hCommLink);
  1530. }
  1531. return rc;
  1532. }
  1533. TransportError CPluggableConnection::TDisconnectRequest(void)
  1534. {
  1535. TRACE_OUT(("CPluggableConnection::TDisconnectRequest"));
  1536. TransportError rc = TRANSPORT_NO_PLUGGABLE_CONNECTION;
  1537. if (NULL != g_pLegacyTransport)
  1538. {
  1539. TransportConnection XprtConn;
  1540. XprtConn.eType = m_eType;
  1541. XprtConn.nLogicalHandle = m_nConnID;
  1542. ::OnProtocolControl(XprtConn, PLUGXPRT_DISCONNECTING);
  1543. ::Sleep(600);
  1544. rc = g_pLegacyTransport->TDisconnectRequest(m_nLegacyLogicalHandle, TRUE);
  1545. }
  1546. return rc;
  1547. }
  1548. int CPluggableConnection::TDataRequest(LPBYTE pbData, ULONG cbDataSize, PLUGXPRT_RESULT *plug_rc)
  1549. {
  1550. TRACE_OUT(("CPluggableConnection::TDataRequest, pbData=0x%x, cbDataSize=%d", pbData, cbDataSize));
  1551. if (NULL != g_pLegacyTransport)
  1552. {
  1553. *plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
  1554. // skip X.224 framing
  1555. ASSERT(cbDataSize > PROTOCOL_OVERHEAD_X224);
  1556. TransportError rc;
  1557. rc = g_pLegacyTransport->TDataRequest(m_nLegacyLogicalHandle,
  1558. pbData + PROTOCOL_OVERHEAD_X224,
  1559. cbDataSize - PROTOCOL_OVERHEAD_X224);
  1560. if (TRANSPORT_NO_ERROR == rc)
  1561. {
  1562. TRACE_OUT(("CPluggableConnection::TDataRequest: sent data size=%d", cbDataSize));
  1563. return cbDataSize;
  1564. }
  1565. }
  1566. else
  1567. {
  1568. *plug_rc = PLUGXPRT_RESULT_WRITE_FAILED;
  1569. }
  1570. return SOCKET_ERROR;
  1571. }
  1572. TransportError TReceiveBufferAvailable(void)
  1573. {
  1574. TRACE_OUT(("CPluggableConnection::TReceiveBufferAvailable"));
  1575. TransportError rc = TRANSPORT_NO_PLUGGABLE_CONNECTION;
  1576. if (NULL != g_pLegacyTransport)
  1577. {
  1578. rc = g_pLegacyTransport->TReceiveBufferAvailable();
  1579. }
  1580. return rc;
  1581. }
  1582. TransportError CPluggableConnection::TPurgeRequest(void)
  1583. {
  1584. TRACE_OUT(("CPluggableConnection::TPurgeRequest"));
  1585. TransportError rc = TRANSPORT_NO_PLUGGABLE_CONNECTION;
  1586. if (NULL != g_pLegacyTransport)
  1587. {
  1588. rc = g_pLegacyTransport->TPurgeRequest(m_nLegacyLogicalHandle);
  1589. }
  1590. return rc;
  1591. }
  1592.