📄 udpsocket.cpp
字号:
//
// NOTE: To properly distinguish between the two packets which are both useing the same opcode...
// the first two bytes of <challenge> (in network byte order) have to be an invalid <name_len> at least.
CSafeMemFile srvinfo(packet, size);
if (size >= 8 && PeekUInt16(packet) == INV_SERV_DESC_LEN)
{
if (update->GetDescReqChallenge() != 0 && PeekUInt32(packet) == update->GetDescReqChallenge())
{
update->SetDescReqChallenge(0);
(void)srvinfo.ReadUInt32(); // skip challenge
UINT uTags = srvinfo.ReadUInt32();
for (UINT i = 0; i < uTags; i++)
{
CTag tag(&srvinfo, update->GetUnicodeSupport());
if (tag.GetNameID() == ST_SERVERNAME && tag.IsStr())
update->SetListName(tag.GetStr());
else if (tag.GetNameID() == ST_DESCRIPTION && tag.IsStr())
update->SetDescription(tag.GetStr());
else if (tag.GetNameID() == ST_DYNIP && tag.IsStr())
update->SetDynIP(tag.GetStr());
else if (tag.GetNameID() == ST_VERSION && tag.IsStr())
update->SetVersion(tag.GetStr());
else if (tag.GetNameID() == ST_VERSION && tag.IsInt()){
CString strVersion;
strVersion.Format(_T("%u.%u"), tag.GetInt() >> 16, tag.GetInt() & 0xFFFF);
update->SetVersion(strVersion);
}
else if (tag.GetNameID() == ST_AUXPORTSLIST && tag.IsStr())
// currently not implemented.
; // <string> = <port> [, <port>...]
else{
if (thePrefs.GetDebugServerUDPLevel() > 0)
Debug(_T("***NOTE: Unknown tag in OP_ServerDescRes: %s\n"), tag.GetFullInfo());
}
}
}
else
{
// A server sent us a new server description packet (including a challenge) although we did not
// ask for it. This may happen, if there are multiple servers running on the same machine with
// multiple IPs. If such a server is asked for a description, the server will answer 2 times,
// but with the same IP.
if (thePrefs.GetDebugServerUDPLevel() > 0)
Debug(_T("***NOTE: Received unexpected new format OP_ServerDescRes from %s:%u with challenge %08x (waiting on packet with challenge %08x)\n"), ipstr(nIP), nUDPPort-4, PeekUInt32(packet), update->GetDescReqChallenge());
; // ignore this packet
}
}
else
{
CString strName = srvinfo.ReadString(update->GetUnicodeSupport());
CString strDesc = srvinfo.ReadString(update->GetUnicodeSupport());
update->SetDescription(strDesc);
update->SetListName(strName);
}
if (thePrefs.GetDebugServerUDPLevel() > 0){
UINT uAddData = srvinfo.GetLength() - srvinfo.GetPosition();
if (uAddData)
Debug(_T("***NOTE: ServerUDPMessage from %s:%u - OP_ServerDescRes: ***AddData: %s\n"), ipstr(nIP), nUDPPort-4, DbgGetHexDump(packet + srvinfo.GetPosition(), uAddData));
}
theApp.emuledlg->serverwnd->serverlistctrl.RefreshServer(update);
break;
}
default:
if (thePrefs.GetDebugServerUDPLevel() > 0)
Debug(_T("***NOTE: ServerUDPMessage from %s:%u - Unknown packet: opcode=0x%02X %s\n"), ipstr(nIP), nUDPPort-4, opcode, DbgGetHexDump(packet, size));
return false;
}
return true;
}
catch(CFileException* error){
TCHAR szError[MAX_CFEXP_ERRORMSG];
error->m_strFileName = _T("server UDP packet");
if (!error->GetErrorMessage(szError, ARRSIZE(szError)))
szError[0] = _T('\0');
ProcessPacketError(size, opcode, nIP, nUDPPort-4, szError);
error->Delete();
//ASSERT(0);
if (opcode==OP_GLOBSEARCHRES || opcode==OP_GLOBFOUNDSOURCES)
return true;
}
catch(CMemoryException* error){
TCHAR szError[MAX_CFEXP_ERRORMSG];
if (!error->GetErrorMessage(szError, ARRSIZE(szError)))
szError[0] = _T('\0');
ProcessPacketError(size, opcode, nIP, nUDPPort-4, szError);
error->Delete();
//ASSERT(0);
if (opcode==OP_GLOBSEARCHRES || opcode==OP_GLOBFOUNDSOURCES)
return true;
}
catch(CString error){
ProcessPacketError(size, opcode, nIP, nUDPPort-4, error);
//ASSERT(0);
}
catch(...){
ProcessPacketError(size, opcode, nIP, nUDPPort-4, _T("Unknown exception"));
ASSERT(0);
}
return false;
}
void CUDPSocket::ProcessPacketError(UINT size, UINT opcode, uint32 nIP, uint16 nTCPPort, LPCTSTR pszError)
{
if (thePrefs.GetVerbose())
{
CString strName;
CServer* pServer = theApp.serverlist->GetServerByAddress(ipstr(nIP), nTCPPort);
if (pServer)
strName = _T(" (") + pServer->GetListName() + _T(")");
AddDebugLogLine(false, _T("Error: Failed to process server UDP packet from %s:%u%s opcode=0x%02x size=%u - %s"), ipstr(nIP), nTCPPort, strName, opcode, size, pszError);
}
}
void CUDPSocket::AsyncResolveDNS(LPCSTR lpszHostAddressA, UINT nHostPort)
{
if (m_DnsTaskHandle){
WSACancelAsyncRequest(m_DnsTaskHandle);
m_DnsTaskHandle = NULL;
}
// see if we have a ip already
SOCKADDR_IN sockAddr = {0};
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = inet_addr(lpszHostAddressA);
sockAddr.sin_port = htons((u_short)nHostPort);
// backup for send socket
m_SaveAddr = sockAddr;
if (sockAddr.sin_addr.s_addr == INADDR_NONE){
/* Resolve hostname "hostname" asynchronously */
memset(m_DnsHostBuffer, 0, sizeof(m_DnsHostBuffer));
m_DnsTaskHandle = WSAAsyncGetHostByName(
m_hWndResolveMessage,
WM_DNSLOOKUPDONE,
lpszHostAddressA,
m_DnsHostBuffer,
MAXGETHOSTSTRUCT);
if (m_DnsTaskHandle == NULL){
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Error: Server UDP socket: Failed to resolve address for '%hs' - %s"), lpszHostAddressA, GetErrorMessage(GetLastError(), 1));
delete[] m_sendbuffer;
m_sendbuffer = NULL;
delete m_cur_server;
m_cur_server = NULL;
}
}
else{
SendBuffer();
}
}
void CUDPSocket::DnsLookupDone(WPARAM wp, LPARAM lp){
m_DnsTaskHandle = NULL;
/* An asynchronous database routine completed. */
if (WSAGETASYNCERROR(lp) != 0){
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Error: Server UDP socket: Failed to resolve address for server '%s' (%s) - %s"), m_cur_server ? m_cur_server->GetListName() : _T(""), m_cur_server ? m_cur_server->GetAddress() : _T(""), GetErrorMessage(WSAGETASYNCERROR(lp), 1));
delete[] m_sendbuffer;
m_sendbuffer = NULL;
delete m_cur_server;
m_cur_server = NULL;
return;
}
if (m_SaveAddr.sin_addr.s_addr == INADDR_NONE){
// get the structure length
int iBufLen = WSAGETASYNCBUFLEN(lp);
if (iBufLen >= sizeof(HOSTENT)){
LPHOSTENT pHost = (LPHOSTENT)m_DnsHostBuffer;
if (pHost->h_length == 4 && pHost->h_addr_list && pHost->h_addr_list[0])
m_SaveAddr.sin_addr.s_addr = ((LPIN_ADDR)(pHost->h_addr_list[0]))->s_addr;
}
// also reset the receive buffer
memset(m_DnsHostBuffer, 0, sizeof(m_DnsHostBuffer));
}
if (m_cur_server){
if (m_SaveAddr.sin_addr.s_addr != INADDR_NONE){
bool bRemoveServer = false;
if (!IsGoodIP(m_SaveAddr.sin_addr.s_addr)){
if (thePrefs.GetLogFilteredIPs())
AddDebugLogLine(false, _T("Resolved IP for server '%s' is %s - Invalid IP or LAN address, server deleted."), m_cur_server->GetListName(), ipstr(m_SaveAddr.sin_addr.s_addr));
bRemoveServer = true;
}
if (!bRemoveServer && theApp.ipfilter->IsFiltered(m_SaveAddr.sin_addr.s_addr)){
if (thePrefs.GetLogFilteredIPs())
AddDebugLogLine(false, _T("Resolved IP for server '%s' is %s - Found in IP filter, server deleted."), m_cur_server->GetListName(), ipstr(m_SaveAddr.sin_addr.s_addr));
bRemoveServer = true;
}
if (!bRemoveServer){
CServer* update = theApp.serverlist->GetServerByAddress(m_cur_server->GetAddress(),m_cur_server->GetPort());
if (update)
update->SetIP(m_SaveAddr.sin_addr.S_un.S_addr);
SendBuffer();
}
else{
CServer* todel = theApp.serverlist->GetServerByAddress(m_cur_server->GetAddress(), m_cur_server->GetPort());
if (todel)
theApp.emuledlg->serverwnd->serverlistctrl.RemoveServer(todel);
delete m_cur_server;
m_cur_server = NULL;
delete[] m_sendbuffer;
m_sendbuffer = NULL;
m_sendblen = 0;
}
}
else{
// still no valid IP for this server - delete packet
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Error: Server UDP socket: Failed to resolve address for server '%s' (%s)"), m_cur_server->GetListName(), m_cur_server->GetAddress());
delete m_cur_server;
m_cur_server = NULL;
delete[] m_sendbuffer;
m_sendbuffer = NULL;
m_sendblen = 0;
}
}
}
void CUDPSocket::OnSend(int nErrorCode){
if (nErrorCode){
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Error: Server UDP socket: Failed to send packet - %s"), GetErrorMessage(nErrorCode, 1));
return;
}
m_bWouldBlock = false;
// ZZ:UploadBandWithThrottler (UDP) -->
sendLocker.Lock();
if(!controlpacket_queue.IsEmpty()) {
theApp.uploadBandwidthThrottler->QueueForSendingControlPacket(this);
}
sendLocker.Unlock();
// <-- ZZ:UploadBandWithThrottler (UDP)
}
SocketSentBytes CUDPSocket::SendControlData(uint32 maxNumberOfBytesToSend, uint32 minFragSize) { // ZZ:UploadBandWithThrottler (UDP)
// ZZ:UploadBandWithThrottler (UDP) -->
// NOTE: *** This function is invoked from a *different* thread!
sendLocker.Lock();
uint32 sentBytes = 0;
// <-- ZZ:UploadBandWithThrottler (UDP)
while (controlpacket_queue.GetHeadPosition() != 0 && !IsBusy() && sentBytes < maxNumberOfBytesToSend) // ZZ:UploadBandWithThrottler (UDP)
{
SServerUDPPacket* packet = controlpacket_queue.GetHead();
int sendSuccess = SendTo(packet->packet, packet->size, packet->dwIP, packet->nPort);
if (sendSuccess >= 0){
if(sendSuccess > 0) {
sentBytes += packet->size; // ZZ:UploadBandWithThrottler (UDP)
}
controlpacket_queue.RemoveHead();
delete[] packet->packet;
delete packet;
}
}
// ZZ:UploadBandWithThrottler (UDP) -->
if(!IsBusy() && !controlpacket_queue.IsEmpty()) {
theApp.uploadBandwidthThrottler->QueueForSendingControlPacket(this);
}
sendLocker.Unlock();
SocketSentBytes returnVal = { true, 0, sentBytes };
return returnVal;
// <-- ZZ:UploadBandWithThrottler (UDP)
}
int CUDPSocket::SendTo(uint8* lpBuf, int nBufLen, uint32 dwIP, uint16 nPort){
// NOTE: *** This function is invoked from a *different* thread!
int iResult = CAsyncSocket::SendTo(lpBuf, nBufLen, nPort, ipstr(dwIP));
if (iResult == SOCKET_ERROR){
DWORD dwError = GetLastError();
if (dwError == WSAEWOULDBLOCK){
m_bWouldBlock = true;
return -1; // blocked
}
else{
if (thePrefs.GetVerbose())
theApp.QueueDebugLogLine(false, _T("Error: Server UDP socket: Failed to send packet to %s:%u - %s"), ipstr(dwIP), nPort, GetErrorMessage(dwError, 1));
return 0; // error
}
}
return 1; // success
}
void CUDPSocket::SendBuffer(){
if(m_cur_server && m_sendbuffer){
u_short nPort = ntohs(m_SaveAddr.sin_port);
// ZZ:UploadBandWithThrottler (UDP) -->
SServerUDPPacket* newpending = new SServerUDPPacket;
newpending->dwIP = m_SaveAddr.sin_addr.s_addr;
newpending->nPort = nPort;
newpending->packet = m_sendbuffer;
newpending->size = m_sendblen;
sendLocker.Lock();
controlpacket_queue.AddTail(newpending);
sendLocker.Unlock();
theApp.uploadBandwidthThrottler->QueueForSendingControlPacket(this);
// <-- ZZ:UploadBandWithThrottler (UDP)
m_sendbuffer = NULL;
m_sendblen = 0;
delete m_cur_server;
m_cur_server = NULL;
}
}
void CUDPSocket::SendPacket(Packet* packet,CServer* host){
USES_CONVERSION;
// if the last DNS query did not yet return, we may still have a packet queued - delete it
if (thePrefs.GetVerbose() && m_cur_server)
AddDebugLogLine(false, _T("Warning: Server UDP socket: Timeout occured when trying to resolve address for server '%s' (%s)"), m_cur_server->GetListName(), m_cur_server->GetAddress());
delete m_cur_server;
m_cur_server = NULL;
delete[] m_sendbuffer;
m_sendbuffer = NULL;
m_sendblen = 0;
m_cur_server = new CServer(host);
m_sendbuffer = new uint8[packet->size+2];
memcpy(m_sendbuffer,packet->GetUDPHeader(),2);
memcpy(m_sendbuffer+2,packet->pBuffer,packet->size);
m_sendblen = packet->size+2;
AsyncResolveDNS(T2CA(m_cur_server->GetAddress()),m_cur_server->GetPort()+4);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -