📄 serverlist.cpp
字号:
//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 "serverlist.h"
#include "emule.h"
#include "HttpDownloadDlg.h"
#include "safefile.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CServerList::CServerList(CPreferences* in_prefs){
servercount = 0;
version = 0;
serverpos = 0;
searchserverpos = 0;
statserverpos = 0;
app_prefs = in_prefs;
udp_timer = 0;
delservercount = 0;
m_nLastSaved = ::GetTickCount();
}
void CServerList::AutoUpdate(){
if (app_prefs->adresses_list.IsEmpty()){
MessageBox(0,GetResString(IDS_ERR_EMPTYADRESSESDAT),GetResString(IDS_ERR_EMPTYADRESSESDAT_TITLE),64);
return;
}
bool bDownloaded=false;
CString servermetdownload;
CString servermetbackup;
CString servermet;
CString strURLToDownload;
servermetdownload.Format("%sserver_met.download",app_prefs->GetAppDir());
servermetbackup.Format("%sserver_met.old",app_prefs->GetAppDir());
servermet.Format("%sserver.met",app_prefs->GetAppDir());
remove(servermetbackup);
remove(servermetdownload);
rename(servermet,servermetbackup);
POSITION Pos = app_prefs->adresses_list.GetHeadPosition();
while ((!bDownloaded) && (Pos != NULL)){
CHttpDownloadDlg dlgDownload;
strURLToDownload = app_prefs->adresses_list.GetNext(Pos);
dlgDownload.m_sURLToDownload = strURLToDownload.GetBuffer();
dlgDownload.m_sFileToDownloadInto = servermetdownload;
if (dlgDownload.DoModal() == IDOK){
bDownloaded=true;
}
else{
theApp.emuledlg->AddLogLine(true,GetResString(IDS_ERR_FAILEDDOWNLOADMET), strURLToDownload.GetBuffer());
}
}
if (bDownloaded){
rename(servermet, servermetdownload);
rename(servermetbackup, servermet);
}
else{
remove(servermet);
rename(servermetbackup,servermet);
}
}
bool CServerList::Init(){
// auto update the list by using an url
if (app_prefs->AutoServerlist())
AutoUpdate();
// Load Metfile
CString strPath;
strPath.Format( "%sserver.met", app_prefs->GetAppDir());
bool bRes = AddServermetToList(strPath, false);
if( theApp.glob_prefs->AutoServerlist() ){
strPath.Format( "%sserver_met.download", app_prefs->GetAppDir());
bool bRes2 = AddServermetToList(strPath);
if( !bRes && bRes2 )
bRes = true;
}
// insert static servers from textfile
strPath.Format( "%sstaticservers.dat", app_prefs->GetAppDir());
AddServersFromTextFile(strPath);
return bRes;
}
bool CServerList::AddServermetToList(CString strFile, bool merge){
if (!merge)
{
theApp.emuledlg->serverwnd.serverlistctrl.DeleteAllItems();
this->RemoveAllServers();
}
CSafeFile servermet;
try{
if (!servermet.Open(strFile,CFile::modeRead|CFile::osSequentialScan)){
if(!merge)
theApp.emuledlg->AddLogLine(false,GetResString(IDS_ERR_LOADSERVERMET));
return false;
}
servermet.Read(&version,1);
if (version != 0xE0 && version != MET_HEADER){
servermet.Close();
theApp.emuledlg->AddLogLine(false,GetResString(IDS_ERR_BADSERVERMETVERSION),version);
return false;
}
theApp.emuledlg->serverwnd.serverlistctrl.Hide();
uint32 fservercount;
servermet.Read(&fservercount,4);
ServerMet_Struct sbuffer;
uint32 iAddCount = 0;
for (uint32 j = 0;j != fservercount;j++){
// get server
servermet.Read(&sbuffer,sizeof(ServerMet_Struct));
CServer* newserver = new CServer(&sbuffer);
//add tags
for (uint32 i=0;i != sbuffer.tagcount;i++)
newserver->AddTagFromFile(&servermet);
// set listname for server
if (!newserver->GetListName()){
char* listname = new char[strlen(newserver->GetAddress())+8];
sprintf(listname,"Server %s",newserver->GetAddress());
newserver->SetListName(listname);
delete listname;
}
if (!theApp.emuledlg->serverwnd.serverlistctrl.AddServer(newserver,true) ){
CServer* update = theApp.serverlist->GetServerByAddress(newserver->GetAddress(), newserver->GetPort());
if(update){
update->SetListName( newserver->GetListName());
if( newserver->GetDescription() )
update->SetDescription( newserver->GetDescription());
theApp.emuledlg->serverwnd.serverlistctrl.RefreshServer(update);
}
delete newserver;
}
else
iAddCount++;
}
if (!merge)
theApp.emuledlg->AddLogLine(true,GetResString(IDS_SERVERSFOUND),fservercount);
else
theApp.emuledlg->AddLogLine(true,GetResString(IDS_SERVERSADDED), iAddCount, fservercount-iAddCount);
servermet.Close();
}
catch(CFileException* error){
OUTPUT_DEBUG_TRACE();
if (error->m_cause == CFileException::endOfFile)
theApp.emuledlg->AddDebugLogLine(true,GetResString(IDS_ERR_BADSERVERLIST));
else{
char buffer[150];
error->GetErrorMessage(buffer,150);
theApp.emuledlg->AddDebugLogLine(true,GetResString(IDS_ERR_FILEERROR_SERVERMET),buffer);
}
error->Delete(); //memleak fix
}
theApp.emuledlg->serverwnd.serverlistctrl.Visable();
return true;
}
bool CServerList::AddServer(CServer* in_server){
if (theApp.glob_prefs->FilterServerByIP())
if (in_server->HasDynIP() || theApp.ipfilter->IsFiltered(in_server->GetIP())) return false;
if (theApp.glob_prefs->FilterBadIPs())
if ( !IsGoodServerIP( in_server ))
return false;
CServer* test_server = GetServerByAddress(in_server->GetAddress(), in_server->GetPort());
if (test_server){
test_server->ResetFailedCount();
theApp.emuledlg->serverwnd.serverlistctrl.RefreshServer( test_server );
return false;
}
list.AddTail(in_server);
return true;
}
void CServerList::ServerStats(){
if( theApp.serverconnect->IsConnected() && list.GetCount() > 0 ) {
CServer* ping_server = GetNextStatServer();
CServer* test = ping_server;
if( !ping_server )
return;
while(ping_server->GetLastPinged() != 0 && (::GetTickCount() - ping_server->GetLastPinged()) < UDPSERVSTATREASKTIME){
ping_server = this->GetNextStatServer();
if( ping_server == test )
return;
}
if( ping_server->GetFailedCount() >= theApp.glob_prefs->GetDeadserverRetries() && theApp.glob_prefs->DeadServer() ){
theApp.emuledlg->serverwnd.serverlistctrl.RemoveServer(ping_server);
return;
}
Packet* packet = new Packet( OP_GLOBSERVSTATREQ, 4 );
srand((unsigned)time(NULL));
uint32 time = 0x55AA0000 + (uint16)rand();
ping_server->SetChallenge(time);
memcpy( packet->pBuffer, &time, 4 );
ping_server->SetLastPinged( ::GetTickCount() );
ping_server->AddFailedCount();
theApp.emuledlg->serverwnd.serverlistctrl.RefreshServer( ping_server );
theApp.uploadqueue->AddUpDataOverheadServer(packet->size);
theApp.serverconnect->SendUDPPacket( packet, ping_server, true );
packet = new Packet( OP_SERVER_DESC_REQ,0);
theApp.uploadqueue->AddUpDataOverheadServer(packet->size);
theApp.serverconnect->SendUDPPacket( packet, ping_server, true );
}
}
/*filter Servers with invalid IP's / Port
0.*
10.*
172.16.0.0 - 172.31.255.255
192.168.0.0 - 192.168.255.255
127.*
*/
bool CServerList::IsGoodServerIP(CServer* in_server){
if (in_server->HasDynIP())
return true;
char * pch;
char ipx[24];
sprintf(ipx,"%s",in_server->GetFullIP());
// Determine first and second number if the given IP
pch = strtok (ipx,"."); CString first=pch;pch=strtok(NULL,"."); CString second=pch;
int secondI=atoi(second);
if (first=="172" && (secondI>=16 && secondI<=31) ) return false;
if (first=="192" && secondI==168 ) return false;
if (first=="0" || first=="10" || first=="127"
|| in_server->GetPort()==0) return false;
return true;
}
void CServerList::RemoveServer(CServer* out_server){
for(POSITION pos = list.GetHeadPosition(); pos != NULL; )
{
POSITION pos2 = pos;
CServer* test_server = list.GetNext(pos);
if (test_server == out_server){
if (theApp.downloadqueue->cur_udpserver == out_server)
theApp.downloadqueue->cur_udpserver = 0;
list.RemoveAt(pos2);
delservercount++;
delete test_server;
return;
}
}
}
void CServerList::RemoveAllServers(){
for(POSITION pos = list.GetHeadPosition(); pos != NULL; pos = list.GetHeadPosition()) {
delete list.GetAt(pos);
list.RemoveAt(pos);
delservercount++;
}
}
void CServerList::GetStatus(uint32 &total, uint32 &failed, uint32 &user, uint32 &file, uint32 &tuser, uint32 &tfile,float &occ){
total = list.GetCount();
failed = 0;
user = 0;
file = 0;
tuser=0;
tfile = 0;
occ=0;
uint32 maxusers=0;
uint32 tuserk = 0;
CServer* curr;
for (POSITION pos = list.GetHeadPosition(); pos !=0;list.GetNext(pos)){
curr = (CServer*)list.GetAt(pos);
if( curr->GetFailedCount() ){
failed++;
}
else{
user += curr->GetUsers();
file += curr->GetFiles();
}
tuser += curr->GetUsers();
tfile += curr->GetFiles();
if (curr->GetMaxUsers()) {
tuserk += curr->GetUsers(); // total users on servers with known maximum
maxusers+=curr->GetMaxUsers();
}
}
if (maxusers>0) occ=(float)(tuserk*100)/maxusers;
}
void CServerList::GetUserFileStatus(uint32 &user, uint32 &file){
user = 0;
file = 0;
CServer* curr;
for (POSITION pos = list.GetHeadPosition(); pos !=0;list.GetNext(pos)){
curr = (CServer*)list.GetAt(pos);
if( !curr->GetFailedCount() ){
user += curr->GetUsers();
file += curr->GetFiles();
}
}
}
CServerList::~CServerList(){
SaveServermetToFile();
for(POSITION pos = list.GetHeadPosition(); pos != NULL; pos = list.GetHeadPosition()) {
delete list.GetAt(pos);
list.RemoveAt(pos);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -