Added subscription service capability.
This commit is contained in:
parent
0a03b3553d
commit
ec39c1df1a
12
Command.cpp
12
Command.cpp
@ -12,16 +12,4 @@ namespace core {
|
||||
out << "Write your own command description here for the help system." << std::endl;
|
||||
}
|
||||
|
||||
bool Command::check(coreutils::ZString &request) {
|
||||
return request[0].equals(name);
|
||||
}
|
||||
|
||||
void Command::setName(std::string name) {
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
std::string Command::getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
32
Command.h
32
Command.h
@ -23,22 +23,6 @@ namespace core {
|
||||
|
||||
public:
|
||||
|
||||
///
|
||||
/// Implement check method to provide a special check rule upon the request to see
|
||||
/// if the command should be processed.
|
||||
///
|
||||
/// The default rule is to verify that the first token in the request string matches
|
||||
/// the name given on the registration of the command to the CommandList. This can
|
||||
/// be overridden by implementing the check() method to perform the test and return
|
||||
/// the condition of the command.
|
||||
///
|
||||
/// @param request The request passed to the parser to check the rule.
|
||||
/// @return Return true to execute the command. Returning false will cause no action
|
||||
/// on this command.
|
||||
///
|
||||
|
||||
virtual bool check(coreutils::ZString &request);
|
||||
|
||||
///
|
||||
/// This method is used to implement the functionality of the requested command.
|
||||
/// This pure virtual function must be implemented in your inheriting object.
|
||||
@ -60,22 +44,6 @@ namespace core {
|
||||
|
||||
virtual void output(std::stringstream &out);
|
||||
|
||||
///
|
||||
/// Set the name of this command used in default rule checking during request parsing.
|
||||
/// NOTE: You do not need to call this under normal conditions as adding a Command
|
||||
/// to a CommandList using the add() method contains a parameter to pass the name
|
||||
/// of the Command.
|
||||
///
|
||||
/// @param name Specify the name of this command for default parsing.
|
||||
///
|
||||
|
||||
void setName(std::string name);
|
||||
|
||||
std::string getName();
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -6,8 +6,7 @@ namespace core {
|
||||
CommandList::CommandList(std::string delimiter) : delimiter(delimiter) {}
|
||||
|
||||
void CommandList::add(Command &command, std::string name) {
|
||||
command.setName(name);
|
||||
commands.push_back(&command);
|
||||
commands.insert(std::make_pair(name, &command));
|
||||
}
|
||||
|
||||
void CommandList::remove(Command &command) {}
|
||||
@ -16,9 +15,10 @@ namespace core {
|
||||
if(session.grab != NULL)
|
||||
return session.grab->processCommand(request, session);
|
||||
else {
|
||||
if(request.equals(""))
|
||||
return false;
|
||||
request.split(delimiter);
|
||||
for(auto *command : commands)
|
||||
if(command->check(request))
|
||||
auto command = commands.find(request[0].str())->second;
|
||||
return command->processCommand(request, session);
|
||||
}
|
||||
return false;
|
||||
@ -34,8 +34,8 @@ namespace core {
|
||||
}
|
||||
|
||||
int CommandList::processCommand(coreutils::ZString &request, TCPSession &session) {
|
||||
for(Command *command : commands)
|
||||
session.out << command->getName() << std::endl;
|
||||
// for(Command *command : commands)
|
||||
// session.out << command->getName() << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ namespace core {
|
||||
/// The vector of all registered commands.
|
||||
///
|
||||
|
||||
std::vector<Command *> commands;
|
||||
std::map<std::string, Command *> commands;
|
||||
std::string delimiter;
|
||||
|
||||
};
|
||||
|
@ -167,7 +167,7 @@ namespace core {
|
||||
coreutils::Log(coreutils::LOG_DEBUG_2) << "Shutdown requested on socket " << descriptor << " with reason " << text << ".";
|
||||
shutDown = true;
|
||||
reset = false;
|
||||
if(!needsToWrite())
|
||||
// if(!needsToWrite())
|
||||
delete this;
|
||||
|
||||
}
|
||||
|
2
Socket.h
2
Socket.h
@ -48,7 +48,7 @@ namespace core {
|
||||
/// Destructor
|
||||
///
|
||||
|
||||
~Socket();
|
||||
virtual ~Socket();
|
||||
|
||||
///
|
||||
/// Use the shutdown() method to terminate the socket connection and remove resources.
|
||||
|
38
Subscription.cpp
Normal file
38
Subscription.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "Subscription.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
Subscription::Subscription(std::string id, TCPSession &session) : id(id), owner(&session) {}
|
||||
|
||||
int Subscription::subscribe(TCPSession &session) {
|
||||
subscribers.push_back(&session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Subscription::unsubscribe(TCPSession &session) {
|
||||
for(auto subscriber = subscribers.begin(); subscriber < subscribers.end(); ++subscriber) {
|
||||
if(*subscriber == &session) {
|
||||
subscribers.erase(subscriber);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Subscription::process(coreutils::ZString &request, std::stringstream &out) {
|
||||
out << "event:" << request[1] << ":" << request[2] << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Subscription::event(std::stringstream &out) {
|
||||
for(auto subscriber = subscribers.begin(); subscriber < subscribers.end(); ++subscriber)
|
||||
(*subscriber)->write(out.str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Subscription::processCommand(coreutils::ZString &request, TCPSession &session) {
|
||||
session.out << "Generic subscription passthrough";
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
32
Subscription.h
Normal file
32
Subscription.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef __Subscription_h__
|
||||
#define __Subscription_h__
|
||||
|
||||
#include "TCPSession.h"
|
||||
#include "Command.h"
|
||||
#include "ZString.h"
|
||||
#include <vector>
|
||||
|
||||
namespace core {
|
||||
|
||||
class Subscription : public Command {
|
||||
|
||||
public:
|
||||
Subscription(std::string id, TCPSession &session);
|
||||
|
||||
int subscribe(TCPSession &session);
|
||||
int unsubscribe(TCPSession &session);
|
||||
virtual int process(coreutils::ZString &request, std::stringstream &out);
|
||||
|
||||
int event(std::stringstream &out);
|
||||
|
||||
int processCommand(coreutils::ZString &request, TCPSession &session) override;
|
||||
|
||||
std::string id;
|
||||
TCPSession *owner;
|
||||
|
||||
std::vector<TCPSession *> subscribers;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
56
SubscriptionManager.cpp
Normal file
56
SubscriptionManager.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include "SubscriptionManager.h"
|
||||
#include "Log.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
SubscriptionManager::SubscriptionManager() {}
|
||||
|
||||
int SubscriptionManager::removeSessionSubscriptions(TCPSession &session) {
|
||||
int count = 0;
|
||||
for(auto subscription = subscriptions.begin(); subscription < subscriptions.end(); ++subscription) {
|
||||
count += (*subscription)->unsubscribe(session);
|
||||
}
|
||||
coreutils::Log(coreutils::LOG_DEBUG_2) << "Removed session from " << count << " subscriptions.";
|
||||
return count;
|
||||
}
|
||||
|
||||
int SubscriptionManager::processCommand(coreutils::ZString &request, TCPSession &session) {
|
||||
|
||||
if(request[0].equals("publish")) {
|
||||
subscriptions.push_back(new Subscription(request[1].str(), session));
|
||||
return 1;
|
||||
} else if(request[0].equals("catalog")) {
|
||||
session.out << ":catalog:";
|
||||
for(auto subscription = subscriptions.begin(); subscription < subscriptions.end(); ++subscription) {
|
||||
session.out << (*subscription)->id << "|";
|
||||
(*subscription)->processCommand(request, session);
|
||||
session.out << (";");
|
||||
}
|
||||
session.out << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(auto subscription = subscriptions.begin(); subscription < subscriptions.end(); ++subscription) {
|
||||
if(request[1].equals((*subscription)->id)) {
|
||||
if(request[0].equals("unpublish")) {
|
||||
subscriptions.erase(subscription);
|
||||
} else if(request[0].equals("subscribe")) {
|
||||
(*subscription)->subscribe(session);
|
||||
} else if(request[0].equals("unsubscribe")) {
|
||||
(*subscription)->unsubscribe(session);
|
||||
} else if(request[0].equals("event")) {
|
||||
if((*subscription)->owner == &session) {
|
||||
std::stringstream out;
|
||||
(*subscription)->process(request, out);
|
||||
(*subscription)->event(out);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
27
SubscriptionManager.h
Normal file
27
SubscriptionManager.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef __SubscriptionManager_h__
|
||||
#define __SubscriptionManager_h__
|
||||
|
||||
#include "TCPSession.h"
|
||||
#include "Subscription.h"
|
||||
#include "Command.h"
|
||||
#include "ZString.h"
|
||||
#include <vector>
|
||||
|
||||
namespace core {
|
||||
|
||||
class SubscriptionManager : public Command {
|
||||
|
||||
public:
|
||||
SubscriptionManager();
|
||||
|
||||
int removeSessionSubscriptions(TCPSession &session);
|
||||
|
||||
int processCommand(coreutils::ZString &request, TCPSession &session) override;
|
||||
|
||||
private:
|
||||
std::vector<Subscription *> subscriptions;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -9,6 +9,13 @@ namespace core {
|
||||
TCPServer::TCPServer(EPoll &ePoll, IPAddress address, std::string delimiter, std::string text)
|
||||
: TCPSocket(ePoll, text), commands(delimiter) {
|
||||
|
||||
commands.add(subscriptions, "publish");
|
||||
commands.add(subscriptions, "unpublish");
|
||||
commands.add(subscriptions, "subscribe");
|
||||
commands.add(subscriptions, "unsubscribe");
|
||||
commands.add(subscriptions, "catalog");
|
||||
commands.add(subscriptions, "event");
|
||||
|
||||
setDescriptor(socket(AF_INET, SOCK_STREAM, 0));
|
||||
int yes = 1;
|
||||
setsockopt(getDescriptor(), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "IPAddressList.h"
|
||||
#include "Command.h"
|
||||
#include "CommandList.h"
|
||||
#include "SubscriptionManager.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@ -40,7 +41,7 @@ namespace core {
|
||||
/// The destructor for this object.
|
||||
///
|
||||
|
||||
~TCPServer();
|
||||
virtual ~TCPServer();
|
||||
|
||||
virtual void sessionErrorHandler(std::string errorString, std::stringstream &out);
|
||||
|
||||
@ -135,6 +136,7 @@ namespace core {
|
||||
|
||||
TCPSession * accept();
|
||||
std::mutex lock;
|
||||
SubscriptionManager subscriptions;
|
||||
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,7 @@ namespace core {
|
||||
|
||||
TCPSession::~TCPSession() {
|
||||
server.removeFromSessionList(this);
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << "Terminating TCPSession level.";
|
||||
}
|
||||
|
||||
void TCPSession::output(std::stringstream &data) {
|
||||
@ -17,7 +18,7 @@ namespace core {
|
||||
|
||||
void TCPSession::protocol(coreutils::ZString &data) {
|
||||
if(!server.commands.processRequest(data, *this)) {
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << data.str();
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << "Received data could not be parsed: " << data.str();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace core {
|
||||
///
|
||||
///
|
||||
|
||||
~TCPSession();
|
||||
virtual ~TCPSession();
|
||||
|
||||
Command *grab = NULL;
|
||||
|
||||
|
@ -23,7 +23,7 @@ namespace core {
|
||||
|
||||
TCPSocket(EPoll &ePoll);
|
||||
TCPSocket(EPoll &ePoll, std::string text);
|
||||
~TCPSocket();
|
||||
virtual ~TCPSocket();
|
||||
|
||||
void connect(IPAddress &address);
|
||||
|
||||
|
@ -4,5 +4,9 @@
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
"settings": {
|
||||
"files.associations": {
|
||||
"iosfwd": "c"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user