|
|
#include "precomp.h"
#include "plgxprt.h"
// #undef TRACE_OUT
// #define TRACE_OUT WARNING_OUT
#define XPRT_CONN_ID_PREFIX "XPRT"
#define XPRT_CONN_ID_PREFIX_LEN 4
static UINT s_nConnID = 0;
CPluggableTransport *g_pPluggableTransport = NULL; BOOL g_fWinsockDisabled = FALSE; BOOL g_fPluggableTransportInitialized = FALSE; DWORD g_dwPluggableTransportThreadID = 0; HANDLE g_hevtUpdatePluggableTransport = FALSE; CRITICAL_SECTION g_csTransport; ILegacyTransport *g_pLegacyTransport = NULL; HINSTANCE g_hlibMST123 = NULL;
BOOL EnsurePluggableTransportThread(void);
extern HWND TCP_Window_Handle; extern SOCKET Listen_Socket; extern SOCKET Listen_Socket_Secure; extern PTransportInterface g_Transport; extern UChar g_X224Header[];
extern void CloseListenSocket(void);
T120Error WINAPI T120_CreatePluggableTransport(IT120PluggableTransport **ppTransport) { if (NULL != ppTransport) { *ppTransport = NULL; if (NULL == g_pPluggableTransport) { if (g_fPluggableTransportInitialized) { DBG_SAVE_FILE_LINE *ppTransport = (CPluggableTransport *) new CPluggableTransport; if (NULL != *ppTransport) { if (EnsurePluggableTransportThread()) { return T120_NO_ERROR; } else { (*ppTransport)->ReleaseInterface(); *ppTransport = NULL; } }
return T120_ALLOCATION_FAILURE; }
return T120_NOT_INITIALIZED; }
return T120_ALREADY_INITIALIZED; }
return T120_INVALID_PARAMETER; }
CPluggableConnection::CPluggableConnection ( PLUGXPRT_CALL_TYPE eCaller, HANDLE hCommLink, HANDLE hevtRead, HANDLE hevtWrite, HANDLE hevtClose, PLUGXPRT_FRAMING eFraming, PLUGXPRT_PARAMETERS *pParams, T120Error *pRC ) : CRefCount(MAKE_STAMP_ID('P','X','P','C')), m_eState(PLUGXPRT_UNKNOWN_STATE), m_eCaller(eCaller), m_hCommLink(hCommLink), m_hevtRead(hevtRead), m_hevtWrite(hevtWrite), m_hevtClose(hevtClose), m_eType(TRANSPORT_TYPE_PLUGGABLE_X224), m_pSocket(NULL), // Legacy tranport
m_nLegacyLogicalHandle(0), // IO queue management for X.224 framing
m_hevtPendingRead(NULL), m_hevtPendingWrite(NULL), m_fPendingReadDone(FALSE), m_cbPendingRead(0), m_pbPendingRead(NULL), m_cbPendingWrite(0), m_pbPendingWrite(NULL), m_OutBufQueue2(MAX_PLUGGABLE_OUT_BUF_SIZE) { TransportError err; BOOL fCaller = (PLUGXPRT_CALLER == eCaller);
// X.224 only
::ZeroMemory(&m_OverlappedRead, sizeof(m_OverlappedRead)); ::ZeroMemory(&m_OverlappedWrite, sizeof(m_OverlappedWrite));
// assign connection ID
::EnterCriticalSection(&g_csTransport); if (s_nConnID > 0x7FFF) { s_nConnID = 0; } m_nConnID = ++s_nConnID; ::LeaveCriticalSection(&g_csTransport);
// create connection ID string
::CreateConnString(GetConnID(), m_szConnID);
// do framing specific initialization
switch (eFraming) { case FRAMING_X224: m_eType = TRANSPORT_TYPE_PLUGGABLE_X224;
m_hevtPendingRead = ::CreateEvent(NULL, TRUE, FALSE, NULL); /* manual reset */ m_hevtPendingWrite = ::CreateEvent(NULL, TRUE, FALSE, NULL); /* manual reset */ ASSERT(NULL != m_hevtPendingRead && NULL != m_hevtPendingWrite); *pRC = (NULL != m_hevtPendingRead && NULL != m_hevtPendingWrite) ? T120_NO_ERROR : T120_ALLOCATION_FAILURE; break;
case FRAMING_LEGACY_PSTN: m_eType = TRANSPORT_TYPE_PLUGGABLE_PSTN; ASSERT(NULL != g_pLegacyTransport);
err = g_pLegacyTransport->TCreateTransportStack(fCaller, m_hCommLink, m_hevtClose, pParams); ASSERT(TRANSPORT_NO_ERROR == err);
*pRC = (TRANSPORT_NO_ERROR == err) ? T120_NO_ERROR : T120_NO_TRANSPORT_STACKS; break;
default: ERROR_OUT(("CPluggableConnection: unknown framing %d", eFraming)); *pRC = T120_INVALID_PARAMETER; break; } }
CPluggableConnection::~CPluggableConnection(void) { if (NULL != m_pSocket) { ::freePluggableSocket(m_pSocket); m_pSocket = NULL; }
Shutdown();
if (TRANSPORT_TYPE_PLUGGABLE_PSTN == m_eType) { if (NULL != g_pLegacyTransport && NULL != m_hCommLink) { g_pLegacyTransport->TCloseTransportStack(m_hCommLink); } }
if (NULL != m_hCommLink) { ::CloseHandle(m_hCommLink); }
if (NULL != m_hevtRead) { ::CloseHandle(m_hevtRead); }
if (NULL != m_hevtWrite) { ::CloseHandle(m_hevtWrite); }
if (NULL != m_hevtClose) { ::CloseHandle(m_hevtClose); }
if (NULL != m_hevtPendingRead) { ::CloseHandle(m_hevtPendingRead); }
if (NULL != m_hevtPendingWrite) { ::CloseHandle(m_hevtPendingWrite); } }
ULONG CreateConnString(int nConnID, char szConnID[]) { return ::wsprintfA(szConnID, "%s: %u", XPRT_CONN_ID_PREFIX, nConnID); }
UINT GetPluggableTransportConnID(LPCSTR pcszNodeAddress) { UINT nConnID = 0; char szName[T120_CONNECTION_ID_LENGTH];
// make sure we have a clean buffer to start with
::ZeroMemory(szName, sizeof(szName));
// copy the address string
::lstrcpynA(szName, pcszNodeAddress, T120_CONNECTION_ID_LENGTH);
// make sure we have the semi-colon in place
if (':' == szName[XPRT_CONN_ID_PREFIX_LEN]) { // compare the prefix string
szName[XPRT_CONN_ID_PREFIX_LEN] = '\0'; if (! lstrcmpA(szName, XPRT_CONN_ID_PREFIX)) { LPSTR psz = &szName[XPRT_CONN_ID_PREFIX_LEN+1];
// get a space?
if (' ' == *psz++) { // now, have a number
if ('0' <= *psz && *psz <= '9') { while ('0' <= *psz && *psz <= '9') { nConnID = nConnID * 10 + (*psz++ - '0'); } } } } }
return nConnID; }
BOOL IsValidPluggableTransportName(LPCSTR pcszNodeAddress) { return GetPluggableTransportConnID(pcszNodeAddress); }
typedef BOOL (WINAPI *LPFN_CANCEL_IO) (HANDLE); void CPluggableConnection::Shutdown(void) { TRACE_OUT(("CPluggableConnection::Shutdown"));
if (NULL != m_OverlappedRead.hEvent || NULL != m_OverlappedWrite.hEvent) { HINSTANCE hLib = ::LoadLibrary("kernel32.dll"); if (NULL != hLib) { LPFN_CANCEL_IO pfnCancelIo = (LPFN_CANCEL_IO) ::GetProcAddress(hLib, "CancelIo"); if (NULL != pfnCancelIo) { (*pfnCancelIo)(m_hCommLink); } ::FreeLibrary(hLib); }
m_OverlappedRead.hEvent = NULL; m_OverlappedWrite.hEvent = NULL; }
delete [] m_pbPendingRead; m_pbPendingRead = NULL;
LPBYTE buffer; while (NULL != (buffer = m_OutBufQueue2.Get())) { delete [] buffer; } }
T120Error CPluggableConnection::UpdateCommLink(HANDLE hCommLink) { T120Error rc;
::EnterCriticalSection(&g_csTransport);
switch (m_eState) { case PLUGXPRT_UNKNOWN_STATE: case PLUGXPRT_DISCONNECTED: Shutdown(); m_hCommLink = hCommLink; rc = T120_NO_ERROR; break;
default: rc = T120_TRANSPORT_NOT_READY; break; }
::LeaveCriticalSection(&g_csTransport);
return rc; }
CPluggableTransport::CPluggableTransport(void) : CRefCount(MAKE_STAMP_ID('X','P','R','T')), m_pfnNotify(NULL), m_pContext(NULL) { g_pPluggableTransport = this; g_pLegacyTransport = NULL; }
CPluggableTransport::~CPluggableTransport(void) { ::PostThreadMessage(g_dwPluggableTransportThreadID, WM_QUIT, 0, 0);
CPluggableConnection *p;
::EnterCriticalSection(&g_csTransport); while (NULL != (p = m_PluggableConnectionList.Get())) { p->Release(); } ::LeaveCriticalSection(&g_csTransport);
if (NULL != g_pLegacyTransport) { g_pLegacyTransport->TCleanup(); g_pLegacyTransport->ReleaseInterface(); g_pLegacyTransport = NULL; }
if (NULL != g_hlibMST123) { ::FreeLibrary(g_hlibMST123); g_hlibMST123 = NULL; }
g_pPluggableTransport = NULL; }
void CPluggableTransport::ReleaseInterface(void) { UnAdvise(); CRefCount::Release(); }
T120Error CPluggableTransport::CreateConnection ( char szConnID[], /* out */ PLUGXPRT_CALL_TYPE eCaller, HANDLE hCommLink, HANDLE hevtRead, HANDLE hevtWrite, HANDLE hevtClose, PLUGXPRT_FRAMING eFraming, PLUGXPRT_PARAMETERS *pParams ) { T120Error rc;
if (FRAMING_LEGACY_PSTN == eFraming) { if (! EnsureLegacyTransportLoaded()) { return T120_NO_TRANSPORT_STACKS; } }
if (NULL != pParams) { if (sizeof(PLUGXPRT_PARAMETERS) != pParams->cbStructSize) { return T120_INVALID_PARAMETER; } }
DBG_SAVE_FILE_LINE CPluggableConnection *p; p = new CPluggableConnection(eCaller, hCommLink, hevtRead, hevtWrite, hevtClose, eFraming, pParams, &rc); if (NULL != p && T120_NO_ERROR == rc) { ::lstrcpyA(szConnID, p->GetConnString());
::EnterCriticalSection(&g_csTransport); m_PluggableConnectionList.Append(p); ::LeaveCriticalSection(&g_csTransport);
TransportConnection XprtConn; XprtConn.eType = p->GetType(); XprtConn.nLogicalHandle = p->GetConnID(); PSocket pSocket = ::newPluggableSocket(XprtConn); p->SetSocket(pSocket); ASSERT(NULL != pSocket);
// update the events list to wait for in the plugable transport thread
::SetEvent(g_hevtUpdatePluggableTransport);
return T120_NO_ERROR; }
if (NULL != p) { p->Release(); } else { rc = T120_ALLOCATION_FAILURE; }
return rc; }
T120Error CPluggableTransport::UpdateConnection ( LPSTR pszConnID, HANDLE hCommLink ) { BOOL fFound = FALSE; CPluggableConnection *p; T120Error rc = GCC_INVALID_TRANSPORT;
::EnterCriticalSection(&g_csTransport); m_PluggableConnectionList.Reset(); while (NULL != (p = m_PluggableConnectionList.Iterate())) { if (! ::lstrcmpA(p->GetConnString(), pszConnID)) { rc = p->UpdateCommLink(hCommLink); break; } } ::LeaveCriticalSection(&g_csTransport);
// update the events list to wait for in the plugable transport thread
::SetEvent(g_hevtUpdatePluggableTransport);
return rc; }
T120Error CPluggableTransport::CloseConnection ( LPSTR pszConnID ) { CPluggableConnection *p;
::EnterCriticalSection(&g_csTransport); m_PluggableConnectionList.Reset(); while (NULL != (p = m_PluggableConnectionList.Iterate())) { if (! ::lstrcmpA(p->GetConnString(), pszConnID)) { m_PluggableConnectionList.Remove(p); break; } } ::LeaveCriticalSection(&g_csTransport);
// update the events list to wait for in the plugable transport thread
::SetEvent(g_hevtUpdatePluggableTransport);
if (NULL != p) { //
// do real work here
//
p->Release();
return T120_NO_ERROR; }
return GCC_INVALID_TRANSPORT; }
T120Error CPluggableTransport::EnableWinsock(void) { if (g_fWinsockDisabled) { g_fWinsockDisabled = FALSE;
//
// LONCHANC: create Listen_Socket if not done so...
//
if (INVALID_SOCKET == Listen_Socket) { Listen_Socket = ::CreateAndConfigureListenSocket(); } }
return T120_NO_ERROR; }
T120Error CPluggableTransport::DisableWinsock(void) { if (! g_fWinsockDisabled) { g_fWinsockDisabled = TRUE;
// close Listen_Socket...
::CloseListenSocket(); }
return T120_NO_ERROR; }
void CPluggableTransport::Advise(LPFN_PLUGXPRT_CB pNotify, LPVOID pContext) { m_pfnNotify = pNotify; m_pContext = pContext; }
void CPluggableTransport::UnAdvise(void) { m_pfnNotify = NULL; m_pContext = NULL; }
void CPluggableTransport::ResetConnCounter(void) { s_nConnID = 0; }
void CPluggableTransport::OnProtocolControl ( TransportConnection XprtConn, PLUGXPRT_STATE eState, PLUGXPRT_RESULT eResult ) { if (IS_PLUGGABLE(XprtConn)) { WARNING_OUT(("CPluggableTransport::OnProtocolControl: socket (%d, %d) is doing %d with result %d", XprtConn.eType, XprtConn.nLogicalHandle, eState, eResult));
if (NULL != m_pfnNotify) { CPluggableConnection *p = GetPluggableConnection(XprtConn.nLogicalHandle); if (NULL != p) { PLUGXPRT_MESSAGE Msg; Msg.eState = eState; Msg.pContext = m_pContext; Msg.pszConnID = p->GetConnString(); // we only support X.224 level notifications
Msg.eProtocol = PLUGXPRT_PROTOCOL_X224; Msg.eResult = eResult;
(*m_pfnNotify)(&Msg); } } } }
void OnProtocolControl ( TransportConnection XprtConn, PLUGXPRT_STATE eState, PLUGXPRT_RESULT eResult ) { if (NULL != g_pPluggableTransport) { g_pPluggableTransport->OnProtocolControl(XprtConn, eState, eResult); } }
// called only in the plugable transport thread
// already in the critical section
ULONG CPluggableTransport::UpdateEvents(HANDLE *aHandles) { ULONG cHandles = 0; CPluggableConnection *p;
::EnterCriticalSection(&g_csTransport); m_PluggableConnectionList.Reset(); while (NULL != (p = m_PluggableConnectionList.Iterate())) { if (TRANSPORT_TYPE_PLUGGABLE_X224 == p->GetType()) { aHandles[cHandles++] = p->GetReadEvent(); aHandles[cHandles++] = p->GetWriteEvent(); aHandles[cHandles++] = p->GetCloseEvent(); aHandles[cHandles++] = p->GetPendingReadEvent(); aHandles[cHandles++] = p->GetPendingWriteEvent(); } } ::LeaveCriticalSection(&g_csTransport);
return cHandles; }
// called only in the plugable transport thread
// already in the critical section
void CPluggableTransport::OnEventSignaled(HANDLE hevtSignaled) { CPluggableConnection *p; BOOL fPostMessage, fFound; WPARAM wParam; LPARAM lParam;
::EnterCriticalSection(&g_csTransport);
m_PluggableConnectionList.Reset(); while (NULL != (p = m_PluggableConnectionList.Iterate())) { fFound = TRUE; fPostMessage = FALSE; wParam = MAKE_PLUGXPRT_WPARAM(p->GetConnID(), p->GetType()); if (hevtSignaled == p->GetReadEvent()) { lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_READ, PLUGXPRT_RESULT_SUCCESSFUL); fPostMessage = TRUE; } else if (hevtSignaled == p->GetWriteEvent()) { lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_WRITE, PLUGXPRT_RESULT_SUCCESSFUL); fPostMessage = TRUE; } else if (hevtSignaled == p->GetCloseEvent()) { lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_CLOSE, PLUGXPRT_RESULT_SUCCESSFUL); fPostMessage = TRUE; } else { TransportConnection XprtConn; XprtConn.eType = p->GetType(); XprtConn.nLogicalHandle = p->GetConnID(); if (hevtSignaled == p->GetPendingReadEvent()) { TRACE_OUT(("OnEventSignaled: PendingREAD(%d, %d)", p->GetType(), p->GetConnID())); if (p->OnPendingRead()) { ::ResetEvent(hevtSignaled); // start next high-level read
p->NotifyHighLevelRead(); } } else if (hevtSignaled == p->GetPendingWriteEvent()) { TRACE_OUT(("OnEventSignaled: PendingWRITE(%d, %d)", p->GetType(), p->GetConnID())); if (p->OnPendingWrite()) { ::ResetEvent(hevtSignaled); // start next low-level write
p->NotifyWriteEvent(); } } else { fFound = FALSE; } }
if (fPostMessage) { BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam); ASSERT(fRet); }
if (fFound) { break; } } // while
::LeaveCriticalSection(&g_csTransport);
ASSERT(NULL != p); }
// called only in the plugable transport thread
// already in the critical section
void CPluggableTransport::OnEventAbandoned(HANDLE hevtSignaled) { CPluggableConnection *p; BOOL fFound; WPARAM wParam; LPARAM lParam;
::EnterCriticalSection(&g_csTransport); m_PluggableConnectionList.Reset(); while (NULL != (p = m_PluggableConnectionList.Iterate())) { fFound = TRUE; wParam = MAKE_PLUGXPRT_WPARAM(p->GetConnID(), p->GetType()); if (hevtSignaled == p->GetReadEvent()) { lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_READ, PLUGXPRT_RESULT_ABANDONED); } else if (hevtSignaled == p->GetWriteEvent()) { lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_WRITE, PLUGXPRT_RESULT_ABANDONED); } else if (hevtSignaled == p->GetCloseEvent()) { lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_CLOSE, PLUGXPRT_RESULT_ABANDONED); } else if (hevtSignaled == p->GetPendingReadEvent()) { lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_PENDING_EVENT, PLUGXPRT_RESULT_ABANDONED); } else if (hevtSignaled == p->GetPendingWriteEvent()) { lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_PENDING_EVENT, PLUGXPRT_RESULT_ABANDONED); } else { fFound = FALSE; }
if (fFound) { m_PluggableConnectionList.Remove(p);
// update the events list to wait for in the plugable transport thread
::SetEvent(g_hevtUpdatePluggableTransport);
BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam); ASSERT(fRet); break; } } // while
::LeaveCriticalSection(&g_csTransport);
ASSERT(NULL != p); }
CPluggableConnection * CPluggableTransport::GetPluggableConnection(PSocket pSocket) { CPluggableConnection *p;
::EnterCriticalSection(&g_csTransport); m_PluggableConnectionList.Reset(); while (NULL != (p = m_PluggableConnectionList.Iterate())) { if (p->GetType() == pSocket->XprtConn.eType && p->GetConnID() == pSocket->XprtConn.nLogicalHandle) { break; } } ::LeaveCriticalSection(&g_csTransport);
return p; }
CPluggableConnection * GetPluggableConnection(PSocket pSocket) { return (NULL != g_pPluggableTransport) ? g_pPluggableTransport->GetPluggableConnection(pSocket) : NULL; }
CPluggableConnection * CPluggableTransport::GetPluggableConnection(UINT_PTR nConnID) { CPluggableConnection *p;
::EnterCriticalSection(&g_csTransport); m_PluggableConnectionList.Reset(); while (NULL != (p = m_PluggableConnectionList.Iterate())) { if (p->GetConnID() == nConnID) { break; } } ::LeaveCriticalSection(&g_csTransport);
return p; }
CPluggableConnection * GetPluggableConnection(UINT_PTR nConnID) { return (NULL != g_pPluggableTransport) ? g_pPluggableTransport->GetPluggableConnection(nConnID) : NULL; }
CPluggableConnection * CPluggableTransport::GetPluggableConnection(HANDLE hCommLink) { CPluggableConnection *p;
::EnterCriticalSection(&g_csTransport); m_PluggableConnectionList.Reset(); while (NULL != (p = m_PluggableConnectionList.Iterate())) { if (p->GetCommLink() == hCommLink) { break; } } ::LeaveCriticalSection(&g_csTransport);
return p; }
CPluggableConnection * GetPluggableConnection(HANDLE hCommLink) { return (NULL != g_pPluggableTransport) ? g_pPluggableTransport->GetPluggableConnection(hCommLink) : NULL; }
CPluggableConnection * CPluggableTransport::GetPluggableConnectionByLegacyHandle(LEGACY_HANDLE logical_handle) { CPluggableConnection *p;
::EnterCriticalSection(&g_csTransport); m_PluggableConnectionList.Reset(); while (NULL != (p = m_PluggableConnectionList.Iterate())) { if (p->GetLegacyHandle() == logical_handle) { break; } } ::LeaveCriticalSection(&g_csTransport);
return p; }
CPluggableConnection * GetPluggableConnectionByLegacyHandle(LEGACY_HANDLE logical_handle) { return (NULL != g_pPluggableTransport) ? g_pPluggableTransport->GetPluggableConnectionByLegacyHandle(logical_handle) : NULL; }
// called in ERNC ConfMgr's constructor
BOOL InitializePluggableTransport(void) { if (! g_fPluggableTransportInitialized) { g_fWinsockDisabled = FALSE; g_hevtUpdatePluggableTransport = ::CreateEvent(NULL, FALSE, FALSE, NULL); if (NULL != g_hevtUpdatePluggableTransport) { g_fPluggableTransportInitialized = TRUE; } } return g_fPluggableTransportInitialized; }
// called in ERNC ConfMgr's destructor
void CleanupPluggableTransport(void) { if (g_fPluggableTransportInitialized) { g_fPluggableTransportInitialized = FALSE;
if (g_dwPluggableTransportThreadID) { ::PostThreadMessage(g_dwPluggableTransportThreadID, WM_QUIT, 0, 0); }
::EnterCriticalSection(&g_csTransport); if (NULL != g_hevtUpdatePluggableTransport) { ::CloseHandle(g_hevtUpdatePluggableTransport); } ::LeaveCriticalSection(&g_csTransport); } }
DWORD __stdcall PluggableTransportThreadProc(LPVOID lpv) { MSG msg; BOOL fContinueMainLoop = TRUE; DWORD nEventSignaled; ULONG cEvents; HANDLE aEvents[MAX_PLUGXPRT_CONNECTIONS * MAX_PLUGXPRT_EVENTS + 1];
// signaling that the work hread has been started.
::SetEvent((HANDLE) lpv);
// set up initial event list, the first entry always for update event
cEvents = 1; aEvents[0] = g_hevtUpdatePluggableTransport; ::SetEvent(g_hevtUpdatePluggableTransport);
// main loop
while (fContinueMainLoop) { // process any possible window and thread messages
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (WM_QUIT != msg.message) { ::DispatchMessage(&msg); } else { fContinueMainLoop = FALSE; break; } }
if (fContinueMainLoop) { nEventSignaled = ::MsgWaitForMultipleObjects(cEvents, aEvents, FALSE, INFINITE, QS_ALLINPUT); ::EnterCriticalSection(&g_csTransport); if (NULL != g_pPluggableTransport) { switch (nEventSignaled) { case WAIT_OBJECT_0: // update the event list
cEvents = 1 + g_pPluggableTransport->UpdateEvents(&aEvents[1]); break; case WAIT_TIMEOUT: // impossible, do nothing
break; default: if (WAIT_OBJECT_0 + 1 <= nEventSignaled && nEventSignaled < WAIT_OBJECT_0 + cEvents) { g_pPluggableTransport->OnEventSignaled(aEvents[nEventSignaled - WAIT_OBJECT_0]); } else if (WAIT_ABANDONED_0 + 1 <= nEventSignaled && nEventSignaled < WAIT_ABANDONED_0 + cEvents) { g_pPluggableTransport->OnEventAbandoned(aEvents[nEventSignaled - WAIT_OBJECT_0]); } break; } } else { fContinueMainLoop = FALSE; } ::LeaveCriticalSection(&g_csTransport); } } // while
g_dwPluggableTransportThreadID = 0;
return 0; }
BOOL EnsurePluggableTransportThread(void) { BOOL fRet = TRUE; if (! g_dwPluggableTransportThreadID) { fRet = FALSE; HANDLE hSync = ::CreateEvent(NULL, FALSE, FALSE, NULL); if (NULL != hSync) { HANDLE hThread = ::CreateThread(NULL, 0, PluggableTransportThreadProc, hSync, 0, &g_dwPluggableTransportThreadID); if (NULL != hThread) { ::WaitForSingleObject(hSync, 5000); // 5 second
::CloseHandle(hThread); fRet = TRUE; } ::CloseHandle(hSync); } } return fRet; }
#if defined(TEST_PLUGGABLE) && defined(_DEBUG)
LPCSTR FakeNodeAddress(LPCSTR pcszNodeAddress) { char szAddr[64]; ::lstrcpyA(szAddr, pcszNodeAddress); for (LPSTR psz = &szAddr[0]; *psz; psz++) { if (*psz == ':') { *psz = '\0'; break; } } if (! ::lstrcmp(szAddr, "157.59.12.93")) { pcszNodeAddress = "XPRT: 1"; } else if (! ::lstrcmp(szAddr, "157.59.13.194")) { pcszNodeAddress = "XPRT: 2"; } else if (! ::lstrcmp(szAddr, "157.59.10.198")) { pcszNodeAddress = "XPRT: 1"; } else { ASSERT(0); } return pcszNodeAddress; } #endif
int SubmitPluggableRead(PSocket pSocket, LPBYTE buffer, int length, PLUGXPRT_RESULT *plug_rc) { TRACE_OUT(("SubmitPluggableRead"));
int nRet = SOCKET_ERROR; *plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
CPluggableConnection *p = ::GetPluggableConnection(pSocket); if (NULL != p) { nRet = p->Read(buffer, length, plug_rc); } else { WARNING_OUT(("SubmitPluggableRead: no such conn ID=%d", pSocket->XprtConn.nLogicalHandle)); } return nRet; }
int CPluggableConnection::Read(LPBYTE buffer, int length, PLUGXPRT_RESULT *plug_rc) { int cbRecv = SOCKET_ERROR; *plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
::EnterCriticalSection(&g_csTransport);
if (NULL != m_OverlappedRead.hEvent) { // handle low-level pending read first
if (m_fPendingReadDone) { // copy the data from internal buffer to external buffer
if (length <= m_cbPendingRead) { // get as requested
cbRecv = length; ::CopyMemory(buffer, m_pbPendingRead, length); m_cbPendingRead -= length; if (m_cbPendingRead <= 0) { CleanupReadState(); } else { // move the memory, do not use copymemory due to overlap
int cb = m_cbPendingRead; LPBYTE pbDst = m_pbPendingRead; LPBYTE pbSrc = &m_pbPendingRead[length]; while (cb--) { *pbDst++ = *pbSrc++; } } } else { // only get partial data
cbRecv = m_cbPendingRead; ::CopyMemory(buffer, m_pbPendingRead, m_cbPendingRead); CleanupReadState(); }
// start next high-level read
NotifyHighLevelRead(); } } else { if (SetupReadState(length)) { TRACE_OUT(("CPluggableConnection::Read: ReadFile(%d)", m_cbPendingRead));
DWORD dwRead = 0; if (! ::ReadFile(m_hCommLink, m_pbPendingRead, m_cbPendingRead, &dwRead, &m_OverlappedRead)) { DWORD dwErr = ::GetLastError(); if (ERROR_HANDLE_EOF != dwErr && ERROR_IO_PENDING != dwErr) { WARNING_OUT(("CPluggableConnection::Read: ReadFile failed, err=%d", dwErr));
CleanupReadState();
// disconnect at next tick
NotifyReadFailure(); *plug_rc = PLUGXPRT_RESULT_READ_FAILED; } } else { // do nothing, treat it as WSAEWOULDBLOCK
} } else { ERROR_OUT(("CPluggableConnection::Read: failed to allocate memory (%d)", length)); // out of memory, try later
// do nothing, treat it as WSAEWOULDBLOCK
} }
::LeaveCriticalSection(&g_csTransport);
return cbRecv; }
BOOL CPluggableConnection::OnPendingRead(void) { TRACE_OUT(("CPluggableConnection::OnPendingRead"));
BOOL fRet = FALSE;
::EnterCriticalSection(&g_csTransport);
if (NULL != m_OverlappedRead.hEvent) { DWORD cbRead = 0;
if (::GetOverlappedResult(m_hCommLink, &m_OverlappedRead, &cbRead, FALSE)) { if ((int) cbRead == m_cbPendingRead) { TRACE_OUT(("CPluggableConnection::OnPendingRead: Received %d bytes (required %d bytes) on socket (%d, %d).", cbRead, m_cbPendingRead, m_eType, m_nConnID)); } else { WARNING_OUT(("CPluggableConnection::OnPendingRead: Received %d bytes (required %d bytes) on socket (%d, %d).", cbRead, m_cbPendingRead, m_eType, m_nConnID)); } m_cbPendingRead = cbRead; // in case cbRead is smaller
m_fPendingReadDone = TRUE; fRet = TRUE; // turn off event
} else { DWORD dwErr = ::GetLastError(); if (ERROR_IO_INCOMPLETE == dwErr) { ASSERT(! cbRead); } else { TRACE_OUT(("CPluggableConnection::OnPendingRead: read failed %d", dwErr)); fRet = TRUE; // turn off event
// disconnect at next tick
NotifyReadFailure(); } } } else { ERROR_OUT(("CPluggableConnection::OnPendingRead: no pending read event handle.")); fRet = TRUE; // turn off event
}
::LeaveCriticalSection(&g_csTransport);
return fRet; }
void CPluggableConnection::NotifyHighLevelRead(void) { WPARAM wParam = MAKE_PLUGXPRT_WPARAM(m_nConnID, m_eType); LPARAM lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_HIGH_LEVEL_READ, PLUGXPRT_RESULT_SUCCESSFUL); BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam); ASSERT(fRet); }
void CPluggableConnection::NotifyReadFailure(void) { WPARAM wParam = MAKE_PLUGXPRT_WPARAM(m_nConnID, m_eType); LPARAM lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_READ, PLUGXPRT_RESULT_READ_FAILED); BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam); ASSERT(fRet); }
void CPluggableConnection::NotifyWriteEvent(void) { WPARAM wParam = MAKE_PLUGXPRT_WPARAM(m_nConnID, m_eType); LPARAM lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_WRITE, PLUGXPRT_RESULT_SUCCESSFUL); BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam); ASSERT(fRet); }
void CPluggableConnection::NotifyHighLevelWrite(void) { WPARAM wParam = MAKE_PLUGXPRT_WPARAM(m_nConnID, m_eType); LPARAM lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_HIGH_LEVEL_WRITE, PLUGXPRT_RESULT_SUCCESSFUL); BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam); ASSERT(fRet); }
void CPluggableConnection::NotifyWriteFailure(void) { WPARAM wParam = MAKE_PLUGXPRT_WPARAM(m_nConnID, m_eType); LPARAM lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_WRITE, PLUGXPRT_RESULT_WRITE_FAILED); BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam); ASSERT(fRet); }
LPBYTE DuplicateBuffer(LPBYTE buffer, UINT length) { // DBG_SAVE_FILE_LINE
LPBYTE new_buffer = new BYTE[length]; if (NULL != new_buffer) { ::CopyMemory(new_buffer, buffer, length); } return new_buffer; }
int SubmitPluggableWrite(PSocket pSocket, LPBYTE buffer, int length, PLUGXPRT_RESULT *plug_rc) { TRACE_OUT(("SubmitPluggableWrite"));
int nRet = SOCKET_ERROR; *plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
CPluggableConnection *p = ::GetPluggableConnection(pSocket); if (NULL != p) { nRet = p->Write(buffer, length, plug_rc); } else { WARNING_OUT(("SubmitPluggableWrite: no such conn ID=%d", pSocket->XprtConn.nLogicalHandle)); } return nRet; }
int CPluggableConnection::Write(LPBYTE buffer, int length, PLUGXPRT_RESULT *plug_rc) { TRACE_OUT(("CPluggableConnection::Write"));
int cbSent = SOCKET_ERROR; *plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
::EnterCriticalSection(&g_csTransport);
if (m_OutBufQueue2.GetCount() < MAX_PLUGGABLE_OUT_BUF_SIZE) // x4K
{ DBG_SAVE_FILE_LINE buffer = ::DuplicateBuffer(buffer, length); if (NULL != buffer) { cbSent = length; m_OutBufQueue2.Append(length, buffer); if (1 == m_OutBufQueue2.GetCount()) { TRACE_OUT(("CPluggableConnection::Write: the only item in the queue")); WriteTheFirst(); #if 0 // avoid another tick
// start next low-level write
WPARAM wParam = MAKE_PLUGXPRT_WPARAM(m_nConnID, m_eType); LPARAM lParam = MAKE_PLUGXPRT_LPARAM(PLUGXPRT_EVENT_WRITE, PLUGXPRT_RESULT_SUCCESSFUL); BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_X224, wParam, lParam); ASSERT(fRet); #endif
} else { TRACE_OUT(("CPluggableConnection::Write: more items in the queue")); } } else { ERROR_OUT(("CPluggableConnection::Write: failed to allocate memory (%d)", length)); // out of memory, try later
// do nothing, treat it as WSAEWOULDBLOCK
} }
::LeaveCriticalSection(&g_csTransport);
return cbSent; }
void CPluggableConnection::WriteTheFirst(void) { int length; LPBYTE buffer;
TRACE_OUT(("CPluggableConnection::WriteTheFirst"));
::EnterCriticalSection(&g_csTransport);
if (NULL == m_OverlappedWrite.hEvent) { length = 0; buffer = m_OutBufQueue2.PeekHead(&length); if (NULL != buffer) { ::ZeroMemory(&m_OverlappedWrite, sizeof(m_OverlappedWrite)); m_OverlappedWrite.hEvent = m_hevtPendingWrite;
m_pbPendingWrite = buffer; m_cbPendingWrite = length;
TRACE_OUT(("CPluggableConnection::WriteTheFirst: WriteFile(%d)", length));
DWORD cbWritten = 0; if (! ::WriteFile(m_hCommLink, buffer, length, &cbWritten, &m_OverlappedWrite)) { DWORD dwErr = ::GetLastError(); if (ERROR_IO_PENDING != dwErr) { ERROR_OUT(("CPluggableConnection::WriteTheFirst: WriteFile failed, err=%d", dwErr)); CleanupWriteState(); m_OutBufQueue2.Get(); // dequeue the buffer which cannot be sent
NotifyWriteFailure(); } else { // we are still in pending
// repeat the write event
NotifyWriteEvent(); } } } else { TRACE_OUT(("CPluggableConnection::WriteTheFirst: queue is empty"));
// no more low-level write
m_pbPendingWrite = NULL; CleanupWriteState();
// start next high-level write
NotifyHighLevelWrite(); } } else { TRACE_OUT(("CPluggableConnection::WriteTheFirst: still pending")); // we are still in write pending, wake up the pending write
OnPendingWrite(); // check for pending write result
NotifyWriteEvent(); }
::LeaveCriticalSection(&g_csTransport); }
void PluggableWriteTheFirst(TransportConnection XprtConn) { if (IS_PLUGGABLE(XprtConn)) { CPluggableConnection *p = ::GetPluggableConnection(XprtConn.nLogicalHandle); if (NULL != p) { p->WriteTheFirst(); } else { ERROR_OUT(("PluggableWriteTheFirst: no such conn ID=%d", XprtConn.nLogicalHandle)); } } else { ERROR_OUT(("PluggableWriteTheFirst: not plugable connection")); } }
void PluggableShutdown(TransportConnection XprtConn) { if (IS_PLUGGABLE(XprtConn)) { CPluggableConnection *p = ::GetPluggableConnection(XprtConn.nLogicalHandle); if (NULL != p) { p->Shutdown(); } else { ERROR_OUT(("PluggableShutdown: no such conn ID=%d", XprtConn.nLogicalHandle)); } } else { ERROR_OUT(("PluggableShutdown: not plugable connection")); } }
BOOL CPluggableConnection::OnPendingWrite(void) { TRACE_OUT(("CPluggableConnection::OnPendingWrite"));
BOOL fRet = FALSE; BOOL fStartNextWrite = FALSE;
::EnterCriticalSection(&g_csTransport);
if (NULL != m_OverlappedWrite.hEvent) { DWORD cbWritten = 0; if (::GetOverlappedResult(m_hCommLink, &m_OverlappedWrite, &cbWritten, FALSE)) { TRACE_OUT(("CPluggableConnection::OnPendingWrite: Sent %d bytes (required %d bytes) on socket (%d, %d).", cbWritten, m_cbPendingWrite, m_eType, m_nConnID)); if (cbWritten >= (DWORD) m_cbPendingWrite) { ASSERT(cbWritten == (DWORD) m_cbPendingWrite);
// remove the item from the queue
int length = 0; LPBYTE buffer = m_OutBufQueue2.Get(&length); ASSERT(length == m_cbPendingWrite); ASSERT(buffer == m_pbPendingWrite);
CleanupWriteState();
fRet = TRUE; // turn off event
} else { ERROR_OUT(("CPluggableConnection::OnPendingWrite: unexpected error, less data written %d (required %d)", cbWritten, m_cbPendingWrite)); NotifyWriteFailure(); fRet = TRUE; // turn off event
} } else { DWORD dwErr = ::GetLastError(); if (ERROR_IO_INCOMPLETE == dwErr) { ASSERT(! cbWritten); } else { ERROR_OUT(("CPluggableConnection::OnPendingWrite: failed to write, err=%d", dwErr)); NotifyWriteFailure(); fRet = TRUE; // turn off event
} } } else { // it is very possible that we hit this many times
fRet = TRUE; }
::LeaveCriticalSection(&g_csTransport);
return fRet; }
BOOL CPluggableConnection::SetupReadState(int length) { DBG_SAVE_FILE_LINE LPBYTE buffer = new BYTE[length]; if (NULL != buffer) { m_pbPendingRead = buffer; m_cbPendingRead = length; m_fPendingReadDone = FALSE;
::ZeroMemory(&m_OverlappedRead, sizeof(m_OverlappedRead)); m_OverlappedRead.hEvent = m_hevtPendingRead; } else { CleanupReadState(); } return (NULL != buffer); }
void CPluggableConnection::CleanupReadState(void) { delete [] m_pbPendingRead; m_pbPendingRead = NULL; m_cbPendingRead = 0; m_fPendingReadDone = FALSE;
::ZeroMemory(&m_OverlappedRead, sizeof(m_OverlappedRead)); }
void CPluggableConnection::CleanupWriteState(void) { delete [] m_pbPendingWrite; m_pbPendingWrite = NULL; m_cbPendingWrite = 0;
::ZeroMemory(&m_OverlappedWrite, sizeof(m_OverlappedWrite)); }
TransportError CALLBACK LegacyTransportCallback(ULONG nMsg, void *Param1, void *Param2) { if (Param2 == g_pPluggableTransport) { BOOL fPostMsg = FALSE; WPARAM wParam = 0; CPluggableConnection *p;
switch (nMsg) { case TRANSPORT_CONNECT_INDICATION: TRACE_OUT(("LegacyTransportCallback::TRANSPORT_CONNECT_INDICATION")); { LegacyTransportID *pID = (LegacyTransportID *) Param1; p = ::GetPluggableConnection(pID->hCommLink); if (NULL != p) { p->SetLegacyHandle(pID->logical_handle);
{ PSocket pSocket = p->GetSocket(); ASSERT(NULL != pSocket); if (NULL != pSocket) { pSocket->State = SOCKET_CONNECTED; wParam = MAKE_PLUGXPRT_WPARAM(p->GetConnID(), TRANSPORT_TYPE_PLUGGABLE_PSTN); fPostMsg = TRUE; } } } } break;
case TRANSPORT_CONNECT_CONFIRM: TRACE_OUT(("LegacyTransportCallback::TRANSPORT_CONNECT_CONFIRM")); { LegacyTransportID *pID = (LegacyTransportID *) Param1; p = ::GetPluggableConnection(pID->hCommLink); if (NULL != p) { ASSERT(p->GetLegacyHandle() == pID->logical_handle);
{ PSocket pSocket = p->GetSocket(); ASSERT(NULL != pSocket); if (NULL != pSocket) { pSocket->State = X224_CONNECTED; wParam = MAKE_PLUGXPRT_WPARAM(p->GetConnID(), TRANSPORT_TYPE_PLUGGABLE_PSTN); fPostMsg = TRUE; } } } } break;
case TRANSPORT_DISCONNECT_INDICATION: TRACE_OUT(("LegacyTransportCallback::TRANSPORT_DISCONNECT_INDICATION")); { LegacyTransportID *pID = (LegacyTransportID *) Param1; TransportConnection XprtConn; XprtConn.eType = TRANSPORT_TYPE_PLUGGABLE_PSTN; p = ::GetPluggableConnectionByLegacyHandle(pID->logical_handle); if (NULL != p) { XprtConn.nLogicalHandle = p->GetConnID(); } ::OnProtocolControl(XprtConn, PLUGXPRT_DISCONNECTED); fPostMsg = FALSE; } break;
case TRANSPORT_DATA_INDICATION: TRACE_OUT(("LegacyTransportCallback::TRANSPORT_DATA_INDICATION")); { //
// This piece of data does not have X.224 framing
//
LegacyTransportData *pData = (LegacyTransportData *) Param1; TRACE_OUT(("LegacyTransportCallback::pbData=0x%x, cbDataSize=%d", pData->pbData, pData->cbDataSize));
if (NULL != g_Transport) { DBG_SAVE_FILE_LINE TransportData *td = new TransportData; if (NULL != td) { td->transport_connection.eType = TRANSPORT_TYPE_PLUGGABLE_PSTN; p = ::GetPluggableConnectionByLegacyHandle(pData->logical_handle); if (NULL != p) { ULONG cbTotalSize = PROTOCOL_OVERHEAD_X224 + pData->cbDataSize; td->transport_connection.nLogicalHandle = p->GetConnID(); DBG_SAVE_FILE_LINE td->memory = ::AllocateMemory(NULL, cbTotalSize, RECV_PRIORITY); if (NULL != td->memory) { td->user_data = td->memory->GetPointer(); td->user_data_length = cbTotalSize;
// take care of the X.224 header
::CopyMemory(td->user_data, g_X224Header, PROTOCOL_OVERHEAD_X224); AddRFCSize(td->user_data, cbTotalSize); // take care of the data
::CopyMemory(td->user_data + PROTOCOL_OVERHEAD_X224, pData->pbData, pData->cbDataSize);
wParam = (WPARAM) td; fPostMsg = TRUE; } else { ERROR_OUT(("LegacyTransportCallback: failed to allocate memory, size=%d", cbTotalSize)); } } } else { ERROR_OUT(("LegacyTransportCallback: failed to allocate TransportData")); } } } break;
default: wParam = (WPARAM) Param1; fPostMsg = TRUE; break; }
if (fPostMsg) { BOOL fRet = ::PostMessage(TCP_Window_Handle, WM_PLUGGABLE_PSTN, wParam, nMsg); ASSERT(fRet); } }
return TRANSPORT_NO_ERROR; }
void HandlePSTNCallback(WPARAM wParam, LPARAM lParam) { if (NULL != g_pPluggableTransport) { CPluggableConnection *p;
switch (lParam) { case TRANSPORT_CONNECT_INDICATION: TRACE_OUT(("HandlePSTNCallback::TRANSPORT_CONNECT_INDICATION")); if (NULL != g_Transport) { TransportConnection XprtConn; XprtConn.nLogicalHandle = PLUGXPRT_WPARAM_TO_ID(wParam); XprtConn.eType = (TransportType) PLUGXPRT_WPARAM_TO_TYPE(wParam); ::OnProtocolControl(XprtConn, PLUGXPRT_CONNECTED); g_Transport->ConnectIndication(XprtConn); } break;
case TRANSPORT_CONNECT_CONFIRM: TRACE_OUT(("HandlePSTNCallback::TRANSPORT_CONNECT_CONFIRM")); if (NULL != g_Transport) { TransportConnection XprtConn; XprtConn.nLogicalHandle = PLUGXPRT_WPARAM_TO_ID(wParam); XprtConn.eType = (TransportType) PLUGXPRT_WPARAM_TO_TYPE(wParam); ::OnProtocolControl(XprtConn, PLUGXPRT_CONNECTED); g_Transport->ConnectConfirm(XprtConn); } break;
case TRANSPORT_DATA_INDICATION: TRACE_OUT(("HandlePSTNCallback::TRANSPORT_DATA_INDICATION")); { TransportData *td = (TransportData *) wParam; if (NULL != g_Transport) { g_Transport->DataIndication(td); } delete td; } break;
case TRANSPORT_BUFFER_EMPTY_INDICATION: TRACE_OUT(("HandlePSTNCallback::TRANSPORT_BUFFER_EMPTY_INDICATION")); { LEGACY_HANDLE logical_handle = (LEGACY_HANDLE) wParam; TransportConnection XprtConn; XprtConn.eType = TRANSPORT_TYPE_PLUGGABLE_PSTN; p = ::GetPluggableConnectionByLegacyHandle(logical_handle); if (NULL != p) { XprtConn.nLogicalHandle = p->GetConnID(); g_Transport->BufferEmptyIndication(XprtConn); } } break;
default: ERROR_OUT(("HandlePSTNCallback: unknown message=%d", lParam)); break; } } }
BOOL CPluggableTransport::EnsureLegacyTransportLoaded(void) { if (NULL == g_pLegacyTransport) { g_hlibMST123 = ::LoadLibrary("MST123.DLL"); if (NULL != g_hlibMST123) { LPFN_T123_CreateTransportInterface pfn = (LPFN_T123_CreateTransportInterface) ::GetProcAddress(g_hlibMST123, LPSTR_T123_CreateTransportInterface); if (NULL != pfn) { TransportError rc = (*pfn)(&g_pLegacyTransport); if (TRANSPORT_NO_ERROR == rc) { ASSERT(NULL != g_pLegacyTransport);
// start to call initialize
rc = g_pLegacyTransport->TInitialize(LegacyTransportCallback, this); ASSERT(TRANSPORT_NO_ERROR == rc);
if (TRANSPORT_NO_ERROR == rc) { return TRUE; }
g_pLegacyTransport->TCleanup(); g_pLegacyTransport->ReleaseInterface(); g_pLegacyTransport = NULL; } }
::FreeLibrary(g_hlibMST123); g_hlibMST123 = NULL; }
return FALSE; }
return TRUE; }
TransportError CPluggableConnection::TConnectRequest(void) { TRACE_OUT(("CPluggableConnection::TConnectRequest")); TransportError rc = TRANSPORT_NO_PLUGGABLE_CONNECTION; if (NULL != g_pLegacyTransport) { TransportConnection XprtConn; XprtConn.eType = m_eType; XprtConn.nLogicalHandle = m_nConnID; ::OnProtocolControl(XprtConn, PLUGXPRT_CONNECTING);
rc = g_pLegacyTransport->TConnectRequest(&m_nLegacyLogicalHandle, m_hCommLink); } return rc; }
TransportError CPluggableConnection::TDisconnectRequest(void) { TRACE_OUT(("CPluggableConnection::TDisconnectRequest")); TransportError rc = TRANSPORT_NO_PLUGGABLE_CONNECTION; if (NULL != g_pLegacyTransport) { TransportConnection XprtConn; XprtConn.eType = m_eType; XprtConn.nLogicalHandle = m_nConnID; ::OnProtocolControl(XprtConn, PLUGXPRT_DISCONNECTING);
::Sleep(600); rc = g_pLegacyTransport->TDisconnectRequest(m_nLegacyLogicalHandle, TRUE); } return rc; }
int CPluggableConnection::TDataRequest(LPBYTE pbData, ULONG cbDataSize, PLUGXPRT_RESULT *plug_rc) { TRACE_OUT(("CPluggableConnection::TDataRequest, pbData=0x%x, cbDataSize=%d", pbData, cbDataSize)); if (NULL != g_pLegacyTransport) { *plug_rc = PLUGXPRT_RESULT_SUCCESSFUL;
// skip X.224 framing
ASSERT(cbDataSize > PROTOCOL_OVERHEAD_X224);
TransportError rc; rc = g_pLegacyTransport->TDataRequest(m_nLegacyLogicalHandle, pbData + PROTOCOL_OVERHEAD_X224, cbDataSize - PROTOCOL_OVERHEAD_X224); if (TRANSPORT_NO_ERROR == rc) { TRACE_OUT(("CPluggableConnection::TDataRequest: sent data size=%d", cbDataSize)); return cbDataSize; } } else { *plug_rc = PLUGXPRT_RESULT_WRITE_FAILED; } return SOCKET_ERROR; }
TransportError TReceiveBufferAvailable(void) { TRACE_OUT(("CPluggableConnection::TReceiveBufferAvailable")); TransportError rc = TRANSPORT_NO_PLUGGABLE_CONNECTION; if (NULL != g_pLegacyTransport) { rc = g_pLegacyTransport->TReceiveBufferAvailable(); } return rc; }
TransportError CPluggableConnection::TPurgeRequest(void) { TRACE_OUT(("CPluggableConnection::TPurgeRequest")); TransportError rc = TRANSPORT_NO_PLUGGABLE_CONNECTION; if (NULL != g_pLegacyTransport) { rc = g_pLegacyTransport->TPurgeRequest(m_nLegacyLogicalHandle); } return rc; }
|