From 4a7957c1b647edb2cbfb2ac0a5b6330e903cce60 Mon Sep 17 00:00:00 2001 From: neru Date: Fri, 20 Mar 2026 05:03:11 -0300 Subject: [PATCH] feat: add basic (unfinished) proxy --- src/unlocker/proxy.cpp | 155 +++++++++++++++++++++++++++++++++++++++++ src/unlocker/proxy.h | 25 +++++++ 2 files changed, 180 insertions(+) create mode 100644 src/unlocker/proxy.cpp create mode 100644 src/unlocker/proxy.h diff --git a/src/unlocker/proxy.cpp b/src/unlocker/proxy.cpp new file mode 100644 index 0000000..060a030 --- /dev/null +++ b/src/unlocker/proxy.cpp @@ -0,0 +1,155 @@ +#include "proxy.h" + +#include +#include + +#include + +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); +} \ No newline at end of file diff --git a/src/unlocker/proxy.h b/src/unlocker/proxy.h new file mode 100644 index 0000000..6b4fa4a --- /dev/null +++ b/src/unlocker/proxy.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#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 _running; +};