From 3a3ba622dbf9c035b0f26979601b2d4d192b4167 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 13 Jul 2008 16:37:18 +0000 Subject: connection sequence updates, breaks network protocol --- src/core/gameconnection.cc | 41 +++++++------- src/core/gameserver.cc | 132 ++++++++++++++++++++++++++++++++++++++++++++- src/core/gameserver.h | 3 ++ src/core/net.h | 3 ++ src/core/netclient.h | 2 +- src/core/netconnection.cc | 30 ++++++++--- src/core/netconnection.h | 5 +- src/core/netserver.cc | 39 ++++++++++++-- src/core/player.cc | 1 + src/core/player.h | 8 +++ 10 files changed, 230 insertions(+), 34 deletions(-) (limited to 'src/core') diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc index 4d2a745..daf47e1 100644 --- a/src/core/gameconnection.cc +++ b/src/core/gameconnection.cc @@ -47,6 +47,12 @@ GameConnection::GameConnection(std::string const &connectionstr) return; } + // send connect request + std::stringstream netmsgstream(""); + netmsgstream << "connect " << PROTOCOLVERSION << "\n"; + connection_network->send(netmsgstream.str()); + connection_network->transmit(); + connection_frametime = 0; connection_running = true; } @@ -112,26 +118,23 @@ void GameConnection::frame(float seconds) } } - if ((connection_network->state() == NetConnection::Connected) && localcontrol() && localcontrol()->dirty()) { - std::ostringstream netmsg; - netmsg << "cup " << localcontrol()->id() << " "; - localcontrol()->serialize_client_update(netmsg); - netmsg << "\n"; - - connection_network->send(netmsg.str()); - localcontrol()->entity_dirty = false; - //con_debug << netmsg.str(); - } - - if (localplayer()->dirty()) { - localplayer()->update_info(); + if (connection_network->state() == NetConnection::Connected) { + + if(localcontrol() && localcontrol()->dirty()) { + std::ostringstream netmsg; + netmsg << "cup " << localcontrol()->id() << " "; + localcontrol()->serialize_client_update(netmsg); + netmsg << "\n"; + + connection_network->send(netmsg.str()); + localcontrol()->entity_dirty = false; + //con_debug << netmsg.str(); + } - std::ostringstream osstream; - osstream << "pif "; - localplayer()->serialize_client_update(osstream); - osstream << '\n'; - connection_network->send(osstream.str()); - localplayer()->player_dirty = false; + if (localplayer()->dirty()) { + connection_network->send_playerinfo(); + + } } connection_network->transmit(); diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index 2027098..4172d4f 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -17,6 +17,15 @@ namespace core { +Player *console_find_player(std::string const & target) +{ + Player *targetplayer = server()->find_player(target); + if (!targetplayer) { + con_print << "^BPlayer " + target + "^B not found."; + } + return targetplayer; +} + void func_who(std::string const &args) { server()->list_players(); @@ -27,6 +36,70 @@ void func_time(std::string const &args) server()->showtime(); } +void func_mute(std::string const &args) +{ + Player *targetplayer = 0; + if (!(targetplayer = console_find_player(args))) + return; + + if (targetplayer->mute()) { + con_print << "^BPlayer " + targetplayer->name() + "^B has already been muted."; + return; + } + + targetplayer->player_mute = true; + server()->broadcast("^B" + targetplayer->name() + "^B has been muted.", targetplayer); + server()->send(targetplayer, "^BYou have been muted."); +} + +void func_unmute(std::string const &args) +{ + Player *targetplayer = 0; + if (!(targetplayer = console_find_player(args))) + return; + + if (!targetplayer->mute()) { + con_print << "^BPlayer " + targetplayer->name() + "^B has not been muted."; + return; + } + + targetplayer->player_mute = false; + server()->broadcast("^B" +targetplayer->name() + "^B has been unmuted.", targetplayer); + server()->send(targetplayer, "^BYou have been unmuted."); +} + +void func_kick(std::string const &args) +{ + std::stringstream str(args); + std::string name; + + if (str >> name) { + Player *targetplayer = 0; + if (!(targetplayer = console_find_player(name))) + return; + std::string reason; + if (args.size() > name.size()+1) + reason.assign(args.substr(name.size()+1)); + else + reason.assign("forcefully removed."); + + server()->kick(targetplayer, reason); + } +} + +void func_grant_rcon(std::string const &args) +{ + Player *targetplayer = 0; + if (!(targetplayer = console_find_player(args))) + return;} + +void func_revoke_rcon(std::string const &args) +{ + Player *targetplayer = 0; + if (!(targetplayer = console_find_player(args))) + return; +} + GameServer *GameServer::server_instance = 0; GameServer::GameServer() : GameInterface() @@ -69,8 +142,30 @@ GameServer::GameServer() : GameInterface() server_network = 0; } - Func::add("time", func_time, Func::Shared); - Func::add("who", func_who, Func::Shared); + Func *func = 0; + + /* -- admin functions -- */ + func = Func::add("mute", func_mute); + func->set_info("[player] mute a player"); + + func = Func::add("unmute", func_unmute); + func->set_info("[player] unmute a player"); + + func = Func::add("kick", func_kick); + func->set_info("[player] [reason] kick a player from the server"); +/* + func = Func::add("grant_rcon", func_grant_rcon); + func->set_info("[player] grant a player rcon rights"); + + func = Func::add("revoke_rcon", func_grant_rcon); + func->set_info("[player] revoke a player's rcon rights"); +*/ + /* -- player functions --*/ + func = Func::add("time", func_time, Func::Shared); + func->set_info("get the server uptime and current localtime"); + + func = Func::add("who", func_who, Func::Shared); + func->set_info("get a list of connected players"); if (!Cvar::sv_dedicated->value()) { player_connect(localplayer()); @@ -100,6 +195,12 @@ GameServer::~GameServer() delete server_module; } + Func::remove("mute"); + Func::remove("unmute"); + +/* Func::remove("grant_rcon"); + Func::remove("revoke_rcon"); +*/ Func::remove("time"); Func::remove("who"); @@ -174,6 +275,11 @@ void GameServer::say(Player *player, std::string const &message) if (!message.size()) return; + if (player->mute()) { + send(player, "^BYou have been muted."); + return; + } + std::string notification("^B"); notification.append(player->name()); notification.append("^F:^B "); @@ -192,6 +298,28 @@ void GameServer::say(Player *player, std::string const &message) } } +void GameServer::kick(Player *player, std::string const &reason) +{ + // FIXME kicked by + if (!server_network) { + con_print << "Not running a networked server." << std::endl; + return; + } + + NetClient *client = server_network->find_client(player); + if (client) { + broadcast("^B" + player->name() + "^B has been kicked: " + reason, player); + send(player, "^WYou have been kicked: " + reason); + + client->send("disconnect\n"); + client->transmit(server_network->fd()); + + client->abort(); + } else { + con_print << "Network client not found." << std::endl; + } +} + void GameServer::broadcast(std::string const & message, Player *ignore_player) { // send to application diff --git a/src/core/gameserver.h b/src/core/gameserver.h index 7a2f4a6..172fb94 100644 --- a/src/core/gameserver.h +++ b/src/core/gameserver.h @@ -52,6 +52,9 @@ public: /// a player sends a chat message to the public channel void say(Player *player, std::string const &args); + /// kick a player from the server + void kick(Player *player, std::string const &reason); + /// broadcast a message to all players void broadcast(std::string const & message, Player *ignore_player = 0); diff --git a/src/core/net.h b/src/core/net.h index 3c49467..2ca81fe 100644 --- a/src/core/net.h +++ b/src/core/net.h @@ -10,6 +10,9 @@ namespace core { +/// network protocol version +const unsigned int PROTOCOLVERSION = 1; + /// maximum lenght of a (compressed) network message block const unsigned int FRAMESIZE = 1152; const unsigned int BLOCKSIZE = 8192; diff --git a/src/core/netclient.h b/src/core/netclient.h index 7176260..39c425f 100644 --- a/src/core/netclient.h +++ b/src/core/netclient.h @@ -65,7 +65,7 @@ public: void abort(); - enum State {Connecting=0, Connected=1}; + enum State {Connecting=0, Pending=1, Connected=2}; inline State state() const { return client_state; } diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc index 4c916a1..bee0843 100644 --- a/src/core/netconnection.cc +++ b/src/core/netconnection.cc @@ -89,6 +89,7 @@ void NetConnection::connect(std::string const &to_host, int to_port) connection_timeout = application()->time(); connection_keepalive = application()->time(); + connection_state = Pending; game()->localplayer()->player_dirty = true; @@ -278,6 +279,18 @@ void NetConnection::send(std::string const &msg) sendq.append(msg); } +void NetConnection::send_playerinfo() +{ + localplayer()->update_info(); + + std::ostringstream osstream; + osstream << "pif "; + localplayer()->serialize_client_update(osstream); + osstream << '\n'; + send(osstream.str()); + localplayer()->player_dirty = false; +} + void NetConnection::transmit() { @@ -363,9 +376,11 @@ void NetConnection::parse_incoming_message(const std::string & message) } } } else if (command == "connect") { - - connection_state = Connected; - con_print << "^BConnected." << std::endl; + if (connection_state == Pending) { + send_playerinfo(); + connection_state = Connected; + con_print << "^BConnected." << std::endl; + } return; } else if (command == "disconnect") { @@ -391,6 +406,7 @@ void NetConnection::parse_incoming_message(const std::string & message) if (e) Entity::remove(id); } + } else if (command == "ent") { unsigned int type; if (msgstream >> type) { @@ -414,6 +430,10 @@ void NetConnection::parse_incoming_message(const std::string & message) break; } } + } else if (command == "pif") { + //con_debug << "Received update player info" << std::endl; + connection()->localplayer()->recieve_server_update(msgstream); + } else if (command == "sup") { if (connection_state == Connected) { @@ -428,11 +448,7 @@ void NetConnection::parse_incoming_message(const std::string & message) } } - } else if (command == "pif") { - //con_debug << "Received update player info" << std::endl; - connection()->localplayer()->recieve_server_update(msgstream); } - } } diff --git a/src/core/netconnection.h b/src/core/netconnection.h index ddc70f0..a2e9f2f 100644 --- a/src/core/netconnection.h +++ b/src/core/netconnection.h @@ -52,6 +52,9 @@ public: /// buffer outgoing data void send(std::string const &msg); + /// sennd a player info message + void send_playerinfo(); + /// send bufered outgoing data void transmit(); @@ -71,7 +74,7 @@ public: inline bool connected() const { return ((connection_fd != -1) && !connection_error); } - enum State {Connecting=0, Connected=1}; + enum State {Connecting=0, Pending=1, Connected=2}; inline State state() const { return connection_state; } diff --git a/src/core/netserver.cc b/src/core/netserver.cc index 2859006..fe6e45b 100644 --- a/src/core/netserver.cc +++ b/src/core/netserver.cc @@ -300,10 +300,14 @@ void NetServer::client_initialize(NetClient *client) { netmsg << "\n"; client->send(netmsg.str()); } + + // send connect completed netmsg.str("connect\n"); client->send(netmsg.str()); - client->transmit(fd()); + + // set client state to pending + client->client_state = NetClient::Pending; } void NetServer::send(NetClient * client, std::string const & message) @@ -361,15 +365,42 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me return; } + // connection request + // connect is the first command expected from the client + if (command == "connect") { + if (client->state() != NetClient::Connecting) + return; + + unsigned int protover; + if (msgstream >> protover) { + if (protover != PROTOCOLVERSION) { + std::stringstream netmsgstream(""); + netmsgstream << "Protocol version mismatch: "; + netmsgstream << "client " << protover << " server " << PROTOCOLVERSION << "!\n"; + + con_print << client->host() << ":" << client->port() << " " << netmsgstream.str() << std::endl; + server()->send(client->player(), netmsgstream.str()); + } else { + client_initialize(client); + } + } else { + std::string message("Unknown client protocol version!"); + con_print << client->host() << ":" << client->port() << " " << message << std::endl; + server()->send(client->player(), message); + client->abort(); + } + return; + } + // pif - update player information - // pif is the first command expected from the client + // client connection is completed on the first pif if (command == "pif") { std::string oldname(client->player()->name()); client->player()->recieve_client_update(msgstream); - if (client->state() == NetClient::Connecting) { + if (client->state() == NetClient::Pending) { + client->client_state = NetClient::Connected; - client_initialize(client); server()->player_connect(client->player()); } else if ((client->state() == NetClient::Connected) && (client->player()->name() != oldname)) { diff --git a/src/core/player.cc b/src/core/player.cc index 97b6944..4ad2c3a 100644 --- a/src/core/player.cc +++ b/src/core/player.cc @@ -29,6 +29,7 @@ void Player::clear() player_name.clear(); player_dirty = false; player_rcon = false; + player_mute = false; clear_assets(); } diff --git a/src/core/player.h b/src/core/player.h index b8dd100..fa13b22 100644 --- a/src/core/player.h +++ b/src/core/player.h @@ -47,6 +47,9 @@ public: /// player base color inline math::Color const & color() const { return player_color; } + /// player has been muted by admin or console + inline bool mute() const { return player_mute; } + /*----- mutators -------------------------------------------------- */ /// serialize player info to a stream @@ -96,10 +99,15 @@ public: /// player color math::Color player_color; + /// player is muted by admin + bool player_mute; + /// the entity the Player is currently controling EntityControlable *player_control; std::list assets; + + }; } -- cgit v1.2.3