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. 214
      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(); return m_channels.size();
} }
int Jupiter::IRC::Client::process_line(std::string_view in_line) { int Jupiter::IRC::Client::process_line(std::string_view line) {
Jupiter::ReferenceString line{in_line}; // TODO: remove this if (!line.empty()) {
if (!line.empty())
{
Jupiter::IRC::Client::writeToLogs(line); Jupiter::IRC::Client::writeToLogs(line);
if (m_output != nullptr) { if (m_output != nullptr) {
// TODO: use ostream instead // 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); fputs("\r\n", m_output);
} }
@ -1116,8 +1114,7 @@ int Jupiter::IRC::Client::process_line(std::string_view in_line) {
return 0; return 0;
} }
bool Jupiter::IRC::Client::connect() bool Jupiter::IRC::Client::connect() {
{
std::string_view clientAddress = Jupiter::IRC::Client::readConfigValue("ClientAddress"_jrs); 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) 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; return false;
@ -1181,15 +1178,12 @@ void Jupiter::IRC::Client::reconnect()
} }
} }
int Jupiter::IRC::Client::think() int Jupiter::IRC::Client::think() {
{ auto handle_error = [this](int error_code) {
auto handle_error = [this](int error_code)
{
if (this->m_dead == true) if (this->m_dead == true)
return error_code; 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)) if (!this->m_reconnect_delay || this->m_reconnect_time < time(0))
this->reconnect(); this->reconnect();
@ -1203,8 +1197,7 @@ int Jupiter::IRC::Client::think()
return handle_error(-1); return handle_error(-1);
int tmp = m_socket->recv(); int tmp = m_socket->recv();
if (tmp > 0) if (tmp > 0) {
{
// Process incoming data // Process incoming data
using namespace std::literals; using namespace std::literals;
auto tokens = jessilib::split_view(m_socket->getBuffer(), "\r\n"sv); auto tokens = jessilib::split_view(m_socket->getBuffer(), "\r\n"sv);

214
src/common/SecureSocket.cpp

@ -21,66 +21,61 @@
#include <openssl/err.h> // OpenSSL SSL errors #include <openssl/err.h> // OpenSSL SSL errors
#include "SecureSocket.h" #include "SecureSocket.h"
struct Jupiter::SecureSocket::SSLData struct Jupiter::SecureSocket::SSLData {
{ SSL* handle = nullptr;
SSL *handle = nullptr; SSL_CTX* context = nullptr;
SSL_CTX *context = nullptr; const SSL_METHOD* method = nullptr;
const SSL_METHOD *method = nullptr;
Jupiter::SecureSocket::EncryptionMethod eMethod = ANY;
std::string cert; std::string cert;
std::string key; std::string key;
~SSLData(); ~SSLData();
}; };
Jupiter::SecureSocket::SSLData::~SSLData() Jupiter::SecureSocket::SSLData::~SSLData() {
{ if (Jupiter::SecureSocket::SSLData::handle != nullptr) {
if (Jupiter::SecureSocket::SSLData::handle != nullptr) if (SSL_shutdown(Jupiter::SecureSocket::SSLData::handle) == 0) {
{ SSL_shutdown(Jupiter::SecureSocket::SSLData::handle);
if (SSL_shutdown(Jupiter::SecureSocket::SSLData::handle) == 0) SSL_shutdown(Jupiter::SecureSocket::SSLData::handle); }
SSL_free(Jupiter::SecureSocket::SSLData::handle); SSL_free(Jupiter::SecureSocket::SSLData::handle);
} }
if (Jupiter::SecureSocket::SSLData::context != nullptr) SSL_CTX_free(Jupiter::SecureSocket::SSLData::context); 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::Socket::operator=(std::move(source));
Jupiter::SecureSocket::SSLdata_ = source.SSLdata_; m_ssl_data = source.m_ssl_data;
source.SSLdata_ = nullptr; source.m_ssl_data = nullptr;
return *this; return *this;
} }
Jupiter::SecureSocket::SecureSocket() : Jupiter::Socket() Jupiter::SecureSocket::SecureSocket() : Jupiter::Socket() {
{ m_ssl_data = new Jupiter::SecureSocket::SSLData();
Jupiter::SecureSocket::SSLdata_ = new Jupiter::SecureSocket::SSLData();
} }
Jupiter::SecureSocket::SecureSocket(size_t bufferSize) : Jupiter::Socket(bufferSize) Jupiter::SecureSocket::SecureSocket(size_t bufferSize)
{ : Jupiter::Socket(bufferSize) {
Jupiter::SecureSocket::SSLdata_ = new Jupiter::SecureSocket::SSLData(); m_ssl_data = new Jupiter::SecureSocket::SSLData();
} }
Jupiter::SecureSocket::SecureSocket(Jupiter::Socket &&source) : Jupiter::Socket(std::move(source)) Jupiter::SecureSocket::SecureSocket(Jupiter::Socket &&source)
{ : Jupiter::Socket(std::move(source)) {
Jupiter::SecureSocket::SSLdata_ = new Jupiter::SecureSocket::SSLData(); m_ssl_data = new Jupiter::SecureSocket::SSLData();
} }
Jupiter::SecureSocket::SecureSocket(Jupiter::SecureSocket &&source) : Jupiter::Socket(std::move(source)) Jupiter::SecureSocket::SecureSocket(Jupiter::SecureSocket &&source)
{ : Jupiter::Socket(std::move(source)) {
Jupiter::SecureSocket::SSLdata_ = source.SSLdata_; m_ssl_data = source.m_ssl_data;
source.SSLdata_ = nullptr; source.m_ssl_data = nullptr;
} }
Jupiter::SecureSocket::~SecureSocket() Jupiter::SecureSocket::~SecureSocket() {
{ if (m_ssl_data != nullptr) {
if (Jupiter::SecureSocket::SSLdata_ != nullptr) delete Jupiter::SecureSocket::SSLdata_; delete m_ssl_data;
}
} }
Jupiter::SecureSocket *Jupiter::SecureSocket::accept() Jupiter::SecureSocket *Jupiter::SecureSocket::accept() {
{ SocketType tSock = SSL_accept(m_ssl_data->handle);
SocketType tSock = SSL_accept(Jupiter::SecureSocket::SSLdata_->handle); if (tSock > 0) {
if (tSock > 0)
{
SecureSocket *r = new SecureSocket(Jupiter::SecureSocket::getBufferSize()); SecureSocket *r = new SecureSocket(Jupiter::SecureSocket::getBufferSize());
r->setDescriptor(tSock); r->setDescriptor(tSock);
r->setType(this->getType()); r->setType(this->getType());
@ -90,86 +85,46 @@ Jupiter::SecureSocket *Jupiter::SecureSocket::accept()
return nullptr; 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); return Jupiter::Socket::bind(hostname, iPort, andListen);
} }
void Jupiter::SecureSocket::shutdown() void Jupiter::SecureSocket::shutdown() {
{
Jupiter::Socket::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) if (SSL_shutdown(m_ssl_data->handle) == 0) {
SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle); SSL_shutdown(m_ssl_data->handle);
}
} }
} }
void Jupiter::SecureSocket::close() void Jupiter::SecureSocket::close() {
{
Jupiter::Socket::close(); Jupiter::Socket::close();
if (Jupiter::SecureSocket::SSLdata_ != nullptr && Jupiter::SecureSocket::SSLdata_->handle != nullptr) if (m_ssl_data != nullptr && m_ssl_data->handle != nullptr) {
{ if (SSL_shutdown(m_ssl_data->handle) == 0) {
if (SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle) == 0) SSL_shutdown(m_ssl_data->handle);
SSL_shutdown(Jupiter::SecureSocket::SSLdata_->handle);
SSL_free(Jupiter::SecureSocket::SSLdata_->handle);
Jupiter::SecureSocket::SSLdata_->handle = nullptr;
} }
} SSL_free(m_ssl_data->handle);
m_ssl_data->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;
} }
} }
const char *Jupiter::SecureSocket::getCipherName() const const char *Jupiter::SecureSocket::getCipherName() const {
{ return SSL_CIPHER_get_name(SSL_get_current_cipher(m_ssl_data->handle));
return SSL_CIPHER_get_name(SSL_get_current_cipher(Jupiter::SecureSocket::SSLdata_->handle));
}
Jupiter::SecureSocket::EncryptionMethod Jupiter::SecureSocket::getMethod() const
{
return Jupiter::SecureSocket::SSLdata_->eMethod;
} }
void Jupiter::SecureSocket::setMethod(Jupiter::SecureSocket::EncryptionMethod method) bool loadCertificate(SSL_CTX *context, const char *cert, const char *key) {
{
Jupiter::SecureSocket::SSLdata_->eMethod = method;
}
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_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_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); ERR_print_errors_fp(stderr);
return false; 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); ERR_print_errors_fp(stderr);
return false; return false;
} }
@ -178,95 +133,84 @@ bool loadCertificate(SSL_CTX *context, const char *cert, const char *key)
return true; return true;
} }
void Jupiter::SecureSocket::setCertificate(std::string cert, std::string key) void Jupiter::SecureSocket::setCertificate(std::string cert, std::string key) {
{ m_ssl_data->cert = std::move(cert);
Jupiter::SecureSocket::SSLdata_->cert = std::move(cert); m_ssl_data->key = std::move(key);
Jupiter::SecureSocket::SSLdata_->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)); 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(); return Jupiter::Socket::connect(hostname, iPort, clientAddress, clientPort) && this->initSSL();
} }
int Jupiter::SecureSocket::peek() int Jupiter::SecureSocket::peek() {
{ if (m_ssl_data->handle == nullptr)
if (Jupiter::SecureSocket::SSLdata_->handle == nullptr)
return -1; return -1;
Jupiter::Socket::Buffer &buffer = this->getInternalBuffer(); Jupiter::Socket::Buffer &buffer = this->getInternalBuffer();
buffer.erase(); buffer.clear();
int r = SSL_peek(Jupiter::SecureSocket::SSLdata_->handle, buffer.get_str(), static_cast<int>(this->getBufferSize())); int r = SSL_peek(m_ssl_data->handle, buffer.data(), static_cast<int>(this->getBufferSize()));
if (r > 0) if (r > 0)
buffer.set_length(r); buffer.set_length(r);
return r; return r;
} }
int Jupiter::SecureSocket::recv() int Jupiter::SecureSocket::recv() {
{ if (m_ssl_data->handle == nullptr)
if (Jupiter::SecureSocket::SSLdata_->handle == nullptr)
return -1; return -1;
Jupiter::Socket::Buffer &buffer = this->getInternalBuffer(); Jupiter::Socket::Buffer &buffer = this->getInternalBuffer();
buffer.erase(); buffer.clear();
int r = SSL_read(Jupiter::SecureSocket::SSLdata_->handle, buffer.get_str(), static_cast<int>(this->getBufferSize())); int r = SSL_read(m_ssl_data->handle, buffer.data(), static_cast<int>(this->getBufferSize()));
if (r > 0) if (r > 0)
buffer.set_length(r); buffer.set_length(r);
return r; return r;
} }
int Jupiter::SecureSocket::send(const char *data, size_t datalen) int Jupiter::SecureSocket::send(const char *data, size_t datalen) {
{ return SSL_write(m_ssl_data->handle, data, static_cast<int>(datalen));
return SSL_write(Jupiter::SecureSocket::SSLdata_->handle, data, static_cast<int>(datalen));
} }
bool Jupiter::SecureSocket::initSSL() bool Jupiter::SecureSocket::initSSL() {
{
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();
if (Jupiter::SecureSocket::SSLdata_->context == nullptr) if (m_ssl_data->context == nullptr) {
{ if (m_ssl_data->method == nullptr) {
if (Jupiter::SecureSocket::SSLdata_->method == nullptr) m_ssl_data->method = TLS_method();
{ if (m_ssl_data->method == nullptr)
Jupiter::SecureSocket::SSLdata_->method = translateEncryptionMethod(Jupiter::SecureSocket::SSLdata_->eMethod);
if (Jupiter::SecureSocket::SSLdata_->method == nullptr)
return false; return false;
} }
Jupiter::SecureSocket::SSLdata_->context = SSL_CTX_new(Jupiter::SecureSocket::SSLdata_->method); m_ssl_data->context = SSL_CTX_new(m_ssl_data->method);
if (Jupiter::SecureSocket::SSLdata_->context == nullptr) if (m_ssl_data->context == nullptr) {
{
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
return false; return false;
} }
if (!Jupiter::SecureSocket::SSLdata_->cert.empty()) if (!m_ssl_data->cert.empty()) {
loadCertificate(Jupiter::SecureSocket::SSLdata_->context, Jupiter::SecureSocket::SSLdata_->cert.c_str(), Jupiter::SecureSocket::SSLdata_->key.c_str()); 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); m_ssl_data->handle = SSL_new(m_ssl_data->context);
if (Jupiter::SecureSocket::SSLdata_->handle == nullptr) if (m_ssl_data->handle == nullptr) {
{
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
return false; return false;
} }
// Not suppressing this warning; descriptor ideally shouldn't be getting shortened here, even if it's "safe" // 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 // 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); ERR_print_errors_fp(stderr);
return false; 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); ERR_print_errors_fp(stderr);
return false; return false;
} }
int t = SSL_connect(Jupiter::SecureSocket::SSLdata_->handle); int t = SSL_connect(m_ssl_data->handle);
if (t != 1) if (t != 1)
{ {
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);

351
src/common/Socket.cpp

@ -45,12 +45,68 @@ bool socketInit = false;
#pragma warning(disable: 4267) #pragma warning(disable: 4267)
#endif #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) { void Jupiter::Socket::Buffer::set_length(size_t in_length) {
this->length = in_length; m_buffer_size = in_length;
}
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);
} }
char *Jupiter::Socket::Buffer::get_str() const { void Jupiter::Socket::Buffer::clear() {
return this->str; 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 { struct Jupiter::Socket::Data {
@ -71,7 +127,7 @@ struct Jupiter::Socket::Data {
}; };
Jupiter::Socket::Data::Data(size_t buffer_size) { 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) { 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 &Jupiter::Socket::operator=(Jupiter::Socket &&source) {
Jupiter::Socket::data_ = source.data_; m_data = source.m_data;
source.data_ = nullptr; source.m_data = nullptr;
return *this; return *this;
} }
@ -98,62 +154,62 @@ Jupiter::Socket::Socket() : Jupiter::Socket::Socket(512) {
} }
Jupiter::Socket::Socket(size_t bufferSize) { 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::Socket(Jupiter::Socket &&source) {
Jupiter::Socket::data_ = source.data_; m_data = source.m_data;
source.data_ = nullptr; source.m_data = nullptr;
} }
Jupiter::Socket::~Socket() { Jupiter::Socket::~Socket() {
if (Jupiter::Socket::data_ != nullptr) { if (m_data != nullptr) {
if (Jupiter::Socket::data_->rawSock > 0) if (m_data->rawSock > 0)
Jupiter::Socket::close(); Jupiter::Socket::close();
delete Jupiter::Socket::data_; delete m_data;
} }
} }
void Jupiter::Socket::setType(int type) { void Jupiter::Socket::setType(int type) {
Jupiter::Socket::data_->sockType = type; m_data->sockType = type;
} }
void Jupiter::Socket::setProtocol(int proto) { void Jupiter::Socket::setProtocol(int proto) {
Jupiter::Socket::data_->sockProto = proto; m_data->sockProto = proto;
} }
int Jupiter::Socket::getType() const { int Jupiter::Socket::getType() const {
return Jupiter::Socket::data_->sockType; return m_data->sockType;
} }
int Jupiter::Socket::getProtocol() const { int Jupiter::Socket::getProtocol() const {
return Jupiter::Socket::data_->sockProto; return m_data->sockProto;
} }
bool Jupiter::Socket::connect(addrinfo *info) { bool Jupiter::Socket::connect(addrinfo *info) {
#if defined _WIN32 #if defined _WIN32
if (!socketInit && !Jupiter::Socket::init()) if (!socketInit && !Jupiter::Socket::init()) {
return false; return false;
}
#endif // _WIN32 #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 if (m_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)) || (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 false;
return true; 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 defined _WIN32
if (!socketInit && !Jupiter::Socket::init()) if (!socketInit && !Jupiter::Socket::init())
return false; return false;
#endif // _WIN32 #endif // _WIN32
Jupiter::Socket::data_->remote_host = hostname; m_data->remote_host = hostname;
Jupiter::Socket::data_->remote_port = iPort; m_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()); 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) { if (info_head != nullptr) {
addrinfo *info = info_head; addrinfo *info = info_head;
do { do {
@ -163,21 +219,20 @@ bool Jupiter::Socket::connect(const char *hostname, unsigned short iPort, const
break; break;
} }
else { else {
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) { if (m_data->rawSock == INVALID_SOCKET) {
info = info->ai_next; info = info->ai_next;
continue; 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 #if defined _WIN32
::closesocket(Jupiter::Socket::data_->rawSock); ::closesocket(m_data->rawSock);
#else // _WIN32 #else // _WIN32
::close(Jupiter::Socket::data_->rawSock); ::close(m_data->rawSock);
#endif // WIN32 #endif // WIN32
Jupiter::Socket::data_->rawSock = INVALID_SOCKET; m_data->rawSock = INVALID_SOCKET;
info = info->ai_next; info = info->ai_next;
continue; continue;
} }
@ -190,38 +245,40 @@ bool Jupiter::Socket::connect(const char *hostname, unsigned short iPort, const
return false; 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 defined _WIN32
if (!socketInit && !Jupiter::Socket::init()) if (!socketInit && !Jupiter::Socket::init()) {
return false; return false;
}
#endif // _WIN32 #endif // _WIN32
Jupiter::Socket::data_->bound_host = hostname; m_data->bound_host = hostname;
Jupiter::Socket::data_->bound_port = iPort; m_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()); 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) { if (info_head != nullptr) {
addrinfo *info = info_head; addrinfo *info = info_head;
do { do {
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) { if (m_data->rawSock == INVALID_SOCKET) {
info = info->ai_next; info = info->ai_next;
continue; 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 #if defined _WIN32
::closesocket(Jupiter::Socket::data_->rawSock); ::closesocket(m_data->rawSock);
#else // _WIN32 #else // _WIN32
::close(Jupiter::Socket::data_->rawSock); ::close(m_data->rawSock);
#endif // WIN32 #endif // WIN32
Jupiter::Socket::data_->rawSock = INVALID_SOCKET; m_data->rawSock = INVALID_SOCKET;
info = info->ai_next; info = info->ai_next;
continue; continue;
} }
Jupiter::Socket::freeAddrInfo(info_head); 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 false;
}
return true; return true;
} while (info != nullptr); } while (info != nullptr);
Jupiter::Socket::freeAddrInfo(info_head); 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() { void Jupiter::Socket::shutdown() {
if (Jupiter::Socket::data_ != nullptr) { if (m_data != nullptr) {
::shutdown(Jupiter::Socket::data_->rawSock, 2); ::shutdown(m_data->rawSock, 2);
Jupiter::Socket::data_->is_shutdown = true; m_data->is_shutdown = true;
} }
} }
void Jupiter::Socket::close() { void Jupiter::Socket::close() {
if (Jupiter::Socket::data_ != nullptr) { if (m_data != nullptr) {
if (Jupiter::Socket::data_->is_shutdown == false) if (m_data->is_shutdown == false)
this->shutdown(); this->shutdown();
#if defined _WIN32 #if defined _WIN32
::closesocket(Jupiter::Socket::data_->rawSock); ::closesocket(m_data->rawSock);
#else // _WIN32 #else // _WIN32
::close(Jupiter::Socket::data_->rawSock); ::close(m_data->rawSock);
#endif // _WIN32 #endif // _WIN32
Jupiter::Socket::data_->rawSock = 0; m_data->rawSock = 0;
} }
} }
bool Jupiter::Socket::isShutdown() const { bool Jupiter::Socket::isShutdown() const {
return Jupiter::Socket::data_->is_shutdown; return m_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;
} }
addrinfo *Jupiter::Socket::getStaticAddrInfo(const char *hostname, const char *port) { // static addrinfo* Jupiter::Socket::getAddrInfo(const char *hostname, const char *port) { // static
static addrinfo *ptr = nullptr; addrinfo *ptr{};
if (ptr != nullptr) freeaddrinfo(ptr); getaddrinfo(hostname, port, nullptr, &ptr);
ptr = Jupiter::Socket::getAddrInfo(hostname, port);
return 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 *Jupiter::Socket::getAddrInfo(addrinfo *addr, unsigned int result) { // static
addrinfo *ptr = addr; addrinfo* ptr = addr;
for (unsigned int i = 0; i != result && ptr != nullptr; i++) ptr = ptr->ai_next; while (ptr != nullptr && result != 0) {
ptr = ptr->ai_next;
--result;
}
return ptr; return ptr;
} }
char *Jupiter::Socket::resolveAddress(const addrinfo *addr) { // static std::string Jupiter::Socket::resolveAddress(const addrinfo *addr) { // static
static char resolved[NI_MAXHOST]; char resolved[NI_MAXHOST];
getnameinfo(addr->ai_addr, addr->ai_addrlen, resolved, NI_MAXHOST, 0, 0, NI_NUMERICHOST); getnameinfo(addr->ai_addr, addr->ai_addrlen, resolved, NI_MAXHOST, 0, 0, NI_NUMERICHOST);
return resolved; 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); addrinfo *ptr = Jupiter::Socket::getAddrInfo(addr, result);
if (ptr == nullptr) return nullptr; if (ptr == nullptr) {
return {};
}
return Jupiter::Socket::resolveAddress(ptr); 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); addrinfo *info = Jupiter::Socket::getAddrInfo(hostname, 0);
if (info == nullptr) return nullptr; if (info == nullptr) {
return {};
};
return Jupiter::Socket::resolveAddress(info, result); return Jupiter::Socket::resolveAddress(info, result);
} }
char *Jupiter::Socket::resolveHostname(addrinfo *addr) { // static std::string Jupiter::Socket::resolveHostname(addrinfo *addr) { // static
static char resolved[NI_MAXHOST]; char resolved[NI_MAXHOST];
getnameinfo(addr->ai_addr, addr->ai_addrlen, resolved, sizeof(resolved), 0, 0, 0); getnameinfo(addr->ai_addr, addr->ai_addrlen, resolved, sizeof(resolved), 0, 0, 0);
return resolved; return resolved;
} }
char *Jupiter::Socket::resolveHostname_alloc(addrinfo *addr) { // static std::string Jupiter::Socket::resolveHostname(addrinfo *addr, unsigned int result) { // 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
addrinfo *ptr = Jupiter::Socket::getAddrInfo(addr, result); addrinfo *ptr = Jupiter::Socket::getAddrInfo(addr, result);
if (ptr == nullptr) return nullptr; if (ptr == nullptr) {
return Jupiter::Socket::resolveHostname(ptr); return {};
} }
char *Jupiter::Socket::resolveHostname_alloc(addrinfo *addr, unsigned int result) { // static return Jupiter::Socket::resolveHostname(ptr);
addrinfo *ptr = Jupiter::Socket::getAddrInfo(addr, result);
if (ptr == nullptr) return nullptr;
return Jupiter::Socket::resolveHostname_alloc(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); addrinfo *info = Jupiter::Socket::getAddrInfo(hostname, 0);
if (info == nullptr) return nullptr; if (info == nullptr) {
return Jupiter::Socket::resolveHostname(info, result); return {};
} }
char *Jupiter::Socket::resolveHostname_alloc(const char *hostname, unsigned int result) { // static return Jupiter::Socket::resolveHostname(info, result);
addrinfo *info = Jupiter::Socket::getAddrInfo(hostname, 0);
if (info == nullptr) return nullptr;
return Jupiter::Socket::resolveHostname_alloc(info, result);
} }
uint32_t Jupiter::Socket::pton4(const char *str) { 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; sockaddr addr;
socklen_t size = sizeof(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) { if (tSock != INVALID_SOCKET) {
char resolved[NI_MAXHOST]; char resolved[NI_MAXHOST];
char resolved_port[NI_MAXSERV]; char resolved_port[NI_MAXSERV];
getnameinfo(&addr, size, resolved, sizeof(resolved), resolved_port, sizeof(resolved_port), NI_NUMERICHOST | NI_NUMERICSERV); getnameinfo(&addr, size, resolved, sizeof(resolved), resolved_port, sizeof(resolved_port), NI_NUMERICHOST | NI_NUMERICSERV);
Socket *r = new Socket(Jupiter::Socket::data_->buffer.capacity()); Socket *result = new Socket(m_data->buffer.capacity());
r->data_->rawSock = tSock; result->m_data->rawSock = tSock;
r->data_->sockType = Jupiter::Socket::data_->sockType; result->m_data->sockType = m_data->sockType;
r->data_->sockProto = Jupiter::Socket::data_->sockProto; result->m_data->sockProto = m_data->sockProto;
r->data_->remote_host = resolved; result->m_data->remote_host = resolved;
r->data_->remote_port = static_cast<unsigned short>(Jupiter_strtoi(resolved_port, 10)); result->m_data->remote_port = static_cast<unsigned short>(Jupiter_strtoi(resolved_port, 10));
return r; return result;
} }
return nullptr; return nullptr;
} }
bool Jupiter::Socket::setReadTimeout(unsigned long milliseconds) { bool Jupiter::Socket::setReadTimeout(unsigned long milliseconds) {
#if defined _WIN32 #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 #else // _WIN32
timeval time; timeval time;
time.tv_sec = milliseconds / 1000; time.tv_sec = milliseconds / 1000;
time.tv_usec = (milliseconds % 1000) * 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 #endif // _WIN32
} }
bool Jupiter::Socket::setSendTimeout(unsigned long milliseconds) { bool Jupiter::Socket::setSendTimeout(unsigned long milliseconds) {
#if defined _WIN32 #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 #else // _WIN32
timeval time; timeval time;
time.tv_sec = milliseconds / 1000; time.tv_sec = milliseconds / 1000;
time.tv_usec = (milliseconds % 1000) * 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 #endif // _WIN32
} }
@ -419,10 +467,10 @@ bool Jupiter::Socket::setTimeout(unsigned long milliseconds) {
bool Jupiter::Socket::setBlocking(bool mode) { bool Jupiter::Socket::setBlocking(bool mode) {
#if defined _WIN32 #if defined _WIN32
Jupiter::Socket::data_->blockMode = !mode; m_data->blockMode = !mode;
return ioctlsocket(Jupiter::Socket::data_->rawSock, FIONBIO, &Jupiter::Socket::data_->blockMode) == 0; return ioctlsocket(m_data->rawSock, FIONBIO, &m_data->blockMode) == 0;
#else // _WIN32 #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 (flags < 0) return 0;
if (mode) { if (mode) {
flags &= ~O_NONBLOCK; flags &= ~O_NONBLOCK;
@ -430,61 +478,62 @@ bool Jupiter::Socket::setBlocking(bool mode) {
else { else {
flags |= O_NONBLOCK; flags |= O_NONBLOCK;
} }
return fcntl(Jupiter::Socket::data_->rawSock, F_SETFL, flags) == 0; return fcntl(m_data->rawSock, F_SETFL, flags) == 0;
#endif // _WIN32 #endif // _WIN32
} }
bool Jupiter::Socket::getBlockingMode() const { bool Jupiter::Socket::getBlockingMode() const {
#if defined _WIN32 #if defined _WIN32
return !Jupiter::Socket::data_->blockMode; return !m_data->blockMode;
#else // _WIN32 #else // _WIN32
int flags = fcntl(data_->rawSock, F_GETFL, 0); int flags = fcntl(m_data->rawSock, F_GETFL, 0);
if (flags == -1) return false; if (flags == -1) return false;
return !(flags & O_NONBLOCK); return !(flags & O_NONBLOCK);
#endif #endif
} }
const std::string &Jupiter::Socket::getRemoteHostname() const { const std::string &Jupiter::Socket::getRemoteHostname() const {
return Jupiter::Socket::data_->remote_host; return m_data->remote_host;
} }
const char *Jupiter::Socket::getRemoteHostnameC() const { 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 { const std::string &Jupiter::Socket::getBoundHostname() const {
return Jupiter::Socket::data_->bound_host; return m_data->bound_host;
} }
const char *Jupiter::Socket::getBoundHostnameC() const { 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 { unsigned short Jupiter::Socket::getRemotePort() const {
return Jupiter::Socket::data_->remote_port; return m_data->remote_port;
} }
unsigned short Jupiter::Socket::getBoundPort() const { unsigned short Jupiter::Socket::getBoundPort() const {
return Jupiter::Socket::data_->bound_port; return m_data->bound_port;
} }
std::string_view Jupiter::Socket::getBuffer() const { std::string_view Jupiter::Socket::getBuffer() const {
return Jupiter::Socket::data_->buffer; return m_data->buffer.view();
} }
size_t Jupiter::Socket::getBufferSize() const { 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) { std::string_view Jupiter::Socket::setBufferSize(size_t size) {
Jupiter::Socket::data_->buffer.setBufferSize(size); m_data->buffer.reserve(size);
return Jupiter::Socket::data_->buffer; return m_data->buffer.view();
} }
std::string_view Jupiter::Socket::getData() { std::string_view Jupiter::Socket::getData() {
if (this->recv() <= 0) if (this->recv() <= 0) {
Jupiter::Socket::data_->buffer.erase(); m_data->buffer.clear();
return Jupiter::Socket::data_->buffer; }
return m_data->buffer.view();
} }
const char *Jupiter::Socket::getLocalHostname() { // static const char *Jupiter::Socket::getLocalHostname() { // static
@ -494,11 +543,11 @@ const char *Jupiter::Socket::getLocalHostname() { // static
} }
void Jupiter::Socket::clearBuffer() { void Jupiter::Socket::clearBuffer() {
Jupiter::Socket::data_->buffer.erase(); m_data->buffer.clear();
} }
int Jupiter::Socket::send(const char *data, size_t datalen) { 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) { 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) { 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) { 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() { int Jupiter::Socket::peek() {
Jupiter::Socket::data_->buffer.erase(); m_data->buffer.clear();
int r = ::recv(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), MSG_PEEK); int r = ::recv(m_data->rawSock, m_data->buffer.chr_data(), m_data->buffer.capacity(), MSG_PEEK);
if (r > 0) if (r > 0)
Jupiter::Socket::data_->buffer.set_length(r); m_data->buffer.set_length(r);
return r; return r;
} }
int Jupiter::Socket::peekFrom(addrinfo *info) { int Jupiter::Socket::peekFrom(addrinfo *info) {
Jupiter::Socket::data_->buffer.erase(); m_data->buffer.clear();
if (info == nullptr) 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; socklen_t len = info->ai_addrlen;
if (len <= 0) { if (len <= 0) {
info->ai_addr = new sockaddr(); info->ai_addr = new sockaddr();
len = sizeof(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) { if (r >= 0) {
info->ai_addrlen = len; info->ai_addrlen = len;
info->ai_family = info->ai_addr->sa_family; info->ai_family = info->ai_addr->sa_family;
@ -546,24 +595,26 @@ int Jupiter::Socket::peekFrom(addrinfo *info) {
} }
int Jupiter::Socket::recv() { int Jupiter::Socket::recv() {
Jupiter::Socket::data_->buffer.erase(); m_data->buffer.clear();
int r = ::recv(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), 0); int r = ::recv(m_data->rawSock, m_data->buffer.chr_data(), m_data->buffer.capacity(), 0);
if (r > 0) if (r > 0) {
Jupiter::Socket::data_->buffer.set_length(r); m_data->buffer.set_length(r);
}
return r; return r;
} }
int Jupiter::Socket::recvFrom(addrinfo *info) { int Jupiter::Socket::recvFrom(addrinfo* info) {
Jupiter::Socket::data_->buffer.erase(); m_data->buffer.clear();
if (info == nullptr) if (info == nullptr) {
return recvfrom(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), 0, nullptr, nullptr); return recvfrom(m_data->rawSock, m_data->buffer.chr_data(), m_data->buffer.capacity(), 0, nullptr, nullptr);
}
socklen_t len = info->ai_addrlen; socklen_t len = info->ai_addrlen;
if (len <= 0) { if (len <= 0) {
info->ai_addr = new sockaddr(); info->ai_addr = new sockaddr();
len = sizeof(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) { if (r >= 0) {
info->ai_addrlen = len; info->ai_addrlen = len;
info->ai_family = info->ai_addr->sa_family; info->ai_family = info->ai_addr->sa_family;
@ -608,15 +659,15 @@ bool Jupiter::Socket::cleanup() { // static
} }
Jupiter::Socket::SocketType Jupiter::Socket::getDescriptor() const { Jupiter::Socket::SocketType Jupiter::Socket::getDescriptor() const {
return Jupiter::Socket::data_->rawSock; return m_data->rawSock;
} }
void Jupiter::Socket::setDescriptor(SocketType descriptor) { void Jupiter::Socket::setDescriptor(SocketType descriptor) {
Jupiter::Socket::data_->rawSock = descriptor; m_data->rawSock = descriptor;
} }
Jupiter::Socket::Buffer &Jupiter::Socket::getInternalBuffer() const { Jupiter::Socket::Buffer &Jupiter::Socket::getInternalBuffer() const {
return Jupiter::Socket::data_->buffer; return m_data->buffer;
} }
/** Re-enable warnings */ /** Re-enable warnings */

29
src/include/Jupiter/SecureSocket.h

@ -39,39 +39,12 @@ namespace Jupiter
{ {
public: 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. * @brief Returns the name of the cipher currently in use.
* @return Name of cipher currently in use, or "NONE" if none is in use. * @return Name of cipher currently in use, or "NONE" if none is in use.
*/ */
const char *getCipherName() const; 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. * @brief Loads a certificate and key for use.
* *
@ -207,7 +180,7 @@ namespace Jupiter
/** Private members */ /** Private members */
private: private:
struct SSLData; 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. * @param port String containing the target port.
* @return Pointer to a NULL-terminated linked list of addrinfo on success, nullptr otherwise. * @return Pointer to a NULL-terminated linked list of addrinfo on success, nullptr otherwise.
*/ */
static addrinfo *getAddrInfo(const char *hostname, const char *port); 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);
/** /**
* @brief Frees the resources associated with an addrinfo struct. * @brief Frees the resources associated with an addrinfo struct.
@ -112,7 +101,7 @@ namespace Jupiter
* @param addr Address info containing IP address. * @param addr Address info containing IP address.
* @return String containing the text representation of the stored address on success, nullptr otherwise. * @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. * @brief Returns the text representation of an addrinfo's stored address.
@ -121,7 +110,7 @@ namespace Jupiter
* @param result Which result to return. * @param result Which result to return.
* @return String containing the text representation of the stored address on success, nullptr otherwise. * @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. * @brief Resolves a hostname to an IP address.
@ -130,7 +119,7 @@ namespace Jupiter
* @param result Which resolution result to return. * @param result Which resolution result to return.
* @return String containing the text representation of the resolved address on success, nullptr otherwise. * @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) * @brief Resolves an address to a hostname. (Reverse DNS)
@ -139,8 +128,7 @@ namespace Jupiter
* @param addr Address info containing IP address. * @param addr Address info containing IP address.
* @return String containing the hostname of the stored address on success, nullptr otherwise. * @return String containing the hostname of the stored address on success, nullptr otherwise.
*/ */
static char *resolveHostname(addrinfo *addr); static std::string resolveHostname(addrinfo *addr);
static char *resolveHostname_alloc(addrinfo *addr);
/** /**
* @brief Resolves an address to a hostname. (Reverse DNS) * @brief Resolves an address to a hostname. (Reverse DNS)
@ -149,8 +137,7 @@ namespace Jupiter
* @param result Which result to return. * @param result Which result to return.
* @return String containing the hostname of the stored address on success, nullptr otherwise. * @return String containing the hostname of the stored address on success, nullptr otherwise.
*/ */
static char *resolveHostname(addrinfo *addr, unsigned int result); static std::string resolveHostname(addrinfo *addr, unsigned int result);
static char *resolveHostname_alloc(addrinfo *addr, unsigned int result);
/** /**
* @brief Resolves an address to a hostname. (Reverse DNS) * @brief Resolves an address to a hostname. (Reverse DNS)
@ -159,8 +146,7 @@ namespace Jupiter
* @param result Which resolution result to return. * @param result Which resolution result to return.
* @return String containing the hostname of the resolved address on success, nullptr otherwise. * @return String containing the hostname of the resolved address on success, nullptr otherwise.
*/ */
static char *resolveHostname(const char *hostname, unsigned int result); static std::string resolveHostname(const char *hostname, unsigned int result);
static char *resolveHostname_alloc(const char *hostname, unsigned int result);
/** /**
* @brief Reinterprets an IPv4 address as a 32-bit integer in network byte order. * @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. * @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. * 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() */ 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. * @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: public:
Buffer();
~Buffer();
void set_length(size_t in_length); 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 members */
private: private:
struct Data; struct Data;
Data *data_; Data *m_data;
}; };
} }

2
src/jessilib

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