/* 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(); ::PostMessage(m_hwndNotify, MBFTNOTIFY_BASIC, (WPARAM) pMsg, (LPARAM) this); 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; }