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

1720 lines
53 KiB

/* file: mbftsend.cpp */
#include "mbftpch.h"
#include "mbftsend.hpp"
#include "fileio.hpp"
#include "messages.hpp"
#include "mbftapi.hpp"
#define _MAX_SEND_PACKETS 1
ULONG g_nSendDisbandDelay = 5000; // Previous: Twenty seconds!
ULONG g_nChannelResponseDelay = 60000;
MBFTPrivateSend::MBFTPrivateSend
(
LPMBFTENGINE lpParentEngine,
MBFTEVENTHANDLE EventHandle,
T120ChannelID wMBFTUserID,
ULONG MaxDataLength
)
:
MBFTSession(lpParentEngine, EventHandle, MBFT_PRIVATE_SEND_TYPE),
m_PrivateMBFTControlChannel(0),
m_PrivateMBFTDataChannel(0),
m_lpUserArray(NULL),
m_lpAcceptedUsersArray(NULL),
m_iUserCount(0),
m_MBFTChannelID(wMBFTUserID),
m_MaxDataLength(MaxDataLength),
m_LastUserCount(0),
m_ResponseCount(0),
m_AcceptCount(0),
m_RejectCount(0),
m_AbortedCount(0),
m_AcknowledgeCount(0),
m_CurrentFileSize(0),
m_lTotalBytesRead(0),
m_lpDataBuffer(NULL),
m_bProshareTransfer(FALSE),
m_bEOFAcknowledge(FALSE),
m_lpFile(NULL),
m_pszCurrentFilePath(NULL),
m_CurrentFileHandle(0),
m_AcceptedIndex(0),
m_bSentFileOfferPDU(FALSE),
m_bUnInitializing(FALSE),
m_bAbortAllFiles(FALSE),
m_bSendingFile(FALSE),
m_bAbortFileSend(FALSE),
m_SentFileStartPDU(FALSE),
m_TimeOutValue(0),
m_bCompressFiles(FALSE),
m_bOKToDisbandChannel(TRUE),
m_lpV42bisPointer(NULL),
m_bFlushv42Compression(FALSE),
m_bEventEndPosted(FALSE),
m_State(EnumIdleNotInitialized)
{
}
MBFTPrivateSend::~MBFTPrivateSend(void)
{
delete m_pszCurrentFilePath;
delete m_lpUserArray;
delete m_lpAcceptedUsersArray;
delete m_lpDataBuffer;
delete m_lpFile;
}
void MBFTPrivateSend::ConveneControlChannel(void)
{
if(m_lpParentEngine->MCSChannelConveneRequest())
{
m_State = EnumWaitConveneControlChannel;
}
else
{
ReportError(MBFT_PERMANENT_ERROR,iMBFT_UNKNOWN_ERROR,TRUE);
UnInitialize();
}
}
void MBFTPrivateSend::ConveneDataChannel(void)
{
if(m_lpParentEngine->MCSChannelConveneRequest())
{
m_State = EnumWaitConveneDataChannel;
}
else
{
ReportError(MBFT_PERMANENT_ERROR,iMBFT_UNKNOWN_ERROR,TRUE);
UnInitialize();
}
}
void MBFTPrivateSend::JoinControlChannel(void)
{
if(m_lpParentEngine->MCSChannelJoinRequest(m_PrivateMBFTControlChannel))
{
m_State = EnumWaitJoinControlChannel;
}
else
{
ReportError(MBFT_PERMANENT_ERROR,iMBFT_UNKNOWN_ERROR,TRUE);
UnInitialize();
}
}
BOOL MBFTPrivateSend::OnMCSChannelJoinConfirm
(
T120ChannelID wChannelId,
BOOL bSuccess
)
{
BOOL bReturn = FALSE;
if(wChannelId == m_PrivateMBFTControlChannel)
{
if(m_State == EnumWaitJoinControlChannel)
{
if(bSuccess)
{
TRACESEND(" Control channel joined [%u]\n",wChannelId);
ConveneDataChannel();
}
else
{
ReportError(MBFT_PERMANENT_ERROR,iMBFT_UNKNOWN_ERROR,TRUE);
UnInitialize();
}
bReturn = TRUE;
}
}
return(bReturn);
}
void MBFTPrivateSend::AdmitControlChannel(void)
{
if(m_lpParentEngine->MCSChannelAdmitRequest(m_PrivateMBFTControlChannel,
m_lpUserArray,
m_iUserCount))
{
TRACESEND(" Admit Control Channel Successful [%u]\n",m_PrivateMBFTControlChannel);
}
else
{
ReportError(MBFT_PERMANENT_ERROR,iMBFT_UNKNOWN_ERROR,TRUE);
UnInitialize();
}
if(m_lpParentEngine->MCSChannelAdmitRequest(m_PrivateMBFTDataChannel,
m_lpUserArray,
m_iUserCount))
{
TRACESEND(" Admit Data Channel Successful [%u]\n",m_PrivateMBFTDataChannel);
m_State = EnumWaitChannelResponsePDU;
m_TimeOutValue = GetTickCount() + g_nChannelResponseDelay;
}
else
{
ReportError(MBFT_PERMANENT_ERROR,iMBFT_UNKNOWN_ERROR,TRUE);
UnInitialize();
}
}
BOOL MBFTPrivateSend::OnMCSChannelConveneConfirm
(
T120ChannelID wChannelId,
BOOL bSuccess
)
{
BOOL bReturn = FALSE;
if(m_State == EnumWaitConveneControlChannel)
{
if(bSuccess)
{
TRACESEND(" Control channel convened [%u]\n",wChannelId);
m_PrivateMBFTControlChannel = wChannelId;
JoinControlChannel();
}
else
{
ReportError(MBFT_PERMANENT_ERROR,iMBFT_UNKNOWN_ERROR,TRUE);
UnInitialize();
}
bReturn = TRUE;
}
else if(m_State == EnumWaitConveneDataChannel)
{
if(bSuccess)
{
TRACESEND(" Data channel convened [%u]\n",wChannelId);
m_PrivateMBFTDataChannel = wChannelId;
m_State = EnumWaitSendChannelInvitePDU;
}
else
{
ReportError(MBFT_PERMANENT_ERROR,iMBFT_UNKNOWN_ERROR,TRUE);
UnInitialize();
}
bReturn = TRUE;
}
return(bReturn);
}
BOOL MBFTPrivateSend::SubmitFileSendRequest
(
SubmitFileSendMsg *pMsg
)
{
BOOL bCompressFiles = pMsg->m_bCompressFiles;
delete m_pszCurrentFilePath; // clean up any possible left over
m_pszCurrentFilePath = pMsg->m_pszFilePath;
m_CurrentFileHandle = pMsg->m_nFileHandle;
pMsg->m_pszFilePath = NULL; // keep this pointer for furure use
MBFT_ERROR_CODE iErrorCode = iMBFT_OK;
MBFT_ERROR_TYPES iErrorType = MBFT_PERMANENT_ERROR;
//NOTE: Merely turning this flag to TRUE will NOT
//enable compression. I have set it to FALSE here
//so that certain stubbed routines will not be
//entered. If you turn this flag to TRUE....
//then...have your finger ready on the reset button!!
//If you want to turn compression on, Then you have
//to include a bunch of v42.bis compression files etc.
bCompressFiles = FALSE;
// get the peer list
CPeerList *pPeerList = m_lpParentEngine->GetPeerList();
ASSERT(! (pMsg->m_nUserID && pMsg->m_nNodeID));
BOOL fBroadcast = (0 == pMsg->m_nUserID && 0 == pMsg->m_nNodeID);
ULONG iNumNodes = 1;
if (fBroadcast)
{
iNumNodes = pPeerList->GetCount();
ASSERT(iNumNodes);
}
DBG_SAVE_FILE_LINE
m_lpDataBuffer = new char[m_MaxDataLength + MAX_PATH + _iMBFT_FILEDATA_PDU_SUBTRACT]; // enough space for the largest PDU
DBG_SAVE_FILE_LINE
m_lpUserArray = new UserID[iNumNodes];
DBG_SAVE_FILE_LINE
m_lpAcceptedUsersArray = new UserID[iNumNodes];
if (NULL == m_lpDataBuffer || NULL == m_lpUserArray || NULL == m_lpAcceptedUsersArray)
{
ERROR_OUT(("MBFTPrivateSend::SubmitFileSendRequest: allocation failure"));
delete m_lpDataBuffer; m_lpDataBuffer = NULL;
delete m_lpUserArray; m_lpUserArray = NULL;
delete m_lpAcceptedUsersArray; m_lpAcceptedUsersArray = NULL;
iErrorCode = iMBFT_MEMORY_ALLOCATION_ERROR;
}
if(iErrorCode == iMBFT_OK)
{
m_iUserCount = 0;
ZeroMemory(m_lpUserArray, sizeof(UserID) * iNumNodes);
ZeroMemory(m_lpAcceptedUsersArray, sizeof(UserID) * iNumNodes);
m_bProshareTransfer = TRUE;
m_bEOFAcknowledge = TRUE;
if (fBroadcast)
{
CPeerData *lpPeer;
pPeerList->Reset();
while (NULL != (lpPeer = pPeerList->Iterate()))
{
if (lpPeer->GetUserID() != m_lpParentEngine->GetUserID())
{
m_lpUserArray[m_iUserCount++] = lpPeer->GetUserID();
if(m_bProshareTransfer)
{
m_bProshareTransfer = lpPeer->GetIsProshareNode();
}
if(m_bEOFAcknowledge)
{
m_bEOFAcknowledge = lpPeer->GetEOFAcknowledge();
}
}
} // while
}
else
{
CPeerData *lpPeer;
pPeerList->Reset();
while (NULL != (lpPeer = pPeerList->Iterate()))
{
if ((pMsg->m_nUserID && pMsg->m_nUserID == lpPeer->GetUserID())
||
(pMsg->m_nNodeID && pMsg->m_nNodeID == lpPeer->GetNodeID()))
{
m_lpUserArray[m_iUserCount++] = lpPeer->GetUserID();
if(m_bProshareTransfer)
{
m_bProshareTransfer = lpPeer->GetIsProshareNode();
}
if(m_bEOFAcknowledge)
{
m_bEOFAcknowledge = lpPeer->GetEOFAcknowledge();
}
break;
}
} // while
if (NULL == lpPeer)
{
iErrorCode = iMBFT_RECIPIENT_NOT_FOUND;
}
}
if(m_bCompressFiles)
{
iErrorCode = iMBFT_MEMORY_ALLOCATION_ERROR;
}
else
{
DBG_SAVE_FILE_LINE
m_lpFile = new CMBFTFile;
}
if(!m_lpFile)
{
iErrorCode = iMBFT_MEMORY_ALLOCATION_ERROR;
}
if(iErrorCode == iMBFT_OK)
{
m_State = EnumFileSendPending;
}
}
if(iErrorCode != iMBFT_OK)
{
// LOGERROR(iErrorCode,0,0);
ReportError(iErrorType,iErrorCode,TRUE);
TerminateSendSession();
}
return(iErrorCode == iMBFT_OK);
}
void MBFTPrivateSend::ReportSenderError
(
int iErrorType,
int iErrorCode,
MBFTFILEHANDLE hFile
)
{
DBG_SAVE_FILE_LINE
FileErrorPDU * lpNewPDU = new FileErrorPDU((hFile) ?
LOWORD(hFile) :
LOWORD(m_CurrentFileHandle),
iErrorType,iErrorCode);
if(lpNewPDU)
{
if(lpNewPDU->Encode())
{
for (ULONG Index = 0; Index < m_iUserCount; Index++)
{
m_lpParentEngine->SendDataRequest(m_lpUserArray[Index],
APPLET_HIGH_PRIORITY,
(LPBYTE)lpNewPDU->GetBuffer(),
lpNewPDU->GetBufferLength());
}
}
delete lpNewPDU;
}
}
void MBFTPrivateSend::ReportError
(
int iErrorType,
int iErrorCode,
BOOL bIsLocalError,
T120UserID SenderID,
MBFTFILEHANDLE FileHandle)
{
T120UserID id = SenderID ? SenderID : m_MBFTChannelID;
DBG_SAVE_FILE_LINE
m_lpParentEngine->SafePostNotifyMessage(
new FileErrorMsg(
m_EventHandle,
FileHandle ? FileHandle : m_CurrentFileHandle,
iErrorType,
iErrorCode,
bIsLocalError,
id));
}
void MBFTPrivateSend::TerminateSendSession(void)
{
UnInitialize();
}
void MBFTPrivateSend::UnInitialize
(
BOOL bShutDown
)
{
BOOL bDataChannelDisbanded = FALSE;
BOOL bControlChannelDisbanded = FALSE;
if(m_State != EnumWaitForTermination)
{
m_State = EnumWaitForTermination;
TRACESEND(" Uninit begin\n");
if (m_bEOFAcknowledge)
{
m_TimeOutValue = 0;
}
else
{
m_TimeOutValue = GetTickCount() + g_nSendDisbandDelay;
}
TRACESEND(" Using TimeOutValue of %d\n", m_TimeOutValue);
}
m_bUnInitializing = TRUE;
if(GetTickCount() >= m_TimeOutValue)
{
if(m_PrivateMBFTDataChannel)
{
if(m_lpParentEngine->MCSChannelDisbandRequest(m_PrivateMBFTDataChannel))
{
TRACESEND(" Uninit: Data Channel disbanded [%u]\n",m_PrivateMBFTDataChannel);
bDataChannelDisbanded = TRUE;
m_PrivateMBFTDataChannel = 0;
}
else if(m_lpParentEngine->GetLastSendDataError() == MCS_TRANSMIT_BUFFER_FULL)
{
TRACESEND("Transmit buffer for [%u] full, data channel disband failed\n",m_PrivateMBFTDataChannel);
}
else
{
TRACESEND("Unexpected error [%u] while disbanding data channel [%u]\n",
m_lpParentEngine->GetLastSendDataError(),m_PrivateMBFTDataChannel);
}
}
else
{
bDataChannelDisbanded = TRUE;
}
if(bDataChannelDisbanded)
{
if(m_PrivateMBFTControlChannel)
{
if(m_lpParentEngine->MCSChannelDisbandRequest(m_PrivateMBFTControlChannel))
{
TRACESEND(" Uninit: Control Channel disbanded [%u]\n",m_PrivateMBFTControlChannel);
bControlChannelDisbanded = TRUE;
m_PrivateMBFTControlChannel = 0;
}
else if(m_lpParentEngine->GetLastSendDataError() == MCS_TRANSMIT_BUFFER_FULL)
{
TRACESEND("Transmit buffer for [%u] full, control channel disband failed\n",m_PrivateMBFTDataChannel);
}
else
{
TRACESEND("Unexpected error [%u] while disbanding control channel [%u]\n",
m_lpParentEngine->GetLastSendDataError(),m_PrivateMBFTDataChannel);
}
}
else
{
bControlChannelDisbanded = TRUE;
}
}
if(!bShutDown)
{
if(bDataChannelDisbanded && bControlChannelDisbanded)
{
DBG_SAVE_FILE_LINE
m_lpParentEngine->SafePostMessage(new DeleteSessionMsg(this));
if(!m_bEventEndPosted)
{
DBG_SAVE_FILE_LINE
m_lpParentEngine->SafePostNotifyMessage(new FileEventEndNotifyMsg(m_EventHandle));
m_bEventEndPosted = TRUE;
}
TRACESEND(" Uninit complete\n");
}
}
else
{
TRACESEND(" Uninit complete\n");
}
}
}
void MBFTPrivateSend::SendChannelInvitePDU(void)
{
MBFT_ERROR_CODE iErrorCode = iMBFT_OK;
MBFT_ERROR_TYPES iErrorType = MBFT_PERMANENT_ERROR;
DBG_SAVE_FILE_LINE
LPPRIVATECHANNELINVITEPDU lpNewPDU = new PrivateChannelInvitePDU(m_PrivateMBFTControlChannel,
m_PrivateMBFTDataChannel,
FALSE);
if(lpNewPDU)
{
if(lpNewPDU->Encode())
{
for (ULONG Index = m_LastUserCount;Index < m_iUserCount;Index++)
{
if(m_lpParentEngine->SendDataRequest(m_lpUserArray[Index],
APPLET_HIGH_PRIORITY,
(LPBYTE)lpNewPDU->GetBuffer(),
lpNewPDU->GetBufferLength()))
{
TRACESEND(" Sent Channel invite PDU, Control Channel [%u], Data Channel [%u] to [%u]\n",m_PrivateMBFTControlChannel,m_PrivateMBFTDataChannel,m_lpUserArray[Index]);
m_LastUserCount++;
}
else
{
m_State = EnumWaitSendChannelInvitePDU;
break;
}
}
if(Index >= m_iUserCount)
{
AdmitControlChannel();
}
}
else
{
iErrorCode = iMBFT_ASN1_ENCODING_ERROR;
}
delete lpNewPDU;
}
else
{
iErrorCode = iMBFT_MEMORY_ALLOCATION_ERROR;
}
if(iErrorCode != iMBFT_OK)
{
ReportError(iErrorType,iErrorCode,TRUE);
UnInitialize();
}
}
BOOL MBFTPrivateSend::OnReceivedFileAbortPDU
(
T120ChannelID wChannelId,
T120Priority iPriority,
T120UserID SenderID,
LPFILEABORTPDU lpFileAbortPDU,
BOOL IsUniformSendData
)
{
MBFTFILEHANDLE hFile = lpFileAbortPDU->GetFileHandle();
if (hFile && hFile == m_CurrentFileHandle)
{
if (m_bUnInitializing)
{
OnControlNotification(hFile,
FileTransferControlMsg::EnumConductorAbortFile,
NULL,
NULL);
}
return TRUE; // handled
}
return FALSE; // not handled
}
void MBFTPrivateSend::DoStateMachine(void)
{
if(m_State == EnumFileSendPending)
{
ConveneControlChannel();
}
else if(m_State == EnumWaitRequestControlConvene)
{
ConveneControlChannel();
}
else if(m_State == EnumWaitRequestJoinControl)
{
JoinControlChannel();
}
else if(m_State == EnumWaitRequestDataConvene)
{
ConveneDataChannel();
}
else if(m_State == EnumWaitSendChannelInvitePDU)
{
SendChannelInvitePDU();
}
else if(m_State == EnumSendNonStandardPDU)
{
TRACESEND(" Not Sending a NonStandardPDU");
m_State = EnumSendFileOfferPDU;
SendFileOfferPDU();
}
else if(m_State == EnumSendFileOfferPDU)
{
SendFileOfferPDU();
}
else if(m_State == EnumSendFileStartPDU)
{
SendFileStartPDU();
}
else if(m_State == EnumSendFileDataPDU)
{
SendFileDataPDU();
}
else if(m_State == EnumTerminateCurrentSend)
{
TerminateCurrentSend();
}
else if(m_State == EnumWaitForTermination)
{
UnInitialize();
}
else if(m_State == EnumWaitChannelResponsePDU)
{
if(GetTickCount() >= m_TimeOutValue)
{
// LOGERROR(iMBFT_TIMEOUT_ERROR,0,0);
ReportError(MBFT_PERMANENT_ERROR,iMBFT_TIMEOUT_ERROR,TRUE);
UnInitialize();
}
}
return;
}
BOOL MBFTPrivateSend::OnReceivedPrivateChannelResponsePDU
(
T120ChannelID wChannelId,
T120Priority iPriority,
T120UserID SenderID,
LPPRIVATECHANNELRESPONSEPDU lpNewPDU,
BOOL IsUniformSendData
)
{
BOOL bReturn = FALSE;
if(m_State == EnumWaitChannelResponsePDU)
{
if(wChannelId == m_MBFTChannelID &&
lpNewPDU->GetControlChannel() == m_PrivateMBFTControlChannel)
{
bReturn = TRUE;
TRACESEND(" Received Channel response PDU from [%u]\n",SenderID);
for (ULONG Index = 0; Index < m_iUserCount; Index++)
{
if(m_lpUserArray[Index] == SenderID)
{
m_ResponseCount++;
}
}
if(!lpNewPDU->GetWasChannelJoined())
{
ReportError(MBFT_INFORMATIVE_ERROR,
iMBFT_RECEIVER_ABORTED,
FALSE,
SenderID,
_iMBFT_PROSHARE_ALL_FILES);
RemoveUserFromList(SenderID);
}
if(m_iUserCount)
{
if(m_ResponseCount >= m_iUserCount)
{
m_State = (! m_bProshareTransfer) ? EnumSendFileOfferPDU :
EnumSendNonStandardPDU;
}
}
}
}
return(bReturn);
}
void MBFTPrivateSend::SendFileOfferPDU(void)
{
MBFT_ERROR_CODE iErrorCode = iMBFT_OK;
MBFT_ERROR_TYPES iErrorType = MBFT_TRANSIENT_ERROR;
m_AcceptCount = 0;
m_RejectCount = 0;
m_ResponseCount = 0;
m_AcknowledgeCount = 0;
m_lTotalBytesRead = 0;
m_SentFileStartPDU = FALSE;
m_AbortedCount = 0;
m_bSentFileOfferPDU = FALSE;
m_AcceptedIndex = 0;
::ZeroMemory(m_lpAcceptedUsersArray, sizeof(UserID) * m_iUserCount);
if (m_lpFile->Open(m_pszCurrentFilePath, CMBFTFile::OpenReadOnly | CMBFTFile::OpenBinary))
{
m_CurrentFileSize = m_lpFile->GetFileSize();
m_CurrentDateTime = m_lpFile->GetFileDateTime();
DBG_SAVE_FILE_LINE
LPFILEOFFERPDU lpNewPDU = new FileOfferPDU(GetFileNameFromPath(m_pszCurrentFilePath),
LOWORD(m_CurrentFileHandle),
m_CurrentFileSize,
m_CurrentDateTime,
m_PrivateMBFTDataChannel,TRUE,
m_lpParentEngine->GetRosterInstance(),
0, NULL, 0, 0);
if(lpNewPDU)
{
if(lpNewPDU->Encode())
{
if(m_lpParentEngine->SendDataRequest(m_PrivateMBFTControlChannel,
APPLET_HIGH_PRIORITY,
(LPBYTE)lpNewPDU->GetBuffer(),
lpNewPDU->GetBufferLength()))
{
TRACESEND(" Transmitted File Offer PDU for [%u] on [%u]\n",LOWORD(m_CurrentFileHandle),m_PrivateMBFTControlChannel);
//Now that we have sent a FileOfferPDU, we can't disband the channel
//without notice....
m_bOKToDisbandChannel = FALSE;
m_bSentFileOfferPDU = TRUE;
m_State = EnumWaitFileAcceptPDU;
}
}
else
{
iErrorCode = iMBFT_ASN1_ENCODING_ERROR;
}
delete lpNewPDU;
}
else
{
iErrorCode = iMBFT_MEMORY_ALLOCATION_ERROR;
}
}
else
{
iErrorCode = (MBFT_ERROR_CODE)m_lpFile->GetLastErrorCode();
//iMBFT_FILE_IO_ERROR;
}
if(iErrorCode != iMBFT_OK)
{
ReportError(iErrorType,iErrorCode,TRUE);
if(m_bSentFileOfferPDU)
{
//If a FileOffer has been sent out, we need to send a FileStartPDU with
//EOF = TRUE...
TerminateCurrentSend();
}
else
{
ReportError(MBFT_INFORMATIVE_ERROR,iMBFT_SENDER_ABORTED,TRUE,
m_MBFTChannelID,m_CurrentFileHandle);
SendNextFile();
}
}
}
BOOL MBFTPrivateSend::OnReceivedFileAcceptPDU
(
T120ChannelID wChannelId,
T120Priority iPriority,
T120UserID SenderID,
LPFILEACCEPTPDU lpNewPDU,
BOOL IsUniformSendData
)
{
BOOL bReturn = FALSE;
if(m_State == EnumWaitFileAcceptPDU)
{
if(wChannelId == m_MBFTChannelID)
{
if(lpNewPDU->GetFileHandle() == m_CurrentFileHandle)
{
TRACESEND(" Received file accept PDU from [%u] for [%u]\n",SenderID,lpNewPDU->GetFileHandle());
bReturn = TRUE;
for (ULONG Index = 0; Index < m_iUserCount; Index++)
{
if(m_lpUserArray[Index] == SenderID)
{
if(m_AcceptedIndex < m_iUserCount)
{
m_lpAcceptedUsersArray[m_AcceptedIndex++] = SenderID;
}
m_AcceptCount++;
m_ResponseCount++;
}
}
if(m_ResponseCount >= m_iUserCount)
{
m_State = EnumSendFileStartPDU;
}
}
}
}
return(bReturn);
}
BOOL MBFTPrivateSend::OnReceivedFileRejectPDU
(
T120ChannelID wChannelId,
T120Priority iPriority,
T120UserID SenderID,
LPFILEREJECTPDU lpNewPDU,
BOOL IsUniformSendData
)
{
BOOL bReturn = FALSE;
if(m_State == EnumWaitFileAcceptPDU)
{
if(wChannelId == m_MBFTChannelID)
{
MBFTFILEHANDLE iFileHandle = lpNewPDU->GetFileHandle();
if((iFileHandle == m_CurrentFileHandle) ||
((iFileHandle == LOWORD(_iMBFT_PROSHARE_ALL_FILES)) && m_bProshareTransfer))
{
TRACESEND(" Received file reject PDU from [%u] for [%u]\n",SenderID,lpNewPDU->GetFileHandle());
for(ULONG Index = 0;Index < m_iUserCount;Index++)
{
if(m_lpUserArray[Index] == SenderID)
{
bReturn = TRUE;
}
}
if(bReturn)
{
if(iFileHandle == m_CurrentFileHandle)
{
m_RejectCount++;
m_ResponseCount++;
}
else if((iFileHandle == LOWORD(_iMBFT_PROSHARE_ALL_FILES)) && m_bProshareTransfer)
{
RemoveUserFromList(SenderID);
}
if(m_iUserCount)
{
if(m_ResponseCount >= m_iUserCount)
{
if(m_ResponseCount != m_RejectCount)
{
m_State = EnumSendFileStartPDU;
}
else
{
m_lpFile->Close();
SendNextFile();
}
}
}
} //if bReturn
}
} //wChannelId == m_MBFTChannelID
} //m_State == EnumWaitFileAcceptPDU
return(bReturn);
}
BOOL MBFTPrivateSend::OnReceivedFileErrorPDU
(
T120ChannelID wChannelId,
T120Priority iPriority,
T120UserID SenderID,
LPFILEERRORPDU lpNewPDU,
BOOL IsUniformSendData
)
{
BOOL bReturn = FALSE;
MBFTFILEHANDLE FileHandle = lpNewPDU->GetFileHandle();
if ((m_CurrentFileHandle == FileHandle) ||
(m_bProshareTransfer && (LOWORD(FileHandle) == LOWORD(_iMBFT_PROSHARE_ALL_FILES))))
{
TRACERECEIVE(" FileErrorPDU from [%u] for [%u], ErrorCode: [%u]\n",SenderID,lpNewPDU->GetFileHandle(),lpNewPDU->GetErrorCode());
if(m_bProshareTransfer)
{
if(m_State != EnumWaitForTermination)
{
if(lpNewPDU->GetErrorCode() == iMBFT_RECEIVER_ABORTED &&
lpNewPDU->GetFileHandle() == LOWORD(_iMBFT_PROSHARE_ALL_FILES))
{
m_AbortedCount++;
RemoveUserFromList(SenderID);
//If the state is EnumWaitFileAcceptPDU, we don't
//have an exact count of the number of recipients who accepted
//the file. Therefore, we cannot make a decision on whether or not
//to abort the file based on AcceptCount and AbortedCount....
if(m_State != EnumWaitFileAcceptPDU)
{
if(m_iUserCount)
{
if(m_AbortedCount >= m_AcceptCount)
{
m_lpFile->Close();
SendNextFile();
}
}
else
{
m_lpFile->Close();
}
}
else if(m_iUserCount)
{
//In this case, the FileErrorPDU acts as a FileRejectPDU...
TRACERECEIVE(" Treating FileErrorPDU for [%u] as FileRejectPDU\n",lpNewPDU->GetFileHandle());
//m_RejectCount++;
//m_ResponseCount++;
//In this case, response count has to be greater
//because a user was just deleted!!!
if(m_ResponseCount >= m_iUserCount)
{
if(m_ResponseCount != m_RejectCount)
{
m_State = EnumSendFileStartPDU;
}
else
{
SendNextFile();
}
}
}
}
else if (FileHandle == m_CurrentFileHandle)
{
m_AbortedCount++;
//If the state is EnumWaitFileAcceptPDU, we don't
//have an exact count of the number of recipients who accepted
//the file. Therefore, we cannot make a decision on whether or not
//to abort the file based on AcceptCount and AbortedCount....
if(m_State != EnumWaitFileAcceptPDU)
{
if(m_AbortedCount >= m_AcceptCount)
{
m_lpFile->Close();
SendNextFile();
}
}
else
{
//In this case, the FileErrorPDU acts as a FileRejectPDU...
TRACERECEIVE(" Treating FileErrorPDU for [%u] as FileRejectPDU\n",lpNewPDU->GetFileHandle());
m_RejectCount++;
m_ResponseCount++;
if(m_ResponseCount >= m_iUserCount)
{
if(m_ResponseCount != m_RejectCount)
{
m_State = EnumSendFileStartPDU;
}
else
{
SendNextFile();
}
}
}
}
} //EnumWaitForTermination
} //IsProshare
}
return(bReturn);
}
BOOL MBFTPrivateSend::OnReceivedNonStandardPDU
(
T120ChannelID wChannelID,
T120Priority iPriority,
T120UserID SenderID,
LPNONSTANDARDPDU lpNewPDU,
BOOL IsUniformSendData
)
{
BOOL bReturn = FALSE;
if(m_State != EnumWaitForTermination)
{
if(wChannelID == m_PrivateMBFTControlChannel)
{
if (! ::lstrcmpA(lpNewPDU->GetKey(), PROSHARE_FILE_END_STRING))
{
TRACESEND(" Received Non Standard PDU (File End Acknowledge) from [%u]\n",SenderID);
FileEndAcknowledgeStruct * lpStruct = (FileEndAcknowledgeStruct *)lpNewPDU->GetDataBuffer();
DBG_SAVE_FILE_LINE
LPFILEENDACKNOWLEDGEPDU lpNewPDU = new FileEndAcknowledgePDU(lpStruct->m_FileHandle);
if (NULL != lpNewPDU)
{
bReturn = OnReceivedFileEndAcknowledgePDU(wChannelID,
iPriority,
SenderID,
lpNewPDU,
IsUniformSendData);
delete lpNewPDU;
}
}
else if (! ::lstrcmpA(lpNewPDU->GetKey(), PROSHARE_CHANNEL_LEAVE_STRING))
{
TRACESEND(" Received Non Standard PDU (Channel Leave) from [%u]\n",SenderID);
ChannelLeaveStruct * lpStruct = (ChannelLeaveStruct *)lpNewPDU->GetDataBuffer();
DBG_SAVE_FILE_LINE
LPCHANNELLEAVEPDU lpNewPDU = new ChannelLeavePDU(lpStruct->m_ChannelID,lpStruct->m_ErrorCode);
if (NULL != lpNewPDU)
{
bReturn = OnReceivedChannelLeavePDU(wChannelID,
iPriority,
SenderID,
lpNewPDU,
IsUniformSendData);
delete lpNewPDU;
}
}
else
{
TRACE("*** Unknown Non Standard PDU received on [%u] *** \n",wChannelID);
}
}
}
return(bReturn);
}
BOOL MBFTPrivateSend::OnReceivedFileEndAcknowledgePDU
(
T120ChannelID wChannelId,
T120Priority iPriority,
T120UserID SenderID,
LPFILEENDACKNOWLEDGEPDU lpNewPDU,
BOOL IsUniformSendData
)
{
BOOL bReturn = FALSE;
if(m_State == EnumWaitFileEndAcknowledgePDU)
{
if(wChannelId == m_PrivateMBFTControlChannel)
{
if(lpNewPDU->GetFileHandle() == m_CurrentFileHandle)
{
TRACESEND(" Received file end acknowledge PDU from [%u] for [%u]\n",SenderID,lpNewPDU->GetFileHandle());
bReturn = TRUE;
for (ULONG Index = 0; Index < m_AcceptedIndex; Index++)
{
if(m_lpAcceptedUsersArray[Index] == SenderID)
{
m_AcknowledgeCount++;
}
}
if(m_AcknowledgeCount >= m_AcceptCount)
{
SendNextFile();
}
}
}
}
return(bReturn);
}
BOOL MBFTPrivateSend::OnReceivedChannelLeavePDU
(
T120ChannelID wChannelId,
T120Priority iPriority,
T120UserID SenderID,
LPCHANNELLEAVEPDU lpNewPDU,
BOOL IsUniformSendData
)
{
BOOL bReturn = FALSE;
if(m_State == EnumSendFileStartPDU || m_State == EnumSendFileDataPDU ||
m_State == EnumWaitFileEndAcknowledgePDU)
{
if(lpNewPDU->GetChannelID() == m_PrivateMBFTDataChannel)
{
bReturn = TRUE;
TRACESEND(" Received Channel Leave PDU from [%u] for [%u], CurrentFile [%u]\n",
SenderID,lpNewPDU->GetChannelID(),m_CurrentFileHandle);
for (ULONG Index = 0; Index < m_AcceptedIndex; Index++)
{
if(m_lpAcceptedUsersArray[Index] == SenderID)
{
m_AcknowledgeCount++;
}
}
if(m_State == EnumWaitFileEndAcknowledgePDU)
{
if(m_AcknowledgeCount >= m_AcceptCount)
{
SendNextFile();
}
}
}
}
return(bReturn);
}
void MBFTPrivateSend::SendFileStartPDU(void)
{
if(!m_bAbortAllFiles)
{
MBFT_ERROR_CODE iErrorCode = iMBFT_OK;
MBFT_ERROR_TYPES iErrorType = MBFT_TRANSIENT_ERROR;
LONG lCurrentPosition = m_lpFile->Seek(0L,CMBFTFile::SeekMode::SeekFromCurrent);
FILE_HEADER_INFO fileHeaderInfo;
fileHeaderInfo.fileName = (LPSTR)GetFileNameFromPath(m_pszCurrentFilePath);
fileHeaderInfo.fileSize = m_CurrentFileSize;
fileHeaderInfo.pduType = T127_FILE_START;
GetFileHeaderSize(&fileHeaderInfo);
int iSizeofFileHeader = fileHeaderInfo.pduSize + sizeof(T127_FILE_START_DATA_BLOCK_HEADER);
int iBytesRead = m_lpFile->Read(m_lpDataBuffer + iSizeofFileHeader ,m_MaxDataLength);
m_bSendingFile = TRUE;
if(iBytesRead != -1)
{
BOOL bIsEOF = (m_lTotalBytesRead + iBytesRead) >= m_CurrentFileSize;
LPFILESTARTPDU lpNewPDU = NULL;
if(!iBytesRead)
{
DBG_SAVE_FILE_LINE
lpNewPDU = new FileStartPDU(m_lpDataBuffer,
fileHeaderInfo.fileName, // GetFileNameFromPath(m_pszCurrentFilePath),
LOWORD(m_CurrentFileHandle),
m_CurrentFileSize,
m_CurrentDateTime,
m_lpDataBuffer,
0,
bIsEOF);
}
else
{
if(!m_bCompressFiles)
{
DBG_SAVE_FILE_LINE
lpNewPDU = new FileStartPDU(m_lpDataBuffer,
fileHeaderInfo.fileName, // GetFileNameFromPath(m_pszCurrentFilePath),
LOWORD(m_CurrentFileHandle),
m_CurrentFileSize,
m_CurrentDateTime,
m_lpDataBuffer,
iBytesRead,
bIsEOF);
}
else
{
iErrorCode = iMBFT_MEMORY_ALLOCATION_ERROR;
}
}
if(iErrorCode == iMBFT_OK)
{
if(lpNewPDU)
{
if(lpNewPDU->Encode())
{
if(m_lpParentEngine->SendDataRequest(m_PrivateMBFTDataChannel,
APPLET_LOW_PRIORITY,
(LPBYTE)lpNewPDU->GetBuffer(),
lpNewPDU->GetBufferLength()))
{
TRACESEND(" Sent file start PDU for [%ld] on [%u], EOF = [%d]\n",
m_CurrentFileHandle, m_PrivateMBFTDataChannel, bIsEOF);
m_lTotalBytesRead += iBytesRead;
m_SentFileStartPDU = TRUE;
SendNotificationMessage(iMBFT_FILE_SEND_BEGIN);
if(bIsEOF)
{
m_lpFile->Close();
if(!m_bEOFAcknowledge)
{
SendNextFile();
}
else
{
TRACESEND(" Waiting for End of File ack PDU\n");
m_State = EnumWaitFileEndAcknowledgePDU;
}
}
else
{
m_State = EnumSendFileDataPDU;
}
}
else
{
m_lpFile->Seek(lCurrentPosition,CMBFTFile::SeekMode::SeekFromBegin);
}
}
else
{
iErrorCode = iMBFT_ASN1_ENCODING_ERROR;
}
} //if(lpNewPDU)
else
{
iErrorCode = iMBFT_MEMORY_ALLOCATION_ERROR;
}
} //if iErrorCode == iMBFT_OK
if(lpNewPDU)
{
lpNewPDU->NULLDataBuffer();
delete lpNewPDU;
}
} //If bytes read...
else
{
iErrorCode = (MBFT_ERROR_CODE)m_lpFile->GetLastErrorCode();
//iMBFT_FILE_IO_ERROR;
}
if(iErrorCode != iMBFT_OK)
{
ReportError(iErrorType,iErrorCode,TRUE);
ReportSenderError(iErrorType,iErrorCode);
TerminateCurrentSend();
}
}
else
{
TerminateCurrentSend();
}
}
void MBFTPrivateSend::SendNotificationMessage
(
int iProgress,
T120UserID iUserID,
MBFTFILEHANDLE hFileHandle
)
{
T120UserID id = iUserID ? iUserID : m_MBFTChannelID;
DBG_SAVE_FILE_LINE
m_lpParentEngine->SafePostNotifyMessage(
new FileTransmitMsg(m_EventHandle,
hFileHandle ? hFileHandle : m_CurrentFileHandle,
m_CurrentFileSize,
m_lTotalBytesRead,
iProgress,
id));
}
void MBFTPrivateSend::TerminateCurrentSend(void)
{
m_State = EnumTerminateCurrentSend;
ReportError(MBFT_INFORMATIVE_ERROR,iMBFT_SENDER_ABORTED,TRUE,
m_MBFTChannelID,m_CurrentFileHandle);
//We don't care about compression in this case because the buffer is NULL....
DBG_SAVE_FILE_LINE
LPFILEDATAPDU lpNewPDU = new FileDataPDU(m_lpDataBuffer,LOWORD(m_CurrentFileHandle),m_lpDataBuffer,0, FALSE, TRUE);
if(lpNewPDU)
{
if(lpNewPDU->Encode())
{
if(m_lpParentEngine->SendDataRequest(m_PrivateMBFTDataChannel,
APPLET_LOW_PRIORITY,
(LPBYTE)lpNewPDU->GetBuffer(),
lpNewPDU->GetBufferLength()))
{
m_lpFile->Close();
SendNextFile();
}
}
lpNewPDU->NULLDataBuffer();
delete lpNewPDU;
}
}
void MBFTPrivateSend::SendFileDataPDU(void)
{
LONG lCurrentPosition = -1;
LPFILEDATAPDU lpNewPDU = NULL;
int iBytesRead,Index;
BOOL bIsEOF = FALSE,bTerminate = FALSE;
MBFT_ERROR_CODE iErrorCode = iMBFT_OK;
MBFT_ERROR_TYPES iErrorType = MBFT_TRANSIENT_ERROR;
if(!m_bAbortFileSend)
{
for(Index = 0;(Index < _MAX_SEND_PACKETS) && !bTerminate;Index++)
{
lCurrentPosition = m_lpFile->Seek(0L,CMBFTFile::SeekMode::SeekFromCurrent);
iBytesRead = m_lpFile->Read(m_lpDataBuffer + sizeof(T127_FILE_DATA_HEADER),m_MaxDataLength);
if(iBytesRead != -1)
{
BOOL bDataSent = FALSE;
bIsEOF = m_lpFile->GetIsEOF();
if(!m_bCompressFiles)
{
DBG_SAVE_FILE_LINE
lpNewPDU = new FileDataPDU(m_lpDataBuffer,
LOWORD(m_CurrentFileHandle),
m_lpDataBuffer,iBytesRead,bIsEOF,
FALSE);
}
else
{
// MSFT error - no compression
}
if(lpNewPDU)
{
if(lpNewPDU->Encode())
{
if(m_lpParentEngine->SendDataRequest(m_PrivateMBFTDataChannel,
APPLET_LOW_PRIORITY,
(LPBYTE)lpNewPDU->GetBuffer(),
lpNewPDU->GetBufferLength()))
{
TRACESEND(" Sent file data PDU on [%u], EOF = [%d], BufferSize = [%d]\n",m_PrivateMBFTDataChannel,bIsEOF,lpNewPDU->GetBufferLength());
//m_lTotalBytesRead += iBytesRead;
m_lTotalBytesRead = m_lpFile->Seek(0L,CMBFTFile::SeekMode::SeekFromCurrent);
bDataSent = TRUE;
SendNotificationMessage(iMBFT_FILE_SEND_PROGRESS);
if(bIsEOF)
{
m_lpFile->Close();
if(!m_bEOFAcknowledge)
{
SendNextFile();
}
else
{
TRACESEND(" Waiting for End of File ack PDU\n");
m_State = EnumWaitFileEndAcknowledgePDU;
}
bTerminate = TRUE;
}
}
if(!bDataSent)
{
m_lpFile->Seek(lCurrentPosition,CMBFTFile::SeekMode::SeekFromBegin);
bTerminate = TRUE;
}
}
else
{
iErrorCode = iMBFT_ASN1_ENCODING_ERROR;
break;
}
lpNewPDU->NULLDataBuffer();
delete lpNewPDU;
}
else
{
iErrorCode = iMBFT_MEMORY_ALLOCATION_ERROR;
break;
}
}
else
{
iErrorCode = (MBFT_ERROR_CODE)m_lpFile->GetLastErrorCode();
//iMBFT_FILE_IO_ERROR;
break;
}
} //for loop
}
else
{
TerminateCurrentSend();
}
if(iErrorCode != iMBFT_OK)
{
ReportError(iErrorType,iErrorCode,TRUE);
ReportSenderError(iErrorType,iErrorCode);
TerminateCurrentSend();
}
}
void MBFTPrivateSend::RemoveFileFromList
(
MBFTFILEHANDLE hFile
)
{
if (hFile == m_CurrentFileHandle)
{
ReportError(MBFT_PERMANENT_ERROR,iMBFT_NO_MORE_FILES,TRUE);
TerminateSendSession();
}
}
BOOL MBFTPrivateSend::RemoveUserFromAcceptedList
(
T120UserID iUserID
)
{
BOOL bUserRemoved = FALSE;
for (ULONG Index = 1; Index <= m_AcceptedIndex; Index++)
{
if(m_lpAcceptedUsersArray[Index - 1] == iUserID)
{
bUserRemoved = TRUE;
if(Index != m_AcceptedIndex)
{
CopyMemory(&m_lpAcceptedUsersArray[Index - 1],&m_lpAcceptedUsersArray[Index],
(m_AcceptedIndex - Index) * sizeof(UserID));
}
m_AcceptedIndex--;
}
}
return(bUserRemoved);
}
BOOL MBFTPrivateSend::RemoveUserFromList
(
T120UserID iUserID
)
{
BOOL bUserRemoved = FALSE;
for (ULONG Index = 1; Index <= m_iUserCount; Index++)
{
if(m_lpUserArray[Index - 1] == iUserID)
{
bUserRemoved = TRUE;
if(Index != m_iUserCount)
{
CopyMemory(&m_lpUserArray[Index - 1],&m_lpUserArray[Index],
(m_iUserCount - Index) * sizeof(UserID));
}
m_iUserCount--;
}
}
if(bUserRemoved)
{
if(!m_iUserCount)
{
ReportError(MBFT_PERMANENT_ERROR,iMBFT_NO_MORE_RECIPIENTS,TRUE);
if(m_State == EnumSendFileDataPDU || m_State == EnumSendFileOfferPDU ||
m_State == EnumWaitFileAcceptPDU)
{
if(m_lpFile)
{
m_lpFile->Close();
}
if(m_State == EnumSendFileDataPDU)
{
SendNotificationMessage(iMBFT_FILE_SEND_END);
}
}
TerminateSendSession();
}
}
return(bUserRemoved);
}
void MBFTPrivateSend::OnControlNotification
(
MBFTFILEHANDLE hFile,
FileTransferControlMsg::FileTransferControl iControlCommand,
LPCSTR lpszDirectory,
LPCSTR lpszFileName
)
{
if(iControlCommand == FileTransferControlMsg::EnumAbortFile ||
iControlCommand == FileTransferControlMsg::EnumConductorAbortFile)
{
if(m_bOKToDisbandChannel)
{
if(hFile == _iMBFT_PROSHARE_ALL_FILES /*&& m_bProshareTransfer*/)
{
//Fix to ensure a iMBFT_SENDER_ABORTED notification if sender aborts way too early...
ReportError(MBFT_INFORMATIVE_ERROR,
(iControlCommand == FileTransferControlMsg::EnumAbortFile) ?
iMBFT_SENDER_ABORTED :
iMBFT_CONDUCTOR_ABORTED,
TRUE,
m_MBFTChannelID,
_iMBFT_PROSHARE_ALL_FILES);
UnInitialize();
}
else
{
RemoveFileFromList(hFile);
}
}
else if(!m_bUnInitializing)
{
if(hFile == _iMBFT_PROSHARE_ALL_FILES)
{
AbortAllFiles();
}
else if(hFile == m_CurrentFileHandle)
{
AbortCurrentFile();
}
}
}
}
void MBFTPrivateSend::AbortAllFiles(void)
{
AbortCurrentFile();
m_bAbortAllFiles = TRUE;
}
void MBFTPrivateSend::AbortCurrentFile(void)
{
if(m_bSendingFile)
{
m_bAbortFileSend = TRUE;
}
}
void MBFTPrivateSend::SendNextFile(void)
{
// Notify the ui if some receivers didn't accept the previous file
if(m_AbortedCount)
{
// All the receivers aborted the FT, this is the same as the sender canceling FT
ReportError(MBFT_PERMANENT_ERROR,
m_AbortedCount >= m_AcceptCount ? iMBFT_SENDER_ABORTED : iMBFT_MULT_RECEIVER_ABORTED,
TRUE);
}
if(m_RejectCount)
{
// If we just had one FT an it rejected we say that there was a problem sending the file
// If we had more receivers we will use the receiver aborted message
ReportError(MBFT_PERMANENT_ERROR,
m_AcceptCount == 0 ? iMBFT_RECEIVER_REJECTED : iMBFT_MULT_RECEIVER_ABORTED,
TRUE);
}
// We are sending or the receiver Rejected before we start sending
if(m_bSendingFile || m_RejectCount)
{
SendNotificationMessage(iMBFT_FILE_SEND_END);
}
m_bSendingFile = FALSE;
m_bAbortFileSend = FALSE;
TerminateSendSession();
}
void MBFTPrivateSend::OnPeerDeletedNotification
(
CPeerData *lpPeerData
)
{
if(m_State != EnumWaitForTermination)
{
if(RemoveUserFromList(lpPeerData->GetUserID()))
{
if(m_iUserCount)
{
if(m_State == EnumWaitFileAcceptPDU ||
m_State == EnumWaitChannelResponsePDU)
{
//m_RejectCount++;
//m_ResponseCount++;
if(m_ResponseCount >= m_iUserCount)
{
if(m_State == EnumWaitFileAcceptPDU)
{
if(m_ResponseCount != m_RejectCount)
{
m_State = EnumSendFileStartPDU;
}
else
{
SendNextFile();
}
}
else if(m_State == EnumWaitChannelResponsePDU)
{
if(!m_bProshareTransfer)
{
m_State = EnumSendFileOfferPDU;
}
else
{
m_State = EnumSendNonStandardPDU;
}
}
} //m_ResponseCount >= m_iUserCount
}
else if ((m_State == EnumWaitFileEndAcknowledgePDU) || (m_State == EnumSendFileDataPDU))
{
if(RemoveUserFromAcceptedList(lpPeerData->GetUserID()))
{
m_AcknowledgeCount++;
}
if(m_AcknowledgeCount >= m_AcceptCount)
{
SendNextFile();
}
}
} //UserCount
} //RemoveUserFromList
} //EnumWaitForTermination
}