📄 transfersocket.cpp
字号:
// FileZilla - a Windows ftp client
// Copyright (C) 2002-2004 - 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
#define STATE_ONCLOSECALLED 4
/////////////////////////////////////////////////////////////////////////////
// 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_pBuffer2 = 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;
if (m_nMode & CSMODE_LIST)
{
m_pListResult = new CFtpListResult(pOwner->m_CurrentServer, &pOwner->m_bUTF8);
m_pListResult->InitLog(this);
}
else
m_pListResult = 0;
m_LastUpdateTime.QuadPart = 0;
memset(&m_zlibStream, 0, sizeof(m_zlibStream));
m_useZlib = false;
}
CTransferSocket::~CTransferSocket()
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("~CTransferSocket()"));
delete [] m_pBuffer;
delete [] m_pBuffer2;
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;
if (m_useZlib)
{
if (m_nMode & CSMODE_UPLOAD)
deflateEnd(&m_zlibStream);
else
inflateEnd(&m_zlibStream);
}
}
/////////////////////////////////////////////////////////////////////////////
// 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];
int numread = CAsyncSocketEx::Receive(buffer, BUFSIZE);
if (numread != SOCKET_ERROR && numread)
{
m_LastActiveTime = CTime::GetCurrentTime();
UpdateRecvLed();
if (m_useZlib)
{
m_zlibStream.next_in = (Bytef *)buffer;
m_zlibStream.avail_in = numread;
char *out = new char[BUFSIZE];
m_zlibStream.next_out = (Bytef *)out;
m_zlibStream.avail_out = BUFSIZE;
int res = inflate(&m_zlibStream, 0);
while (res == Z_OK)
{
m_pListResult->AddData(out, BUFSIZE - m_zlibStream.avail_out);
out = new char[BUFSIZE];
m_zlibStream.next_out = (Bytef *)out;
m_zlibStream.avail_out = BUFSIZE;
res = inflate(&m_zlibStream, 0);
}
delete [] buffer;
if (res == Z_STREAM_END)
m_pListResult->AddData(out, BUFSIZE - m_zlibStream.avail_out);
else if (res != Z_OK && res != Z_BUF_ERROR)
{
delete [] out;
Close();
if (!m_bSentClose)
{
m_nMode |= CSMODE_TRANSFERERROR;
m_bSentClose = TRUE;
m_pOwner->m_pOwner->PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_TRANSFEREND, m_nMode);
}
return;
}
else
delete [] out;
}
else
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);
}
else
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
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);
}
}
}
}
else if (m_nMode & CSMODE_DOWNLOAD)
{
if (m_nTransferState == STATE_STARTING)
OnConnect(0);
bool beenWaiting = false;
_int64 ableToRead;
if (GetState() != closed)
ableToRead = m_pOwner->GetAbleToDownloadSize(beenWaiting);
else
ableToRead = BUFSIZE;
if (!beenWaiting)
ASSERT(ableToRead);
else if (!ableToRead)
{
TriggerEvent(FD_READ);
return;
}
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);
}
while (numread != SOCKET_ERROR && numread)
{
m_LastActiveTime = CTime::GetCurrentTime();
UpdateRecvLed();
TRY
{
if (m_useZlib)
{
if (!m_pBuffer2)
m_pBuffer2 = new char[BUFSIZE];
m_zlibStream.next_in = (Bytef *)m_pBuffer;
m_zlibStream.avail_in = numread;
m_zlibStream.next_out = (Bytef *)m_pBuffer2;
m_zlibStream.avail_out = BUFSIZE;
int res = inflate(&m_zlibStream, 0);
while (res == Z_OK)
{
m_pFile->Write(m_pBuffer2, BUFSIZE - m_zlibStream.avail_out);
m_zlibStream.next_out = (Bytef *)m_pBuffer2;
m_zlibStream.avail_out = BUFSIZE;
res = inflate(&m_zlibStream, 0);
}
if (res == Z_STREAM_END)
m_pFile->Write(m_pBuffer2, BUFSIZE - m_zlibStream.avail_out);
else if (res != Z_OK && res != Z_BUF_ERROR)
{
Close();
if (!m_bSentClose)
{
m_nMode |= CSMODE_TRANSFERERROR;
m_bSentClose = TRUE;
m_pOwner->m_pOwner->PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_TRANSFEREND, m_nMode);
}
return;
}
}
else
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);
}
return;
}
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"));
if (IsLayerAttached())
TriggerEvent(FD_READ);
UpdateStatusBar(false);
return;
}
UpdateStatusBar(false);
if (GetState() != closed)
ableToRead = m_pOwner->GetAbleToDownloadSize(beenWaiting);
else
ableToRead = BUFSIZE;
if (!beenWaiting)
ASSERT(ableToRead);
else if (!ableToRead)
{
TriggerEvent(FD_READ);
return;
}
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
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);
}
}
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);
int res = m_pSslLayer->InitSSLConnection(true);
if (res == SSL_FAILURE_LOADDLLS)
m_pOwner->ShowStatus(IDS_ERRORMSG_CANTLOADSSLDLLS, 1);
else if (res == SSL_FAILURE_INITSSL)
m_pOwner->ShowStatus(IDS_ERRORMSG_CANTINITSSL, 1);
if (res)
{
Close();
if (!m_bSentClose)
{
m_nMode |= CSMODE_TRANSFERERROR;
m_bSentClose = TRUE;
m_pOwner->m_pOwner->PostThreadMessage(m_nInternalMessageID, FZAPI_THREADMSG_TRANSFEREND, m_nMode);
}
return;
}
}
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)
{
TCHAR buffer[1000];
memset(buffer,0,1000);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, nErrorCode, 0, buffer, 999, 0);
CString str;
str.Format(IDS_ERRORMSG_CANTOPENTRANSFERCHANNEL,buffer);
str.Replace( _T("\n"), _T("\0") );
str.Replace( _T("\r"), _T("\0") );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -