Commit 2e7d689f authored by louiz’'s avatar louiz’

Implement all the connection + auth process. Also fix a leak by correctly...

Implement all the connection + auth process. Also fix a leak by correctly deleting the clients that get disconnected.
parent 994ccd64
......@@ -9,11 +9,11 @@
#include <vector>
#include <database/db_object.hpp>
#ifndef __USER_HPP__
# define __USER_HPP__
#include <database/db_object.hpp>
class User: public DbObject
{
public:
......@@ -48,11 +48,6 @@ public:
*/
void remove_friend(const std::string&);
/**
* User values
*/
std::map<std::string, std::string> values;
private:
User(const DbObject&);
};
......
......@@ -3,6 +3,11 @@
#include <unistd.h>
static const char* auth_messages[] = {"Success",
"Unknown error",
"User does not exist",
"Invalid password",
"User already logged from an other location"};
Game::Game()
{
log_info("Launching game");
......@@ -37,12 +42,15 @@ void Game::on_connection_success(const std::string& login, const std::string& pa
void Game::authenticate(const std::string& login, const std::string& password)
{
this->client.request_answer("AUTH", login.data(), boost::bind(&Game::on_authenticate, this, _1));
// TODO send a password hash, and do not use that stupid separator.
this->client.request_answer("AUTH", std::string(login + '*' + password).data(), boost::bind(&Game::on_authenticate, this, _1));
}
void Game::on_authenticate(const std::string& result)
{
log_debug("on_authenticate ");
int res = atoi(result.data());
log_debug("on_authenticate :" << res << "." << ((res > 4) ? "Unknown error" : auth_messages[res]));
// TODO some UI stuf, etc.
}
void Game::run()
......@@ -58,10 +66,10 @@ void Game::run()
// Simulate a login flow
int main(int argc, char** argv)
{
Config::read_conf("../config/batajelo.conf");
Config::read_conf("../../batajelo.conf");
Game game;
game.on_login_form_validated("test", "coucou", "127.0.0.1", 7878);
game.on_login_form_validated("testing", "new_pass", "127.0.0.1", 7878);
game.run();
return 0;
}
......@@ -44,6 +44,8 @@ public:
*/
void poll(void);
virtual void on_connection_closed() {}
private:
void connect_handler(boost::function< void(void) >,
boost::function< void(void) >,
......
......@@ -40,11 +40,13 @@ boost::function< void(std::string) > CommandHandler::get_callback(const std::str
void CommandHandler::read_handler(const boost::system::error_code& error, const std::size_t bytes_transferred)
{
log_debug("read_handler, size: " << bytes_transferred << " bytes. error: " << error);
log_debug("read_handler, size: " << bytes_transferred << " bytes.");
if (error)
log_debug("Read error: " << error);
if (error)
{
// TODO check more precisely for errors
this->on_connection_closed();
return;
}
// Extract the needed data from the buffer
......
......@@ -75,6 +75,10 @@ protected:
/**
* A buffer keeping the data that is read on the socket.
*/
/**
* What happens when a read error occurs.
*/
virtual void on_connection_closed() = 0;
boost::asio::streambuf data;
tcp::socket* socket;
......
#include <network/remote_client.hpp>
#include <network/server.hpp>
#include <database/database.hpp>
#include <database/db_object.hpp>
int RemoteClient::clients_number = 0;
unsigned long int RemoteClient::clients_number = 0;
RemoteClient::RemoteClient(boost::asio::io_service& io_service):
number(RemoteClient::clients_number++)
RemoteClient::RemoteClient(boost::asio::io_service& io_service,
Server* server):
number(RemoteClient::clients_number++),
server(0),
user(0)
{
this->socket = new tcp::socket(io_service);
this->server = server;
}
RemoteClient::~RemoteClient()
{
log_info("Deleting remote client");
log_info("Deleting remote client " << this->number);
delete this->socket;
delete this->user;
}
tcp::socket& RemoteClient::get_socket(void)
......@@ -19,6 +27,11 @@ tcp::socket& RemoteClient::get_socket(void)
return *this->socket;
}
User* RemoteClient::get_user()
{
return this->user;
}
void RemoteClient::install_callbacks()
{
this->install_callback("AUTH", boost::bind(&RemoteClient::auth_callback, this, _1));
......@@ -26,16 +39,54 @@ void RemoteClient::install_callbacks()
void RemoteClient::auth_callback(const std::string& arg)
{
std::string res("AUTH.");
log_debug("auth_callback: " << arg);
// TODO check login for user, check if it is already logged,
// set it as logged in the database, and return 0 if it failed and 1
// if it succeded
this->send("AUTH.1:1");
size_t pos = arg.find('*');
if (pos == std::string::npos)
res += "1:1";
else
{
std::string login = arg.substr(0, pos);
std::string password = arg.substr(pos+1);
log_debug(login << ":" << password);
DbObject* user = Database::inst()->get_object("*", "User",
std::string("`login`='" + login + "'"));
if (user == 0)
{
log_info("Authentication: User " << login << " does not exist in database.");
res += "1:2";
}
else if (user->get("password") != password)
{
log_info("Authentication: Invalid password for user " << login);
res += "1:3";
delete user;
}
else if (this->server->find_client_by_login(login) != 0)
{
log_info("Authentication: user already logged in from an other location: " << login);
res += "1:4";
delete user;
}
else
{
log_info("Authentication: succes for user " << login);
res += "1:0";
this->user = static_cast<User*>(user);
}
}
this->send(res.data());
}
void RemoteClient::start(void)
void RemoteClient::start()
{
log_debug("Starting RemoteClient " << this->number);
CommandHandler::install_read_handler();
this->install_callbacks();
}
void RemoteClient::on_connection_closed()
{
this->server->remove_client(this);
}
......@@ -10,25 +10,30 @@
* @class RemoteClient
*/
#include <network/command_handler.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#ifndef __REMOTE_CLIENT_HPP__
# define __REMOTE_CLIENT_HPP__
#include <database/user.hpp>
#include <network/command_handler.hpp>
class Server;
using boost::asio::ip::tcp;
class RemoteClient: public CommandHandler
{
public:
RemoteClient(boost::asio::io_service&);
RemoteClient(boost::asio::io_service&, Server*);
~RemoteClient();
/**
* starts the client (install the read handler, etc)
*/
void start(void);
void start();
/**
* @return tcp::socket&
*/
......@@ -37,8 +42,10 @@ public:
* The number of clients is incremented each time
* a new client is accepted.
*/
static int clients_number;
static unsigned long int clients_number;
virtual void on_connection_closed();
User* get_user();
private:
/**
* Creates the default callbacks associated with a network command.
......@@ -48,7 +55,13 @@ private:
void install_callbacks();
void install_read_handler(void);
void auth_callback(const std::string&);
const int number;
const unsigned long int number;
/**
* A pointer to the server, to call its method when the RemoteClient
* has to be deleted.
*/
Server* server;
User* user;
};
#endif
......
......@@ -15,7 +15,7 @@ Server::~Server()
void Server::install_accept_handler(void)
{
RemoteClient* new_client = new RemoteClient(this->io_service);
RemoteClient* new_client = new RemoteClient(this->io_service, this);
this->acceptor->async_accept(new_client->get_socket(),
boost::bind(&Server::handle_accept, this, new_client,
......@@ -39,6 +39,7 @@ void Server::accept(void)
void Server::handle_accept(RemoteClient* client, const boost::system::error_code& error)
{
client->start();
this->clients.push_back(client);
this->install_accept_handler();
}
......@@ -47,3 +48,30 @@ void Server::run()
this->accept();
this->io_service.run();
}
void Server::remove_client(RemoteClient* client)
{
std::vector<RemoteClient*>::iterator it;
for (it = this->clients.begin(); it < this->clients.end(); ++it)
if (*it == client)
this->clients.erase(it);
delete client;
}
RemoteClient* Server::find_client_by_login(const std::string& login)
{
std::vector<RemoteClient*>::iterator it;
for (it = this->clients.begin(); it < this->clients.end(); ++it)
if ((*it)->get_user() && (*it)->get_user()->get("login") == login)
return *it;
return 0;
}
int main(int argc, char *argv[])
{
if (!Config::read_conf("../../batajelo.conf"))
return 1;
Server s(7878);
s.run();
return 0;
}
......@@ -11,11 +11,11 @@
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <network/remote_client.hpp>
#ifndef __SERVER_HPP__
# define __SERVER_HPP__
#include <network/remote_client.hpp>
using boost::asio::ip::tcp;
class Server
......@@ -32,12 +32,23 @@ public:
* @return void
*/
void run(void);
/**
* To be called by the a RemoteClient instance, to delete itself from
* the RemoteClient list.
*/
void remove_client(RemoteClient*);
/**
* Search for a connected client with this login
* @return RemoteClient* can be NULL if nothing is found
*/
RemoteClient* find_client_by_login(const std::string&);
private:
void install_accept_handler(void);
void handle_accept(RemoteClient*, const boost::system::error_code&);
void accept(void);
std::vector<RemoteClient*> clients;
boost::asio::io_service io_service;
tcp::acceptor* acceptor;
short port;
......
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