📄 transfersocket.cpp
字号:
// FileZilla - a Windows ftp client
// Copyright (C) 2002 - Tim Kosse <tim.kosse@gmx.de>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// TransferSocket.cpp: Implementierungsdatei
//
#include "stdafx.h"
#include "filezilla.h"
#include "TransferSocket.h"
#include "mainthread.h"
#include "AsyncProxySocketLayer.h"
#include "AsyncGssSocketLayer.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define BUFSIZE 16384
#define STATE_WAITING 0
#define STATE_STARTING 1
#define STATE_STARTED 2
/////////////////////////////////////////////////////////////////////////////
// CTransferSocket
CTransferSocket::CTransferSocket(CFtpControlSocket *pOwner, int nMode)
{
ASSERT(pOwner);
InitLog(pOwner);
m_pOwner = pOwner;
m_nMode = nMode;
m_nTransferState = STATE_WAITING;
m_bCheckTimeout = FALSE;
m_pBuffer = 0;
m_bufferpos = 0;
m_ReadPos = 0;
m_ReadBuffer = 0;
m_ReadSize = 0;
m_cLastChar = 0;
m_pFile = 0;
m_bListening = FALSE;
m_bSentClose = FALSE;
m_nInternalMessageID = 0;
m_transferdata.transfersize = 0;
m_transferdata.transferleft = 0;
m_transferdata.nTransferStart = 0;
m_nNotifyWaiting = 0;
m_bShutDown = FALSE;
UpdateStatusBar(true);
for (int i = 0; i < SPEED_SECONDS; i++)
{
m_Transfered[i] = 0;
m_UsedForTransfer[i] = 0;
}
m_pProxyLayer = NULL;
m_pSslLayer = NULL;
m_pGssLayer = NULL;
m_pListResult = new CFtpListResult(pOwner->m_CurrentServer);
m_LastUpdateTime.QuadPart = 0;
}
CTransferSocket::~CTransferSocket()
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("~CTransferSocket()"));
if (m_pBuffer)
{
delete [] m_pBuffer;
m_pBuffer = 0;
}
if (m_ReadBuffer)
{
delete [] m_ReadBuffer;
m_ReadBuffer = 0;
}
PostMessage(m_pOwner->m_pOwner->m_hOwnerWnd, m_pOwner->m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_TRANSFERSTATUS, 0), 0);
Close();
RemoveAllLayers();
delete m_pProxyLayer;
delete m_pSslLayer;
delete m_pGssLayer;
m_pOwner->RemoveActiveTransfer();
delete m_pListResult;
}
/////////////////////////////////////////////////////////////////////////////
// Member-Funktion CTransferSocket
void CTransferSocket::OnReceive(int nErrorCode)
{
if (GetState() != connected && GetState() != attached && GetState() != closed)
return;
if (m_nTransferState == STATE_WAITING)
{
m_nNotifyWaiting |= FD_READ;
return;
}
if (m_bSentClose)
return;
if (m_bListening)
return;
if (m_nMode&CSMODE_LIST)
{
if (m_nTransferState == STATE_STARTING)
OnConnect(0);
char *buffer=new char[BUFSIZE];
AsyncSelect(FD_CLOSE);
int numread = CAsyncSocketEx::Receive(buffer,BUFSIZE);
while (numread!=SOCKET_ERROR && numread)
{
m_LastActiveTime = CTime::GetCurrentTime();
UpdateRecvLed();
m_pListResult->AddData(buffer,numread);
m_transferdata.transfersize += numread;
CTimeSpan timespan = CTime::GetCurrentTime()-m_StartTime;
int elapsed = (int)timespan.GetTotalSeconds();
//TODO
//There are servers which report the total number of
//bytes in the list response message, but yet it is not supported by FZ.
/*double leftmodifier=(transfersize-transferstart-transferleft);
leftmodifier*=100;
leftmodifier/=(transfersize-transferstart);
if (leftmodifier==0)
leftmodifier=1;
double leftmodifier2=100-leftmodifier;
int left=(int)((elapsed/leftmodifier)*leftmodifier2);
int percent=MulDiv(100,transfersize-transferleft,transfersize);*/
int transferrate=static_cast<int>( (elapsed && m_transferdata.transfersize)?m_transferdata.transfersize/elapsed:0 );
t_ffam_transferstatus *status = new t_ffam_transferstatus;
status->bFileTransfer = FALSE;
status->bytes = m_transferdata.transfersize;
status->percent = -1;
status->timeelapsed = elapsed;
status->timeleft = -1;
status->transferrate = transferrate;
PostMessage(m_pOwner->m_pOwner->m_hOwnerWnd, m_pOwner->m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_TRANSFERSTATUS, 0), (LPARAM)status);
//Check if there are other commands in the command queue.
MSG msg;
if (PeekMessage(&msg, 0, m_nInternalMessageID, m_nInternalMessageID, PM_NOREMOVE) && GetState() != closed)
{
LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("Message waiting in queue, resuming later"));
AsyncSelect(FD_READ | FD_CLOSE);
if (IsLayerAttached())
TriggerEvent(FD_READ);
return;
}
buffer = new char[BUFSIZE];
numread = CAsyncSocketEx::Receive(buffer, BUFSIZE);
}
delete [] buffer;
if (!numread)
{
Close();
if (!m_bSentClose)
{
m_bSentClose = TRUE;
m_pOwner->m_pOwner->PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_TRANSFEREND, m_nMode);
}
}
if (numread==SOCKET_ERROR)
{
int nError = GetLastError();
if (nError==WSAENOTCONN)
{
//Not yet connected
AsyncSelect(FD_READ | FD_CLOSE);
return;
}
if (nError!=WSAEWOULDBLOCK)
{
Close();
if (!m_bSentClose)
{
m_nMode |= CSMODE_TRANSFERERROR;
m_bSentClose = TRUE;
m_pOwner->m_pOwner->PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_TRANSFEREND, m_nMode);
}
}
}
AsyncSelect(FD_READ | FD_CLOSE);
}
else if (m_nMode&CSMODE_DOWNLOAD)
{
if (m_nTransferState == STATE_STARTING)
OnConnect(0);
AsyncSelect(FD_CLOSE);
bool beenWaiting;
_int64 ableToRead;
if (GetState() != closed)
ableToRead = m_pOwner->GetAbleToDownloadSize(beenWaiting);
else
ableToRead = BUFSIZE;
if (!m_pBuffer)
m_pBuffer = new char[BUFSIZE];
int numread = CAsyncSocketEx::Receive(m_pBuffer, static_cast<int>(ableToRead));
if (numread!=SOCKET_ERROR)
{
Transfered( numread, CTime::GetCurrentTime());
m_pOwner->SpeedLimitAddDownloadedBytes(numread);
}
int loopcount=0;
while (numread!=SOCKET_ERROR && numread)
{
loopcount++;
m_LastActiveTime = CTime::GetCurrentTime();
UpdateRecvLed();
TRY
{
m_pFile->Write(m_pBuffer, numread);
}
CATCH(CFileException,e)
{
LPTSTR msg = new TCHAR[BUFSIZE];
if (e->GetErrorMessage(msg, BUFSIZE))
m_pOwner->ShowStatus(msg, 1);
delete [] msg;
Close();
if (!m_bSentClose)
{
m_nMode |= CSMODE_TRANSFERERROR;
m_bSentClose = TRUE;
m_pOwner->m_pOwner->PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_TRANSFEREND, m_nMode);
}
}
END_CATCH;
m_transferdata.transferleft -= numread;
//Check if there are other commands in the command queue.
MSG msg;
if (PeekMessage(&msg, 0, m_nInternalMessageID, m_nInternalMessageID, PM_NOREMOVE) && GetState() != closed)
{
LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("Message waiting in queue, resuming later"));
AsyncSelect(FD_READ | FD_CLOSE);
if (IsLayerAttached())
TriggerEvent(FD_READ);
UpdateStatusBar(false);
return;
}
UpdateStatusBar(false);
if (GetState() != closed)
ableToRead = m_pOwner->GetAbleToDownloadSize(beenWaiting);
else
ableToRead = BUFSIZE;
numread = CAsyncSocketEx::Receive(m_pBuffer, static_cast<int>(ableToRead));
if (numread!=SOCKET_ERROR)
{
Transfered( numread, CTime::GetCurrentTime());
m_pOwner->SpeedLimitAddDownloadedBytes(numread);
}
}
if (!numread)
{
Close();
if (!m_bSentClose)
{
m_bSentClose = TRUE;
m_pOwner->m_pOwner->PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_TRANSFEREND, m_nMode);
}
}
if (numread == SOCKET_ERROR)
{
int nError=GetLastError();
if (nError==WSAENOTCONN)
{
//Not yet connected
AsyncSelect(FD_READ | FD_CLOSE);
return;
}
if (nError!=WSAEWOULDBLOCK)
{
Close();
if (!m_bSentClose)
{
m_nMode |= CSMODE_TRANSFERERROR;
m_bSentClose = TRUE;
m_pOwner->m_pOwner->PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_TRANSFEREND, m_nMode);
}
}
UpdateStatusBar(false);
}
else
UpdateStatusBar(false);
AsyncSelect(FD_READ | FD_CLOSE);
}
}
void CTransferSocket::OnAccept(int nErrorCode)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("OnAccept(%d)"), nErrorCode);
m_bListening=FALSE;
CAsyncSocketEx tmp;
Accept(tmp);
SOCKET socket=tmp.Detach();
CAsyncSocketEx::Close();
Attach(socket);
/* Set internal socket send buffer to twice the programs buffer size
* this should fix the speed problems some users have reported
*/
DWORD value;
int len = sizeof(value);
GetSockOpt(SO_SNDBUF, &value, &len);
if (value < (BUFSIZE*2))
{
value = BUFSIZE * 2;
SetSockOpt(SO_SNDBUF, &value, sizeof(value));
}
if (m_nTransferState == STATE_STARTING)
{
m_nTransferState = STATE_STARTED;
if (m_pSslLayer)
{
AddLayer(m_pSslLayer);
m_pSslLayer->InitClientSSL();
}
if (m_pGssLayer)
{
AddLayer(m_pGssLayer);
}
m_TransferedFirst = m_StartTime = CTime::GetCurrentTime();
m_LastActiveTime=CTime::GetCurrentTime();
}
}
void CTransferSocket::OnConnect(int nErrorCode)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("OnConnect(%d)"), nErrorCode);
if (nErrorCode)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -