2031 lines
70 KiB
C++
2031 lines
70 KiB
C++
/* file: mbft.cpp */
|
|
|
|
#include "mbftpch.h"
|
|
#include <it120app.h>
|
|
#include <version.h>
|
|
|
|
#define __NO_EXTERNS__
|
|
#include "mbft.hpp"
|
|
#include "osshelp.hpp"
|
|
#include "messages.hpp"
|
|
#include "mbftrecv.hpp"
|
|
#include "mbftsend.hpp"
|
|
|
|
void CALLBACK T120Callback(T120AppletSessionMsg *);
|
|
|
|
// from mbftapi.cpp
|
|
BOOL g_fWaitingForBufferAvailable = FALSE;
|
|
|
|
|
|
#ifdef ENABLE_HEARTBEAT_TIMER
|
|
|
|
// WM_TIMER has the lowest priority among window messages
|
|
#define IDLE_TIMER_SPEED 5000
|
|
#define SESSION_TIMER_SPEED 20
|
|
|
|
void HeartBeatTimerProc(HWND hWnd, UINT uMsg, UINT_PTR nTimerID, DWORD dwTime)
|
|
{
|
|
if (NULL != g_pFileXferApplet)
|
|
{
|
|
MBFTEngine *pEngine = g_pFileXferApplet->FindEngineByTimerID(nTimerID);
|
|
if (NULL != pEngine)
|
|
{
|
|
::PostMessage(g_pFileXferApplet->GetHiddenWnd(), MBFTMSG_HEART_BEAT,
|
|
0, (LPARAM) pEngine);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
MBFTEngine::MBFTEngine
|
|
(
|
|
MBFTInterface *pMBFTIntf,
|
|
MBFT_MODE eMode,
|
|
T120SessionID nSessionID
|
|
)
|
|
:
|
|
CRefCount(MAKE_STAMP_ID('F','T','E','g')),
|
|
|
|
m_pAppletSession(NULL),
|
|
m_eLastSendDataError(T120_NO_ERROR),
|
|
|
|
m_pMBFTIntf(pMBFTIntf),
|
|
|
|
m_fConfAvailable(FALSE),
|
|
m_fJoinedConf(FALSE),
|
|
|
|
m_uidMyself(0), // user id
|
|
m_nidMyself(0), // node id
|
|
m_eidMyself(0), // entity id
|
|
|
|
m_eMBFTMode(eMode),
|
|
m_SessionID(nSessionID),
|
|
|
|
m_MBFTControlChannel(nSessionID),
|
|
m_MBFTDataChannel(0),
|
|
|
|
m_nRosterInstance(0),
|
|
|
|
m_nConfID(0),
|
|
|
|
m_MBFTMaxFileSize(_iMBFT_MAX_FILE_SIZE),
|
|
|
|
m_MBFTMaxDataPayload(_iMBFT_DEFAULT_MAX_FILEDATA_PDU_LENGTH),
|
|
m_MBFTMaxSendDataPayload(_iMBFT_DEFAULT_MAX_MCS_SIZE - _iMBFT_FILEDATA_PDU_SUBTRACT),
|
|
|
|
m_bV42CompressionSupported(FALSE),
|
|
m_v42bisP1(_iMBFT_V42_NO_OF_CODEWORDS),
|
|
m_v42bisP2(_iMBFT_V42_MAX_STRING_LENGTH),
|
|
|
|
// LONCHANC: NetMeeting's Node Controller does not exercise conductorship.
|
|
#ifdef ENABLE_CONDUCTORSHIP
|
|
m_bInConductedMode(FALSE),
|
|
m_ConductorNodeID(0),
|
|
m_MBFTConductorID(0),
|
|
m_ConductedModePermission(0),
|
|
m_bWaitingForPermission(FALSE),
|
|
#endif // ENABLE_CONDUCTORSHIP
|
|
|
|
m_pWindow(NULL),
|
|
m_State(IdleNotInitialized)
|
|
{
|
|
g_fWaitingForBufferAvailable = FALSE;
|
|
|
|
switch (m_eMBFTMode)
|
|
{
|
|
case MBFT_STATIC_MODE:
|
|
ASSERT(m_MBFTControlChannel == _MBFT_CONTROL_CHANNEL);
|
|
m_MBFTDataChannel = _MBFT_DATA_CHANNEL;
|
|
break;
|
|
|
|
#ifdef USE_MULTICAST_SESSION
|
|
case MBFT_MULTICAST_MODE:
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
ERROR_OUT(("MBFTEngine::MBFTEngine: invalid session type=%u", m_eMBFTMode));
|
|
break;
|
|
}
|
|
|
|
// clear join session structures
|
|
::ZeroMemory(&m_aStaticChannels, sizeof(m_aStaticChannels));
|
|
#ifdef USE_MULTICAST_SESSION
|
|
::ZeroMemory(&m_aJoinResourceReqs, sizeof(m_aJoinResourceReqs));
|
|
#endif
|
|
::ZeroMemory(&m_JoinSessionReq, sizeof(m_JoinSessionReq));
|
|
|
|
ASSERT(NULL != g_pFileXferApplet);
|
|
g_pFileXferApplet->RegisterEngine(this);
|
|
|
|
m_pWindow = g_pFileXferApplet->GetUnattendedWindow();
|
|
if (NULL != m_pWindow)
|
|
{
|
|
m_pWindow->RegisterEngine(this);
|
|
}
|
|
|
|
#ifdef ENABLE_HEARTBEAT_TIMER
|
|
m_nTimerID = ::SetTimer(NULL, 0, IDLE_TIMER_SPEED, HeartBeatTimerProc);
|
|
#endif
|
|
}
|
|
|
|
MBFTEngine::~MBFTEngine(void)
|
|
{
|
|
#ifdef ENABLE_HEARTBEAT_TIMER
|
|
// kill the timer now
|
|
::KillTimer(NULL, m_nTimerID);
|
|
#endif
|
|
|
|
// the interface object is already gone
|
|
m_pMBFTIntf = NULL;
|
|
|
|
MBFTSession *pSession;
|
|
while (NULL != (pSession = m_SessionList.Get()))
|
|
{
|
|
pSession->UnInitialize(FALSE);
|
|
delete pSession; // LONCHANC: not sure about this delete
|
|
}
|
|
|
|
if (NULL != m_pAppletSession)
|
|
{
|
|
m_pAppletSession->ReleaseInterface();
|
|
}
|
|
|
|
ASSERT(! m_fJoinedConf);
|
|
|
|
m_PeerList.DeleteAll();
|
|
}
|
|
|
|
void MBFTEngine::SetInterfacePointer( MBFTInterface *pIntf )
|
|
{
|
|
CPeerData *pPeerData;
|
|
|
|
ASSERT (pIntf);
|
|
m_pMBFTIntf = pIntf;
|
|
m_PeerList.Reset();
|
|
while (NULL != (pPeerData = m_PeerList.Iterate()))
|
|
{
|
|
if (pPeerData->GetNodeID() != m_nidMyself)
|
|
{
|
|
AddPeerNotification(pPeerData->GetNodeID(),
|
|
pPeerData->GetUserID(),
|
|
pPeerData->GetIsLocalNode(),
|
|
pPeerData->GetIsProshareNode(), TRUE,
|
|
pPeerData->GetAppKey(),
|
|
m_SessionID);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL MBFTEngine::Has2xNodeInConf(void)
|
|
{
|
|
CPeerData *pPeerData;
|
|
m_PeerList.Reset();
|
|
while (NULL != (pPeerData = m_PeerList.Iterate()))
|
|
{
|
|
// if (pPeerData->GetVersion() < HIWORD(VER_PRODUCTVERSION_DW))
|
|
if (pPeerData->GetVersion() < 0x0404)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL MBFTEngine::HasSDK(void)
|
|
{
|
|
return (m_pMBFTIntf ? TRUE : FALSE);
|
|
}
|
|
|
|
|
|
HRESULT MBFTEngine::SafePostMessage
|
|
(
|
|
MBFTMsg *pMsg
|
|
)
|
|
{
|
|
if (NULL != pMsg)
|
|
{
|
|
AddRef();
|
|
::PostMessage(g_pFileXferApplet->GetHiddenWnd(), MBFTMSG_BASIC, (WPARAM) pMsg, (LPARAM) this);
|
|
return S_OK;
|
|
}
|
|
ERROR_OUT(("MBFTEngine::SafePostMessage: null msg ptr"));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
void MBFTEngine::OnPermitToEnrollIndication
|
|
(
|
|
GCCAppPermissionToEnrollInd *pInd
|
|
)
|
|
{
|
|
T120Error rc;
|
|
|
|
TRACEGCC( " Permission to enroll in conference [%d] is %sgranted.\n",
|
|
pInd->nConfID, pInd->fPermissionGranted?"":"not " );
|
|
|
|
m_fConfAvailable = pInd->fPermissionGranted;
|
|
|
|
if (pInd->fPermissionGranted)
|
|
{
|
|
m_nConfID = pInd->nConfID;
|
|
|
|
// build the common part of the join session request for the base session
|
|
ASSERT(m_SessionID == m_MBFTControlChannel);
|
|
::ZeroMemory(&m_JoinSessionReq, sizeof(m_JoinSessionReq));
|
|
m_JoinSessionReq.dwAttachmentFlags = ATTACHMENT_DISCONNECT_IN_DATA_LOSS;
|
|
m_JoinSessionReq.fConductingCapable = FALSE;
|
|
m_JoinSessionReq.nStartupChannelType = MCS_STATIC_CHANNEL;
|
|
m_JoinSessionReq.cNonCollapsedCaps = sizeof(g_aAppletNonCollCaps) / sizeof(g_aAppletNonCollCaps[0]);
|
|
m_JoinSessionReq.apNonCollapsedCaps = (GCCNonCollCap **) &g_aAppletNonCollCaps[0];
|
|
m_JoinSessionReq.cCollapsedCaps = sizeof(g_aAppletCaps) / sizeof(g_aAppletCaps[0]);
|
|
m_JoinSessionReq.apCollapsedCaps = (GCCAppCap **) &g_aAppletCaps[0];
|
|
|
|
// put in the session ID which is the control channel ID
|
|
m_JoinSessionReq.SessionKey = g_AppletSessionKey;
|
|
m_JoinSessionReq.SessionKey.session_id = m_SessionID;
|
|
m_aStaticChannels[0] = m_MBFTControlChannel;
|
|
|
|
// at least one static channel to join
|
|
m_JoinSessionReq.aStaticChannels = &m_aStaticChannels[0];
|
|
|
|
// build the complete join session request for the base session
|
|
switch (m_eMBFTMode)
|
|
{
|
|
case MBFT_STATIC_MODE:
|
|
ASSERT(m_MBFTControlChannel == _MBFT_CONTROL_CHANNEL);
|
|
ASSERT(m_MBFTDataChannel = _MBFT_DATA_CHANNEL);
|
|
m_aStaticChannels[1] = m_MBFTDataChannel;
|
|
m_JoinSessionReq.cStaticChannels = 2; // control and data channels
|
|
// m_JoinSessionReq.cResourceReqs = 0;
|
|
break;
|
|
|
|
#ifdef USE_MULTICAST_SESSION
|
|
case MBFT_MULTICAST_MODE:
|
|
m_JoinSessionReq.cStaticChannels = 1; // control channel only
|
|
::ZeroMemory(&m_aJoinResourceReqs, sizeof(m_aJoinResourceReqs));
|
|
m_aJoinResourceReqs[0].eCommand = APPLET_RETRIEVE_N_JOIN_CHANNEL;
|
|
m_aJoinResourceReqs[0].RegKey.resource_id.length = sizeof(DATA_CHANNEL_RESOURCE_ID) - 1;
|
|
m_aJoinResourceReqs[0].RegKey.resource_id.value = DATA_CHANNEL_RESOURCE_ID;
|
|
m_aJoinResourceReqs[0].RegKey.session_key = m_JoinSessionReq.SessionKey;
|
|
m_JoinSessionReq.cResourceReqs = sizeof(m_aJoinResourceReqs) / sizeof(m_aJoinResourceReqs[0]);
|
|
m_JoinSessionReq.aResourceReqs = &m_aJoinResourceReqs[0];
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
ERROR_OUT(("MBFTEngine::OnPermitToEnrollIndication: invalid session type=%u", m_eMBFTMode));
|
|
break;
|
|
}
|
|
|
|
// now, create the applet session
|
|
rc = g_pFileXferApplet->CreateAppletSession(&m_pAppletSession, m_nConfID);
|
|
if (T120_NO_ERROR == rc)
|
|
{
|
|
ASSERT(NULL != m_pAppletSession);
|
|
m_pAppletSession->Advise(T120Callback, // callback function
|
|
g_pFileXferApplet, // applet context
|
|
this); // session context
|
|
|
|
rc = m_pAppletSession->Join(&m_JoinSessionReq);
|
|
}
|
|
|
|
if (T120_NO_ERROR != rc)
|
|
{
|
|
WARNING_OUT(("MBFTEngine::OnPermitToEnrollIndication: CreateAppletSession failed, rc=%u", rc));
|
|
DBG_SAVE_FILE_LINE
|
|
SafePostNotifyMessage(new InitUnInitNotifyMsg(EnumInitFailed));
|
|
}
|
|
} // in conference
|
|
else
|
|
// leaving the conference here
|
|
{
|
|
LPMBFTSESSION pSession;
|
|
m_SessionList.Reset();
|
|
while (NULL != (pSession = m_SessionList.Iterate()))
|
|
{
|
|
pSession->UnInitialize( TRUE );
|
|
}
|
|
|
|
//Time to say goodbye...
|
|
AddPeerNotification( m_nidMyself, m_uidMyself, TRUE, TRUE, FALSE, MY_APP_STR, m_SessionID );
|
|
|
|
//Clear the peer list...
|
|
m_PeerList.DeleteAll();
|
|
|
|
//Nuke all sessions except for the first one....
|
|
while (NULL != (pSession = m_SessionList.Get()))
|
|
{
|
|
delete pSession;
|
|
}
|
|
|
|
// leave the conference if not done so
|
|
if (NULL != m_pAppletSession)
|
|
{
|
|
m_pAppletSession->Unadvise();
|
|
|
|
// LONCHANC: I commented out the following line because we should not
|
|
// leave the conference until we are sure that we can release the interface.
|
|
// There are outstanding send-data-indication messages. If we leave now,
|
|
// we will not be able to free them...
|
|
// m_pAppletSession->Leave();
|
|
|
|
// let the core know we left the conference
|
|
DBG_SAVE_FILE_LINE
|
|
SafePostNotifyMessage(new InitUnInitNotifyMsg(EnumInvoluntaryUnInit));
|
|
}
|
|
|
|
// we are not in the conference anymore
|
|
m_fJoinedConf = FALSE;
|
|
|
|
// release this engine object in the next tick
|
|
::PostMessage(g_pFileXferApplet->GetHiddenWnd(), MBFTMSG_DELETE_ENGINE, 0, (LPARAM) this);
|
|
}
|
|
}
|
|
|
|
|
|
void MBFTEngine::OnJoinSessionConfirm
|
|
(
|
|
T120JoinSessionConfirm *pConfirm
|
|
)
|
|
{
|
|
if (T120_RESULT_SUCCESSFUL == pConfirm->eResult)
|
|
{
|
|
if (pConfirm->pIAppletSession == m_pAppletSession)
|
|
{
|
|
m_uidMyself = pConfirm->uidMyself;
|
|
m_eidMyself = pConfirm->eidMyself;
|
|
m_nidMyself = pConfirm->nidMyself;
|
|
ASSERT(m_SessionID == pConfirm->sidMyself);
|
|
|
|
#ifdef USE_MULTICAST_SESSION
|
|
if (MBFT_MULTICAST_MODE == m_eMBFTMode)
|
|
{
|
|
ASSERT(1 == pConfirm->cResourceReqs);
|
|
ASSERT(0 == m_MBFTDataChannel);
|
|
ASSERT(APPLET_RETRIEVE_N_JOIN_CHANNEL == pConfirm->aResourceResults[0].eCommand);
|
|
m_MBFTDataChannel = pConfirm->aResourceResults[0].nChannelID;
|
|
ASSERT(0 != m_MBFTDataChannel);
|
|
}
|
|
#endif
|
|
|
|
// we are now officially in the conference
|
|
m_fJoinedConf = TRUE;
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("MBFTEngine::OnJoinSessionConfirm: not my session confirm, pConfirm->pI=0x%x, m_pI=0x%x", pConfirm->pIAppletSession, m_pAppletSession));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING_OUT(("MBFTEngine::OnJoinSessionConfirm: failed, result=%u", pConfirm->eResult));
|
|
DBG_SAVE_FILE_LINE
|
|
SafePostNotifyMessage(new InitUnInitNotifyMsg(EnumInitFailed));
|
|
}
|
|
}
|
|
|
|
|
|
CPeerData::CPeerData
|
|
(
|
|
T120NodeID NodeID,
|
|
T120UserID MBFTUserID,
|
|
BOOL bIsLocalNode,
|
|
BOOL IsProshareNode,
|
|
BOOL bCanConduct,
|
|
BOOL bEOFAcknowledgment,
|
|
LPCSTR lpszAppKey,
|
|
DWORD dwVersion
|
|
)
|
|
:
|
|
m_NodeID(NodeID),
|
|
m_MBFTUserID(MBFTUserID),
|
|
m_bIsLocalNode(bIsLocalNode),
|
|
m_bIsProshareNode(IsProshareNode),
|
|
m_bCanConduct(bCanConduct),
|
|
m_bEOFAcknowledgment(bEOFAcknowledgment),
|
|
m_dwVersion(dwVersion)
|
|
{
|
|
if (lpszAppKey)
|
|
{
|
|
::lstrcpynA(m_szAppKey, lpszAppKey, sizeof(m_szAppKey));
|
|
}
|
|
else
|
|
{
|
|
m_szAppKey[0] = '\0';
|
|
}
|
|
}
|
|
|
|
|
|
void MBFTEngine::AddPeerNotification
|
|
(
|
|
T120NodeID NodeID,
|
|
T120UserID MBFTUserID,
|
|
BOOL IsLocalNode,
|
|
BOOL IsProshareNode,
|
|
BOOL bPeerAdded,
|
|
LPCSTR lpszAppKey,
|
|
T120SessionID SessionID
|
|
)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
SafePostNotifyMessage(
|
|
new PeerMsg(NodeID, MBFTUserID, IsLocalNode, IsProshareNode,
|
|
lpszAppKey, bPeerAdded, SessionID));
|
|
}
|
|
|
|
|
|
void MBFTEngine::AddAllPeers(void)
|
|
{
|
|
T120NodeID nNodeId;
|
|
CPeerData *pPeerData;
|
|
|
|
m_PeerList.Reset();
|
|
while (NULL != (pPeerData = m_PeerList.Iterate()))
|
|
{
|
|
nNodeId = pPeerData->GetNodeID();
|
|
if (nNodeId != m_nidMyself)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
SafePostNotifyMessage(new PeerMsg(nNodeId, pPeerData->GetUserID(),
|
|
FALSE, pPeerData->GetIsProshareNode(),
|
|
pPeerData->GetAppKey(), TRUE, m_SessionID));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// LONCHANC: NetMeeting's Node Controller does not exercise conductorship.
|
|
#ifdef ENABLE_CONDUCTORSHIP
|
|
void MBFTEngine::OnConductAssignIndication(GCCConductorAssignInd *pInd)
|
|
{
|
|
m_ConductorNodeID = pInd->nidConductor;
|
|
m_MBFTConductorID = 0;
|
|
m_ConductedModePermission = 0;
|
|
m_bWaitingForPermission = FALSE;
|
|
|
|
if (m_nidMyself == m_ConductorNodeID)
|
|
{
|
|
m_ConductedModePermission |= PrivilegeAssignPDU::EnumFileTransfer;
|
|
m_ConductedModePermission |= PrivilegeAssignPDU::EnumFileRequest;
|
|
m_ConductedModePermission |= PrivilegeAssignPDU::EnumPriority;
|
|
m_ConductedModePermission |= PrivilegeAssignPDU::EnumPrivateChannel;
|
|
m_ConductedModePermission |= PrivilegeAssignPDU::EnumAbort;
|
|
m_ConductedModePermission |= PrivilegeAssignPDU::EnumNonStandard;
|
|
}
|
|
else
|
|
{
|
|
CPeerData *lpPeer;
|
|
if (NULL != (lpPeer = m_PeerList.Find(m_ConductorNodeID)))
|
|
{
|
|
if (lpPeer->GetCanConduct())
|
|
{
|
|
//Now that we have found a conductor on the conducting node,
|
|
//our search is over....
|
|
m_MBFTConductorID = lpPeer->GetUserID();
|
|
}
|
|
}
|
|
|
|
//MBFT 8.11.1
|
|
//If there is a change in the conductor, and there is no MBFT conductor at the
|
|
//new conducting node, all transactions must cease....
|
|
//The m_bInConductedMode flag tells us if we were already in the conducted mode.
|
|
if( !m_MBFTConductorID && m_bInConductedMode )
|
|
{
|
|
//Abort all transactions....
|
|
AbortAllSends();
|
|
}
|
|
}
|
|
|
|
m_bInConductedMode = TRUE;
|
|
}
|
|
|
|
void MBFTEngine::OnConductReleaseIndication( GCCConferenceID ConfID )
|
|
{
|
|
m_bInConductedMode = FALSE;
|
|
m_ConductorNodeID = 0;
|
|
m_MBFTConductorID = 0;
|
|
m_ConductedModePermission = 0;
|
|
m_bWaitingForPermission = FALSE;
|
|
}
|
|
|
|
void MBFTEngine::OnConductGrantIndication(GCCConductorPermitGrantInd *pInd)
|
|
{
|
|
UINT Index;
|
|
|
|
for( Index = 0; Index < pInd->Granted.cNodes; Index++ )
|
|
{
|
|
if (pInd->Granted.aNodeIDs[Index] == m_nidMyself)
|
|
{
|
|
if( pInd->fThisNodeIsGranted )
|
|
{
|
|
m_ConductedModePermission |= PrivilegeAssignPDU::EnumFileTransfer;
|
|
m_ConductedModePermission |= PrivilegeAssignPDU::EnumFileRequest;
|
|
m_ConductedModePermission |= PrivilegeAssignPDU::EnumPriority;
|
|
m_ConductedModePermission |= PrivilegeAssignPDU::EnumPrivateChannel;
|
|
m_ConductedModePermission |= PrivilegeAssignPDU::EnumAbort;
|
|
m_ConductedModePermission |= PrivilegeAssignPDU::EnumNonStandard;
|
|
}
|
|
else
|
|
{
|
|
//TO DO:
|
|
//MBFT 8.11.1 and 8.12.1
|
|
//If the MBFT provider receives a GCCConductorPermissionGrantIndication
|
|
//with permission_flag = FALSE, all privileges are revoked and all
|
|
//transactions should be terminated....
|
|
m_ConductedModePermission = 0;
|
|
AbortAllSends();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MBFTEngine::AbortAllSends(void)
|
|
{
|
|
if( m_bInConductedMode )
|
|
{
|
|
MBFTSession *pSession;
|
|
m_SessionList.Reset();
|
|
while (NULL != (pSession = m_SessionList.Iterate()))
|
|
{
|
|
if (pSession->GetSessionType() == MBFT_PRIVATE_SEND_TYPE)
|
|
{
|
|
pSession->OnControlNotification(
|
|
_iMBFT_PROSHARE_ALL_FILES,
|
|
FileTransferControlMsg::EnumConductorAbortFile,
|
|
NULL,
|
|
NULL );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif // ENABLE_CONDUCTORSHIP
|
|
|
|
|
|
void MBFTEngine::OnDetachUserIndication
|
|
(
|
|
T120UserID mcsUserID,
|
|
T120Reason eReason
|
|
)
|
|
{
|
|
TRACEMCS(" Detach User Indication [%u]\n",mcsUserID);
|
|
|
|
if (mcsUserID == m_uidMyself)
|
|
{
|
|
m_fJoinedConf = FALSE;
|
|
m_pAppletSession->Unadvise();
|
|
|
|
//Time to say goodbye...
|
|
AddPeerNotification(m_nidMyself, m_uidMyself, TRUE, TRUE, FALSE, MY_APP_STR, m_SessionID);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL MBFTEngine::ProcessMessage(MBFTMsg *pMsg)
|
|
{
|
|
BOOL bWasHandled = FALSE;
|
|
BOOL bBroadcastFileOfferHack = FALSE;
|
|
MBFTSession *pSession;
|
|
|
|
// lonchanc: it is possible that the channel admit indication comes in
|
|
// before the session is created. in this case, put the message back to the queue.
|
|
if (m_SessionList.IsEmpty())
|
|
{
|
|
if (EnumMCSChannelAdmitIndicationMsg == pMsg->GetMsgType())
|
|
{
|
|
return FALSE; // do not delete the message and put it back to the queue
|
|
}
|
|
}
|
|
|
|
m_SessionList.Reset();
|
|
while (!bWasHandled && NULL != (pSession = m_SessionList.Iterate()))
|
|
{
|
|
switch (pMsg->GetMsgType())
|
|
{
|
|
case EnumMCSChannelAdmitIndicationMsg:
|
|
if (pSession->IsReceiveSession())
|
|
{
|
|
MBFTPrivateReceive *pRecvSession = (MBFTPrivateReceive *) pSession;
|
|
MCSChannelAdmitIndicationMsg *p = (MCSChannelAdmitIndicationMsg *) pMsg;
|
|
//We have to make an exception in the case because we get this
|
|
//message before the PrivateChannelInvitePDU() !!!
|
|
bWasHandled = pRecvSession->OnMCSChannelAdmitIndication(p->m_wChannelId, p->m_ManagerID);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEMCS(" Channel Admit Indication [%u], Manager [%u]\n", p->m_wChannelId, p->m_ManagerID);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumMCSChannelExpelIndicationMsg:
|
|
if (pSession->IsReceiveSession())
|
|
{
|
|
MBFTPrivateReceive *pRecvSession = (MBFTPrivateReceive *) pSession;
|
|
MCSChannelExpelIndicationMsg *p = (MCSChannelExpelIndicationMsg *) pMsg;
|
|
bWasHandled = pRecvSession->OnMCSChannelExpelIndication(p->m_wChannelId, p->m_iReason);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEMCS(" Channel Expel Indication [%u]\n", p->m_wChannelId);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumMCSChannelJoinConfirmMsg:
|
|
{
|
|
MCSChannelJoinConfirmMsg *p = (MCSChannelJoinConfirmMsg *) pMsg;
|
|
bWasHandled = pSession->OnMCSChannelJoinConfirm(p->m_wChannelId, p->m_bSuccess);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEMCS(" Channel Join Confirm [%u], Success = [%d]\n", p->m_wChannelId, p->m_bSuccess);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumMCSChannelConveneConfirmMsg:
|
|
if (pSession->IsSendSession())
|
|
{
|
|
MBFTPrivateSend *pSendSession = (MBFTPrivateSend *) pSession;
|
|
MCSChannelConveneConfirmMsg *p = (MCSChannelConveneConfirmMsg *) pMsg;
|
|
bWasHandled = pSendSession->OnMCSChannelConveneConfirm(p->m_wChannelId, p->m_bSuccess);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEMCS(" Channel Convene Confirm [%u], Success = [%d]\n", p->m_wChannelId, p->m_bSuccess);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumGenericMBFTPDUMsg:
|
|
{
|
|
MBFTPDUMsg *p = (MBFTPDUMsg *) pMsg;
|
|
bWasHandled = DispatchPDUMessage(pSession, p);
|
|
|
|
//Background on this hack:
|
|
//In the broadcast mode, we may get a FileOfferPDU followed by a FileStart
|
|
//PDU and may therefore not give the client application sufficient time
|
|
//to process the File Offer. Therefore, we make sure that we stop processing
|
|
//other messages if we get a broadcast FileOffer...
|
|
if(bWasHandled)
|
|
{
|
|
if (p->m_PDUType == EnumFileOfferPDU)
|
|
{
|
|
LPFILEOFFERPDU lpNewFileOfferPDU = (LPFILEOFFERPDU) p->m_lpNewPDU;
|
|
if(lpNewFileOfferPDU->GetAcknowledge() == 0)
|
|
{
|
|
bBroadcastFileOfferHack = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumPeerDeletedMsg:
|
|
{
|
|
PeerDeletedMsg *p = (PeerDeletedMsg *) pMsg;
|
|
pSession->OnPeerDeletedNotification(p->m_lpPeerData);
|
|
}
|
|
break;
|
|
|
|
case EnumSubmitFileSendMsg:
|
|
{
|
|
SubmitFileSendMsg *p = (SubmitFileSendMsg *) pMsg;
|
|
if (p->m_EventHandle == pSession->GetEventHandle())
|
|
{
|
|
if(pSession->GetSessionType() == MBFT_PRIVATE_SEND_TYPE)
|
|
{
|
|
bWasHandled = TRUE;
|
|
((MBFTPrivateSend *) pSession)->SubmitFileSendRequest(p);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumFileTransferControlMsg:
|
|
{
|
|
FileTransferControlMsg *p = (FileTransferControlMsg *) pMsg;
|
|
if (p->m_EventHandle == pSession->GetEventHandle())
|
|
{
|
|
bWasHandled = TRUE;
|
|
pSession->OnControlNotification(
|
|
p->m_hFile,
|
|
p->m_ControlCommand,
|
|
p->m_szDirectory,
|
|
p->m_szFileName);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
} // switch
|
|
|
|
if(bBroadcastFileOfferHack)
|
|
{
|
|
TRACE("(MBFT:) BroadcastFileOfferHack detected, aborting message processing\n");
|
|
break; //Out of message for loop
|
|
}
|
|
} //Message for loop
|
|
|
|
return TRUE; // delete the message
|
|
}
|
|
|
|
|
|
|
|
#ifdef ENABLE_CONDUCTORSHIP
|
|
BOOL MBFTEngine::ConductedModeOK(void)
|
|
{
|
|
BOOL bReturn = TRUE;
|
|
|
|
if(m_bInConductedMode)
|
|
{
|
|
bReturn = (m_ConductedModePermission & PrivilegeRequestPDU::EnumFileTransfer) &&
|
|
(m_ConductedModePermission & PrivilegeRequestPDU::EnumPrivateChannel);
|
|
|
|
}
|
|
|
|
return(bReturn);
|
|
}
|
|
#endif // ENABLE_CONDUCTORSHIP
|
|
|
|
|
|
BOOL MBFTEngine::HandleSessionCreation(MBFTMsg *pMsg)
|
|
{
|
|
switch (pMsg->GetMsgType())
|
|
{
|
|
case EnumCreateSessionMsg:
|
|
{
|
|
CreateSessionMsg *p = (CreateSessionMsg *) pMsg;
|
|
MBFTSession *lpNewSession = NULL;
|
|
MBFTEVENTHANDLE EventHandle = p->m_EventHandle;
|
|
T120SessionID SessionID = p->m_SessionID;
|
|
#ifdef ENABLE_CONDUCTORSHIP
|
|
BOOL bDeleteMessage = TRUE;
|
|
#endif
|
|
|
|
switch (p->m_iSessionType)
|
|
{
|
|
case MBFT_PRIVATE_SEND_TYPE:
|
|
if(m_State == IdleInitialized)
|
|
{
|
|
if(ConductedModeOK())
|
|
{
|
|
TRACESTATE(" Creating new acknowledged send session\n");
|
|
DBG_SAVE_FILE_LINE
|
|
lpNewSession = new MBFTPrivateSend(this,EventHandle,
|
|
m_uidMyself,
|
|
m_MBFTMaxSendDataPayload);
|
|
ASSERT(NULL != lpNewSession);
|
|
}
|
|
#ifdef ENABLE_CONDUCTORSHIP
|
|
else
|
|
{
|
|
bDeleteMessage = FALSE;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
TRACE(" Invalid attempt to create session before initialization\n");
|
|
}
|
|
break;
|
|
|
|
case MBFT_PRIVATE_RECV_TYPE:
|
|
if(m_State == IdleInitialized)
|
|
{
|
|
TRACESTATE(" Creating new acknowledge session\n");
|
|
DBG_SAVE_FILE_LINE
|
|
lpNewSession = new MBFTPrivateReceive(this,
|
|
EventHandle,
|
|
p->m_ControlChannel,
|
|
p->m_DataChannel);
|
|
ASSERT(NULL != lpNewSession);
|
|
}
|
|
else
|
|
{
|
|
TRACE(" Invalid attempt to create session before initialization\n");
|
|
}
|
|
break;
|
|
|
|
case MBFT_BROADCAST_RECV_TYPE:
|
|
#ifdef USE_BROADCAST_RECEIVE
|
|
if(m_State == IdleInitialized)
|
|
{
|
|
TRACESTATE(" Creating new broadcast receive session\n");
|
|
DBG_SAVE_FILE_LINE
|
|
lpNewSession = new MBFTBroadcastReceive(this,
|
|
EventHandle,
|
|
p->m_ControlChannel,
|
|
p->m_DataChannel,
|
|
p->m_SenderID,
|
|
p->m_FileHandle);
|
|
ASSERT(NULL != lpNewSession);
|
|
}
|
|
else
|
|
{
|
|
TRACE(" Invalid attempt to create session before initialization\n");
|
|
}
|
|
#endif // USE_BROADCAST_RECEIVE
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
} // switch
|
|
|
|
if (lpNewSession)
|
|
{
|
|
#ifdef ENABLE_HEARTBEAT_TIMER
|
|
if (lpNewSession->IsSendSession())
|
|
{
|
|
KillTimer(NULL, m_nTimerID);
|
|
m_nTimerID = ::SetTimer(NULL, 0, SESSION_TIMER_SPEED, HeartBeatTimerProc);
|
|
}
|
|
#endif
|
|
m_SessionList.Append(lpNewSession);
|
|
}
|
|
} // if create session message
|
|
break;
|
|
|
|
case EnumDeleteSessionMsg:
|
|
{
|
|
DeleteSessionMsg *p = (DeleteSessionMsg *) pMsg;
|
|
#ifdef ENABLE_HEARTBEAT_TIMER
|
|
if (NULL != p->m_lpDeleteSession)
|
|
{
|
|
if (p->m_lpDeleteSession->IsSendSession())
|
|
{
|
|
BOOL fSendSessExists = FALSE;
|
|
MBFTSession *pSess;
|
|
m_SessionList.Reset();
|
|
while (NULL != (pSess = m_SessionList.Iterate()))
|
|
{
|
|
if (pSess->IsSendSession())
|
|
{
|
|
fSendSessExists = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (! fSendSessExists)
|
|
{
|
|
::KillTimer(NULL, m_nTimerID);
|
|
m_nTimerID = ::SetTimer(NULL, 0, IDLE_TIMER_SPEED, HeartBeatTimerProc);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
m_SessionList.Delete(p->m_lpDeleteSession);
|
|
} // if delete session message
|
|
break;
|
|
|
|
default:
|
|
return FALSE; // not handled
|
|
}
|
|
|
|
return TRUE; // handled
|
|
}
|
|
|
|
|
|
BOOL MBFTEngine::DispatchPDUMessage(MBFTSession *lpMBFTSession,MBFTPDUMsg * lpNewMessage)
|
|
{
|
|
T120ChannelID wChannelID = lpNewMessage->m_wChannelId;
|
|
T120Priority iPriority = lpNewMessage->m_iPriority;
|
|
T120UserID SenderID = lpNewMessage->m_SenderID;
|
|
T120NodeID NodeID = GetNodeIdByUserID(SenderID);
|
|
BOOL IsUniformSendData = lpNewMessage->m_IsUniformSendData;
|
|
|
|
LPGENERICPDU lpNewPDU = lpNewMessage->m_lpNewPDU;
|
|
MBFTPDUType DecodedPDUType = lpNewMessage->m_PDUType;
|
|
|
|
BOOL bWasHandled = FALSE;
|
|
|
|
ASSERT(NULL != lpNewPDU);
|
|
switch(DecodedPDUType)
|
|
{
|
|
case EnumFileOfferPDU:
|
|
if (lpMBFTSession->IsReceiveSession())
|
|
{
|
|
MBFTPrivateReceive *pRecvSession = (MBFTPrivateReceive *) lpMBFTSession;
|
|
bWasHandled = pRecvSession->OnReceivedFileOfferPDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
NodeID,
|
|
(LPFILEOFFERPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEPDU(" File Offer PDU from [%u]\n",SenderID);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumFileAcceptPDU:
|
|
if (lpMBFTSession->IsSendSession())
|
|
{
|
|
MBFTPrivateSend *pSendSession = (MBFTPrivateSend *) lpMBFTSession;
|
|
bWasHandled = pSendSession->OnReceivedFileAcceptPDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPFILEACCEPTPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEPDU(" File Accept PDU from [%u]\n",SenderID);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumFileRejectPDU:
|
|
if (lpMBFTSession->IsSendSession())
|
|
{
|
|
MBFTPrivateSend *pSendSession = (MBFTPrivateSend *) lpMBFTSession;
|
|
bWasHandled = pSendSession->OnReceivedFileRejectPDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPFILEREJECTPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEPDU(" File Reject PDU from [%u]\n",SenderID);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumFileAbortPDU:
|
|
#ifdef ENABLE_CONDUCTORSHIP
|
|
if(m_bInConductedMode)
|
|
{
|
|
LPFILEABORTPDU lpAbortPDU = (LPFILEABORTPDU)lpNewPDU;
|
|
T120UserID MBFTUserID = lpAbortPDU->GetTransmitterID();
|
|
|
|
//MBFT 8.11.2
|
|
//If no MBFTUserID is specified, all providers must stop transmission...
|
|
|
|
if(!MBFTUserID)
|
|
{
|
|
AbortAllSends();
|
|
bWasHandled = TRUE;
|
|
}
|
|
else if(MBFTUserID == m_uidMyself)
|
|
{
|
|
//If only MBFTUserID is specified, all transmissions by that
|
|
//MBFT provider must cease....
|
|
|
|
if(!lpAbortPDU->GetFileHandle() && !lpAbortPDU->GetDataChannelID())
|
|
{
|
|
AbortAllSends();
|
|
bWasHandled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (lpMBFTSession->IsSendSession())
|
|
{
|
|
MBFTPrivateSend *pSendSession = (MBFTPrivateSend *) lpMBFTSession;
|
|
bWasHandled = pSendSession->OnReceivedFileAbortPDU(
|
|
wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPFILEABORTPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Message was not meant for us...
|
|
bWasHandled = TRUE;
|
|
}
|
|
}
|
|
else
|
|
#endif // ENABLE_CONDUCTORSHIP
|
|
{
|
|
bWasHandled = TRUE;
|
|
}
|
|
|
|
if(bWasHandled)
|
|
{
|
|
TRACEPDU(" File Abort PDU from [%u]\n",SenderID);
|
|
}
|
|
break;
|
|
|
|
case EnumFileStartPDU:
|
|
if (lpMBFTSession->IsReceiveSession())
|
|
{
|
|
MBFTPrivateReceive *pRecvSession = (MBFTPrivateReceive *) lpMBFTSession;
|
|
bWasHandled = pRecvSession->OnReceivedFileStartPDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPFILESTARTPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEPDU(" File Start PDU from [%u]\n",SenderID);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumFileDataPDU:
|
|
if (lpMBFTSession->IsReceiveSession())
|
|
{
|
|
MBFTPrivateReceive *pRecvSession = (MBFTPrivateReceive *) lpMBFTSession;
|
|
bWasHandled = pRecvSession->OnReceivedFileDataPDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPFILEDATAPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEPDU(" File Data PDU from [%u]\n",SenderID);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumPrivateChannelInvitePDU:
|
|
bWasHandled = TRUE;
|
|
TRACEPDU(" Private Channel Invite PDU from [%u]\n",SenderID);
|
|
break;
|
|
|
|
case EnumPrivateChannelResponsePDU:
|
|
if (lpMBFTSession->IsSendSession())
|
|
{
|
|
MBFTPrivateSend *pSendSession = (MBFTPrivateSend *) lpMBFTSession;
|
|
bWasHandled = pSendSession->OnReceivedPrivateChannelResponsePDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPPRIVATECHANNELRESPONSEPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEPDU(" Private Channel Response PDU from [%u]\n",SenderID);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumNonStandardPDU:
|
|
if (lpMBFTSession->IsSendSession())
|
|
{
|
|
MBFTPrivateSend *pSendSession = (MBFTPrivateSend *) lpMBFTSession;
|
|
bWasHandled = pSendSession->OnReceivedNonStandardPDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPNONSTANDARDPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEPDU(" Non Standard PDU from [%u]\n",SenderID);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EnumFileErrorPDU:
|
|
bWasHandled = lpMBFTSession->OnReceivedFileErrorPDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPFILEERRORPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEPDU(" File Error PDU from [%u]\n",SenderID);
|
|
}
|
|
break;
|
|
|
|
case EnumFileRequestPDU:
|
|
bWasHandled = OnReceivedFileRequestPDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPFILEREQUESTPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEPDU(" File Request PDU from [%u]\n",SenderID);
|
|
}
|
|
break;
|
|
|
|
case EnumFileDenyPDU:
|
|
TRACE(" *** WARNING (MBFT): Received File Deny PDU from [%u] *** \n",SenderID);
|
|
bWasHandled = TRUE;
|
|
break;
|
|
|
|
case EnumDirectoryRequestPDU:
|
|
bWasHandled = OnReceivedDirectoryRequestPDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPDIRECTORYREQUESTPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
if(bWasHandled)
|
|
{
|
|
TRACEPDU(" DirectoryRequest PDU from [%u]\n",SenderID);
|
|
}
|
|
break;
|
|
|
|
case EnumDirectoryResponsePDU:
|
|
TRACE(" *** WARNING (MBFT): Received Directory Response PDU from [%u] *** \n",SenderID);
|
|
bWasHandled = TRUE;
|
|
break;
|
|
|
|
case EnumPrivilegeAssignPDU:
|
|
bWasHandled = OnReceivedPrivilegeAssignPDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPPRIVILEGEASSIGNPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
break;
|
|
|
|
#if 0
|
|
//Do not delete this code...
|
|
//It may become part of the MBFT standard in the future...
|
|
|
|
case EnumFileEndAcknowledgePDU:
|
|
if (lpMBFTSession->IsSendSession())
|
|
{
|
|
MBFTPrivateSend *pSendSession = (MBFTPrivateSend *) lpMBFTSession;
|
|
bWasHandled = pSendSession->OnReceivedFileEndAcknowledgePDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPFILEENDACKNOWLEDGEPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
}
|
|
break;
|
|
|
|
case EnumChannelLeavePDU:
|
|
if (lpMBFTSession->IsSendSession())
|
|
{
|
|
MBFTPrivateSend *pSendSession = (MBFTPrivateSend *) lpMBFTSession;
|
|
bWasHandled = pSendSession->OnReceivedChannelLeavePDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPCHANNELLEAVEPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
}
|
|
break;
|
|
//Do not delete this code...
|
|
//It may become part of the MBFT standard in the future...
|
|
#endif
|
|
|
|
default:
|
|
TRACE(" *** WARNING (MBFT): Unhandled PDU from [%u] *** \n",SenderID);
|
|
bWasHandled = TRUE; // LONCHANC: this should be false, right? why true?
|
|
break;
|
|
} // switch
|
|
|
|
return(bWasHandled);
|
|
}
|
|
|
|
|
|
BOOL MBFTEngine::OnReceivedPrivateChannelInvitePDU(T120ChannelID wChannelID,
|
|
T120Priority iPriority,
|
|
T120UserID SenderID,
|
|
LPPRIVATECHANNELINVITEPDU lpNewPDU,
|
|
BOOL IsUniformSendData)
|
|
{
|
|
if(m_State == IdleInitialized)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
MBFTMsg *pMsg = new CreateSessionMsg(MBFT_PRIVATE_RECV_TYPE,
|
|
::GetNewEventHandle(),
|
|
0,
|
|
lpNewPDU->GetControlChannel(),
|
|
lpNewPDU->GetDataChannel());
|
|
if (NULL != pMsg)
|
|
{
|
|
DoStateMachine(pMsg);
|
|
delete pMsg;
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOL MBFTEngine::OnReceivedFileRequestPDU(T120ChannelID wChannelId,
|
|
T120Priority iPriority,
|
|
T120UserID SenderID,
|
|
LPFILEREQUESTPDU lpNewPDU,
|
|
BOOL IsUniformSendData)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
DBG_SAVE_FILE_LINE
|
|
LPFILEDENYPDU lpDenyPDU = new FileDenyPDU(lpNewPDU->GetRequestHandle());
|
|
if(lpDenyPDU)
|
|
{
|
|
if(lpDenyPDU->Encode())
|
|
{
|
|
if (SendDataRequest(SenderID, APPLET_HIGH_PRIORITY,
|
|
(LPBYTE)lpDenyPDU->GetBuffer(),
|
|
lpDenyPDU->GetBufferLength()))
|
|
{
|
|
bReturn = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(bReturn);
|
|
}
|
|
|
|
BOOL MBFTEngine::OnReceivedDirectoryRequestPDU(T120ChannelID wChannelId,
|
|
T120Priority iPriority,
|
|
T120UserID SenderID,
|
|
LPDIRECTORYREQUESTPDU lpNewPDU,
|
|
BOOL IsUniformSendData)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
DBG_SAVE_FILE_LINE
|
|
LPDIRECTORYRESPONSEPDU lpDirPDU = new DirectoryResponsePDU();
|
|
if(lpDirPDU)
|
|
{
|
|
if(lpDirPDU->Encode())
|
|
{
|
|
if (SendDataRequest(SenderID, APPLET_HIGH_PRIORITY,
|
|
(LPBYTE)lpDirPDU->GetBuffer(),
|
|
lpDirPDU->GetBufferLength()))
|
|
{
|
|
bReturn = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(bReturn);
|
|
}
|
|
|
|
BOOL MBFTEngine::OnReceivedPrivilegeAssignPDU(T120ChannelID wChannelId,
|
|
T120Priority iPriority,
|
|
T120UserID SenderID,
|
|
LPPRIVILEGEASSIGNPDU lpNewPDU,
|
|
BOOL IsUniformSendData)
|
|
{
|
|
#ifdef ENABLE_CONDUCTORSHIP
|
|
if(m_bInConductedMode)
|
|
{
|
|
m_ConductedModePermission = lpNewPDU->GetPrivilegeWord();
|
|
}
|
|
#endif
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
#ifdef ENABLE_CONDUCTORSHIP
|
|
void MBFTEngine::ApplyForPermission(void)
|
|
{
|
|
//m_bWaitingForPermission is set to make sure that we don't keep
|
|
//reapplying for permission until the conductor changes...
|
|
|
|
if(!m_bWaitingForPermission && m_bInConductedMode)
|
|
{
|
|
//MBFT 8.11.1
|
|
//If there is a MBFT conductor at the conducting node, we send
|
|
//a PrivilegeRequestPDU to the conductor....
|
|
|
|
if(m_MBFTConductorID)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
PrivilegeRequestPDU * lpNewPDU = new PrivilegeRequestPDU(PrivilegeRequestPDU::EnumFileTransfer |
|
|
PrivilegeRequestPDU::EnumPrivateChannel |
|
|
PrivilegeRequestPDU::EnumNonStandard);
|
|
if(lpNewPDU)
|
|
{
|
|
if(lpNewPDU->Encode())
|
|
{
|
|
if (SendDataRequest(m_MBFTConductorID, APPLET_HIGH_PRIORITY,
|
|
(LPBYTE)lpNewPDU->GetBuffer(),
|
|
lpNewPDU->GetBufferLength()))
|
|
{
|
|
m_bWaitingForPermission = TRUE;
|
|
}
|
|
}
|
|
|
|
delete lpNewPDU;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//MBFT 8.11.2
|
|
//Ask for permission via Node Controller...
|
|
}
|
|
}
|
|
}
|
|
#endif // ENABLE_CONDUCTORSHIP
|
|
|
|
|
|
BOOL MBFTEngine::DoStateMachine(MBFTMsg *pMsg)
|
|
{
|
|
BOOL fDeleteThisMessage = TRUE;
|
|
if (m_fConfAvailable)
|
|
{
|
|
BOOL fHandled = (NULL != pMsg) ? HandleSessionCreation(pMsg) : FALSE;
|
|
|
|
#ifdef ENABLE_CONDUCTORSHIP
|
|
//Logic: If we are in the conducted mode, we check to see if
|
|
// we have sufficient privileges. If not, we make
|
|
// an attempt to secure the requisite privileges....
|
|
if(m_bInConductedMode)
|
|
{
|
|
if(!ConductedModeOK())
|
|
{
|
|
if(!m_bWaitingForPermission)
|
|
{
|
|
ApplyForPermission();
|
|
}
|
|
}
|
|
}
|
|
#endif // ENABLE_CONDUCTORSHIP
|
|
|
|
if (NULL != pMsg && ! fHandled)
|
|
{
|
|
fDeleteThisMessage = ProcessMessage(pMsg);
|
|
}
|
|
|
|
if (m_State == IdleInitialized && ! m_SessionList.IsEmpty())
|
|
{
|
|
CSessionList SessionListCopy(&m_SessionList);
|
|
MBFTSession *pSession;
|
|
while (NULL != (pSession = SessionListCopy.Get()))
|
|
{
|
|
pSession->DoStateMachine();
|
|
}
|
|
}
|
|
}
|
|
return fDeleteThisMessage;
|
|
}
|
|
|
|
|
|
//
|
|
// T120 Callback
|
|
//
|
|
|
|
|
|
void MBFTEngine::OnSendDataIndication
|
|
(
|
|
BOOL IsUniformSendData,
|
|
T120UserID SenderID,
|
|
T120ChannelID wChannelID,
|
|
T120Priority iPriority,
|
|
ULONG ulDataLength,
|
|
LPBYTE lpBuffer
|
|
)
|
|
{
|
|
GenericPDU * lpNewPDU = NULL;
|
|
LPCSTR lpDecodeBuffer = NULL;
|
|
BOOL bAddToPendingList = FALSE;
|
|
|
|
{
|
|
MBFTPDUType DecodedPDUType = GenericPDU::DecodePDU(
|
|
(LPSTR) lpBuffer,
|
|
ulDataLength,
|
|
&lpNewPDU,
|
|
&lpDecodeBuffer,
|
|
m_uidMyself,
|
|
m_pAppletSession);
|
|
if(DecodedPDUType != EnumUnknownPDU)
|
|
{
|
|
ASSERT (m_pAppletSession != NULL);
|
|
DBG_SAVE_FILE_LINE
|
|
MBFTPDUMsg * lpNewMessage = new MBFTPDUMsg(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
lpNewPDU,
|
|
IsUniformSendData,
|
|
DecodedPDUType,
|
|
(LPSTR)lpDecodeBuffer);
|
|
|
|
//Now that we have received a valid PDU, we must make sure that
|
|
//we know about this particular MBFT peer. If not, we add the PDU
|
|
//message to a different list....
|
|
|
|
if(IsValidPeerID(SenderID) && m_State == IdleInitialized)
|
|
{
|
|
//If the FileOffer is received on the default Control channel, it
|
|
//cannot be a private subsession send. Therefore, we create a special
|
|
//receive session to handle this case....
|
|
#ifdef USE_BROADCAST_RECEIVE
|
|
if(DecodedPDUType == EnumFileOfferPDU && wChannelID == m_MBFTControlChannel)
|
|
{
|
|
FileOfferPDU * lpFileOffer = (FileOfferPDU *)lpNewPDU;
|
|
|
|
DBG_SAVE_FILE_LINE
|
|
MBFTMsg *pMsg = new CreateSessionMsg(MBFT_BROADCAST_RECV_TYPE,
|
|
::GetNewEventHandle(),
|
|
0,
|
|
m_MBFTControlChannel,
|
|
lpFileOffer->GetDataChannelID(),
|
|
SenderID,
|
|
lpFileOffer->GetFileHandle());
|
|
if (NULL != pMsg)
|
|
{
|
|
DoStateMachine(pMsg);
|
|
delete pMsg;
|
|
}
|
|
}
|
|
else
|
|
#endif // USE_BROADCAST_RECEIVE
|
|
|
|
if(DecodedPDUType == EnumPrivateChannelInvitePDU && wChannelID == m_uidMyself)
|
|
{
|
|
//In theory, the PrivateChannelInvitePDU marks the beginning of
|
|
//a PrivateSubsession receive. Therefore, we create one to handle all subsequent
|
|
//notifications....
|
|
|
|
OnReceivedPrivateChannelInvitePDU(wChannelID,
|
|
iPriority,
|
|
SenderID,
|
|
(LPPRIVATECHANNELINVITEPDU)lpNewPDU,
|
|
IsUniformSendData);
|
|
}
|
|
|
|
SafePostMessage(lpNewMessage);
|
|
} // if(IsValidPeerID(SenderID))
|
|
else
|
|
{
|
|
WARNING_OUT((" Received PDU from unknown peer [%u], adding to pending message list\n", (UINT) SenderID));
|
|
delete lpNewMessage;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRACE(" PDU Decoding Error or Invalid PDU\n");
|
|
|
|
}
|
|
|
|
// Unless this is one of the special 3 types of PDUs, we also
|
|
// need to free the MCS buffer. In the 3 special cases, the PDUs
|
|
// are responsible for freeing the buffer when they are done.
|
|
if ((DecodedPDUType != EnumFileDataPDU) &&
|
|
(DecodedPDUType != EnumNonStandardPDU) &&
|
|
(DecodedPDUType != EnumFileStartPDU))
|
|
{
|
|
m_pAppletSession->FreeSendDataBuffer((void *) lpBuffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void MBFTEngine::OnRosterReportIndication
|
|
(
|
|
ULONG cRosters,
|
|
GCCAppRoster *aAppRosters[] // array, size_is(cRosters)
|
|
)
|
|
{
|
|
TRACEGCC(" RosterReport: Session count %u\n", (UINT) cRosters);
|
|
|
|
UINT Index, PeerIndex, CapIndex;
|
|
LPCSTR lpszAppKey = NULL;
|
|
BOOL fConductorFound = FALSE;
|
|
|
|
CPeerList NewPeerList;
|
|
CPeerData *pOldPeer;
|
|
|
|
if (0 == cRosters) // not bloody likely
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (Index = 0; Index < cRosters; Index++ )
|
|
{
|
|
GCCAppRoster *pRoster = aAppRosters[Index];
|
|
if (pRoster->session_key.session_id != m_SessionID)
|
|
{
|
|
// this roster is not for our session...ignore it
|
|
continue;
|
|
}
|
|
|
|
//Added by Atul on 7/18 to fix missing roster instance bug...
|
|
m_nRosterInstance = pRoster->instance_number;
|
|
|
|
TRACEGCC( " Peer count [%u]\n", (UINT) pRoster->number_of_records );
|
|
|
|
for (PeerIndex = 0; PeerIndex < pRoster->number_of_records; PeerIndex++)
|
|
{
|
|
GCCAppRecord *pRecord = pRoster->application_record_list[PeerIndex];
|
|
lpszAppKey = NULL;
|
|
|
|
TRACE( "Local Entity ID [%u], Entity ID [%u], Node ID [%u], MBFTUser ID [%u]\n",
|
|
(UINT) m_eidMyself,
|
|
(UINT) pRecord->entity_id,
|
|
(UINT) pRecord->node_id,
|
|
(UINT) pRecord->application_user_id );
|
|
|
|
BOOL IsProshareNode = FALSE;
|
|
BOOL bEOFAcknowledgment = FALSE;
|
|
|
|
if (0 == Index)
|
|
{
|
|
for (CapIndex=0; CapIndex < pRoster->number_of_capabilities; CapIndex++)
|
|
{
|
|
GCCAppCap *pCap = pRoster->capabilities_list[CapIndex];
|
|
if (GCC_STANDARD_CAPABILITY != pCap->capability_id.capability_id_type)
|
|
{
|
|
continue;
|
|
}
|
|
switch (pCap->capability_id.standard_capability)
|
|
{
|
|
case _MBFT_MAX_FILE_SIZE_ID:
|
|
m_MBFTMaxFileSize = pCap->capability_class.nMinOrMax;
|
|
TRACEGCC( "max file size set to %u\n", (UINT) m_MBFTMaxFileSize );
|
|
break;
|
|
|
|
case _MBFT_MAX_DATA_PAYLOAD_ID:
|
|
m_MBFTMaxDataPayload = _iMBFT_DEFAULT_MAX_FILEDATA_PDU_LENGTH;
|
|
if (pCap->number_of_entities == pRoster->number_of_records)
|
|
{
|
|
m_MBFTMaxDataPayload = pCap->capability_class.nMinOrMax;
|
|
}
|
|
TRACEGCC( "max data payload set to %u\n", (UINT) m_MBFTMaxDataPayload );
|
|
break;
|
|
|
|
case _MBFT_V42_COMPRESSION_ID:
|
|
m_bV42CompressionSupported = (BOOL) (pCap->number_of_entities == pRoster->number_of_records);
|
|
TRACEGCC( "V.42bis compression is now %ssupported\n", m_bV42CompressionSupported ? "" : "not " );
|
|
break;
|
|
}
|
|
} // for CapIndex
|
|
} // if 0 == Index
|
|
|
|
// TODO: only check for 'ProShare node' if this node is new to us
|
|
for (CapIndex = 0; CapIndex < pRecord->number_of_non_collapsed_caps; CapIndex++)
|
|
{
|
|
GCCNonCollCap *pCap2 = pRecord->non_collapsed_caps_list[CapIndex];
|
|
if (GCC_STANDARD_CAPABILITY == pCap2->capability_id.capability_id_type)
|
|
{
|
|
if (_iMBFT_FIRST_PROSHARE_CAPABILITY_ID == pCap2->capability_id.standard_capability)
|
|
{
|
|
LPSTR pszData = (LPSTR) pCap2->application_data->value;
|
|
if (pCap2->application_data->length > sizeof(PROSHARE_STRING))
|
|
{
|
|
if (0 == ::memcmp(pszData, PROSHARE_STRING, sizeof(PROSHARE_STRING)))
|
|
{
|
|
IsProshareNode = TRUE;
|
|
lpszAppKey = &pszData[sizeof(PROSHARE_STRING)];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if (_iMBFT_PROSHARE_FILE_EOF_ACK_ID == pCap2->capability_id.standard_capability)
|
|
{
|
|
LPSTR pszData = (LPSTR) pCap2->application_data->value;
|
|
if (pCap2->application_data->length >= sizeof(PROSHARE_FILE_END_STRING) - 1)
|
|
{
|
|
if (0 == ::memcmp(pszData, PROSHARE_FILE_END_STRING, sizeof(PROSHARE_FILE_END_STRING) - 1))
|
|
{
|
|
bEOFAcknowledgment = TRUE;
|
|
}
|
|
}
|
|
}
|
|
} // if std cap
|
|
} // for CapIndex
|
|
|
|
BOOL IsLocalNode = (m_eidMyself == pRecord->entity_id) && (m_nidMyself == pRecord->node_id);
|
|
|
|
if( ( IdleNotInitialized == m_State )
|
|
&& IsLocalNode
|
|
&& pRecord->is_enrolled_actively )
|
|
{
|
|
m_State = IdleInitialized;
|
|
// m_uidMyself = pRecord->application_user_id;
|
|
m_MBFTControlChannel = m_SessionID;
|
|
}
|
|
|
|
#ifdef ENABLE_CONDUCTORSHIP
|
|
if( m_bInConductedMode )
|
|
{
|
|
if (pRecord->node_id == m_ConductorNodeID &&
|
|
pRecord->is_conducting_capable)
|
|
{
|
|
//Now that we have found a conductor on the conducting node,
|
|
//our search is over....
|
|
|
|
//Make sure that the previously assigned conductor is still
|
|
//present in the roster report...
|
|
|
|
if( m_MBFTConductorID )
|
|
{
|
|
if( m_MBFTConductorID == pRecord->application_user_id )
|
|
{
|
|
fConductorFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//First time conductor assignment.....
|
|
m_MBFTConductorID = pRecord->application_user_id;
|
|
fConductorFound = TRUE;
|
|
if(m_ConductorNodeID != m_nidMyself)
|
|
{
|
|
m_ConductedModePermission = 0;
|
|
m_bWaitingForPermission = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif // ENABLE_CONDUCTORSHIP
|
|
|
|
// build a new peer list
|
|
if (pRecord->is_enrolled_actively)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
CPeerData *lpPeer = new CPeerData(
|
|
pRecord->node_id,
|
|
pRecord->application_user_id,
|
|
IsLocalNode,
|
|
IsProshareNode,
|
|
pRecord->is_conducting_capable,
|
|
bEOFAcknowledgment,
|
|
lpszAppKey,
|
|
(DWORD)((pRecord->node_id == m_nidMyself)?((VER_PRODUCTVERSION_DW&0xffff0000)>>16):
|
|
T120_GetNodeVersion(m_nConfID, pRecord->node_id)));
|
|
if (NULL == lpPeer)
|
|
{
|
|
ASSERT(0);
|
|
return;
|
|
}
|
|
NewPeerList.Append(lpPeer);
|
|
pOldPeer = m_PeerList.FindSamePeer(lpPeer);
|
|
if (NULL != pOldPeer)
|
|
{
|
|
// we already new about this peer
|
|
m_PeerList.Delete(pOldPeer);
|
|
}
|
|
else
|
|
{
|
|
// this is a new peer
|
|
AddPeerNotification(
|
|
pRecord->node_id,
|
|
pRecord->application_user_id,
|
|
IsLocalNode,
|
|
IsProshareNode,
|
|
TRUE,
|
|
lpszAppKey ? lpszAppKey : "", // TODO: address appkey issue here; needed?
|
|
pRoster->session_key.session_id );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef ENABLE_CONDUCTORSHIP
|
|
//If we are on the conducting node, we need no privileges...
|
|
if (m_bInConductedMode && (m_ConductorNodeID != m_nidMyself))
|
|
{
|
|
//MBFT 8.11.1
|
|
//If the previously assigned conductor is not present in the roster report,
|
|
//all privileges are revoked and we should abort all sends...
|
|
if( !fConductorFound )
|
|
{
|
|
AbortAllSends();
|
|
}
|
|
}
|
|
#endif // ENABLE_CONDUCTORSHIP
|
|
|
|
while (NULL != (pOldPeer = m_PeerList.Get()))
|
|
{
|
|
AddPeerNotification(
|
|
pOldPeer->GetNodeID(),
|
|
pOldPeer->GetUserID(),
|
|
pOldPeer->GetIsLocalNode(),
|
|
pOldPeer->GetIsProshareNode(),
|
|
FALSE,
|
|
MY_APP_STR,
|
|
m_SessionID );
|
|
|
|
DBG_SAVE_FILE_LINE
|
|
CPeerData *p = new CPeerData(
|
|
pOldPeer->GetNodeID(),
|
|
pOldPeer->GetUserID(),
|
|
pOldPeer->GetIsLocalNode(),
|
|
pOldPeer->GetIsProshareNode(),
|
|
pOldPeer->GetCanConduct(),
|
|
pOldPeer->GetEOFAcknowledge(),
|
|
pOldPeer->GetAppKey(),
|
|
pOldPeer->GetVersion());
|
|
ASSERT(NULL != p);
|
|
if (p)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
SafePostMessage(new PeerDeletedMsg(p));
|
|
}
|
|
TRACEGCC("Peer Removed: Node [%u], UserID [%u]\n", pOldPeer->GetNodeID(), pOldPeer->GetUserID() );
|
|
delete pOldPeer;
|
|
}
|
|
|
|
while (NULL != (pOldPeer = NewPeerList.Get()))
|
|
{
|
|
m_PeerList.Append(pOldPeer);
|
|
}
|
|
|
|
// notify UI of new rosters
|
|
if (NULL != m_pWindow)
|
|
{
|
|
m_pWindow->UpdateUI();
|
|
}
|
|
}
|
|
|
|
|
|
void MBFTEngine::OnChannelAdmitIndication
|
|
(
|
|
T120ChannelID nChannelID,
|
|
T120UserID nManagerID
|
|
)
|
|
{
|
|
if (IsValidPeerID(nManagerID) && m_State == IdleInitialized)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
SafePostMessage(new MCSChannelAdmitIndicationMsg(nChannelID, nManagerID));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CALLBACK T120Callback
|
|
(
|
|
T120AppletSessionMsg *pMsg
|
|
)
|
|
{
|
|
MBFTEngine *pEngine = (MBFTEngine *) pMsg->pSessionContext;
|
|
ASSERT(NULL != pEngine);
|
|
|
|
BOOL fSuccess;
|
|
T120ChannelID nChannelID;
|
|
|
|
switch (pMsg->eMsgType)
|
|
{
|
|
case T120_JOIN_SESSION_CONFIRM:
|
|
pEngine->OnJoinSessionConfirm(&pMsg->JoinSessionConfirm);
|
|
break;
|
|
|
|
case GCC_APP_ROSTER_REPORT_INDICATION:
|
|
pEngine->OnRosterReportIndication(pMsg->AppRosterReportInd.cRosters,
|
|
pMsg->AppRosterReportInd.apAppRosters);
|
|
break;
|
|
|
|
// case GCC_APPLICATION_INVOKE_CONFIRM:
|
|
// break;
|
|
|
|
case MCS_SEND_DATA_INDICATION:
|
|
case MCS_UNIFORM_SEND_DATA_INDICATION:
|
|
pEngine->OnSendDataIndication(
|
|
(pMsg->eMsgType == MCS_UNIFORM_SEND_DATA_INDICATION),
|
|
pMsg->SendDataInd.initiator,
|
|
pMsg->SendDataInd.channel_id,
|
|
(T120Priority) pMsg->SendDataInd.data_priority,
|
|
pMsg->SendDataInd.user_data.length,
|
|
pMsg->SendDataInd.user_data.value);
|
|
break;
|
|
|
|
case MCS_CHANNEL_JOIN_CONFIRM:
|
|
fSuccess = (T120_RESULT_SUCCESSFUL == pMsg->ChannelConfirm.eResult);
|
|
DBG_SAVE_FILE_LINE
|
|
pEngine->SafePostMessage(new MCSChannelJoinConfirmMsg(pMsg->ChannelConfirm.nChannelID, fSuccess));
|
|
break;
|
|
|
|
case MCS_CHANNEL_CONVENE_CONFIRM:
|
|
fSuccess = (T120_RESULT_SUCCESSFUL == pMsg->ChannelConfirm.eResult);
|
|
DBG_SAVE_FILE_LINE
|
|
pEngine->SafePostMessage(new MCSChannelConveneConfirmMsg(pMsg->ChannelConfirm.nChannelID, fSuccess));
|
|
break;
|
|
|
|
// case MCS_CHANNEL_LEAVE_INDICATION:
|
|
// break;
|
|
|
|
// case MCS_CHANNEL_DISBAND_INDICATION:
|
|
// break;
|
|
|
|
case MCS_CHANNEL_ADMIT_INDICATION:
|
|
pEngine->OnChannelAdmitIndication(pMsg->ChannelInd.nChannelID, pMsg->ChannelInd.nManagerID);
|
|
break;
|
|
|
|
case MCS_CHANNEL_EXPEL_INDICATION:
|
|
DBG_SAVE_FILE_LINE
|
|
pEngine->SafePostMessage(new MCSChannelExpelIndicationMsg(pMsg->ChannelInd.nChannelID, pMsg->ChannelInd.eReason));
|
|
break;
|
|
|
|
// case MCS_TOKEN_GRAB_CONFIRM:
|
|
// case MCS_TOKEN_INHIBIT_CONFIRM:
|
|
// case MCS_TOKEN_GIVE_CONFIRM:
|
|
// case MCS_TOKEN_RELEASE_CONFIRM:
|
|
// case MCS_TOKEN_TEST_CONFIRM:
|
|
// break;
|
|
|
|
// case MCS_TOKEN_GIVE_INDICATION:
|
|
// case MCS_TOKEN_PLEASE_INDICATION:
|
|
// case MCS_TOKEN_RELEASE_INDICATION:
|
|
// break;
|
|
|
|
case MCS_DETACH_USER_INDICATION:
|
|
pEngine->OnDetachUserIndication(pMsg->DetachUserInd.nUserID, pMsg->DetachUserInd.eReason);
|
|
break;
|
|
|
|
case MCS_TRANSMIT_BUFFER_AVAILABLE_INDICATION:
|
|
g_fWaitingForBufferAvailable = FALSE;
|
|
::PostMessage(g_pFileXferApplet->GetHiddenWnd(),
|
|
MBFTMSG_HEART_BEAT, 0, (LPARAM) pEngine);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL MBFTEngine::SimpleChannelRequest
|
|
(
|
|
AppletChannelCommand eCommand,
|
|
T120ChannelID nChannelID
|
|
)
|
|
{
|
|
T120ChannelRequest req;
|
|
::ZeroMemory(&req, sizeof(req));
|
|
req.eCommand = eCommand;
|
|
req.nChannelID = nChannelID;
|
|
T120Error rc = m_pAppletSession->ChannelRequest(&req);
|
|
return (T120_NO_ERROR == rc);
|
|
}
|
|
|
|
T120NodeID MBFTEngine::GetNodeIdByUserID(T120UserID nUserID)
|
|
{
|
|
CPeerData *p;
|
|
m_PeerList.Reset();
|
|
while (NULL != (p = m_PeerList.Iterate()))
|
|
{
|
|
if (nUserID == p->GetUserID())
|
|
{
|
|
return p->GetNodeID();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
BOOL MBFTEngine::MCSChannelAdmitRequest
|
|
(
|
|
T120ChannelID nChannelID,
|
|
T120UserID *aUsers,
|
|
ULONG cUsers
|
|
)
|
|
{
|
|
T120ChannelRequest req;
|
|
::ZeroMemory(&req, sizeof(req));
|
|
req.eCommand = APPLET_ADMIT_CHANNEL;
|
|
req.nChannelID = nChannelID;
|
|
req.cUsers = cUsers;
|
|
req.aUsers = aUsers;
|
|
T120Error rc = m_pAppletSession->ChannelRequest(&req);
|
|
return (T120_NO_ERROR == rc);
|
|
}
|
|
|
|
BOOL MBFTEngine::SendDataRequest
|
|
(
|
|
T120ChannelID nChannelID,
|
|
T120Priority ePriority,
|
|
LPBYTE pBuffer,
|
|
ULONG cbBufSize
|
|
)
|
|
{
|
|
if (m_eLastSendDataError == MCS_TRANSMIT_BUFFER_FULL)
|
|
{
|
|
if (g_fWaitingForBufferAvailable == FALSE)
|
|
{
|
|
m_eLastSendDataError = MCS_NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
TRACEMCS("MBFTEngine::SendDataReques still waiting for a MCS_TRANSMIT_BUFFER_AVAILABLE_INDICATION");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
m_eLastSendDataError = m_pAppletSession->SendData(
|
|
NORMAL_SEND_DATA, nChannelID, ePriority,
|
|
pBuffer, cbBufSize, APP_ALLOCATION);
|
|
//
|
|
// T120 is busy and can't allocate data
|
|
//
|
|
if (m_eLastSendDataError == MCS_TRANSMIT_BUFFER_FULL)
|
|
{
|
|
g_fWaitingForBufferAvailable = TRUE;
|
|
TRACEMCS("MCSSendDataRequest failed we will not send data until we get a MCS_TRANSMIT_BUFFER_AVAILABLE_INDICATION");
|
|
}
|
|
|
|
return (T120_NO_ERROR == m_eLastSendDataError);
|
|
}
|
|
|
|
|
|
//
|
|
// CPeerList
|
|
//
|
|
|
|
CPeerData * CPeerList::Find(T120NodeID nNodeID)
|
|
{
|
|
CPeerData *p;
|
|
Reset();
|
|
while (NULL != (p = Iterate()))
|
|
{
|
|
if (p->GetUserID() == nNodeID)
|
|
{
|
|
return p;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
CPeerData * CPeerList::FindSamePeer(CPeerData *pPeer)
|
|
{
|
|
CPeerData *p;
|
|
Reset();
|
|
while (NULL != (p = Iterate()))
|
|
{
|
|
if (pPeer->GetNodeID() == p->GetNodeID() && pPeer->GetUserID() == p->GetUserID())
|
|
{
|
|
return p;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void CPeerList::Delete(CPeerData *p)
|
|
{
|
|
if (Remove(p))
|
|
{
|
|
delete p;
|
|
}
|
|
}
|
|
|
|
void CPeerList::DeleteAll(void)
|
|
{
|
|
CPeerData *p;
|
|
while (NULL != (p = Get()))
|
|
{
|
|
delete p;
|
|
}
|
|
}
|
|
|
|
|
|
void CSessionList::Delete(MBFTSession *p)
|
|
{
|
|
if (Remove(p))
|
|
{
|
|
delete p;
|
|
}
|
|
}
|
|
|
|
|
|
// thought it is a pure virtual, we still need a destructor
|
|
MBFTSession::~MBFTSession(void) { }
|
|
|
|
|
|
HRESULT MBFTEngine::SafePostNotifyMessage(MBFTMsg *p)
|
|
{
|
|
// notify applet UI if it exists
|
|
if (NULL != m_pWindow)
|
|
{
|
|
m_pWindow->OnEngineNotify(p);
|
|
}
|
|
|
|
if (NULL != m_pMBFTIntf)
|
|
{
|
|
return m_pMBFTIntf->SafePostNotifyMessage(p);
|
|
}
|
|
|
|
delete p;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
MBFTEVENTHANDLE GetNewEventHandle(void)
|
|
{
|
|
static ULONG s_nEventHandle = 0x55AA;
|
|
ULONG nEvtHdl;
|
|
|
|
::EnterCriticalSection(&g_csWorkThread);
|
|
if (s_nEventHandle > 0xFFFF)
|
|
{
|
|
s_nEventHandle = 0x55AA;
|
|
}
|
|
nEvtHdl = s_nEventHandle++;
|
|
::LeaveCriticalSection(&g_csWorkThread);
|
|
|
|
return nEvtHdl;
|
|
}
|
|
|
|
|
|
MBFTFILEHANDLE GetNewFileHandle(void)
|
|
{
|
|
static ULONG s_nFileHandle = 1;
|
|
ULONG nFileHdl;
|
|
|
|
::EnterCriticalSection(&g_csWorkThread);
|
|
if (s_nFileHandle > 0xFFFF)
|
|
{
|
|
s_nFileHandle = 0x1;
|
|
}
|
|
nFileHdl = s_nFileHandle++;
|
|
::LeaveCriticalSection(&g_csWorkThread);
|
|
|
|
return nFileHdl;
|
|
}
|
|
|
|
|
|
|