Implementation of Serice object into structure.

This commit is contained in:
Brad Arant 2019-02-16 12:01:36 -08:00
parent a2526dd3ed
commit 2cb1e3e2f2
23 changed files with 278 additions and 293 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
Debug
*.o
*~
libServerCore.a

View File

@ -5,23 +5,23 @@ namespace core {
void Command::output(Session *session) {}
bool Command::check(std::string request) {
if(request != "") {
if(name.length() > 0) {
size_t start = request.find_first_not_of(" ");
if(name == request.substr(start, name.length()))
return true;
}
return false;
}
}
bool Command::check(std::string request) {
if(request != "") {
if(name.length() > 0) {
size_t start = request.find_first_not_of(" ");
if(name == request.substr(start, name.length()))
return true;
}
return false;
}
}
void Command::setName(std::string name) {
this->name = name;
}
void Command::setName(std::string name) {
this->name = name;
}
std::string Command::getName() {
return name;
}
std::string Command::getName() {
return name;
}
}

104
Command.h
View File

@ -1,76 +1,76 @@
#ifndef __Command_h__
#define __Command_h__
# define __Command_h__
#include "includes"
#include "Object.h"
# include "includes"
# include "Object.h"
namespace core {
class Session;
///
/// Command
///
/// 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.
///
///
/// Command
///
/// 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 Object {
public:
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.
///
///
/// 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(std::string request);
virtual bool check(std::string request);
///
/// This method is used to implement the functionality of the requested command.
/// 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
/// command process can return its output to the session.
/// @return Returns 0 if execution of the command was successful. Otherwise returns
/// a non-zero value indicating an error condition.
///
///
/// This method is used to implement the functionality of the requested command.
/// 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
/// command process can return its output to the session.
/// @return Returns 0 if execution of the command was successful. Otherwise returns
/// a non-zero value indicating an error condition.
///
virtual int processCommand(std::string request, Session *session) = 0;
///
/// Specify the output that will occur to the specified session.
///
/// @param session The session that will receive the output.
///
///
/// Specify the output that will occur to the specified session.
///
/// @param session The session that will receive the output.
///
virtual void output(Session *session);
virtual void output(Session *session);
///
/// 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.
///
///
/// 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);
void setName(std::string name);
std::string getName();
std::string getName();
private:
std::string name;
private:
std::string name;
};

View File

@ -2,38 +2,35 @@
namespace core {
CommandList::CommandList() {}
CommandList::CommandList() {}
CommandList::~CommandList() {}
CommandList::~CommandList() {}
void CommandList::add(Command &command, std::string name) {
command.setName(name);
void CommandList::add(Command &command, std::string name) {
command.setName(name);
commands.push_back(&command);
}
void CommandList::remove(Command &command) {
void CommandList::remove(Command &command) {
}
bool CommandList::processRequest(std::string request, Session *session) {
bool found = false;
}
bool CommandList::processRequest(std::string request, Session *session) {
bool found = false;
for(auto *command : commands) {
if(command->check(request)) {
command->processCommand(request, session);
found = true;
break;
}
}
if(command->check(request)) {
command->processCommand(request, session);
found = true;
break;
}
}
return found;
}
return found;
}
int CommandList::processCommand(std::string request, Session *session) {
for(Command *command : commands)
session->out << command->getName() << std::endl;
}
int CommandList::processCommand(std::string request, Session *session) {
for(Command *command : commands)
session->out << command->getName() << std::endl;
}
}

View File

@ -6,24 +6,46 @@
namespace core {
class CommandList : public Command {
///
/// CommandList
///
/// This object organizes Command objects into a list that is used
/// to parse an input and run the process associated with the
/// selected command.
///
public:
CommandList();
~CommandList();
class CommandList : public Command {
void add(Command &command, std::string name = "");
public:
void remove(Command &command);
///
/// The constructor for the object.
///
bool processRequest(std::string request, Session *session);
CommandList();
///
/// The destructor for the object.
///
~CommandList();
///
/// Add a new command to the command list and assign a default search value.
///
void add(Command &command, std::string name = "");
void remove(Command &command);
bool processRequest(std::string request, Session *session);
int processCommand(std::string request, Session *session) override;
private:
std::vector<Command *> commands;
private:
std::vector<Command *> commands;
};
};
}

View File

@ -7,18 +7,18 @@ namespace core {
ConsoleServer::ConsoleServer(EPoll &ePoll, std::string url, short int port)
: TCPServerSocket(ePoll, url, port) {
Log(this);
}
Log(this);
}
ConsoleServer::~ConsoleServer() {}
void ConsoleServer::sendToConnectedConsoles(std::string out) {
for(auto *session : sessions)
((ConsoleSession *)session)->writeLog(out);
for(auto *session : service->sessions)
((ConsoleSession *)session)->writeLog(out);
}
Session * ConsoleServer::getSocketAccept() {
return new ConsoleSession(ePoll, *this);
return new ConsoleSession(ePoll, *this->service);
}
void ConsoleServer::output(Session *session) {

View File

@ -3,6 +3,7 @@
#include "includes"
#include "TCPServerSocket.h"
#include "Service.h"
#include "Command.h"
#include "Session.h"
#include "EPoll.h"

View File

@ -1,12 +1,11 @@
#include "ConsoleSession.h"
#include "Log.h"
namespace core {
ConsoleSession::ConsoleSession(EPoll &ePoll, ConsoleServer &server) : TerminalSession(ePoll, server) {
}
ConsoleSession::ConsoleSession(EPoll &ePoll, Service &service) : TerminalSession(ePoll, service) {}
ConsoleSession::~ConsoleSession() {
}
ConsoleSession::~ConsoleSession() {}
void ConsoleSession::output(std::stringstream &out) {
// socket->output(out);
@ -63,7 +62,7 @@ namespace core {
break;
case PROMPT:
Log(LOG_DEBUG_1) << "Lines is " << getLines() << ".";
Log(LOG_DEBUG_1) << "Lines is " << getLines() << ".";
setCursorLocation(17, 1);
clearEOL();
out << ("--> ");
@ -106,7 +105,7 @@ namespace core {
saveCursor();
setCursorLocation(16, 1);
out << "--> " << request << std::endl;
server.commands.processRequest(request, this);
service.commands.processRequest(request, this);
restoreCursor();
send();
}

View File

@ -3,7 +3,7 @@
#include "TerminalSession.h"
#include "Session.h"
#include "ConsoleServer.h"
#include "Service.h"
#include "CommandList.h"
namespace core {
@ -19,7 +19,7 @@ namespace core {
class ConsoleSession : public TerminalSession {
public:
ConsoleSession(EPoll &ePoll, ConsoleServer &server);
ConsoleSession(EPoll &ePoll, Service &service);
~ConsoleSession();
virtual void output(std::stringstream &out);

View File

@ -1,5 +1,6 @@
#include "ConsoleSession.h"
#include "Log.h"
#include "ConsoleServer.h"
namespace core {

View File

@ -1,14 +1,13 @@
#include "Session.h"
#include "Log.h"
#include "TCPServerSocket.h"
#include "Service.h"
namespace core {
Session::Session(EPoll &ePoll, TCPServerSocket &server) : TCPSocket(ePoll), server(server) {
}
Session::Session(EPoll &ePoll, Service &service) : TCPSocket(ePoll), service(service) {}
Session::~Session() {
server.removeFromSessionList(this);
service.removeFromSessionList(this);
}
void Session::init() {}
@ -17,15 +16,11 @@ namespace core {
session->out << "|" << ipAddress.getClientAddressAndPort();
}
TCPServerSocket &Session::getServer() {
return server;
}
void Session::protocol(std::string data = "") {
if(data.length() > 0)
if(!server.commands.processRequest(data, this))
server.sessionErrorHandler("Invalid data received.", this);
}
if(data.length() > 0)
if(!service.commands.processRequest(data, this))
service.sessionErrorHandler("Invalid data received.", this);
}
void Session::onConnected() {
protocol();
@ -36,7 +31,7 @@ namespace core {
}
void Session::sendToAll() {
for(auto session : server.sessions) {
for(auto session : service.sessions) {
if(session != this)
session->write(out.str());
}
@ -44,7 +39,7 @@ namespace core {
}
void Session::sendToAll(SessionFilter *filter) {
for(auto session : server.sessions) {
for(auto session : service.sessions) {
if(filter->test(*session)) {
if(session != this)
session->write(out.str());

View File

@ -2,12 +2,12 @@
#define __Session_h__
#include "TCPSocket.h"
//#include "TCPServerSocket.h"
#include "SessionFilter.h"
//#include "Service.h"
namespace core {
class TCPServerSocket;
class Service;
///
/// Session
@ -22,7 +22,7 @@ namespace core {
class Session : public TCPSocket {
public:
Session(EPoll &ePoll, TCPServerSocket &server);
Session(EPoll &ePoll, Service &service);
~Session();
virtual void init();
@ -53,25 +53,22 @@ namespace core {
std::stringstream out;
TCPServerSocket &getServer();
TCPServerSocket &server;
Service &service;
protected:
protected:
void onDataReceived(std::string data) override;
void onConnected() override;
///
/// 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
/// default will process the 'commands' added to the server object using the
/// processRequest method on the session input.
///
///
/// 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
/// default will process the 'commands' added to the server object using the
/// processRequest method on the session input.
///
virtual void protocol(std::string data);
private:
};
}

View File

@ -11,24 +11,18 @@ namespace core {
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
struct hostent *hp = gethostbyname(url.c_str());
memcpy((void *)&addr.sin_addr, hp->h_addr_list[0], hp->h_length);
setDescriptor(socket(AF_INET, SOCK_STREAM, 0));
int yes = 1;
setsockopt(getDescriptor(), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
if(bind(getDescriptor(), (struct sockaddr *)&addr, sizeof(addr)) < 0)
throw Exception("Error on bind to socket");
if(listen(getDescriptor(), 10) < 0)
throw Exception("Error on listen to socket");
ePoll.registerSocket(this);
service = _getService();
}
TCPServerSocket::~TCPServerSocket() {
@ -38,51 +32,39 @@ namespace core {
void TCPServerSocket::init() {}
void TCPServerSocket::onDataReceived(std::string data) {
Log(LOG_DEBUG_2) << "Connection request on socket " << getDescriptor() << ".";
Session *session = accept();
sessions.push_back(session);
service->sessions.push_back(session);
}
Session * TCPServerSocket::accept() {
Session *session = getSocketAccept();
session->setDescriptor(::accept(getDescriptor(), (struct sockaddr *)&session->ipAddress.address, &session->ipAddress.addressLength));
ePoll.registerSocket(session);
Log(LOG_DEBUG_2) << "Session started on socket " << session->getDescriptor() << ".";
return session;
}
Session * TCPServerSocket::getSocketAccept() {
return new Session(ePoll, *this);
}
return new Session(ePoll, *service);
}
Service * TCPServerSocket::_getService() {
return getService();
}
Service * TCPServerSocket::getService() {
return new Service(*this);
}
int TCPServerSocket::processCommand(std::string command, Session *session) {
int sequence = 0;
for(auto *sessionx : sessions) {
for(auto *sessionx : service->sessions) {
session->out << "|" << ++sequence;
sessionx->output(session);
session->out << "|" << std::endl;
}
session->send();
}
void TCPServerSocket::removeFromSessionList(Session *session) {
std::vector<Session *>::iterator cursor;
for(cursor = sessions.begin(); cursor < sessions.end(); ++cursor)
if(*cursor == session)
sessions.erase(cursor);
}
void TCPServerSocket::sessionErrorHandler(std::string errorString, Session *session) {
throw Exception(errorString);
}
}

View File

@ -3,8 +3,7 @@
#include "Socket.h"
#include "TCPSocket.h"
#include "Command.h"
#include "CommandList.h"
#include "Service.h"
namespace core {
@ -41,23 +40,6 @@ namespace core {
~TCPServerSocket();
void removeFromSessionList(Session *session);
///
/// The list of sessions that are currently open and being maintained by this object.
///
std::vector<Session *> sessions;
///
/// The commands object is a CommandList and is used to store Command objects to be
/// parsed and run as data comes into the session.
///
CommandList commands;
virtual void sessionErrorHandler(std::string errorString, Session *session);
protected:
virtual void init();
@ -72,6 +54,14 @@ namespace core {
virtual Session * getSocketAccept();
///
/// TCP servers can have an associated Service object that provides services for
/// sessions created by the server. You can extend the Service object and place
/// commands and server application support for extended servers.
///
virtual Service * getService();
///
/// Override the virtual dataReceived since for the server these
/// are requests to accept the new connection socket.
@ -93,9 +83,12 @@ namespace core {
int processCommand(std::string command, Session *session) override;
Service *service;
private:
Session * accept();
Service * _getService();
};

View File

@ -1,5 +1,6 @@
#include "TLSServerSocket.h"
#include "TLSSession.h"
#include "TLSService.h"
#include "EPoll.h"
#include "Session.h"
#include "Exception.h"
@ -18,24 +19,24 @@ namespace core {
TLSServerSocket::TLSServerSocket(EPoll &ePoll, std::string url, short int port) : TCPServerSocket(ePoll, url, port) {
tlsServerInit();
// TODO: Convert to use core::Exception object.
if(!(ctx = SSL_CTX_new(SSLv23_server_method())))
throw std::string("Error while setting server method SSLv23.");
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
if(!(((TLSService *)service)->ctx = SSL_CTX_new(SSLv23_server_method())))
throw Exception("Error while setting server method SSLv23.");
SSL_CTX_set_mode(((TLSService *)service)->ctx, SSL_MODE_RELEASE_BUFFERS | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
SSL_CTX_set_options(((TLSService *)service)->ctx, SSL_OP_NO_TICKET);
SSL_CTX_set_session_cache_mode(((TLSService *)service)->ctx, SSL_SESS_CACHE_SERVER);
// SSL_CTX_set_generate_session_id(ctx, generate_session_id);
SSL_CTX_set_cipher_list(ctx, "ECDH-ECDSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA");
if(SSL_CTX_use_certificate_file(ctx, sip_cert, SSL_FILETYPE_PEM) <= 0)
SSL_CTX_set_cipher_list(((TLSService *)service)->ctx, "ECDH-ECDSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA");
if(SSL_CTX_use_certificate_file(((TLSService *)service)->ctx, sip_cert, SSL_FILETYPE_PEM) <= 0)
throw Exception("Error looking up certificate.");
if(SSL_CTX_use_PrivateKey_file(ctx, sip_key, SSL_FILETYPE_PEM) < 0)
if(SSL_CTX_use_PrivateKey_file(((TLSService *)service)->ctx, sip_key, SSL_FILETYPE_PEM) < 0)
throw Exception("Error with private key.");
if(SSL_CTX_check_private_key(ctx) != 1)
if(SSL_CTX_check_private_key(((TLSService *)service)->ctx) != 1)
throw Exception("Private key does not match certificate.");
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_verify_depth(ctx, 1);
if(!SSL_CTX_load_verify_locations(ctx, sip_cacert, NULL))
SSL_CTX_set_verify(((TLSService *)service)->ctx, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_verify_depth(((TLSService *)service)->ctx, 1);
if(!SSL_CTX_load_verify_locations(((TLSService *)service)->ctx, sip_cacert, NULL))
throw Exception("Cannot verify locations.");
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(sip_cacert));
SSL_CTX_set_client_CA_list(((TLSService *)service)->ctx, SSL_load_client_CA_file(sip_cacert));
Log(LOG_DEBUG_1) << "Server key authenticated.";
}
@ -59,8 +60,13 @@ namespace core {
}
Session * TLSServerSocket::getSocketAccept() {
Session *session = new TLSSession(ePoll, *this);
Session *session = new TLSSession(ePoll, *this->service);
return session;
}
Service * TLSServerSocket::getService() {
return new TLSService(*this);
}
}

View File

@ -5,12 +5,7 @@
#include "TCPServerSocket.h"
#include "Command.h"
#include "Session.h"
#include <openssl/ssl.h>
#include <openssl/rand.h>
#include <openssl/err.h>
// Global values used by all TLS functions for this server socket.
//
namespace core {
///
@ -41,10 +36,11 @@ namespace core {
~TLSServerSocket();
SSL_CTX *ctx;
// SSL_CTX *ctx;
protected:
Session * getSocketAccept() override;
Service * getService() override;
private:
void tlsServerInit();

View File

@ -1,8 +1,9 @@
#include "TLSSession.h"
#include "TLSService.h"
#include "EPoll.h"
#include "Log.h"
#include "Exception.h"
#include <openssl/rand.h>
//#include <openssl/rand.h>
namespace core {
@ -32,7 +33,7 @@ namespace core {
Log(LOG_DEBUG_3) << "No client certificate.";
}
TLSSession::TLSSession(EPoll &ePoll, TLSServerSocket &server) : Session(ePoll, server) {}
TLSSession::TLSSession(EPoll &ePoll, Service &service) : Session(ePoll, service) {}
void TLSSession::init() {
@ -44,7 +45,7 @@ namespace core {
fcntl(getDescriptor(), F_SETFL, fcntl(getDescriptor(), F_GETFL, 0) | O_NONBLOCK);
if(!(ssl = SSL_new(((core::TLSServerSocket &)server).ctx)))
if(!(ssl = SSL_new(((TLSService &)service).ctx)))
throw std::string("Error creating new TLS socket.");
SSL_set_info_callback(ssl, handshake_complete);

View File

@ -24,7 +24,7 @@ namespace core {
public:
TLSSession(EPoll &ePoll, TLSServerSocket &server);
TLSSession(EPoll &ePoll, Service &service);
~TLSSession();
///

View File

@ -2,7 +2,7 @@
namespace core {
TerminalSession::TerminalSession(EPoll &ePoll, TCPServerSocket &server) : Session(ePoll, server) {
TerminalSession::TerminalSession(EPoll &ePoll, Service &service) : Session(ePoll, service) {
}
TerminalSession::~TerminalSession() {

View File

@ -3,6 +3,7 @@
#include "includes"
#include "Session.h"
#include "TCPServerSocket.h"
namespace core {
@ -29,7 +30,7 @@ namespace core {
class TerminalSession : public Session {
public:
TerminalSession(EPoll &ePoll, TCPServerSocket &server);
TerminalSession(EPoll &ePoll, Service &service);
~TerminalSession();
int getLines();

14
compile
View File

@ -11,11 +11,21 @@ do
echo "OK"
else
echo "ERROR"
exit -1
fi
done
wait
echo $list
g++ -o main.cpp $list
echo -n "Building static library libServerCore.a..."
ar rcs libServerCore.a $list
if [ $? = '0' ]
then
echo "OK"
else
echo "ERROR"
exit -1
fi
rm *.o
rm *~

View File

@ -1,20 +0,0 @@
#!/bin/bash
for file in *.cpp
do
filename="${file%.*}"
list="$list, $filename.o"
echo -n "Compiling $filename..."
g++ -c $file
if [ $? = '0' ]
then
echo "OK"
else
echo "ERROR"
fi
done
wait
echo $list

View File

@ -28,4 +28,7 @@
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <openssl/ssl.h>
#include <openssl/rand.h>
#include <openssl/err.h>