Commit 023042a3 authored by Seblu's avatar Seblu

- fix bugs sur test de connection existante dans la classe connection

- ajout de test de connection sur toutes les fonctions de la class connection
- changement du mode de dispatch par la classe console, il faut desormais passer par login pour obtenir une class fils
- separation des headers des classes clients filles et maman
- ajout type d'erreur ERR_PARSE
- Archi du backend console
parent bf7aa142
......@@ -33,7 +33,9 @@ sls_SOURCES= src/sls.hh \
src/connection.cc \
src/client.hh \
src/client.cc \
src/client_console.hh \
src/client_console.cc \
src/client_daemon.hh \
src/client_daemon.cc
CLEANFILES= *~ '\#*'
......
......@@ -18,56 +18,68 @@
#include "sls.hh"
#include "client.hh"
#include "client_console.hh"
#include "client_daemon.hh"
static inline Client *login_fail(Connection &c);
/*******************************************************************************
** Method of Classes
*******************************************************************************/
Client *Client::login(Connection &c) {
// read login info
string slogin = c.recvln();
string spass = c.recvln();
// FIXME: find better method than fucking magic number
char clientbuf[512];
char loginbuf[512];
char passbuf[512];
// cut read data
if (sscanf(slogin.c_str(), "%512s %512s\n", clientbuf, loginbuf) != 2)
return login_fail(c);
if (sscanf(spass.c_str(), "PASS %512s\n", passbuf) != 1)
return login_fail(c);
if (sscanf(slogin.c_str(), "HOST %512s\n", loginbuf) == 1) {
// check login and password
// Register login and pass in client
// create client
Client *real_client;
if (strcmp(clientbuf, "HOST") == 0)
real_client = new Daemon(c);
else if (strcmp(clientbuf, "USER") == 0)
real_client = new Console(c);
else
return login_fail(c);
// Print succefful login
std::cout << "Connection id " << c.getid() << ": Host " << loginbuf
<< " logged from " << c.getremoteip()
<< " on port " << c.getremoteport() << ".\n";
return new Daemon(c);
}
else if (sscanf(slogin.c_str(), "USER %512s\n", loginbuf) == 1) {
return new Console(c);
// check login and password and register it in DB if success
if (real_client->trust(loginbuf, passbuf) == false) {
delete real_client;
return login_fail(c);
}
return login_fail(c);
}
// Print succefful login
std::cout << "CId " << c.getid() << ": Host " << loginbuf
<< " logged from " << c.getremoteip()
<< " on port " << c.getremoteport() << ".\n";
Client *Client::login_fail(Connection &c) {
std::cout << "Connection id " << c.getid() << ": Bad authentification.\n";
c.sendln("Bad authentification.");
return 0;
return real_client;
}
/*******************************************************************************
** Public Classes
** Public methods
*******************************************************************************/
Client::Client(Connection &c) : c_ (c) {}
Client::~Client() {}
/*******************************************************************************
** Local functions
*******************************************************************************/
void Client::exec() {
assert(0);
static Client *login_fail(Connection &c) {
std::cout << "CId " << c.getid() << ": Bad authentification.\n";
c.sendln("Bad authentification.");
return 0;
}
......@@ -21,42 +21,24 @@
# include "connection.hh"
/*!
** Client Class
/**
* Client
*/
class Client {
public:
Client(Connection &c);
virtual ~Client();
virtual void exec();
virtual void exec() = 0;
static Client *login(Connection &c);
protected:
Connection c_;
private:
static Client *login_fail(Connection &c);
};
/*!
** Client Daemon Class
*/
class Daemon: public Client {
public:
Daemon(Connection &c);
void exec();
};
Client(Connection &c);
/*!
** Client Console Class
*/
class Console : public Client {
public:
Console(Connection &c);
void exec();
virtual bool trust(const char *login, const char *pass) = 0;
protected:
Connection c_;
string login_;
};
#endif
......@@ -17,10 +17,81 @@
*/
#include "sls.hh"
#include "client.hh"
#include "error.hh"
#include "option.hh"
#include "client_console.hh"
Console::Console(Connection &c) : Client(c) {}
/*******************************************************************************
** Public methods
*******************************************************************************/
/**
* Entry point for a console backend
*/
void Console::exec() {
c_.sendln("You are a console !!");
while (1) {
// receive line
string cmd = c_.recvln();
// Print info
if (O.verbose) std::cout << "Cid " << c_.getid() << ": Receive: " << cmd << ".\n";
else std::cout << "Cid " << c_.getid() << ": Receive request.\n";
// call parser
try { parse(cmd); }
catch (const Error &e) {
if (e.code() == ERR_PARSE) {
// Print info
if (O.verbose) std::cout << "Cid " << c_.getid() << ": Parse error: " << e << ".\n";
else std::cout << "Cid " << c_.getid() << ": Invalid command.\n";
}
else throw;
}
}
}
/*******************************************************************************
** Protected methods
*******************************************************************************/
/**
* Constructor
*
* @param c Attached connection
*/
Console::Console(Connection &c) : Client(c) {}
/**
* Check if login and pass are valid user
* and register login and pass are logged in DB
*
* @param login user login
* @param pass user pass
*
* @return if user is logged or not
*/
bool Console::trust(const char *login, const char *pass) {
assert(login);
assert(pass);
// check login and password in DB
c_.sendln("User always trusted !!");
// store username
login_ = login;
// register as logged in DB
return true;
}
/**
* Parse and execute
*
* @param cmd string to parse
*/
void Console::parse(const string &cmd) {
if (!cmd.empty())
throw Error(ERR_PARSE, "Empty command");
// FIXME
}
/*
This file is part of SLS.
Copyright (C) 2008 Sebastien LUTTRINGER <contact@seblu.net>
SLS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
SLS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SLS; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef CLIENT_CONSOLE_HH
# define CLIENT_CONSOLE_HH
# include "client.hh"
/*!
** Client Console Class
*/
class Console : public Client {
public:
friend class Client;
virtual void exec();
protected:
Console(Connection &c);
virtual bool trust(const char *login, const char *pass);
void parse(const string &cmd);
};
#endif
......@@ -17,9 +17,11 @@
*/
#include "sls.hh"
#include "client.hh"
#include "client_daemon.hh"
Daemon::Daemon(Connection &c) : Client(c) {}
/*******************************************************************************
** Public methods
*******************************************************************************/
void Daemon::exec() {
// send scripts
......@@ -28,3 +30,39 @@ void Daemon::exec() {
c_.sendln("EXIT");
}
/*******************************************************************************
** Protected methods
*******************************************************************************/
/**
* Constructor
*
* @param c Attached connection
*/
Daemon::Daemon(Connection &c) : Client(c) {}
/**
* Check if login and pass are valid daemon
* and register login and pass are logged in DB
*
* @param login user login
* @param pass user pass
*
* @return if daemon is logged or not
*/
bool Daemon::trust(const char *login, const char *pass) {
assert(login);
assert(pass);
// check login and password in DB
c_.sendln("Daemon always untrusted !!");
// store username
login_ = login;
// register as logged in DB
return false;
}
/*
This file is part of SLS.
Copyright (C) 2008 Sebastien LUTTRINGER <contact@seblu.net>
SLS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
SLS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SLS; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef CLIENT_DAEMON_HH
# define CLIENT_DAEMON_HH
# include "client.hh"
/*!
** Client Daemon Class
*/
class Daemon: public Client {
public:
friend class Client;
virtual void exec();
protected:
Daemon(Connection &c);
virtual bool trust(const char *login, const char *pass);
};
#endif
......@@ -179,7 +179,7 @@ void Connection::listen(int port, int max) {
* Disconnect socket
*/
void Connection::disconnect() {
if (socket < 0)
if (socket_fd_ < 0)
throw Error(ERR_NET, "No connection established but trying to disconnect");
// lock all mutex
......@@ -218,7 +218,7 @@ bool Connection::connected() {
* @return null on error, else a new connection
*/
Connection *Connection::accept() {
if (socket < 0)
if (socket_fd_ < 0)
throw Error(ERR_NET, "No connection established but trying to accept");
struct sockaddr_in r_addr;
......@@ -243,7 +243,7 @@ Connection *Connection::accept() {
* Send data on @param buf of size @param len on socket
*/
void Connection::send(const char* buf, size_t len) {
if (socket < 0)
if (socket_fd_ < 0)
throw Error(ERR_NET, "No connection established but trying to send data");
pthread_mutex_lock(&w_mutex_);
......@@ -260,7 +260,7 @@ void Connection::send(const char* buf, size_t len) {
* Send data on @param buf of size @param len followed by '\n' on socket
*/
void Connection::sendln(const char* buf, size_t len) {
if (socket < 0)
if (socket_fd_ < 0)
throw Error(ERR_NET, "No connection established but trying to send line");
pthread_mutex_lock(&w_mutex_);
......@@ -284,7 +284,7 @@ void Connection::sendln(const char* buf, size_t len) {
* Receive a line
*/
string Connection::recvln() {
if (socket < 0)
if (socket_fd_ < 0)
throw Error(ERR_NET, "No connection established but trying to receive line");
pthread_mutex_lock(&r_mutex_);
......@@ -327,6 +327,9 @@ string Connection::recvln() {
}
string Connection::getlocalip() {
if (socket_fd_ < 0)
throw Error(ERR_NET, "No connection established but trying to get local ip");
pthread_mutex_lock(&c_mutex_);
if (local_ip_.empty())
setlocalip_();
......@@ -336,6 +339,9 @@ string Connection::getlocalip() {
}
int Connection::getlocalport() {
if (socket_fd_ < 0)
throw Error(ERR_NET, "No connection established but trying to get local port");
pthread_mutex_lock(&c_mutex_);
if (local_port_ == -1)
setlocalport_();
......@@ -345,6 +351,9 @@ int Connection::getlocalport() {
}
string Connection::getremoteip() {
if (socket_fd_ < 0)
throw Error(ERR_NET, "No connection established but trying to get remote ip");
pthread_mutex_lock(&c_mutex_);
if (remote_ip_.empty())
setremoteip_();
......@@ -354,6 +363,9 @@ string Connection::getremoteip() {
}
int Connection::getremoteport() {
if (socket_fd_ < 0)
throw Error(ERR_NET, "No connection established but trying to get remote port");
pthread_mutex_lock(&c_mutex_);
if (remote_port_ == -1)
setremoteport_();
......@@ -367,6 +379,9 @@ unsigned long int Connection::getid() {
}
int Connection::getsocket() {
if (socket_fd_ < 0)
throw Error(ERR_NET, "No connection established but trying to get socket fd");
pthread_mutex_lock(&c_mutex_);
int ret = socket_fd_;
pthread_mutex_unlock(&c_mutex_);
......
......@@ -73,7 +73,7 @@ void Server::start(int port, size_t max_conn, bool verbose) {
// check max conn
if (threads_.size() >= max_conn_) {
std::cout << "Connection id " << nc->getid() << ": Refused from ip " << nc->getremoteip()
std::cout << "CId " << nc->getid() << ": Refused from ip " << nc->getremoteip()
<< " on port " << nc->getremoteport()
<< ": Max connections reached.\n";
nc->disconnect();
......@@ -81,7 +81,7 @@ void Server::start(int port, size_t max_conn, bool verbose) {
}
// Print connection
std::cout << "Connection id " << nc->getid() << ": New connection from ip "
std::cout << "CId " << nc->getid() << ": New connection from ip "
<< nc->getremoteip() << " on port " << nc->getremoteport();
if (verbose_)
std::cout << " (socket " << nc->getsocket() << ")" ;
......@@ -177,14 +177,14 @@ void *Server::start_client(void *voidconn) {
}
}
catch (const Error &e) {
std::cerr << "Connection id " << conn->getid() << ": " << e << ".\n";
std::cerr << "CId " << conn->getid() << ": " << e << ".\n";
}
// stop connexion
conn->disconnect();
// Print closing connection
std::cout << "Connection id " << conn->getid() << ": Closed.\n";
std::cout << "CId " << conn->getid() << ": Closed.\n";
// remove from thread set
pthread_mutex_lock(&S.threads_mutex_);
......
......@@ -30,11 +30,18 @@
#include <errno.h>
#include <time.h>
// -----------------------------------------------------------------------------
// Globals
// -----------------------------------------------------------------------------
Option O;
Database D;
Server S;
Cron C;
// -----------------------------------------------------------------------------
// Functions
// -----------------------------------------------------------------------------
int main(int argc, char *argv[])
{
try {
......
......@@ -44,6 +44,7 @@ enum {
ERR_DB = 7,
ERR_SRV = 8,
ERR_THREAD = 9,
ERR_PARSE = 10,
ERR_NOMEM = 41,
ERR_UNKNOWN = 42
};
......@@ -56,4 +57,19 @@ static const string VERSION = (string) "testing.\nBuild: " + __DATE__ + " " + __
//static const string VERSION = "1.0";
static const int MAX_LINE_SIZE = 512;
// -----------------------------------------------------------------------------
// global variables
// -----------------------------------------------------------------------------
class Option;
extern Option O;
class Database;
extern Database D;
class Server;
extern Server S;
class Cron;
extern Cron C;
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment