📄 nfsserver.cpp
字号:
//////////////////////////////////////////////////////////////////////
// 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 + -