Browse Source

Fix & cleanup sockets; update jessilib

task/remove_strings
Jessica James 3 years ago
parent
commit
e4dc793c42
  1. 23
      src/common/IRC_Client.cpp
  2. 216
      src/common/SecureSocket.cpp
  3. 351
      src/common/Socket.cpp
  4. 29
      src/include/Jupiter/SecureSocket.h
  5. 48
      src/include/Jupiter/Socket.h
  6. 2
      src/jessilib

23
src/common/IRC_Client.cpp

@ -377,14 +377,12 @@ size_t Jupiter::IRC::Client::messageChannels(std::string_view message)
return m_channels.size();
}
int Jupiter::IRC::Client::process_line(std::string_view in_line) {
Jupiter::ReferenceString line{in_line}; // TODO: remove this
if (!line.empty())
{
int Jupiter::IRC::Client::process_line(std::string_view line) {
if (!line.empty()) {
Jupiter::IRC::Client::writeToLogs(line);
if (m_output != nullptr) {
// TODO: use ostream instead
fwrite(in_line.data(), sizeof(char), in_line.size(), m_output);
fwrite(line.data(), sizeof(char), line.size(), m_output);
fputs("\r\n", m_output);
}
@ -1116,8 +1114,7 @@ int Jupiter::IRC::Client::process_line(std::string_view in_line) {
return 0;
}
bool Jupiter::IRC::Client::connect()
{
bool Jupiter::IRC::Client::connect() {
std::string_view clientAddress = Jupiter::IRC::Client::readConfigValue("ClientAddress"_jrs);
if (m_socket->connect(m_server_hostname.c_str(), m_server_port, clientAddress.empty() ? nullptr : static_cast<std::string>(clientAddress).c_str(), (unsigned short)Jupiter::IRC::Client::readConfigLong("ClientPort"_jrs)) == false)
return false;
@ -1181,15 +1178,12 @@ void Jupiter::IRC::Client::reconnect()
}
}
int Jupiter::IRC::Client::think()
{
auto handle_error = [this](int error_code)
{
int Jupiter::IRC::Client::think() {
auto handle_error = [this](int error_code) {
if (this->m_dead == true)
return error_code;
if (this->m_max_reconnect_attempts < 0 || this->m_reconnect_attempts < this->m_max_reconnect_attempts)
{
if (this->m_max_reconnect_attempts < 0 || this->m_reconnect_attempts < this->m_max_reconnect_attempts) {
if (!this->m_reconnect_delay || this->m_reconnect_time < time(0))
this->reconnect();
@ -1203,8 +1197,7 @@ int Jupiter::IRC::Client::think()
return handle_error(-1);
int tmp = m_socket->recv();
if (tmp > 0)
{
if (tmp > 0) {
// Process incoming data
using namespace std::literals;
auto tokens = jessilib::split_view(m_socket->getBuffer(), "\r\n"sv);

216
src/common/SecureSocket.cpp

@ -21,66 +21,61 @@
#include <openssl/err.h> // OpenSSL SSL errors
#include "SecureSocket.h"
struct Jupiter::SecureSocket::SSLData
{
SSL *handle = nullptr;
SSL_CTX *context = nullptr;
const SSL_METHOD *method = nullptr;
Jupiter::SecureSocket::EncryptionMethod eMethod = ANY;
struct Jupiter::SecureSocket::SSLData {
SSL* handle = nullptr;
SSL_CTX* context = nullptr;
const SSL_METHOD* method = nullptr;
std::string cert;
std::string key;
~SSLData();
};
Jupiter::SecureSocket::SSLData::~SSLData()
{
if (Jupiter::SecureSocket::SSLData::handle != nullptr)
{
if (SSL_shutdown(Jupiter::SecureSocket::SSLData::handle) == 0) SSL_shutdown(Jupiter::SecureSocket::SSLData::handle);
Jupiter::SecureSocket::SSLData::~SSLData() {
if (Jupiter::SecureSocket::SSLData::handle != nullptr) {
if (SSL_shutdown(Jupiter::SecureSocket::SSLData::handle) == 0) {
SSL_shutdown(Jupiter::SecureSocket::SSLData::handle);
}
SSL_free(Jupiter::SecureSocket::SSLData::handle);
}
if (Jupiter::SecureSocket::SSLData::context != nullptr) SSL_CTX_free(Jupiter::SecureSocket::SSLData::context);
}
Jupiter::SecureSocket &Jupiter::SecureSocket::operator=(Jupiter::SecureSocket &&source)
{
Jupiter::SecureSocket &Jupiter::SecureSocket::operator=(Jupiter::SecureSocket &&source) {
Jupiter::Socket::operator=(std::move(source));
Jupiter::SecureSocket::SSLdata_ = source.SSLdata_;
source.SSLdata_ = nullptr;
m_ssl_data = source.m_ssl_data;
source.m_ssl_data = nullptr;
return *this;
}
Jupiter::SecureSocket::SecureSocket() : Jupiter::Socket()
{
Jupiter::SecureSocket::SSLdata_ = new Jupiter::SecureSocket::SSLData();
Jupiter::SecureSocket::SecureSocket() : Jupiter::Socket() {
m_ssl_data = new Jupiter::SecureSocket::SSLData();
}
Jupiter::SecureSocket::SecureSocket(size_t bufferSize) : Jupiter::Socket(bufferSize)
{
Jupiter::SecureSocket::SSLdata_ = new Jupiter::SecureSocket::SSLData();
Jupiter::SecureSocket::SecureSocket(size_t bufferSize)
: Jupiter::Socket(bufferSize) {
m_ssl_data = new Jupiter::SecureSocket::SSLData();
}
Jupiter::SecureSocket::SecureSocket(Jupiter::Socket &&source) : Jupiter::Socket(std::move(source))
{
Jupiter::SecureSocket::SSLdata_ = new Jupiter::SecureSocket::SSLData();
Jupiter::SecureSocket::SecureSocket(Jupiter::Socket &&source)
: Jupiter::Socket(std::move(source)) {
m_ssl_data = new Jupiter::SecureSocket::SSLData();
}
Jupiter::SecureSocket::SecureSocket(Jupiter::SecureSocket &&source) : Jupiter::Socket(std::move(source))
{
Jupiter::SecureSocket::SSLdata_ = source.SSLdata_;
source.SSLdata_ = nullptr;
Jupiter::SecureSocket::SecureSocket(Jupiter::SecureSocket &&source)
: Jupiter::Socket(std::move(source)) {
m_ssl_data = source.m_ssl_data;
source.m_ssl_data = nullptr;
}
Jupiter::SecureSocket::~SecureSocket()
{
if (Jupiter::SecureSocket::SSLdata_ != nullptr) delete Jupiter::SecureSocket::SSLdata_;
Jupiter::SecureSocket::~SecureSocket() {
if (m_ssl_data != nullptr) {
delete m_ssl_data;
}
}
Jupiter::SecureSocket *Jupiter::SecureSocket::accept()
{
SocketType tSock = SSL_accept(Jupiter::SecureSocket::SSLdata_->handle);
if (tSock > 0)
{
Jupiter::SecureSocket *Jupiter::SecureSocket::accept() {
SocketType tSock = SSL_accept(m_ssl_data->handle);
if (tSock > 0) {
SecureSocket *r = new SecureSocket(Jupiter::SecureSocket::getBufferSize());
r->setDescriptor(tSock);
r->setType(this->getType());
@ -90,86 +85,46 @@ Jupiter::SecureSocket *Jupiter::SecureSocket::accept()
return nullptr;
}
bool Jupiter::SecureSocket::bind(const char *hostname, unsigned short iPort, bool andListen)
{
bool Jupiter::SecureSocket::bind(const char *hostname, unsigned short iPort, bool andListen) {
return Jupiter::Socket::bind(hostname, iPort, andListen);
}
void Jupiter::SecureSocket::shutdown()
{
void Jupiter::SecureSocket::shutdown() {
Jupiter::Socket::shutdown();
if (Jupiter::SecureSocket::SSLdata_ != nullptr && Jupiter::SecureSocket::SSLdata_->handle != nullptr)
if (m_ssl_data != nullptr && m_ssl_data->handle != nullptr)
{
if (SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle) == 0)
SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle);
if (SSL_shutdown(m_ssl_data->handle) == 0) {
SSL_shutdown(m_ssl_data->handle);
}
}
}
void Jupiter::SecureSocket::close()
{
void Jupiter::SecureSocket::close() {
Jupiter::Socket::close();
if (Jupiter::SecureSocket::SSLdata_ != nullptr && Jupiter::SecureSocket::SSLdata_->handle != nullptr)
{
if (SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle) == 0)
SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle);
SSL_free(Jupiter::SecureSocket::SSLdata_->handle);
Jupiter::SecureSocket::SSLdata_->handle = nullptr;
}
}
const SSL_METHOD *translateEncryptionMethod(Jupiter::SecureSocket::EncryptionMethod method) {
// These are disabled due to deprecations, but also there's not that much reason to actually maintain this method
// since we realistically never use anything except EncryptionMethod::ANY. It was an interesting idea, but there
// just isn't a real use case for these methods. Regardless, better way to implement setMethod/getMethod() would be
// to not provide any abstract implementation at all, and to instead include such option setting as part of some
// OpenSSL provider plugin
switch (method) {
//case Jupiter::SecureSocket::EncryptionMethod::SSL3:
// return SSLv3_method();
case Jupiter::SecureSocket::EncryptionMethod::TLS1:
//return TLSv1_method();
case Jupiter::SecureSocket::EncryptionMethod::TLS1_1:
//return TLSv1_1_method();
case Jupiter::SecureSocket::EncryptionMethod::TLS1_2:
//return TLSv1_2_method();
case Jupiter::SecureSocket::EncryptionMethod::DTLS1:
//return DTLSv1_method();
case Jupiter::SecureSocket::EncryptionMethod::ANY:
return SSLv23_method();
default:
return nullptr;
if (m_ssl_data != nullptr && m_ssl_data->handle != nullptr) {
if (SSL_shutdown(m_ssl_data->handle) == 0) {
SSL_shutdown(m_ssl_data->handle);
}
SSL_free(m_ssl_data->handle);
m_ssl_data->handle = nullptr;
}
}
const char *Jupiter::SecureSocket::getCipherName() const
{
return SSL_CIPHER_get_name(SSL_get_current_cipher(Jupiter::SecureSocket::SSLdata_->handle));
const char *Jupiter::SecureSocket::getCipherName() const {
return SSL_CIPHER_get_name(SSL_get_current_cipher(m_ssl_data->handle));
}
Jupiter::SecureSocket::EncryptionMethod Jupiter::SecureSocket::getMethod() const
{
return Jupiter::SecureSocket::SSLdata_->eMethod;
}
void Jupiter::SecureSocket::setMethod(Jupiter::SecureSocket::EncryptionMethod method)
{
Jupiter::SecureSocket::SSLdata_->eMethod = method;
}
bool loadCertificate(SSL_CTX *context, const char *cert, const char *key)
{
bool loadCertificate(SSL_CTX *context, const char *cert, const char *key) {
if (SSL_CTX_load_verify_locations(context, cert, key) != 1) ERR_print_errors_fp(stderr);
if (SSL_CTX_set_default_verify_paths(context) != 1) ERR_print_errors_fp(stderr);
if (SSL_CTX_use_certificate_file(context, cert, SSL_FILETYPE_PEM) <= 0)
{
if (SSL_CTX_use_certificate_file(context, cert, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
return false;
}
if (SSL_CTX_use_PrivateKey_file(context, key, SSL_FILETYPE_PEM) <= 0)
{
if (SSL_CTX_use_PrivateKey_file(context, key, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
return false;
}
@ -178,95 +133,84 @@ bool loadCertificate(SSL_CTX *context, const char *cert, const char *key)
return true;
}
void Jupiter::SecureSocket::setCertificate(std::string cert, std::string key)
{
Jupiter::SecureSocket::SSLdata_->cert = std::move(cert);
Jupiter::SecureSocket::SSLdata_->key = std::move(key);
void Jupiter::SecureSocket::setCertificate(std::string cert, std::string key) {
m_ssl_data->cert = std::move(cert);
m_ssl_data->key = std::move(key);
}
void Jupiter::SecureSocket::setCertificate(std::string_view pem)
{
void Jupiter::SecureSocket::setCertificate(std::string_view pem) {
Jupiter::SecureSocket::setCertificate(static_cast<std::string>(pem), static_cast<std::string>(pem));
}
bool Jupiter::SecureSocket::connect(const char *hostname, unsigned short iPort, const char *clientAddress, unsigned short clientPort)
{
bool Jupiter::SecureSocket::connect(const char *hostname, unsigned short iPort, const char *clientAddress, unsigned short clientPort) {
return Jupiter::Socket::connect(hostname, iPort, clientAddress, clientPort) && this->initSSL();
}
int Jupiter::SecureSocket::peek()
{
if (Jupiter::SecureSocket::SSLdata_->handle == nullptr)
int Jupiter::SecureSocket::peek() {
if (m_ssl_data->handle == nullptr)
return -1;
Jupiter::Socket::Buffer &buffer = this->getInternalBuffer();
buffer.erase();
int r = SSL_peek(Jupiter::SecureSocket::SSLdata_->handle, buffer.get_str(), static_cast<int>(this->getBufferSize()));
buffer.clear();
int r = SSL_peek(m_ssl_data->handle, buffer.data(), static_cast<int>(this->getBufferSize()));
if (r > 0)
buffer.set_length(r);
return r;
}
int Jupiter::SecureSocket::recv()
{
if (Jupiter::SecureSocket::SSLdata_->handle == nullptr)
int Jupiter::SecureSocket::recv() {
if (m_ssl_data->handle == nullptr)
return -1;
Jupiter::Socket::Buffer &buffer = this->getInternalBuffer();
buffer.erase();
int r = SSL_read(Jupiter::SecureSocket::SSLdata_->handle, buffer.get_str(), static_cast<int>(this->getBufferSize()));
buffer.clear();
int r = SSL_read(m_ssl_data->handle, buffer.data(), static_cast<int>(this->getBufferSize()));
if (r > 0)
buffer.set_length(r);
return r;
}
int Jupiter::SecureSocket::send(const char *data, size_t datalen)
{
return SSL_write(Jupiter::SecureSocket::SSLdata_->handle, data, static_cast<int>(datalen));
int Jupiter::SecureSocket::send(const char *data, size_t datalen) {
return SSL_write(m_ssl_data->handle, data, static_cast<int>(datalen));
}
bool Jupiter::SecureSocket::initSSL()
{
bool Jupiter::SecureSocket::initSSL() {
SSL_load_error_strings();
SSL_library_init();
if (Jupiter::SecureSocket::SSLdata_->context == nullptr)
{
if (Jupiter::SecureSocket::SSLdata_->method == nullptr)
{
Jupiter::SecureSocket::SSLdata_->method = translateEncryptionMethod(Jupiter::SecureSocket::SSLdata_->eMethod);
if (Jupiter::SecureSocket::SSLdata_->method == nullptr)
if (m_ssl_data->context == nullptr) {
if (m_ssl_data->method == nullptr) {
m_ssl_data->method = TLS_method();
if (m_ssl_data->method == nullptr)
return false;
}
Jupiter::SecureSocket::SSLdata_->context = SSL_CTX_new(Jupiter::SecureSocket::SSLdata_->method);
if (Jupiter::SecureSocket::SSLdata_->context == nullptr)
{
m_ssl_data->context = SSL_CTX_new(m_ssl_data->method);
if (m_ssl_data->context == nullptr) {
ERR_print_errors_fp(stderr);
return false;
}
if (!Jupiter::SecureSocket::SSLdata_->cert.empty())
loadCertificate(Jupiter::SecureSocket::SSLdata_->context, Jupiter::SecureSocket::SSLdata_->cert.c_str(), Jupiter::SecureSocket::SSLdata_->key.c_str());
if (!m_ssl_data->cert.empty()) {
loadCertificate(m_ssl_data->context, m_ssl_data->cert.c_str(), m_ssl_data->key.c_str());
}
}
Jupiter::SecureSocket::SSLdata_->handle = SSL_new(Jupiter::SecureSocket::SSLdata_->context);
if (Jupiter::SecureSocket::SSLdata_->handle == nullptr)
{
m_ssl_data->handle = SSL_new(m_ssl_data->context);
if (m_ssl_data->handle == nullptr) {
ERR_print_errors_fp(stderr);
return false;
}
// Not suppressing this warning; descriptor ideally shouldn't be getting shortened here, even if it's "safe"
// TODO: Can't resolve this without removing OpenSSL usage on Windows; we should ideally use Windows APIs
if (SSL_set_fd(Jupiter::SecureSocket::SSLdata_->handle, this->getDescriptor()) == 0)
{
if (SSL_set_fd(m_ssl_data->handle, this->getDescriptor()) == 0) {
ERR_print_errors_fp(stderr);
return false;
}
if (SSL_set_tlsext_host_name(Jupiter::SecureSocket::SSLdata_->handle, this->getRemoteHostnameC()) != 1) // This error check is potentially redundant, but no documentation has been found.
{
if (SSL_set_tlsext_host_name(m_ssl_data->handle, this->getRemoteHostnameC()) != 1) {
// This error check is potentially redundant, but no documentation has been found.
ERR_print_errors_fp(stderr);
return false;
}
int t = SSL_connect(Jupiter::SecureSocket::SSLdata_->handle);
int t = SSL_connect(m_ssl_data->handle);
if (t != 1)
{
ERR_print_errors_fp(stderr);

351
src/common/Socket.cpp

@ -45,12 +45,68 @@ bool socketInit = false;
#pragma warning(disable: 4267)
#endif
constexpr size_t s_initial_buffer_size = 512;
Jupiter::Socket::Buffer::Buffer()
: m_buffer{ ::operator new(s_initial_buffer_size) },
m_buffer_capacity{ s_initial_buffer_size },
m_buffer_size{0} {
}
Jupiter::Socket::Buffer::~Buffer() {
::operator delete(m_buffer);
}
void Jupiter::Socket::Buffer::set_length(size_t in_length) {
this->length = in_length;
m_buffer_size = in_length;
}
char *Jupiter::Socket::Buffer::get_str() const {
return this->str;
size_t Jupiter::Socket::Buffer::capacity() const {
return m_buffer_capacity;
}
void Jupiter::Socket::Buffer::reserve(size_t new_capacity) {
if (capacity() == new_capacity // Skip when already this size
|| new_capacity == 0 // Don't allow empty buffers, results in 0 from recv
|| new_capacity < m_buffer_size) { // Don't shrink smaller than what we require
return;
}
// We're gonna change the buffer one way or another; update our capacity
m_buffer_capacity = new_capacity;
if (m_buffer_size == 0) {
// Nothing to copy; easy mode
::operator delete(m_buffer);
m_buffer = ::operator new(new_capacity);
return;
}
// Backup current buffer data
void* old_buffer = m_buffer;
// Create new buffer
m_buffer = ::operator new(new_capacity);
std::memcpy(m_buffer, old_buffer, m_buffer_size);
// Nuke the old buffer
::operator delete(m_buffer);
}
void Jupiter::Socket::Buffer::clear() {
m_buffer_size = 0;
}
std::string_view Jupiter::Socket::Buffer::view() const {
return { static_cast<char*>(m_buffer), m_buffer_size };
}
void* Jupiter::Socket::Buffer::data() const {
return m_buffer;
}
char* Jupiter::Socket::Buffer::chr_data() const {
return static_cast<char*>(m_buffer);
}
struct Jupiter::Socket::Data {
@ -71,7 +127,7 @@ struct Jupiter::Socket::Data {
};
Jupiter::Socket::Data::Data(size_t buffer_size) {
Jupiter::Socket::Data::buffer.setBufferSizeNoCopy(buffer_size);
Jupiter::Socket::Data::buffer.reserve(buffer_size);
}
Jupiter::Socket::Data::Data(const Data &source) {
@ -89,8 +145,8 @@ Jupiter::Socket::Data::Data(const Data &source) {
}
Jupiter::Socket &Jupiter::Socket::operator=(Jupiter::Socket &&source) {
Jupiter::Socket::data_ = source.data_;
source.data_ = nullptr;
m_data = source.m_data;
source.m_data = nullptr;
return *this;
}
@ -98,62 +154,62 @@ Jupiter::Socket::Socket() : Jupiter::Socket::Socket(512) {
}
Jupiter::Socket::Socket(size_t bufferSize) {
Jupiter::Socket::data_ = new Jupiter::Socket::Data(bufferSize);
m_data = new Jupiter::Socket::Data(bufferSize);
}
Jupiter::Socket::Socket(Jupiter::Socket &&source) {
Jupiter::Socket::data_ = source.data_;
source.data_ = nullptr;
m_data = source.m_data;
source.m_data = nullptr;
}
Jupiter::Socket::~Socket() {
if (Jupiter::Socket::data_ != nullptr) {
if (Jupiter::Socket::data_->rawSock > 0)
if (m_data != nullptr) {
if (m_data->rawSock > 0)
Jupiter::Socket::close();
delete Jupiter::Socket::data_;
delete m_data;
}
}
void Jupiter::Socket::setType(int type) {
Jupiter::Socket::data_->sockType = type;
m_data->sockType = type;
}
void Jupiter::Socket::setProtocol(int proto) {
Jupiter::Socket::data_->sockProto = proto;
m_data->sockProto = proto;
}
int Jupiter::Socket::getType() const {
return Jupiter::Socket::data_->sockType;
return m_data->sockType;
}
int Jupiter::Socket::getProtocol() const {
return Jupiter::Socket::data_->sockProto;
return m_data->sockProto;
}
bool Jupiter::Socket::connect(addrinfo *info) {
#if defined _WIN32
if (!socketInit && !Jupiter::Socket::init())
if (!socketInit && !Jupiter::Socket::init()) {
return false;
}
#endif // _WIN32
Jupiter::Socket::data_->rawSock = socket(info->ai_family, Jupiter::Socket::data_->sockType, Jupiter::Socket::data_->sockProto);
m_data->rawSock = socket(info->ai_family, m_data->sockType, m_data->sockProto);
if (Jupiter::Socket::data_->rawSock == INVALID_SOCKET
|| (Jupiter::Socket::data_->sockType != SOCK_RAW && Jupiter::Socket::data_->sockProto != IPPROTO_RAW && ::connect(Jupiter::Socket::data_->rawSock, info->ai_addr, info->ai_addrlen) == SOCKET_ERROR))
if (m_data->rawSock == INVALID_SOCKET
|| (m_data->sockType != SOCK_RAW && m_data->sockProto != IPPROTO_RAW && ::connect(m_data->rawSock, info->ai_addr, info->ai_addrlen) == SOCKET_ERROR))
return false;
return true;
}
bool Jupiter::Socket::connect(const char *hostname, unsigned short iPort, const char *clientAddress, unsigned short clientPort)
{
bool Jupiter::Socket::connect(const char *hostname, unsigned short iPort, const char *clientAddress, unsigned short clientPort) {
#if defined _WIN32
if (!socketInit && !Jupiter::Socket::init())
return false;
#endif // _WIN32
Jupiter::Socket::data_->remote_host = hostname;
Jupiter::Socket::data_->remote_port = iPort;
addrinfo *info_head = Jupiter::Socket::getAddrInfo(Jupiter::Socket::data_->remote_host.c_str(), std::to_string(Jupiter::Socket::data_->remote_port).c_str());
m_data->remote_host = hostname;
m_data->remote_port = iPort;
addrinfo *info_head = Jupiter::Socket::getAddrInfo(m_data->remote_host.c_str(), std::to_string(m_data->remote_port).c_str());
if (info_head != nullptr) {
addrinfo *info = info_head;
do {
@ -163,21 +219,20 @@ bool Jupiter::Socket::connect(const char *hostname, unsigned short iPort, const
break;
}
else {
Jupiter::Socket::data_->rawSock = socket(info->ai_family, Jupiter::Socket::data_->sockType, Jupiter::Socket::data_->sockProto);
if (Jupiter::Socket::data_->rawSock == INVALID_SOCKET) {
m_data->rawSock = socket(info->ai_family, m_data->sockType, m_data->sockProto);
if (m_data->rawSock == INVALID_SOCKET) {
info = info->ai_next;
continue;
}
}
if (::connect(Jupiter::Socket::data_->rawSock, info->ai_addr, info->ai_addrlen) == SOCKET_ERROR)
{
if (::connect(m_data->rawSock, info->ai_addr, info->ai_addrlen) == SOCKET_ERROR) {
#if defined _WIN32
::closesocket(Jupiter::Socket::data_->rawSock);
::closesocket(m_data->rawSock);
#else // _WIN32
::close(Jupiter::Socket::data_->rawSock);
::close(m_data->rawSock);
#endif // WIN32
Jupiter::Socket::data_->rawSock = INVALID_SOCKET;
m_data->rawSock = INVALID_SOCKET;
info = info->ai_next;
continue;
}
@ -190,38 +245,40 @@ bool Jupiter::Socket::connect(const char *hostname, unsigned short iPort, const
return false;
}
bool Jupiter::Socket::bind(const char *hostname, unsigned short iPort, bool andListen)
{
bool Jupiter::Socket::bind(const char *hostname, unsigned short iPort, bool andListen) {
#if defined _WIN32
if (!socketInit && !Jupiter::Socket::init())
if (!socketInit && !Jupiter::Socket::init()) {
return false;
}
#endif // _WIN32
Jupiter::Socket::data_->bound_host = hostname;
Jupiter::Socket::data_->bound_port = iPort;
addrinfo *info_head = Jupiter::Socket::getAddrInfo(Jupiter::Socket::data_->bound_host.c_str(), std::to_string(Jupiter::Socket::data_->bound_port).c_str());
m_data->bound_host = hostname;
m_data->bound_port = iPort;
addrinfo *info_head = Jupiter::Socket::getAddrInfo(m_data->bound_host.c_str(), std::to_string(m_data->bound_port).c_str());
if (info_head != nullptr) {
addrinfo *info = info_head;
do {
Jupiter::Socket::data_->rawSock = socket(info->ai_family, Jupiter::Socket::data_->sockType, Jupiter::Socket::data_->sockProto);
if (Jupiter::Socket::data_->rawSock == INVALID_SOCKET) {
m_data->rawSock = socket(info->ai_family, m_data->sockType, m_data->sockProto);
if (m_data->rawSock == INVALID_SOCKET) {
info = info->ai_next;
continue;
}
if (::bind(Jupiter::Socket::data_->rawSock, info->ai_addr, info->ai_addrlen) == SOCKET_ERROR) {
if (::bind(m_data->rawSock, info->ai_addr, info->ai_addrlen) == SOCKET_ERROR) {
#if defined _WIN32
::closesocket(Jupiter::Socket::data_->rawSock);
::closesocket(m_data->rawSock);
#else // _WIN32
::close(Jupiter::Socket::data_->rawSock);
::close(m_data->rawSock);
#endif // WIN32
Jupiter::Socket::data_->rawSock = INVALID_SOCKET;
m_data->rawSock = INVALID_SOCKET;
info = info->ai_next;
continue;
}
Jupiter::Socket::freeAddrInfo(info_head);
if (andListen && Jupiter::Socket::data_->sockType == SOCK_STREAM && ::listen(Jupiter::Socket::data_->rawSock, SOMAXCONN) == SOCKET_ERROR)
if (andListen && m_data->sockType == SOCK_STREAM && ::listen(m_data->rawSock, SOMAXCONN) == SOCKET_ERROR) {
return false;
}
return true;
} while (info != nullptr);
Jupiter::Socket::freeAddrInfo(info_head);
@ -230,39 +287,32 @@ bool Jupiter::Socket::bind(const char *hostname, unsigned short iPort, bool andL
}
void Jupiter::Socket::shutdown() {
if (Jupiter::Socket::data_ != nullptr) {
::shutdown(Jupiter::Socket::data_->rawSock, 2);
Jupiter::Socket::data_->is_shutdown = true;
if (m_data != nullptr) {
::shutdown(m_data->rawSock, 2);
m_data->is_shutdown = true;
}
}
void Jupiter::Socket::close() {
if (Jupiter::Socket::data_ != nullptr) {
if (Jupiter::Socket::data_->is_shutdown == false)
if (m_data != nullptr) {
if (m_data->is_shutdown == false)
this->shutdown();
#if defined _WIN32
::closesocket(Jupiter::Socket::data_->rawSock);
::closesocket(m_data->rawSock);
#else // _WIN32
::close(Jupiter::Socket::data_->rawSock);
::close(m_data->rawSock);
#endif // _WIN32
Jupiter::Socket::data_->rawSock = 0;
m_data->rawSock = 0;
}
}
bool Jupiter::Socket::isShutdown() const {
return Jupiter::Socket::data_->is_shutdown;
}
addrinfo *Jupiter::Socket::getAddrInfo(const char *hostname, const char *port) { // static
addrinfo *ptr;
if (getaddrinfo(hostname, port, nullptr, &ptr)) return nullptr;
return ptr;
return m_data->is_shutdown;
}
addrinfo *Jupiter::Socket::getStaticAddrInfo(const char *hostname, const char *port) { // static
static addrinfo *ptr = nullptr;
if (ptr != nullptr) freeaddrinfo(ptr);
ptr = Jupiter::Socket::getAddrInfo(hostname, port);
addrinfo* Jupiter::Socket::getAddrInfo(const char *hostname, const char *port) { // static
addrinfo *ptr{};
getaddrinfo(hostname, port, nullptr, &ptr);
return ptr;
}
@ -271,63 +321,61 @@ void Jupiter::Socket::freeAddrInfo(addrinfo *info) { // static
}
addrinfo *Jupiter::Socket::getAddrInfo(addrinfo *addr, unsigned int result) { // static
addrinfo *ptr = addr;
for (unsigned int i = 0; i != result && ptr != nullptr; i++) ptr = ptr->ai_next;
addrinfo* ptr = addr;
while (ptr != nullptr && result != 0) {
ptr = ptr->ai_next;
--result;
}
return ptr;
}
char *Jupiter::Socket::resolveAddress(const addrinfo *addr) { // static
static char resolved[NI_MAXHOST];
std::string Jupiter::Socket::resolveAddress(const addrinfo *addr) { // static
char resolved[NI_MAXHOST];
getnameinfo(addr->ai_addr, addr->ai_addrlen, resolved, NI_MAXHOST, 0, 0, NI_NUMERICHOST);
return resolved;
}
char *Jupiter::Socket::resolveAddress(addrinfo *addr, unsigned int result) { // static
std::string Jupiter::Socket::resolveAddress(addrinfo *addr, unsigned int result) { // static
addrinfo *ptr = Jupiter::Socket::getAddrInfo(addr, result);
if (ptr == nullptr) return nullptr;
if (ptr == nullptr) {
return {};
}
return Jupiter::Socket::resolveAddress(ptr);
}
char *Jupiter::Socket::resolveAddress(const char *hostname, unsigned int result) { // static
std::string Jupiter::Socket::resolveAddress(const char *hostname, unsigned int result) { // static
addrinfo *info = Jupiter::Socket::getAddrInfo(hostname, 0);
if (info == nullptr) return nullptr;
if (info == nullptr) {
return {};
};
return Jupiter::Socket::resolveAddress(info, result);
}
char *Jupiter::Socket::resolveHostname(addrinfo *addr) { // static
static char resolved[NI_MAXHOST];
std::string Jupiter::Socket::resolveHostname(addrinfo *addr) { // static
char resolved[NI_MAXHOST];
getnameinfo(addr->ai_addr, addr->ai_addrlen, resolved, sizeof(resolved), 0, 0, 0);
return resolved;
}
char *Jupiter::Socket::resolveHostname_alloc(addrinfo *addr) { // static
char *resolved = new char[NI_MAXHOST];
getnameinfo(addr->ai_addr, addr->ai_addrlen, resolved, NI_MAXHOST, 0, 0, 0);
return resolved;
}
char *Jupiter::Socket::resolveHostname(addrinfo *addr, unsigned int result) { // static
std::string Jupiter::Socket::resolveHostname(addrinfo *addr, unsigned int result) { // static
addrinfo *ptr = Jupiter::Socket::getAddrInfo(addr, result);
if (ptr == nullptr) return nullptr;
return Jupiter::Socket::resolveHostname(ptr);
}
if (ptr == nullptr) {
return {};
}
char *Jupiter::Socket::resolveHostname_alloc(addrinfo *addr, unsigned int result) { // static
addrinfo *ptr = Jupiter::Socket::getAddrInfo(addr, result);
if (ptr == nullptr) return nullptr;
return Jupiter::Socket::resolveHostname_alloc(ptr);
return Jupiter::Socket::resolveHostname(ptr);
}
char *Jupiter::Socket::resolveHostname(const char *hostname, unsigned int result) { // static
std::string Jupiter::Socket::resolveHostname(const char *hostname, unsigned int result) { // static
addrinfo *info = Jupiter::Socket::getAddrInfo(hostname, 0);
if (info == nullptr) return nullptr;
return Jupiter::Socket::resolveHostname(info, result);
}
if (info == nullptr) {
return {};
}
char *Jupiter::Socket::resolveHostname_alloc(const char *hostname, unsigned int result) { // static
addrinfo *info = Jupiter::Socket::getAddrInfo(hostname, 0);
if (info == nullptr) return nullptr;
return Jupiter::Socket::resolveHostname_alloc(info, result);
return Jupiter::Socket::resolveHostname(info, result);
}
uint32_t Jupiter::Socket::pton4(const char *str) {
@ -371,44 +419,44 @@ Jupiter::StringS Jupiter::Socket::ntop(void *ip, size_t size) {
}
}
Jupiter::Socket *Jupiter::Socket::accept() {
Jupiter::Socket* Jupiter::Socket::accept() {
sockaddr addr;
socklen_t size = sizeof(addr);
SocketType tSock = ::accept(Socket::data_->rawSock, &addr, &size);
SocketType tSock = ::accept(m_data->rawSock, &addr, &size);
if (tSock != INVALID_SOCKET) {
char resolved[NI_MAXHOST];
char resolved_port[NI_MAXSERV];
getnameinfo(&addr, size, resolved, sizeof(resolved), resolved_port, sizeof(resolved_port), NI_NUMERICHOST | NI_NUMERICSERV);
Socket *r = new Socket(Jupiter::Socket::data_->buffer.capacity());
r->data_->rawSock = tSock;
r->data_->sockType = Jupiter::Socket::data_->sockType;
r->data_->sockProto = Jupiter::Socket::data_->sockProto;
r->data_->remote_host = resolved;
r->data_->remote_port = static_cast<unsigned short>(Jupiter_strtoi(resolved_port, 10));
return r;
Socket *result = new Socket(m_data->buffer.capacity());
result->m_data->rawSock = tSock;
result->m_data->sockType = m_data->sockType;
result->m_data->sockProto = m_data->sockProto;
result->m_data->remote_host = resolved;
result->m_data->remote_port = static_cast<unsigned short>(Jupiter_strtoi(resolved_port, 10));
return result;
}
return nullptr;
}
bool Jupiter::Socket::setReadTimeout(unsigned long milliseconds) {
#if defined _WIN32
return setsockopt(Jupiter::Socket::data_->rawSock, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<const char *>(&milliseconds), sizeof(milliseconds)) == 0;
return setsockopt(m_data->rawSock, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<const char *>(&milliseconds), sizeof(milliseconds)) == 0;
#else // _WIN32
timeval time;
time.tv_sec = milliseconds / 1000;
time.tv_usec = (milliseconds % 1000) * 1000;
return setsockopt(Jupiter::Socket::data_->rawSock, SOL_SOCKET, SO_RCVTIMEO, (const void *) &time, sizeof(time)) == 0;
return setsockopt(m_data->rawSock, SOL_SOCKET, SO_RCVTIMEO, (const void *) &time, sizeof(time)) == 0;
#endif // _WIN32
}
bool Jupiter::Socket::setSendTimeout(unsigned long milliseconds) {
#if defined _WIN32
return setsockopt(Jupiter::Socket::data_->rawSock, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<const char *>(&milliseconds), sizeof(milliseconds)) == 0;
return setsockopt(m_data->rawSock, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<const char *>(&milliseconds), sizeof(milliseconds)) == 0;
#else // _WIN32
timeval time;
time.tv_sec = milliseconds / 1000;
time.tv_usec = (milliseconds % 1000) * 1000;
return setsockopt(Jupiter::Socket::data_->rawSock, SOL_SOCKET, SO_SNDTIMEO, (const void *) &time, sizeof(time)) == 0;
return setsockopt(m_data->rawSock, SOL_SOCKET, SO_SNDTIMEO, (const void *) &time, sizeof(time)) == 0;
#endif // _WIN32
}
@ -419,10 +467,10 @@ bool Jupiter::Socket::setTimeout(unsigned long milliseconds) {
bool Jupiter::Socket::setBlocking(bool mode) {
#if defined _WIN32
Jupiter::Socket::data_->blockMode = !mode;
return ioctlsocket(Jupiter::Socket::data_->rawSock, FIONBIO, &Jupiter::Socket::data_->blockMode) == 0;
m_data->blockMode = !mode;
return ioctlsocket(m_data->rawSock, FIONBIO, &m_data->blockMode) == 0;
#else // _WIN32
int flags = fcntl(Jupiter::Socket::data_->rawSock, F_GETFL, 0);
int flags = fcntl(m_data->rawSock, F_GETFL, 0);
if (flags < 0) return 0;
if (mode) {
flags &= ~O_NONBLOCK;
@ -430,61 +478,62 @@ bool Jupiter::Socket::setBlocking(bool mode) {
else {
flags |= O_NONBLOCK;
}
return fcntl(Jupiter::Socket::data_->rawSock, F_SETFL, flags) == 0;
return fcntl(m_data->rawSock, F_SETFL, flags) == 0;
#endif // _WIN32
}
bool Jupiter::Socket::getBlockingMode() const {
#if defined _WIN32
return !Jupiter::Socket::data_->blockMode;
return !m_data->blockMode;
#else // _WIN32
int flags = fcntl(data_->rawSock, F_GETFL, 0);
int flags = fcntl(m_data->rawSock, F_GETFL, 0);
if (flags == -1) return false;
return !(flags & O_NONBLOCK);
#endif
}
const std::string &Jupiter::Socket::getRemoteHostname() const {
return Jupiter::Socket::data_->remote_host;
return m_data->remote_host;
}
const char *Jupiter::Socket::getRemoteHostnameC() const {
return Jupiter::Socket::data_->remote_host.c_str();
return m_data->remote_host.c_str();
}
const std::string &Jupiter::Socket::getBoundHostname() const {
return Jupiter::Socket::data_->bound_host;
return m_data->bound_host;
}
const char *Jupiter::Socket::getBoundHostnameC() const {
return Jupiter::Socket::data_->bound_host.c_str();
return m_data->bound_host.c_str();
}
unsigned short Jupiter::Socket::getRemotePort() const {
return Jupiter::Socket::data_->remote_port;
return m_data->remote_port;
}
unsigned short Jupiter::Socket::getBoundPort() const {
return Jupiter::Socket::data_->bound_port;
return m_data->bound_port;
}
std::string_view Jupiter::Socket::getBuffer() const {
return Jupiter::Socket::data_->buffer;
return m_data->buffer.view();
}
size_t Jupiter::Socket::getBufferSize() const {
return Jupiter::Socket::data_->buffer.capacity();
return m_data->buffer.capacity();
}
std::string_view Jupiter::Socket::setBufferSize(size_t size) {
Jupiter::Socket::data_->buffer.setBufferSize(size);
return Jupiter::Socket::data_->buffer;
m_data->buffer.reserve(size);
return m_data->buffer.view();
}
std::string_view Jupiter::Socket::getData() {
if (this->recv() <= 0)
Jupiter::Socket::data_->buffer.erase();
return Jupiter::Socket::data_->buffer;
if (this->recv() <= 0) {
m_data->buffer.clear();
}
return m_data->buffer.view();
}
const char *Jupiter::Socket::getLocalHostname() { // static
@ -494,11 +543,11 @@ const char *Jupiter::Socket::getLocalHostname() { // static
}
void Jupiter::Socket::clearBuffer() {
Jupiter::Socket::data_->buffer.erase();
m_data->buffer.clear();
}
int Jupiter::Socket::send(const char *data, size_t datalen) {
return ::send(Jupiter::Socket::data_->rawSock, data, datalen, 0);
return ::send(m_data->rawSock, data, datalen, 0);
}
int Jupiter::Socket::send(std::string_view str) {
@ -510,32 +559,32 @@ int Jupiter::Socket::send(const char *msg) {
}
int Jupiter::Socket::sendTo(const addrinfo *info, const char *data, size_t datalen) {
return sendto(Jupiter::Socket::data_->rawSock, data, datalen, 0, info->ai_addr, info->ai_addrlen);
return sendto(m_data->rawSock, data, datalen, 0, info->ai_addr, info->ai_addrlen);
}
int Jupiter::Socket::sendTo(const addrinfo *info, const char *msg) {
return sendto(Jupiter::Socket::data_->rawSock, msg, strlen(msg), 0, info->ai_addr, info->ai_addrlen);
return sendto(m_data->rawSock, msg, strlen(msg), 0, info->ai_addr, info->ai_addrlen);
}
int Jupiter::Socket::peek() {
Jupiter::Socket::data_->buffer.erase();
int r = ::recv(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), MSG_PEEK);
m_data->buffer.clear();
int r = ::recv(m_data->rawSock, m_data->buffer.chr_data(), m_data->buffer.capacity(), MSG_PEEK);
if (r > 0)
Jupiter::Socket::data_->buffer.set_length(r);
m_data->buffer.set_length(r);
return r;
}
int Jupiter::Socket::peekFrom(addrinfo *info) {
Jupiter::Socket::data_->buffer.erase();
m_data->buffer.clear();
if (info == nullptr)
return recvfrom(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), MSG_PEEK, nullptr, nullptr);
return recvfrom(m_data->rawSock, m_data->buffer.chr_data(), m_data->buffer.capacity(), MSG_PEEK, nullptr, nullptr);
socklen_t len = info->ai_addrlen;
if (len <= 0) {
info->ai_addr = new sockaddr();
len = sizeof(sockaddr);
}
int r = recvfrom(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), MSG_PEEK, info->ai_addr, &len);
int r = recvfrom(m_data->rawSock, m_data->buffer.chr_data(), m_data->buffer.capacity(), MSG_PEEK, info->ai_addr, &len);
if (r >= 0) {
info->ai_addrlen = len;
info->ai_family = info->ai_addr->sa_family;
@ -546,24 +595,26 @@ int Jupiter::Socket::peekFrom(addrinfo *info) {
}
int Jupiter::Socket::recv() {
Jupiter::Socket::data_->buffer.erase();
int r = ::recv(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), 0);
if (r > 0)
Jupiter::Socket::data_->buffer.set_length(r);
m_data->buffer.clear();
int r = ::recv(m_data->rawSock, m_data->buffer.chr_data(), m_data->buffer.capacity(), 0);
if (r > 0) {
m_data->buffer.set_length(r);
}
return r;
}
int Jupiter::Socket::recvFrom(addrinfo *info) {
Jupiter::Socket::data_->buffer.erase();
if (info == nullptr)
return recvfrom(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), 0, nullptr, nullptr);
int Jupiter::Socket::recvFrom(addrinfo* info) {
m_data->buffer.clear();
if (info == nullptr) {
return recvfrom(m_data->rawSock, m_data->buffer.chr_data(), m_data->buffer.capacity(), 0, nullptr, nullptr);
}
socklen_t len = info->ai_addrlen;
if (len <= 0) {
info->ai_addr = new sockaddr();
len = sizeof(sockaddr);
}
int r = recvfrom(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), 0, info->ai_addr, &len);
int r = recvfrom(m_data->rawSock, m_data->buffer.chr_data(), m_data->buffer.capacity(), 0, info->ai_addr, &len);
if (r >= 0) {
info->ai_addrlen = len;
info->ai_family = info->ai_addr->sa_family;
@ -608,15 +659,15 @@ bool Jupiter::Socket::cleanup() { // static
}
Jupiter::Socket::SocketType Jupiter::Socket::getDescriptor() const {
return Jupiter::Socket::data_->rawSock;
return m_data->rawSock;
}
void Jupiter::Socket::setDescriptor(SocketType descriptor) {
Jupiter::Socket::data_->rawSock = descriptor;
m_data->rawSock = descriptor;
}
Jupiter::Socket::Buffer &Jupiter::Socket::getInternalBuffer() const {
return Jupiter::Socket::data_->buffer;
return m_data->buffer;
}
/** Re-enable warnings */

29
src/include/Jupiter/SecureSocket.h

@ -39,39 +39,12 @@ namespace Jupiter
{
public:
/**
* @brief Enumerator translating to various SSL/TLS protocols.
* Used in getMethod() and setMethod().
*/
enum EncryptionMethod
{
//SSL3 = 1, /** SSL 3.0 - Unrecommended */
TLS1 = 2, /** TLS 1.0 - Unrecommended */
TLS1_1 = 3, /** TLS 1.1 */
TLS1_2 = 4, /** TLS 1.2 */
DTLS1 = 5, /** DTLS 1.0 */
ANY = 126, /** Attempt to use any of the above encryption methods (generally the most secure available between both client and server) */
END = 127 /** END OF ENUM */
};
/**
* @brief Returns the name of the cipher currently in use.
* @return Name of cipher currently in use, or "NONE" if none is in use.
*/
const char *getCipherName() const;
/**
* @brief Returns the encryption method that the socket attempts to use.
* This is ANY by default.
* @return Encrpytion method that the socket attempts to use.
*/
EncryptionMethod getMethod() const;
/**
* @brief Sets the encryption method to be used when connecting.
*/
void setMethod(EncryptionMethod method);
/**
* @brief Loads a certificate and key for use.
*
@ -207,7 +180,7 @@ namespace Jupiter
/** Private members */
private:
struct SSLData;
SSLData *SSLdata_;
SSLData *m_ssl_data;
};
}

48
src/include/Jupiter/Socket.h

@ -76,18 +76,7 @@ namespace Jupiter
* @param port String containing the target port.
* @return Pointer to a NULL-terminated linked list of addrinfo on success, nullptr otherwise.
*/
static addrinfo *getAddrInfo(const char *hostname, const char *port);
/**
* @brief Resolves and stores address information in an addrinfo struct.
* Unlike the function getAddrInfo, this function stores the returned addrinfo
* as static, meaning that any subsequent calls will overwrite the previous call.
*
* @param host String containing the hostname of the target.
* @param port String containing the target port.
* @return Pointer to a NULL-terminated linked list of addrinfo on success, nullptr otherwise.
*/
static addrinfo *getStaticAddrInfo(const char *hostname, const char *port);
static addrinfo* getAddrInfo(const char *hostname, const char *port);
/**
* @brief Frees the resources associated with an addrinfo struct.
@ -112,7 +101,7 @@ namespace Jupiter
* @param addr Address info containing IP address.
* @return String containing the text representation of the stored address on success, nullptr otherwise.
*/
static char *resolveAddress(const addrinfo *addr);
static std::string resolveAddress(const addrinfo *addr);
/**
* @brief Returns the text representation of an addrinfo's stored address.
@ -121,7 +110,7 @@ namespace Jupiter
* @param result Which result to return.
* @return String containing the text representation of the stored address on success, nullptr otherwise.
*/
static char *resolveAddress(addrinfo *addr, unsigned int result);
static std::string resolveAddress(addrinfo *addr, unsigned int result);
/**
* @brief Resolves a hostname to an IP address.
@ -130,7 +119,7 @@ namespace Jupiter
* @param result Which resolution result to return.
* @return String containing the text representation of the resolved address on success, nullptr otherwise.
*/
static char *resolveAddress(const char *hostname, unsigned int result);
static std::string resolveAddress(const char *hostname, unsigned int result);
/**
* @brief Resolves an address to a hostname. (Reverse DNS)
@ -139,8 +128,7 @@ namespace Jupiter
* @param addr Address info containing IP address.
* @return String containing the hostname of the stored address on success, nullptr otherwise.
*/
static char *resolveHostname(addrinfo *addr);
static char *resolveHostname_alloc(addrinfo *addr);
static std::string resolveHostname(addrinfo *addr);
/**
* @brief Resolves an address to a hostname. (Reverse DNS)
@ -149,8 +137,7 @@ namespace Jupiter
* @param result Which result to return.
* @return String containing the hostname of the stored address on success, nullptr otherwise.
*/
static char *resolveHostname(addrinfo *addr, unsigned int result);
static char *resolveHostname_alloc(addrinfo *addr, unsigned int result);
static std::string resolveHostname(addrinfo *addr, unsigned int result);
/**
* @brief Resolves an address to a hostname. (Reverse DNS)
@ -159,8 +146,7 @@ namespace Jupiter
* @param result Which resolution result to return.
* @return String containing the hostname of the resolved address on success, nullptr otherwise.
*/
static char *resolveHostname(const char *hostname, unsigned int result);
static char *resolveHostname_alloc(const char *hostname, unsigned int result);
static std::string resolveHostname(const char *hostname, unsigned int result);
/**
* @brief Reinterprets an IPv4 address as a 32-bit integer in network byte order.
@ -415,7 +401,7 @@ namespace Jupiter
* @return Number of bytes written to buffer on success, SOCKET_ERROR (-1) otherwise.
* Note: Any returned value less than or equal to 0 should be treated as an error.
*/
virtual int recvFrom(addrinfo *info);
virtual int recvFrom(addrinfo* info);
int receive(); /** @see recv() */
@ -544,11 +530,23 @@ namespace Jupiter
/**
* @brief An extended verison of the string class, which allows for low-level length and string modification.
*/
class Buffer : public Jupiter::StringL
class Buffer
{
public:
Buffer();
~Buffer();
void set_length(size_t in_length);
char *get_str() const;
size_t capacity() const;
void reserve(size_t new_capacity);
void clear();
std::string_view view() const;
void* data() const;
char* chr_data() const;
private:
void* m_buffer;
size_t m_buffer_capacity;
size_t m_buffer_size;
};
/**
@ -575,7 +573,7 @@ namespace Jupiter
/** Private members */
private:
struct Data;
Data *data_;
Data *m_data;
};
}

2
src/jessilib

@ -1 +1 @@
Subproject commit f714a1da00dfd9f1f6ef9a8350099318ddd4734e
Subproject commit 25198a3c77c45c1713b3e6befd3b945ee981d5a9
Loading…
Cancel
Save