--- a/src/CMakeLists.txt Wed Dec 03 19:16:32 2008 +0000
+++ b/src/CMakeLists.txt Wed Dec 03 19:30:54 2008 +0000
@@ -1,5 +1,5 @@
-FILE(GLOB SOURCE_FILES "*.cc")
-FILE(GLOB HEADER_FILES "*.hh")
+FILE(GLOB SOURCE_FILES "*.cc" "Network/*.cc")
+FILE(GLOB HEADER_FILES "*.hh" "Network/*.hh")
set(SOURCES ${SOURCE_FILES} ${HEADER_FILES})
--- a/src/Engine.cc Wed Dec 03 19:16:32 2008 +0000
+++ b/src/Engine.cc Wed Dec 03 19:30:54 2008 +0000
@@ -1,7 +1,5 @@
#include "Engine.hh"
-#include "NetworkServer.hh"
-#include "NetworkClient.hh"
#include "SinglePlayer.hh"
#include <iostream>
--- a/src/Engine.hh Wed Dec 03 19:16:32 2008 +0000
+++ b/src/Engine.hh Wed Dec 03 19:30:54 2008 +0000
@@ -6,8 +6,8 @@
#include "GameState.hh"
#include "Graphics.hh"
-#include "NetworkServer.hh"
-#include "NetworkClient.hh"
+#include "Network/Server.hh"
+#include "Network/Client.hh"
#include "Logger.hh"
--- a/src/Network.cc Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-#include "Network.hh"
-#include "NetworkAddress.hh"
-#include "NetworkSocket.hh"
-#include "Engine.hh"
-
-#include <sstream>
-#include <cstring>
-
-std::ostream& operator<< (std::ostream &s, const NetworkAddress &addr) {
- s << "[" << addr.get_address() << ":" << addr.get_port() << "]";
-
- return s;
-
-}
-
-std::string NetworkSocketError::build_str (const NetworkSocket &socket, const char *op, const char *err) {
- std::stringstream ss;
-
- ss << "socket #" << socket.get_socket() << " " << op << ": " << err;
-
- return ss.str();
-}
-
-NetworkSocketError::NetworkSocketError (const NetworkSocket &socket, const char *op, const char *err) :
- Error(build_str(socket, op, err)) {
-
- // nothing
-}
-
--- a/src/Network.hh Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-#ifndef NETWORK_HH
-#define NETWORK_HH
-
-#include "NetworkConfig.hh"
-#include "GameState.hh"
-
-#include <ClanLib/network.h>
-
-const int32_t COORDINATE_MAX = 1 << 30;
-
-class NetworkCore {
- protected:
- GameState &state;
-
- CL_SlotContainer slots;
-
- // constructor
- NetworkCore (GameState &state) : state(state) { }
-
-
-
-
-};
-
-enum NetworkChannel {
- /*
- * Core channel used for NetworkSession
- */
- NETCHAN_CORE = 0x01,
-};
-
-enum NetworkPhysicsFlags {
- NETWORK_PHYSICS_INAIR = 0x01,
-};
-
-enum NetworkMessage {
- NETMSG_PACKET_INVALID = 0x00,
-
- /*
- * You have joined the game:
- *
- * Vector initial_position
- */
- NETMSG_SERVER_HELLO = 0x0100,
-
- /*
- * New client has connected to server:
- *
- * Vector initial_position
- */
- NETMSG_PLAYER_JOIN = 0x0101,
-
- /*
- * Client has left server:
- *
- */
- NETMSG_PLAYER_QUIT = 0x0102,
-
- /*
- * Client has moved
- *
- * uint16_t PlayerInput_Move
- */
- NETMSG_CLIENT_MOVE = 0x0201,
-
- /*
- * Initial player info
- *
- * Vector initial_position
- */
- NETMSG_PLAYER_INFO = 0x0300,
-
- /*
- * Player position update
- *
- * Vector position
- * Vector velocity
- * uint8_t NetworkPhysicsFlags
- */
- NETMSG_PLAYER_POSITION = 0x0301,
-};
-
-#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Address.hh Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,11 @@
+#ifndef NETWORK_ADDRESS_HH
+#define NETWORK_ADDRESS_HH
+
+#include <ClanLib/Network/Socket/ip_address.h>
+
+typedef CL_IPAddress NetworkAddress;
+
+// Network.cc
+std::ostream& operator<< (std::ostream &s, const NetworkAddress &addr);
+
+#endif /* NETWORK_ADDRESS_HH */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Client.cc Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,143 @@
+
+#include "Client.hh"
+#include "../Engine.hh"
+#include "../Logger.hh"
+
+#include <cassert>
+
+NetworkClient::NetworkClient (GameState &state, const NetworkAddress &connect_to) :
+ NetworkCore(state), netsession(NETWORK_MAGIC_ID), server(netsession.connect(connect_to)), netobjs(netsession, NETCHAN_CORE, server) {
+
+ // connect slots
+ slots.connect(netobjs.sig_create(), this, &NetworkClient::on_create);
+
+ // XXX: sig_disconnected
+}
+
+void NetworkClient::on_create (NetworkObject_Client *obj, NetworkMessageID msg_id, NetworkPacket &pkt) {
+ switch (msg_id) {
+ case NETMSG_SERVER_HELLO:
+ on_server_hello(obj, pkt);
+
+ break;
+
+ case NETMSG_PLAYER_INFO:
+ on_player_info(obj, pkt);
+
+ break;
+
+ case NETMSG_PLAYER_JOIN:
+ on_player_join(obj, pkt);
+
+ break;
+
+ default:
+ Engine::log(WARN, "client.on_create_object") << "unknown msg_id=" << msg_id << " for obj=" << obj;
+ }
+}
+
+void NetworkClient::on_server_hello (NetworkObject_Client *obj, NetworkPacket &pkt) {
+ // read the packet
+ Vector position = pkt.read_vector();
+
+ Engine::log(INFO, "client.on_server_hello") << "obj=" << obj << ", pos=" << position;
+
+ // create the LocalPlayer object
+ NetworkClientLocalPlayer *player = new NetworkClientLocalPlayer(*this, obj, position);
+
+ // inform state
+ state.newLocalPlayer(player);
+}
+
+void NetworkClient::on_player_info (NetworkObject_Client *obj, NetworkPacket &pkt) {
+ // read the packet
+ Vector position = pkt.read_vector();
+
+ Engine::log(INFO, "client.on_player_info") << "obj=" << obj << ", pos=" << position;
+
+ // create the LocalPlayer object
+ NetworkClientRemotePlayer *player = new NetworkClientRemotePlayer(*this, obj, position);
+
+ // inform state
+ state.newRemotePlayer(player);
+
+}
+
+void NetworkClient::on_player_join (NetworkObject_Client *obj, NetworkPacket &pkt) {
+ // read the packet
+ Vector position = pkt.read_vector();
+
+ Engine::log(INFO, "client.on_player_join") << "obj=" << obj << ", pos=" << position;
+
+ // create the RemotePlayer object
+ NetworkClientRemotePlayer *player = new NetworkClientRemotePlayer(*this, obj, position);
+
+ // inform state
+ state.newRemotePlayer(player);
+}
+
+void NetworkClient::player_quit (NetworkClientRemotePlayer *player) {
+ // inform state
+ state.removePlayer(player);
+
+ // delete
+ // XXX: leak because deleting the slot while it's being called breaks ClanLib
+ // delete player;
+}
+
+NetworkClientLocalPlayer::NetworkClientLocalPlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position) :
+ LocalPlayer(client.state, position, true), client(client), obj(obj) {
+
+ // receive messages
+ slots.connect(obj->sig_message(NETMSG_PLAYER_POSITION), this, &NetworkClientLocalPlayer::on_position);
+}
+
+void NetworkClientLocalPlayer::handleMove (PlayerInput_Move input) {
+ // always send move, in all cases
+ NetworkPacket pkt;
+ pkt.write_uint16(input);
+
+ obj->send(NETMSG_CLIENT_MOVE, pkt, false);
+
+ // do not handle locally
+}
+
+void NetworkClientLocalPlayer::on_position (NetworkPacket &pkt) {
+ Vector position = pkt.read_vector();
+ Vector velocity = pkt.read_vector();
+ uint8_t flags = pkt.read_uint8();
+
+ Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", position=" << position << ", velocity=" << velocity;
+
+ // just update...
+ updatePhysics(position, velocity, flags & NETWORK_PHYSICS_INAIR);
+}
+
+NetworkClientRemotePlayer::NetworkClientRemotePlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position) :
+ RemotePlayer(client.state, position, true), client(client), obj(obj) {
+
+ // receive messages
+ slots.connect(obj->sig_message(NETMSG_PLAYER_POSITION), this, &NetworkClientRemotePlayer::on_position);
+ slots.connect(obj->sig_message(NETMSG_PLAYER_QUIT), this, &NetworkClientRemotePlayer::on_quit);
+}
+
+void NetworkClientRemotePlayer::on_position (NetworkPacket &pkt) {
+ Vector position = pkt.read_vector();
+ Vector velocity = pkt.read_vector();
+ uint8_t flags = pkt.read_uint8();
+
+ Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", position=" << position << ", velocity=" << velocity;
+
+ // just update...
+ updatePhysics(position, velocity, flags & NETWORK_PHYSICS_INAIR);
+}
+
+void NetworkClientRemotePlayer::on_quit (NetworkPacket &pkt) {
+ // pkt is empty
+ (void) pkt;
+
+ Engine::log(INFO, "client_player.on_quit") << "obj=" << obj;
+
+ client.player_quit(this);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Client.hh Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,71 @@
+#ifndef NETWORKCLIENT_HH
+#define NETWORKCLIENT_HH
+
+#include "../GameState.hh"
+#include "Network.hh"
+#include "Session.hh"
+#include "Object.hh"
+
+// forward-declare
+class NetworkClientLocalPlayer;
+class NetworkClientRemotePlayer;
+
+class NetworkClient : public NetworkCore {
+ friend class NetworkClientLocalPlayer;
+ friend class NetworkClientRemotePlayer;
+
+ private:
+ NetworkSession netsession;
+ NetworkNode *server;
+
+ NetworkObject_ClientController netobjs;
+
+ public:
+ NetworkClient (GameState &state, const NetworkAddress &connect_to);
+
+ private:
+ void on_create (NetworkObject_Client *obj, NetworkMessageID msg_id, NetworkPacket &pkt);
+
+ void on_server_hello (NetworkObject_Client *obj, NetworkPacket &pkt);
+ void on_player_info (NetworkObject_Client *obj, NetworkPacket &pkt);
+ void on_player_join (NetworkObject_Client *obj, NetworkPacket &pkt);
+
+ public:
+ void player_quit (NetworkClientRemotePlayer *player);
+};
+
+class NetworkClientLocalPlayer : public LocalPlayer {
+ private:
+ NetworkClient &client;
+
+ CL_SlotContainer slots;
+
+ NetworkObject_Client *obj;
+
+ public:
+ NetworkClientLocalPlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position);
+
+ virtual void handleMove (PlayerInput_Move input);
+
+ private:
+ void on_position (NetworkPacket &pkt);
+};
+
+class NetworkClientRemotePlayer : public RemotePlayer {
+ private:
+ NetworkClient &client;
+
+ CL_SlotContainer slots;
+
+ NetworkObject_Client *obj;
+
+ public:
+ NetworkClientRemotePlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position);
+
+ private:
+ void on_position (NetworkPacket &pkt);
+
+ void on_quit (NetworkPacket &pkt);
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Config.hh Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,29 @@
+#ifndef NETWORK_CONFIG_HH
+#define NETWORK_CONFIG_HH
+
+// socket-related includes
+// copied from clanlib code, so should be relatively OS-safe
+#ifndef WIN32
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <sys/time.h>
+ #include <unistd.h>
+#else
+ #include <winsock2.h>
+ #include <windows.h>
+ typedef int socklen_t;
+#endif
+
+#include <string>
+
+const std::string NETWORK_PORT_STR = "9338";
+
+const size_t NETWORK_PACKET_SIZE = 1280;
+const int NETWORK_LISTEN_BACKLOG = 5;
+
+const char NETWORK_MAGIC_STR[8+1] = "KISNGLIS";
+const uint64_t NETWORK_MAGIC_ID = * ((const uint64_t *) NETWORK_MAGIC_STR);
+
+#endif /* NETWORK_CONFIG_HH */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Network.cc Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,29 @@
+#include "Network.hh"
+#include "Address.hh"
+#include "Socket.hh"
+#include "../Engine.hh"
+
+#include <sstream>
+#include <cstring>
+
+std::ostream& operator<< (std::ostream &s, const NetworkAddress &addr) {
+ s << "[" << addr.get_address() << ":" << addr.get_port() << "]";
+
+ return s;
+
+}
+
+std::string NetworkSocketError::build_str (const NetworkSocket &socket, const char *op, const char *err) {
+ std::stringstream ss;
+
+ ss << "socket #" << socket.get_socket() << " " << op << ": " << err;
+
+ return ss.str();
+}
+
+NetworkSocketError::NetworkSocketError (const NetworkSocket &socket, const char *op, const char *err) :
+ Error(build_str(socket, op, err)) {
+
+ // nothing
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Network.hh Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,83 @@
+#ifndef NETWORK_HH
+#define NETWORK_HH
+
+#include "Config.hh"
+#include "../GameState.hh"
+
+#include <ClanLib/network.h>
+
+const int32_t COORDINATE_MAX = 1 << 30;
+
+class NetworkCore {
+ protected:
+ GameState &state;
+
+ CL_SlotContainer slots;
+
+ // constructor
+ NetworkCore (GameState &state) : state(state) { }
+
+
+
+
+};
+
+enum NetworkChannel {
+ /*
+ * Core channel used for NetworkSession
+ */
+ NETCHAN_CORE = 0x01,
+};
+
+enum NetworkPhysicsFlags {
+ NETWORK_PHYSICS_INAIR = 0x01,
+};
+
+enum NetworkMessage {
+ NETMSG_PACKET_INVALID = 0x00,
+
+ /*
+ * You have joined the game:
+ *
+ * Vector initial_position
+ */
+ NETMSG_SERVER_HELLO = 0x0100,
+
+ /*
+ * New client has connected to server:
+ *
+ * Vector initial_position
+ */
+ NETMSG_PLAYER_JOIN = 0x0101,
+
+ /*
+ * Client has left server:
+ *
+ */
+ NETMSG_PLAYER_QUIT = 0x0102,
+
+ /*
+ * Client has moved
+ *
+ * uint16_t PlayerInput_Move
+ */
+ NETMSG_CLIENT_MOVE = 0x0201,
+
+ /*
+ * Initial player info
+ *
+ * Vector initial_position
+ */
+ NETMSG_PLAYER_INFO = 0x0300,
+
+ /*
+ * Player position update
+ *
+ * Vector position
+ * Vector velocity
+ * uint8_t NetworkPhysicsFlags
+ */
+ NETMSG_PLAYER_POSITION = 0x0301,
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Node.cc Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,51 @@
+
+#include <cassert>
+
+#include "Node.hh"
+
+NetworkNode::NetworkNode (NetworkSession &session, NetworkTCPTransport *tcp, NetworkUDP *udp, const NetworkAddress &address) :
+ session(session), tcp(tcp), udp(udp), address(address) {
+
+ // connect signals
+ slots.connect(tcp->sig_disconnect(), this, &NetworkNode::on_disconnect);
+ slots.connect(tcp->sig_packet(), &session, &NetworkSession::handle_message, this);
+
+}
+
+NetworkNode::~NetworkNode (void) {
+ delete tcp;
+}
+
+void NetworkNode::on_disconnect (void) {
+ // tell session
+ session.handle_disconnect(this);
+
+ // fire signal
+ _sig_disconnected();
+
+ // delete
+// delete this;
+}
+
+void NetworkNode::send (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable) {
+ assert(channel_id > 0);
+
+ // add our header
+ NetworkPacket pkt2;
+ pkt2.write_uint16(channel_id);
+ pkt2.write_packet(pkt);
+
+ // either tcp or udp
+ if (reliable) {
+ assert(tcp);
+
+ tcp->write_packet(pkt2);
+
+ } else {
+ udp->sendto(pkt2, address);
+ }
+}
+
+const NetworkAddress& NetworkNode::getRemoteAddress (void) {
+ return address;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Node.hh Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,45 @@
+#ifndef NETWORK_NODE_HH
+#define NETWORK_NODE_HH
+
+// forward-declare
+class NetworkNode;
+
+enum NetworkNodeType {
+ NETWORK_NODE_SERVER_CLIENT,
+ NETWORK_NODE_CLIENT_SERVER
+};
+
+#include "TCP.hh"
+#include "UDP.hh"
+#include "Session.hh"
+
+class NetworkNode {
+ private:
+ NetworkSession &session;
+ NetworkTCPTransport *tcp;
+ NetworkUDP *udp;
+ const NetworkAddress address;
+
+ CL_SlotContainer slots;
+
+ public:
+ NetworkNode (NetworkSession &session, NetworkTCPTransport *tcp, NetworkUDP *udp, const NetworkAddress &address);
+
+ private:
+ NetworkNode (const NetworkNode ©);
+ ~NetworkNode (void);
+ NetworkNode& operator= (const NetworkNode ©);
+
+ void on_disconnect (void);
+
+ CL_Signal_v0 _sig_disconnected;
+
+ public:
+ void send (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable = true);
+
+ const NetworkAddress& getRemoteAddress (void);
+
+ CL_Signal_v0& sig_disconnected (void) { return _sig_disconnected; }
+};
+
+#endif /* NETWORK_NODE_HH */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Object.cc Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,148 @@
+
+#include <cassert>
+
+#include "Object.hh"
+
+/*
+ * NetworkObject_Controller
+ */
+NetworkObjectController::NetworkObjectController (NetworkSession &session, NetworkChannelID channel_id) :
+ session(session), channel_id(channel_id) {
+
+ // setup signals
+ slot_message = session.sig_chan_message(channel_id).connect(this, &NetworkObjectController::on_message);
+}
+
+void NetworkObjectController::on_message (NetworkPacket &pkt, NetworkNode *node) {
+ uint32_t obj_id = pkt.read_uint32();
+ uint16_t msg_id = pkt.read_uint16();
+
+ // lookup object
+ NetworkObject *obj = objects[obj_id];
+
+ if (obj) {
+ obj->handle_packet(node, msg_id, pkt);
+
+ } else {
+ handle_create(obj_id, msg_id, pkt, node);
+ }
+}
+
+/*
+ * NetworkObject_ServerController
+ */
+NetworkObject_ServerController::NetworkObject_ServerController (NetworkSession &session, NetworkChannelID channel_id) :
+ NetworkObjectController(session, channel_id), id_pool(0) {
+
+}
+
+NetworkObjectID NetworkObject_ServerController::getObjectID (void) {
+ return ++id_pool;
+}
+
+void NetworkObject_ServerController::handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node) {
+ (void) obj_id;
+ (void) msg_id;
+ (void) pkt;
+ (void) node;
+
+ // XXX: fail
+ throw CL_Error("clients cannot create objects");
+}
+
+/*
+ * NetworkObject_ClientController *
+ */
+NetworkObject_ClientController::NetworkObject_ClientController (NetworkSession &session, NetworkChannelID channel_id, NetworkNode *server) :
+ NetworkObjectController(session, channel_id), server(server) {
+
+
+}
+
+void NetworkObject_ClientController::handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node) {
+ // we only communicate with the server
+ assert(node == server);
+
+ // create new object
+ NetworkObject_Client *obj = new NetworkObject_Client(*this, obj_id);
+
+ // signal
+ _sig_create(obj, msg_id, pkt);
+}
+
+/*
+ * NetworkObject
+ */
+NetworkObject::NetworkObject (NetworkObjectController &controller, NetworkObjectID obj_id) :
+ obj_id(obj_id) {
+
+ assert(obj_id);
+
+ controller.objects[obj_id] = this;
+}
+
+void NetworkObject::buildPacket (NetworkPacket &pkt, NetworkMessageID msg_id, const NetworkPacket &payload) {
+ pkt.write_uint32(obj_id);
+ pkt.write_uint16(msg_id);
+ pkt.write_packet(payload);
+}
+
+std::ostream& operator<< (std::ostream &s, const NetworkObject &obj) {
+ return s << "<NetworkObject #" << obj.obj_id << ">";
+}
+
+/*
+ * NetworkObject_Server
+ */
+NetworkObject_Server::NetworkObject_Server (NetworkObject_ServerController &controller) :
+ NetworkObject(controller, controller.getObjectID()), controller(controller) {
+
+}
+
+void NetworkObject_Server::handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt) {
+ _map_sig_message[msg_id](node, pkt);
+}
+
+void NetworkObject_Server::send_to (NetworkNode *dst, NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable) {
+ NetworkPacket pkt_out;
+
+ buildPacket(pkt_out, msg_id, pkt);
+
+ dst->send(controller.channel_id, pkt_out, reliable);
+}
+
+void NetworkObject_Server::send_all (NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable) {
+ send_all_except(msg_id, pkt, NULL, reliable);
+}
+
+void NetworkObject_Server::send_all_except (NetworkMessageID msg_id, const NetworkPacket &pkt, NetworkNode *black_sheep, bool reliable) {
+ NetworkPacket pkt_out;
+
+ buildPacket(pkt_out, msg_id, pkt);
+
+ controller.session.send_all_except(controller.channel_id, pkt_out, black_sheep, reliable);
+}
+
+/*
+ * NetworkObject_Client
+ */
+NetworkObject_Client::NetworkObject_Client (NetworkObject_ClientController &controller, NetworkObjectID id) :
+ NetworkObject(controller, id), controller(controller) {
+
+ // nothing
+}
+
+void NetworkObject_Client::handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt) {
+ assert(node == controller.server);
+
+ _map_sig_message[msg_id](pkt);
+}
+
+void NetworkObject_Client::send (NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable) {
+ NetworkPacket pkt_out;
+
+ buildPacket(pkt_out, msg_id, pkt);
+
+ controller.server->send(controller.channel_id, pkt_out, reliable);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Object.hh Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,132 @@
+#ifndef NETWORK_OBJECT_HH
+#define NETWORK_OBJECT_HH
+
+#include "Session.hh"
+#include "Node.hh"
+#include "../Logger.hh"
+
+#include <map>
+
+typedef uint32_t NetworkObjectID;
+typedef uint16_t NetworkMessageID;
+
+// forward-declare
+class NetworkObject;
+class NetworkObject_Client;
+class NetworkObject_Server;
+
+class NetworkObjectController {
+ friend class NetworkObject;
+ friend class NetworkObject_Server;
+ friend class NetworkObject_Client;
+
+ private:
+ NetworkSession &session;
+ NetworkChannelID channel_id;
+
+ std::map<NetworkObjectID, NetworkObject*> objects;
+
+ CL_Slot slot_message;
+
+ protected:
+ NetworkObjectController (NetworkSession &session, NetworkChannelID channel_id);
+
+ private:
+ void on_message (NetworkPacket &pkt, NetworkNode *node);
+
+ protected:
+ virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node) = 0;
+};
+
+class NetworkObject_ServerController : public NetworkObjectController {
+ friend class NetworkObject_Server;
+
+ private:
+ NetworkObjectID id_pool;
+
+ public:
+ NetworkObject_ServerController (NetworkSession &session, NetworkChannelID channel_id);
+
+ protected:
+ NetworkObjectID getObjectID (void);
+
+ virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node);
+};
+
+class NetworkObject_ClientController : public NetworkObjectController {
+ friend class NetworkObject_Client;
+
+ private:
+ NetworkNode *server;
+
+ CL_Signal_v3<NetworkObject_Client*, NetworkMessageID, NetworkPacket&> _sig_create;
+
+ public:
+ NetworkObject_ClientController (NetworkSession &session, NetworkChannelID channel_id, NetworkNode *server);
+
+ protected:
+ virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node);
+
+ public:
+ CL_Signal_v3<NetworkObject_Client*, NetworkMessageID, NetworkPacket&>& sig_create (void) { return _sig_create; }
+};
+
+class NetworkObject {
+ friend class NetworkObjectController;
+ friend std::ostream& operator<< (std::ostream &s, const NetworkObject &obj);
+
+ protected:
+ NetworkObjectID obj_id;
+
+ protected:
+ NetworkObject (NetworkObjectController &controller, NetworkObjectID obj_id);
+
+ virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt) = 0;
+
+ void buildPacket (NetworkPacket &pkt, NetworkMessageID msg_id, const NetworkPacket &payload);
+};
+
+std::ostream& operator<< (std::ostream &s, const NetworkObject &obj);
+
+class NetworkObject_Server : public NetworkObject {
+ friend class NetworkObject_ServerController;
+
+ private:
+ NetworkObject_ServerController &controller;
+
+ std::map<NetworkMessageID, CL_Signal_v2<NetworkNode*, NetworkPacket&> > _map_sig_message;
+
+ public:
+ NetworkObject_Server (NetworkObject_ServerController &controller);
+
+ protected:
+ virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt);
+
+ public:
+ void send_to (NetworkNode *dst, NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable = true);
+ void send_all (NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable = true);
+ void send_all_except (NetworkMessageID msg_id, const NetworkPacket &pkt, NetworkNode *black_sheep, bool reliable = true);
+
+ CL_Signal_v2<NetworkNode*, NetworkPacket&>& sig_message (NetworkMessageID msg_id) { return _map_sig_message[msg_id]; }
+};
+
+class NetworkObject_Client : public NetworkObject {
+ friend class NetworkObject_ClientController;
+
+ private:
+ NetworkObject_ClientController &controller;
+
+ std::map<NetworkMessageID, CL_Signal_v1<NetworkPacket&> > _map_sig_message;
+
+ protected:
+ NetworkObject_Client (NetworkObject_ClientController &controller, NetworkObjectID id);
+
+ virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt);
+
+ public:
+ void send (NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable = true);
+
+ CL_Signal_v1<NetworkPacket&>& sig_message (NetworkMessageID msg_id) { return _map_sig_message[msg_id]; }
+};
+
+#endif /* NETWORK_OBJECT_HH */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Packet.cc Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,144 @@
+
+#include <cassert>
+#include <cstring>
+
+#include "Packet.hh"
+
+
+NetworkPacket::NetworkPacket (void) :
+ buf_size(NETWORK_PACKET_SIZE), data_size(0), offset(0) {
+
+ // nothing
+}
+
+void NetworkPacket::check_write_size (size_t item_size) {
+ if (offset + item_size > buf_size)
+ throw NetworkPacketError("not enough space to write");
+
+}
+
+void NetworkPacket::check_read_size (size_t item_size) {
+ if (offset + item_size > data_size)
+ throw NetworkPacketError("not enough data to read");
+}
+
+void NetworkPacket::write (const void *ptr, size_t len) {
+ // check buffer overflow
+ check_write_size(len);
+
+ // set value
+ memcpy(buf + offset, ptr, len);
+
+ // update offset and size
+ offset += len;
+ data_size += len;
+}
+
+void NetworkPacket::read (void *ptr, size_t len) {
+ // check buffer underflow
+ check_read_size(len);
+
+ // set value
+ memcpy(ptr, buf + offset, len);
+
+ // update offset
+ offset += len;
+}
+
+template <typename T> T NetworkPacket::read_val (void) {
+ T val;
+
+ // read
+ read(&val, sizeof(T));
+
+ // return
+ return val;
+}
+
+template <typename T> void NetworkPacket::write_val (const T &val) {
+ // write
+ write(&val, sizeof(T));
+}
+
+uint32_t NetworkPacket::read_uint32 (void) {
+ return ntohl(read_val<uint32_t>());
+}
+
+uint16_t NetworkPacket::read_uint16 (void) {
+ return ntohs(read_val<uint16_t>());
+}
+
+uint8_t NetworkPacket::read_uint8 (void) {
+ return read_val<uint8_t>();
+}
+
+int32_t NetworkPacket::read_int32 (void) {
+ return ntohl(read_val<int32_t>());
+}
+
+int16_t NetworkPacket::read_int16 (void) {
+ return ntohs(read_val<int16_t>());
+}
+
+int8_t NetworkPacket::read_int8 (void) {
+ return read_val<int8_t>();
+}
+
+float NetworkPacket::read_float32 (void) {
+ int32_t ival = read_int32();
+
+ return *((float *) &ival);
+}
+
+Vector NetworkPacket::read_vector (void) {
+ float fx = read_float32();
+ float fy = read_float32();
+
+ return Vector(fx, fy);
+}
+
+void NetworkPacket::write_uint32 (uint32_t val) {
+ write_val<uint32_t>(htonl(val));
+}
+
+void NetworkPacket::write_uint16 (uint16_t val) {
+ write_val<uint16_t>(htons(val));
+}
+
+void NetworkPacket::write_uint8 (uint8_t val) {
+ write_val<uint8_t>(val);
+}
+
+void NetworkPacket::write_int32 (int32_t val) {
+ write_val<int32_t>(htonl(val));
+}
+
+void NetworkPacket::write_int16 (int16_t val) {
+ write_val<int16_t>(htons(val));
+}
+
+void NetworkPacket::write_int8 (int8_t val) {
+ write_val<int8_t>(val);
+}
+
+void NetworkPacket::write_float32 (float val) {
+ write_int32(*((int32_t *) &val));
+}
+
+void NetworkPacket::write_vector (const Vector &vec) {
+ write_float32(vec.x);
+ write_float32(vec.y);
+}
+
+void NetworkPacket::write_packet (const NetworkPacket &pkt) {
+ // check buffer size
+ check_write_size(pkt.get_data_size());
+
+ // copy
+ memcpy(buf + offset, pkt.get_buf(), pkt.get_data_size());
+
+ // update offset/data_size
+ offset += pkt.get_data_size();
+ data_size += pkt.get_data_size();
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Packet.hh Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,66 @@
+#ifndef NETWORK_PACKET_HH
+#define NETWORK_PACKET_HH
+
+#include "Config.hh"
+#include "../Vector.hh"
+#include "../Error.hh"
+
+class NetworkPacketError : public Error {
+ public:
+ NetworkPacketError (const std::string &message) : Error(message) { }
+};
+
+class NetworkPacket {
+ private:
+ char buf[NETWORK_PACKET_SIZE];
+ size_t buf_size, data_size, offset;
+
+ void check_write_size (size_t item_size);
+ void check_read_size (size_t item_size);
+
+ template <typename T> T read_val (void);
+ template <typename T> void write_val (const T &val);
+
+ public:
+ NetworkPacket (void);
+
+ char* get_buf (void) { return buf; }
+ const char* get_buf (void) const { return buf; }
+ size_t get_data_size (void) const { return data_size; }
+ size_t get_buf_size (void) const { return buf_size; }
+
+ void set_data_size (size_t size) { offset = 0; data_size = size; }
+
+ // raw
+ void write (const void *ptr, size_t len);
+ void read (void *ptr, size_t len);
+
+ // type-reads, handle network-endianlness
+ uint32_t read_uint32 (void);
+ uint16_t read_uint16 (void);
+ uint8_t read_uint8 (void);
+
+ int32_t read_int32 (void);
+ int16_t read_int16 (void);
+ int8_t read_int8 (void);
+
+ float read_float32 (void);
+
+
+ void write_uint32 (uint32_t val);
+ void write_uint16 (uint16_t val);
+ void write_uint8 (uint8_t val);
+
+ void write_int32 (int32_t val);
+ void write_int16 (int16_t val);
+ void write_int8 (int8_t val);
+
+ void write_float32 (float val);
+
+ // complex
+ Vector read_vector (void);
+ void write_vector (const Vector &vec);
+ void write_packet (const NetworkPacket &pkt);
+};
+
+#endif /* NETWORK_PACKET_HH */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Server.cc Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,114 @@
+#include "Server.hh"
+#include "../Engine.hh"
+#include "../Logger.hh"
+
+#include <cassert>
+
+NetworkServer::NetworkServer (GameState &state, const NetworkAddress &listen_addr) :
+ NetworkCore(state), netsession(NETWORK_MAGIC_ID), netobjs(netsession, NETCHAN_CORE) {
+
+ // connect slots
+ slots.connect(netsession.sig_node_connected(), this, &NetworkServer::on_node_connected);
+
+ // and then we listen
+ netsession.listen(listen_addr);
+
+ Engine::log(INFO, "server") << "running, listen_addr=" << listen_addr;
+}
+
+void NetworkServer::on_node_connected (NetworkNode *node) {
+ // create the player object (it logs it)
+ NetworkServerPlayer *player = new NetworkServerPlayer(*this, node);
+
+ // add to players
+ players.push_back(player);
+
+ // add to GameState
+ state.newRemotePlayer(player);
+}
+
+void NetworkServer::handle_disconnect (NetworkServerPlayer *player) {
+ // remove from state
+ state.removePlayer(player);
+
+ // remove from list
+ players.remove(player);
+}
+
+NetworkServerPlayer::NetworkServerPlayer (NetworkServer &server, NetworkNode *node) :
+ RemotePlayer(server.state, Vector(PLAYER_INITIAL_X, PLAYER_INITIAL_Y), true), server(server), obj(server.netobjs), node(node) {
+
+ // log
+ Engine::log(INFO, "server_player.connected") << "node=" << node << ", obj=" << obj;
+
+ // messages
+ slots.connect(node->sig_disconnected(), this, &NetworkServerPlayer::on_disconnected);
+ slots.connect(obj.sig_message(NETMSG_CLIENT_MOVE), this, &NetworkServerPlayer::on_move);
+
+ // the initial NETMSG_PLAYER_HELLO
+ NetworkPacket hello_pkt;
+ hello_pkt.write_vector(position);
+
+ obj.send_to(node, NETMSG_SERVER_HELLO, hello_pkt, true);
+
+ // send other player objects
+ for (std::list<NetworkServerPlayer*>::iterator it = server.players.begin(); it != server.players.end(); it++) {
+ NetworkServerPlayer *player = *it;
+ NetworkPacket player_pkt;
+
+ // player is not in players list yet
+ assert(player != this);
+
+ player_pkt.write_vector(player->position);
+
+ player->obj.send_to(node, NETMSG_PLAYER_INFO, player_pkt, true);
+ }
+
+ // broadcast NETMSG_PLAYER_JOIN to all clients except current
+ obj.send_all_except(NETMSG_PLAYER_JOIN, hello_pkt, node, true);
+}
+
+void NetworkServerPlayer::on_disconnected (void) {
+ NetworkPacket pkt;
+
+ Engine::log(INFO, "server_player.disconnected") << "node=" << node << ", obj=" << obj;
+
+ // remove from server
+ server.handle_disconnect(this);
+
+ // tell other clients
+ obj.send_all(NETMSG_PLAYER_QUIT, pkt, true);
+
+ // free
+// delete this;
+}
+
+void NetworkServerPlayer::on_move (NetworkNode *src, NetworkPacket &pkt) {
+ // sanity-check, other players shouldn't move
+ if (src != node) {
+ Engine::log(WARN, "server_player.on_move") << "packet from wrong src=" << src << ", node=" << node;
+ return;
+ }
+
+ PlayerInput_Move input = pkt.read_uint16();
+
+ Engine::log(INFO, "server_player.on_move") << "player=" << obj << ", old_pos=" << position << ", input=" << input;
+
+ // apply input
+ handleMove(input);
+
+ // send position update
+ send_position_update();
+}
+
+void NetworkServerPlayer::send_position_update (void) {
+ NetworkPacket pkt;
+ pkt.write_vector(position);
+ pkt.write_vector(velocity);
+ pkt.write_uint8(inAir & NETWORK_PHYSICS_INAIR);
+
+ Engine::log(INFO, "server_player.send_position_update") << "obj=" << obj << " -> " << position << "+" << velocity;
+
+ obj.send_all(NETMSG_PLAYER_POSITION, pkt, false);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Server.hh Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,52 @@
+#ifndef NETWORKSERVER_HH
+#define NETWORKSERVER_HH
+
+#include "Network.hh"
+#include "../GameState.hh"
+#include "Session.hh"
+#include "Object.hh"
+
+#include <list>
+#include <map>
+#include <ClanLib/core.h>
+
+// forward-declare
+class NetworkServerPlayer;
+
+class NetworkServer : public NetworkCore {
+ friend class NetworkServerPlayer;
+
+ protected:
+ NetworkSession netsession;
+ NetworkObject_ServerController netobjs;
+ std::list<NetworkServerPlayer *> players;
+
+ public:
+ NetworkServer (GameState &state, const NetworkAddress &listen_addr);
+
+ protected:
+ void handle_disconnect (NetworkServerPlayer *player);
+
+ private:
+ void on_node_connected (NetworkNode *node);
+};
+
+class NetworkServerPlayer : public RemotePlayer {
+ private:
+ NetworkServer &server;
+ NetworkObject_Server obj;
+ NetworkNode *node;
+
+ CL_SlotContainer slots;
+
+ public:
+ NetworkServerPlayer (NetworkServer &server, NetworkNode *node);
+
+ private:
+ void on_disconnected (void);
+ void on_move (NetworkNode *node, NetworkPacket &pkt);
+
+ void send_position_update (void);
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Session.cc Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,107 @@
+
+#include "Session.hh"
+#include "../Engine.hh"
+
+#include <cassert>
+
+NetworkSession::NetworkSession (uint64_t magic) :
+ magic(magic), tcp_srv(NULL), udp_srv(NULL), udp_client(NULL) {
+
+ // nothing
+}
+
+void NetworkSession::listen (const NetworkAddress &addr) {
+ assert(tcp_srv == NULL && udp_srv == NULL);
+
+ // create TCP/UDP servers
+ tcp_srv = new NetworkTCPServer(addr);
+ udp_srv = new NetworkUDP(addr);
+
+ // connect signals
+ slots.connect(tcp_srv->sig_client(), this, &NetworkSession::on_tcp_client);
+ slots.connect(udp_srv->sig_packet(), this, &NetworkSession::on_udp_packet);
+}
+
+NetworkNode *NetworkSession::build_node (NetworkTCPTransport *tcp, NetworkUDP *udp, const NetworkAddress &addr, enum NetworkNodeType type) {
+ // XXX: unused
+ (void) type;
+
+ // create node
+ return new NetworkNode(*this, tcp, udp, addr);
+}
+
+NetworkNode* NetworkSession::connect (const NetworkAddress &addr) {
+ // XXX: only one connect
+ assert(!udp_client);
+
+ // connect TCP
+ NetworkTCPClient *tcp_client = new NetworkTCPClient(addr);
+
+ // create UDP socket on same address
+ udp_client = new NetworkUDP(tcp_client->getLocalAddress());
+
+ // build client
+ NetworkNode *client_node = build_node(tcp_client, udp_client, addr, NETWORK_NODE_CLIENT_SERVER);
+
+ // add to nodes
+ nodes[addr] = client_node;
+
+ // connect signals
+ slots.connect(udp_client->sig_packet(), this, &NetworkSession::on_udp_packet);
+
+ // return the "server" node
+ return client_node;
+}
+
+void NetworkSession::handle_disconnect (NetworkNode *node) {
+ // remove from nodes
+ nodes.erase(node->getRemoteAddress());
+}
+
+void NetworkSession::handle_message (NetworkPacket &pkt, NetworkNode *node) {
+ // read the channel id
+ NetworkChannelID channel_id = pkt.read_uint16();
+
+ // fire signal
+ _map_sig_chan_message[channel_id](pkt, node);
+}
+
+void NetworkSession::on_tcp_client (NetworkTCPTransport *tcp_client) {
+ // get remote address manually, because NetworkTCPServer doesn't pass it in to us
+ NetworkAddress addr = tcp_client->getRemoteAddress();
+
+ // build client
+ NetworkNode *client_node = build_node(tcp_client, udp_srv, addr, NETWORK_NODE_SERVER_CLIENT);
+
+ // add to nodes
+ nodes[addr] = client_node;
+
+ // fire signals
+ _sig_node_connected(client_node);
+}
+
+void NetworkSession::on_udp_packet (NetworkPacket &pkt, const NetworkAddress &addr) {
+ NetworkNode *node = nodes[addr];
+
+ // drop from unknown sources
+ if (!node) {
+ Engine::log(WARN, "net_session.on_udp_packet") << "dropping unsolicted UDP packet from " << addr;
+ return;
+ }
+
+ // handle
+ handle_message(pkt, node);
+}
+
+void NetworkSession::send_all (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable) {
+ send_all_except(channel_id, pkt, NULL, reliable);
+}
+
+void NetworkSession::send_all_except (NetworkChannelID channel_id, const NetworkPacket &pkt, const NetworkNode *node, bool reliable) {
+ for (std::map<NetworkAddress, NetworkNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
+ if (it->second == node)
+ continue;
+
+ it->second->send(channel_id, pkt, reliable);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Session.hh Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,58 @@
+#ifndef NETWORK_SESSION_HH
+#define NETWORK_SESSION_HH
+
+#include <map>
+#include <stdint.h>
+
+// forward-declare
+class NetworkSession;
+
+/*
+ * Used to separate packets, ID zero is reserved for NetworkSession use
+ */
+typedef uint16_t NetworkChannelID;
+
+#include "TCP.hh"
+#include "UDP.hh"
+#include "Node.hh"
+
+class NetworkSession {
+ friend class NetworkNode;
+
+ private:
+ uint64_t magic;
+ NetworkTCPServer *tcp_srv;
+ NetworkUDP *udp_srv, *udp_client;
+
+ CL_SlotContainer slots;
+
+ std::map<NetworkAddress, NetworkNode*> nodes;
+ std::map<NetworkChannelID, CL_Signal_v2<NetworkPacket&, NetworkNode *> > _map_sig_chan_message;
+
+ public:
+ NetworkSession (uint64_t magic);
+
+ void listen (const NetworkAddress &addr);
+ NetworkNode* connect (const NetworkAddress &addr);
+
+ protected:
+ virtual NetworkNode *build_node (NetworkTCPTransport *tcp, NetworkUDP *udp, const NetworkAddress &addr, enum NetworkNodeType type);
+
+ void handle_disconnect (NetworkNode *node);
+ void handle_message (NetworkPacket &pkt, NetworkNode *node);
+
+ private:
+ void on_tcp_client (NetworkTCPTransport *client);
+ void on_udp_packet (NetworkPacket &pkt, const NetworkAddress &addr);
+
+ CL_Signal_v1<NetworkNode*> _sig_node_connected;
+
+ public:
+ void send_all (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable = true);
+ void send_all_except (NetworkChannelID channel_id, const NetworkPacket &pkt, const NetworkNode *node, bool reliable = true);
+
+ CL_Signal_v1<NetworkNode*>& sig_node_connected (void) { return _sig_node_connected; }
+ CL_Signal_v2<NetworkPacket&, NetworkNode *>& sig_chan_message (NetworkChannelID cid) { return _map_sig_chan_message[cid]; }
+};
+
+#endif /* NETWORK_SESSION_HH */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Socket.hh Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,32 @@
+#ifndef NETWORK_SOCKET_HH
+#define NETWORK_SOCKET_HH
+
+#include "../Error.hh"
+
+#include <ClanLib/Network/Socket/socket.h>
+#include <cerrno>
+#include <cstring>
+
+typedef CL_Socket NetworkSocket;
+
+// Network.cc
+class NetworkSocketError : public Error {
+ protected:
+ std::string build_str (const NetworkSocket &socket, const char *op, const char *err);
+
+ NetworkSocketError (const NetworkSocket &socket, const char *op, const char *err);
+};
+
+class NetworkSocketOSError : public NetworkSocketError {
+ public:
+ NetworkSocketOSError (const NetworkSocket &socket, const char *op) :
+ NetworkSocketError(socket, op, strerror(errno)) { }
+};
+
+class NetworkSocketEOFError : public NetworkSocketError {
+ public:
+ NetworkSocketEOFError (const NetworkSocket &socket, const char *op) :
+ NetworkSocketError(socket, op, "EOF") { }
+};
+
+#endif /* NETWORK_SOCKET_HH */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/TCP.cc Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,325 @@
+
+#include "TCP.hh"
+#include "../Engine.hh"
+
+#include <cstdlib>
+#include <cassert>
+
+NetworkBuffer::NetworkBuffer (NetworkSocket &socket, size_t size_hint) :
+ socket(socket), buf(0), size(0), offset(0) {
+
+ // allocate initial buffer
+ if ((buf = (char *) malloc(size_hint)) == NULL)
+ throw NetworkBufferError("malloc failed");
+
+ // remember size
+ size = size_hint;
+}
+
+NetworkBuffer::~NetworkBuffer (void) {
+ free(buf);
+}
+
+void NetworkBuffer::resize (size_t item_size) {
+ size_t new_size = size;
+
+ // grow new_size until item_size fits
+ while (offset + item_size > new_size)
+ new_size *= 2;
+
+ // grow if needed
+ if (new_size != size) {
+ // realloc buffer
+ if ((buf = (char *) realloc((void *) buf, new_size)) == NULL)
+ throw NetworkBufferError("realloc failed");
+
+ // update size
+ size = new_size;
+
+ } else if (new_size > (offset + item_size) * 4) {
+ // XXX: shrink?
+ }
+}
+
+void NetworkBuffer::trim (size_t prefix_size) {
+ // update offset
+ offset -= prefix_size;
+
+ // shift the buffer forwards from (buf + prefix) -> (buf), copying (old_offset - prefix) bytes
+ memmove(buf, buf + prefix_size, offset);
+}
+
+bool NetworkBuffer::try_read (size_t item_size) {
+ int ret;
+ size_t to_read = item_size;
+
+ // keept reads at at least NETWORK_CHUNK_SIZE bytes
+ if (to_read < NETWORK_TCP_CHUNK_SIZE)
+ to_read = NETWORK_TCP_CHUNK_SIZE;
+
+ // resize buffer if needed
+ resize(to_read);
+
+ // read once
+ try {
+ ret = socket.recv(buf + offset, to_read);
+
+ } catch (CL_Error &e) {
+ if (errno == EAGAIN)
+ return false;
+
+ else
+ throw NetworkSocketOSError(socket, "recv");
+ }
+
+ // handle EOF
+ if (ret == 0)
+ throw NetworkSocketEOFError(socket, "recv");
+
+ assert(ret >= 0);
+
+ // update offset
+ offset += ret;
+
+ // did we get enough?
+ if ((unsigned int) ret < item_size)
+ return false;
+ else
+ return true;
+}
+
+bool NetworkBuffer::peek_prefix (uint16_t &ref) {
+ if (offset < sizeof(uint16_t))
+ return false;
+
+ ref = ntohs(*((uint16_t *) (buf)));
+
+ return true;
+}
+
+bool NetworkBuffer::peek_prefix (uint32_t &ref) {
+ if (offset < sizeof(uint32_t))
+ return false;
+
+ ref = ntohl(*((uint32_t *) (buf)));
+
+ return true;
+}
+
+template <typename PrefixType> PrefixType NetworkBuffer::read_prefix (char *buf_ptr, size_t buf_max) {
+ PrefixType prefix = 0;
+ size_t missing = 0;
+
+ do {
+ // do we have the prefix?
+ if (peek_prefix(prefix)) {
+ // do we already have the payload?
+ if (offset >= sizeof(PrefixType) + prefix) {
+ break;
+
+ } else {
+ missing = (sizeof(PrefixType) + prefix) - offset;
+ }
+
+ } else {
+ missing = sizeof(PrefixType);
+ }
+
+ // sanity-check
+ assert(missing);
+
+ // try and read the missing data
+ if (try_read(missing) == false) {
+ // if unable to read what we need, return zero.
+ return 0;
+ }
+
+ // assess the situation again
+ } while (true);
+
+ // copy the data over, unless it's too large
+ if (prefix <= buf_max) {
+ // ...don't copy the prefix, though
+ memcpy(buf_ptr, buf + sizeof(PrefixType), prefix);
+
+ // trim the bytes out
+ trim(sizeof(PrefixType) + prefix);
+
+ // return
+ return prefix;
+
+ } else {
+ // trim the bytes out
+ trim(sizeof(PrefixType) + prefix);
+
+ throw NetworkBufferError("recv prefix overflow");
+ }
+}
+
+void NetworkBuffer::push_write (char *buf_ptr, size_t buf_size) {
+ int ret;
+
+ // try and short-circuit writes unless we have already buffered data
+ if (offset == 0) {
+ try {
+ // attempt to send something
+ ret = socket.send(buf_ptr, buf_size);
+
+ } catch (CL_Error &e) {
+ // ignore EAGAIN, detect this by setting ret to -1
+ if (errno != EAGAIN)
+ throw NetworkSocketOSError(socket, "send");
+
+ ret = -1;
+ }
+
+ // if we managed to send something, adjust buf/size and buffer
+ if (ret > 0) {
+ // sanity-check
+ assert(buf_size >= (unsigned int) ret);
+
+ buf_ptr += ret;
+ buf_size -= ret;
+
+ // if that was all, we're done
+ if (buf_size == 0)
+ return;
+ }
+ }
+
+ // resize to fit buf_size more bytes
+ resize(buf_size);
+
+ // copy into our internal buffer
+ memcpy(buf + offset, buf_ptr, buf_size);
+}
+
+void NetworkBuffer::flush_write (void) {
+ int ret;
+
+ // ignore if we don't have any data buffered
+ if (offset == 0)
+ return;
+
+ // attempt to write as much as possible
+ try {
+ ret = socket.send(buf, offset);
+
+ } catch (CL_Error &e) {
+ // ignore EAGAIN and just return
+ if (errno == EAGAIN)
+ return;
+
+ else
+ throw NetworkSocketOSError(socket, "send");
+ }
+
+ // trim the buffer
+ trim(ret);
+}
+
+void NetworkBuffer::write_prefix (char *buf, uint16_t prefix) {
+ uint16_t nval = htons(prefix);
+
+ push_write((char*) &nval, sizeof(uint16_t));
+ push_write(buf, prefix);
+}
+
+void NetworkBuffer::write_prefix (char *buf, uint32_t prefix) {
+ uint32_t nval = htonl(prefix);
+
+ push_write((char*) &nval, sizeof(uint32_t));
+ push_write(buf, prefix);
+}
+
+NetworkTCPTransport::NetworkTCPTransport (NetworkSocket socket) :
+ socket(socket), in(socket, NETWORK_TCP_INITIAL_IN_BUF), out(socket, NETWORK_TCP_INITIAL_OUT_BUF) {
+
+ // connect signals
+ slots.connect(socket.sig_read_triggered(), this, &NetworkTCPTransport::on_read);
+ slots.connect(socket.sig_write_triggered(), this, &NetworkTCPTransport::on_write);
+ slots.connect(socket.sig_disconnected(), this, &NetworkTCPTransport::on_disconnected);
+}
+
+
+void NetworkTCPTransport::on_read (void) {
+ uint16_t prefix;
+ NetworkPacket packet;
+
+ // let the in stream read length-prefixed packets and pass them on to handle_packet
+ while ((prefix = in.read_prefix<uint16_t>(packet.get_buf(), packet.get_buf_size())) > 0) {
+ packet.set_data_size(prefix);
+ _sig_packet(packet);
+ }
+}
+
+void NetworkTCPTransport::on_write (void) {
+ // just flush the output buffer
+ out.flush_write();
+}
+
+void NetworkTCPTransport::on_disconnected (void) {
+ // pass right through
+ _sig_disconnect();
+}
+
+void NetworkTCPTransport::write_packet (const NetworkPacket &packet) {
+ uint16_t prefix = packet.get_data_size();
+
+ if (prefix != packet.get_data_size())
+ throw CL_Error("send prefix overflow");
+
+ try {
+ // just write to the output buffer
+ out.write_prefix((char *) packet.get_buf(), prefix);
+
+ } catch (Error &e) {
+ const char *err = e.what();
+
+ Engine::log(ERROR, "tcp.write_packet") << err;
+
+ throw;
+ }
+}
+
+NetworkTCPServer::NetworkTCPServer (const NetworkAddress &listen_addr) :
+ socket(CL_Socket::tcp, CL_Socket::ipv4) {
+
+ // bind
+ socket.bind(listen_addr);
+
+ // assign slots
+ slots.connect(socket.sig_read_triggered(), this, &NetworkTCPServer::on_accept);
+
+ // listen
+ socket.listen(NETWORK_LISTEN_BACKLOG);
+
+ // use nonblocking sockets
+ socket.set_nonblocking(true);
+}
+
+
+void NetworkTCPServer::on_accept (void) {
+ // accept a new socket
+ NetworkSocket client_sock = socket.accept();
+
+ // create a new NetworkTCPTransport
+ NetworkTCPTransport *client = buildTransport(client_sock);
+
+ // let our user handle it
+ _sig_client(client);
+}
+
+NetworkTCPTransport* NetworkTCPServer::buildTransport (CL_Socket &socket) {
+ return new NetworkTCPTransport(socket);
+}
+
+NetworkTCPClient::NetworkTCPClient (const NetworkAddress &connect_addr) :
+ NetworkTCPTransport(NetworkSocket(CL_Socket::tcp, CL_Socket::ipv4)) {
+
+ // connect
+ socket.connect(connect_addr);
+
+ // use nonblocking sockets
+ socket.set_nonblocking(true);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/TCP.hh Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,105 @@
+#ifndef NETWORK_TCP_HH
+#define NETWORK_TCP_HH
+
+#include <ClanLib/core.h>
+
+#include "Socket.hh"
+#include "Address.hh"
+#include "Packet.hh"
+#include "../Error.hh"
+
+const size_t NETWORK_TCP_CHUNK_SIZE = 1024;
+const size_t NETWORK_TCP_INITIAL_IN_BUF = 4096;
+const size_t NETWORK_TCP_INITIAL_OUT_BUF = 0;
+
+class NetworkBufferError : public Error {
+ public:
+ NetworkBufferError (const std::string &message) : Error(message) { }
+};
+
+class NetworkBuffer {
+ private:
+ NetworkSocket socket;
+
+ char *buf;
+ size_t size, offset;
+
+ public:
+ NetworkBuffer (NetworkSocket &socket, size_t size_hint);
+ ~NetworkBuffer (void);
+
+ private:
+ NetworkBuffer (const NetworkBuffer ©);
+ NetworkBuffer& operator= (const NetworkBuffer ©);
+
+ void resize (size_t item_size);
+ void trim (size_t prefix_size);
+
+ public:
+ void push_write (char *buf_ptr, size_t buf_size);
+ void flush_write (void);
+ void write_prefix (char *buf, uint16_t prefix);
+ void write_prefix (char *buf, uint32_t prefix);
+
+ bool try_read (size_t item_size);
+ bool peek_prefix (uint16_t &ref);
+ bool peek_prefix (uint32_t &ref);
+ template <typename PrefixType> PrefixType read_prefix (char *buf_ptr, size_t buf_max);
+};
+
+class NetworkTCPTransport {
+ protected:
+ NetworkSocket socket;
+
+ NetworkBuffer in, out;
+
+ CL_SlotContainer slots;
+
+ public:
+ NetworkTCPTransport (NetworkSocket socket);
+
+ private:
+ void on_read (void);
+ void on_write (void);
+ void on_disconnected (void);
+
+ CL_Signal_v1<NetworkPacket &> _sig_packet;
+ CL_Signal_v0 _sig_disconnect;
+
+ public:
+ NetworkAddress getLocalAddress (void) { return socket.get_source_address(); }
+ NetworkAddress getRemoteAddress (void) { return socket.get_dest_address(); }
+
+ void write_packet (const NetworkPacket &packet);
+
+ CL_Signal_v1<NetworkPacket&>& sig_packet (void) { return _sig_packet; }
+ CL_Signal_v0& sig_disconnect (void) { return _sig_disconnect; }
+};
+
+class NetworkTCPServer {
+ private:
+ NetworkSocket socket;
+
+ CL_SlotContainer slots;
+
+ public:
+ NetworkTCPServer (const NetworkAddress &listen_addr);
+
+ private:
+ void on_accept (void);
+
+ CL_Signal_v1<NetworkTCPTransport *> _sig_client;
+
+ protected:
+ virtual NetworkTCPTransport* buildTransport (CL_Socket &socket);
+
+ public:
+ CL_Signal_v1<NetworkTCPTransport *>& sig_client (void) { return _sig_client; }
+};
+
+class NetworkTCPClient : public NetworkTCPTransport {
+ public:
+ NetworkTCPClient (const NetworkAddress &connect_addr);
+};
+
+#endif /* NETWORK_TCP_HH */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/UDP.cc Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,79 @@
+
+#include "UDP.hh"
+
+#include <ClanLib/core.h>
+#include <cassert>
+
+NetworkUDP::NetworkUDP (void) :
+ socket(CL_Socket::udp, CL_Socket::ipv4) {
+
+ // do not bind
+
+ // connect signal
+ slots.connect(socket.sig_read_triggered(), this, &NetworkUDP::on_recv);
+
+ // nonblocking
+ socket.set_nonblocking(true);
+}
+
+NetworkUDP::NetworkUDP (const NetworkAddress &bind_addr) :
+ socket(CL_Socket::udp, CL_Socket::ipv4) {
+
+ // bind socket
+ socket.bind(bind_addr);
+
+ // connect signal
+ slots.connect(socket.sig_read_triggered(), this, &NetworkUDP::on_recv);
+
+ // nonblocking
+ socket.set_nonblocking(true);
+}
+
+void NetworkUDP::on_recv (void) {
+ int ret;
+ NetworkPacket pkt;
+ NetworkAddress src;
+
+ // receieve as many packets as possible
+ do {
+ // attempt to recv a packet
+ try {
+ ret = socket.recv(pkt.get_buf(), pkt.get_buf_size(), src);
+
+ } catch (CL_Error &e) {
+ if (errno == EAGAIN)
+ return;
+ else
+ throw;
+ }
+
+ // set packet data size
+ pkt.set_data_size(ret);
+
+ // handle packet
+ _sig_packet(pkt, src);
+
+ } while (true);
+}
+
+bool NetworkUDP::sendto (const NetworkPacket &packet, const NetworkAddress &dst) {
+ int ret;
+
+ // XXX: shouldn't get trimmed
+ try {
+ ret = socket.send(packet.get_buf(), packet.get_data_size(), dst);
+
+ } catch (CL_Error &e) {
+ // XXX: catch some errors, but not others?
+ return false;
+ }
+
+ assert(ret > 0);
+
+ // UDP shouldn't trim packets
+ assert((unsigned int) ret == packet.get_data_size());
+
+ // good
+ return true;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/UDP.hh Wed Dec 03 19:30:54 2008 +0000
@@ -0,0 +1,29 @@
+#ifndef NETWORK_UDP_HH
+#define NETWORK_UDP_HH
+
+#include "Socket.hh"
+#include "Address.hh"
+#include "Packet.hh"
+
+class NetworkUDP {
+ private:
+ NetworkSocket socket;
+
+ CL_SlotContainer slots;
+
+ public:
+ NetworkUDP (void);
+ NetworkUDP (const NetworkAddress &bind_addr);
+
+ private:
+ void on_recv (void);
+
+ CL_Signal_v2<NetworkPacket &, const NetworkAddress&> _sig_packet;
+
+ public:
+ bool sendto (const NetworkPacket &packet, const NetworkAddress &dst);
+
+ CL_Signal_v2<NetworkPacket &, const NetworkAddress&>& sig_packet (void) { return _sig_packet; }
+};
+
+#endif /* NETWORK_UDP_HH */
--- a/src/NetworkAddress.hh Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-#ifndef NETWORK_ADDRESS_HH
-#define NETWORK_ADDRESS_HH
-
-#include <ClanLib/Network/Socket/ip_address.h>
-
-typedef CL_IPAddress NetworkAddress;
-
-// Network.cc
-std::ostream& operator<< (std::ostream &s, const NetworkAddress &addr);
-
-#endif /* NETWORK_ADDRESS_HH */
--- a/src/NetworkClient.cc Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-
-#include "NetworkClient.hh"
-#include "Engine.hh"
-#include "Logger.hh"
-
-#include <cassert>
-
-NetworkClient::NetworkClient (GameState &state, const NetworkAddress &connect_to) :
- NetworkCore(state), netsession(NETWORK_MAGIC_ID), server(netsession.connect(connect_to)), netobjs(netsession, NETCHAN_CORE, server) {
-
- // connect slots
- slots.connect(netobjs.sig_create(), this, &NetworkClient::on_create);
-
- // XXX: sig_disconnected
-}
-
-void NetworkClient::on_create (NetworkObject_Client *obj, NetworkMessageID msg_id, NetworkPacket &pkt) {
- switch (msg_id) {
- case NETMSG_SERVER_HELLO:
- on_server_hello(obj, pkt);
-
- break;
-
- case NETMSG_PLAYER_INFO:
- on_player_info(obj, pkt);
-
- break;
-
- case NETMSG_PLAYER_JOIN:
- on_player_join(obj, pkt);
-
- break;
-
- default:
- Engine::log(WARN, "client.on_create_object") << "unknown msg_id=" << msg_id << " for obj=" << obj;
- }
-}
-
-void NetworkClient::on_server_hello (NetworkObject_Client *obj, NetworkPacket &pkt) {
- // read the packet
- Vector position = pkt.read_vector();
-
- Engine::log(INFO, "client.on_server_hello") << "obj=" << obj << ", pos=" << position;
-
- // create the LocalPlayer object
- NetworkClientLocalPlayer *player = new NetworkClientLocalPlayer(*this, obj, position);
-
- // inform state
- state.newLocalPlayer(player);
-}
-
-void NetworkClient::on_player_info (NetworkObject_Client *obj, NetworkPacket &pkt) {
- // read the packet
- Vector position = pkt.read_vector();
-
- Engine::log(INFO, "client.on_player_info") << "obj=" << obj << ", pos=" << position;
-
- // create the LocalPlayer object
- NetworkClientRemotePlayer *player = new NetworkClientRemotePlayer(*this, obj, position);
-
- // inform state
- state.newRemotePlayer(player);
-
-}
-
-void NetworkClient::on_player_join (NetworkObject_Client *obj, NetworkPacket &pkt) {
- // read the packet
- Vector position = pkt.read_vector();
-
- Engine::log(INFO, "client.on_player_join") << "obj=" << obj << ", pos=" << position;
-
- // create the RemotePlayer object
- NetworkClientRemotePlayer *player = new NetworkClientRemotePlayer(*this, obj, position);
-
- // inform state
- state.newRemotePlayer(player);
-}
-
-void NetworkClient::player_quit (NetworkClientRemotePlayer *player) {
- // inform state
- state.removePlayer(player);
-
- // delete
- // XXX: leak because deleting the slot while it's being called breaks ClanLib
- // delete player;
-}
-
-NetworkClientLocalPlayer::NetworkClientLocalPlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position) :
- LocalPlayer(client.state, position, true), client(client), obj(obj) {
-
- // receive messages
- slots.connect(obj->sig_message(NETMSG_PLAYER_POSITION), this, &NetworkClientLocalPlayer::on_position);
-}
-
-void NetworkClientLocalPlayer::handleMove (PlayerInput_Move input) {
- // always send move, in all cases
- NetworkPacket pkt;
- pkt.write_uint16(input);
-
- obj->send(NETMSG_CLIENT_MOVE, pkt, false);
-
- // do not handle locally
-}
-
-void NetworkClientLocalPlayer::on_position (NetworkPacket &pkt) {
- Vector position = pkt.read_vector();
- Vector velocity = pkt.read_vector();
- uint8_t flags = pkt.read_uint8();
-
- Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", position=" << position << ", velocity=" << velocity;
-
- // just update...
- updatePhysics(position, velocity, flags & NETWORK_PHYSICS_INAIR);
-}
-
-NetworkClientRemotePlayer::NetworkClientRemotePlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position) :
- RemotePlayer(client.state, position, true), client(client), obj(obj) {
-
- // receive messages
- slots.connect(obj->sig_message(NETMSG_PLAYER_POSITION), this, &NetworkClientRemotePlayer::on_position);
- slots.connect(obj->sig_message(NETMSG_PLAYER_QUIT), this, &NetworkClientRemotePlayer::on_quit);
-}
-
-void NetworkClientRemotePlayer::on_position (NetworkPacket &pkt) {
- Vector position = pkt.read_vector();
- Vector velocity = pkt.read_vector();
- uint8_t flags = pkt.read_uint8();
-
- Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", position=" << position << ", velocity=" << velocity;
-
- // just update...
- updatePhysics(position, velocity, flags & NETWORK_PHYSICS_INAIR);
-}
-
-void NetworkClientRemotePlayer::on_quit (NetworkPacket &pkt) {
- // pkt is empty
- (void) pkt;
-
- Engine::log(INFO, "client_player.on_quit") << "obj=" << obj;
-
- client.player_quit(this);
-}
-
--- a/src/NetworkClient.hh Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#ifndef NETWORKCLIENT_HH
-#define NETWORKCLIENT_HH
-
-#include "Network.hh"
-#include "GameState.hh"
-#include "NetworkSession.hh"
-#include "NetworkObject.hh"
-
-// forward-declare
-class NetworkClientLocalPlayer;
-class NetworkClientRemotePlayer;
-
-class NetworkClient : public NetworkCore {
- friend class NetworkClientLocalPlayer;
- friend class NetworkClientRemotePlayer;
-
- private:
- NetworkSession netsession;
- NetworkNode *server;
-
- NetworkObject_ClientController netobjs;
-
- public:
- NetworkClient (GameState &state, const NetworkAddress &connect_to);
-
- private:
- void on_create (NetworkObject_Client *obj, NetworkMessageID msg_id, NetworkPacket &pkt);
-
- void on_server_hello (NetworkObject_Client *obj, NetworkPacket &pkt);
- void on_player_info (NetworkObject_Client *obj, NetworkPacket &pkt);
- void on_player_join (NetworkObject_Client *obj, NetworkPacket &pkt);
-
- public:
- void player_quit (NetworkClientRemotePlayer *player);
-};
-
-class NetworkClientLocalPlayer : public LocalPlayer {
- private:
- NetworkClient &client;
-
- CL_SlotContainer slots;
-
- NetworkObject_Client *obj;
-
- public:
- NetworkClientLocalPlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position);
-
- virtual void handleMove (PlayerInput_Move input);
-
- private:
- void on_position (NetworkPacket &pkt);
-};
-
-class NetworkClientRemotePlayer : public RemotePlayer {
- private:
- NetworkClient &client;
-
- CL_SlotContainer slots;
-
- NetworkObject_Client *obj;
-
- public:
- NetworkClientRemotePlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position);
-
- private:
- void on_position (NetworkPacket &pkt);
-
- void on_quit (NetworkPacket &pkt);
-};
-
-#endif
--- a/src/NetworkConfig.hh Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-#ifndef NETWORK_CONFIG_HH
-#define NETWORK_CONFIG_HH
-
-// socket-related includes
-// copied from clanlib code, so should be relatively OS-safe
-#ifndef WIN32
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <sys/time.h>
- #include <unistd.h>
-#else
- #include <winsock2.h>
- #include <windows.h>
- typedef int socklen_t;
-#endif
-
-#include <string>
-
-const std::string NETWORK_PORT_STR = "9338";
-
-const size_t NETWORK_PACKET_SIZE = 1280;
-const int NETWORK_LISTEN_BACKLOG = 5;
-
-const char NETWORK_MAGIC_STR[8+1] = "KISNGLIS";
-const uint64_t NETWORK_MAGIC_ID = * ((const uint64_t *) NETWORK_MAGIC_STR);
-
-#endif /* NETWORK_CONFIG_HH */
--- a/src/NetworkNode.cc Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-
-#include <cassert>
-
-#include "NetworkNode.hh"
-
-NetworkNode::NetworkNode (NetworkSession &session, NetworkTCPTransport *tcp, NetworkUDP *udp, const NetworkAddress &address) :
- session(session), tcp(tcp), udp(udp), address(address) {
-
- // connect signals
- slots.connect(tcp->sig_disconnect(), this, &NetworkNode::on_disconnect);
- slots.connect(tcp->sig_packet(), &session, &NetworkSession::handle_message, this);
-
-}
-
-NetworkNode::~NetworkNode (void) {
- delete tcp;
-}
-
-void NetworkNode::on_disconnect (void) {
- // tell session
- session.handle_disconnect(this);
-
- // fire signal
- _sig_disconnected();
-
- // delete
-// delete this;
-}
-
-void NetworkNode::send (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable) {
- assert(channel_id > 0);
-
- // add our header
- NetworkPacket pkt2;
- pkt2.write_uint16(channel_id);
- pkt2.write_packet(pkt);
-
- // either tcp or udp
- if (reliable) {
- assert(tcp);
-
- tcp->write_packet(pkt2);
-
- } else {
- udp->sendto(pkt2, address);
- }
-}
-
-const NetworkAddress& NetworkNode::getRemoteAddress (void) {
- return address;
-}
--- a/src/NetworkNode.hh Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-#ifndef NETWORK_NODE_HH
-#define NETWORK_NODE_HH
-
-// forward-declare
-class NetworkNode;
-
-enum NetworkNodeType {
- NETWORK_NODE_SERVER_CLIENT,
- NETWORK_NODE_CLIENT_SERVER
-};
-
-#include "NetworkTCP.hh"
-#include "NetworkUDP.hh"
-#include "NetworkSession.hh"
-
-class NetworkNode {
- private:
- NetworkSession &session;
- NetworkTCPTransport *tcp;
- NetworkUDP *udp;
- const NetworkAddress address;
-
- CL_SlotContainer slots;
-
- public:
- NetworkNode (NetworkSession &session, NetworkTCPTransport *tcp, NetworkUDP *udp, const NetworkAddress &address);
-
- private:
- NetworkNode (const NetworkNode ©);
- ~NetworkNode (void);
- NetworkNode& operator= (const NetworkNode ©);
-
- void on_disconnect (void);
-
- CL_Signal_v0 _sig_disconnected;
-
- public:
- void send (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable = true);
-
- const NetworkAddress& getRemoteAddress (void);
-
- CL_Signal_v0& sig_disconnected (void) { return _sig_disconnected; }
-};
-
-#endif /* NETWORK_NODE_HH */
--- a/src/NetworkObject.cc Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-
-#include <cassert>
-
-#include "NetworkObject.hh"
-
-/*
- * NetworkObject_Controller
- */
-NetworkObjectController::NetworkObjectController (NetworkSession &session, NetworkChannelID channel_id) :
- session(session), channel_id(channel_id) {
-
- // setup signals
- slot_message = session.sig_chan_message(channel_id).connect(this, &NetworkObjectController::on_message);
-}
-
-void NetworkObjectController::on_message (NetworkPacket &pkt, NetworkNode *node) {
- uint32_t obj_id = pkt.read_uint32();
- uint16_t msg_id = pkt.read_uint16();
-
- // lookup object
- NetworkObject *obj = objects[obj_id];
-
- if (obj) {
- obj->handle_packet(node, msg_id, pkt);
-
- } else {
- handle_create(obj_id, msg_id, pkt, node);
- }
-}
-
-/*
- * NetworkObject_ServerController
- */
-NetworkObject_ServerController::NetworkObject_ServerController (NetworkSession &session, NetworkChannelID channel_id) :
- NetworkObjectController(session, channel_id), id_pool(0) {
-
-}
-
-NetworkObjectID NetworkObject_ServerController::getObjectID (void) {
- return ++id_pool;
-}
-
-void NetworkObject_ServerController::handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node) {
- (void) obj_id;
- (void) msg_id;
- (void) pkt;
- (void) node;
-
- // XXX: fail
- throw CL_Error("clients cannot create objects");
-}
-
-/*
- * NetworkObject_ClientController *
- */
-NetworkObject_ClientController::NetworkObject_ClientController (NetworkSession &session, NetworkChannelID channel_id, NetworkNode *server) :
- NetworkObjectController(session, channel_id), server(server) {
-
-
-}
-
-void NetworkObject_ClientController::handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node) {
- // we only communicate with the server
- assert(node == server);
-
- // create new object
- NetworkObject_Client *obj = new NetworkObject_Client(*this, obj_id);
-
- // signal
- _sig_create(obj, msg_id, pkt);
-}
-
-/*
- * NetworkObject
- */
-NetworkObject::NetworkObject (NetworkObjectController &controller, NetworkObjectID obj_id) :
- obj_id(obj_id) {
-
- assert(obj_id);
-
- controller.objects[obj_id] = this;
-}
-
-void NetworkObject::buildPacket (NetworkPacket &pkt, NetworkMessageID msg_id, const NetworkPacket &payload) {
- pkt.write_uint32(obj_id);
- pkt.write_uint16(msg_id);
- pkt.write_packet(payload);
-}
-
-std::ostream& operator<< (std::ostream &s, const NetworkObject &obj) {
- return s << "<NetworkObject #" << obj.obj_id << ">";
-}
-
-/*
- * NetworkObject_Server
- */
-NetworkObject_Server::NetworkObject_Server (NetworkObject_ServerController &controller) :
- NetworkObject(controller, controller.getObjectID()), controller(controller) {
-
-}
-
-void NetworkObject_Server::handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt) {
- _map_sig_message[msg_id](node, pkt);
-}
-
-void NetworkObject_Server::send_to (NetworkNode *dst, NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable) {
- NetworkPacket pkt_out;
-
- buildPacket(pkt_out, msg_id, pkt);
-
- dst->send(controller.channel_id, pkt_out, reliable);
-}
-
-void NetworkObject_Server::send_all (NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable) {
- send_all_except(msg_id, pkt, NULL, reliable);
-}
-
-void NetworkObject_Server::send_all_except (NetworkMessageID msg_id, const NetworkPacket &pkt, NetworkNode *black_sheep, bool reliable) {
- NetworkPacket pkt_out;
-
- buildPacket(pkt_out, msg_id, pkt);
-
- controller.session.send_all_except(controller.channel_id, pkt_out, black_sheep, reliable);
-}
-
-/*
- * NetworkObject_Client
- */
-NetworkObject_Client::NetworkObject_Client (NetworkObject_ClientController &controller, NetworkObjectID id) :
- NetworkObject(controller, id), controller(controller) {
-
- // nothing
-}
-
-void NetworkObject_Client::handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt) {
- assert(node == controller.server);
-
- _map_sig_message[msg_id](pkt);
-}
-
-void NetworkObject_Client::send (NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable) {
- NetworkPacket pkt_out;
-
- buildPacket(pkt_out, msg_id, pkt);
-
- controller.server->send(controller.channel_id, pkt_out, reliable);
-}
-
--- a/src/NetworkObject.hh Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-#ifndef NETWORK_OBJECT_HH
-#define NETWORK_OBJECT_HH
-
-#include "NetworkSession.hh"
-#include "NetworkNode.hh"
-#include "Logger.hh"
-
-#include <map>
-
-typedef uint32_t NetworkObjectID;
-typedef uint16_t NetworkMessageID;
-
-// forward-declare
-class NetworkObject;
-class NetworkObject_Client;
-class NetworkObject_Server;
-
-class NetworkObjectController {
- friend class NetworkObject;
- friend class NetworkObject_Server;
- friend class NetworkObject_Client;
-
- private:
- NetworkSession &session;
- NetworkChannelID channel_id;
-
- std::map<NetworkObjectID, NetworkObject*> objects;
-
- CL_Slot slot_message;
-
- protected:
- NetworkObjectController (NetworkSession &session, NetworkChannelID channel_id);
-
- private:
- void on_message (NetworkPacket &pkt, NetworkNode *node);
-
- protected:
- virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node) = 0;
-};
-
-class NetworkObject_ServerController : public NetworkObjectController {
- friend class NetworkObject_Server;
-
- private:
- NetworkObjectID id_pool;
-
- public:
- NetworkObject_ServerController (NetworkSession &session, NetworkChannelID channel_id);
-
- protected:
- NetworkObjectID getObjectID (void);
-
- virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node);
-};
-
-class NetworkObject_ClientController : public NetworkObjectController {
- friend class NetworkObject_Client;
-
- private:
- NetworkNode *server;
-
- CL_Signal_v3<NetworkObject_Client*, NetworkMessageID, NetworkPacket&> _sig_create;
-
- public:
- NetworkObject_ClientController (NetworkSession &session, NetworkChannelID channel_id, NetworkNode *server);
-
- protected:
- virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node);
-
- public:
- CL_Signal_v3<NetworkObject_Client*, NetworkMessageID, NetworkPacket&>& sig_create (void) { return _sig_create; }
-};
-
-class NetworkObject {
- friend class NetworkObjectController;
- friend std::ostream& operator<< (std::ostream &s, const NetworkObject &obj);
-
- protected:
- NetworkObjectID obj_id;
-
- protected:
- NetworkObject (NetworkObjectController &controller, NetworkObjectID obj_id);
-
- virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt) = 0;
-
- void buildPacket (NetworkPacket &pkt, NetworkMessageID msg_id, const NetworkPacket &payload);
-};
-
-std::ostream& operator<< (std::ostream &s, const NetworkObject &obj);
-
-class NetworkObject_Server : public NetworkObject {
- friend class NetworkObject_ServerController;
-
- private:
- NetworkObject_ServerController &controller;
-
- std::map<NetworkMessageID, CL_Signal_v2<NetworkNode*, NetworkPacket&> > _map_sig_message;
-
- public:
- NetworkObject_Server (NetworkObject_ServerController &controller);
-
- protected:
- virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt);
-
- public:
- void send_to (NetworkNode *dst, NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable = true);
- void send_all (NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable = true);
- void send_all_except (NetworkMessageID msg_id, const NetworkPacket &pkt, NetworkNode *black_sheep, bool reliable = true);
-
- CL_Signal_v2<NetworkNode*, NetworkPacket&>& sig_message (NetworkMessageID msg_id) { return _map_sig_message[msg_id]; }
-};
-
-class NetworkObject_Client : public NetworkObject {
- friend class NetworkObject_ClientController;
-
- private:
- NetworkObject_ClientController &controller;
-
- std::map<NetworkMessageID, CL_Signal_v1<NetworkPacket&> > _map_sig_message;
-
- protected:
- NetworkObject_Client (NetworkObject_ClientController &controller, NetworkObjectID id);
-
- virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt);
-
- public:
- void send (NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable = true);
-
- CL_Signal_v1<NetworkPacket&>& sig_message (NetworkMessageID msg_id) { return _map_sig_message[msg_id]; }
-};
-
-#endif /* NETWORK_OBJECT_HH */
--- a/src/NetworkPacket.cc Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-
-#include <cassert>
-#include <cstring>
-
-#include "NetworkPacket.hh"
-
-
-NetworkPacket::NetworkPacket (void) :
- buf_size(NETWORK_PACKET_SIZE), data_size(0), offset(0) {
-
- // nothing
-}
-
-void NetworkPacket::check_write_size (size_t item_size) {
- if (offset + item_size > buf_size)
- throw NetworkPacketError("not enough space to write");
-
-}
-
-void NetworkPacket::check_read_size (size_t item_size) {
- if (offset + item_size > data_size)
- throw NetworkPacketError("not enough data to read");
-}
-
-void NetworkPacket::write (const void *ptr, size_t len) {
- // check buffer overflow
- check_write_size(len);
-
- // set value
- memcpy(buf + offset, ptr, len);
-
- // update offset and size
- offset += len;
- data_size += len;
-}
-
-void NetworkPacket::read (void *ptr, size_t len) {
- // check buffer underflow
- check_read_size(len);
-
- // set value
- memcpy(ptr, buf + offset, len);
-
- // update offset
- offset += len;
-}
-
-template <typename T> T NetworkPacket::read_val (void) {
- T val;
-
- // read
- read(&val, sizeof(T));
-
- // return
- return val;
-}
-
-template <typename T> void NetworkPacket::write_val (const T &val) {
- // write
- write(&val, sizeof(T));
-}
-
-uint32_t NetworkPacket::read_uint32 (void) {
- return ntohl(read_val<uint32_t>());
-}
-
-uint16_t NetworkPacket::read_uint16 (void) {
- return ntohs(read_val<uint16_t>());
-}
-
-uint8_t NetworkPacket::read_uint8 (void) {
- return read_val<uint8_t>();
-}
-
-int32_t NetworkPacket::read_int32 (void) {
- return ntohl(read_val<int32_t>());
-}
-
-int16_t NetworkPacket::read_int16 (void) {
- return ntohs(read_val<int16_t>());
-}
-
-int8_t NetworkPacket::read_int8 (void) {
- return read_val<int8_t>();
-}
-
-float NetworkPacket::read_float32 (void) {
- int32_t ival = read_int32();
-
- return *((float *) &ival);
-}
-
-Vector NetworkPacket::read_vector (void) {
- float fx = read_float32();
- float fy = read_float32();
-
- return Vector(fx, fy);
-}
-
-void NetworkPacket::write_uint32 (uint32_t val) {
- write_val<uint32_t>(htonl(val));
-}
-
-void NetworkPacket::write_uint16 (uint16_t val) {
- write_val<uint16_t>(htons(val));
-}
-
-void NetworkPacket::write_uint8 (uint8_t val) {
- write_val<uint8_t>(val);
-}
-
-void NetworkPacket::write_int32 (int32_t val) {
- write_val<int32_t>(htonl(val));
-}
-
-void NetworkPacket::write_int16 (int16_t val) {
- write_val<int16_t>(htons(val));
-}
-
-void NetworkPacket::write_int8 (int8_t val) {
- write_val<int8_t>(val);
-}
-
-void NetworkPacket::write_float32 (float val) {
- write_int32(*((int32_t *) &val));
-}
-
-void NetworkPacket::write_vector (const Vector &vec) {
- write_float32(vec.x);
- write_float32(vec.y);
-}
-
-void NetworkPacket::write_packet (const NetworkPacket &pkt) {
- // check buffer size
- check_write_size(pkt.get_data_size());
-
- // copy
- memcpy(buf + offset, pkt.get_buf(), pkt.get_data_size());
-
- // update offset/data_size
- offset += pkt.get_data_size();
- data_size += pkt.get_data_size();
-}
-
--- a/src/NetworkPacket.hh Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-#ifndef NETWORK_PACKET_HH
-#define NETWORK_PACKET_HH
-
-#include "NetworkConfig.hh"
-#include "Vector.hh"
-#include "Error.hh"
-
-class NetworkPacketError : public Error {
- public:
- NetworkPacketError (const std::string &message) : Error(message) { }
-};
-
-class NetworkPacket {
- private:
- char buf[NETWORK_PACKET_SIZE];
- size_t buf_size, data_size, offset;
-
- void check_write_size (size_t item_size);
- void check_read_size (size_t item_size);
-
- template <typename T> T read_val (void);
- template <typename T> void write_val (const T &val);
-
- public:
- NetworkPacket (void);
-
- char* get_buf (void) { return buf; }
- const char* get_buf (void) const { return buf; }
- size_t get_data_size (void) const { return data_size; }
- size_t get_buf_size (void) const { return buf_size; }
-
- void set_data_size (size_t size) { offset = 0; data_size = size; }
-
- // raw
- void write (const void *ptr, size_t len);
- void read (void *ptr, size_t len);
-
- // type-reads, handle network-endianlness
- uint32_t read_uint32 (void);
- uint16_t read_uint16 (void);
- uint8_t read_uint8 (void);
-
- int32_t read_int32 (void);
- int16_t read_int16 (void);
- int8_t read_int8 (void);
-
- float read_float32 (void);
-
-
- void write_uint32 (uint32_t val);
- void write_uint16 (uint16_t val);
- void write_uint8 (uint8_t val);
-
- void write_int32 (int32_t val);
- void write_int16 (int16_t val);
- void write_int8 (int8_t val);
-
- void write_float32 (float val);
-
- // complex
- Vector read_vector (void);
- void write_vector (const Vector &vec);
- void write_packet (const NetworkPacket &pkt);
-};
-
-#endif /* NETWORK_PACKET_HH */
--- a/src/NetworkServer.cc Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-#include "NetworkServer.hh"
-#include "Engine.hh"
-#include "Logger.hh"
-
-#include <cassert>
-
-NetworkServer::NetworkServer (GameState &state, const NetworkAddress &listen_addr) :
- NetworkCore(state), netsession(NETWORK_MAGIC_ID), netobjs(netsession, NETCHAN_CORE) {
-
- // connect slots
- slots.connect(netsession.sig_node_connected(), this, &NetworkServer::on_node_connected);
-
- // and then we listen
- netsession.listen(listen_addr);
-
- Engine::log(INFO, "server") << "running, listen_addr=" << listen_addr;
-}
-
-void NetworkServer::on_node_connected (NetworkNode *node) {
- // create the player object (it logs it)
- NetworkServerPlayer *player = new NetworkServerPlayer(*this, node);
-
- // add to players
- players.push_back(player);
-
- // add to GameState
- state.newRemotePlayer(player);
-}
-
-void NetworkServer::handle_disconnect (NetworkServerPlayer *player) {
- // remove from state
- state.removePlayer(player);
-
- // remove from list
- players.remove(player);
-}
-
-NetworkServerPlayer::NetworkServerPlayer (NetworkServer &server, NetworkNode *node) :
- RemotePlayer(server.state, Vector(PLAYER_INITIAL_X, PLAYER_INITIAL_Y), true), server(server), obj(server.netobjs), node(node) {
-
- // log
- Engine::log(INFO, "server_player.connected") << "node=" << node << ", obj=" << obj;
-
- // messages
- slots.connect(node->sig_disconnected(), this, &NetworkServerPlayer::on_disconnected);
- slots.connect(obj.sig_message(NETMSG_CLIENT_MOVE), this, &NetworkServerPlayer::on_move);
-
- // the initial NETMSG_PLAYER_HELLO
- NetworkPacket hello_pkt;
- hello_pkt.write_vector(position);
-
- obj.send_to(node, NETMSG_SERVER_HELLO, hello_pkt, true);
-
- // send other player objects
- for (std::list<NetworkServerPlayer*>::iterator it = server.players.begin(); it != server.players.end(); it++) {
- NetworkServerPlayer *player = *it;
- NetworkPacket player_pkt;
-
- // player is not in players list yet
- assert(player != this);
-
- player_pkt.write_vector(player->position);
-
- player->obj.send_to(node, NETMSG_PLAYER_INFO, player_pkt, true);
- }
-
- // broadcast NETMSG_PLAYER_JOIN to all clients except current
- obj.send_all_except(NETMSG_PLAYER_JOIN, hello_pkt, node, true);
-}
-
-void NetworkServerPlayer::on_disconnected (void) {
- NetworkPacket pkt;
-
- Engine::log(INFO, "server_player.disconnected") << "node=" << node << ", obj=" << obj;
-
- // remove from server
- server.handle_disconnect(this);
-
- // tell other clients
- obj.send_all(NETMSG_PLAYER_QUIT, pkt, true);
-
- // free
-// delete this;
-}
-
-void NetworkServerPlayer::on_move (NetworkNode *src, NetworkPacket &pkt) {
- // sanity-check, other players shouldn't move
- if (src != node) {
- Engine::log(WARN, "server_player.on_move") << "packet from wrong src=" << src << ", node=" << node;
- return;
- }
-
- PlayerInput_Move input = pkt.read_uint16();
-
- Engine::log(INFO, "server_player.on_move") << "player=" << obj << ", old_pos=" << position << ", input=" << input;
-
- // apply input
- handleMove(input);
-
- // send position update
- send_position_update();
-}
-
-void NetworkServerPlayer::send_position_update (void) {
- NetworkPacket pkt;
- pkt.write_vector(position);
- pkt.write_vector(velocity);
- pkt.write_uint8(inAir & NETWORK_PHYSICS_INAIR);
-
- Engine::log(INFO, "server_player.send_position_update") << "obj=" << obj << " -> " << position << "+" << velocity;
-
- obj.send_all(NETMSG_PLAYER_POSITION, pkt, false);
-}
-
--- a/src/NetworkServer.hh Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-#ifndef NETWORKSERVER_HH
-#define NETWORKSERVER_HH
-
-#include "Network.hh"
-#include "GameState.hh"
-#include "NetworkSession.hh"
-#include "NetworkObject.hh"
-
-#include <list>
-#include <map>
-#include <ClanLib/core.h>
-
-// forward-declare
-class NetworkServerPlayer;
-
-class NetworkServer : public NetworkCore {
- friend class NetworkServerPlayer;
-
- protected:
- NetworkSession netsession;
- NetworkObject_ServerController netobjs;
- std::list<NetworkServerPlayer *> players;
-
- public:
- NetworkServer (GameState &state, const NetworkAddress &listen_addr);
-
- protected:
- void handle_disconnect (NetworkServerPlayer *player);
-
- private:
- void on_node_connected (NetworkNode *node);
-};
-
-class NetworkServerPlayer : public RemotePlayer {
- private:
- NetworkServer &server;
- NetworkObject_Server obj;
- NetworkNode *node;
-
- CL_SlotContainer slots;
-
- public:
- NetworkServerPlayer (NetworkServer &server, NetworkNode *node);
-
- private:
- void on_disconnected (void);
- void on_move (NetworkNode *node, NetworkPacket &pkt);
-
- void send_position_update (void);
-};
-
-#endif
--- a/src/NetworkSession.cc Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-
-#include "NetworkSession.hh"
-#include "Engine.hh"
-
-#include <cassert>
-
-NetworkSession::NetworkSession (uint64_t magic) :
- magic(magic), tcp_srv(NULL), udp_srv(NULL), udp_client(NULL) {
-
- // nothing
-}
-
-void NetworkSession::listen (const NetworkAddress &addr) {
- assert(tcp_srv == NULL && udp_srv == NULL);
-
- // create TCP/UDP servers
- tcp_srv = new NetworkTCPServer(addr);
- udp_srv = new NetworkUDP(addr);
-
- // connect signals
- slots.connect(tcp_srv->sig_client(), this, &NetworkSession::on_tcp_client);
- slots.connect(udp_srv->sig_packet(), this, &NetworkSession::on_udp_packet);
-}
-
-NetworkNode *NetworkSession::build_node (NetworkTCPTransport *tcp, NetworkUDP *udp, const NetworkAddress &addr, enum NetworkNodeType type) {
- // XXX: unused
- (void) type;
-
- // create node
- return new NetworkNode(*this, tcp, udp, addr);
-}
-
-NetworkNode* NetworkSession::connect (const NetworkAddress &addr) {
- // XXX: only one connect
- assert(!udp_client);
-
- // connect TCP
- NetworkTCPClient *tcp_client = new NetworkTCPClient(addr);
-
- // create UDP socket on same address
- udp_client = new NetworkUDP(tcp_client->getLocalAddress());
-
- // build client
- NetworkNode *client_node = build_node(tcp_client, udp_client, addr, NETWORK_NODE_CLIENT_SERVER);
-
- // add to nodes
- nodes[addr] = client_node;
-
- // connect signals
- slots.connect(udp_client->sig_packet(), this, &NetworkSession::on_udp_packet);
-
- // return the "server" node
- return client_node;
-}
-
-void NetworkSession::handle_disconnect (NetworkNode *node) {
- // remove from nodes
- nodes.erase(node->getRemoteAddress());
-}
-
-void NetworkSession::handle_message (NetworkPacket &pkt, NetworkNode *node) {
- // read the channel id
- NetworkChannelID channel_id = pkt.read_uint16();
-
- // fire signal
- _map_sig_chan_message[channel_id](pkt, node);
-}
-
-void NetworkSession::on_tcp_client (NetworkTCPTransport *tcp_client) {
- // get remote address manually, because NetworkTCPServer doesn't pass it in to us
- NetworkAddress addr = tcp_client->getRemoteAddress();
-
- // build client
- NetworkNode *client_node = build_node(tcp_client, udp_srv, addr, NETWORK_NODE_SERVER_CLIENT);
-
- // add to nodes
- nodes[addr] = client_node;
-
- // fire signals
- _sig_node_connected(client_node);
-}
-
-void NetworkSession::on_udp_packet (NetworkPacket &pkt, const NetworkAddress &addr) {
- NetworkNode *node = nodes[addr];
-
- // drop from unknown sources
- if (!node) {
- Engine::log(WARN, "net_session.on_udp_packet") << "dropping unsolicted UDP packet from " << addr;
- return;
- }
-
- // handle
- handle_message(pkt, node);
-}
-
-void NetworkSession::send_all (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable) {
- send_all_except(channel_id, pkt, NULL, reliable);
-}
-
-void NetworkSession::send_all_except (NetworkChannelID channel_id, const NetworkPacket &pkt, const NetworkNode *node, bool reliable) {
- for (std::map<NetworkAddress, NetworkNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
- if (it->second == node)
- continue;
-
- it->second->send(channel_id, pkt, reliable);
- }
-}
--- a/src/NetworkSession.hh Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-#ifndef NETWORK_SESSION_HH
-#define NETWORK_SESSION_HH
-
-#include <map>
-#include <stdint.h>
-
-// forward-declare
-class NetworkSession;
-
-/*
- * Used to separate packets, ID zero is reserved for NetworkSession use
- */
-typedef uint16_t NetworkChannelID;
-
-#include "NetworkTCP.hh"
-#include "NetworkUDP.hh"
-#include "NetworkNode.hh"
-
-class NetworkSession {
- friend class NetworkNode;
-
- private:
- uint64_t magic;
- NetworkTCPServer *tcp_srv;
- NetworkUDP *udp_srv, *udp_client;
-
- CL_SlotContainer slots;
-
- std::map<NetworkAddress, NetworkNode*> nodes;
- std::map<NetworkChannelID, CL_Signal_v2<NetworkPacket&, NetworkNode *> > _map_sig_chan_message;
-
- public:
- NetworkSession (uint64_t magic);
-
- void listen (const NetworkAddress &addr);
- NetworkNode* connect (const NetworkAddress &addr);
-
- protected:
- virtual NetworkNode *build_node (NetworkTCPTransport *tcp, NetworkUDP *udp, const NetworkAddress &addr, enum NetworkNodeType type);
-
- void handle_disconnect (NetworkNode *node);
- void handle_message (NetworkPacket &pkt, NetworkNode *node);
-
- private:
- void on_tcp_client (NetworkTCPTransport *client);
- void on_udp_packet (NetworkPacket &pkt, const NetworkAddress &addr);
-
- CL_Signal_v1<NetworkNode*> _sig_node_connected;
-
- public:
- void send_all (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable = true);
- void send_all_except (NetworkChannelID channel_id, const NetworkPacket &pkt, const NetworkNode *node, bool reliable = true);
-
- CL_Signal_v1<NetworkNode*>& sig_node_connected (void) { return _sig_node_connected; }
- CL_Signal_v2<NetworkPacket&, NetworkNode *>& sig_chan_message (NetworkChannelID cid) { return _map_sig_chan_message[cid]; }
-};
-
-#endif /* NETWORK_SESSION_HH */
--- a/src/NetworkSocket.hh Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#ifndef NETWORK_SOCKET_HH
-#define NETWORK_SOCKET_HH
-
-#include "Error.hh"
-
-#include <ClanLib/Network/Socket/socket.h>
-#include <cerrno>
-#include <cstring>
-
-typedef CL_Socket NetworkSocket;
-
-// Network.cc
-class NetworkSocketError : public Error {
- protected:
- std::string build_str (const NetworkSocket &socket, const char *op, const char *err);
-
- NetworkSocketError (const NetworkSocket &socket, const char *op, const char *err);
-};
-
-class NetworkSocketOSError : public NetworkSocketError {
- public:
- NetworkSocketOSError (const NetworkSocket &socket, const char *op) :
- NetworkSocketError(socket, op, strerror(errno)) { }
-};
-
-class NetworkSocketEOFError : public NetworkSocketError {
- public:
- NetworkSocketEOFError (const NetworkSocket &socket, const char *op) :
- NetworkSocketError(socket, op, "EOF") { }
-};
-
-#endif /* NETWORK_SOCKET_HH */
--- a/src/NetworkTCP.cc Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,325 +0,0 @@
-
-#include "NetworkTCP.hh"
-#include "Engine.hh"
-
-#include <cstdlib>
-#include <cassert>
-
-NetworkBuffer::NetworkBuffer (NetworkSocket &socket, size_t size_hint) :
- socket(socket), buf(0), size(0), offset(0) {
-
- // allocate initial buffer
- if ((buf = (char *) malloc(size_hint)) == NULL)
- throw NetworkBufferError("malloc failed");
-
- // remember size
- size = size_hint;
-}
-
-NetworkBuffer::~NetworkBuffer (void) {
- free(buf);
-}
-
-void NetworkBuffer::resize (size_t item_size) {
- size_t new_size = size;
-
- // grow new_size until item_size fits
- while (offset + item_size > new_size)
- new_size *= 2;
-
- // grow if needed
- if (new_size != size) {
- // realloc buffer
- if ((buf = (char *) realloc((void *) buf, new_size)) == NULL)
- throw NetworkBufferError("realloc failed");
-
- // update size
- size = new_size;
-
- } else if (new_size > (offset + item_size) * 4) {
- // XXX: shrink?
- }
-}
-
-void NetworkBuffer::trim (size_t prefix_size) {
- // update offset
- offset -= prefix_size;
-
- // shift the buffer forwards from (buf + prefix) -> (buf), copying (old_offset - prefix) bytes
- memmove(buf, buf + prefix_size, offset);
-}
-
-bool NetworkBuffer::try_read (size_t item_size) {
- int ret;
- size_t to_read = item_size;
-
- // keept reads at at least NETWORK_CHUNK_SIZE bytes
- if (to_read < NETWORK_TCP_CHUNK_SIZE)
- to_read = NETWORK_TCP_CHUNK_SIZE;
-
- // resize buffer if needed
- resize(to_read);
-
- // read once
- try {
- ret = socket.recv(buf + offset, to_read);
-
- } catch (CL_Error &e) {
- if (errno == EAGAIN)
- return false;
-
- else
- throw NetworkSocketOSError(socket, "recv");
- }
-
- // handle EOF
- if (ret == 0)
- throw NetworkSocketEOFError(socket, "recv");
-
- assert(ret >= 0);
-
- // update offset
- offset += ret;
-
- // did we get enough?
- if ((unsigned int) ret < item_size)
- return false;
- else
- return true;
-}
-
-bool NetworkBuffer::peek_prefix (uint16_t &ref) {
- if (offset < sizeof(uint16_t))
- return false;
-
- ref = ntohs(*((uint16_t *) (buf)));
-
- return true;
-}
-
-bool NetworkBuffer::peek_prefix (uint32_t &ref) {
- if (offset < sizeof(uint32_t))
- return false;
-
- ref = ntohl(*((uint32_t *) (buf)));
-
- return true;
-}
-
-template <typename PrefixType> PrefixType NetworkBuffer::read_prefix (char *buf_ptr, size_t buf_max) {
- PrefixType prefix = 0;
- size_t missing = 0;
-
- do {
- // do we have the prefix?
- if (peek_prefix(prefix)) {
- // do we already have the payload?
- if (offset >= sizeof(PrefixType) + prefix) {
- break;
-
- } else {
- missing = (sizeof(PrefixType) + prefix) - offset;
- }
-
- } else {
- missing = sizeof(PrefixType);
- }
-
- // sanity-check
- assert(missing);
-
- // try and read the missing data
- if (try_read(missing) == false) {
- // if unable to read what we need, return zero.
- return 0;
- }
-
- // assess the situation again
- } while (true);
-
- // copy the data over, unless it's too large
- if (prefix <= buf_max) {
- // ...don't copy the prefix, though
- memcpy(buf_ptr, buf + sizeof(PrefixType), prefix);
-
- // trim the bytes out
- trim(sizeof(PrefixType) + prefix);
-
- // return
- return prefix;
-
- } else {
- // trim the bytes out
- trim(sizeof(PrefixType) + prefix);
-
- throw NetworkBufferError("recv prefix overflow");
- }
-}
-
-void NetworkBuffer::push_write (char *buf_ptr, size_t buf_size) {
- int ret;
-
- // try and short-circuit writes unless we have already buffered data
- if (offset == 0) {
- try {
- // attempt to send something
- ret = socket.send(buf_ptr, buf_size);
-
- } catch (CL_Error &e) {
- // ignore EAGAIN, detect this by setting ret to -1
- if (errno != EAGAIN)
- throw NetworkSocketOSError(socket, "send");
-
- ret = -1;
- }
-
- // if we managed to send something, adjust buf/size and buffer
- if (ret > 0) {
- // sanity-check
- assert(buf_size >= (unsigned int) ret);
-
- buf_ptr += ret;
- buf_size -= ret;
-
- // if that was all, we're done
- if (buf_size == 0)
- return;
- }
- }
-
- // resize to fit buf_size more bytes
- resize(buf_size);
-
- // copy into our internal buffer
- memcpy(buf + offset, buf_ptr, buf_size);
-}
-
-void NetworkBuffer::flush_write (void) {
- int ret;
-
- // ignore if we don't have any data buffered
- if (offset == 0)
- return;
-
- // attempt to write as much as possible
- try {
- ret = socket.send(buf, offset);
-
- } catch (CL_Error &e) {
- // ignore EAGAIN and just return
- if (errno == EAGAIN)
- return;
-
- else
- throw NetworkSocketOSError(socket, "send");
- }
-
- // trim the buffer
- trim(ret);
-}
-
-void NetworkBuffer::write_prefix (char *buf, uint16_t prefix) {
- uint16_t nval = htons(prefix);
-
- push_write((char*) &nval, sizeof(uint16_t));
- push_write(buf, prefix);
-}
-
-void NetworkBuffer::write_prefix (char *buf, uint32_t prefix) {
- uint32_t nval = htonl(prefix);
-
- push_write((char*) &nval, sizeof(uint32_t));
- push_write(buf, prefix);
-}
-
-NetworkTCPTransport::NetworkTCPTransport (NetworkSocket socket) :
- socket(socket), in(socket, NETWORK_TCP_INITIAL_IN_BUF), out(socket, NETWORK_TCP_INITIAL_OUT_BUF) {
-
- // connect signals
- slots.connect(socket.sig_read_triggered(), this, &NetworkTCPTransport::on_read);
- slots.connect(socket.sig_write_triggered(), this, &NetworkTCPTransport::on_write);
- slots.connect(socket.sig_disconnected(), this, &NetworkTCPTransport::on_disconnected);
-}
-
-
-void NetworkTCPTransport::on_read (void) {
- uint16_t prefix;
- NetworkPacket packet;
-
- // let the in stream read length-prefixed packets and pass them on to handle_packet
- while ((prefix = in.read_prefix<uint16_t>(packet.get_buf(), packet.get_buf_size())) > 0) {
- packet.set_data_size(prefix);
- _sig_packet(packet);
- }
-}
-
-void NetworkTCPTransport::on_write (void) {
- // just flush the output buffer
- out.flush_write();
-}
-
-void NetworkTCPTransport::on_disconnected (void) {
- // pass right through
- _sig_disconnect();
-}
-
-void NetworkTCPTransport::write_packet (const NetworkPacket &packet) {
- uint16_t prefix = packet.get_data_size();
-
- if (prefix != packet.get_data_size())
- throw CL_Error("send prefix overflow");
-
- try {
- // just write to the output buffer
- out.write_prefix((char *) packet.get_buf(), prefix);
-
- } catch (Error &e) {
- const char *err = e.what();
-
- Engine::log(ERROR, "tcp.write_packet") << err;
-
- throw;
- }
-}
-
-NetworkTCPServer::NetworkTCPServer (const NetworkAddress &listen_addr) :
- socket(CL_Socket::tcp, CL_Socket::ipv4) {
-
- // bind
- socket.bind(listen_addr);
-
- // assign slots
- slots.connect(socket.sig_read_triggered(), this, &NetworkTCPServer::on_accept);
-
- // listen
- socket.listen(NETWORK_LISTEN_BACKLOG);
-
- // use nonblocking sockets
- socket.set_nonblocking(true);
-}
-
-
-void NetworkTCPServer::on_accept (void) {
- // accept a new socket
- NetworkSocket client_sock = socket.accept();
-
- // create a new NetworkTCPTransport
- NetworkTCPTransport *client = buildTransport(client_sock);
-
- // let our user handle it
- _sig_client(client);
-}
-
-NetworkTCPTransport* NetworkTCPServer::buildTransport (CL_Socket &socket) {
- return new NetworkTCPTransport(socket);
-}
-
-NetworkTCPClient::NetworkTCPClient (const NetworkAddress &connect_addr) :
- NetworkTCPTransport(NetworkSocket(CL_Socket::tcp, CL_Socket::ipv4)) {
-
- // connect
- socket.connect(connect_addr);
-
- // use nonblocking sockets
- socket.set_nonblocking(true);
-}
--- a/src/NetworkTCP.hh Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-#ifndef NETWORK_TCP_HH
-#define NETWORK_TCP_HH
-
-#include <ClanLib/core.h>
-
-#include "NetworkSocket.hh"
-#include "NetworkAddress.hh"
-#include "NetworkPacket.hh"
-#include "Error.hh"
-
-const size_t NETWORK_TCP_CHUNK_SIZE = 1024;
-const size_t NETWORK_TCP_INITIAL_IN_BUF = 4096;
-const size_t NETWORK_TCP_INITIAL_OUT_BUF = 0;
-
-class NetworkBufferError : public Error {
- public:
- NetworkBufferError (const std::string &message) : Error(message) { }
-};
-
-class NetworkBuffer {
- private:
- NetworkSocket socket;
-
- char *buf;
- size_t size, offset;
-
- public:
- NetworkBuffer (NetworkSocket &socket, size_t size_hint);
- ~NetworkBuffer (void);
-
- private:
- NetworkBuffer (const NetworkBuffer ©);
- NetworkBuffer& operator= (const NetworkBuffer ©);
-
- void resize (size_t item_size);
- void trim (size_t prefix_size);
-
- public:
- void push_write (char *buf_ptr, size_t buf_size);
- void flush_write (void);
- void write_prefix (char *buf, uint16_t prefix);
- void write_prefix (char *buf, uint32_t prefix);
-
- bool try_read (size_t item_size);
- bool peek_prefix (uint16_t &ref);
- bool peek_prefix (uint32_t &ref);
- template <typename PrefixType> PrefixType read_prefix (char *buf_ptr, size_t buf_max);
-};
-
-class NetworkTCPTransport {
- protected:
- NetworkSocket socket;
-
- NetworkBuffer in, out;
-
- CL_SlotContainer slots;
-
- public:
- NetworkTCPTransport (NetworkSocket socket);
-
- private:
- void on_read (void);
- void on_write (void);
- void on_disconnected (void);
-
- CL_Signal_v1<NetworkPacket &> _sig_packet;
- CL_Signal_v0 _sig_disconnect;
-
- public:
- NetworkAddress getLocalAddress (void) { return socket.get_source_address(); }
- NetworkAddress getRemoteAddress (void) { return socket.get_dest_address(); }
-
- void write_packet (const NetworkPacket &packet);
-
- CL_Signal_v1<NetworkPacket&>& sig_packet (void) { return _sig_packet; }
- CL_Signal_v0& sig_disconnect (void) { return _sig_disconnect; }
-};
-
-class NetworkTCPServer {
- private:
- NetworkSocket socket;
-
- CL_SlotContainer slots;
-
- public:
- NetworkTCPServer (const NetworkAddress &listen_addr);
-
- private:
- void on_accept (void);
-
- CL_Signal_v1<NetworkTCPTransport *> _sig_client;
-
- protected:
- virtual NetworkTCPTransport* buildTransport (CL_Socket &socket);
-
- public:
- CL_Signal_v1<NetworkTCPTransport *>& sig_client (void) { return _sig_client; }
-};
-
-class NetworkTCPClient : public NetworkTCPTransport {
- public:
- NetworkTCPClient (const NetworkAddress &connect_addr);
-};
-
-#endif /* NETWORK_TCP_HH */
--- a/src/NetworkUDP.cc Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-
-#include "NetworkUDP.hh"
-
-#include <ClanLib/core.h>
-#include <cassert>
-
-NetworkUDP::NetworkUDP (void) :
- socket(CL_Socket::udp, CL_Socket::ipv4) {
-
- // do not bind
-
- // connect signal
- slots.connect(socket.sig_read_triggered(), this, &NetworkUDP::on_recv);
-
- // nonblocking
- socket.set_nonblocking(true);
-}
-
-NetworkUDP::NetworkUDP (const NetworkAddress &bind_addr) :
- socket(CL_Socket::udp, CL_Socket::ipv4) {
-
- // bind socket
- socket.bind(bind_addr);
-
- // connect signal
- slots.connect(socket.sig_read_triggered(), this, &NetworkUDP::on_recv);
-
- // nonblocking
- socket.set_nonblocking(true);
-}
-
-void NetworkUDP::on_recv (void) {
- int ret;
- NetworkPacket pkt;
- NetworkAddress src;
-
- // receieve as many packets as possible
- do {
- // attempt to recv a packet
- try {
- ret = socket.recv(pkt.get_buf(), pkt.get_buf_size(), src);
-
- } catch (CL_Error &e) {
- if (errno == EAGAIN)
- return;
- else
- throw;
- }
-
- // set packet data size
- pkt.set_data_size(ret);
-
- // handle packet
- _sig_packet(pkt, src);
-
- } while (true);
-}
-
-bool NetworkUDP::sendto (const NetworkPacket &packet, const NetworkAddress &dst) {
- int ret;
-
- // XXX: shouldn't get trimmed
- try {
- ret = socket.send(packet.get_buf(), packet.get_data_size(), dst);
-
- } catch (CL_Error &e) {
- // XXX: catch some errors, but not others?
- return false;
- }
-
- assert(ret > 0);
-
- // UDP shouldn't trim packets
- assert((unsigned int) ret == packet.get_data_size());
-
- // good
- return true;
-}
-
--- a/src/NetworkUDP.hh Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-#ifndef NETWORK_UDP_HH
-#define NETWORK_UDP_HH
-
-#include "NetworkSocket.hh"
-#include "NetworkAddress.hh"
-#include "NetworkPacket.hh"
-
-class NetworkUDP {
- private:
- NetworkSocket socket;
-
- CL_SlotContainer slots;
-
- public:
- NetworkUDP (void);
- NetworkUDP (const NetworkAddress &bind_addr);
-
- private:
- void on_recv (void);
-
- CL_Signal_v2<NetworkPacket &, const NetworkAddress&> _sig_packet;
-
- public:
- bool sendto (const NetworkPacket &packet, const NetworkAddress &dst);
-
- CL_Signal_v2<NetworkPacket &, const NetworkAddress&>& sig_packet (void) { return _sig_packet; }
-};
-
-#endif /* NETWORK_UDP_HH */
--- a/src/main.cc Wed Dec 03 19:16:32 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-#include "config.h"
-#include <iostream>
-
-int main() {
- std::cout << "Hello from " PROJECT_LONG_NAME " " PROJECT_VERSION << std::endl;
-}
-