Merge tls into master: bring in subscription ownership, keep all TLS/stability work
tls and master diverged from a July 2024 fork point and never reconciled - tls carries ~19 months of real socket/TLS stability fixes (uninitialized tlsInfo, TCPServer::connectionRequest() unconditionally initializing TLS, the WANT_READ write busy-spin, the console authentication fix from this session), while master independently picked up a Subscription/SubscriptionManager rework (MString-based ownership tracking: owner/ownership/selection/time fields and a working subscriptionOwner() method) that tls never had. Every file both branches touched was resolved by keeping tls's side entirely (Command.h, Socket.cpp, TCPServer.h, TCPSession.cpp/h, TCPSocket.h were pure reformatting on master's side, or an alternate/superseded fix for a bug tls already fixed a different way - e.g. master's TCPSession uuid/alias handling vs tls's existing uuid_unparse-based fix), with two deliberate exceptions: - TCPServer.cpp's constructor was missing the commands.add(subscriptions, "publish"/"subscribe"/"catalog"/...) wiring master had - without it, SubscriptionManager existed but was completely unreachable through the normal command dispatch. Restored on top of tls's TLS-aware constructor. - SubscriptionManager.cpp's "invite" command handler had a real incompatibility: master's version assigned into an `invitee` member typed as coreutils::MString via a stray `(coreutils::MString *)` cast that doesn't match the member's actual (non-pointer) type, and called session.server.getSessionByAlias() against a TCPServer reference - tls made TCPSession::server a pointer (part of removing the separate TCPSession2 class), so that call site no longer compiles as written. Took tls's cleaner local-variable version instead (functionally identical - looks up a session by alias and forwards an invite message) and removed the now-unused `invitee` member from SubscriptionManager.h. One additional compile fix needed after resolving conflicts: Subscription::subscriptionOwners is an MString (master's ownership design), but TCPSession::alias is void* (tls's identity mechanism, unchanged and depended on elsewhere) - MString has an implicit constructor from void* already used successfully elsewhere in this same file (the "publish" handler's Subscription constructor call), but operator== doesn't accept the same implicit conversion, so removeSessionSubscriptions()'s ownership check needed an explicit coreutils::MString(session.alias) construction to compile. Also drops output/main (a stray checked-in compiled binary, already removed on tls) and the doxygen docs/html output (already removed on tls, was carried on master since the fork). Verified: full ServerCore rebuild (./compile) succeeds with zero errors or warnings beyond the one compile fix documented above.
This commit is contained in:
commit
3609ed603e
2883 files changed
+5296
-84468
No files matched your search
+66
-51
@@ -4,49 +4,71 @@
|
||||
#include "Log.h"
|
||||
#include "TCPSession.h"
|
||||
|
||||
namespace core
|
||||
{
|
||||
namespace core {
|
||||
|
||||
TCPServer::TCPServer(EPoll &ePoll, IPAddress address, TLSInfo *tlsInfo, std::string delimiter, int depth, std::string text)
|
||||
: TCPSocket(ePoll, tlsInfo, text), commands(delimiter, depth) {
|
||||
|
||||
TCPServer::TCPServer(EPoll &ePoll, IPAddress address, std::string delimiter, int depth, std::string text)
|
||||
: TCPSocket(ePoll, text), commands(delimiter, depth)
|
||||
{
|
||||
// Wires the subscription (pub/sub) command set into this server's
|
||||
// own command dispatch - previously missing entirely here (the
|
||||
// subscriptions member existed but nothing ever routed these verbs
|
||||
// to it), so publish/subscribe/catalog/etc were unreachable on any
|
||||
// TCPServer built after the TLS work, even though SubscriptionManager
|
||||
// itself was still fully implemented.
|
||||
commands.add(subscriptions, "publish");
|
||||
commands.add(subscriptions, "unpublish");
|
||||
commands.add(subscriptions, "subscribe");
|
||||
commands.add(subscriptions, "unsubscribe");
|
||||
commands.add(subscriptions, "catalog");
|
||||
commands.add(subscriptions, "event");
|
||||
commands.add(subscriptions, "invite");
|
||||
|
||||
commands.add(subscriptions, "publish");
|
||||
commands.add(subscriptions, "unpublish");
|
||||
commands.add(subscriptions, "subscribe");
|
||||
commands.add(subscriptions, "unsubscribe");
|
||||
commands.add(subscriptions, "catalog");
|
||||
commands.add(subscriptions, "event");
|
||||
commands.add(subscriptions, "invite");
|
||||
|
||||
setDescriptor(socket(AF_INET, SOCK_STREAM, 0));
|
||||
int yes = 1;
|
||||
setsockopt(getDescriptor(), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
|
||||
|
||||
if (bind(getDescriptor(), address.getPointer(), address.addressLength) < 0)
|
||||
throw coreutils::Exception("Error on bind to socket: " + std::to_string(errno));
|
||||
|
||||
if (listen(getDescriptor(), 20) < 0)
|
||||
throw coreutils::Exception("Error on listen to socket");
|
||||
}
|
||||
|
||||
TCPServer::~TCPServer()
|
||||
{
|
||||
setDescriptor(socket(AF_INET, SOCK_STREAM, 0));
|
||||
int yes = 1;
|
||||
setsockopt(getDescriptor(), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
|
||||
|
||||
if (bind(getDescriptor(), address.getPointer(), address.addressLength) < 0)
|
||||
throw coreutils::Exception("Error on bind to socket: " + std::to_string(errno));
|
||||
|
||||
if (listen(getDescriptor(), 20) < 0)
|
||||
throw coreutils::Exception("Error on listen to socket");
|
||||
}
|
||||
|
||||
TCPServer::~TCPServer() {
|
||||
coreutils::Log(coreutils::LOG_DEBUG_2) << "Closing server socket " << getDescriptor() << ".";
|
||||
close(getDescriptor());
|
||||
}
|
||||
|
||||
void TCPServer::onDataReceived(std::string data)
|
||||
{
|
||||
void TCPServer::connectionRequest() {
|
||||
coreutils::Log(coreutils::LOG_DEBUG_2) << "Connection request is being received on socket " << getDescriptor() << ".";
|
||||
lock.lock();
|
||||
TCPSession *session = accept();
|
||||
if (session)
|
||||
sessions.push_back(session);
|
||||
// Must run ON THE SESSION, not `this` (the listening server) - the
|
||||
// unqualified registerSocket()/acceptSocket() calls this replaced
|
||||
// built the SSL* handshake state on the SERVER's own TLS-base
|
||||
// member instead of the newly accepted session's, leaving every
|
||||
// session's own `ssl` uninitialized and segfaulting the first time
|
||||
// real data arrived on it (SSL_read() against a never-SSL_new()'d
|
||||
// pointer - confirmed via gdb). Sessions already correctly inherit
|
||||
// this server's SSL_CTX at construction (TCPSession's own
|
||||
// TLS(SSL_CTX*)-taking constructor) - performTLSHandshake() just
|
||||
// needed to actually be invoked on that object.
|
||||
if (session && tlsInfo)
|
||||
session->performTLSHandshake();
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
TCPSession *TCPServer::accept()
|
||||
{
|
||||
void TCPServer::receiveData(coreutils::ZString &buffer) {
|
||||
// See this override's own doc comment in TCPServer.h - the
|
||||
// listening socket always uses the plain read()/ENOTCONN detection
|
||||
// path, never TLS::receiveData(), regardless of whether this server
|
||||
// is TLS-configured.
|
||||
Socket::receiveData(buffer);
|
||||
}
|
||||
|
||||
TCPSession * TCPServer::accept() {
|
||||
|
||||
try
|
||||
{
|
||||
@@ -65,19 +87,16 @@ namespace core
|
||||
// }
|
||||
return session;
|
||||
}
|
||||
catch (coreutils::Exception e)
|
||||
{
|
||||
catch (coreutils::Exception e) {
|
||||
coreutils::Log(coreutils::LOG_EXCEPT) << "Major error on session initialization. Error is '" << e.text << "'.";
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
catch (...) {
|
||||
coreutils::Log(coreutils::LOG_EXCEPT) << "Unnspecified error on session initialization.";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void TCPServer::removeFromSessionList(TCPSession *session)
|
||||
{
|
||||
|
||||
void TCPServer::removeFromSessionList(TCPSession *session) {
|
||||
std::vector<TCPSession *>::iterator cursor;
|
||||
lock.lock();
|
||||
for (cursor = sessions.begin(); cursor < sessions.end(); ++cursor)
|
||||
@@ -88,15 +107,13 @@ namespace core
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
void TCPServer::sessionErrorHandler(std::string errorString, std::stringstream &out)
|
||||
{
|
||||
|
||||
void TCPServer::sessionErrorHandler(std::string errorString, std::stringstream &out) {
|
||||
throw coreutils::Exception(errorString);
|
||||
}
|
||||
|
||||
TCPSession *TCPServer::getSocketAccept(EPoll &ePoll)
|
||||
{
|
||||
return new TCPSession(ePoll, *this);
|
||||
TCPSession * TCPServer::getSocketAccept(EPoll &ePoll) {
|
||||
return new TCPSession(ePoll, this);
|
||||
}
|
||||
|
||||
void TCPServer::output(std::stringstream &out)
|
||||
@@ -116,23 +133,20 @@ namespace core
|
||||
return 1;
|
||||
}
|
||||
|
||||
void TCPServer::sendToAll(std::stringstream &data)
|
||||
{
|
||||
void TCPServer::sendToAll(std::stringstream &data) {
|
||||
for (auto session : sessions)
|
||||
session->write(data.str());
|
||||
session->write(data.str());
|
||||
data.str("");
|
||||
}
|
||||
|
||||
void TCPServer::sendToAll(std::stringstream &data, TCPSession &sender)
|
||||
{
|
||||
void TCPServer::sendToAll(std::stringstream &data, TCPSession &sender) {
|
||||
for (auto session : sessions)
|
||||
if (session != &sender)
|
||||
session->write(data.str());
|
||||
data.str("");
|
||||
}
|
||||
|
||||
void TCPServer::sendToAll(std::stringstream &data, TCPSession &sender, SessionFilter filter)
|
||||
{
|
||||
void TCPServer::sendToAll(std::stringstream &data, TCPSession &sender, SessionFilter filter) {
|
||||
for (auto session : sessions)
|
||||
if (filter.test(*session))
|
||||
if (session != &sender)
|
||||
@@ -140,7 +154,8 @@ namespace core
|
||||
data.str("");
|
||||
}
|
||||
|
||||
TCPSession *TCPServer::getSessionByAlias(coreutils::MString alias) {
|
||||
TCPSession *TCPServer::getSessionByAlias(void *alias) {
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << alias;
|
||||
for (auto session : sessions)
|
||||
if (session->alias == alias)
|
||||
return session;
|
||||
|
||||
Reference in new issue
Block a user