more documentation tweaking, all Network/ files now have a @file comment. Fix Platform.h -> Platform.hh, and Buffer.hh + Packet.cc
#ifndef NETWORK_OBJECT_HH
#define NETWORK_OBJECT_HH
/**
* @file
*
* Object-based network protocol for use with NetworkSession
*/
#include "Session.hh"
#include "Node.hh"
#include "../Logger.hh"
#include <map>
/**
* A NetworkObject's ID is a 32-bit integer
*/
typedef uint32_t NetworkObjectID;
/**
* A NetworkObject's message type is a 16-bit integer
*/
typedef uint16_t NetworkMessageID;
// forward-declare
class NetworkObject;
class NetworkObject_Client;
class NetworkObject_Server;
/**
* A NetworkObjectController contains a mapping of NetworkObjectID -> NetworkObject, and handles the
* messages received on our channel from the NetworkSession.
*
* Additionally, this provides methods to read/write NetworkObject references from/to a NetworkPacket
*/
class NetworkObjectController {
friend class NetworkObject;
friend class NetworkObject_Server;
friend class NetworkObject_Client;
private:
/**
* The NetworkSession that we use
*/
NetworkSession &session;
/**
* The NetworkChannelID that we use to communicate
*/
NetworkChannelID channel_id;
/**
* Our map of NetworkObjectID -> NetworkObject
*/
std::map<NetworkObjectID, NetworkObject*> objects;
CL_Slot slot_message;
protected:
/**
* Construct a NetworkObjectController to use the given NetworkSession and NetworkChannelID
*/
NetworkObjectController (NetworkSession &session, NetworkChannelID channel_id);
private:
/**
* Our NetworkSession::sig_chan_message handler
*
* Reads the NetworkObjectID and NetworkMessageID from the packet, and then either calls handle_create or
* NetworkObject::handle_packet.
*/
void on_message (NetworkPacketInput &pkt, NetworkNode *node);
protected:
/**
* Abstract method called by on_message if we recieve a message for an unknown NetworkObjectID
*
* @param obj_id the unknown NetworkObjectID
* @param msg_id the packet's NetworkMessageID
* @param pkt the packet itself, with the header read
* @param node the node that we got this packet from
*/
virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node) = 0;
public:
/**
* Read an NetworkObjectID from the given packet, and return the corresponding NetworkObject, or NULL if:
* * it was zero
* * we don't know the object (should this thrown an exception instead?)
*
* @return the NetworkObject* corresponding to the NetworkObjectID in the packet, or NULL if zero/not found
*/
NetworkObject* read_object (NetworkPacketInput &pkt);
/**
* Write the given Object's NetworkObjectID (or 0, if the obj is NULL) to the given packet
*
* @param the NetworkObject* whose NetworkObjectID to write to the packet, or NULL to write zero
*/
void write_object (NetworkPacketOutput &pkt, NetworkObject *obj);
};
/**
* A NetworkObjectController intended for use with a server.
*
* This has an id_pool that new NetworkObjectIDs can be generated from, and this doesn't accept unknown
* NetworkObjectIDs from clients.
*/
class NetworkObject_ServerController : public NetworkObjectController {
friend class NetworkObject_Server;
private:
/**
* The id_pool that we use to generate NetworkObjectIDs for new NetworkObject's
*/
NetworkObjectID id_pool;
public:
/**
* @see NetworkObjectController
*/
NetworkObject_ServerController (NetworkSession &session, NetworkChannelID channel_id);
protected:
/**
* Get a new NetworkObjectID
*/
NetworkObjectID getObjectID (void);
/**
* Throw an error, as we don't accept unknown NetworkObjects from clients
*/
virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node);
};
/**
* A NetworkObjectController intended for use with a client.
*
* This provides two ways to handle unknown objects: override handle_create, or use sig_create
*/
class NetworkObject_ClientController : public NetworkObjectController {
friend class NetworkObject_Client;
protected:
/**
* The server node, as returned by NetworkSession::connect
*/
NetworkNode *server;
/**
* A mapping of NetworkMessageID -> sig_create, used by the default handle_create
*/
std::map<NetworkMessageID, CL_Signal_v2<NetworkObject_Client*, NetworkPacketInput&> > _map_sig_create;
public:
/**
* Construct a NetworkObjectController using the given NetworkNode (as returned by NetworkSession::connect) as
* a server.
*
* @see NetworkObjectController
*/
NetworkObject_ClientController (NetworkSession &session, NetworkChannelID channel_id, NetworkNode *server);
protected:
/**
* Handle unknown NetworkObjectIDs by constructing a new NetworkObject_Client and calling sig_create.
*
* This can be overriden to handle this differently, e.g. to create an instance of a NetworkObject_Client
* subclass instead.
*/
virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node);
public:
/**
* Signal triggered by default handle_create when we get a message for an unknown NetworkObject.
* The signal gets the new NetworkObject_Client, and the packet itself.
*
* @param msg_id the NetworkMessageID to handle creates for
*/
CL_Signal_v2<NetworkObject_Client*, NetworkPacketInput&>& sig_create (NetworkMessageID msg_id) { return _map_sig_create[msg_id]; }
};
/**
* Base class of NetworkObject_(Client/Server)
*
* A NetworkObject has an NetworkObjectID, and can handle packets to/from this object
*/
class NetworkObject {
friend class NetworkObjectController;
friend std::ostream& operator<< (std::ostream &s, const NetworkObject &obj);
protected:
/**
* Generic controller
*/
NetworkObjectController &controller;
/**
* This object's object id
*/
NetworkObjectID obj_id;
protected:
/**
* Construct a NetworkObject using the given controller and object id
*
* @param controller the NetworkObjectController (subclass)
* @param obj_id our NetworkObjectID
*/
NetworkObject (NetworkObjectController &controller, NetworkObjectID obj_id);
/**
* Removes this object from the controller's objects list
*/
~NetworkObject (void);
/**
* Abstract method to handle packets sent to this object
*
* @param node the NetworkNode that sent this packet to us
* @param msg_id the packet's NetworkMessageID
* @param pkt the packet itself, with the headers read
*/
virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacketInput &pkt) = 0;
/**
* Prepare an outgoing packet, writing the header and the payload
*
* @param pkt the packet to prepare
* @param msg_id the packet's message id
* @param payload the packet's payload
*/
void buildPacket (NetworkPacketOutput &pkt, NetworkMessageID msg_id, const NetworkPacketBuffer &payload);
};
/**
* Formats the object as "<NetworkObject #" <obj_id> ">"
*/
std::ostream& operator<< (std::ostream &s, const NetworkObject &obj);
/**
* A server-side NetworkObject
*/
class NetworkObject_Server : public NetworkObject {
friend class NetworkObject_ServerController;
protected:
/**
* The NetworkObject_ServerController
*/
NetworkObject_ServerController &controller;
/**
* Mapping of NetworkMessageID -> sig_message used for received messages
*/
std::map<NetworkMessageID, CL_Signal_v2<NetworkNode*, NetworkPacketInput&> > _map_sig_message;
public:
/**
* @see NetworkObject
*/
NetworkObject_Server (NetworkObject_ServerController &controller);
protected:
/**
* Handle an incoming packet by invoking the appopriate sig_message
*
* @see NetworkObject::handlePacket
*/
virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacketInput &pkt);
public:
/**
* Send a message on this object to the given node
*
* @param dst the NetworkNode to send the message to
* @param msg_id the type of message to send
* @param pkt the packet payload
* @param reliable Whether to use TCP or UDP
*/
void send_to (NetworkNode *dst, NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, bool reliable = true);
/**
* Send a message on this object to all nodes on our controller's NetworkSession
*
* @param msg_id the type of message to send
* @param pkt the packet payload
* @param reliable Whether to use TCP or UDP
*/
void send_all (NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, bool reliable = true);
/**
* Send a message on this object to all nodes on our controller's NetworkSession, except the given node
*
* @param msg_id the type of message to send
* @param pkt the packet payload
* @param black_sheep the node to *NOT* send the message to
* @param reliable Whether to use TCP or UDP
*/
void send_all_except (NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, NetworkNode *black_sheep, bool reliable = true);
/**
* Triggered whenever we receive a message of the given type on this object, giving the node that sent it and the
* packet itself
*
* @param msg_id the NetworkMessageID to handle
*/
CL_Signal_v2<NetworkNode*, NetworkPacketInput&>& sig_message (NetworkMessageID msg_id) { return _map_sig_message[msg_id]; }
};
/**
* A client-side NetworkObject
*/
class NetworkObject_Client : public NetworkObject {
friend class NetworkObject_ClientController;
protected:
/**
* Our NetworkObject_ClientController
*/
NetworkObject_ClientController &controller;
/**
* Our mapping of NetworkMessageID -> sig_message, used to handle received packets
*/
std::map<NetworkMessageID, CL_Signal_v1<NetworkPacketInput&> > _map_sig_message;
protected:
/**
* @see NetworkObject
*/
NetworkObject_Client (NetworkObject_ClientController &controller, NetworkObjectID id);
/**
* Handle an incoming packet by invoking the appropriate sig_message.
*
* This assumes that packets only come from the server
*
* @see NetworkObject::handlePacket
*/
virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacketInput &pkt);
public:
/**
* Send a message on this object to the server
*
* @param msg_id the type of message to send
* @param pkt the packet payload
* @param reliable Whether to use TCP or UDP
*/
void send (NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, bool reliable = true);
/**
* Triggered whenever we receive a message of the given type on this object from the server.
*
* @param msg_id the NetworkMessageID to handle
*/
CL_Signal_v1<NetworkPacketInput&>& sig_message (NetworkMessageID msg_id) { return _map_sig_message[msg_id]; }
};
#endif /* NETWORK_OBJECT_HH */