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.
531 lines
15 KiB
531 lines
15 KiB
/* file: mbftApi.cpp */
|
|
|
|
#include "mbftpch.h"
|
|
|
|
#include "messages.hpp"
|
|
#include "mbftapi.hpp"
|
|
|
|
|
|
MBFT_SEND_FILE_INFO *AllocateSendFileInfo(LPSTR pszPathName);
|
|
void FreeSendFileInfo(MBFT_SEND_FILE_INFO *);
|
|
|
|
|
|
MBFTInterface::MBFTInterface
|
|
(
|
|
IMbftEvents *pEvents,
|
|
HRESULT *pHr
|
|
)
|
|
:
|
|
CRefCount(MAKE_STAMP_ID('I','F','T','I')),
|
|
m_pEvents(pEvents),
|
|
m_pEngine(NULL),
|
|
m_FileHandle(0),
|
|
m_InStateMachine(FALSE),
|
|
m_bFileOfferOK(TRUE),
|
|
m_MBFTUserID(0),
|
|
m_SendEventHandle(0),
|
|
m_ReceiveEventHandle(0)
|
|
{
|
|
// register window class first
|
|
WNDCLASS wc;
|
|
::ZeroMemory(&wc, sizeof(wc));
|
|
// wc.style = 0;
|
|
wc.lpfnWndProc = MBFTNotifyWndProc;
|
|
// wc.cbClsExtra = 0;
|
|
// wc.cbWndExtra = 0;
|
|
wc.hInstance = g_hDllInst;
|
|
// wc.hIcon = NULL;
|
|
// wc.hbrBackground = NULL;
|
|
// wc.hCursor = NULL;
|
|
// wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = g_szMBFTWndClassName;
|
|
|
|
::RegisterClass(&wc);
|
|
|
|
// Create a hidden window for notification
|
|
m_hwndNotify = ::CreateWindowA(g_szMBFTWndClassName, NULL, WS_POPUP,
|
|
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
NULL, NULL, g_hDllInst, NULL);
|
|
if (NULL != m_hwndNotify)
|
|
{
|
|
HANDLE hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if (NULL != hEvent)
|
|
{
|
|
if (::PostMessage(g_pFileXferApplet->GetHiddenWnd(), MBFTMSG_CREATE_ENGINE, (WPARAM) hEvent, (LPARAM) this))
|
|
{
|
|
DWORD dwRet = ::WaitForSingleObject(hEvent, 1000);
|
|
ASSERT(WAIT_OBJECT_0 == dwRet);
|
|
}
|
|
else
|
|
{
|
|
WARNING_OUT(("MBFTInterface::MBFTInterface: PostMessage failed, err=%d", ::GetLastError()));
|
|
}
|
|
*pHr = (NULL != m_pEngine) ? S_OK : E_FAIL;
|
|
::CloseHandle(hEvent);
|
|
return;
|
|
}
|
|
}
|
|
*pHr = E_FAIL;
|
|
}
|
|
|
|
|
|
MBFTInterface::~MBFTInterface(void)
|
|
{
|
|
if (NULL != m_pEngine)
|
|
{
|
|
m_pEngine->ClearInterfacePointer();
|
|
m_pEngine = NULL;
|
|
}
|
|
|
|
if (NULL != m_hwndNotify)
|
|
{
|
|
::DestroyWindow(m_hwndNotify);
|
|
}
|
|
}
|
|
|
|
|
|
void MBFTInterface::ReleaseInterface(void)
|
|
{
|
|
Release();
|
|
}
|
|
|
|
|
|
void MBFTInterface::Update(void)
|
|
{
|
|
// DoStateMachine();
|
|
}
|
|
|
|
|
|
HRESULT MBFTInterface::AcceptFileOffer
|
|
(
|
|
MBFT_FILE_OFFER *pOffer,
|
|
LPCSTR pszRecDir,
|
|
LPCSTR pszFileName
|
|
)
|
|
{
|
|
BOOL bAcceptFile = (NULL != pszRecDir) && FEnsureDirExists(pszRecDir);
|
|
|
|
DBG_SAVE_FILE_LINE
|
|
return m_pEngine->SafePostMessage(
|
|
new FileTransferControlMsg(
|
|
pOffer->hEvent,
|
|
pOffer->lpFileInfoList->hFile,
|
|
pszRecDir,
|
|
pszFileName,
|
|
bAcceptFile ? FileTransferControlMsg::EnumAcceptFile
|
|
: FileTransferControlMsg::EnumRejectFile));
|
|
}
|
|
|
|
|
|
void MBFTInterface::RejectFileOffer
|
|
(
|
|
MBFT_FILE_OFFER *pOffer
|
|
)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
m_pEngine->SafePostMessage(
|
|
new FileTransferControlMsg(
|
|
pOffer->hEvent,
|
|
pOffer->lpFileInfoList->hFile,
|
|
NULL,
|
|
NULL,
|
|
FileTransferControlMsg::EnumRejectFile));
|
|
}
|
|
|
|
|
|
void MBFTInterface::CancelFt
|
|
(
|
|
MBFTEVENTHANDLE hEvent,
|
|
MBFTFILEHANDLE hFile
|
|
)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
m_pEngine->SafePostMessage(
|
|
new FileTransferControlMsg(
|
|
hEvent,
|
|
hFile,
|
|
NULL,
|
|
NULL,
|
|
FileTransferControlMsg::EnumAbortFile));
|
|
}
|
|
|
|
|
|
HRESULT MBFTInterface::SendFile
|
|
(
|
|
LPCSTR lpszFilePath,
|
|
T120NodeID nidReceiver,
|
|
MBFTEVENTHANDLE *lpEventHandle,
|
|
MBFTFILEHANDLE *lpFileHandle
|
|
)
|
|
{
|
|
if (NULL != m_SendEventHandle)
|
|
{
|
|
// We are waiting for a timeout in a file sent to a 3rd party FT
|
|
// that does not support our file end notification
|
|
return E_PENDING;
|
|
}
|
|
|
|
#ifdef ENABLE_CONDUCTORSHIP
|
|
if( !m_pEngine->ConductedModeOK() )
|
|
{
|
|
return E_ACCESSDENIED;
|
|
}
|
|
#endif
|
|
|
|
::EnterCriticalSection(&g_csWorkThread);
|
|
|
|
// set event handle
|
|
*lpEventHandle = ::GetNewEventHandle();
|
|
|
|
::LeaveCriticalSection(&g_csWorkThread);
|
|
|
|
DBG_SAVE_FILE_LINE
|
|
HRESULT hr = m_pEngine->SafePostMessage(
|
|
new CreateSessionMsg(MBFT_PRIVATE_SEND_TYPE, *lpEventHandle));
|
|
if (S_OK == hr)
|
|
{
|
|
*lpFileHandle = ::GetNewFileHandle();
|
|
|
|
ULONG cbSize = ::lstrlenA(lpszFilePath)+1;
|
|
DBG_SAVE_FILE_LINE
|
|
LPSTR pszPath = new char[cbSize];
|
|
if (NULL != pszPath)
|
|
{
|
|
::CopyMemory(pszPath, lpszFilePath, cbSize);
|
|
|
|
DBG_SAVE_FILE_LINE
|
|
hr = m_pEngine->SafePostMessage(
|
|
new SubmitFileSendMsg(
|
|
0, // SDK only knows node ID
|
|
nidReceiver,
|
|
pszPath,
|
|
*lpFileHandle,
|
|
*lpEventHandle,
|
|
FALSE));
|
|
if (S_OK == hr)
|
|
{
|
|
m_SendEventHandle = *lpEventHandle;
|
|
}
|
|
else
|
|
{
|
|
delete [] pszPath;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
void MBFTInterface::DoStateMachine(MBFTMsg *pMsg)
|
|
{
|
|
if(!m_InStateMachine)
|
|
{
|
|
BOOL fHeartBeat = FALSE;
|
|
|
|
m_InStateMachine = TRUE;
|
|
|
|
switch(pMsg->GetMsgType())
|
|
{
|
|
case EnumFileOfferNotifyMsg:
|
|
HandleFileOfferNotify((FileOfferNotifyMsg *) pMsg);
|
|
break;
|
|
|
|
case EnumFileTransmitMsg:
|
|
HandleProgressNotify((FileTransmitMsg *) pMsg);
|
|
fHeartBeat = TRUE;
|
|
break;
|
|
|
|
case EnumFileErrorMsg:
|
|
HandleErrorNotify((FileErrorMsg *) pMsg);
|
|
break;
|
|
|
|
case EnumPeerMsg:
|
|
HandlePeerNotification((PeerMsg *) pMsg);
|
|
break;
|
|
|
|
case EnumInitUnInitNotifyMsg:
|
|
HandleInitUninitNotification((InitUnInitNotifyMsg *) pMsg);
|
|
break;
|
|
|
|
case EnumFileEventEndNotifyMsg:
|
|
HandleGenericNotification((FileEventEndNotifyMsg *) pMsg);
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
} // switch
|
|
|
|
m_InStateMachine = FALSE;
|
|
|
|
if (fHeartBeat)
|
|
{
|
|
::PostMessage(g_pFileXferApplet->GetHiddenWnd(), MBFTMSG_HEART_BEAT, 0, (LPARAM) m_pEngine);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void MBFTInterface::HandleFileOfferNotify(FileOfferNotifyMsg * lpNotifyMessage)
|
|
{
|
|
if((m_ReceiveEventHandle == 0) || (m_ReceiveEventHandle != lpNotifyMessage->m_EventHandle))
|
|
{
|
|
TRACEAPI(" File Offer Notification for [%s], Event: [%ld], Size: [%ld], Handle [%Fp]\n",
|
|
lpNotifyMessage->m_szFileName,lpNotifyMessage->m_EventHandle,
|
|
lpNotifyMessage->m_FileSize,lpNotifyMessage->m_hFile);
|
|
|
|
MBFT_FILE_OFFER NewFileOffer;
|
|
MBFT_RECEIVE_FILE_INFO FileData;
|
|
|
|
NewFileOffer.hEvent = lpNotifyMessage->m_EventHandle;
|
|
NewFileOffer.SenderID = lpNotifyMessage->m_SenderID;
|
|
NewFileOffer.NodeID = lpNotifyMessage->m_NodeID;
|
|
NewFileOffer.uNumFiles = 1;
|
|
NewFileOffer.lpFileInfoList = &FileData;
|
|
NewFileOffer.bIsBroadcastEvent = !lpNotifyMessage->m_bAckNeeded;
|
|
|
|
::lstrcpynA(FileData.szFileName, lpNotifyMessage->m_szFileName, sizeof(FileData.szFileName));
|
|
FileData.hFile = lpNotifyMessage->m_hFile;
|
|
FileData.lFileSize = lpNotifyMessage->m_FileSize;
|
|
FileData.FileDateTime = lpNotifyMessage->m_FileDateTime;
|
|
|
|
m_pEvents->OnFileOffer(&NewFileOffer);
|
|
}
|
|
}
|
|
|
|
void MBFTInterface::HandleProgressNotify(FileTransmitMsg * lpProgressMessage)
|
|
{
|
|
MBFT_NOTIFICATION wMBFTCode = (MBFT_NOTIFICATION)lpProgressMessage->m_TransmitStatus;
|
|
|
|
TRACEAPI(" Notification [%x] from Event [%ld], Handle: [%ld] FileSize: [%ld], Bytes Xfered[%ld]\n",
|
|
wMBFTCode,lpProgressMessage->m_EventHandle,
|
|
lpProgressMessage->m_hFile,
|
|
lpProgressMessage->m_FileSize,
|
|
lpProgressMessage->m_BytesTransmitted);
|
|
|
|
switch (wMBFTCode)
|
|
{
|
|
case iMBFT_FILE_RECEIVE_BEGIN:
|
|
if(!m_ReceiveEventHandle)
|
|
{
|
|
m_ReceiveEventHandle = lpProgressMessage->m_EventHandle;
|
|
}
|
|
//m_bFileOfferOK = FALSE;
|
|
break;
|
|
|
|
case iMBFT_FILE_RECEIVE_PROGRESS:
|
|
case iMBFT_FILE_SEND_PROGRESS:
|
|
{
|
|
MBFT_FILE_PROGRESS Progress;
|
|
Progress.hEvent = lpProgressMessage->m_EventHandle;
|
|
Progress.hFile = lpProgressMessage->m_hFile;
|
|
Progress.lFileSize = lpProgressMessage->m_FileSize;
|
|
Progress.lBytesTransmitted = lpProgressMessage->m_BytesTransmitted;
|
|
Progress.bIsBroadcastEvent = lpProgressMessage->m_bIsBroadcastEvent;
|
|
|
|
m_pEvents->OnFileProgress(&Progress);
|
|
}
|
|
break;
|
|
|
|
case iMBFT_FILE_RECEIVE_END:
|
|
//m_bFileOfferOK = TRUE;
|
|
if(m_ReceiveEventHandle == lpProgressMessage->m_EventHandle)
|
|
{
|
|
m_ReceiveEventHandle = 0;
|
|
}
|
|
// fall through
|
|
case iMBFT_FILE_SEND_END:
|
|
m_pEvents->OnFileEnd(lpProgressMessage->m_hFile);
|
|
break;
|
|
|
|
default:
|
|
ASSERT(iMBFT_FILE_SEND_BEGIN == wMBFTCode);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void MBFTInterface::HandleErrorNotify(FileErrorMsg * lpErrorMessage)
|
|
{
|
|
|
|
TRACEAPI(" Error Notification, Event: [%ld], Handle [%ld], IsLocal = [%d]\n",
|
|
lpErrorMessage->m_EventHandle,lpErrorMessage->m_hFile,
|
|
lpErrorMessage->m_bIsLocalError);
|
|
|
|
|
|
MBFT_EVENT_ERROR Error;
|
|
|
|
Error.hEvent = lpErrorMessage->m_EventHandle;
|
|
Error.bIsLocalError = lpErrorMessage->m_bIsLocalError;
|
|
Error.UserID = lpErrorMessage->m_UserID;
|
|
Error.hFile = lpErrorMessage->m_hFile;
|
|
Error.bIsBroadcastEvent = lpErrorMessage->m_bIsBroadcastEvent;
|
|
|
|
if(LOWORD(Error.hFile) == LOWORD(_iMBFT_PROSHARE_ALL_FILES))
|
|
{
|
|
Error.hFile = _iMBFT_PROSHARE_ALL_FILES;
|
|
}
|
|
|
|
Error.eErrorType = (MBFT_ERROR_TYPES)lpErrorMessage->m_ErrorType;
|
|
Error.eErrorCode = (MBFT_ERROR_CODE)lpErrorMessage->m_ErrorCode;
|
|
|
|
m_pEvents->OnFileError(&Error);
|
|
}
|
|
|
|
void MBFTInterface::HandlePeerNotification(PeerMsg * lpNewMessage)
|
|
{
|
|
|
|
TRACEAPI(" Peer Notification, Node [%u], UserID [%u], IsProshare = [%u], Added = [%u]\n",
|
|
lpNewMessage->m_NodeID,
|
|
lpNewMessage->m_MBFTPeerID,lpNewMessage->m_bIsProsharePeer,
|
|
lpNewMessage->m_bPeerAdded);
|
|
|
|
|
|
MBFT_PEER_INFO PeerInfo;
|
|
|
|
PeerInfo.NodeID = lpNewMessage->m_NodeID;
|
|
PeerInfo.MBFTPeerID = lpNewMessage->m_MBFTPeerID;
|
|
PeerInfo.bIsProShareApp = lpNewMessage->m_bIsProsharePeer;
|
|
PeerInfo.MBFTSessionID = lpNewMessage->m_MBFTSessionID;
|
|
|
|
//PeerInfo.bIsLocalPeer = lpNewMessage->m_bIsLocalPeer;
|
|
|
|
::lstrcpynA(PeerInfo.szAppKey,lpNewMessage->m_szAppKey, sizeof(PeerInfo.szAppKey));
|
|
|
|
//lstrcpyn(PeerInfo.szProtocolKey,lpNewMessage->m_szProtocolKey, sizeof(PeerInfo.szProtocolKey));
|
|
|
|
if(!lpNewMessage->m_bIsLocalPeer)
|
|
{
|
|
TRACEAPI("Delivering PEER Notification\n");
|
|
if (lpNewMessage->m_bPeerAdded)
|
|
{
|
|
m_pEvents->OnPeerAdded(&PeerInfo);
|
|
}
|
|
else
|
|
{
|
|
m_pEvents->OnPeerRemoved(&PeerInfo);
|
|
}
|
|
}
|
|
|
|
if(lpNewMessage->m_bIsLocalPeer)
|
|
{
|
|
if(lpNewMessage->m_bPeerAdded)
|
|
{
|
|
m_MBFTUserID = PeerInfo.MBFTPeerID;
|
|
|
|
m_pEvents->OnInitializeComplete();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void MBFTInterface::HandleInitUninitNotification(InitUnInitNotifyMsg * lpNewMessage)
|
|
{
|
|
if (lpNewMessage->m_iNotifyMessage == EnumInvoluntaryUnInit)
|
|
{
|
|
if (NULL != m_pEvents)
|
|
{
|
|
m_pEvents->OnSessionEnd();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MBFTInterface::HandleGenericNotification(FileEventEndNotifyMsg * lpNewMessage)
|
|
{
|
|
if (m_SendEventHandle == lpNewMessage->m_EventHandle)
|
|
{
|
|
m_SendEventHandle = 0;
|
|
}
|
|
m_pEvents->OnFileEventEnd(lpNewMessage->m_EventHandle);
|
|
}
|
|
|
|
|
|
|
|
MBFT_SEND_FILE_INFO *AllocateSendFileInfo(LPSTR pszPathName)
|
|
{
|
|
MBFT_SEND_FILE_INFO *p = new MBFT_SEND_FILE_INFO;
|
|
if (NULL != p)
|
|
{
|
|
::ZeroMemory(p, sizeof(*p));
|
|
ULONG cb = ::lstrlenA(pszPathName) + 1;
|
|
p->lpszFilePath = new char[cb];
|
|
if (NULL != p->lpszFilePath)
|
|
{
|
|
::CopyMemory(p->lpszFilePath, pszPathName, cb);
|
|
#ifdef BUG_INTL
|
|
::AnsiToOem(p->lpszFilePath, p->lpszFilePath);
|
|
#endif /* BUG_INTL */
|
|
}
|
|
else
|
|
{
|
|
delete p;
|
|
p = NULL;
|
|
}
|
|
}
|
|
return p;
|
|
}
|
|
|
|
void FreeSendFileInfo(MBFT_SEND_FILE_INFO *p)
|
|
{
|
|
if (NULL != p)
|
|
{
|
|
delete p->lpszFilePath;
|
|
delete p;
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT MBFTInterface::SafePostNotifyMessage(MBFTMsg *pMsg)
|
|
{
|
|
if (NULL != pMsg)
|
|
{
|
|
AddRef();
|
|
if( !::PostMessage(m_hwndNotify, MBFTNOTIFY_BASIC, (WPARAM) pMsg, (LPARAM) this) )
|
|
{
|
|
Release();
|
|
delete pMsg;
|
|
pMsg = NULL;
|
|
}
|
|
return S_OK;
|
|
}
|
|
ERROR_OUT(("MBFTInterface::SafePostNotifyMessage: null msg ptr"));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
LRESULT CALLBACK
|
|
MBFTNotifyWndProc
|
|
(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case MBFTNOTIFY_BASIC:
|
|
{
|
|
MBFTInterface *pIntf = (MBFTInterface *) lParam;
|
|
MBFTMsg *pMsg = (MBFTMsg *) wParam;
|
|
ASSERT(NULL != pIntf);
|
|
ASSERT(NULL != pMsg);
|
|
pIntf->DoStateMachine(pMsg);
|
|
delete pMsg;
|
|
pIntf->Release();
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
::DestroyWindow(hwnd);
|
|
break;
|
|
|
|
default:
|
|
return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|