Added vscode

This commit is contained in:
Brad Arant 2020-11-07 17:28:24 -08:00
parent 177bc602af
commit f652ba1f34
6 changed files with 165 additions and 136 deletions

29
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,29 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++14",
"intelliSenseMode": "gcc-x64",
"compileCommands": "./compile"
},
{
"name": "config",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++17",
"intelliSenseMode": "gcc-x64",
"compileCommands": "./compile"
}
],
"version": 4
}

View File

@ -4,96 +4,96 @@
#include "Exception.h" #include "Exception.h"
namespace core { namespace core {
EPoll::EPoll() : Command() { EPoll::EPoll() : Command() {
coreutils::Log(coreutils::LOG_DEBUG_2) << "EPoll object being constructed."; coreutils::Log(coreutils::LOG_DEBUG_2) << "EPoll object being constructed.";
maxSockets = 1000; maxSockets = 1000;
epfd = epoll_create1(0); epfd = epoll_create1(0);
terminateThreads = false; terminateThreads = false;
} }
EPoll::~EPoll() { EPoll::~EPoll() {
coreutils::Log(coreutils::LOG_DEBUG_2) << "BMAEPoll destructed."; coreutils::Log(coreutils::LOG_DEBUG_2) << "BMAEPoll destructed.";
} }
bool EPoll::start(int numberOfThreads, int maxSockets) { bool EPoll::start(int numberOfThreads, int maxSockets) {
coreutils::Log(coreutils::LOG_DEBUG_2) << "Starting epoll event processing."; coreutils::Log(coreutils::LOG_DEBUG_2) << "Starting epoll event processing.";
this->numberOfThreads = numberOfThreads; this->numberOfThreads = numberOfThreads;
coreutils::Log(coreutils::LOG_DEBUG_3) << "Number of threads starting is " << numberOfThreads << "."; coreutils::Log(coreutils::LOG_DEBUG_3) << "Number of threads starting is " << numberOfThreads << ".";
coreutils::Log(coreutils::LOG_DEBUG_3) << "Maximum connections is " << maxSockets << "."; coreutils::Log(coreutils::LOG_DEBUG_3) << "Maximum connections is " << maxSockets << ".";
// TODO: Set the number of maximum open files to the maxSockets value. // TODO: Set the number of maximum open files to the maxSockets value.
// //
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Create thread objects into vector for number of threads requested. // Create thread objects into vector for number of threads requested.
// Hand all the threads a pointer to the EPoll object so they can run // Hand all the threads a pointer to the EPoll object so they can run
// the socket handlers. // the socket handlers.
//---------------------------------------------------------------------- //----------------------------------------------------------------------
for(int ix = 0; ix < numberOfThreads; ++ix) for(int ix = 0; ix < numberOfThreads; ++ix)
threads.emplace_back(*this); threads.emplace_back(*this);
for(int ix = 0; ix < numberOfThreads; ++ix) for(int ix = 0; ix < numberOfThreads; ++ix)
threads[ix].start(); threads[ix].start();
return true; return true;
} }
bool EPoll::stop() { bool EPoll::stop() {
terminateThreads = true; terminateThreads = true;
//-------------------------------------------------------- //--------------------------------------------------------
// Kill and join all the threads that have been started. // Kill and join all the threads that have been started.
//-------------------------------------------------------- //--------------------------------------------------------
for(int ix = 0; ix < numberOfThreads; ++ix) for(int ix = 0; ix < numberOfThreads; ++ix)
threads[ix].join(); threads[ix].join();
//-------------------------- //--------------------------
// Close the epoll socket. // Close the epoll socket.
//-------------------------- //--------------------------
close(epfd); close(epfd);
return true; return true;
} }
bool EPoll::isStopping() { bool EPoll::isStopping() {
return terminateThreads; return terminateThreads;
} }
bool EPoll::registerSocket(Socket *socket) { bool EPoll::registerSocket(Socket *socket) {
coreutils::Log(coreutils::LOG_DEBUG_3) << "Registering socket " << socket->getDescriptor() << "."; coreutils::Log(coreutils::LOG_DEBUG_3) << "Registering socket " << socket->getDescriptor() << ".";
enableSocket(socket); enableSocket(socket);
return true; return true;
} }
bool EPoll::unregisterSocket(Socket *socket) { bool EPoll::unregisterSocket(Socket *socket) {
coreutils::Log(coreutils::LOG_DEBUG_3) << "Unregistering socket " << socket->getDescriptor() << "."; coreutils::Log(coreutils::LOG_DEBUG_3) << "Unregistering socket " << socket->getDescriptor() << ".";
disableSocket(socket); disableSocket(socket);
return true; return true;
} }
int EPoll::getDescriptor() { int EPoll::getDescriptor() {
return epfd; return epfd;
} }
int EPoll::processCommand(std::string command, TCPSession *session, std::stringstream &data) { int EPoll::processCommand(std::string command, TCPSession *session, std::stringstream &data) {
int sequence = 0; int sequence = 0;
for(auto threadx : threads) { for(auto threadx : threads) {
data << "|" << ++sequence; data << "|" << ++sequence;
threadx.output(data); threadx.output(data);
data << "|" << std::endl; data << "|" << std::endl;
} }
return 1; return 1;
} }
void EPoll::enableSocket(Socket *socket) { void EPoll::enableSocket(Socket *socket) {
coreutils::Log(coreutils::LOG_DEBUG_4) << "Enabling socket " << socket->getDescriptor() << " for events."; coreutils::Log(coreutils::LOG_DEBUG_4) << "Enabling socket " << socket->getDescriptor() << " for events.";
struct epoll_event event; struct epoll_event event;
@ -101,13 +101,13 @@ namespace core {
event.events = EPOLLIN | EPOLLONESHOT | EPOLLRDHUP | EPOLLET; event.events = EPOLLIN | EPOLLONESHOT | EPOLLRDHUP | EPOLLET;
epoll_ctl(epfd, EPOLL_CTL_ADD, socket->getDescriptor(), &event); epoll_ctl(epfd, EPOLL_CTL_ADD, socket->getDescriptor(), &event);
} }
void EPoll::disableSocket(Socket *socket) { void EPoll::disableSocket(Socket *socket) {
coreutils::Log(coreutils::LOG_DEBUG_4) << "Disabling socket " << socket->getDescriptor() << " from events."; coreutils::Log(coreutils::LOG_DEBUG_4) << "Disabling socket " << socket->getDescriptor() << " from events.";
epoll_ctl(epfd, EPOLL_CTL_DEL, socket->getDescriptor(), NULL); epoll_ctl(epfd, EPOLL_CTL_DEL, socket->getDescriptor(), NULL);
} }
void EPoll::resetSocket(Socket *socket) { void EPoll::resetSocket(Socket *socket) {
coreutils::Log(coreutils::LOG_DEBUG_4) << "Resetting socket " << socket->getDescriptor() << " for read."; coreutils::Log(coreutils::LOG_DEBUG_4) << "Resetting socket " << socket->getDescriptor() << " for read.";
struct epoll_event event; struct epoll_event event;
event.data.ptr = socket; event.data.ptr = socket;

View File

@ -10,17 +10,17 @@ namespace core {
public: public:
IPAddressList(); IPAddressList();
std::map<std::string, IPAddress> getList(); std::map<std::string, IPAddress> getList();
void add(IPAddress ipAddress); void add(IPAddress ipAddress);
bool remove(IPAddress ipAddress); bool remove(IPAddress ipAddress);
bool contains(std::string ipAddress); bool contains(std::string ipAddress);
private: private:
std::map<std::string, IPAddress> list; std::map<std::string, IPAddress> list;
std::map<std::string, IPAddress>::iterator it = list.begin(); std::map<std::string, IPAddress>::iterator it = list.begin();
}; };
} }
#endif #endif

View File

@ -4,23 +4,23 @@
#include "PString.h" #include "PString.h"
namespace core { namespace core {
TCPSession::TCPSession(EPoll &ePoll, TCPServer &server, std::string text) : TCPSocket(ePoll, text), server(server) {} TCPSession::TCPSession(EPoll &ePoll, TCPServer &server, std::string text) : TCPSocket(ePoll, text), server(server) {}
TCPSession::~TCPSession() { TCPSession::~TCPSession() {
server.removeFromSessionList(this); server.removeFromSessionList(this);
} }
void TCPSession::output(std::stringstream &data) { void TCPSession::output(std::stringstream &data) {
data << "|" << ipAddress.getClientAddressAndPort(); data << "|" << ipAddress.getClientAddressAndPort();
} }
void TCPSession::protocol(std::string data = "") { void TCPSession::protocol(std::string data = "") {
if(!server.commands.processRequest(data, this, out)) if(!server.commands.processRequest(data, this, out))
if(data != "") if(data != "")
server.sessionErrorHandler("Invalid data received.", out); server.sessionErrorHandler("Invalid data received.", out);
} }
void TCPSession::onRegistered() { void TCPSession::onRegistered() {
onConnected(); onConnected();
protocol(); protocol();
@ -30,17 +30,17 @@ namespace core {
} }
void TCPSession::onConnected() {} void TCPSession::onConnected() {}
void TCPSession::onDataReceived(char *data, int len) { void TCPSession::onDataReceived(char *data, int len) {
if(len > 0) { if(len > 0) {
lineBuffer = (char *)realloc(lineBuffer, lineBufferSize + len); lineBuffer = (char *)realloc(lineBuffer, lineBufferSize + len);
memcpy(lineBuffer + lineBufferSize, data, len); memcpy(lineBuffer + lineBufferSize, data, len);
lineBufferSize += len; lineBufferSize += len;
while(lineBufferSize > 0) { while(lineBufferSize > 0) {
switch(mode) { switch(mode) {
case LINE: case LINE:
lineLength = strcspn(lineBuffer, "\r\n"); lineLength = strcspn(lineBuffer, "\r\n");
if(lineLength == lineBufferSize) if(lineLength == lineBufferSize)
break; break;
onLineReceived(std::string(lineBuffer, lineLength)); onLineReceived(std::string(lineBuffer, lineLength));
if(lineBuffer[lineLength] == '\r') if(lineBuffer[lineLength] == '\r')
@ -48,53 +48,59 @@ namespace core {
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);
break; break;
case BLOCK: case BLOCK:
if(lineBufferSize >= blockLength) { if(lineBufferSize >= blockLength) {
onBlockReceived(std::string(lineBuffer, blockLength)); onBlockReceived(std::string(lineBuffer, blockLength));
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);
} }
break; break;
} }
} }
} }
} }
void TCPSession::setMode(core::Mode mode, int blockSize) { void TCPSession::setMode(core::Mode mode, int blockSize) {
this->mode = mode; this->mode = mode;
this->blockSize = blockSize; this->blockSize = blockSize;
} }
void TCPSession::onLineReceived(std::string line) { void TCPSession::onLineReceived(std::string line) {
coreutils::Log(coreutils::LOG_DEBUG_3) << "[" << line << "]"; coreutils::Log(coreutils::LOG_DEBUG_3) << "[" << line << "]";
protocol(line); protocol(line);
send(); send();
if(term) if(term)
shutdown("termination requested"); shutdown("termination requested");
} }
void TCPSession::onBlockReceived(std::string block) {
coreutils::Log(coreutils::LOG_DEBUG_3) << "[" << block.length() << "]";
if(term)
shutdown("termination requested");
}
void TCPSession::sendToAll() { void TCPSession::sendToAll() {
for(auto session : server.sessions) for(auto session : server.sessions)
if(session != this) if(session != this)
session->write(out.str()); session->write(out.str());
out.str(""); out.str("");
} }
void TCPSession::sendToAll(SessionFilter filter) { void TCPSession::sendToAll(SessionFilter filter) {
for(auto session : server.sessions) for(auto session : server.sessions)
if(filter.test(*session)) if(filter.test(*session))
if(session != this) if(session != this)
session->write(out.str()); session->write(out.str());
out.str(""); out.str("");
} }
void TCPSession::send() { void TCPSession::send() {
if(out.tellp() > 0) if(out.tellp() > 0)
write(out.str()); write(out.str());
@ -104,5 +110,5 @@ namespace core {
void TCPSession::terminate() { void TCPSession::terminate() {
term = true; term = true;
} }
} }

View File

@ -8,151 +8,144 @@ namespace core {
class Command; class Command;
enum Mode {LINE, BLOCK}; enum Mode {LINE, BLOCK};
class TCPServer; class TCPServer;
/// ///
/// TCPSession /// TCPSession
/// ///
/// TCPSession defines the nature of the interaction with the client /// TCPSession defines the nature of the interaction with the client
/// and stores persistent data for a defined session. TCPSession objects /// and stores persistent data for a defined session. TCPSession objects
/// are not sockets but instead provide a communications control /// are not sockets but instead provide a communications control
/// mechanism. Protocol conversations are provided through extensions /// mechanism. Protocol conversations are provided through extensions
/// from this object. /// from this object.
///
///
/// ///
///
///
class TCPSession : public TCPSocket { class TCPSession : public TCPSocket {
public: public:
/// ///
/// ///
/// ///
TCPSession(EPoll &ePoll, TCPServer &server, std::string text = ""); TCPSession(EPoll &ePoll, TCPServer &server, std::string text = "");
/// ///
/// ///
/// ///
~TCPSession(); ~TCPSession();
Command *grab = NULL; Command *grab = NULL;
virtual void output(std::stringstream &data); virtual void output(std::stringstream &data);
/// ///
/// Use out to send data to the session socket or other session sockets. /// Use out to send data to the session socket or other session sockets.
/// ///
std::stringstream out; std::stringstream out;
/// ///
/// The send method is used to output the contents of the out stream /// The send method is used to output the contents of the out stream
/// to the session containing the stream. /// to the session containing the stream.
/// ///
void send(); void send();
/// ///
/// Use this sendToAll method to output the contents of the out stream /// Use this sendToAll method to output the contents of the out stream
/// to all the connections on the server excluding the sender session. /// to all the connections on the server excluding the sender session.
/// ///
void sendToAll(); void sendToAll();
/// ///
/// Use this sendToAll method to output the contents of the out stream /// Use this sendToAll method to output the contents of the out stream
/// to all the connections on the server excluding the sender session /// to all the connections on the server excluding the sender session
/// and the entries identified by the passed in filter object. /// and the entries identified by the passed in filter object.
/// ///
void sendToAll(SessionFilter filter); void sendToAll(SessionFilter filter);
/// ///
/// Use this method to terminate this TCPSession. /// Use this method to terminate this TCPSession.
/// ///
void terminate(); void terminate();
/// ///
///
/// ///
///
TCPServer &server; TCPServer &server;
///
/// Set this value to control the next read event coming
/// from this socket.
///
// enum Mode {LINE, BLOCK};
protected: protected:
/// ///
/// ///
/// ///
virtual void onRegistered() override; virtual void onRegistered() override;
/// ///
/// Override this method to receive data directly from the socket as data is /// Override this method to receive data directly from the socket as data is
/// received. If you need data split by line termination characters then /// received. If you need data split by line termination characters then
/// override the onLineReceived method instead. /// override the onLineReceived method instead.
/// ///
virtual void onDataReceived(char *data, int len) override; virtual void onDataReceived(char *data, int len) override;
/// ///
/// Override the onLineReceived method to receive a string of characters that /// Override the onLineReceived method to receive a string of characters that
/// represents a single line of data terminated by a LF or CRLF. If onDataReceived /// represents a single line of data terminated by a LF or CRLF. If onDataReceived
/// was overriden this method will not be called unless the onDataReceived calls /// was overriden this method will not be called unless the onDataReceived calls
/// this method explicitly using the class and member name. /// this method explicitly using the class and member name.
/// ///
virtual void onLineReceived(std::string line); virtual void onLineReceived(std::string line);
/// ///
/// Override the onBlockReceived method to receive a string of characters that /// 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 /// 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 /// onDataReceived was overriden this method will not be called unless the onDataReceived
/// calls this method explicitly using the class and member name. /// calls this method explicitly using the class and member name.
/// ///
virtual void onBlockReceived(std::string block); virtual void onBlockReceived(std::string block);
/// ///
/// This method is called from within the protocol method when protocol is called /// 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 /// on the initial connection where the data is an empty string. Use this method
/// to deliver a message to the connection upon connection. /// to deliver a message to the connection upon connection.
/// ///
virtual void onConnected(); virtual void onConnected();
/// ///
/// Override the protocol method to manage and control the session communications /// Override the protocol method to manage and control the session communications
/// in your inherited session. If you do not override this method then the Session /// in your inherited session. If you do not override this method then the Session
/// default will process the 'commands' added to the server object using the /// default will process the 'commands' added to the server object using the
/// processRequest method on the session input. /// processRequest method on the session input.
/// ///
/// When data is received within the session two modes are available to pass the /// When data is received within the session two modes are available to pass the
/// data through the protocol method: LINE or BLOCK. /// data through the protocol method: LINE or BLOCK.
/// ///
virtual void protocol(std::string data); virtual void protocol(std::string data);
/// ///
/// Use the setMode method to set the receiving mode for the data on this socket. /// Use the setMode method to set the receiving mode for the data on this socket.
/// Data can be received in LINE mode, which will receive data from the socket one /// Data can be received in LINE mode, which will receive data from the socket one
/// line at a time, or BLOCK mode where a certain specified data block is received /// line at a time, or BLOCK mode where a certain specified data block is received
/// before calling the onBlockReceived method. /// before calling the onBlockReceived method.
/// ///
void setMode(core::Mode mode, int size = 0); void setMode(core::Mode mode, int size = 0);
private: private:
char *lineBuffer = NULL; char *lineBuffer = NULL;
int lineBufferSize = 0; int lineBufferSize = 0;
@ -162,9 +155,9 @@ namespace core {
bool term = false; bool term = false;
core::Mode mode = LINE; core::Mode mode = LINE;
int blockSize; int blockSize;
}; };
} }
#endif #endif

11
compile
View File

@ -3,17 +3,17 @@
for file in *.cpp for file in *.cpp
do 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 -I../CoreUtils $file
if [ $? = '0' ] if [ $? = '0' ]
then then
echo "OK" echo "OK"
else else
echo "ERROR" echo "ERROR"
exit -1 exit -1
fi fi
done done
wait wait
@ -25,8 +25,9 @@ then
else else
echo "ERROR" echo "ERROR"
exit -1 exit -1
fi fi
echo -n "Building library documentation manual..." echo -n "Building library documentation manual..."
doxygen docs/latex/doxygen.sty >/dev/null 2>/dev/null doxygen docs/latex/doxygen.sty >/dev/null 2>/dev/null
echo "OK" echo "OK"