sparkle/libs/tls/network.hpp
ZZMOaG(vj3GeCEpn7k76EZFEj_PL$%u@9)Oxp;BrMykYFFxC
 1fb42627b1 added
2024-12-31 02:20:56 +05:00

107 lines
3.8 KiB
C++

#ifndef TLS_NETWORK_HPP_
#define TLS_NETWORK_HPP_
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <memory>
#include <iostream>
#include <string>
#include <net/if.h>
#include <netdb.h>
#include <unistd.h>
#include <utils/types.hpp>
using std::cout;
using std::cerr;
using std::endl;
class NetworkManager {
private:
static NetworkManager* instance;
SSL_CTX* ctx;
int sock = -1;
std::string result;
std::unique_ptr<SSL, decltype(&SSL_free)> ssl = { nullptr, &SSL_free };
void handleSSLInitErrors() {
ERR_print_errors_fp(stderr);
abort();
}
void createSSLConnection(const std::string& hostname, const std::string& port) {
addrinfo hints = { 0 }, * res = { 0 };
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(hostname.c_str(), port.c_str(), &hints, &res) != 0) {
cerr << "Failed to get address info for " << hostname << ":" << port << endl;
handleSSLInitErrors();
}
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sock == -1) {
cerr << "Failed to create socket" << endl;
handleSSLInitErrors();
}
if (connect(sock, res->ai_addr, res->ai_addrlen) == -1) {
cerr << "Failed to connect to " << hostname << ":" << port << endl;
close(sock);
handleSSLInitErrors();
}
ssl.reset(SSL_new(ctx));
if (!ssl) {
cerr << "Failed to create SSL structure" << endl;
close(sock);
handleSSLInitErrors();
}
SSL_set_fd(ssl.get(), sock);
if (SSL_connect(ssl.get()) != 1) {
cerr << "SSL connection failed" << endl;
close(sock);
handleSSLInitErrors();
}
freeaddrinfo(res);
}
NetworkManager() : ctx(nullptr), result("") {
if (!ctx) {
ctx = SSL_CTX_new(TLS_client_method());
if (!ctx) {
cerr << "Failed to create SSL context" << endl;
handleSSLInitErrors();
}
OPENSSL_init_ssl(0, 0);
OPENSSL_add_all_algorithms_noconf();
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
createSSLConnection("discord.com", "443");
}
}
public:
static NetworkManager* getInstance() {
if (!instance) {
instance = new NetworkManager();
}
return instance;
}
~NetworkManager() {
if (ctx) SSL_CTX_free(ctx);
close(sock);
}
const std::string& request(const std::string& method, const std::string& path, const std::string& authorization, const std::string& data) {
auto net = [this, method, path, authorization, data, bytesRead = 0, request = std::string("")]() mutable -> void {
request = method + " " + path + " HTTP/1.1\r\nHost: discord.com\r\nAccept: application/json\r\nContent-Type: application/json\r\n";
request += "Authorization: " + authorization + "\r\n";
request += "Content-Length: " + std::to_string(data.length()) + "\r\n";
request += "Connection: keep-alive\r\n\r\n";
request += data;
if (SSL_write(ssl.get(), request.c_str(), request.length()) <= 0) {
cerr << "Failed to send request" << endl;
handleSSLInitErrors();
}
chngcol("REQUEST: " + path, 192, 255, 0);
#ifdef DEBUG
char buffer[4096];
while ((bytesRead = SSL_read(ssl.get(), buffer, sizeof(buffer))) > 0) {
result.append(buffer);
}
#endif
};
net();
return result;
}
};
NetworkManager* NetworkManager::instance = nullptr;
#endif