summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2010-12-07 02:02:42 +0100
committerVegard Storheil Eriksen <zyp@jvnv.net>2010-12-07 02:02:58 +0100
commit18e73025a15b98aae008ffe5a19570a0e5ea19ef (patch)
treeb67baeb7e6c18f6fd6290ddeebf1d0fa171812c1
parent1624b37bf4ce632a486d6729dc90724241417868 (diff)
Completed framework for reconnection. Still missing client-fallback and resync upon reconnect.
-rw-r--r--server/client.cpp51
-rw-r--r--server/client.h30
-rw-r--r--server/lobby.cpp48
-rw-r--r--server/lobby.h2
4 files changed, 84 insertions, 47 deletions
diff --git a/server/client.cpp b/server/client.cpp
index 07a59f4..af2494e 100644
--- a/server/client.cpp
+++ b/server/client.cpp
@@ -2,32 +2,53 @@
#include <boost/bind.hpp>
-Client::p Client::create(Connection::p c, boost::function<void (Client::p)> f) {
- Client::p p(new Client(c));
- p->start(f);
+std::map<uint64_t, boost::weak_ptr<Client> > Client::client_list;
+
+Client::p Client::create(Connection::p c, std::string n) {
+ Client::p p(new Client(c, n));
+ p->start();
return p;
}
-Client::Client(Connection::p c) : connection(c), timer(c->socket.get_io_service()) {
+Client::p Client::exists(Message::Login::p login_msg) {
+ if(client_list.count(login_msg->cookie)) {
+ // Obtain shared pointer to existing client.
+ Client::p client = client_list[login_msg->cookie].lock();
+
+ // TODO: Check if game still is ongoing?
+ // A client should only be reconnected to if still participating in an active game.
+ // It may however be proven that a client is always destructed if the game has ended, so this test might not be neccessary.
+
+ return client;
+
+ } else {
+ // No or invalid existing client found.
+ return Client::p();
+ }
+}
+
+Client::Client(Connection::p c, std::string n) : connection(c), timer(c->socket.get_io_service()), nick_(n) {
}
-void Client::disconnect() {
- //delete connection;
- //connection = NULL;
- //We need to make this player dumb?
+Client::~Client() {
+ client_list.erase(cookie);
}
void Client::reconnect(Connection::p c) {
connection = c;
+ // TODO: Resync client.
}
-void Client::start(boost::function<void (Client::p)> f) {
- // Send Hello.
- connection->send(make_shared<Message::Hello>("aotenjoud git"));
+void Client::start() {
+ // Create a unique cookie for this client.
+ cookie = uint64_t(this); // TODO: Use a better cookie source.
+
+ // Store a weak pointer to this client.
+ client_list[cookie] = shared_from_this();
- // Wait for Login.
- connection->recv(boost::bind(&Client::handle_login, shared_from_this(), _1, f));
+ // Logged in to lobby.
+ connection->send(make_shared<Message::LoginResponse>(Message::LoginResponse::Lobby));
}
void Client::handle_login(Message::p msg, boost::function<void (Client::p)> login_callback) {
@@ -94,10 +115,6 @@ void Client::lobby_status(const std::vector<std::string>& game_modes, boost::fun
connection->recv(boost::bind(&Client::handle_lobby, shared_from_this(), _1, callback));
}
-unsigned int Client::id() {
- return id_;
-}
-
std::string Client::nick() {
return nick_;
}
diff --git a/server/client.h b/server/client.h
index 676264e..82968b4 100644
--- a/server/client.h
+++ b/server/client.h
@@ -2,6 +2,7 @@
#define CLIENT_H
#include <string>
+#include <map>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/function.hpp>
@@ -16,9 +17,6 @@ class ClientBase {
virtual ~ClientBase() {}
- //! Return client's id.
- virtual unsigned int id() = 0;
-
//! Return client's nick.
virtual std::string nick() = 0;
@@ -44,21 +42,29 @@ class Client : public ClientBase, public boost::enable_shared_from_this<Client>
public:
typedef boost::shared_ptr<Client> p;
- static p create(Connection::p c, boost::function<void (Client::p)> f);
+ //! Construct and return a new Client instance.
+ static p create(Connection::p c, std::string n);
+
+ //! Check if a Client instance of the user already exists and return it.
+ static p exists(Message::Login::p login_msg);
+
+ ~Client();
private:
+ uint64_t cookie;
+
+ static std::map<uint64_t, boost::weak_ptr<Client> > client_list;
+
Connection::p connection;
boost::asio::deadline_timer timer;
- unsigned int id_;
-
std::string nick_;
- Client(Connection::p c);
+ Client(Connection::p c, std::string n);
//! Start communicating.
- void start(boost::function<void (Client::p)> f);
+ void start();
//! Handle Login-message.
void handle_login(Message::p msg, boost::function<void (Client::p)> login_callback);
@@ -76,9 +82,6 @@ class Client : public ClientBase, public boost::enable_shared_from_this<Client>
//! Inform client of lobby status (available game modes).
void lobby_status(const std::vector<std::string>& game_modes, boost::function<void (int)> callback);
- //! Return client's id.
- virtual unsigned int id();
-
//! Return client's nick.
virtual std::string nick();
@@ -97,10 +100,7 @@ class Client : public ClientBase, public boost::enable_shared_from_this<Client>
//! Get action. Upon connection error, last element of expected_actions will be provided.
virtual void get_action(boost::function<void (Action)> callback, Actions expected_actions);
- //! Dis-connect a player.
- virtual void disconnect();
-
- //! Re-connect a player.
+ //! Reconnect a player.
virtual void reconnect(Connection::p c);
};
diff --git a/server/lobby.cpp b/server/lobby.cpp
index 7939977..9fb769e 100644
--- a/server/lobby.cpp
+++ b/server/lobby.cpp
@@ -7,27 +7,47 @@
#include "game.h"
void Lobby::handle_connect(Connection::p connection) {
- // Create player.
- Client::create(connection, boost::bind(&Lobby::handle_login, this, _1));
+ // Send Hello.
+ connection->send(make_shared<Message::Hello>("aotenjoud git"));
+
+ // Wait for Login.
+ connection->recv(boost::bind(&Lobby::handle_login, this, connection, _1));
// Get another connection.
server.get_connection(boost::bind(&Lobby::handle_connect, this, _1));
}
-void Lobby::handle_login(Client::p client) {
- std::cout << "Client " << client->nick() << " entered the lobby." << std::endl;
+void Lobby::handle_login(Connection::p connection, Message::p msg) {
+ if(msg->type != Message::Types::Login) {
+ return;
+ }
- if(0) {//client->id != 0
- //We check if player is in an ongoing game?
-
- } else {
- std::vector<std::string> game_modes;
-
- game_modes.push_back("1p test mode");
- game_modes.push_back("4p test mode");
-
- client->lobby_status(game_modes, boost::bind(&Lobby::handle_action, this, client, _1));
+ Message::Login::p login_msg = dynamic_pointer_cast<Message::Login>(msg);
+
+ Client::p client;
+
+ // Check if this is a reconnection attempt and whether a reconnection is possible.
+ if(login_msg->cookie && (client = Client::exists(login_msg))) {
+ client->reconnect(connection);
+ return;
}
+
+ // Validate nick.
+ if(login_msg->nick.size() == 0) {
+ connection->send(make_shared<Message::LoginResponse>(Message::LoginResponse::Invalid));
+ connection->recv(boost::bind(&Lobby::handle_login, this, connection, _1));
+ return;
+ }
+
+ // Create a new client.
+ client = Client::create(connection, login_msg->nick);
+
+ std::vector<std::string> game_modes;
+
+ game_modes.push_back("1p test mode");
+ game_modes.push_back("4p test mode");
+
+ client->lobby_status(game_modes, boost::bind(&Lobby::handle_action, this, client, _1));
}
void Lobby::handle_action(Client::p client, int game_mode) {
diff --git a/server/lobby.h b/server/lobby.h
index fa0e5fe..c445506 100644
--- a/server/lobby.h
+++ b/server/lobby.h
@@ -19,7 +19,7 @@ class Lobby {
void handle_connect(Connection::p connection);
//! Handle login.
- void handle_login(Client::p client);
+ void handle_login(Connection::p connection, Message::p msg);
//! Handle action.
void handle_action(Client::p client, int game_mode);