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

📄 nfsserver.cpp

📁 c++系统开发实例精粹内附的80例源代码 环境:windows2000,c++6.0
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////////////////////
// FileFury
// Copyright (c) 2000 Tenebril Incorporated
// All rights reserved.
//
// This source code is governed by the Tenebril open source
// license (http://www.tenebril.com/developers/opensource/license.html)
//
// For more information on this and other open source applications,
// visit the Tenebril OpenSource page:
//       http://www.tenebril.com/developers/opensource
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "NetworkFileSystem.h"
#include "NFSServer.h"
#include "NetworkMonitorFrame.h"
#include "Oscar.h"

#define _afxSockThreadState AfxGetModuleThreadState()
#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE

CNFSServer::CNFSServer(CSecurityFilter *pFilter)
{
	m_nNumInstances = 0;
	m_pEntries = NULL;
	m_nNextID = 0;
	ASSERT(pFilter != NULL);
	m_pFilter = pFilter;

	m_pFilter->Reference();
}

CNFSServer::~CNFSServer()
{
	if(m_pEntries)
	{
		for(UINT i = 0; i < m_nNumInstances; i++)
			delete m_pEntries[i].pFileSystem;

		delete m_pEntries;
	}

	m_pEntries = NULL;
	m_nNumInstances = 0;
	m_pFilter->Dereference();
}

static HANDLE NFSServerHandle;

UINT PASCAL CNFSServer::DriveWork(LPVOID *Param)
{
	CNFSServer *NFSServer;

	// Jump into the object itself
	NFSServer = (CNFSServer *)Param;
	if(!NFSServer)
	{
		NFSServerHandle = NULL;     // Clear the global handle
		return 1;
	}

	// Initialize COM for this thread
	CoInitialize(NULL);    // COM (shortcuts)

	// Initialize this thread's AFX socket stuff (hack for VC6)
#ifdef PER_THREAD_SOCKINIT
	{
		_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
		if (pState->m_pmapSocketHandle == NULL)
			pState->m_pmapSocketHandle = new CMapPtrToPtr;
		if (pState->m_pmapDeadSockets == NULL)
			pState->m_pmapDeadSockets = new CMapPtrToPtr;
		if (pState->m_plistSocketNotifications == NULL)
			pState->m_plistSocketNotifications = new CPtrList;
	}
#endif

	// Set up the receiving socket
	CTimeoutSocket *sock = new CTimeoutSocket;
	UINT nLoopCheck = 0;
	while(!sock->Create(PORT_OSCARNFS))
	{
		Sleep(SOCKET_TIMEOUT);  // Probably just restarted after a close
		nLoopCheck += 1;
		if(nLoopCheck > SOCKET_RETRY_LIMIT)
			return 0;
	}

	sock->Listen(LISTEN_BUFFER);

	CTimeoutSocket *sockClient = NULL;
	while(NFSServer->m_bStayOn)
	{
		// Handle a connection

		if(sockClient)                         // Can't reuse sockets?
			delete sockClient;

		sockClient = new CTimeoutSocket;

		// This will fall through each time the socket times out; it will
		// keep this thread from stalling.
		BOOL bAccepted;
		sock->SetTimeout(SOCKET_TIMEOUT);
		bAccepted = sock->Accept(*sockClient);

		if(bAccepted)
		{
			// Do the work to handle the request / suggestion
			// This function should only be called here to avoid thread stomping
			NFSServer->HandleRequest(sockClient);

			// Close the connection
			sockClient->Close();
		}

		// Keep working until the StayOn flag goes down
	}

	// Clean up memory.
	sock->Close();
	delete sock;
	if(sockClient) delete sockClient;

	// Clean up
	NFSServerHandle = NULL;
	return 1;
}

bool CNFSServer::Start()
{
	CWinThread *NFSServerThread;

	if(NFSServerHandle)
		return false;

	m_bStayOn = true;

	NFSServerThread = AfxBeginThread((AFX_THREADPROC)(CNFSServer::DriveWork),
		(LPVOID)this, THREAD_PRIORITY_LOWEST);

	ASSERT(NFSServerThread);
	if(!NFSServerThread) return FALSE;

	NFSServerHandle = NFSServerThread->m_hThread;

	return true;
}

bool CNFSServer::Stop(bool wait)
{
	DWORD ExitCode = STILL_ACTIVE;

	if(!NFSServerHandle)
		return false;

	m_bStayOn = false;

	while(ExitCode == STILL_ACTIVE && wait)
	{
		if(!GetExitCodeThread(NFSServerHandle, &ExitCode))
			return false;

		if(ExitCode == STILL_ACTIVE)
			Sleep(THREAD_DIE_WAIT);
	}

	return true;
}

void CNFSServer::HandleRequest(CTimeoutSocket *sock)
{
	UINT nRequest;

	AppendComment(_T("NFSServer: Got a request"));

	// Receive the request
	sock->SetTimeout(SOCKET_TIMEOUT);
	if(sock->Receive((void *)&nRequest, sizeof(UINT)) != sizeof(UINT))
	{
		// Receive failed; quit and close the socket
		AppendComment(_T("NFSServer: Could not get request type"));
		return;
	}

	// All commands will first identify themselves with their instance ID,
	// except for the one which seeks a new instance ID.  Handle this special
	// case now.

	if(nRequest == REQUEST_NEWID)
	{
		UINT nClientVer;

		// This is a new connection.
		AppendComment(_T("NFSServer: New client connection"));

		// Get the client version.
		sock->SetTimeout(SOCKET_TIMEOUT);
		if(sock->Receive((void *)&nClientVer, sizeof(UINT)) != sizeof(UINT))
		{
			// Receive failed; quit and close the socket
			AppendComment(_T("NFSServer: Could not receive client version"));
			return;
		}

		// Get the new id and set an appropriate server version.
		UINT nServerVer;
		int nNewID = GenerateNewInstanceID(nClientVer, nServerVer);

		// Send back the instance identifier.
		sock->SetTimeout(SOCKET_TIMEOUT);
		if(sock->Send((void *)&nNewID, sizeof(int)) != sizeof(int))
		{
			// Send failed; quit and close the socket
			AppendComment(_T("NFSServer: Could not send session id"));
			return;
		}

		// Send back the server version.
		sock->SetTimeout(SOCKET_TIMEOUT);
		sock->Send((void *)&nServerVer, sizeof(UINT));

		// The connection will now close.  We don't care if the previous command
		// failed; there's nothing we can do.

		return;
	}

	// Now handle the general case- all other commands will first identify
	// themselves

	ASSERT(nRequest == SUGGEST_SETID);
	if(nRequest != SUGGEST_SETID)
	{
		// For some reason, this command did not identify itself.  Don't
		// allow it to continue.

		AppendComment(_T("NFSServer: Client did not identify himself"));

		return;
	}

	// Get the identifier
	int nInstanceID;
	sock->SetTimeout(SOCKET_TIMEOUT);
	if(sock->Receive((void *)&nInstanceID, sizeof(int)) != sizeof(int))
	{
		AppendComment(_T("NFSServer: Client not get client identity"));
		return;
	}

	// Get the FileSystem object associated with the instance
	CSecureFileSystem *pFileSystem = GetFileSystem(nInstanceID);

	BOOL bDoneInstance;
	if(!pFileSystem)
	{
		// Be fair to the command and return FALSE.

		AppendComment(_T("NFSServer: Client not get secury filesystem"));

		bDoneInstance = FALSE;
		sock->SetTimeout(SOCKET_TIMEOUT);
		sock->Send((void *)&bDoneInstance, sizeof(BOOL));
		return;
	}

	// End the get-identifier stage
	bDoneInstance = TRUE;
	sock->SetTimeout(SOCKET_TIMEOUT);
	if(sock->Send((void *)&bDoneInstance, sizeof(BOOL)) != sizeof(BOOL))
		return;

	// Get the actual command
	sock->SetTimeout(SOCKET_TIMEOUT);
	if(sock->Receive((void *)&nRequest, sizeof(UINT)) != sizeof(UINT))
	{
		// Receive failed; quit and close the socket
		AppendComment(_T("NFSServer: Client not get client request"));
		return;
	}

	AppendComment(_T("NFSServer: Fulfilling client request"));

	// Now parse the command's parameters
	int nOpType, nOpCommand;

	nOpType = (int)(nRequest & OPMASK_TYPE);
	nOpCommand = (int)(nRequest & OPMASK_OPERATION);

	switch(nOpType)
	{
	case OPTYPE_BOOL_0P:
		// Handle SUGGEST_RELEASEIDENTIFIER specially.

		if(nOpCommand == SUGGEST_RELEASEIDENTIFIER)
		{
			ReleaseIdentifier(nInstanceID);

			// Send the result back over the wire.
			BOOL bResult = TRUE;
			sock->Send((void *)&bResult, sizeof(BOOL));
		}
		else
			HandleBoolOp_0P(sock, pFileSystem, nOpCommand);

		break;

	case OPTYPE_BOOL_1P:
		HandleBoolOp_1P(sock, pFileSystem, nOpCommand);
		break;

	case OPTYPE_BOOL_2P:
		HandleBoolOp_2P(sock, pFileSystem, nOpCommand);
		break;

	case OPTYPE_STR_0P:
		HandleStringOp_0P(sock, pFileSystem, nOpCommand);
		break;

	case OPTYPE_STR_1P:
		HandleStringOp_1P(sock, pFileSystem, nOpCommand);
		break;

	case OPTYPE_UINT_1P:

⌨️ 快捷键说明

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