Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
275c7298ee | ||
|
|
b5f4947f7c | ||
|
|
1d16d0c17f | ||
|
|
4230734ee6 | ||
|
|
57f47fdecb | ||
|
|
3a75e920d9 | ||
|
|
9a39b6224c |
No files matched your search
+7
-4
@@ -1,14 +1,17 @@
|
||||
#include "Command.h"
|
||||
#include "Log.h"
|
||||
#include "CommandList.h"
|
||||
#include "Log.h"
|
||||
|
||||
namespace core {
|
||||
namespace core
|
||||
{
|
||||
|
||||
int Command::processCommand(coreutils::ZString &request, TCPSession &session) {
|
||||
int Command::processCommand(coreutils::ZString &request, TCPSession &session)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Command::output(std::stringstream &out) {
|
||||
void Command::output(std::stringstream &out)
|
||||
{
|
||||
out << "Write your own command description here for the help system." << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#ifndef __Command_h__
|
||||
#define __Command_h__
|
||||
|
||||
#include "includes"
|
||||
#include "Object.h"
|
||||
#include "TCPSession.h"
|
||||
#include "ZString.h"
|
||||
#include "includes"
|
||||
|
||||
namespace core {
|
||||
namespace core
|
||||
{
|
||||
|
||||
class CommandList;
|
||||
|
||||
@@ -15,22 +16,22 @@ namespace core {
|
||||
///
|
||||
/// Command
|
||||
///
|
||||
/// Use the Command object in combination with a CommandList object to maintain
|
||||
/// Use the Command object in combination with a CommandList object to maintain
|
||||
/// a list of functions that can be invoked as a result of processing a request.
|
||||
///
|
||||
|
||||
class Command {
|
||||
|
||||
public:
|
||||
class Command
|
||||
{
|
||||
|
||||
public:
|
||||
///
|
||||
/// This method is used to implement the functionality of the requested command.
|
||||
/// This pure virtual function must be implemented in your inheriting object.
|
||||
/// This pure virtual function must be implemented in your inheriting object.
|
||||
///
|
||||
/// @param request The request that was entered by the user to invoke this command.
|
||||
/// @param session Specify the requesting session so that the execution of the
|
||||
/// @param session Specify the requesting session so that the execution of the
|
||||
/// command process can return its output to the session.
|
||||
/// @return Returns 0 if execution of the command was successful. Otherwise returns
|
||||
/// @return Returns 0 if execution of the command was successful. Otherwise returns
|
||||
/// a non-zero value indicating an error condition.
|
||||
///
|
||||
|
||||
@@ -43,7 +44,6 @@ namespace core {
|
||||
///
|
||||
|
||||
virtual void output(std::stringstream &out);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+10
-21
@@ -48,17 +48,6 @@ namespace core
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
void Socket::setBufferSize(int length)
|
||||
{
|
||||
this->length = length;
|
||||
buffer = (char *)realloc(buffer, length);
|
||||
}
|
||||
|
||||
int Socket::getBufferSize()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
void Socket::onRegister() {}
|
||||
|
||||
void Socket::onRegistered() {}
|
||||
@@ -70,8 +59,8 @@ namespace core
|
||||
bool Socket::eventReceived(struct epoll_event event, long long eventId) {
|
||||
// coreutils::Log(coreutils::LOG_DEBUG_1) << "Event process beginning for socket " << getDescriptor();
|
||||
if(inHandler)
|
||||
// coreutils::Log(coreutils::LOG_DEBUG_2) << "inHandler was already true.";
|
||||
inHandler = true;
|
||||
// coreutils::Log(coreutils::LOG_DEBUG_2) << "inHandler was already true.";
|
||||
inHandler = true;
|
||||
if(event.events & EPOLLRDHUP) {
|
||||
// coreutils::Log(coreutils::LOG_DEBUG_2) << "EPOLLRDHUP";
|
||||
readHangup = true;
|
||||
@@ -79,9 +68,8 @@ namespace core
|
||||
}
|
||||
if(event.events & EPOLLIN) {
|
||||
// coreutils::Log(coreutils::LOG_DEBUG_2) << "EPOLLIN";
|
||||
coreutils::ZString zbuffer(buffer, length);
|
||||
lock.lock();
|
||||
receiveData(zbuffer);
|
||||
receiveDataNotification();
|
||||
if(!shutDown) {
|
||||
inHandler = false;
|
||||
lock.unlock();
|
||||
@@ -99,18 +87,19 @@ namespace core
|
||||
return !shutDown;
|
||||
}
|
||||
|
||||
void Socket::onDataReceived(std::string data)
|
||||
{
|
||||
void Socket::onDataReceived(std::string data) {
|
||||
throw coreutils::Exception("Need to override onDataReceived.", __FILE__, __LINE__, -1);
|
||||
}
|
||||
|
||||
void Socket::onDataReceived(coreutils::ZString &data)
|
||||
{
|
||||
void Socket::onDataReceived(coreutils::ZString &data) {
|
||||
onDataReceived(std::string(data.getData(), data.getLength()));
|
||||
}
|
||||
|
||||
void Socket::receiveData(coreutils::ZString &buffer) {
|
||||
coreutils::ZString blank("");
|
||||
void Socket::receiveDataNotification() {}
|
||||
|
||||
|
||||
|
||||
coreutils::ZString blank("");
|
||||
if(buffer.getLength() <= 0)
|
||||
throw coreutils::Exception("Request to receive data with a zero buffer length.", __FILE__, __LINE__, -1);
|
||||
int len;
|
||||
|
||||
@@ -124,10 +124,6 @@ namespace core {
|
||||
|
||||
EPoll &ePoll; // The EPoll control object.
|
||||
|
||||
void setBufferSize(int length);
|
||||
|
||||
int getBufferSize();
|
||||
|
||||
///
|
||||
/// The onConnected method is called when the socket is ready to communicate.
|
||||
/// Writing to the socket can begin on this call to initiate a contact with the
|
||||
@@ -143,27 +139,10 @@ namespace core {
|
||||
// virtual void onDisconnected(); ///< Called when socket is closing and no longer ready to communicate.
|
||||
|
||||
///
|
||||
/// The onDataReceived method is called when the socket has received an event from
|
||||
/// epoll and there is data ready to be read from the socket. The default handler
|
||||
/// will pull the data and put it into the streambuf for the socket. EPOLLIN
|
||||
///
|
||||
/// @param data the data that has been received from the socket.
|
||||
/// This method is called when data is ready to be read from the socket.
|
||||
///
|
||||
|
||||
virtual void onDataReceived(std::string data); ///< Called when data is received from the socket.
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
|
||||
virtual void onDataReceived(coreutils::ZString &data);
|
||||
|
||||
///
|
||||
/// receiveData will read the data from the socket and place it in the socket buffer.
|
||||
/// TLS layer overrides this to be able to read from SSL.
|
||||
///
|
||||
|
||||
virtual void receiveData(coreutils::ZString &buffer);
|
||||
virtual void readDataNotification();
|
||||
|
||||
private:
|
||||
|
||||
@@ -171,7 +150,7 @@ namespace core {
|
||||
int descriptor = -1;
|
||||
std::mutex outlock;
|
||||
bool readHangup = false;
|
||||
volatile bool inHandler = false;
|
||||
volatile bool inHandler = false;
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
// the writeSocket is called when epoll has received a write request for a socket.
|
||||
@@ -187,9 +166,6 @@ namespace core {
|
||||
// int_type pbackfail(int_type ch);
|
||||
// streamsize showmanyc();
|
||||
|
||||
char *buffer; // This is a pointer to the managed buffer space.
|
||||
int length; // This is the length of the buffer.
|
||||
|
||||
std::queue<std::string> fifo;
|
||||
|
||||
void resetSocket();
|
||||
|
||||
+34
-23
@@ -1,23 +1,29 @@
|
||||
#include "Subscription.h"
|
||||
#include "Log.h"
|
||||
#include "MString.h"
|
||||
#include "TCPSession.h"
|
||||
#include "TCPSocket.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace core {
|
||||
|
||||
Subscription::Subscription(std::string id, std::string mode)
|
||||
: id(id), mode(mode), owner(NULL), handler(NULL) {}
|
||||
Subscription::Subscription(coreutils::MString id, coreutils::MString mode)
|
||||
: id(id), mode(mode), owner(""), handler(NULL) {}
|
||||
|
||||
Subscription::Subscription(std::string id, TCPSession &session, std::string mode)
|
||||
: id(id), mode(mode), owner(&session), handler(NULL) {}
|
||||
Subscription::Subscription(coreutils::MString id, coreutils::MString owner, coreutils::MString mode)
|
||||
: id(id), mode(mode), owner(owner), handler(NULL) {}
|
||||
|
||||
Subscription::Subscription(std::string id, TCPSession &session, std::string mode, SubscriptionHandler *handler)
|
||||
: id(id), mode(mode), owner(&session), handler(handler) {
|
||||
// coreutils::Log(coreutils::LOG_DEBUG_3) << "Subscription '" << id << "' with handler '" << handler->name << "'";
|
||||
}
|
||||
Subscription::Subscription(coreutils::MString id, coreutils::MString owner, coreutils::MString ownership, coreutils::MString mode, SubscriptionHandler *handler, coreutils::MString will, coreutils::MString timer)
|
||||
: id(id), ownership(ownership), mode(mode), owner(owner), handler(handler), will(will), timer(timer) {
|
||||
coreutils::Log(coreutils::LOG_DEBUG_3) << owner;
|
||||
coreutils::Log(coreutils::LOG_DEBUG_3) << will;
|
||||
subscriptionOwner(owner, will);
|
||||
}
|
||||
|
||||
Subscription::~Subscription() {
|
||||
|
||||
std::stringstream out;
|
||||
|
||||
out << "cancel:" << id << std::endl;
|
||||
for (auto subscriber : subscribers) {
|
||||
subscriber->write(out.str());
|
||||
@@ -26,24 +32,30 @@ namespace core {
|
||||
|
||||
int Subscription::subscribe(TCPSession &session) {
|
||||
if (handler)
|
||||
handler->onSubscribe(session, this);
|
||||
handler->onSubscribe(session, this);
|
||||
else
|
||||
onSubscribe(session);
|
||||
|
||||
subscribers.push_back(&session);
|
||||
onSubscribe(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;
|
||||
}
|
||||
}
|
||||
for (auto subscriber = subscribers.begin(); subscriber < subscribers.end(); ++subscriber)
|
||||
if (*subscriber == &session) {
|
||||
subscribers.erase(subscriber++);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Subscription::subscriptionOwner(coreutils::MString alias, coreutils::MString ownerSelection) {
|
||||
subscriptionOwners = alias;
|
||||
selectionOfOwnerForSubscription = ownerSelection;
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << "Owner of Subscription: " << subscriptionOwners;
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << "Will of Subscription: " << selectionOfOwnerForSubscription;
|
||||
return true;
|
||||
}
|
||||
|
||||
int Subscription::process(coreutils::ZString &request, std::stringstream &out, TCPSession &session) {
|
||||
if (handler)
|
||||
handler->process(request, out, session, this);
|
||||
@@ -53,8 +65,8 @@ namespace core {
|
||||
}
|
||||
|
||||
int Subscription::event(std::stringstream &out) {
|
||||
for (auto subscriber = subscribers.begin(); subscriber < subscribers.end(); ++subscriber)
|
||||
(*subscriber)->write(out.str());
|
||||
for (auto subscriber = subscribers.begin(); subscriber < subscribers.end(); ++subscriber)
|
||||
(*subscriber)->write(out.str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -72,10 +84,9 @@ namespace core {
|
||||
|
||||
void Subscription::sendToAll(std::stringstream &data, TCPSession &sender) {
|
||||
for (auto session : subscribers)
|
||||
if (session != &sender)
|
||||
session->write(data.str());
|
||||
if (session != &sender)
|
||||
session->write(data.str());
|
||||
data.str("");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+17
-12
@@ -1,23 +1,23 @@
|
||||
#ifndef __Subscription_h__
|
||||
#define __Subscription_h__
|
||||
|
||||
#include "SubscriptionHandler.h"
|
||||
#include "MString.h"
|
||||
#include "SessionFilter.h"
|
||||
#include "SubscriptionHandler.h"
|
||||
#include "ZString.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace core
|
||||
{
|
||||
namespace core {
|
||||
|
||||
class TCPSession;
|
||||
|
||||
class Subscription {
|
||||
|
||||
public:
|
||||
Subscription(std::string id, std::string mode = "*AUTHOR");
|
||||
Subscription(std::string id, TCPSession &session, std::string mode);
|
||||
Subscription(std::string id, TCPSession &session, std::string mode, SubscriptionHandler *handler);
|
||||
public:
|
||||
Subscription(coreutils::MString id, coreutils::MString mode = "*AUTHOR");
|
||||
Subscription(coreutils::MString id, coreutils::MString owner, coreutils::MString mode);
|
||||
Subscription(coreutils::MString id, coreutils::MString owner, coreutils::MString ownership, coreutils::MString mode, SubscriptionHandler *handler, coreutils::MString selection, coreutils::MString time);
|
||||
virtual ~Subscription();
|
||||
|
||||
int subscribe(TCPSession &session);
|
||||
@@ -28,7 +28,7 @@ namespace core
|
||||
virtual int onSubscribe(TCPSession &session);
|
||||
|
||||
int event(std::stringstream &out);
|
||||
|
||||
bool subscriptionOwner(coreutils::MString owner, coreutils::MString selection);
|
||||
bool ifSubscriber(TCPSession &session);
|
||||
|
||||
bool subInvite(TCPSession &session);
|
||||
@@ -36,13 +36,18 @@ namespace core
|
||||
void sendToAll(std::stringstream &data, TCPSession &sender);
|
||||
void sendToAll(std::stringstream &data, TCPSession &sender, SessionFilter filter);
|
||||
|
||||
std::string id;
|
||||
std::string mode;
|
||||
TCPSession *owner;
|
||||
|
||||
coreutils::MString id;
|
||||
coreutils::MString mode;
|
||||
coreutils::MString owner;
|
||||
coreutils::MString subscriptionOwners;
|
||||
coreutils::MString selectionOfOwnerForSubscription;
|
||||
coreutils::MString will;
|
||||
coreutils::MString ownership;
|
||||
coreutils::MString timer;
|
||||
SubscriptionHandler *handler;
|
||||
|
||||
std::vector<TCPSession *> subscribers;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+59
-33
@@ -1,9 +1,9 @@
|
||||
#include "SubscriptionManager.h"
|
||||
#include "Log.h"
|
||||
#include "Subscription.h"
|
||||
#include "SubscriptionHandlerFactory.h"
|
||||
#include "TCPServer.h"
|
||||
#include <algorithm>
|
||||
#include "SubscriptionHandlerFactory.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -14,29 +14,51 @@ namespace core {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool SubscriptionManager::onClearSubscription(coreutils::MString temp, coreutils::MString key) {
|
||||
temp = "";
|
||||
key = "";
|
||||
return true;
|
||||
}
|
||||
|
||||
int SubscriptionManager::removeSessionSubscriptions(TCPSession &session) {
|
||||
int countSubscribed = 0;
|
||||
int countPublished = 0;
|
||||
int count = 0;
|
||||
|
||||
lock.lock();
|
||||
std::string temp = "";
|
||||
for (auto [key, subscription] : subscriptions)
|
||||
{
|
||||
if (temp != "")
|
||||
{
|
||||
coreutils::MString temp = "";
|
||||
for (auto [key, subscription] : subscriptions) {
|
||||
if (temp != "") {
|
||||
subscriptions.erase(temp);
|
||||
temp = "";
|
||||
}
|
||||
countSubscribed += subscription->unsubscribe(session);
|
||||
if (subscription->owner == &session)
|
||||
{
|
||||
temp = key;
|
||||
delete subscription;
|
||||
if (subscription->subscriptionOwners == session.alias) {
|
||||
if (subscription->selectionOfOwnerForSubscription == "*DIE") {
|
||||
onClearSubscription(temp, key);
|
||||
}
|
||||
|
||||
else if (subscription->will == "*NEXT") {
|
||||
if (subscription->subscribers.size() < 1) {
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << "There is not enough people to move to the next";
|
||||
onClearSubscription(temp, key);
|
||||
}
|
||||
else {
|
||||
for (auto subscribed = subscription->subscribers.begin(); subscribed < subscription->subscribers.end(); subscribed++) {
|
||||
if ((*subscribed)->alias == session.alias) {
|
||||
subscription->subscribers.erase(subscribed++);
|
||||
}
|
||||
subscription->subscriptionOwner(session.alias, "*NEXT");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << "Subscription doesn't exist";
|
||||
}
|
||||
++countPublished;
|
||||
}
|
||||
}
|
||||
if (temp != "")
|
||||
{
|
||||
if (temp != "") {
|
||||
subscriptions.erase(temp);
|
||||
temp = "";
|
||||
}
|
||||
@@ -47,29 +69,34 @@ namespace core {
|
||||
}
|
||||
|
||||
int SubscriptionManager::processCommand(coreutils::ZString &request, TCPSession &session) {
|
||||
if (request[0].equals("publish")) {
|
||||
if (request[0] == "publish") {
|
||||
SubscriptionHandler *handler = NULL;
|
||||
if(request.getList().size() > 3) {
|
||||
factory->getSubscriptionHandler(request[3].str());
|
||||
if (request.getList().size() > 3) {
|
||||
handler = factory->getSubscriptionHandler(request[4].str());
|
||||
}
|
||||
newSubscription = new Subscription(request[1].str(), session, request[2].str(), handler);
|
||||
subscriptions.insert(std::make_pair(request[1].str(), newSubscription));
|
||||
newSubscription->owner = &session;
|
||||
if (request[2] == "*OWNER") {
|
||||
newSubscription = new Subscription(request[1].str(), session.alias, request[2].str(), request[3].str(), handler, request[5].str(), request[6].str());
|
||||
subscriptions.insert(std::make_pair(request[1].str(), newSubscription));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else if (request[0].equals("catalog")) {
|
||||
}
|
||||
else if (request[0] == "catalog") {
|
||||
session.out << ":catalog:";
|
||||
for (auto const &[key, subscription] : subscriptions) {
|
||||
session.out << subscription->id << ";";
|
||||
}
|
||||
session.out << std::endl;
|
||||
return 1;
|
||||
} else if (request[0].equals("invite")) {
|
||||
}
|
||||
else if (request[0] == "invite") {
|
||||
std::stringstream out;
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << request[2];
|
||||
std::string invitee = request[2].str();
|
||||
TCPSession *tempSession = session.server.getSessionByAlias(&invitee);
|
||||
invitee = (coreutils::MString *)&request[2];
|
||||
TCPSession *tempSession = session.server.getSessionByAlias(invitee);
|
||||
std::stringstream temp;
|
||||
temp << "invite:" << request[1] << ":" << *(std::string *)session.alias;
|
||||
temp << "invite:" << request[1] << ":" << invitee;
|
||||
tempSession->write(temp.str());
|
||||
return 1;
|
||||
}
|
||||
@@ -77,30 +104,29 @@ namespace core {
|
||||
auto subscription = subscriptions[request[1].str()];
|
||||
|
||||
if (request[1].equals(subscription->id)) {
|
||||
if (request[0].equals("unpublish")) {
|
||||
if (request[0] == "unpublish") {
|
||||
subscriptions.erase(request[1].str());
|
||||
} else if (request[0].equals("subscribe")) {
|
||||
}
|
||||
else if (request[0] == "subscribe") {
|
||||
subscription->subscribe(session);
|
||||
return 1;
|
||||
} else if (request[0].equals("unsubscribe")) {
|
||||
}
|
||||
else if (request[0] == "unsubscribe") {
|
||||
subscription->unsubscribe(session);
|
||||
return 1;
|
||||
} else if (request[0].equals("event")) {
|
||||
}
|
||||
else if (request[0] == "event") {
|
||||
std::stringstream out;
|
||||
subscription->process(request, out, session);
|
||||
if (subscription->mode == "*ANYONE") {
|
||||
subscription->event(out);
|
||||
return 1;
|
||||
} else if (subscription->mode == "*SUBSCRIBERS") {
|
||||
}
|
||||
else if (subscription->mode == "*SUBSCRIBERS") {
|
||||
if (subscription->ifSubscriber(session)) {
|
||||
subscription->event(out);
|
||||
return 1;
|
||||
}
|
||||
} else if (subscription->mode == "*AUTHOR") {
|
||||
if (subscription->owner == &session) {
|
||||
subscription->event(out);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
+22
-15
@@ -2,33 +2,40 @@
|
||||
#define __SubscriptionManager_h__
|
||||
|
||||
#include "Command.h"
|
||||
#include "MString.h"
|
||||
#include "SessionFilter.h"
|
||||
#include "Subscription.h"
|
||||
#include "SubscriptionHandler.h"
|
||||
#include "TCPSession.h"
|
||||
#include "ZString.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace core {
|
||||
|
||||
class SubscriptionHandlerFactory;
|
||||
//*AUTHOR -> Dies when player disconnects
|
||||
//*ANYONE -> Does not die when player disconnects
|
||||
//*SUBSCRIPTION -> Does not die when player disconnects
|
||||
//*OWNER -> Does die and transfers Ownership before he does
|
||||
|
||||
class SubscriptionManager : public Command {
|
||||
class SubscriptionHandlerFactory;
|
||||
|
||||
public:
|
||||
class SubscriptionManager : public Command {
|
||||
|
||||
int add(Subscription &subscription);
|
||||
int removeSessionSubscriptions(TCPSession &session);
|
||||
int processCommand(coreutils::ZString &request, TCPSession &session) override;
|
||||
public:
|
||||
int add(Subscription &subscription);
|
||||
int removeSessionSubscriptions(TCPSession &session);
|
||||
int processCommand(coreutils::ZString &request, TCPSession &session) override;
|
||||
bool onClearSubscription(coreutils::MString temp, coreutils::MString key);
|
||||
SubscriptionHandlerFactory *factory = NULL;
|
||||
|
||||
SubscriptionHandlerFactory *factory = NULL;
|
||||
|
||||
private:
|
||||
Subscription *subscription;
|
||||
std::map<std::string, Subscription *> subscriptions;
|
||||
Subscription *newSubscription;
|
||||
std::mutex lock;
|
||||
};
|
||||
private:
|
||||
Subscription *subscription;
|
||||
std::map<coreutils::MString, Subscription *> subscriptions;
|
||||
Subscription *newSubscription;
|
||||
std::mutex lock;
|
||||
coreutils::MString invitee;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "TCPLineBufferParser.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
TCPLineBufferParser::TCPLineBufferParser() {
|
||||
buffer = nullptr;
|
||||
bufferSize = 4096;
|
||||
buffer = realloc(buffer, bufferSize);
|
||||
cursor = buffer;
|
||||
}
|
||||
|
||||
void TCPLineBufferParser::readDataNotification() {
|
||||
|
||||
len = ::read(getDescriptor(), buffer, bufferSize);
|
||||
|
||||
for(unsigned int index = 0; index < bufferSize; ++index) {
|
||||
if(cursor[index] == '\n') {
|
||||
coreutils::ZString data(cursor, index);
|
||||
dataReceived(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void TCPLineBufferParser::onDataReceived(coreutils::ZString data) {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#ifndef __TCPLineBufferParser_h__
|
||||
#define __TCPLineBufferParser_h__
|
||||
|
||||
#include "TCPSocket.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
///
|
||||
/// TCPLineBufferParser
|
||||
///
|
||||
/// This object will read lines of data from the source one line at a time.
|
||||
///
|
||||
///
|
||||
|
||||
class TCPLineBufferParser : public TCPSocket {
|
||||
|
||||
protected:
|
||||
|
||||
///
|
||||
/// This method is called when a line is ready to be processed.
|
||||
///
|
||||
|
||||
virtual void onDataReceived();
|
||||
|
||||
private:
|
||||
|
||||
///
|
||||
/// Read the data for the socket and split into lines and call dataReceived
|
||||
/// for each line parsed.
|
||||
///
|
||||
|
||||
void readDataNotification() override;
|
||||
|
||||
char *buffer;
|
||||
size_t bufferSize;
|
||||
char *cursor;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+27
-19
@@ -8,7 +8,8 @@ namespace core
|
||||
{
|
||||
|
||||
TCPServer::TCPServer(EPoll &ePoll, IPAddress address, std::string delimiter, int depth, std::string text)
|
||||
: TCPSocket(ePoll, text), commands(delimiter, depth) {
|
||||
: TCPSocket(ePoll, text), commands(delimiter, depth)
|
||||
{
|
||||
|
||||
commands.add(subscriptions, "publish");
|
||||
commands.add(subscriptions, "unpublish");
|
||||
@@ -35,7 +36,8 @@ namespace core
|
||||
close(getDescriptor());
|
||||
}
|
||||
|
||||
void TCPServer::onDataReceived(std::string data) {
|
||||
void TCPServer::onDataReceived(std::string data)
|
||||
{
|
||||
lock.lock();
|
||||
TCPSession *session = accept();
|
||||
if (session)
|
||||
@@ -43,9 +45,11 @@ namespace core
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
TCPSession * TCPServer::accept() {
|
||||
TCPSession *TCPServer::accept()
|
||||
{
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
|
||||
TCPSession *session = getSocketAccept(ePoll);
|
||||
session->setDescriptor(::accept(getDescriptor(), (struct sockaddr *)&session->ipAddress.addr, &session->ipAddress.addressLength));
|
||||
@@ -72,30 +76,36 @@ namespace core
|
||||
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)
|
||||
if(*cursor == session) {
|
||||
sessions.erase(cursor);
|
||||
break;
|
||||
}
|
||||
for (cursor = sessions.begin(); cursor < sessions.end(); ++cursor)
|
||||
if (*cursor == session)
|
||||
{
|
||||
sessions.erase(cursor);
|
||||
break;
|
||||
}
|
||||
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) {
|
||||
TCPSession *TCPServer::getSocketAccept(EPoll &ePoll)
|
||||
{
|
||||
return new TCPSession(ePoll, *this);
|
||||
}
|
||||
|
||||
void TCPServer::output(std::stringstream &out) {
|
||||
void TCPServer::output(std::stringstream &out)
|
||||
{
|
||||
out << "Use the 'help' command to list the commands for this server." << std::endl;
|
||||
}
|
||||
|
||||
int TCPServer::processCommand(coreutils::ZString &request, TCPSession &session) {
|
||||
int TCPServer::processCommand(coreutils::ZString &request, TCPSession &session)
|
||||
{
|
||||
int sequence = 0;
|
||||
for (auto *sessionx : sessions)
|
||||
{
|
||||
@@ -130,12 +140,10 @@ namespace core
|
||||
data.str("");
|
||||
}
|
||||
|
||||
TCPSession *TCPServer::getSessionByAlias(void *alias)
|
||||
{
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << alias;
|
||||
TCPSession *TCPServer::getSessionByAlias(coreutils::MString alias) {
|
||||
for (auto session : sessions)
|
||||
if (session->compareAlias(alias))
|
||||
return session;
|
||||
if (session->alias == alias)
|
||||
return session;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -122,7 +122,7 @@ namespace core
|
||||
/// of the alias pointer.
|
||||
///
|
||||
|
||||
TCPSession *getSessionByAlias(void *alias);
|
||||
TCPSession *getSessionByAlias(coreutils::MString alias);
|
||||
|
||||
protected:
|
||||
///
|
||||
|
||||
+22
-41
@@ -4,52 +4,38 @@
|
||||
#include "TCPServer.h"
|
||||
#include "uuid/uuid.h"
|
||||
|
||||
namespace core
|
||||
{
|
||||
namespace core {
|
||||
|
||||
TCPSession::TCPSession(EPoll &ePoll, TCPServer &server, std::string text) : TCPSocket(ePoll, text), server(server)
|
||||
{
|
||||
uuid_t uuidObject;
|
||||
uuid_generate(uuidObject);
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << uuidObject;
|
||||
alias = (void *)uuidObject;
|
||||
TCPSession::TCPSession(EPoll &ePoll, TCPServer &server, std::string text) : TCPSocket(ePoll, text), server(server) {
|
||||
uuid_t uuid;
|
||||
uuid_generate(uuid);
|
||||
alias = coreutils::MString((char *)uuid, 26);
|
||||
}
|
||||
|
||||
TCPSession::~TCPSession()
|
||||
{
|
||||
TCPSession::~TCPSession() {
|
||||
server.removeFromSessionList(this);
|
||||
server.subscriptions.removeSessionSubscriptions(*this);
|
||||
}
|
||||
|
||||
void TCPSession::output(std::stringstream &data)
|
||||
{
|
||||
void TCPSession::output(std::stringstream &data) {
|
||||
data << "|" << ipAddress.getClientAddressAndPort();
|
||||
}
|
||||
|
||||
void TCPSession::protocol(coreutils::ZString &data)
|
||||
{
|
||||
if (data.getLength() != 0)
|
||||
{
|
||||
if (!server.commands.processRequest(data, *this))
|
||||
{
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << "Received data could not be parsed: " << data.str();
|
||||
}
|
||||
}
|
||||
void TCPSession::protocol(coreutils::ZString &data) {
|
||||
if (data.getLength() != 0)
|
||||
if (!server.commands.processRequest(data, *this))
|
||||
coreutils::Log(coreutils::LOG_DEBUG_1) << "Received data could not be parsed: " << data.str();
|
||||
}
|
||||
|
||||
bool TCPSession::compareAlias(void *alias) {
|
||||
return this->alias = alias;
|
||||
}
|
||||
|
||||
void TCPSession::outputAlias(std::stringstream &out) {
|
||||
out << alias;
|
||||
}
|
||||
// bool TCPSession::compareAlias(coreutils::MString alias) {
|
||||
// return this->alias == alias;
|
||||
// }
|
||||
|
||||
void TCPSession::onRegistered() {
|
||||
onConnected();
|
||||
send();
|
||||
if (term)
|
||||
shutdown("termination requested");
|
||||
shutdown("termination requested");
|
||||
}
|
||||
|
||||
void TCPSession::onConnected() {}
|
||||
@@ -75,8 +61,7 @@ namespace core
|
||||
memmove(lineBuffer, lineBuffer + lineLength, lineBufferSize);
|
||||
lineBuffer = (char *)realloc(lineBuffer, lineBufferSize);
|
||||
}
|
||||
else if (lineBufferSize >= blockLength)
|
||||
{
|
||||
else if (lineBufferSize >= blockLength) {
|
||||
coreutils::ZString zBlock(lineBuffer, blockLength);
|
||||
onBlockReceived(zBlock);
|
||||
lineBufferSize -= blockLength;
|
||||
@@ -88,34 +73,30 @@ namespace core
|
||||
}
|
||||
}
|
||||
|
||||
void TCPSession::setBlockSize(int blockSize)
|
||||
{
|
||||
void TCPSession::setBlockSize(int blockSize) {
|
||||
this->blockSize = blockSize;
|
||||
}
|
||||
|
||||
void TCPSession::onLineReceived(coreutils::ZString &line)
|
||||
{
|
||||
void TCPSession::onLineReceived(coreutils::ZString &line) {
|
||||
protocol(line);
|
||||
send();
|
||||
if (term)
|
||||
shutdown("termination requested");
|
||||
}
|
||||
|
||||
void TCPSession::onBlockReceived(coreutils::ZString &block)
|
||||
{
|
||||
void TCPSession::onBlockReceived(coreutils::ZString &block) {
|
||||
coreutils::Log(coreutils::LOG_DEBUG_3) << "[" << block.getLength() << "]";
|
||||
if (term)
|
||||
shutdown("termination requested");
|
||||
}
|
||||
|
||||
void TCPSession::send() {
|
||||
if(out.tellp() > 0)
|
||||
write(out.str());
|
||||
if (out.tellp() > 0)
|
||||
write(out.str());
|
||||
out.str("");
|
||||
}
|
||||
|
||||
void TCPSession::terminate()
|
||||
{
|
||||
void TCPSession::terminate() {
|
||||
term = true;
|
||||
}
|
||||
|
||||
|
||||
+13
-29
@@ -1,11 +1,12 @@
|
||||
#ifndef __Session_h__
|
||||
#define __Session_h__
|
||||
|
||||
#include "TCPLineBufferParser.h"
|
||||
#include "MString.h"
|
||||
#include "SessionFilter.h"
|
||||
#include "TCPSocket.h"
|
||||
|
||||
namespace core
|
||||
{
|
||||
namespace core {
|
||||
|
||||
class Command;
|
||||
class TCPServer;
|
||||
@@ -22,8 +23,7 @@ namespace core
|
||||
///
|
||||
///
|
||||
|
||||
class TCPSession : public TCPSocket
|
||||
{
|
||||
class TCPSession : public TCPLineBufferParser {
|
||||
|
||||
public:
|
||||
///
|
||||
@@ -76,20 +76,20 @@ namespace core
|
||||
char uuid[37];
|
||||
|
||||
///
|
||||
/// alias is a void pointer that can be set to point to any object that identifies
|
||||
/// this session uniquely. Using this approach, inheriting objects can determine
|
||||
/// how it knows the contacts that this server manages.
|
||||
/// alias is a MString that can be set to any string of characters that identifies
|
||||
/// this session uniquely. Alias's should be unique between sessions.
|
||||
///
|
||||
|
||||
void *alias;
|
||||
coreutils::MString alias;
|
||||
///
|
||||
///
|
||||
///
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
|
||||
virtual bool compareAlias(void *alias);
|
||||
|
||||
virtual void outputAlias(std::stringstream &out);
|
||||
// bool compareAlias(coreutils::MString alias);
|
||||
|
||||
protected:
|
||||
///
|
||||
@@ -103,7 +103,8 @@ namespace core
|
||||
/// received. If you need data split by line termination characters then
|
||||
/// override the onLineReceived method instead.
|
||||
///
|
||||
virtual void onDataReceived(coreutils::ZString &data) override;
|
||||
|
||||
void onDataReceived(coreutils::ZString &data) override;
|
||||
|
||||
///
|
||||
/// Override the onLineReceived method to receive a string of characters that
|
||||
@@ -112,23 +113,6 @@ namespace core
|
||||
/// this method explicitly using the class and member name.
|
||||
///
|
||||
|
||||
virtual void onLineReceived(coreutils::ZString &line);
|
||||
|
||||
///
|
||||
/// Override the onBlockReceived method to receive a string of characters that
|
||||
/// represents a single block of data of length determined by the block length value. If
|
||||
/// onDataReceived was overriden this method will not be called unless the onDataReceived
|
||||
/// calls this method explicitly using the class and member name.
|
||||
///
|
||||
|
||||
virtual void onBlockReceived(coreutils::ZString &block);
|
||||
|
||||
///
|
||||
/// This method is called from within the protocol method when protocol is called
|
||||
/// on the initial connection where the data is an empty string. Use this method
|
||||
/// to deliver a message to the connection upon connection.
|
||||
///
|
||||
|
||||
virtual void onConnected();
|
||||
|
||||
///
|
||||
|
||||
+3
-5
@@ -1,9 +1,9 @@
|
||||
#ifndef __TCPSocket_h__
|
||||
#define __TCPSocket_h__
|
||||
|
||||
#include "includes"
|
||||
#include "Socket.h"
|
||||
#include "IPAddress.h"
|
||||
#include "Socket.h"
|
||||
#include "includes"
|
||||
|
||||
namespace core {
|
||||
|
||||
@@ -19,8 +19,7 @@ namespace core {
|
||||
|
||||
class TCPSocket : public Socket {
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
TCPSocket(EPoll &ePoll);
|
||||
TCPSocket(EPoll &ePoll, std::string text);
|
||||
virtual ~TCPSocket();
|
||||
@@ -37,7 +36,6 @@ namespace core {
|
||||
///
|
||||
|
||||
virtual void output(std::stringstream &out);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
#include "Timer.h"
|
||||
|
||||
namespace core {
|
||||
namespace core
|
||||
{
|
||||
|
||||
Timer::Timer(EPoll &ePoll, double delay = 0.0f) : Socket(ePoll, "Timer") {
|
||||
Timer::Timer(EPoll &ePoll, double delay = 0.0f) : Socket(ePoll, "Timer")
|
||||
{
|
||||
setDescriptor(timerfd_create(CLOCK_REALTIME, 0));
|
||||
setTimer(delay);
|
||||
}
|
||||
|
||||
Timer::~Timer() {
|
||||
Timer::~Timer()
|
||||
{
|
||||
}
|
||||
|
||||
void Timer::setTimer(double delay) {
|
||||
void Timer::setTimer(double delay)
|
||||
{
|
||||
|
||||
double integer;
|
||||
double fraction;
|
||||
@@ -27,10 +31,10 @@ namespace core {
|
||||
timer.it_value.tv_nsec = (int)(fraction * 1000000000);
|
||||
|
||||
timerfd_settime(getDescriptor(), 0, &timer, NULL);
|
||||
|
||||
}
|
||||
|
||||
void Timer::clearTimer() {
|
||||
void Timer::clearTimer()
|
||||
{
|
||||
|
||||
struct itimerspec timer;
|
||||
|
||||
@@ -42,19 +46,22 @@ namespace core {
|
||||
timerfd_settime(getDescriptor(), 0, &timer, NULL);
|
||||
}
|
||||
|
||||
double Timer::getElapsed() {
|
||||
double Timer::getElapsed()
|
||||
{
|
||||
struct itimerspec timer;
|
||||
timerfd_gettime(getDescriptor(), &timer);
|
||||
double toTimeout = (double)((timer.it_value.tv_sec * 1000000000L) + timer.it_value.tv_nsec) / 1000000000L;
|
||||
return delayValue - toTimeout;
|
||||
}
|
||||
|
||||
void Timer::onDataReceived(std::string data) {
|
||||
void Timer::onDataReceived(std::string data)
|
||||
{
|
||||
onTimeout();
|
||||
}
|
||||
|
||||
double Timer::getEpoch() {
|
||||
return (double)std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count() /1000000000L;
|
||||
double Timer::getEpoch()
|
||||
{
|
||||
return (double)std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count() / 1000000000L;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,66 +1,66 @@
|
||||
#ifndef __Timer_h__
|
||||
#define __Timer_h__
|
||||
|
||||
#include "Socket.h"
|
||||
#include "EPoll.h"
|
||||
#include "Socket.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
///
|
||||
/// Timer
|
||||
///
|
||||
/// Set and trigger callback upon specified timeout.
|
||||
///
|
||||
/// The Timer is used to establish a timer using the timer socket
|
||||
/// interface. It cannot be instantiated directly but must be extended.
|
||||
///
|
||||
|
||||
class Timer : Socket {
|
||||
|
||||
public:
|
||||
namespace core
|
||||
{
|
||||
|
||||
///
|
||||
/// Timer
|
||||
///
|
||||
/// Set and trigger callback upon specified timeout.
|
||||
///
|
||||
/// The Timer is used to establish a timer using the timer socket
|
||||
/// interface. It cannot be instantiated directly but must be extended.
|
||||
///
|
||||
|
||||
class Timer : Socket
|
||||
{
|
||||
|
||||
public:
|
||||
Timer(EPoll &ePoll);
|
||||
Timer(EPoll &ePoll, double delay);
|
||||
~Timer();
|
||||
|
||||
///
|
||||
/// Use the setTimer() method to set the time out value for timer. Setting the timer
|
||||
/// also starts the timer countdown. The clearTimer() method can be used to reset
|
||||
/// the timer without triggering the onTimeout() callback.
|
||||
///
|
||||
/// @param delay the amount of time in seconds to wait before trigering the onTimeout function.
|
||||
///
|
||||
|
||||
void setTimer(double delay);
|
||||
|
||||
///
|
||||
/// Use the clearTimer() to unset the timer and return the timer to an idle state.
|
||||
///
|
||||
|
||||
void clearTimer();
|
||||
|
||||
///
|
||||
/// Use the getElapsed() method to obtain the amount of time that has elapsed since
|
||||
/// the timer was set.
|
||||
///
|
||||
|
||||
double getElapsed();
|
||||
|
||||
double getEpoch();
|
||||
|
||||
protected:
|
||||
|
||||
///
|
||||
/// This method is called when the time out occurs.
|
||||
///
|
||||
|
||||
virtual void onTimeout() = 0;
|
||||
|
||||
private:
|
||||
void onDataReceived(std::string data) override;
|
||||
double delayValue;
|
||||
|
||||
};
|
||||
|
||||
Timer(EPoll &ePoll, double delay);
|
||||
~Timer();
|
||||
|
||||
///
|
||||
/// Use the setTimer() method to set the time out value for timer. Setting the timer
|
||||
/// also starts the timer countdown. The clearTimer() method can be used to reset
|
||||
/// the timer without triggering the onTimeout() callback.
|
||||
///
|
||||
/// @param delay the amount of time in seconds to wait before trigering the onTimeout function.
|
||||
///
|
||||
|
||||
void setTimer(double delay);
|
||||
|
||||
///
|
||||
/// Use the clearTimer() to unset the timer and return the timer to an idle state.
|
||||
///
|
||||
|
||||
void clearTimer();
|
||||
|
||||
///
|
||||
/// Use the getElapsed() method to obtain the amount of time that has elapsed since
|
||||
/// the timer was set.
|
||||
///
|
||||
|
||||
double getElapsed();
|
||||
|
||||
double getEpoch();
|
||||
|
||||
protected:
|
||||
///
|
||||
/// This method is called when the time out occurs.
|
||||
///
|
||||
|
||||
virtual void onTimeout() = 0;
|
||||
|
||||
private:
|
||||
void onDataReceived(std::string data) override;
|
||||
double delayValue;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
BIN
Binary file not shown.
@@ -1,6 +0,0 @@
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
std::cout << "Hello world!" << std::endl;
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "../../CoreUtils"
|
||||
},
|
||||
{
|
||||
"path": ".."
|
||||
},
|
||||
{
|
||||
"path": "../../HTTPServer"
|
||||
}
|
||||
],
|
||||
"settings": {},
|
||||
"launch": {
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(gdb) Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "/home/barant/Development/HTTPServer/HTTPServer",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "/home/barant/Development/HTTPServer/",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user