📄 transferagentview.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 + -