⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transferagentview.cpp

📁 c++系统开发实例精粹内附的80例源代码 环境:windows2000,c++6.0
💻 CPP
字号:
//////////////////////////////////////////////////////////////////////
// FileFury
// Copyright (c) 2000 Tenebril Incorporated
// All rights reserved.
//
// This source code is governed by the Tenebril open source
// license (http://www.tenebril.com/developers/opensource/license.html)
//
// For more information on this and other open source applications,
// visit the Tenebril OpenSource page:
//       http://www.tenebril.com/developers/opensource
//
//////////////////////////////////////////////////////////////////////

// TransferAgentView.cpp : implementation file
//

#include "stdafx.h"
#include "Oscar.h"
#include "TransferAgentView.h"

#include "MainFrm.h"

#include "TransferAgentFrame.h"

#include "AwareNetDivers.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

static HANDLE handleThread;

#define _afxSockThreadState AfxGetModuleThreadState()
#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE


/////////////////////////////////////////////////////////////////////////////
// CTransferAgentView

IMPLEMENT_DYNCREATE(CTransferAgentView, CView)

CTransferAgentView::CTransferAgentView()
{
	m_nLastPercentage = 100;
	m_pFrame = NULL;
}

CTransferAgentView::~CTransferAgentView()
{
}


BEGIN_MESSAGE_MAP(CTransferAgentView, CView)
	//{{AFX_MSG_MAP(CTransferAgentView)
	ON_WM_CREATE()
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTransferAgentView drawing

void CTransferAgentView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
}

/////////////////////////////////////////////////////////////////////////////
// CTransferAgentView diagnostics

#ifdef _DEBUG
void CTransferAgentView::AssertValid() const
{
	CView::AssertValid();
}

void CTransferAgentView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CTransferAgentView message handlers

int CTransferAgentView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// create CListCtrl
	VERIFY (m_cListCtrl.Create (WS_CHILD | WS_VISIBLE | LVS_REPORT | 
		LVS_SHOWSELALWAYS, 
		CRect (0, 0, 0, 0), this, IDI_LIST));

	// Get the column widths.
	COscarApp *pApp = (COscarApp *)AfxGetApp();
	ASSERT(pApp);
	CSettingsArchive *pArchive = pApp->GetArchive();
	ASSERT(pArchive);

	// Setup columns.
	LV_COLUMN lvcol;
	lvcol.cx = pArchive->m_arch1.nTransferAgentWidths[0];
	lvcol.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
	lvcol.fmt = LVCFMT_LEFT;
	lvcol.pszText = (LPSTR)_T("File name");     // First column.
	lvcol.iSubItem = 0;
	m_cListCtrl.InsertColumn( 0, &lvcol );

	// Second column.
	lvcol.cx = pArchive->m_arch1.nTransferAgentWidths[1];
	lvcol.fmt = LVCFMT_LEFT;
	lvcol.pszText = (LPSTR)_T("Host");
	lvcol.iSubItem = 1;
	m_cListCtrl.InsertColumn( 1, &lvcol );

	// Third column.
	lvcol.cx = pArchive->m_arch1.nTransferAgentWidths[2];
	lvcol.fmt = LVCFMT_LEFT;
	lvcol.pszText = (LPSTR)_T("Status");
	lvcol.iSubItem = 2;
	m_cListCtrl.InsertColumn( 2, &lvcol );

	return 0;
}

UINT CTransferAgentView::AddTransfer(LPCTSTR czFileSrc, LPCTSTR czSrcMachine, 
									 LPCTSTR czFileDst, LPCTSTR czDstMachine)
{
	if(!czFileSrc || !czSrcMachine || !czFileDst || !czDstMachine) 
		return 0;

	// Make sure buffers are suitable.
	CString cszFileSrc, cszSrcMachine;
	CString cszFileDst, cszDstMachine;

	cszFileSrc = czFileSrc;
	cszSrcMachine = czSrcMachine;
	cszFileDst = czFileDst;
	cszDstMachine = czDstMachine;

	if(cszFileSrc.GetLength() > MAX_PATH ||
	   cszSrcMachine.GetLength() > MAX_MACHINE ||
	   cszFileDst.GetLength() > MAX_PATH ||
	   cszDstMachine.GetLength() > MAX_MACHINE)
	   return 0;

	// Make sure we don't step on anything.
	m_cListLock.Lock();

	// Check for duplicates.
	for(int i = 0; i < m_cListCtrl.GetItemCount(); i++)
	{
		TransferItem *ptItemData = (TransferItem *)m_cListCtrl.GetItemData(i);
		if(!ptItemData) continue;

		CString cszItemSrcName = ptItemData->czSrcName;
		CString cszItemSrcMach = ptItemData->czSrcMach;
		CString cszItemDstName = ptItemData->czDstName;
		CString cszItemDstMach = ptItemData->czDstMach;

		BOOL bFound = (cszItemSrcName.CompareNoCase(cszFileSrc) == 0);
		bFound &= (cszItemSrcMach.CompareNoCase(cszSrcMachine) == 0);
		bFound &= (cszItemDstName.CompareNoCase(cszFileDst) == 0);
		bFound &= (cszItemDstMach.CompareNoCase(cszDstMachine) == 0);

		if(bFound)         // Match.
		{
			m_cListLock.Unlock();
			return 0;
		}
	}

	int nNewPos = m_cListCtrl.GetItemCount();
	int nItemID = m_cListCtrl.InsertItem(nNewPos, czFileSrc);
	ASSERT(nItemID >= 0);
	if(nItemID < 0)
	{
		m_cListLock.Unlock();
		return 0;
	}

	// Set the source machine.
	m_cListCtrl.SetItemText(nItemID, 1, czSrcMachine);

	// Set the item state.
	m_cListCtrl.SetItemText(nItemID, 2, _T("Waiting"));

	// Construct a data structure for this item.
	TransferItem *ptItem = new TransferItem;
	memset((void *)ptItem, 0, sizeof(TransferItem));

	memcpy((void *)ptItem->czSrcName, cszFileSrc.GetBuffer(0),
		cszFileSrc.GetLength() * sizeof(TCHAR));
	memcpy((void *)ptItem->czSrcMach, cszSrcMachine.GetBuffer(0),
		cszSrcMachine.GetLength() * sizeof(TCHAR));
	memcpy((void *)ptItem->czDstName, cszFileDst.GetBuffer(0),
		cszFileDst.GetLength() * sizeof(TCHAR));
	memcpy((void *)ptItem->czDstMach, cszDstMachine.GetBuffer(0),
		cszDstMachine.GetLength() * sizeof(TCHAR));

	// Set the item's data here.
	m_cListCtrl.SetItemData(nItemID, (DWORD)ptItem);

	// Done.
	m_cListLock.Unlock();

	// Start the transfer daemon if we haven't already.
	StartTransfer();

	return 1;
}

void CTransferAgentView::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);
	
	// resize list to fill the whole view
	m_cListCtrl.MoveWindow (0, 0, cx, cy);
}

BOOL CTransferAgentView::StartTransfer()
{
	CWinThread *pThread;

	if(handleThread)
		return FALSE;

	m_bKeepGoing = true;

	pThread = AfxBeginThread((AFX_THREADPROC)(CTransferAgentView::DriveTransfer),
		(LPVOID)this, THREAD_PRIORITY_LOWEST);

	ASSERT(pThread);
	if(!pThread) return FALSE;

	handleThread = pThread->m_hThread;

	return TRUE;
}

BOOL CTransferAgentView::StopTransfer(BOOL bWait)
{
	DWORD dwExitCode = STILL_ACTIVE;

	if(!handleThread)
		return FALSE;

	m_bKeepGoing = false;

	while(dwExitCode == STILL_ACTIVE && bWait)
	{
		if(!GetExitCodeThread(handleThread, &dwExitCode))
			return FALSE;

		if(dwExitCode == STILL_ACTIVE)
		{
			// Process any unhandled messages
			
			MSG msg;
			while ( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) 
			{ 
				CWinThread *pThisThread = AfxGetThread();
				ASSERT(pThisThread);

				if ( !pThisThread->PumpMessage( ) ) 
					break;
			}

			Sleep(THREAD_DIE_WAIT);
		}
	}

	return TRUE;
}

UINT PASCAL CTransferAgentView::DriveTransfer(LPVOID *Param)
{
	// Get the owning object.
	CTransferAgentView *pThis = (CTransferAgentView *)Param;
	ASSERT(pThis);

	if(!pThis)
	{
		handleThread = NULL;
		return 0;
	}

	// Initialize this thread's AFX socket stuff (hack for VC6)
#ifdef PER_THREAD_SOCKINIT
	{
		_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
		if (pState->m_pmapSocketHandle == NULL)
			pState->m_pmapSocketHandle = new CMapPtrToPtr;
		if (pState->m_pmapDeadSockets == NULL)
			pState->m_pmapDeadSockets = new CMapPtrToPtr;
		if (pState->m_plistSocketNotifications == NULL)
			pState->m_plistSocketNotifications = new CPtrList;
	}
#endif

	int nNumEntries;

	// Get the number of entries, protecting thread stomping.
	pThis->m_cListLock.Lock();
	nNumEntries = pThis->m_cListCtrl.GetItemCount();
	pThis->m_cListLock.Unlock();

	while(nNumEntries)        // Process each entry.
	{
		// Protect the list control.
		pThis->m_cListLock.Lock();

		// Get the first entry.
		TransferItem *pItemData;
		pItemData = (TransferItem *)pThis->m_cListCtrl.GetItemData(0);
		ASSERT(pItemData);
		if(!pItemData)
		{
			pThis->m_cListLock.Unlock();
			continue;
		}

		// Update the first entry's status.
		pThis->m_cListCtrl.SetItemText(0, 2, _T("Transferring"));

		// Unlink the entry's handle to the data structure.
		pThis->m_cListCtrl.SetItemData(0, (DWORD)NULL);

		// Unlock the list control.
		pThis->m_cListLock.Unlock();

		// Now we can run the transfer.
		pThis->RunTransfer(pItemData);

		// The transfer has been completed.  Delete the item.
		pThis->m_cListLock.Lock();
		pThis->m_cListCtrl.DeleteItem(0);

		// Get the number of entries.
		nNumEntries = pThis->m_cListCtrl.GetItemCount();
		pThis->m_cListLock.Unlock();

		// Update any views that should be changed.
		{
			// Get the affected directory.
			CString cszDestDir = pItemData->czDstName;
			// Strip off the filename.
			int nPos = cszDestDir.ReverseFind(_T('\\'));
			if(nPos > 0)
			{
				cszDestDir = cszDestDir.Left(nPos);

				// Notify the main window.
				COscarApp *pApp = (COscarApp *)AfxGetApp();
				ASSERT(pApp);
				pApp->UpdateAfterTransfer(cszDestDir);
			}
		}

		// Free the data structure.
		delete pItemData;
	}

	// If we need to autoclose, handle it.
	if(pThis->m_pFrame && pThis->m_pFrame->m_bAutoClose)
	{
		UINT AutoCloseMessage = 
			RegisterWindowMessage(_T("Oscar auto close transfer agent"));
		pThis->m_pFrame->PostMessage(AutoCloseMessage);
	}

	handleThread = NULL;
	return 1;
}

BOOL CTransferAgentView::IsWorking()
{
	return (handleThread != NULL);
}

BOOL CTransferAgentView::RunTransfer(TransferItem *pData)
{
	ASSERT(pData);
	if(!pData) return FALSE;

	// Switch into the correct type of transfer.
	if(IsLocal(pData->czSrcMach) && IsLocal(pData->czDstMach))
	{
		// We shouldn't support local-local copies with the transfer
		// agent; remote, long-running copies would stall them.

		return FALSE;
	}

	if(IsLocal(pData->czSrcMach) && !IsLocal(pData->czDstMach))
	{
		// We're copying out of this machine.  This is not supported
		// currently; the transfer daemon does this, not the agent.

		return FALSE;
	}

	if(!IsLocal(pData->czSrcMach) && !IsLocal(pData->czDstMach))
	{
		// There is no mechanism for remote-remote copies currently.

		return FALSE;
	}

	// We have a copy from a remote machine to the local machine.
	// We can handle this.

	// Open the destination file.  We need to do this first so we know
	// we have a target.
	CFile fileDest;
	if(!fileDest.Open(pData->czDstName, CFile::modeCreate | CFile::modeWrite))
	{
		// Can't do it.  Clear.
		return FALSE;
	}

	// Resolve the source machine's name.
	CString cszSrcMachine = pData->czSrcMach;
	if(cszSrcMachine.Find(_T('@')) > -1)  // E-mail address; use AwareNet.
	{
		CString cszSrcIP;
		CAwareNet cANet;       // Get a handle.  AwareNet will handle synchro.

		// Check to make sure AwareNet has been initialized.
		COscarApp *pApp = (COscarApp *)AfxGetApp();
		ASSERT(pApp);
		if(!pApp->m_bANetInit)
		{
			// Wouldn't be able to resolve the e-mail address.  Bail.
			fileDest.Close();
			return FALSE;
		}

		if(!AwareNet_FindIP(&cANet, cszSrcMachine, cszSrcIP, FALSE))
		{
			// Couldn't resolve the e-mail address.  Bail.
			fileDest.Close();
			return FALSE;
		}

		cszSrcMachine = cszSrcIP;
	}

	// Open a connection to the remote machine.
	CTimeoutSocket cSock;
	if(!cSock.Create())
	{
		ASSERT(0);      // Should not happen.
		fileDest.Close();
		return FALSE;
	}

	if(!cSock.Connect(cszSrcMachine, PORT_OSCARTRANSFER))
	{
		fileDest.Close();
		return FALSE;
	}

	// We have a connection.  Now send the file name.
	TCHAR tczFileName[MAX_PATH * 2];
	memset((void *)tczFileName, 0, sizeof(tczFileName));
	memcpy((void *)tczFileName, pData->czSrcName,
		sizeof(pData->czSrcName));

	cSock.SetTimeout(SOCKET_TIMEOUT);
	if(cSock.Send((void *)tczFileName, sizeof(tczFileName)) !=
		sizeof(tczFileName))
	{
		// Couldn't send file name.  Bail.
		cSock.Close();
		fileDest.Close();
		return FALSE;
	}

	// Receive the file length.  From now on, we may very well lose
	// the connection due to security problems.
	LONG lFileLength;
	cSock.SetTimeout(SOCKET_TIMEOUT);
	if(cSock.Receive((void *)&lFileLength, sizeof(LONG)) != sizeof(LONG))
	{
		// Probably didn't have permission.
		cSock.Close();
		fileDest.Close();
		return FALSE;
	}

	// Now we have the file length.  Make sure it's valid.
	ASSERT(lFileLength > 0);
	if(lFileLength <= 0)
	{
		cSock.Close();
		fileDest.Close();
		return FALSE;
	}

	// Loop over the file.
	char cBuffer[10 * 1024];
	for(LONG l = 0; l < lFileLength; l += sizeof(cBuffer))
	{
		int nReceived = 0, nChunk;
		char *bBuf = cBuffer;

		while(nReceived < sizeof(cBuffer))
		{
			cSock.SetTimeout(SOCKET_TIMEOUT);
			nChunk = cSock.Receive((void *)bBuf, sizeof(cBuffer) - nReceived);

			if(nChunk == 0)
				break;

			bBuf += nChunk;
			nReceived += nChunk;

			UpdateItemStatus((LONG)nReceived + l, lFileLength);
		}

		if(nReceived < sizeof(cBuffer))
		{
			// We bailed because of a timeout.
			cSock.Close();
			fileDest.Close();
			return FALSE;
		}

		// We have the next chunk.  Add it to the file.
		try
		{
			int nValid = lFileLength - l;
			if(nValid > sizeof(cBuffer)) nValid = sizeof(cBuffer);
			
			fileDest.Write(cBuffer, nValid);
		}
		catch(CFileException *pExcept)
		{
			ASSERT(pExcept);
			delete pExcept;

			cSock.Close();
			fileDest.Close();
			return FALSE;
		}

		// Continue.
	}

	// We have the whole file.  Close the socket.
	cSock.Close();

	// Close the file.
	fileDest.Close();

	// Done.
	return TRUE;
}

BOOL CTransferAgentView::IsLocal(LPCTSTR czIP)
{
	// Check to see if the IP address is local.  The convention
	// is 127.0.0.1 only.

	CString cszIP = czIP;
	return (cszIP.CompareNoCase(_T("127.0.0.1")) == 0);
}

BOOL CTransferAgentView::UpdateItemStatus(LONG lDone, LONG lTotal)
{
	float fPercentage = (float)lDone / (float)lTotal;
	int nPercentage = (int)(fPercentage * 100);

	if(nPercentage < 0) nPercentage = 0;
	else if(nPercentage > 100) nPercentage = 100;

	if(nPercentage != m_nLastPercentage)
	{
		CString cszPercentage;
		cszPercentage.Format(_T("Transferring (%i%%)"), nPercentage);
		m_cListCtrl.SetItemText(0, 2, cszPercentage);

		m_nLastPercentage = nPercentage;
	}

	return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -