📄 serversocket.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 "emule.h"
#include "packets.h"
#include "serversocket.h"
#include "emuleDlg.h"
#include "opcodes.h"
#include "searchlist.h"
#include <time.h>
#include <afxmt.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CServerSocket::CServerSocket(CServerConnect* in_serverconnect){
serverconnect = in_serverconnect;
connectionstate = 0;
cur_server = 0;
m_bIsDeleting = false;
info="";
}
CServerSocket::~CServerSocket(){
if (cur_server)
delete cur_server;
cur_server = NULL;
}
void CServerSocket::OnConnect(int nErrorCode){
CAsyncSocket::OnConnect(nErrorCode);
switch (nErrorCode){
case 0:{
if (cur_server->HasDynIP()){
SOCKADDR_IN sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
uint32 nSockAddrLen = sizeof(sockAddr);
GetPeerName((SOCKADDR*)&sockAddr,(int*)&nSockAddrLen);
cur_server->SetID(sockAddr.sin_addr.S_un.S_addr);
theApp.serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort())->SetID(sockAddr.sin_addr.S_un.S_addr);
}
SetConnectionState(CS_WAITFORLOGIN);
break;
}
case WSAEADDRNOTAVAIL:
case WSAECONNREFUSED:
case WSAENETUNREACH:
case WSAETIMEDOUT:
case WSAEADDRINUSE:
m_bIsDeleting = true;
SetConnectionState(CS_SERVERDEAD);
serverconnect->DestroySocket(this);
return;
default:
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);
}
bool CServerSocket::ProcessPacket(char* packet, int32 size, int8 opcode){
try{
CServer* update;
switch(opcode){
case OP_SERVERMESSAGE:{
theApp.downloadqueue->AddDownDataOverheadServer(size);
char* buffer = new char[size-1];
memcpy(buffer,&packet[2],size-2);
buffer[size-2] = 0;
CString message(buffer);
if (message.Find("[emDynIP: ") != (-1) && message.Find("]") != (-1) && message.Find("[emDynIP: ") < message.Find("]")){
CString 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(dynip.GetBuffer());
cur_server->SetDynIP(dynip.GetBuffer());
theApp.emuledlg->serverwnd.serverlistctrl.RefreshServer(eserver);
}
}
}
theApp.emuledlg->AddServerMessageLine(buffer);
delete[] buffer;
break;
}
case OP_IDCHANGE:{
theApp.downloadqueue->AddDownDataOverheadServer(size);
if (size != sizeof(LoginAnswer_Struct)){
throw GetResString(IDS_ERR_BADSERVERREPLY);
}
LoginAnswer_Struct* la = (LoginAnswer_Struct*) packet;
if (la->clientid == 0){
// SetConnectionState(CS_ERROR);
uint8 state = theApp.glob_prefs->GetSmartIdState();
if ( state > 0 ){
// SetConnectionState(CS_ERROR);
state++;
if( state > 3 )
theApp.glob_prefs->SetSmartIdState(0);
else
theApp.glob_prefs->SetSmartIdState(state);
}
break;
}
if( theApp.glob_prefs->GetSmartIdCheck() ){
if (la->clientid >= 16777216 )
theApp.glob_prefs->SetSmartIdState(1);
else{
uint8 state = theApp.glob_prefs->GetSmartIdState();
if ( state > 0 ){
// SetConnectionState(CS_ERROR);
state++;
if( state > 3 )
theApp.glob_prefs->SetSmartIdState(0);
else
theApp.glob_prefs->SetSmartIdState(state);
break;
}
}
}
if (connectionstate != CS_CONNECTED) {
SetConnectionState(CS_CONNECTED);
theApp.OnlineSig(); // Added By Bouc7
}
serverconnect->SetClientID(la->clientid);
theApp.emuledlg->AddLogLine(false,GetResString(IDS_NEWCLIENTID),la->clientid);
for(POSITION pos = theApp.downloadqueue->filelist.GetHeadPosition(); pos != NULL;theApp.downloadqueue->filelist.GetNext(pos)) {
CPartFile* cur_file = theApp.downloadqueue->filelist.GetAt(pos);
if( cur_file->GetStatus() == PS_READY ){
cur_file->ResumeFile();
}
}
theApp.downloadqueue->filelist.GetCount();
break;
}
case OP_SEARCHRESULT:{
theApp.downloadqueue->AddDownDataOverheadServer(size);
theApp.emuledlg->searchwnd.LocalSearchEnd(theApp.searchlist->ProcessSearchanswer(packet,size));
break;
}
case OP_FOUNDSOURCES:{
theApp.downloadqueue->AddDownDataOverheadServer(size);
CMemFile* sources = new CMemFile((BYTE*)packet,size);
uchar fileid[16];
sources->Read(fileid,16);
if (CPartFile* file = theApp.downloadqueue->GetFileByID(fileid))
file->AddSources(sources,cur_server->GetIP(), cur_server->GetPort());
delete sources;
break;
}
case OP_SERVERSTATUS:{
theApp.downloadqueue->AddDownDataOverheadServer(size);
// FIXME some statuspackets have a different size -> why? structur?
if (size < 8)
break;//throw "Invalid status packet";
uint32 cur_user;
memcpy(&cur_user,packet,4);
uint32 cur_files;
memcpy(&cur_files,packet+4,4);
update = theApp.serverlist->GetServerByAddress( cur_server->GetAddress(), cur_server->GetPort() );
if (update){
update->SetUserCount(cur_user);
update->SetFileCount(cur_files);
theApp.emuledlg->ShowUserCount(cur_user, cur_files);
theApp.emuledlg->serverwnd.serverlistctrl.RefreshServer( update );
}
break;
}
//<<--Working, but needs to be cleaned up..
case OP_SERVERIDENT:{
theApp.downloadqueue->AddDownDataOverheadServer(size);
if (size<38) {
theApp.emuledlg->AddDebugLogLine(false,GetResString(IDS_ERR_KNOWNSERVERINFOREC));
break;// throw "Invalid server info received";
}
char* buffer = new char[size-29];
CServer* update = theApp.serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
uint16 num,num2;
char* temp=new char[size-38];
memcpy(buffer,&packet[30],size-30);// 1st 30 char contain only server address & fillers
memcpy(&num,&buffer[0],2); // length of server_name
memcpy(temp,&buffer[2],num);
temp[num]=0;//close the string
update->SetListName(temp);
memcpy(&num2,&buffer[num+6],2);
memcpy (temp,&buffer[num+8],num2);
temp[num2]=0; //close the string
update->SetDescription(temp);
theApp.emuledlg->ShowConnectionState(true,update->GetListName());
theApp.emuledlg->serverwnd.serverlistctrl.RefreshServer(update);
delete[] temp;
delete[] buffer;
break;
}
// tecxx 1609 2002 - add server's serverlist to own serverlist
case OP_SERVERLIST:{
theApp.downloadqueue->AddDownDataOverheadServer(size);
try{
CSafeMemFile* servers = new CSafeMemFile((BYTE*)packet,size);
byte count;
servers->Read(&count, 1);// check if packet is valid
if ((int32)(count*6 + 1) > size) // (servercount*(4bytes ip + 2bytes port) + 1byte servercount)
count = 0;
int addcount = 0;
while(count)
{
uint32 ip;
unsigned short port;
servers->Read(&ip, 4);
servers->Read(&port, 2);
in_addr host;
host.S_un.S_addr = ip;
CServer* srv = new CServer(port, inet_ntoa(host));
srv->SetListName(srv->GetFullIP());
if (!theApp.emuledlg->serverwnd.serverlistctrl.AddServer(srv, true))
delete srv;
else
addcount++;
count--;
}
delete servers;
if (addcount)
theApp.emuledlg->AddLogLine(false,GetResString(IDS_NEWSERVERS), addcount);
}
catch(CFileException* error){
OUTPUT_DEBUG_TRACE();
theApp.emuledlg->AddDebugLogLine(false,GetResString(IDS_ERR_BADSERVERLISTRECEIVED));
error->Delete(); //memleak fix
}
break;
}
case OP_CALLBACKREQUESTED:{
theApp.downloadqueue->AddDownDataOverheadServer(size);
if (size == 6){
uint32 dwIP;
memcpy(&dwIP,packet,4);
uint16 nPort;
memcpy(&nPort,packet+4,2);
CUpDownClient* client = theApp.clientlist->FindClientByIP(dwIP,nPort);
if (client)
client->TryToConnect();
else{
client = new CUpDownClient(nPort,dwIP,0,0,0);
theApp.clientlist->AddClient(client);
client->TryToConnect();
}
}
}
default:
;
}
return true;
}
catch(CString error){
OUTPUT_DEBUG_TRACE();
theApp.emuledlg->AddDebugLogLine(false,GetResString(IDS_ERR_PACKAGEHANDLING),error.GetBuffer());
SetConnectionState(CS_DISCONNECTED);
return false;
}
}
void CServerSocket::ConnectToServer(CServer* server){
cur_server = new CServer(server);
theApp.emuledlg->AddLogLine(false,GetResString(IDS_CONNECTINGTO),cur_server->GetListName(),cur_server->GetFullIP(),cur_server->GetPort());
SetConnectionState(CS_CONNECTING);
if (!this->Connect(server->GetAddress(),server->GetPort())){
int error = this->GetLastError();
if ( error != WSAEWOULDBLOCK){
theApp.emuledlg->AddLogLine(false,GetResString(IDS_ERR_CONNECTIONERROR),cur_server->GetListName(),cur_server->GetFullIP(),cur_server->GetPort(), error);
SetConnectionState(CS_FATALERROR);
return;
}
}
info=server->GetListName();
SetConnectionState(CS_CONNECTING);
}
void CServerSocket::OnError(int nErrorCode){
SetConnectionState(CS_DISCONNECTED);
theApp.emuledlg->AddDebugLogLine(false,GetResString(IDS_ERR_SOCKET),cur_server->GetListName(),cur_server->GetFullIP(),cur_server->GetPort(), nErrorCode);
}
void CServerSocket::PacketReceived(Packet* packet){
ProcessPacket(packet->pBuffer,packet->size,packet->opcode);
}
void CServerSocket::OnClose(int nErrorCode){
CEMSocket::OnClose(0);
if (connectionstate == CS_WAITFORLOGIN){
SetConnectionState(CS_SERVERFULL);
}
else if (connectionstate == CS_CONNECTED){
SetConnectionState(CS_DISCONNECTED);
}
else{
SetConnectionState(CS_NOTCONNECTED);
}
serverconnect->DestroySocket(this);
}
void CServerSocket::SetConnectionState(sint8 newstate){
sint8 oldstate = connectionstate;
connectionstate = newstate;
if (newstate < 1){
serverconnect->ConnectionFailed(this);
}
else if (newstate == CS_CONNECTED || newstate == CS_WAITFORLOGIN){
if (serverconnect)
serverconnect->ConnectionEstablished(this);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -