📄 serversocket.cpp
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.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"));
CServer* pServer = cur_server ? theApp.serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort()) : NULL;
CSafeMemFile data((const BYTE*)packet, size);
CString strMessages(data.ReadString(pServer ? pServer->GetUnicodeSupport() : false));
if (thePrefs.GetDebugServerTCPLevel() > 0){
UINT uAddData = data.GetLength() - data.GetPosition();
if (uAddData > 0){
Debug(_T("*** NOTE: OP_ServerMessage: ***AddData: %u bytes\n"), uAddData);
DebugHexDump((uint8*)packet + data.GetPosition(), uAddData);
}
}
// 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.
int iPos = 0;
CString message = strMessages.Tokenize(_T("\r\n"), iPos);
while (!message.IsEmpty())
{
bool bOutputMessage = true;
if (_tcsnicmp(message, _T("server version"), 14) == 0){
CString strVer = message.Mid(14);
strVer.Trim();
strVer = strVer.Left(64); // truncate string to avoid misuse by servers in showing ads
if (pServer){
pServer->SetVersion(strVer);
theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer(pServer);
theApp.emuledlg->serverwnd->UpdateMyInfo();
}
if (thePrefs.GetDebugServerTCPLevel() > 0)
Debug(_T("%s\n"), message);
}
else if (_tcsncmp(message, _T("ERROR"), 5) == 0){
AddLogLine(true, _T("%s %s (%s:%u) - %s"),
GetResString(IDS_ERROR),
pServer ? pServer->GetListName() : GetResString(IDS_PW_SERVER),
cur_server ? cur_server->GetAddress() : _T(""),
cur_server ? cur_server->GetPort() : 0, message.Mid(5).Trim(_T(" :")));
bOutputMessage = false;
}
else if (_tcsncmp(message, _T("WARNING"), 7) == 0){
AddLogLine(true, _T("%s %s (%s:%u) - %s"),
GetResString(IDS_WARNING),
pServer ? pServer->GetListName() : GetResString(IDS_PW_SERVER),
cur_server ? cur_server->GetAddress() : _T(""),
cur_server ? cur_server->GetPort() : 0, message.Mid(7).Trim(_T(" :")));
bOutputMessage = false;
}
if (message.Find(_T("[emDynIP: ")) != -1 && message.Find(_T("]")) != -1 && message.Find(_T("[emDynIP: ")) < message.Find(_T("]"))){
CString dynip = message.Mid(message.Find(_T("[emDynIP: ")) + 10, message.Find(_T("]")) - (message.Find(_T("[emDynIP: ")) + 10));
dynip.Trim(_T(" "));
if (dynip.GetLength() && dynip.GetLength() < 51){
if (pServer){
pServer->SetDynIP(dynip);
if (cur_server)
cur_server->SetDynIP(dynip);
theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer(pServer);
theApp.emuledlg->serverwnd->UpdateMyInfo();
}
}
}
if (bOutputMessage)
theApp.emuledlg->AddServerMessageLine(message);
message = strMessages.Tokenize(_T("\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){
DWORD dwFlags = *((uint32*)(packet + sizeof(LoginAnswer_Struct)));
if (thePrefs.GetDebugServerTCPLevel() > 0){
CString strInfo;
strInfo.AppendFormat(_T(" TCP Flags=0x%08x"), dwFlags);
const DWORD dwKnownBits = SRV_TCPFLG_COMPRESSION | SRV_TCPFLG_NEWTAGS | SRV_TCPFLG_UNICODE;
if (dwFlags & ~dwKnownBits)
strInfo.AppendFormat(_T(" ***UnkBits=0x%08x"), dwFlags & ~dwKnownBits);
if (dwFlags & SRV_TCPFLG_COMPRESSION)
strInfo.AppendFormat(_T(" Compression=1"));
if (dwFlags & SRV_TCPFLG_NEWTAGS)
strInfo.AppendFormat(_T(" NewTags=1"));
if (dwFlags & SRV_TCPFLG_UNICODE)
strInfo.AppendFormat(_T(" Unicode=1"));
Debug(_T("%s\n"), strInfo);
}
cur_server->SetTCPFlags(dwFlags);
}
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);
if (theApp.serverconnect->IsLowID()){
AddLogLine(false,GetResString(IDS_HAVE_A_LOWID)); //VeryCD版,增加LowID提醒
AddLogLine(false,GetResString(IDS_HAVE_IP));
AddLogLine(false,GetResString(IDS_IS_INTERNAT));
AddLogLine(false,GetResString(IDS_ID_DETAILS));
}
theApp.downloadqueue->ResetLocalServerRequests();
break;
}
case OP_SEARCHRESULT:{
if (thePrefs.GetDebugServerTCPLevel() > 0)
Debug(_T("ServerMsg - OP_SearchResult\n"));
CServer* cur_srv = (serverconnect) ? serverconnect->GetCurrentServer() : NULL;
CServer* pServer = cur_srv ? theApp.serverlist->GetServerByAddress(cur_srv->GetAddress(), cur_srv->GetPort()) : NULL;
bool bMoreResultsAvailable;
uint16 uSearchResults = theApp.searchlist->ProcessSearchanswer(packet, size, true/*pServer ? pServer->GetUnicodeSupport() : false*/, 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));
ASSERT( cur_server );
if (cur_server)
{
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 = cur_server ? theApp.serverlist->GetServerByAddress(cur_server->GetAddress(), cur_server->GetPort()) : NULL;
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){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -