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

📄 searchserver.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
//
//////////////////////////////////////////////////////////////////////

// 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 + -