Beispiel #1
0
bool CServer::Create()
{
	//Create window
	WNDCLASSEX wndclass{};
	wndclass.cbSize = sizeof wndclass;
	wndclass.lpfnWndProc = WindowProc;
	wndclass.hInstance = GetModuleHandle(0);
	wndclass.lpszClassName = _T("FileZilla Server Helper Window");

	RegisterClassEx(&wndclass);

	m_hWnd = CreateWindow(_T("FileZilla Server Helper Window"), _T("FileZilla Server Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0));
	if (!m_hWnd)
		return false;
	SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG)this);

	hMainWnd = m_hWnd;

	m_pOptions = new COptions;
	m_pFileLogger = new CFileLogger(m_pOptions);
	m_pAutoBanManager = new CAutoBanManager(m_pOptions);

	//Create the threads
	int num = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM);
	for (int i = 0; i < num; ++i) {
		int index = GetNextThreadNotificationID();
		CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
		m_ThreadNotificationIDs[index] = pThread;
		if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) {
			pThread->ResumeThread();
			m_ThreadArray.push_back(pThread);
		}
	}

	m_pFileLogger->Log(GetProductVersionString() + _T(" started"));
	m_pFileLogger->Log(_T("Initializing Server."));

	m_nTimerID = SetTimer(m_hWnd, 1234, 10000, NULL);
	ASSERT(m_nTimerID);

	m_nBanTimerID = SetTimer(m_hWnd, 1235, 60000, NULL);
	ASSERT(m_nBanTimerID);

	if (CreateListenSocket()) {
		m_nServerState = STATE_ONLINE;
		ShowStatus(_T("Server online."), 0);
	}
	else
		ShowStatus(_T("Server not online."), 1);

	CreateAdminListenSocket();

	m_sslLoader = make_unique<CAsyncSslSocketLayer>(0);
	m_sslLoader->InitSSL();

	return true;
}
Beispiel #2
0
SERVERDLL int servermain( const serverstartdata_t &data )
{
	//Init filesystem
	filesystem::Filesystem &filesys = filesystem::Filesystem::GetInstance();
	filesys.mountArchive("data.rpaf");

	g_ServerData = new serverstartdata_t( data );

	CServerThread *serverThread = new CServerThread(g_ServerData);

	if(data.bThreaded)
		serverThread->Start();
	else
		serverThread->StartSync();

	return SERVERCREATEERROR_NONE;
}
Beispiel #3
0
bool CServer::ToggleActive(int nServerState)
{
	if (nServerState & STATE_MASK_GOOFFLINE) {
		if (m_nServerState & STATE_MASK_GOOFFLINE)
			return false;

		int ftm_gooffline_arg{};
		switch (nServerState & STATE_MASK_GOOFFLINE) {
		case STATE_GOOFFLINE_LOGOUT:
			ftm_gooffline_arg = 2;
			break;
		case STATE_GOOFFLINE_WAITTRANSFER:
			ftm_gooffline_arg = 1;
			break;
		case STATE_GOOFFLINE_NOW:
			ftm_gooffline_arg = 0;
			break;
		default:
			return false;
		}

		for (auto & listenSocket : m_ListenSocketList) {
			listenSocket->Close();
			delete listenSocket;
		}
		m_ListenSocketList.clear();

		std::move(m_ThreadArray.begin(), m_ThreadArray.end(), std::back_inserter(m_ClosedThreads));
		m_ThreadArray.clear();
		for (auto & closedThread : m_ClosedThreads) {
			closedThread->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, ftm_gooffline_arg);
		}
		m_nServerState &= ~STATE_ONLINE;
		if (!m_ClosedThreads.empty()) {
			m_nServerState |= nServerState & STATE_MASK_GOOFFLINE;
		}
	}
	else if (nServerState & STATE_ONLINE) {
		if (m_ListenSocketList.empty()) {
			if (!CreateListenSocket()) {
				ShowStatus(_T("Failed to create a listen socket on any of the specified ports. Server is not online!"), 1);
				return true;
			}
		}

		if (!m_ListenSocketList.empty()) {
			ShowStatus(_T("Server online"), 0);
			int num = (m_pOptions ? (int)m_pOptions->GetOptionVal(OPTION_THREADNUM) : 2);

			//Recreate the threads
			while (m_ThreadArray.size() < num) {
				int index = GetNextThreadNotificationID();
				CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
				m_ThreadNotificationIDs[index] = pThread;
				if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) {
					m_ThreadArray.push_back(pThread);
					pThread->ResumeThread();
				}
			}
		}
		for (auto iter = m_ListenSocketList.begin(); iter != m_ListenSocketList.end(); ++iter)
			(*iter)->m_bLocked = nServerState & STATE_LOCKED;

		// Set closing threads to "wait until logout" mode.
		for (std::list<CServerThread *>::iterator iter = m_ClosedThreads.begin(); iter != m_ClosedThreads.end(); ++iter)
			(*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);

		m_nServerState = (m_ListenSocketList.empty() ? 0 : STATE_ONLINE) | (nServerState & STATE_LOCKED);
	}

	SendState();
	return true;
}
Beispiel #4
0
BOOL CServer::ProcessCommand(CAdminSocket *pAdminSocket, int nID, unsigned char *pData, int nDataLength)
{
	switch (nID)
	{
	case 2:
		if (!nDataLength) {
			unsigned char buffer[2];
			buffer[0] = m_nServerState / 256;
			buffer[1] = m_nServerState % 256;
			pAdminSocket->SendCommand(1, 2, buffer, 2);
		}
		else if (nDataLength == 2) {
			ToggleActive(*pData * 256 + pData[1]);
			unsigned char buffer[2];
			buffer[0] = m_nServerState / 256;
			buffer[1] = m_nServerState % 256;
			pAdminSocket->SendCommand(1, 2, buffer, 2);
		}
		else
			pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1);
		break;
	case 3:
		if (!nDataLength) {
			pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1);
		}
		else if (*pData == USERCONTROL_GETLIST) {
			int len = 4;
			std::map<int, t_connectiondata>::iterator iter;
			for (iter = m_UsersList.begin(); iter != m_UsersList.end(); ++iter) {
				const t_connectiondata& data = iter->second;
				auto ip = ConvToNetwork(data.ip);
				auto user = ConvToNetwork(data.user);
				len += 4 + ip.size() + 2 + 4 + user.size() + 2 + 1;
				if (data.transferMode) {
					auto physicalFile = ConvToNetwork(data.physicalFile);
					auto logicalFile = ConvToNetwork(data.logicalFile);
					len += 2 + physicalFile.size() + 2 + logicalFile.size();

					if (data.currentOffset != 0)
						len += 8;
					if (data.totalSize != -1)
						len += 8;
				}
			}
			unsigned char *buffer = new unsigned char[len];
			buffer[0] = USERCONTROL_GETLIST;
			buffer[1] = ((m_UsersList.size() / 256) / 256) & 0xff;
			buffer[2] = (m_UsersList.size() / 256) & 0xff;
			buffer[3] = m_UsersList.size() % 256;
			unsigned char *p = buffer + 4;
			for (iter = m_UsersList.begin(); iter != m_UsersList.end(); ++iter) {
				const t_connectiondata& data = iter->second;
				auto ip = ConvToNetwork(data.ip);
				auto user = ConvToNetwork(data.user);

				memcpy(p, &data.userid, 4);
				p += 4;
				*p++ = (ip.size() / 256) & 0xff;
				*p++ = ip.size() % 256;
				memcpy(p, ip.c_str(), ip.size());
				p += ip.size();

				memcpy(p, &data.port, 4);
				p += 4;

				*p++ = (user.size() / 256) & 0xff;
				*p++ = user.size() % 256;
				memcpy(p, user.c_str(), user.size());
				p += user.size();

				*p = data.transferMode;
				if (data.transferMode) {
					// Bit 5 and 6 indicate presence of currentOffset and totalSize.
					if (data.currentOffset != 0) {
						*p |= 0x20;
					}
					if (data.totalSize != -1) {
						*p |= 0x40;
					}
					p++;

					auto physicalFile = ConvToNetwork(data.physicalFile);
					*p++ = (physicalFile.size() / 256) & 0xff;
					*p++ = physicalFile.size() % 256;
					memcpy(p, physicalFile.c_str(), physicalFile.size());
					p += physicalFile.size();

					auto logicalFile = ConvToNetwork(data.logicalFile);
					*p++ = (logicalFile.size() / 256) & 0xff;
					*p++ = logicalFile.size() % 256;
					memcpy(p, logicalFile.c_str(), logicalFile.size());
					p += logicalFile.size();

					if (data.currentOffset != 0) {
						memcpy(p, &data.currentOffset, 8);
						p += 8;
					}
					if (data.totalSize != -1) {
						memcpy(p, &data.totalSize, 8);
						p += 8;
					}
				}
				else {
					p++;
				}
			}
			m_pAdminInterface->SendCommand(1, 3, buffer, len);
			delete [] buffer;
		}
		else if (*pData == USERCONTROL_KICK || *pData == USERCONTROL_BAN) {
			if (nDataLength != 5)
				pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
			else {
				int nUserID;
				memcpy(&nUserID, pData+1, 4);

				std::map<int, t_connectiondata>::iterator iter = m_UsersList.find(nUserID);
				if (iter!=m_UsersList.end()) {
					if (*pData == USERCONTROL_BAN) {
						// Get the list of IP filter rules.
						CStdString ips = m_pOptions->GetOption(OPTION_IPFILTER_DISALLOWED);
						if (ips != _T(""))
							ips += _T(" ");

						int pos = ips.Find(' ');
						while (pos != -1) {
							CStdString blockedIP = ips.Left(pos);
							ips = ips.Mid(pos + 1);
							pos = ips.Find(' ');

							if (MatchesFilter(blockedIP, iter->second.ip))
								break;
						}
						if (pos == -1) {
							ips = m_pOptions->GetOption(OPTION_IPFILTER_DISALLOWED);
							if (ips != _T(""))
								ips += _T(" ");
							ips += iter->second.ip;
							m_pOptions->SetOption(OPTION_IPFILTER_DISALLOWED, ips);
						}
					}
					t_controlmessage *msg = new t_controlmessage;
					msg->command = USERCONTROL_KICK;
					msg->socketid = nUserID;
					iter->second.pThread->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_CONTROL, (LPARAM)msg);
					char buffer[2];
					buffer[0] = *pData;
					buffer[1] = 0;
					pAdminSocket->SendCommand(1, 3, &buffer, 2);
				}
				else {
					char buffer[2];
					buffer[0] = USERCONTROL_KICK;
					buffer[1] = 1;
					pAdminSocket->SendCommand(1, 3, &buffer, 2);
				}
			}
		}
		else
			pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data", strlen("\001Protocol error: Invalid data")+1);
		break;
	case 5:
		if (!nDataLength) {
			unsigned char *pBuffer = NULL;
			DWORD nBufferLength = 0;
			if (m_pOptions && m_pOptions->GetAsCommand(&pBuffer, &nBufferLength)) {
				pAdminSocket->SendCommand(1, 5, pBuffer, nBufferLength);
				delete [] pBuffer;
			}
		}
		else if (m_pOptions) {
			if (nDataLength < 2)
				pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
			else {
				CStdString const listenPorts = m_pOptions->GetOption(OPTION_SERVERPORT);
				CStdString const listenPortsSsl = m_pOptions->GetOption(OPTION_TLSPORTS);
				bool const enableSsl = m_pOptions->GetOptionVal(OPTION_ENABLETLS) != 0;
				CStdString const ipBindings = m_pOptions->GetOption(OPTION_IPBINDINGS);
				int const nAdminListenPort = (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT);
				CStdString const adminIpBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS);

				CStdString peerIP;
				UINT port = 0;
				bool bLocal = false;
				if (!pAdminSocket->GetPeerName(peerIP, port))
					return FALSE;
				else
					bLocal = IsLocalhost(peerIP);

				if (!m_pOptions->ParseOptionsCommand(pData, nDataLength, bLocal)) {
					pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import settings.", strlen("\001Protocol error: Invalid data, could not import settings.")+1);
					char buffer = 1;
					pAdminSocket->SendCommand(1, 5, &buffer, 1);
					break;
				}

				char buffer = 0;
				pAdminSocket->SendCommand(1, 5, &buffer, 1);

				unsigned int threadnum = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM);
				if (m_nServerState & STATE_ONLINE) {
					if (threadnum > m_ThreadArray.size()) {
						while (threadnum > m_ThreadArray.size()) {
							int index = GetNextThreadNotificationID();
							CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
							m_ThreadNotificationIDs[index] = pThread;
							if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) {
								pThread->ResumeThread();
								m_ThreadArray.push_back(pThread);
							}
						}
						CStdString str;
						str.Format(_T("Number of threads increased to %d."), threadnum);
						ShowStatus(str, 0);
					}
					else if (threadnum < m_ThreadArray.size()) {
						CStdString str;
						str.Format(_T("Decreasing number of threads to %d."), threadnum);
						ShowStatus(str, 0);
						unsigned int i = 0;
						std::vector<CServerThread *> newList;
						for (auto iter = m_ThreadArray.begin(); iter != m_ThreadArray.end(); iter++, i++) {
							if (i >= threadnum) {
								(*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);
								m_ClosedThreads.push_back(*iter);
							}
							else
								newList.push_back(*iter);
						}
						m_ThreadArray.swap(newList);
					}
				}
				if (listenPorts != m_pOptions->GetOption(OPTION_SERVERPORT) ||
					enableSsl != (m_pOptions->GetOptionVal(OPTION_ENABLETLS) != 0) ||
					(m_pOptions->GetOptionVal(OPTION_ENABLETLS) && listenPortsSsl != m_pOptions->GetOption(OPTION_TLSPORTS)) ||
					ipBindings != m_pOptions->GetOption(OPTION_IPBINDINGS))
				{
					if (!m_ListenSocketList.empty()) {
						ShowStatus(_T("Closing all listening sockets"), 0);
						for (std::list<CListenSocket*>::iterator listIter = m_ListenSocketList.begin(); listIter != m_ListenSocketList.end(); ++listIter) {
							(*listIter)->Close();
							delete *listIter;
						}
						m_ListenSocketList.clear();

						if (!CreateListenSocket()) {
							ShowStatus(_T("Failed to create a listen socket on any of the specified ports. Server is not online!"), 1);
							m_nServerState &= ~STATE_ONLINE;
						}
						else {
							ShowStatus(_T("Listen socket port changed"), 0);
							if (!(m_nServerState & STATE_MASK_GOOFFLINE))
								m_nServerState |= STATE_ONLINE;
						}
						SendState();
					}
				}
				if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT) || adminIpBindings != m_pOptions->GetOption(OPTION_ADMINIPBINDINGS)) {
					CreateAdminListenSocket();
				}

				VerifyTlsSettings(pAdminSocket);
				VerifyPassiveModeSettings(pAdminSocket);
			}
		}
		break;
	case 6:
		if (!nDataLength) {
			unsigned char *pBuffer = NULL;
			DWORD nBufferLength = 0;
			CPermissions permissions = CPermissions(std::function<void()>());
			permissions.GetAsCommand(&pBuffer, &nBufferLength);
			pAdminSocket->SendCommand(1, 6, pBuffer, nBufferLength);
			delete [] pBuffer;
		}
		else {
			if (nDataLength < 2)
				pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
			else {
				CPermissions permissions = CPermissions(std::function<void()>());
				if (!permissions.ParseUsersCommand(pData, nDataLength)) {
					pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import account settings.", strlen("\001Protocol error: Invalid data, could not import account settings.")+1);
					char buffer = 1;
					pAdminSocket->SendCommand(1, 6, &buffer, 1);
					break;
				}
				char buffer = 0;
				pAdminSocket->SendCommand(1, 6, &buffer, 1);
			}
		}
		break;
	case 8:
		pAdminSocket->SendCommand(1, 8, NULL, 0);
		break;
	default:
		{
			CStdStringA str;
			str.Format("\001Protocol error: Unknown command (%d).", nID);
			pAdminSocket->SendCommand(1, 1, str.c_str(), str.GetLength());
		}
		break;
	}

	return TRUE;
}
Beispiel #5
0
LRESULT CALLBACK CServer::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	CServer *pServer=(CServer *)GetWindowLongPtr(hWnd, GWLP_USERDATA);

	if (message == WM_CLOSE) {
		pServer->OnClose();
		return 0;
	}
	else if (hWnd && message == WM_DESTROY) {
		ASSERT (hWnd == pServer->m_hWnd);
		HANDLE *handle = new HANDLE[pServer->m_ThreadArray.size()];
		unsigned int i = 0;
		for (auto iter = pServer->m_ThreadArray.begin(); iter != pServer->m_ThreadArray.end(); ++iter, ++i) {
			handle[i] = (*iter)->m_hThread;
			(*iter)->PostThreadMessage(WM_QUIT, 0, 0);
		}
		for (i = 0; i < pServer->m_ThreadArray.size(); ++i) {
			int res = WaitForSingleObject(handle[i], INFINITE);
			if (res == WAIT_FAILED)
				res = GetLastError();
		}
		delete [] handle;
		handle = new HANDLE[pServer->m_ClosedThreads.size()];
		i = 0;
		for (auto iter = pServer->m_ClosedThreads.begin(); iter != pServer->m_ClosedThreads.end(); ++iter, ++i) {
			handle[i] = (*iter)->m_hThread;
			(*iter)->PostThreadMessage(WM_QUIT, 0, 0);
		}
		for (i = 0; i < pServer->m_ClosedThreads.size(); ++i) {
			int res = WaitForSingleObject(handle[i], INFINITE);
			if (res == WAIT_FAILED)
				res = GetLastError();
		}
		delete [] handle;
		pServer->m_AdminListenSocketList.clear();
		delete pServer->m_pAdminInterface;
		pServer->m_pAdminInterface = NULL;
		delete pServer->m_pOptions;
		pServer->m_pOptions = NULL;
		if (pServer->m_nTimerID) {
			KillTimer(pServer->m_hWnd, pServer->m_nTimerID);
			pServer->m_nTimerID = 0;
		}
		PostQuitMessage(0);
		return 0;
	}
	else if (message == WM_TIMER)
		pServer->OnTimer(wParam);
	else if (message == WM_FILEZILLA_RELOADCONFIG) {
		COptions options;
		options.ReloadConfig();
		CPermissions perm = CPermissions(std::function<void()>());
		perm.ReloadConfig();
	}
	else if (message >= WM_FILEZILLA_SERVERMSG) {
		UINT index = message - WM_FILEZILLA_SERVERMSG;
		if (index >= pServer->m_ThreadNotificationIDs.size())
			return 0;

		CServerThread *pThread = pServer->m_ThreadNotificationIDs[index];
		if (pThread) {
			std::list<CServerThread::t_Notification> notifications;
			pThread->GetNotifications(notifications);
			for (std::list<CServerThread::t_Notification>::const_iterator iter = notifications.begin(); iter != notifications.end(); iter++)
				if (pServer->OnServerMessage(pThread, iter->wParam, iter->lParam) != 0)
					break;
		}
		return 0;
	}

	return ::DefWindowProc(hWnd, message, wParam, lParam);
}
Beispiel #6
0
bool CServer::Create()
{
	//Create window
	WNDCLASSEX wndclass; 
	wndclass.cbSize=sizeof wndclass; 
	wndclass.style=0; 
	wndclass.lpfnWndProc=WindowProc; 
	wndclass.cbClsExtra=0; 
	wndclass.cbWndExtra=0; 
	wndclass.hInstance=GetModuleHandle(0); 
	wndclass.hIcon=0; 
	wndclass.hCursor=0; 
	wndclass.hbrBackground=0; 
	wndclass.lpszMenuName=0; 
	wndclass.lpszClassName=_T("FileZilla Server Helper Window"); 
	wndclass.hIconSm=0; 
	
	RegisterClassEx(&wndclass);
	
	m_hWnd=CreateWindow(_T("FileZilla Server Helper Window"), _T("FileZilla Server Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0));
	if (!m_hWnd)
		return false;
	SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this);

	hMainWnd = m_hWnd;

	m_pOptions=new COptions;
	m_pFileLogger = new CFileLogger(m_pOptions);
	
	//Create the threads
	int num = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM);
	for (int i=0;i<num;i++)
	{
		CServerThread *pThread = new CServerThread;
		if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED))
		{
			pThread->ResumeThread();
			m_ThreadArray.push_back(pThread);
		}
	}
	
	m_pFileLogger->Log(GetVersionString() + " started");
	m_pFileLogger->Log("Initializing Server.");
	
	m_pListenSocket = new CListenSocket(this);
	m_pListenSocket->m_pThreadList = &m_ThreadArray;
	
	//TODO Start on startup check
	int nPort = (int)m_pOptions->GetOptionVal(OPTION_SERVERPORT);
	CStdString str;
	str.Format("Creating listen socket on port %d...", nPort);
	ShowStatus(str, 0);
	if (!m_pListenSocket->Create(nPort, SOCK_STREAM, FD_ACCEPT, 0) || !m_pListenSocket->Listen())
	{
		str.Format("Failed to create listen socket on port %d. Server is not online!", nPort);
		ShowStatus(str, 1);
		delete m_pListenSocket;
		m_pListenSocket = NULL;
	}
	else
	{
		str.Format("Server online.");
		ShowStatus(str, 0);
		m_nServerState = 1;
	}

	m_nTimerID = SetTimer(m_hWnd, 1234, 10000, NULL);
	ASSERT(m_nTimerID);

	CreateAdminListenSocket();

	return true;
}
Beispiel #7
0
BOOL CServer::ToggleActive(int nServerState)
{
	if (nServerState&2)
	{
		if (m_pListenSocket)
		{
			m_pListenSocket->Close();
			delete m_pListenSocket;
			m_pListenSocket = NULL;
		}
		for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++)
			(*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 0);			
		if (m_nServerState & 1)
			m_nServerState = m_nServerState |= 2;
	}
	else if (nServerState&4)
	{
		if (m_pListenSocket)
		{
			m_pListenSocket->Close();
			delete m_pListenSocket;
			m_pListenSocket = NULL;
		}
		for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++)
			(*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);			
		if (m_nServerState & 1)
			m_nServerState = m_nServerState |= 4;
	}
	else if (nServerState&8)
	{
		if (m_pListenSocket)
		{
			m_pListenSocket->Close();
			delete m_pListenSocket;
			m_pListenSocket = NULL;
		}
		for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++)
			(*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 1);			
		if (m_nServerState & 1)
			m_nServerState = m_nServerState |= 8;
	}
	else if (nServerState&1)
	{
		if (!m_pListenSocket)
		{
			m_pListenSocket = new CListenSocket(this);
			m_pListenSocket->m_pThreadList=&m_ThreadArray;
			
			int nPort = (m_pOptions ? (int)m_pOptions->GetOptionVal(OPTION_SERVERPORT) : 21);
			CStdString str;
			str.Format("Creating listen socket on port %d...", nPort);
			ShowStatus(str, 0);
			if (!m_pListenSocket->Create(nPort, SOCK_STREAM, FD_ACCEPT, 0) || !m_pListenSocket->Listen())
			{
				delete m_pListenSocket;
				m_pListenSocket = NULL;
				str.Format("Failed to create listen socket on port %d. Server is not online!", nPort);
				ShowStatus(str, 1);
			}
			else
			{
				ShowStatus(_T("Server online"), 0);
			}
		}

		if (m_pListenSocket)
		{
			int i=0;
			int num = (m_pOptions ? (int)m_pOptions->GetOptionVal(OPTION_THREADNUM) : 2);
			for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++, i++)
				if (i<num)
					(*iter)->DontQuit();
				else
					break;
			//Recreate the threads
			for (i=m_ThreadArray.size();i<num;i++)
			{
				CServerThread *pThread = new CServerThread;
				if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED))
				{
					pThread->ResumeThread();
					m_ThreadArray.push_back(pThread);
				}
			}
		}
		m_pListenSocket->m_bLocked = nServerState & 0x10;

		m_nServerState = (m_pListenSocket?1:0) + (nServerState&16);
	}
	unsigned char buffer[2];
	buffer[0]=m_nServerState/256;
	buffer[1]=m_nServerState%256;
	m_pAdminInterface->SendCommand(2, 2, buffer, 2);
	return TRUE;
}
Beispiel #8
0
BOOL CServer::ProcessCommand(CAdminSocket *pAdminSocket, int nID, unsigned char *pData, int nDataLength)
{
	switch (nID)
	{
	case 2:
		if (!nDataLength)
		{
			unsigned char buffer[2];
			buffer[0]=m_nServerState/256;
			buffer[1]=m_nServerState%256;
			pAdminSocket->SendCommand(1, 2, buffer, 2);
		}
		else if (nDataLength == 2)
		{
			ToggleActive(*pData*256+pData[1]);
			unsigned char buffer[2];
			buffer[0]=m_nServerState/256;
			buffer[1]=m_nServerState%256;
			pAdminSocket->SendCommand(1, 2, buffer, 2);
		}
		else
			pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
		break;
	case 3:
		if (!nDataLength)
			pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
		else if (*pData == USERCONTROL_GETLIST)
		{
			int len = 3;
			std::map<int, t_connectiondata>::iterator iter;
			for (iter=m_UsersList.begin(); iter!=m_UsersList.end(); iter++)
				len += 4 + strlen(iter->second.ip)+2 + 4 + strlen(iter->second.user)+2;
			unsigned char *buffer = new unsigned char[len];
			buffer[0] = USERCONTROL_GETLIST;
			buffer[1] = m_UsersList.size() / 256;
			buffer[2] = m_UsersList.size() % 256;
			unsigned char *p = buffer + 3;
			for (iter=m_UsersList.begin(); iter!=m_UsersList.end(); iter++)
			{
				USES_CONVERSION;
				memcpy(p, &iter->second.userid, 4);
				p+=4;
				*p++ = strlen(iter->second.ip) / 256;
				*p++ = strlen(iter->second.ip) % 256;
				memcpy(p, T2CA(iter->second.ip), strlen(T2CA(iter->second.ip)));
				p+=strlen(T2CA(iter->second.ip));

				memcpy(p, &iter->second.port, 4);
				p+=4;

				if (iter->second.user)
				{
					*p++ = strlen(iter->second.user) / 256;
					*p++ = strlen(iter->second.user) % 256;
					memcpy(p, T2CA(iter->second.user), strlen(T2CA(iter->second.user)));
					p+=strlen(T2CA(iter->second.user));
				}
				else
				{
					*p++ = 0;
					*p++ = 0;
				}
				
			}
			m_pAdminInterface->SendCommand(1, 3, buffer, len);			
			delete [] buffer;
		}
		else if (*pData == USERCONTROL_KICK)
		{
			if (nDataLength != 5)
				pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
			else
			{
				int nUserID;
				memcpy(&nUserID, pData+1, 4);
				
				std::map<int, t_connectiondata>::iterator iter = m_UsersList.find(nUserID);
				if (iter!=m_UsersList.end())
				{
					t_controlmessage *msg=new t_controlmessage;
					msg->command=USERCONTROL_KICK;
					msg->socketid=nUserID;
					iter->second.pThread->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_CONTROL, (LPARAM)msg);
					char buffer[2];
					buffer[0] = USERCONTROL_KICK;
					buffer[1] = 0;
					pAdminSocket->SendCommand(1, 3, &buffer, 2);
				}
				else
				{
					char buffer[2];
					buffer[0] = USERCONTROL_KICK;
					buffer[1] = 1;
					pAdminSocket->SendCommand(1, 3, &buffer, 2);
				}
			}
		}
		else
			pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data", strlen("\001Protocol error: Invalid data")+1);
		break;
	case 5:
		if (!nDataLength)
		{
			char *pBuffer = NULL;
			DWORD nBufferLength = 0;
			if (m_pOptions && m_pOptions->GetAsCommand(&pBuffer, &nBufferLength))
			{
				pAdminSocket->SendCommand(1, 5, pBuffer, nBufferLength);
				delete [] pBuffer;
			}
		}
		else if (m_pOptions)
		{
			if (nDataLength < 2)
				pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
			else
			{
				int nListenPort = (int)m_pOptions->GetOptionVal(OPTION_SERVERPORT);
				int nAdminListenPort = (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT);
				CStdString adminIpBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS);
				
				SOCKADDR_IN sockAddr;
				memset(&sockAddr, 0, sizeof(sockAddr));
				int nSockAddrLen = sizeof(sockAddr);	
				BOOL bLocal = pAdminSocket->GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen) && sockAddr.sin_addr.S_un.S_addr == 0x0100007f;

				if (!m_pOptions->ParseOptionsCommand(pData, nDataLength, bLocal))
				{
					pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import settings.", strlen("\001Protocol error: Invalid data, could not import settings.")+1);
					char buffer = 1;
					pAdminSocket->SendCommand(1, 5, &buffer, 1);
					break;
				}

				char buffer = 0;
				pAdminSocket->SendCommand(1, 5, &buffer, 1);

				unsigned int threadnum = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM);
				if (threadnum>m_ThreadArray.size())
				{
					int newthreads=threadnum-m_ThreadArray.size();
					for (int i=0;i<newthreads;i++)
					{
						CServerThread *pThread = new CServerThread;
						if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED))
						{
							pThread->ResumeThread();
							m_ThreadArray.push_back(pThread);
						}
					}
					CStdString str;
					str.Format("Number of threads increased to %d.", threadnum);
					ShowStatus(str, 0);
				}
				else if (threadnum<m_ThreadArray.size())
				{
					CStdString str;
					str.Format("Decreasing number of threads to %d.", threadnum);
					ShowStatus(str, 0);
					unsigned int i=0;
					for (std::list<CServerThread *>::iterator iter=m_ThreadArray.begin(); iter!=m_ThreadArray.end(); iter++,i++)
						if (i>=threadnum)
							(*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2);
				}
				if (nListenPort != m_pOptions->GetOptionVal(OPTION_SERVERPORT))
				{
					if (m_pListenSocket)
					{
						CStdString str;
						str.Format("Closing listen socket on port %d", nListenPort);
						ShowStatus(str, 0);
						m_pListenSocket->Close();
						str.Format("Creating listen socket on port %I64d...", m_pOptions->GetOptionVal(OPTION_SERVERPORT));
						ShowStatus(str, 0);
						if (!m_pListenSocket->Create((int)m_pOptions->GetOptionVal(OPTION_SERVERPORT), SOCK_STREAM,FD_ACCEPT,0) || !m_pListenSocket->Listen())
						{
							delete m_pListenSocket;
							m_pListenSocket = NULL;
							str.Format("Failed to create listen socket on port %I64d. Server is not online!", m_pOptions->GetOptionVal(OPTION_SERVERPORT));
							ShowStatus(str,1);
							m_nServerState = 0;
						}
						else
							ShowStatus("Listen socket port changed",0);
					}
				}
				if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT) || adminIpBindings!=m_pOptions->GetOption(OPTION_ADMINIPBINDINGS))
				{
					if (nAdminListenPort == m_pOptions->GetOptionVal(OPTION_ADMINPORT))
					{
						for (std::list<CAdminListenSocket*>::iterator iter = m_AdminListenSocketList.begin(); iter!=m_AdminListenSocketList.end(); iter++)
						{
							(*iter)->Close();
							delete *iter;
						}
						m_AdminListenSocketList.clear();
					}
					CAdminListenSocket *pSocket = new CAdminListenSocket(m_pAdminInterface);
					if (!pSocket->Create((int)m_pOptions->GetOptionVal(OPTION_ADMINPORT), SOCK_STREAM, FD_ACCEPT, (m_pOptions->GetOption(OPTION_ADMINIPBINDINGS)!="*") ? _T("127.0.0.1") : NULL))
					{
						delete pSocket;
						CStdString str;
						str.Format(_T("Failed to change admin listen port to %I64d."), m_pOptions->GetOptionVal(OPTION_ADMINPORT));
						m_pOptions->SetOption(OPTION_ADMINPORT, nAdminListenPort);
						ShowStatus(str, 1);
					}
					else
					{
						pSocket->Listen();
						for (std::list<CAdminListenSocket*>::iterator iter = m_AdminListenSocketList.begin(); iter!=m_AdminListenSocketList.end(); iter++)
						{
							(*iter)->Close();
							delete *iter;
						}
						m_AdminListenSocketList.clear();

						m_AdminListenSocketList.push_back(pSocket);
						if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT))
						{
							CStdString str;
							str.Format(_T("Admin listen port changed to %I64d."), m_pOptions->GetOptionVal(OPTION_ADMINPORT));
							ShowStatus(str, 0);
						}

						if (m_pOptions->GetOption(OPTION_ADMINIPBINDINGS) != "*")
						{
							BOOL bError = FALSE;
							CStdString str = _T("Failed to bind the admin interface to the following IPs:");
							CStdString ipBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS);

							if (ipBindings != "")
								ipBindings += " ";
							while (ipBindings != "")
							{
								int pos = ipBindings.Find(" ");
								if (pos == -1)
									break;
								CStdString ip = ipBindings.Left(pos);
								ipBindings = ipBindings.Mid(pos+1);
								CAdminListenSocket *pAdminListenSocket = new CAdminListenSocket(m_pAdminInterface);
								if (!pAdminListenSocket->Create((int)m_pOptions->GetOptionVal(OPTION_ADMINPORT), SOCK_STREAM, FD_ACCEPT, ip) || !pAdminListenSocket->Listen())
								{
									bError = TRUE;
									str += _T(" ") + ip;
									delete pAdminListenSocket;
								}
								else
									m_AdminListenSocketList.push_back(pAdminListenSocket);
							}
							if (bError)
								ShowStatus(str, 1);
						}
						if (adminIpBindings!=m_pOptions->GetOption(OPTION_ADMINIPBINDINGS))
							ShowStatus(_T("Admin interface IP bindings changed"), 0);
					}
	
				}
			}
		}
		break;
	case 6:
		if (!nDataLength)
		{
			char *pBuffer = NULL;
			DWORD nBufferLength = 0;
			CPermissions permissions;
			permissions.GetAsCommand(&pBuffer, &nBufferLength);
			pAdminSocket->SendCommand(1, 6, pBuffer, nBufferLength);
			delete [] pBuffer;
		}
		else
		{
			if (nDataLength < 2)
				pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1);
			else
			{
				CPermissions permissions;
				if (!permissions.ParseUsersCommand(pData, nDataLength))
				{
					pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import account settings.", strlen("\001Protocol error: Invalid data, could not import account settings.")+1);
					char buffer = 1;
					pAdminSocket->SendCommand(1, 6, &buffer, 1);
					break;
				}
				char buffer = 0;
				pAdminSocket->SendCommand(1, 6, &buffer, 1);
			}
		}
		break;
	case 8:
		pAdminSocket->SendCommand(1, 8, NULL, 0);
		break;
	default:
		{
			CStdString str;
			str.Format("\001Protocol error: Unknown command (%d).", nID);
			pAdminSocket->SendCommand(1, 1, str.c_str(), str.GetLength());
		}
		break;
	}

	return TRUE;
}