📄 connectsocket.cpp
字号:
/********************************************************************/
/* */
/* CONNECTSOCKET.CPP */
/* */
/* Implementation of the Connect Socket. */
/* This class is a part of the ConnectThread which handles */
/* socket connections. Incomming data is processed in OnReceive */
/* */
/* Programmed by Pablo van der Meer */
/* http://www.pablovandermeer.nl */
/* */
/* Last updated: 10 july 2002 */
/* */
/********************************************************************/
#include "stdafx.h"
#include "FTPServerApp.h"
#include "FTPServer.h"
#include "ConnectSocket.h"
#include "ConnectThread.h"
#include "ApplicationDlg.h"
#include "DataSocket.h"
extern CFTPServer theServer;
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/********************************************************************/
/* */
/* Function name : CConnectSocket::CConnectSocket */
/* Description : Constructor */
/* */
/********************************************************************/
CConnectSocket::CConnectSocket()
{
m_bLoggedon = FALSE;
m_bRenameFile = FALSE;
// reset transfer status
m_TransferStatus.m_pDataSocket = NULL;
m_TransferStatus.m_strRemoteHost = "";
m_TransferStatus.m_nRemotePort = -1;
m_TransferStatus.m_bPassiveMode = FALSE;
m_TransferStatus.m_nRest = -1;
}
/********************************************************************/
/* */
/* Function name : CConnectSocket::~CConnectSocket */
/* Description : Destructor */
/* */
/********************************************************************/
CConnectSocket::~CConnectSocket()
{
DestroyDataSocket();
// tell our thread we have been closed
AfxGetThread()->PostThreadMessage(WM_QUIT,0,0);
TRACE0("CConnectSocket destroyed.\n");
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CConnectSocket, CSocket)
//{{AFX_MSG_MAP(CConnectSocket)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/********************************************************************/
/* */
/* Function name : OnClose */
/* Description : Send WM_QUIT message to the thread containing */
/* the socket to shutdown once the connection is */
/* closed. */
/* */
/********************************************************************/
void CConnectSocket::OnClose(int nErrorCode)
{
Close();
// destroy connection
m_pThread->PostThreadMessage(WM_THREADMSG, 1, 0);
TRACE("CConnectSocket() OnClose()\n");
CSocket::OnClose(nErrorCode);
}
#define BUFFERSIZE 4096
/********************************************************************/
/* */
/* Function name : OnReceive */
/* Description : Called by the framework to notify this socket */
/* that there is data in the buffer. */
/* */
/********************************************************************/
void CConnectSocket::OnReceive(int nErrorCode)
{
TCHAR buff[BUFFERSIZE];
int nRead = Receive(buff, BUFFERSIZE);
switch (nRead)
{
case 0:
Close();
break;
case SOCKET_ERROR:
if (GetLastError() != WSAEWOULDBLOCK)
{
TCHAR szError[256];
wsprintf(szError, "OnReceive error: %d", GetLastError());
AfxMessageBox (szError);
}
break;
default:
if (nRead != SOCKET_ERROR && nRead != 0)
{
((CConnectThread *)AfxGetThread())->IncReceivedBytes(nRead);
// terminate the string
buff[nRead] = 0;
m_RxBuffer += CString(buff);
GetRxLine();
}
break;
}
CSocket::OnReceive(nErrorCode);
}
/********************************************************************/
/* */
/* Function name: GetRxCommand */
/* Description : Get command from receiver buffer. */
/* */
/********************************************************************/
BOOL CConnectSocket::GetRxCommand(CString &strCommand, CString &strArguments)
{
if (!m_strCommands.IsEmpty())
{
CString strBuff = m_strCommands.RemoveHead();
int nIndex = strBuff.Find(" ");
if (nIndex != -1)
{
CString strPassword = strBuff;
strPassword.MakeUpper();
// make password invisible
if (strPassword.Left(5) == "PASS ")
{
strPassword = strBuff.Left(5);
for (int i=0; i<strBuff.GetLength()-5; i++)
strPassword += "*";
FireStatusMessage(strPassword, 1);
}
else
{
FireStatusMessage(strBuff, 1);
}
strCommand = strBuff.Left(nIndex);
strArguments = strBuff.Mid(nIndex+1);
}
else
{
FireStatusMessage(strBuff, 1);
strCommand = strBuff;
}
if (strCommand != "")
{
strCommand.MakeUpper();
// who screwed up ???
if (strCommand.Right(4) == "ABOR")
{
strCommand = "ABOR";
}
TRACE2("COMMAND: %s, ARGS: %s\n", strCommand, strArguments);
return TRUE;
}
}
return FALSE;
}
/********************************************************************/
/* */
/* Function name: GetRxLine */
/* Description : Parse complete command line */
/* */
/********************************************************************/
void CConnectSocket::GetRxLine()
{
CString strTemp;
int nIndex;
while(!m_RxBuffer.IsEmpty())
{
nIndex = m_RxBuffer.Find("\r\n");
if (nIndex != -1)
{
strTemp = m_RxBuffer.Left(nIndex);
m_RxBuffer = m_RxBuffer.Mid(nIndex + 2);
if (!strTemp.IsEmpty())
{
m_strCommands.AddTail(strTemp);
// parse and execute command
ParseCommand();
}
}
else
break;
}
}
/********************************************************************/
/* */
/* Function name: OnConnect */
/* Description : Called by the framework to notify this connecting */
/* socket that its connection attempt is completed. */
/* */
/********************************************************************/
void CConnectSocket::OnConnect(int nErrorCode)
{
CSocket::OnConnect(nErrorCode);
}
/********************************************************************/
/* */
/* Function name: HasConnectionDropped */
/* Description : Check if connection has been dropped. */
/* Used to detect if client has crashed. */
/* */
/********************************************************************/
BOOL CConnectSocket::HasConnectionDropped(void)
{
BOOL bConnDropped = FALSE;
INT iRet = 0;
BOOL bOK = TRUE;
if (m_hSocket == INVALID_SOCKET)
return TRUE;
struct timeval timeout = { 0, 0 };
fd_set readSocketSet;
FD_ZERO(&readSocketSet);
FD_SET(m_hSocket, &readSocketSet);
iRet = ::select(0, &readSocketSet, NULL, NULL, &timeout);
bOK = (iRet > 0);
if(bOK)
{
bOK = FD_ISSET(m_hSocket, &readSocketSet);
}
if(bOK)
{
CHAR szBuffer[1] = "";
iRet = ::recv(m_hSocket, szBuffer, 1, MSG_PEEK);
bOK = (iRet > 0);
if(!bOK)
{
INT iError = ::WSAGetLastError();
bConnDropped = (( iError == WSAENETRESET) ||
(iError == WSAECONNABORTED) ||
(iError == WSAECONNRESET) ||
(iError == WSAEINVAL) ||
(iRet == 0));
}
}
return(bConnDropped);
}
/********************************************************************/
/* */
/* Function name: SendResponse */
/* Description : Send response to client. */
/* */
/********************************************************************/
BOOL CConnectSocket::SendResponse(CString strData)
{
// is connection still active ?
if (HasConnectionDropped())
{
FireStatusMessage("could not send reply, disconnected.", 2);
Close();
// tell our thread we have been closed
// destroy connection
m_pThread->PostThreadMessage(WM_THREADMSG, 1, 0);
return FALSE;
}
int nBytes = CSocket::Send(strData + "\r\n", strData.GetLength()+2);
if (nBytes == SOCKET_ERROR)
{
Close();
FireStatusMessage("could not send reply, disconnected.", 2);
// tell our thread we have been closed
m_pThread->PostThreadMessage(WM_THREADMSG, 1, 0);
return FALSE;
}
FireStatusMessage(strData, 2);
((CConnectThread *)AfxGetThread())->IncSentBytes(nBytes);
return TRUE;
}
/********************************************************************/
/* */
/* Function name: ParseCommand */
/* Description : Parse and execute command from client. */
/* */
/********************************************************************/
void CConnectSocket::ParseCommand()
{
static CFTPCommand commandList[] =
{
{TOK_USER, "USER", TRUE},
{TOK_PASS, "PASS", TRUE},
{TOK_CWD, "CWD", TRUE},
{TOK_PWD, "PWD", FALSE},
{TOK_PORT, "PORT", TRUE},
{TOK_PASV, "PASV", FALSE},
{TOK_TYPE, "TYPE", TRUE},
{TOK_LIST, "LIST", FALSE},
{TOK_REST, "REST", TRUE},
{TOK_CDUP, "CDUP", FALSE},
{TOK_RETR, "RETR", TRUE},
{TOK_STOR, "STOR", TRUE},
{TOK_SIZE, "SIZE", TRUE},
{TOK_DELE, "DELE", TRUE},
{TOK_RMD, "RMD", TRUE},
{TOK_MKD, "MKD", TRUE},
{TOK_RNFR, "RNFR", TRUE},
{TOK_RNTO, "RNTO", TRUE},
{TOK_ABOR, "ABOR", FALSE},
{TOK_SYST, "SYST", FALSE},
{TOK_NOOP, "NOOP", FALSE},
{TOK_BYE, "BYE", FALSE},
{TOK_QUIT, "QUIT", FALSE},
{TOK_ERROR, "", FALSE},
};
// parse command
CString strCommand, strArguments;
if (!GetRxCommand(strCommand, strArguments))
{
return;
}
int nCommand;
// find command in command list
for (nCommand = TOK_USER; nCommand < TOK_ERROR; nCommand++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -