This commit is contained in:
Brad Arant 2022-01-24 18:36:47 -08:00
parent 96d9295df8
commit 3ef82e0fce
14 changed files with 159 additions and 115 deletions

View File

@ -11,7 +11,8 @@
"cStandard": "c17", "cStandard": "c17",
"cppStandard": "gnu++20", "cppStandard": "gnu++20",
"intelliSenseMode": "windows-gcc-x64", "intelliSenseMode": "windows-gcc-x64",
"compileCommands": "./compile" "compileCommands": "./compile",
"configurationProvider": "ms-vscode.cmake-tools"
}, },
{ {
"name": "config", "name": "config",

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"cmake.configureOnOpen": false
}

View File

@ -17,11 +17,17 @@ namespace core {
else { else {
if(request.equals("")) if(request.equals(""))
return false; return false;
request.split(delimiter); request.split(delimiter, 2);
auto command = commands[request[0].str()]; request.reset();
return command->processCommand(request, session); try {
auto command = commands.at(request[0].str());
return command->processCommand(request, session);
}
catch(...) {
return false;
}
} }
return false; return true;
} }
bool CommandList::grabInput(TCPSession &session, Command &command) { bool CommandList::grabInput(TCPSession &session, Command &command) {

View File

@ -33,6 +33,7 @@ namespace core {
out << "Password: "; out << "Password: ";
status = WAIT_PASSWORD; status = WAIT_PASSWORD;
break; break;
case WAIT_PASSWORD: case WAIT_PASSWORD:
status = PROMPT; status = PROMPT;
protocol(blank); protocol(blank);

View File

@ -67,23 +67,23 @@ namespace core {
if(event.events & EPOLLRDHUP) { if(event.events & EPOLLRDHUP) {
readHangup = true; readHangup = true;
shutdown("hangup received"); shutdown("hangup received");
lock.unlock(); lock.unlock();
return false; return false;
} }
if(event.events & EPOLLIN) { if(event.events & EPOLLIN) {
coreutils::ZString zbuffer(buffer, length); coreutils::ZString zbuffer(buffer, length);
receiveData(zbuffer); receiveData(zbuffer);
} }
if(event.events & EPOLLWRNORM) { if(event.events & EPOLLWRNORM) {
writeSocket(); writeSocket();
} }
if(event.events & EPOLLHUP) { if(event.events & EPOLLHUP) {
shutdown(); shutdown();
lock.unlock(); lock.unlock();
return false; return false;
} }
lock.unlock(); lock.unlock();
@ -115,6 +115,7 @@ namespace core {
if((len = ::read(getDescriptor(), buffer.getData(), buffer.getLength())) >= 0) { if((len = ::read(getDescriptor(), buffer.getData(), buffer.getLength())) >= 0) {
coreutils::ZString zbuffer(buffer.getData(), len); coreutils::ZString zbuffer(buffer.getData(), len);
// coreutils::Log(coreutils::LOG_DEBUG_1) << zbuffer;
onDataReceived(zbuffer); onDataReceived(zbuffer);
} }
else { else {
@ -141,12 +142,12 @@ namespace core {
void Socket::writeSocket() { void Socket::writeSocket() {
if(fifo.size() > 0) { if(fifo.size() > 0) {
outlock.lock(); outlock.lock();
::write(descriptor, fifo.front().c_str(), fifo.front().length()); ::write(descriptor, fifo.front().c_str(), fifo.front().length());
fifo.pop(); fifo.pop();
if(shutDown && !needsToWrite()) if(shutDown && !needsToWrite())
delete this; delete this;
outlock.unlock(); outlock.unlock();
} }
} }

View File

@ -2,7 +2,15 @@
namespace core { namespace core {
Subscription::Subscription(std::string id, TCPSession &session) : id(id), owner(&session) {} Subscription::Subscription(std::string id, TCPSession &session) : id(id), owner(session) {}
Subscription::~Subscription() {
std::stringstream out;
out << "cancel:" << id << std::endl;
for(auto subscriber : subscribers) {
subscriber->write(out.str());
}
}
int Subscription::subscribe(TCPSession &session) { int Subscription::subscribe(TCPSession &session) {
subscribers.push_back(&session); subscribers.push_back(&session);
@ -12,7 +20,7 @@ namespace core {
int Subscription::unsubscribe(TCPSession &session) { int Subscription::unsubscribe(TCPSession &session) {
for(auto subscriber = subscribers.begin(); subscriber < subscribers.end(); ++subscriber) { for(auto subscriber = subscribers.begin(); subscriber < subscribers.end(); ++subscriber) {
if(*subscriber == &session) { if(*subscriber == &session) {
subscribers.erase(subscriber); subscribers.erase(subscriber++);
return 1; return 1;
} }
} }

View File

@ -5,6 +5,7 @@
#include "Command.h" #include "Command.h"
#include "ZString.h" #include "ZString.h"
#include <vector> #include <vector>
#include <string>
namespace core { namespace core {
@ -12,6 +13,7 @@ namespace core {
public: public:
Subscription(std::string id, TCPSession &session); Subscription(std::string id, TCPSession &session);
~Subscription();
int subscribe(TCPSession &session); int subscribe(TCPSession &session);
int unsubscribe(TCPSession &session); int unsubscribe(TCPSession &session);
@ -22,7 +24,7 @@ namespace core {
int processCommand(coreutils::ZString &request, TCPSession &session) override; int processCommand(coreutils::ZString &request, TCPSession &session) override;
std::string id; std::string id;
TCPSession *owner; TCPSession &owner;
std::vector<TCPSession *> subscribers; std::vector<TCPSession *> subscribers;

View File

@ -6,49 +6,62 @@ namespace core {
SubscriptionManager::SubscriptionManager() {} SubscriptionManager::SubscriptionManager() {}
int SubscriptionManager::removeSessionSubscriptions(TCPSession &session) { int SubscriptionManager::removeSessionSubscriptions(TCPSession &session) {
int count = 0; int countSubscribed = 0;
for(auto subscription = subscriptions.begin(); subscription < subscriptions.end(); ++subscription) { int countPublished = 0;
count += (*subscription)->unsubscribe(session); for(auto subscription = subscriptions.begin(); subscription != subscriptions.end();) {
countSubscribed += (*subscription).second->unsubscribe(session);
if(&(*subscription).second->owner == &session) {
subscription = subscriptions.erase(subscription);
delete (*subscription).second;
++countPublished;
} else
++subscription;
} }
coreutils::Log(coreutils::LOG_DEBUG_2) << "Removed session from " << count << " subscriptions."; coreutils::Log(coreutils::LOG_DEBUG_2) << "Removed session from " << countSubscribed << " subscription(s).";
return count; coreutils::Log(coreutils::LOG_DEBUG_2) << "Cancelled " << countPublished << " channel(s) for session.";
return countSubscribed;
} }
int SubscriptionManager::processCommand(coreutils::ZString &request, TCPSession &session) { int SubscriptionManager::processCommand(coreutils::ZString &request, TCPSession &session) {
coreutils::Log(coreutils::LOG_DEBUG_2) << "Processing subscription request: " << request << ".";
if(request[0].equals("publish")) { if(request[0].equals("publish")) {
subscriptions.push_back(new Subscription(request[1].str(), session)); Subscription *newSubscription = new Subscription(request[1].str(), session);
subscriptions.insert(std::make_pair(request[1].str(), newSubscription));
return 1; return 1;
} else if(request[0].equals("catalog")) { } else if(request[0].equals("catalog")) {
session.out << ":catalog:"; session.out << ":catalog:";
for(auto subscription = subscriptions.begin(); subscription < subscriptions.end(); ++subscription) { for(auto const& [key, subscription] : subscriptions) {
session.out << (*subscription)->id << "|"; session.out << subscription->id << "|";
(*subscription)->processCommand(request, session); subscription->processCommand(request, session);
session.out << (";"); session.out << (";");
} }
session.out << std::endl; session.out << std::endl;
return 1; return 1;
} }
for(auto subscription = subscriptions.begin(); subscription < subscriptions.end(); ++subscription) { auto subscription = subscriptions[request[1].str()];
if(request[1].equals((*subscription)->id)) {
if(request[0].equals("unpublish")) { if(request[1].equals(subscription->id)) {
subscriptions.erase(subscription); if(request[0].equals("unpublish")) {
} else if(request[0].equals("subscribe")) { subscriptions.erase(request[1].str());
(*subscription)->subscribe(session); } else if(request[0].equals("subscribe")) {
} else if(request[0].equals("unsubscribe")) { subscription->subscribe(session);
(*subscription)->unsubscribe(session); } else if(request[0].equals("unsubscribe")) {
} else if(request[0].equals("event")) { subscription->unsubscribe(session);
if((*subscription)->owner == &session) { } else if(request[0].equals("event")) {
std::stringstream out; if(&subscription->owner == &session) {
(*subscription)->process(request, out); std::stringstream out;
(*subscription)->event(out); subscription->process(request, out);
} subscription->event(out);
else
return 0;
} }
return 1; else
return 0;
} }
return 1;
} }
return 0; return 0;
} }

View File

@ -6,6 +6,7 @@
#include "Command.h" #include "Command.h"
#include "ZString.h" #include "ZString.h"
#include <vector> #include <vector>
#include <string>
namespace core { namespace core {
@ -19,7 +20,7 @@ namespace core {
int processCommand(coreutils::ZString &request, TCPSession &session) override; int processCommand(coreutils::ZString &request, TCPSession &session) override;
private: private:
std::vector<Subscription *> subscriptions; std::map<std::string, Subscription *> subscriptions;
}; };
} }

View File

@ -109,6 +109,12 @@ namespace core {
void sendToAll(std::stringstream &out, TCPSession &sender); void sendToAll(std::stringstream &out, TCPSession &sender);
///
/// The Subscription Manager tracks all subscriptions on the server.
///
SubscriptionManager subscriptions;
protected: protected:
/// ///
@ -136,7 +142,6 @@ namespace core {
TCPSession * accept(); TCPSession * accept();
std::mutex lock; std::mutex lock;
SubscriptionManager subscriptions;
}; };

View File

@ -9,6 +9,7 @@ namespace core {
TCPSession::~TCPSession() { TCPSession::~TCPSession() {
server.removeFromSessionList(this); server.removeFromSessionList(this);
server.subscriptions.removeSessionSubscriptions(*this);
coreutils::Log(coreutils::LOG_DEBUG_1) << "Terminating TCPSession level."; coreutils::Log(coreutils::LOG_DEBUG_1) << "Terminating TCPSession level.";
} }
@ -17,8 +18,10 @@ namespace core {
} }
void TCPSession::protocol(coreutils::ZString &data) { void TCPSession::protocol(coreutils::ZString &data) {
if(!server.commands.processRequest(data, *this)) { if(data.getLength() != 0) {
coreutils::Log(coreutils::LOG_DEBUG_1) << "Received data could not be parsed: " << data.str(); if(!server.commands.processRequest(data, *this)) {
coreutils::Log(coreutils::LOG_DEBUG_1) << "Received data could not be parsed: " << data.str();
}
} }
} }
@ -35,33 +38,33 @@ namespace core {
void TCPSession::onDataReceived(coreutils::ZString &data) { void TCPSession::onDataReceived(coreutils::ZString &data) {
if(data.getLength() > 0) { if(data.getLength() > 0) {
lineBuffer = (char *)realloc(lineBuffer, lineBufferSize + data.getLength()); lineBuffer = (char *)realloc(lineBuffer, lineBufferSize + data.getLength());
memcpy(lineBuffer + lineBufferSize, data.getData(), data.getLength()); memcpy(lineBuffer + lineBufferSize, data.getData(), data.getLength());
lineBufferSize += data.getLength(); lineBufferSize += data.getLength();
while(lineBufferSize > 0) { while(lineBufferSize > 0) {
if(blockSize == 0) { if(blockSize == 0) {
lineLength = strcspn(lineBuffer, "\r\n"); lineLength = strcspn(lineBuffer, "\r\n");
if(lineLength == lineBufferSize) if(lineLength == lineBufferSize)
break; break;
coreutils::ZString zLine(lineBuffer, lineLength); coreutils::ZString zLine(lineBuffer, lineLength);
onLineReceived(zLine); onLineReceived(zLine);
if(lineBuffer[lineLength] == '\r') if(lineBuffer[lineLength] == '\r')
++lineLength; ++lineLength;
if(lineBuffer[lineLength] == '\n') if(lineBuffer[lineLength] == '\n')
++lineLength; ++lineLength;
lineBufferSize -= lineLength; lineBufferSize -= lineLength;
if(lineBufferSize > 0) if(lineBufferSize > 0)
memmove(lineBuffer, lineBuffer + lineLength, lineBufferSize); memmove(lineBuffer, lineBuffer + lineLength, lineBufferSize);
lineBuffer = (char *)realloc(lineBuffer, lineBufferSize); lineBuffer = (char *)realloc(lineBuffer, lineBufferSize);
} else if(lineBufferSize >= blockLength) { } else if(lineBufferSize >= blockLength) {
coreutils::ZString zBlock(lineBuffer, blockLength); coreutils::ZString zBlock(lineBuffer, blockLength);
onBlockReceived(zBlock); onBlockReceived(zBlock);
lineBufferSize -= blockLength; lineBufferSize -= blockLength;
if(lineBufferSize > 0) if(lineBufferSize > 0)
memmove(lineBuffer, lineBuffer + blockLength, lineBufferSize); memmove(lineBuffer, lineBuffer + blockLength, lineBufferSize);
lineBuffer = (char *)realloc(lineBuffer, lineBufferSize); lineBuffer = (char *)realloc(lineBuffer, lineBufferSize);
} }
} }
} }
} }
@ -84,7 +87,7 @@ namespace core {
void TCPSession::send() { void TCPSession::send() {
if(out.tellp() > 0) if(out.tellp() > 0)
write(out.str()); write(out.str());
out.str(""); out.str("");
} }

View File

@ -5,7 +5,7 @@ do
filename="${file%.*}" filename="${file%.*}"
list="$list $filename.o" list="$list $filename.o"
echo -n "Compiling $filename..." echo -n "Compiling $filename..."
g++ -g -c -I../CoreUtils $file & g++ -g -c -std=c++17 -I../CoreUtils $file &
if [ $? = '0' ] if [ $? = '0' ]
then then
echo "OK" echo "OK"

Binary file not shown.