mirror of
https://github.com/netchx/netch.git
synced 2026-03-14 17:43:18 +08:00
178 lines
3.3 KiB
C++
178 lines
3.3 KiB
C++
#include "DNSHandler.h"
|
|
|
|
#include "Utils.h"
|
|
|
|
void dns_freePacket(PDNSPKT i)
|
|
{
|
|
if (i)
|
|
{
|
|
if (i->Target)
|
|
{
|
|
delete[] i->Target;
|
|
}
|
|
|
|
if (i->Buffer)
|
|
{
|
|
delete[] i->Buffer;
|
|
}
|
|
|
|
if (i->Option)
|
|
{
|
|
delete i->Option;
|
|
}
|
|
|
|
delete i;
|
|
}
|
|
|
|
i = NULL;
|
|
}
|
|
|
|
DNSHandler::DNSHandler(string dnsHost, USHORT dnsPort)
|
|
{
|
|
this->dnsHost = dnsHost;
|
|
this->dnsPort = dnsPort;
|
|
}
|
|
|
|
BOOL DNSHandler::init()
|
|
{
|
|
this->Started = TRUE;
|
|
|
|
WaitForSingleObject(this->dnsLock, INFINITE);
|
|
for (size_t i = 0; i < 4; i++)
|
|
{
|
|
this->dnsLoop[i] = thread(&DNSHandler::Thread, this);
|
|
}
|
|
ReleaseMutex(this->dnsLock);
|
|
}
|
|
|
|
void DNSHandler::free()
|
|
{
|
|
if (this->dnsLock)
|
|
{
|
|
WaitForSingleObject(this->dnsLock, INFINITE);
|
|
}
|
|
|
|
this->Started = FALSE;
|
|
for (size_t i = 0; i < this->dnsLoop.size(); i++)
|
|
{
|
|
if (this->dnsLoop[i].joinable())
|
|
{
|
|
this->dnsLoop[i].join();
|
|
}
|
|
}
|
|
this->dnsLoop.clear();
|
|
|
|
auto size = this->dnsList.size();
|
|
for (size_t i = 0; i < size; i++)
|
|
{
|
|
dns_freePacket(this->dnsList.front());
|
|
}
|
|
|
|
if (this->dnsLock)
|
|
{
|
|
CloseHandle(this->dnsLock);
|
|
this->dnsLock = NULL;
|
|
}
|
|
}
|
|
|
|
void DNSHandler::Create(ENDPOINT_ID id, PBYTE target, ULONG targetLength, PCHAR buffer, ULONG bufferLength, PNF_UDP_OPTIONS option)
|
|
{
|
|
if (!this->Started)
|
|
{
|
|
return;
|
|
}
|
|
|
|
auto data = new DNSPKT();
|
|
data->ID = id;
|
|
data->Target = new BYTE[targetLength]();
|
|
data->TargetLength = targetLength;
|
|
data->Buffer = new CHAR[bufferLength]();
|
|
data->BufferLength = bufferLength;
|
|
data->Option = new NF_UDP_OPTIONS();
|
|
|
|
memcpy(data->Target, target, targetLength);
|
|
memcpy(data->Buffer, buffer, bufferLength);
|
|
memcpy(data->Option, option, sizeof(NF_UDP_OPTIONS));
|
|
|
|
WaitForSingleObject(this->dnsLock, INFINITE);
|
|
this->dnsList.emplace(data);
|
|
ReleaseMutex(this->dnsLock);
|
|
}
|
|
|
|
void DNSHandler::Thread()
|
|
{
|
|
while (this->Started && this->dnsLock)
|
|
{
|
|
switch (WaitForSingleObject(this->dnsLock, 10))
|
|
{
|
|
case WAIT_OBJECT_0:
|
|
this->Handle();
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DNSHandler::Handle()
|
|
{
|
|
SOCKADDR_IN addr;
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(this->dnsPort);
|
|
if (!inet_pton(AF_INET, this->dnsHost.c_str(), &addr.sin_addr))
|
|
{
|
|
ReleaseMutex(this->dnsLock);
|
|
return;
|
|
}
|
|
|
|
auto data = this->dnsList.front();
|
|
this->dnsList.pop();
|
|
ReleaseMutex(this->dnsLock);
|
|
|
|
auto client = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
if (!client)
|
|
{
|
|
dns_freePacket(data);
|
|
|
|
printf("[Redirector][DNSHandler::Handle] Create socket failed: %d\n", WSAGetLastError());
|
|
return;
|
|
}
|
|
|
|
TIMEVAL tv;
|
|
tv.tv_sec = 4;
|
|
tv.tv_usec = 0;
|
|
|
|
FD_SET fds;
|
|
FD_ZERO(&fds);
|
|
FD_SET(client, &fds);
|
|
|
|
if (sendto(client, data->Buffer, data->BufferLength, 0, (PSOCKADDR)&addr, sizeof(SOCKADDR_IN)))
|
|
{
|
|
if (select(0, &fds, 0, 0, &tv))
|
|
{
|
|
CHAR buffer[1024];
|
|
auto length = recvfrom(client, buffer, sizeof(buffer), 0, NULL, NULL);
|
|
|
|
if (length)
|
|
{
|
|
nf_udpPostReceive(data->ID, data->Target, buffer, length, data->Option);
|
|
}
|
|
else
|
|
{
|
|
printf("[Redirector][DNSHandler::Handle] Receive failed: %d\n", WSAGetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
puts("[Redirector][DNSHandler::Handle] Receive timed out");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("[Redirector][DNSHandler::Handle] Send failed: %d\n", WSAGetLastError());
|
|
}
|
|
|
|
closesocket(client);
|
|
dns_freePacket(data);
|
|
}
|