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

📄 ftpserver.cpp

📁 It can also accept a number of ftp connection (multithreaded), and with most of the commercial ftp s
💻 CPP
字号:
/****************************************************************/
/*																*/
/*  FTPServer.cpp												*/
/*																*/
/*  Implementation of the CFTPServer class.						*/
/*	This class is a part of the FTP Server Application			*/
/*																*/
/*  Programmed by Pablo van der Meer							*/
/*  Copyright Pablo Software Solutions 2002						*/
/*	http://www.pablovandermeer.nl								*/
/*																*/
/*  Last updated: 10 july 2002									*/
/*																*/
/****************************************************************/


#include "stdafx.h"
#include "FTPServer.h"


CFTPServer::CFTPServer()
{
	m_nPort = 21;
	m_nMaxUsers = 10;
	m_strWelcomeMessage = "Welcome to Pablo's FTP Server";
	m_strGoodbyeMessage = "Bye";
	m_nTimeout = 5;
	m_bRunning = FALSE;
	m_hWnd = NULL;
	m_nConnectionCount = 0;

	// intialize statistics
	m_dwTotalSentBytes = 0;
	m_dwTotalReceivedBytes = 0;
	m_nTotalConnections = 0;
	m_nFilesDownloaded = 0;
	m_nFilesUploaded = 0;
	m_nFailedDownloads = 0;
	m_nFailedUploads = 0;

	m_nSecurityMode = 0;

	m_nStatisticsInterval = 0;

	// load users
	m_UserManager.Serialize(FALSE);

	// load security
	m_SecurityManager.Serialize(FALSE);
}

CFTPServer::~CFTPServer()
{
	Stop();
}


BEGIN_MESSAGE_MAP(CFTPServer, CWnd)
	//{{AFX_MSG_MAP(CFTPServer)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_THREADSTART, OnThreadStart)
	ON_MESSAGE(WM_THREADCLOSE, OnThreadClose)
	ON_MESSAGE(WM_THREADMSG, OnThreadMessage)
END_MESSAGE_MAP()



/********************************************************************/
/*																	*/
/* Function name : Start											*/
/* Description   : Start listining on port 21 and accept new		*/
/*				   connections.										*/
/*																	*/
/********************************************************************/
BOOL CFTPServer::Start()
{
	if (m_bRunning)
		return FALSE;

	// create dummy window for message routing
    if (!CWnd::CreateEx(0, AfxRegisterWndClass(0), "FTP Server Notification Sink", WS_POPUP, 0,0,0,0, NULL, 0))
	{
		AddTraceLine(0, "Failed to create notification window.");
		return FALSE;
	}
	// created the listen socket
	if (m_ListenSocket.Create(m_nPort))
	{
		// start listening
		if (m_ListenSocket.Listen())
		{
			m_ListenSocket.m_pWndServer = this;
			m_bRunning = TRUE;	
			
			SetTimer(1, m_nStatisticsInterval, NULL);

			AddTraceLine(0, "FTP Server started on port %d.", m_nPort);
			return TRUE;
		}
	}
	AddTraceLine(0, "FTP Server failed to listen on port %d.", m_nPort);

	// destroy notification window
	if (IsWindow(m_hWnd))
		DestroyWindow();
	m_hWnd = NULL;

	return FALSE;
}


/********************************************************************/
/*																	*/
/* Function name : Stop												*/
/* Description   : Stop FTP server.									*/
/*																	*/
/********************************************************************/
void CFTPServer::Stop()
{
	if (!m_bRunning)
		return;

	// stop statistics timer
	KillTimer(1);

	m_bRunning = FALSE;	
	m_ListenSocket.Close();

	CConnectThread* pThread = NULL;

	// close all running threads
	do
	{
		m_CriticalSection.Lock();

		POSITION pos = m_ThreadList.GetHeadPosition();
		if (pos != NULL)
		{
			pThread = (CConnectThread *)m_ThreadList.GetAt(pos);
		
			m_CriticalSection.Unlock();

			// save thread members
			int nThreadID = pThread->m_nThreadID;
			HANDLE hThread = pThread->m_hThread;

			AddTraceLine(0, "[%d] Shutting down thread...", nThreadID);

			// tell thread to stop
			pThread->SetThreadPriority(THREAD_PRIORITY_HIGHEST);
			pThread->PostThreadMessage(WM_QUIT,0,0);

			// wait for thread to end, while keeping the messages pumping (max 5 seconds)
			if (WaitWithMessageLoop(hThread, 5000) == FALSE)
			{
				// thread doesn't want to stopped
				AddTraceLine(0, "[%d] Problem while killing thread.", nThreadID);
				// don't try again, so remove
				m_CriticalSection.Lock();
				POSITION rmPos = m_ThreadList.Find(pThread);
				if (rmPos != NULL)
					m_ThreadList.RemoveAt(rmPos);
				m_CriticalSection.Unlock();
			}
			else
			{
				AddTraceLine(0, "[%d] Thread successfully stopped.", nThreadID);
			}
		}
		else
		{
			m_CriticalSection.Unlock();	
			pThread = NULL;
		}
	}
	while (pThread != NULL);

	AddTraceLine(0, "FTP Server stopped.");

	if (IsWindow(m_hWnd))
		DestroyWindow();

	m_hWnd = NULL;
}


/********************************************************************/
/*																	*/
/* Function name : IsActive											*/
/* Description   : Is FTP server active?							*/
/*																	*/
/********************************************************************/
BOOL CFTPServer::IsActive()
{
	return m_bRunning;
}


/********************************************************************/
/*																	*/
/* Function name : SetMaxUsers										*/
/* Description   : Set maximum number of users						*/
/*																	*/
/********************************************************************/
void CFTPServer::SetMaxUsers(int nValue)
{
	m_nMaxUsers = nValue;
}


/********************************************************************/
/*																	*/
/* Function name : SetPort											*/
/* Description   : Set listening port for new connections			*/
/*																	*/
/********************************************************************/
void CFTPServer::SetPort(int nValue)
{
	m_nPort = nValue;
}


/********************************************************************/
/*																	*/
/* Function name : SetTimeout										*/
/* Description   : Set connection timeout							*/
/*																	*/
/********************************************************************/
void CFTPServer::SetTimeout(int nValue)
{
	m_nTimeout = nValue;
}


/********************************************************************/
/*																	*/
/* Function name : SetTimeout										*/
/* Description   : Set connection timeout							*/
/*																	*/
/********************************************************************/
void CFTPServer::SetStatisticsInterval(int nValue)
{
	m_nStatisticsInterval = nValue;
	if (m_nStatisticsInterval != 0)
	{
		KillTimer(1);
		SetTimer(1, nValue, NULL);
	}
	else
	{
		KillTimer(1);
	}
}


/********************************************************************/
/*																	*/
/* Function name : SetWelcomeMessage								*/
/* Description   : Set welcome message								*/
/*																	*/
/********************************************************************/
void CFTPServer::SetWelcomeMessage(LPCTSTR lpszText)
{
	m_strWelcomeMessage = lpszText;
}


/********************************************************************/
/*																	*/
/* Function name : SetGoodbyeMessage								*/
/* Description   : Set goodbye message								*/
/*																	*/
/********************************************************************/
void CFTPServer::SetGoodbyeMessage(LPCTSTR lpszText)
{
	m_strGoodbyeMessage = lpszText;
}


/********************************************************************/
/*																	*/
/* Function name : Initialize										*/
/* Description   : Initialize event sink.							*/
/*																	*/
/********************************************************************/
void CFTPServer::Initialize(CFTPEventSink *pEventSink)
{
	m_pEventSink = pEventSink;
}


/********************************************************************/
/*																	*/
/* Function name : AddTraceLine										*/
/* Description   : FTP status change.								*/
/*																	*/
/********************************************************************/
void CFTPServer::AddTraceLine(int nType, LPCTSTR pstrFormat, ...)
{
	CString str;

	// format and write the data we were given
	va_list args;
	va_start(args, pstrFormat);
	str.FormatV(pstrFormat, args);
	m_pEventSink->OnFTPStatusChange(nType, str);
}


/********************************************************************/
/*																	*/
/* Function name : OnThreadStart									*/
/* Description   : Called when a new thread has started.			*/
/*																	*/
/********************************************************************/
LRESULT CFTPServer::OnThreadStart(WPARAM wParam, LPARAM)
{
	m_nConnectionCount++;
	m_nTotalConnections++;
	CConnectThread *pThread = (CConnectThread *)wParam;

	UINT port;

	pThread->m_ConnectSocket.GetPeerName(pThread->m_strRemoteHost, port);
	AddTraceLine(0, "[%d] Client connected from %s.", pThread->m_nThreadID, pThread->m_strRemoteHost);

	return TRUE;
}


/********************************************************************/
/*																	*/
/* Function name : OnThreadClose									*/
/* Description   : Called when a thread is about to stop.			*/
/*																	*/
/********************************************************************/
LRESULT CFTPServer::OnThreadClose(WPARAM wParam, LPARAM lParam)
{
	m_nConnectionCount--;
	CConnectThread *pThread = (CConnectThread *)wParam;

	AddTraceLine(0, "[%d] Client disconnected from %s.", pThread->m_nThreadID, pThread->m_strRemoteHost);
	
	m_pEventSink->OnFTPUserDisconnected(pThread->m_nThreadID, pThread->m_ConnectSocket.m_strUserName);
	return TRUE;
}


/********************************************************************/
/*																	*/
/* Function name : OnThreadMessage									*/
/* Description   : Message sent from connect connection.			*/
/*																	*/
/********************************************************************/
LRESULT CFTPServer::OnThreadMessage(WPARAM wParam, LPARAM lParam)
{
	switch(wParam)
	{
		case 0:
			m_dwTotalSentBytes += (int)lParam;
			break;
		case 1:
			m_dwTotalReceivedBytes += (int)lParam;
			break;
		case 2:
			switch(lParam)
			{
				case FTPSTAT_DOWNLOADSUCCEEDED:
					m_nFilesDownloaded++;
					break;
				case FTPSTAT_UPLOADSUCCEEDED:
					m_nFilesUploaded++;
					break;
				case FTPSTAT_DOWNLOADFAILED:
					m_nFailedDownloads++;
					break;
				case FTPSTAT_UPLOADFAILED:
					m_nFailedUploads++;
					break;
			}
			break;
		default:
			
			break;
	}
	return TRUE;
}


/********************************************************************/
/*																	*/
/* Function name : CheckMaxUsers									*/
/* Description   : Reached maximum number of connections?			*/
/*																	*/
/********************************************************************/
BOOL CFTPServer::CheckMaxUsers()
{
	if (m_nConnectionCount > m_nMaxUsers)
		return TRUE;
	else
		return FALSE;
}


/********************************************************************/
/*																	*/
/* Function name : OnTimer											*/
/* Description   : Update statictics.								*/
/*																	*/
/********************************************************************/
void CFTPServer::OnTimer(UINT nIDEvent) 
{
	// update statictics ?
	if (nIDEvent == 1)
	{
		m_pEventSink->OnFTPSentBytesChange(m_dwTotalSentBytes);
		m_pEventSink->OnFTPReceivedBytesChange(m_dwTotalReceivedBytes);
		m_pEventSink->OnFTPStatisticChange(0, m_nTotalConnections);
		m_pEventSink->OnFTPStatisticChange(1, m_nConnectionCount);
		m_pEventSink->OnFTPStatisticChange(2, m_nFilesDownloaded);
		m_pEventSink->OnFTPStatisticChange(3, m_nFilesUploaded);
		m_pEventSink->OnFTPStatisticChange(4, m_nFailedDownloads);
		m_pEventSink->OnFTPStatisticChange(5, m_nFailedUploads);
	}
	CWnd::OnTimer(nIDEvent);
}


/********************************************************************/
/*																	*/
/* Function name : SetSecurityMode									*/
/* Description   : Set security mode.								*/
/*																	*/
/********************************************************************/
void CFTPServer::SetSecurityMode(BOOL bBlockSpecific)
{
	m_nSecurityMode = bBlockSpecific ? 0 : 1;
}


/********************************************************************/
/*																	*/
/* Function name : IsIPAddressAllowed								*/
/* Description   : Check (based on blockmode) if IP is allowed.		*/
/*																	*/
/********************************************************************/
BOOL CFTPServer::IsIPAddressAllowed(LPCTSTR lpszIPAddress)
{
	if (m_nSecurityMode == 0)
	{
		return !m_SecurityManager.IsIPAddressBlocked(lpszIPAddress);
	}
	else
	{
		return m_SecurityManager.IsIPAddressNonBlocked(lpszIPAddress);
	}
}

⌨️ 快捷键说明

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