📄 searchserver.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
//
//////////////////////////////////////////////////////////////////////
// SearchServer.cpp: implementation of the CSearchServer class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Oscar.h"
#include "SearchServer.h"
#include "NetworkMonitorFrame.h"
#include "AwareNetDivers.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
static HANDLE SearchServerHandle;
#define _afxSockThreadState AfxGetModuleThreadState()
#define _AFX_SOCK_THREAD_STATE AFX_MODULE_THREAD_STATE
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSearchServer::CSearchServer(CSecurityFilter *pFilter)
{
ASSERT(pFilter);
m_pFilter = pFilter; // Hold on to the security filter.
m_pFilter->Reference();
// Set up the file system.
m_pFileSystem = new CSecureFileSystem(m_pFilter);
// Allocate the redundancy-check buffer.
m_pRecords = NULL;
AllocateRecords(40);
}
CSearchServer::~CSearchServer()
{
m_pFilter->Dereference(); // Let go now.
delete m_pFileSystem;
ASSERT(FreeRecords() == 40);
}
BOOL CSearchServer::Start()
{
CWinThread *SearchServerThread;
if(SearchServerHandle)
return FALSE;
m_bStayOn = TRUE;
SearchServerThread = AfxBeginThread((AFX_THREADPROC)(CSearchServer::DriveWork),
(LPVOID)this, THREAD_PRIORITY_LOWEST);
ASSERT(SearchServerThread);
if(!SearchServerThread) return FALSE;
SearchServerHandle = SearchServerThread->m_hThread;
return TRUE;
}
BOOL CSearchServer::Stop(BOOL bWait)
{
DWORD dwExitCode = STILL_ACTIVE;
if(!SearchServerHandle)
return FALSE;
m_bStayOn = FALSE;
while(dwExitCode == STILL_ACTIVE && bWait)
{
if(!GetExitCodeThread(SearchServerHandle, &dwExitCode))
return FALSE;
if(dwExitCode == STILL_ACTIVE)
Sleep(THREAD_DIE_WAIT);
}
return TRUE;
}
UINT PASCAL CSearchServer::DriveWork(LPVOID *Param)
{
CSearchServer *SearchServer;
// Jump into the object itself
SearchServer = (CSearchServer *)Param;
if(!SearchServer)
{
SearchServerHandle = 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_OSCARSEARCH))
{
Sleep(SOCKET_TIMEOUT); // Probably just restarted after a close
nLoopCheck += 1;
if(nLoopCheck > SOCKET_RETRY_LIMIT)
return 0;
}
sock->Listen(SEARCH_LISTEN_BUFFER);
CTimeoutSocket *sockClient = NULL;
while(SearchServer->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 parse the request.
// This function should only be called here to avoid thread stomping
RequestHeader rHeader;
CString cszReqString;
SearchServer->AppendComment(_T("SearchServer: Got a search request"));
ASSERT(SearchServer->m_pFileSystem);
if(!SearchServer->m_pFileSystem)
{
sockClient->Close();
SearchServer->AppendComment(_T("SearchServer: Can't get filesystem"));
continue;
}
if(SearchServer->GetRequest(sockClient, rHeader, cszReqString))
{
// We were able to parse the request. Now, close the socket
// so the sender can go back to whatever it is he wants to do.
sockClient->Close();
SearchServer->AppendComment(_T("SearchServer: Parsed request"));
// Make sure this request hasn't circulated too long. If it
// has, let it drop.
if(rHeader.nHops > SEARCH_MAXHOPS)
continue;
// Make sure it wasn't ours.
if(SearchServer->FromMe(rHeader))
continue;
// Make sure this isn't an old request.
if(!SearchServer->RegisterSearch(rHeader.tczStart, rHeader.nID))
continue;
SearchServer->AppendComment(_T("SearchServer: Request is valid"));
// Construct the next request header.
RequestHeader rbHeader = rHeader;
rbHeader.nHops += 1;
// Broadcast the search to all online friends.
SearchServer->SendRequest(rbHeader, cszReqString);
// Now, we need to actually fulfill the request.
CStringArray csaResults, csaTitles;
// It's a SecureFileSystem.
ASSERT(SearchServer->m_pFileSystem->GetFSType() == 2);
SearchServer->AppendComment(_T("SearchServer: Compiling query results"));
if(!SearchServer->m_pFileSystem->PerformFullSearch(rHeader.nType,
cszReqString, csaResults, csaTitles))
{
// Didn't work. Bail.
continue; // Presumes no post-logue code.
}
// We now have results. If they're non-empty, send them to
// the inquirer.
SearchServer->AppendComment(_T("SearchServer: Returning query results"));
if(csaResults.GetSize() > 0)
SearchServer->ReturnResults(rHeader, csaResults,
csaTitles);
}
else
{
// For some reason, we couldn't parse the request. Bail out.
SearchServer->AppendComment(_T("SearchServer: Could not parse request"));
sockClient->Close();
}
}
// Keep working until the StayOn flag goes down
}
// Clean up memory.
sock->Close();
delete sock;
if(sockClient) delete sockClient;
// Clean up
SearchServerHandle = NULL;
return 1;
}
BOOL CSearchServer::GetRequest(CTimeoutSocket *sock, RequestHeader &rReqHeader,
CString &cszReqString)
{
// First, get the request header.
RequestHeader reqHeader;
sock->SetTimeout(SOCKET_TIMEOUT);
if(sock->Receive((void *)&reqHeader, sizeof(reqHeader)) != sizeof(reqHeader))
{
// Receive failed; quit and close the socket
return FALSE;
}
// Second, get the request string.
TCHAR tczRequest[REQUEST_STRING_LEN];
memset((void *)tczRequest, 0, sizeof(tczRequest));
sock->SetTimeout(SOCKET_TIMEOUT);
if(sock->Receive((void *)tczRequest, sizeof(TCHAR) * REQUEST_STRING_LEN) !=
sizeof(TCHAR) * REQUEST_STRING_LEN)
{
// Receive failed; quit and close the socket
return FALSE;
}
// Now we have the information. Push it back upstream.
memcpy((void *)&rReqHeader, (void *)&reqHeader, sizeof(RequestHeader));
cszReqString = tczRequest;
return TRUE;
}
BOOL CSearchServer::ReturnResults(RequestHeader reqHeader,
CStringArray &csaResults,
CStringArray &csaTitles)
{
// Get the requesting machine's address.
CString cszIPAddress;
if(!IP_ByteToExplicit((unsigned char *)reqHeader.tczStart, cszIPAddress))
return FALSE;
ASSERT(cszIPAddress.GetLength() > 0);
// Construct the result header.
ResultHeader resHeader;
CString cszMyEMail = _T("(Unknown)");
// Get the app.
COscarApp *pApp = (COscarApp *)AfxGetApp();
ASSERT(pApp);
// Get the e-mail address out of AwareNet, if possible.
if(pApp->m_bANetInit)
AwareNet_GetMyEmail(&pApp->m_cANet, cszMyEMail);
// Truncate it to the maximum buffer length;
cszMyEMail = cszMyEMail.Left(sizeof(resHeader.tczMyName) / sizeof(TCHAR) -
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -