📄 udpsocket.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 "UDPSocket.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CUDPSocketWnd::CUDPSocketWnd(){
}
BEGIN_MESSAGE_MAP(CUDPSocketWnd, CWnd)
ON_MESSAGE(WM_DNSLOOKUPDONE, OnDNSLookupDone)
END_MESSAGE_MAP()
LRESULT CUDPSocketWnd::OnDNSLookupDone(WPARAM wParam,LPARAM lParam){
m_pOwner->DnsLookupDone(wParam,lParam);
return true;
};
CUDPSocket::CUDPSocket(CServerConnect* in_serverconnect){
m_hWndResolveMessage = NULL;
sendbuffer = 0;
cur_server = 0;
serverconnect = in_serverconnect;
DnsTaskHandle = 0;
}
CUDPSocket::~CUDPSocket(){
if (cur_server)
delete cur_server;
if (sendbuffer)
delete[] sendbuffer;
m_udpwnd.DestroyWindow();
}
bool CUDPSocket::Create(){
VERIFY( m_udpwnd.CreateEx(0, AfxRegisterWndClass(0),_T("Emule Socket Wnd"),WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL));
m_hWndResolveMessage = m_udpwnd.m_hWnd;
m_udpwnd.m_pOwner = this;
return CAsyncSocket::Create(0,SOCK_DGRAM,FD_READ);
}
void CUDPSocket::OnReceive(int nErrorCode){
char buffer[5000];
CString serverbuffer;
uint32 port;
int32 length = ReceiveFrom(buffer,5000,serverbuffer,port);
if ((uint8)buffer[0] == OP_EDONKEYPROT && length != SOCKET_ERROR)
ProcessPacket(buffer+2,length-2,buffer[1],serverbuffer.GetBuffer(),port);
else if (((uint8)buffer[0] == OP_EMULEPROT) && length != SOCKET_ERROR)
ProcessExtPacket(buffer+2,length-2,buffer[1],serverbuffer.GetBuffer(),port);
}
bool CUDPSocket::ProcessPacket(char* packet, int16 size, int8 opcode, char* host, uint16 port){
try{
CServer* update;
update = theApp.serverlist->GetServerByAddress( host, port-4 );
if( update ){
update->ResetFailedCount();
theApp.emuledlg->serverwnd.serverlistctrl.RefreshServer( update );
}
switch(opcode){
case OP_GLOBSEARCHRES:{
theApp.downloadqueue->AddDownDataOverheadOther(size);
theApp.emuledlg->searchwnd.AddUDPResult(theApp.searchlist->ProcessUDPSearchanswer(packet,size));
break;
}
case OP_GLOBFOUNDSORUCES:{
theApp.downloadqueue->AddDownDataOverheadOther(size);
CSafeMemFile* sources = new CSafeMemFile((BYTE*)packet,size);
uchar fileid[16];
sources->Read(fileid,16);
if (CPartFile* file = theApp.downloadqueue->GetFileByID(fileid))
file->AddSources(sources,inet_addr(host),port);
else
theApp.serverlist->CancelUDPBroadcast();
delete sources;
break;
}
case OP_GLOBSERVSTATRES:{
theApp.downloadqueue->AddDownDataOverheadOther(size);
if( size < 12 || update == NULL )
return true;
uint32 challenge;
memcpy(&challenge,packet,4);
if( challenge != update->GetChallenge() )
return true;
uint32 cur_user;
memcpy(&cur_user,packet+4,4);
uint32 cur_files;
memcpy(&cur_files,packet+8,4);
uint32 cur_maxusers = 0;
if( size >= 16 ){
memcpy(&cur_maxusers, packet+12,4);
}
if( update ){
update->SetPing( ::GetTickCount() - update->GetLastPinged() );
update->SetUserCount( cur_user );
update->SetFileCount( cur_files );
update->SetMaxUsers( cur_maxusers );
theApp.emuledlg->serverwnd.serverlistctrl.RefreshServer( update );
}
break;
}
case OP_SERVER_DESC_RES:{
if(!update)
return true;
theApp.downloadqueue->AddDownDataOverheadOther(size);
CSafeMemFile* srvinfo = new CSafeMemFile((BYTE*)packet,size);
uint16 stringlen;
srvinfo->Read(&stringlen,2);
char* name = new char[stringlen+1];
srvinfo->Read(name,stringlen);
name[stringlen] = 0;
srvinfo->Read(&stringlen,2);
char* desc = new char[stringlen+1];
srvinfo->Read(desc,stringlen);
desc[stringlen] = 0;
if(update){
update->SetDescription(desc);
update->SetListName(name);
}
delete name;
delete desc;
delete srvinfo;
break;
}
default:
theApp.downloadqueue->AddDownDataOverheadOther(size);
return false;
}
return true;
}
catch(...){
OUTPUT_DEBUG_TRACE();
theApp.emuledlg->AddDebugLogLine(false,GetResString(IDS_ERR_UDP_MISCONF));
return false;
}
}
bool CUDPSocket::ProcessExtPacket(char* packet, int16 size, int8 opcode, char* host, uint16 port){
try{
switch(opcode){
/*
case OP_UDPVERIFYUPREQ:{
ASSERT (size == 6);
if (size == 6){
uint32 checkclientip = 0;
uint16 checkclientport = 0;
memcpy(&checkclientip,packet,4);
memcpy(&checkclientport,packet,2);
if (theApp.clientlist->VerifyUpload(checkclientip,checkclientport)){
Packet answer(OP_UDPVERIFYUPA,0,OP_EMULEPROT);
SendTo(answer.GetUDPHeader(),2,port,host);
}
}
break;
}*/
case OP_UDPVERIFYUPA:{
theApp.downloadqueue->AddDownDataOverheadOther(size);
break;
}
default:
theApp.downloadqueue->AddDownDataOverheadOther(size);
return false;
}
return true;
}
catch(...){
OUTPUT_DEBUG_TRACE();
theApp.emuledlg->AddDebugLogLine(false,GetResString(IDS_ERR_UDPEXT));
return false;
}
}
void CUDPSocket::AsyncResolveDNS(LPCTSTR lpszHostAddress, UINT nHostPort){
m_lpszHostAddress = lpszHostAddress;
m_nHostPort = nHostPort;
if (DnsTaskHandle)
WSACancelAsyncRequest(DnsTaskHandle);
DnsTaskHandle = NULL;
// see if we have a ip already
USES_CONVERSION;
SOCKADDR_IN sockAddr;
memset(&sockAddr,0,sizeof(sockAddr));
LPSTR lpszAscii = T2A((LPTSTR)m_lpszHostAddress);
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = inet_addr(lpszAscii);
sockAddr.sin_port = htons((u_short)m_nHostPort);
// backup for send socket
m_SaveAddr = sockAddr;
if (sockAddr.sin_addr.s_addr == INADDR_NONE){
/* Resolve hostname "hostname" asynchronously */
memset(DnsHostBuffer, 0, sizeof(DnsHostBuffer));
DnsTaskHandle = WSAAsyncGetHostByName(
m_hWndResolveMessage,
WM_DNSLOOKUPDONE,
lpszHostAddress,
DnsHostBuffer,
MAXGETHOSTSTRUCT);
if (DnsTaskHandle == 0){
delete[] sendbuffer;
sendbuffer = 0;
delete cur_server;
cur_server = 0;
#ifdef _DEBUG
AfxMessageBox("LOOKUPERROR DNSTASKHANDLE = 0");
#endif
}
}
else{
SendBuffer();
}
}
void CUDPSocket::DnsLookupDone(WPARAM wp, LPARAM lp){
DnsTaskHandle = NULL;
/* An asynchronous database routine completed. */
if (WSAGETASYNCERROR(lp) != 0){
if (sendbuffer)
delete[] sendbuffer;
sendbuffer = 0;
if (cur_server)
delete cur_server;
cur_server = 0;
return;
}
if (m_SaveAddr.sin_addr.s_addr == INADDR_NONE){
// get the structure length
int iBufLen = WSAGETASYNCBUFLEN(lp);
LPHOSTENT lphost = (LPHOSTENT)malloc(iBufLen);
memcpy(lphost, DnsHostBuffer, iBufLen);
m_SaveAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
free(lphost);
// also reset the receive buffer
memset(DnsHostBuffer, 0, sizeof(DnsHostBuffer));
}
if (cur_server){
CServer* update = theApp.serverlist->GetServerByAddress(cur_server->GetAddress(),cur_server->GetPort());
if (update)
update->SetID(m_SaveAddr.sin_addr.S_un.S_addr);
SendBuffer();
}
}
void CUDPSocket::SendBuffer(){
if(cur_server && sendbuffer){
SendTo(sendbuffer,sendblen,(SOCKADDR*)&m_SaveAddr, sizeof(m_SaveAddr));
delete[] sendbuffer;
sendbuffer = 0;
delete cur_server;
cur_server = 0;
}
}
void CUDPSocket::SendPacket(Packet* packet,CServer* host){
cur_server = new CServer(host);
sendbuffer = new char[packet->size+2];
memcpy(sendbuffer,packet->GetUDPHeader(),2);
memcpy(sendbuffer+2,packet->pBuffer,packet->size);
sendblen = packet->size+2;
AsyncResolveDNS(cur_server->GetAddress(),cur_server->GetPort()+4);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -