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

📄 serversocket.cpp

📁 另外一款开放源码的高质量p2p源码软件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include "emule.h"
#include "ServerSocket.h"
#include "SearchList.h"
#include "DownloadQueue.h"
#include "Statistics.h"
#include "ClientList.h"
#include "Server.h"
#include "ServerList.h"
#include "Sockets.h"
#include "OtherFunctions.h"
#include "Opcodes.h"
#include "Preferences.h"
#include "SafeFile.h"
#include "PartFile.h"
#include "Packets.h"
#include "UpDownClient.h"
#include "emuleDlg.h"
#include "ServerWnd.h"
#include "SearchDlg.h"
#include "IPFilter.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


#pragma pack(1)
struct LoginAnswer_Struct {
	uint32	clientid;
};
#pragma pack()


CServerSocket::CServerSocket(CServerConnect* in_serverconnect){
	serverconnect = in_serverconnect;
	connectionstate = 0;
	cur_server = 0;
	m_bIsDeleting = false;
	m_dwLastTransmission = 0;
}

CServerSocket::~CServerSocket(){
	if (cur_server)
		delete cur_server;
	cur_server = NULL;
}

void CServerSocket::OnConnect(int nErrorCode){
	CAsyncSocketEx::OnConnect(nErrorCode); // deadlake PROXYSUPPORT - changed to AsyncSocketEx
	switch (nErrorCode){
		case 0:{
			if (cur_server->HasDynIP()){
				SOCKADDR_IN sockAddr = {0};
				int nSockAddrLen = sizeof(sockAddr);
				GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
				cur_server->SetIP(sockAddr.sin_addr.S_un.S_addr);
				CServer* pServer = theApp.serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
				if (pServer)
					pServer->SetIP(sockAddr.sin_addr.S_un.S_addr);
			}
			SetConnectionState(CS_WAITFORLOGIN);
			break;
		}
		case WSAEADDRNOTAVAIL:
		case WSAECONNREFUSED:
		//case WSAENETUNREACH:	// let this error default to 'fatal error' as it does not inrease the server's failed count
		case WSAETIMEDOUT: 	
		case WSAEADDRINUSE:
			if (thePrefs.GetVerbose())
				AddDebugLogLine(false, _T("Failed to connect to server %s; %s"), cur_server->GetAddress(), GetErrorMessage(nErrorCode, 1));
			m_bIsDeleting = true;
			SetConnectionState(CS_SERVERDEAD);
			serverconnect->DestroySocket(this);
			return;
		// deadlake PROXYSUPPORT
		case WSAECONNABORTED:
			if (m_ProxyConnectFailed)
			{
				if (thePrefs.GetVerbose())
					AddDebugLogLine(false, _T("Failed to connect to server %s; %s"), cur_server->GetAddress(), GetErrorMessage(nErrorCode, 1));
				m_ProxyConnectFailed = false;
				m_bIsDeleting = true;
				SetConnectionState(CS_SERVERDEAD);
				serverconnect->DestroySocket(this);
				return;
			}
		default:	
			if (thePrefs.GetVerbose())
				AddDebugLogLine(false, _T("Failed to connect to server %s; %s"), cur_server->GetAddress(), GetErrorMessage(nErrorCode, 1));
			m_bIsDeleting = true;
			SetConnectionState(CS_FATALERROR);
			serverconnect->DestroySocket(this);
			return;
	}	 
}

void CServerSocket::OnReceive(int nErrorCode){
	if (connectionstate != CS_CONNECTED && !this->serverconnect->IsConnecting()){
		serverconnect->DestroySocket(this);
		return;
	}
	CEMSocket::OnReceive(nErrorCode);
	m_dwLastTransmission = GetTickCount();
}

bool CServerSocket::ProcessPacket(char* packet, uint32 size, uint8 opcode){
	try{
		switch(opcode){
			case OP_SERVERMESSAGE:{
				if (thePrefs.GetDebugServerTCPLevel() > 0)
					Debug(_T("ServerMsg - OP_ServerMessage\n"));

				CStringA strMessages;
				if (size >= 2){
					UINT uLen = *(uint16*)packet;
					if (uLen > size-2)
						uLen = size-2;
					memcpy(strMessages.GetBuffer(uLen), packet + sizeof uint16, uLen);
					strMessages.ReleaseBuffer(uLen);
				}

				// 16.40 servers do not send separate OP_SERVERMESSAGE packets for each line;
				// instead of this they are sending all text lines with one OP_SERVERMESSAGE packet.
				USES_CONVERSION;
				int iPos = 0;
				CStringA message = strMessages.Tokenize("\r\n", iPos);
				while (!message.IsEmpty())
				{
					bool bOutputMessage = true;
					if (strnicmp(message, "server version", 14) == 0){
						CStringA strVer = message.Mid(14);
						strVer.Trim();
						strVer = strVer.Left(64); // truncate string to avoid misuse by servers in showing ads
						CServer* eserver = theApp.serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
						if (eserver){
							eserver->SetVersion(A2CT(strVer));
							theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer(eserver);
							theApp.emuledlg->serverwnd->UpdateMyInfo();
						}
						if (thePrefs.GetDebugServerTCPLevel() > 0)
							Debug(_T("%hs\n"), message);
					}
					else if (strncmp(message, "ERROR", 5) == 0){
						CServer* pServer = theApp.serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
						AddLogLine(true, _T("%s %s (%s:%u) - %hs"), 
							GetResString(IDS_ERROR),
							pServer ? pServer->GetListName() : GetResString(IDS_PW_SERVER), 
							cur_server->GetAddress(), cur_server->GetPort(), message.Mid(5).Trim(" :"));
						bOutputMessage = false;
					}
					else if (strncmp(message, "WARNING", 7) == 0){
						CServer* pServer = theApp.serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
						AddLogLine(true, _T("%s %s (%s:%u) - %hs"), 
							GetResString(IDS_WARNING),
							pServer ? pServer->GetListName() : GetResString(IDS_PW_SERVER), 
							cur_server->GetAddress(), cur_server->GetPort(), message.Mid(7).Trim(" :"));
						bOutputMessage = false;
					}

					if (message.Find("[emDynIP: ") != (-1) && message.Find("]") != (-1) && message.Find("[emDynIP: ") < message.Find("]")){
						CStringA dynip = message.Mid(message.Find("[emDynIP: ")+10,message.Find("]") - (message.Find("[emDynIP: ")+10));
						dynip.Trim(" ");
						if ( dynip.GetLength() && dynip.GetLength() < 51){
							CServer* eserver = theApp.serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
							if (eserver){
								eserver->SetDynIP(A2CT(dynip));
								cur_server->SetDynIP(A2CT(dynip));
								theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer(eserver);
								theApp.emuledlg->serverwnd->UpdateMyInfo();
							}
						}
					}
					if (bOutputMessage)
						theApp.emuledlg->AddServerMessageLine(A2CT(message));

					message = strMessages.Tokenize("\r\n", iPos);
				}
				break;
			}
			case OP_IDCHANGE:{
				if (thePrefs.GetDebugServerTCPLevel() > 0)
					Debug(_T("ServerMsg - OP_IDChange\n"));
				if (size < sizeof(LoginAnswer_Struct)){
					throw GetResString(IDS_ERR_BADSERVERREPLY);
				}
				LoginAnswer_Struct* la = (LoginAnswer_Struct*)packet;

				// save TCP flags in 'cur_server'
				ASSERT( cur_server );
				if (cur_server){
					if (size >= sizeof(LoginAnswer_Struct)+4){
						if (thePrefs.GetDebugServerTCPLevel() > 0)
							Debug(_T("  Flags=%08x\n"), *((uint32*)(packet + sizeof(LoginAnswer_Struct))));
						cur_server->SetTCPFlags(*((uint32*)(packet + sizeof(LoginAnswer_Struct))));
					}
					else
						cur_server->SetTCPFlags(0);

					// copy TCP flags into the server in the server list
					CServer* pServer = theApp.serverlist->GetServerByAddress(cur_server->GetAddress(), cur_server->GetPort());
					if (pServer)
						pServer->SetTCPFlags(cur_server->GetTCPFlags());
				}

				if (la->clientid == 0){
					uint8 state = thePrefs.GetSmartIdState();
					if ( state > 0 ){
						state++;
						if( state > 3 )
							thePrefs.SetSmartIdState(0);
						else
							thePrefs.SetSmartIdState(state);
					}
					break;
				}
				if( thePrefs.GetSmartIdCheck() ){
					if (!IsLowID(la->clientid))
						thePrefs.SetSmartIdState(1);
					else{
						uint8 state = thePrefs.GetSmartIdState();
						if ( state > 0 ){
							state++;
							if( state > 3 )
								thePrefs.SetSmartIdState(0);
							else
								thePrefs.SetSmartIdState(state);
							break;
						}
					}
				}
				
				// we need to know our client's HighID when sending our shared files (done indirectly on SetConnectionState)
				serverconnect->clientid = la->clientid;

				if (connectionstate != CS_CONNECTED) {
					SetConnectionState(CS_CONNECTED);
					theApp.OnlineSig();       // Added By Bouc7 
				}
				serverconnect->SetClientID(la->clientid);
				AddLogLine(false,GetResString(IDS_NEWCLIENTID),la->clientid);

				theApp.downloadqueue->ResetLocalServerRequests();
				break;
			}
			case OP_SEARCHRESULT:{
				if (thePrefs.GetDebugServerTCPLevel() > 0)
					Debug(_T("ServerMsg - OP_SearchResult\n"));
				CServer* cur_srv = (serverconnect) ? serverconnect->GetCurrentServer() : NULL;
				bool bMoreResultsAvailable;
				uint16 uSearchResults = theApp.searchlist->ProcessSearchanswer(packet, size, cur_srv ? cur_srv->GetIP():0, cur_srv ? cur_srv->GetPort() : 0, &bMoreResultsAvailable);
				theApp.emuledlg->searchwnd->LocalSearchEnd(uSearchResults, bMoreResultsAvailable);
				break;
			}
			case OP_FOUNDSOURCES:{
				if (thePrefs.GetDebugServerTCPLevel() > 0)
					Debug(_T("ServerMsg - OP_FoundSources; Sources=%u  %s\n"), (UINT)(uchar)packet[16], DbgGetFileInfo((uchar*)packet));
				CSafeMemFile sources((BYTE*)packet,size);
				uchar fileid[16];
				sources.ReadHash16(fileid);
				if (CPartFile* file = theApp.downloadqueue->GetFileByID(fileid))
					file->AddSources(&sources,cur_server->GetIP(), cur_server->GetPort());
				break;
			}
			case OP_SERVERSTATUS:{
				if (thePrefs.GetDebugServerTCPLevel() > 0)
					Debug(_T("ServerMsg - OP_ServerStatus\n"));
				// FIXME some statuspackets have a different size -> why? structur?
				if (size < 8)
					break;//throw "Invalid status packet";
				uint32 cur_user = PeekUInt32(packet);
				uint32 cur_files = PeekUInt32(packet+4);
				CServer* update = theApp.serverlist->GetServerByAddress( cur_server->GetAddress(), cur_server->GetPort() );
				if (update){
					update->SetUserCount(cur_user); 
					update->SetFileCount(cur_files);
					theApp.emuledlg->ShowUserCount();
					theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer( update );
					theApp.emuledlg->serverwnd->UpdateMyInfo();
				}
				if (thePrefs.GetDebugServerTCPLevel() > 0){
					if (size > 8){
						Debug(_T("*** NOTE: OP_ServerStatus: ***AddData: %u bytes\n"), size - 8);
						DebugHexDump((uint8*)packet + 8, size - 8);
					}
				}
				break;
			}
			case OP_SERVERIDENT:{
				// OP_SERVERIDENT - this is sent by the server only if we send a OP_GETSERVERLIST
				if (thePrefs.GetDebugServerTCPLevel() > 0)
					Debug(_T("ServerMsg - OP_ServerIdent\n"));
				if (size<16+4+2+4){
					if (thePrefs.GetVerbose())
						AddDebugLogLine(false,GetResString(IDS_ERR_KNOWNSERVERINFOREC)); 
					break;// throw "Invalid server info received"; 
				} 

⌨️ 快捷键说明

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