feat: add basic (unfinished) proxy
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
#include "proxy.h"
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#include <nerutils/log.h>
|
||||
|
||||
Proxy::Proxy() {}
|
||||
|
||||
Proxy::~Proxy() {}
|
||||
|
||||
bool Proxy::Init()
|
||||
{
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
|
||||
{
|
||||
Log::error("WSAStartup failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
_listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (_listenSocket == INVALID_SOCKET)
|
||||
{
|
||||
Log::error("Error creating listen socket: {0:x}", WSAGetLastError());
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
sockaddr_in serverAddr;
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(PROXY_PORT);
|
||||
inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr);
|
||||
|
||||
if (bind(_listenSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
|
||||
{
|
||||
Log::error("Error binding listen socket: {0:x}", WSAGetLastError());
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
listen(_listenSocket, SOMAXCONN);
|
||||
|
||||
Log::verbose("Listening on 127.0.0.1:{}", PROXY_PORT);
|
||||
|
||||
_running = true;
|
||||
_workerThread = std::thread(&Proxy::loop, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Proxy::Shutdown()
|
||||
{
|
||||
_running = false;
|
||||
|
||||
if (_listenSocket != INVALID_SOCKET && _listenSocket != 0)
|
||||
{
|
||||
closesocket(_listenSocket);
|
||||
_listenSocket = 0;
|
||||
}
|
||||
|
||||
if (_workerThread.joinable()) _workerThread.join();
|
||||
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
void Proxy::loop()
|
||||
{
|
||||
while (_running)
|
||||
{
|
||||
SOCKET clientSocket = accept(_listenSocket, NULL, NULL);
|
||||
|
||||
if (!_running)
|
||||
{
|
||||
if (clientSocket != INVALID_SOCKET) closesocket(clientSocket);
|
||||
break;
|
||||
}
|
||||
|
||||
if (clientSocket == INVALID_SOCKET) continue;
|
||||
|
||||
std::thread([this, clientSocket]() { this->handleClient(clientSocket); }).detach();
|
||||
}
|
||||
}
|
||||
|
||||
void Proxy::handleClient(SOCKET clientSocket)
|
||||
{
|
||||
char buffer[8192];
|
||||
int bytesReceived = recv(clientSocket, buffer, sizeof(buffer) - 1, 0);
|
||||
|
||||
if (bytesReceived <= 0)
|
||||
{
|
||||
closesocket(clientSocket);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string request(buffer, bytesReceived);
|
||||
|
||||
/*
|
||||
get host
|
||||
*/
|
||||
std::string host;
|
||||
size_t hostPos = request.find("Host: ");
|
||||
if (hostPos != std::string::npos)
|
||||
{
|
||||
size_t endPos = request.find("\r\n", hostPos);
|
||||
host = request.substr(hostPos + 6, endPos - (hostPos + 6));
|
||||
}
|
||||
|
||||
if (host.empty())
|
||||
{
|
||||
closesocket(clientSocket);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
handle remote
|
||||
*/
|
||||
struct addrinfo hints = {}, *res;
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (getaddrinfo(host.c_str(), "80", &hints, &res) != 0)
|
||||
{
|
||||
Log::error("Could not resolve host: {}", host);
|
||||
closesocket(clientSocket);
|
||||
return;
|
||||
}
|
||||
|
||||
SOCKET remoteSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (connect(remoteSocket, res->ai_addr, (int)res->ai_addrlen) == SOCKET_ERROR)
|
||||
{
|
||||
Log::error("Connection to {} failed", host);
|
||||
freeaddrinfo(res);
|
||||
closesocket(clientSocket);
|
||||
return;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
|
||||
/*
|
||||
fwd
|
||||
*/
|
||||
send(remoteSocket, buffer, bytesReceived, 0);
|
||||
|
||||
/*
|
||||
recv
|
||||
*/
|
||||
int remoteBytes;
|
||||
while ((remoteBytes = recv(remoteSocket, buffer, sizeof(buffer), 0)) > 0)
|
||||
{
|
||||
// Log::verbose("Forwarding {} bytes from server back to client", remoteBytes);
|
||||
send(clientSocket, buffer, remoteBytes, 0);
|
||||
}
|
||||
|
||||
closesocket(remoteSocket);
|
||||
closesocket(clientSocket);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
||||
#define PROXY_PORT 1337
|
||||
|
||||
typedef unsigned __int64 SOCKET;
|
||||
|
||||
class Proxy {
|
||||
public:
|
||||
Proxy();
|
||||
~Proxy();
|
||||
|
||||
bool Init();
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
void loop();
|
||||
void handleClient(SOCKET clientSocket);
|
||||
|
||||
SOCKET _listenSocket = 0;
|
||||
std::thread _workerThread;
|
||||
std::atomic<bool> _running;
|
||||
};
|
||||
Reference in New Issue
Block a user