📄 nfs_svr.cpp
字号:
#include <windows.h>
#include <__trace.h>
#include <dyn.h>
#include <tempory.h>
#include <hashtmp.h>
#include <regkey.h>
#include "nfs.h"
#include "nfp.inl"
#if !defined(TRACE_PRINTF) && !defined(NDEBUG) && defined(TRACE) && defined(_CONSOLE)
#include <stdio.h>
#define TRACE_PRINTF( expr ) printf expr
#define TRACE_PRINTF_IF( condition, expr ) ( condition? printf expr: (void)0 )
#endif
#ifdef VERBOSE_TRACE
#define TRACE_VERBOSE_MSG TRACE_PRINTF
#else
#define TRACE_VERBOSE_MSG
#endif
namespace namNFS
{
const size_t MAX_OPENFILES = 0x400;
unsigned ForST_HashTable_getHashCode(ClServerFileObject * p)
{
unsigned uHashCode = (unsigned)p;
unsigned uGranularity = ( sizeof(ClServerFileObject) + sizeof(PVOID) - 1 )
/ sizeof(PVOID) * sizeof(PVOID);
uHashCode = uHashCode/uGranularity;
uHashCode = uHashCode%MAX_OPENFILES;
return uHashCode;
}
class ClOpenFiles : public ST_HashTable<ClServerFileObject *>
{
typedef ST_HashTable<ClServerFileObject *> ClParentClass;
protected:
int m_nOpenFiles;
SOCKET m_Connection;
ClParentClass::add;
ClParentClass::remove;
void clearNode(ClNode & node);
public:
ClOpenFiles( SOCKET Connection ) :
ClParentClass( MAX_OPENFILES ),
m_Connection( Connection ),
m_nOpenFiles( 0 )
{}
~ClOpenFiles();
BOOL add(ClServerFileObject * pFile)
{
if( ClParentClass::add( pFile ) )
{
m_nOpenFiles ++;
return TRUE;
}
return FALSE;
}
BOOL remove(ClServerFileObject * pFile)
{
if( ClParentClass::remove( pFile ) )
{
m_nOpenFiles --;
return TRUE;
}
return FALSE;
}
};
void ClOpenFiles::clearNode(ClNode & node)
{
ClServerFileObject * pFileObject = node.m_data;
if( pFileObject )
{
if( pFileObject->isValid() )
{
delete pFileObject;
node.m_data = NULL;
}
else
{
::OutputDebugString( "!!!Fatal Error: A open file list of a connection is corrupted!!!\n" );
}
}
}
ClOpenFiles::~ClOpenFiles()
{
if( m_nOpenFiles )
{
size_t nItems = m_Table;
// Close all open files in this connection
for(unsigned i = 0; i < nItems; i ++)
{
if( m_Table[i].m_isUsed )
{
clearNode( m_Table[i] );
}
ClNode * p = m_Table[i].m_pNext;
while( p )
{
clearNode( *p );
p = p->m_pNext;
}
} // for
TRACE_PRINTF( ("Closed %d files open in connection %d\n", m_nOpenFiles, m_Connection ) );
}
}
BOOL matchAlias( LPCSTR szName, LPSTR szLocalPath )
{
CHAR szDir[MAX_PATH];
LPCSTR szRest = ::strchr( szName, '\\' );
if( szRest == NULL )
{ // There is no alias because there is not subdirectory name
return FALSE;
}
size_t n = szRest - szName;
::strncpy( szDir, szName, n );
szDir[n] = 0;
try
{
ClRegKey keyAliases( HKEY_LOCAL_MACHINE, "Software\\TodaySoft\\NfpService\\ShareAlias" );
DWORD dwValueCount;
if( ::RegQueryInfoKey( keyAliases,
NULL, NULL, // Class
NULL, // Reserved
NULL, NULL, NULL,
&dwValueCount,
NULL, NULL, NULL, NULL
) != ERROR_SUCCESS ||
dwValueCount == 0
)
{
return FALSE;
}
for( int i = 0; i < (int)dwValueCount; i ++ )
{
CHAR szAlias[MAX_PATH];
CHAR szLocalDir[MAX_PATH];
DWORD dwValueSize = MAX_PATH;
DWORD dwDataSize = MAX_PATH;
DWORD dwType = REG_SZ;
if( ::RegEnumValue( keyAliases,
i, szAlias, &dwValueSize,
NULL, &dwType,
(LPBYTE)szLocalDir, &dwDataSize ) == ERROR_SUCCESS )
{
if( ::stricmp( szAlias, szDir ) == 0 )
{
::strcpy( szLocalPath, szLocalDir );
::strcat( szLocalPath, szRest );
return TRUE;
}
}
}
return FALSE;
}
catch( ClRegKey::XFailedToCreate & )
{
return FALSE;
}
}
}
static void PutErrorMsg(void)
{
DWORD dwLastError = ::GetLastError();
LPVOID lpMsgBuf;
if( ::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwLastError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
) )
{
TRACE_PRINTF( ("GetLastError: Error code: %#x, reason: %s\n", dwLastError, lpMsgBuf) );
// Free the buffer.
LocalFree( lpMsgBuf );
}
else
{
TRACE_PRINTF( ("GetLastError: Error code: %#x\n", dwLastError) );
}
}
using namespace namNFS;
ClNFSFileSysAgent::ClNFSFileSysAgent( const char * szServerIP ) :
ClServerSocket( szServerIP, namNFS::FILE_SYS_PORT )
{}
void ClNFSFileSysAgent::OnConnect( SOCKET Connection )
{
ClOpenFiles OpenFiles( Connection );
// Above object will make sure all open files in this connection can be
// closed if this connection is disconnected abnormally.
TRACE_PRINTF( ("ClNFSFileSysAgent::OnConnect( %d )\n", Connection) );
DYN<St_FileSysRequest> pRequest = new (MAX_PATH) St_FileSysRequest;
if( (St_FileSysRequest *)pRequest == NULL )
{
TRACE_PRINTF( ("ClNFSFileSysAgent::OnConnect: Failed to allocate a St_FileSysRequest\n") );
return;
}
while( TRUE )
{
// Receive the file system request
int nReceived = ::recv( Connection,
(LPSTR)(St_FileSysRequest *)pRequest, sizeof(St_FileSysRequest)+MAX_PATH, 0 );
if( !nReceived )
{
TRACE_PRINTF( ("ClNFSFileSysAgent::OnConnect - Connection %d has been closed\n", Connection) );
return;
}
if( nReceived == SOCKET_ERROR )
{
int nReason = ::WSAGetLastError();
if( nReason == WSAECONNRESET )
{ // This connection has been closed, so quit this function
TRACE_PRINTF( ("ClNFSFileSysAgent::OnConnect - Connection %d has been closed\n", Connection) );
return;
}
TRACE_PRINTF( ("Failed to receive a file system request\n") );
return;
}
switch( pRequest->eRequest )
{
case St_FileSysRequest::enOpen:
{
TRACE_PRINTF( ("Receive St_FileSysRequest::enOpen\n") );
LPCSTR szFile;
CHAR szLocalPath[MAX_PATH];
if( matchAlias( (LPCSTR)pRequest->aryData, szLocalPath ) )
{
szFile = szLocalPath;
}
else
{
szFile = (LPCSTR)pRequest->aryData;
}
HANDLE hFile = ::CreateFile( szFile,
pRequest->dwPara, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
if( hFile != INVALID_HANDLE_VALUE )
{
ClServerFileObject * pFileObject = new ClServerFileObject( hFile );
if( pFileObject == NULL )
{
TRACE_PRINTF( ("ClNFSFileSysAgent::OnConnect: Failed to new a ClServerFileObject( %#x )\n", hFile) );
::CloseHandle( hFile );
return;
}
if( OpenFiles.add( pFileObject ) )
{
hFile = (HANDLE)pFileObject;
}
else
{
::OutputDebugString( "!!!Fatal Error: A connection is corrupted!!!\n" );
hFile = INVALID_HANDLE_VALUE;
delete pFileObject;
}
}
else
{
PutErrorMsg();
TRACE_PRINTF( ("Failed to open file \'%s\'\n", (LPCSTR)pRequest->aryData) );
}
// Send back the handle of the open file
int nSent = ::send( Connection, (LPCSTR)&hFile, sizeof(hFile), 0 );
if( nSent != sizeof(hFile) )
{
TRACE_PRINTF( ("Failed to send back the handle\n") );
// Close the file and delete the file object
if( hFile != INVALID_HANDLE_VALUE )
{
ClServerFileObject * pFileObject = (ClServerFileObject *)hFile;
if( !OpenFiles.remove( pFileObject ) )
{
::OutputDebugString( "!!!Fatal Error: A connection is corrupted!!!\n" );
}
delete pFileObject;
}
return; // An unhandled error, so close this connection
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -