better NetworkBuffer/Packet stuff + some additional Physics+Network stuff + random fixes
--- a/src/GameState.cc Thu Dec 04 21:10:41 2008 +0000
+++ b/src/GameState.cc Thu Dec 04 21:59:23 2008 +0000
@@ -17,7 +17,7 @@
local_player = player;
}
-
+
void GameState::newRemotePlayer (RemotePlayer *player) {
player_list.push_back(player);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Buffer.cc Thu Dec 04 21:59:23 2008 +0000
@@ -0,0 +1,211 @@
+
+#include "Buffer.hh"
+#include "Config.hh"
+
+#include <ClanLib/core.h>
+#include <cstdlib>
+
+/*
+ * NetworkBufferBase
+ */
+NetworkBufferBase::NetworkBufferBase (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;
+}
+
+NetworkBufferBase::~NetworkBufferBase (void) {
+ free(buf);
+}
+
+void NetworkBufferBase::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 NetworkBufferBase::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);
+}
+
+/*
+ * NetworkBufferInput
+ */
+NetworkBufferInput::NetworkBufferInput (NetworkSocket &socket, size_t size_hint) :
+ NetworkBufferBase(socket, size_hint)
+{
+
+}
+
+bool NetworkBufferInput::try_read (size_t item_size) {
+ int ret;
+ size_t to_read = item_size;
+
+ // keept reads at at least NETWORK_BUFFER_CHUNK_SIZE bytes
+ if (to_read < NETWORK_BUFFER_CHUNK_SIZE)
+ to_read = NETWORK_BUFFER_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 NetworkBufferInput::have_data (size_t data_size) {
+ return (offset >= data_size);
+}
+
+bool NetworkBufferInput::peek_prefix (uint16_t &val_ref) {
+ if (!have_data(sizeof(uint16_t)))
+ return false;
+
+ val_ref = ntohs(*((uint16_t *) (buf)));
+
+ return true;
+}
+
+bool NetworkBufferInput::peek_prefix (uint32_t &val_ref) {
+ if (!have_data(sizeof(uint32_t)))
+ return false;
+
+ val_ref = ntohl(*((uint32_t *) (buf)));
+
+ return true;
+}
+
+/*
+ * NetworkBufferOutput
+ */
+NetworkBufferOutput::NetworkBufferOutput (NetworkSocket &socket, size_t size_hint) :
+ NetworkBufferBase(socket, size_hint)
+{
+
+}
+
+
+void NetworkBufferOutput::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 NetworkBufferOutput::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 NetworkBufferOutput::write_prefix (char *buf, uint16_t prefix) {
+ uint16_t nval = htons(prefix);
+
+ push_write((char*) &nval, sizeof(uint16_t));
+ push_write(buf, prefix);
+}
+
+void NetworkBufferOutput::write_prefix (char *buf, uint32_t prefix) {
+ uint32_t nval = htonl(prefix);
+
+ push_write((char*) &nval, sizeof(uint32_t));
+ push_write(buf, prefix);
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Network/Buffer.hh Thu Dec 04 21:59:23 2008 +0000
@@ -0,0 +1,150 @@
+#ifndef NETWORK_BUFFER_HH
+#define NETWORK_BUFFER_HH
+
+#include "Socket.hh"
+#include "../Error.hh"
+
+#include <cassert>
+
+/*
+ * Minimum chunk size to avoid handling single bytes at a time (for resize, mainly)
+ */
+const size_t NETWORK_BUFFER_CHUNK_SIZE = 1024;
+
+class NetworkBufferError : public Error {
+ public:
+ NetworkBufferError (const std::string &message) : Error(message) { }
+};
+
+/*
+ * Base buffer operations for uffered socket send/recv
+ */
+class NetworkBufferBase {
+ protected:
+ // the socket that we use
+ NetworkSocket socket;
+
+ char *buf;
+ size_t size, offset;
+
+ public:
+ NetworkBufferBase (NetworkSocket &socket, size_t size_hint);
+ ~NetworkBufferBase (void);
+
+ private:
+ NetworkBufferBase (const NetworkBufferBase ©);
+ NetworkBufferBase& operator= (const NetworkBufferBase ©);
+
+ protected:
+ void resize (size_t item_size);
+ void trim (size_t prefix_size);
+};
+
+/*
+ * Buffered prefix-len socket input
+ */
+class NetworkBufferInput : public NetworkBufferBase {
+ public:
+ NetworkBufferInput (NetworkSocket &socket, size_t size_hint);
+
+ private:
+ /*
+ * Attempts to recv the given number of bytes, returning true on success
+ */
+ bool try_read (size_t item_size);
+
+ /*
+ * Returns true if the buffer contains at least the given amount of data
+ */
+ bool have_data (size_t data_size);
+
+ public:
+ /*
+ * Attempts to read the length prefix into val_ref, returning true on success
+ */
+ bool peek_prefix (uint16_t &val_ref);
+ bool peek_prefix (uint32_t &val_ref);
+
+ /*
+ * This attempts to collect the prefix + data into our buffer, and then returns the length and a pointer to the
+ * internal memory buffer. Use flush_data when done with the data
+ */
+
+ // XXX: template definition moved here from .cc
+ template <typename PrefixType> bool peek_data (PrefixType &prefix, char *&buf_ref) {
+ 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
+ // XXX: a zero-prefix will trigger this
+ assert(missing);
+
+ // try and read the missing data
+ if (try_read(missing) == false) {
+ // if unable to read what we need, return zero.
+ return false;
+ }
+
+ // assess the situation again
+ } while (true);
+
+ // update the buf_ref to point past the prefix-length
+ buf_ref = buf + sizeof(PrefixType);
+
+ // return
+ return true;
+ }
+
+ template <typename PrefixType> void flush_data (void) {
+ PrefixType prefix;
+
+ // we *must* have a valid prefix
+ assert(peek_prefix(prefix));
+
+ // trim the bytes out
+ trim(sizeof(PrefixType) + prefix);
+ }
+};
+
+/*
+ * Buffered prefix-len socket output
+ */
+class NetworkBufferOutput : public NetworkBufferBase {
+ public:
+ NetworkBufferOutput (NetworkSocket &socket, size_t size_hint);
+
+ private:
+ /*
+ * If our buffer is empty, fast-path the given buf_ptr directly to send(), else copy the remaining
+ * portion to our buffer for later use with flush_write
+ */
+ void push_write (char *buf_ptr, size_t buf_size);
+
+ public:
+ /*
+ * Try and send() stuff out of our buffer, or ignore if it's empty
+ */
+ void flush_write (void);
+
+ /*
+ * push_write, first the given prefix and then the buf (which contains <prefix> bytes of data)
+ */
+ void write_prefix (char *buf, uint16_t prefix);
+ void write_prefix (char *buf, uint32_t prefix);
+};
+
+#endif
--- a/src/Network/Client.cc Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Client.cc Thu Dec 04 21:59:23 2008 +0000
@@ -16,7 +16,7 @@
// XXX: sig_disconnected
}
-void NetworkClient::on_create (NetworkObject_Client *obj, NetworkMessageID msg_id, NetworkPacket &pkt) {
+void NetworkClient::on_create (NetworkObject_Client *obj, NetworkMessageID msg_id, NetworkPacketInput &pkt) {
switch (msg_id) {
case NETMSG_SERVER_HELLO:
on_server_hello(obj, pkt);
@@ -38,7 +38,7 @@
}
}
-void NetworkClient::on_server_hello (NetworkObject_Client *obj, NetworkPacket &pkt) {
+void NetworkClient::on_server_hello (NetworkObject_Client *obj, NetworkPacketInput &pkt) {
// read the packet
Vector position = pkt.read_vector();
@@ -51,7 +51,7 @@
state.newLocalPlayer(player);
}
-void NetworkClient::on_player_info (NetworkObject_Client *obj, NetworkPacket &pkt) {
+void NetworkClient::on_player_info (NetworkObject_Client *obj, NetworkPacketInput &pkt) {
// read the packet
Vector position = pkt.read_vector();
@@ -65,7 +65,7 @@
}
-void NetworkClient::on_player_join (NetworkObject_Client *obj, NetworkPacket &pkt) {
+void NetworkClient::on_player_join (NetworkObject_Client *obj, NetworkPacketInput &pkt) {
// read the packet
Vector position = pkt.read_vector();
@@ -87,11 +87,40 @@
// delete player;
}
+NetworkClientPlayerHelper::NetworkClientPlayerHelper (NetworkClient &client, NetworkObject_Client *obj) :
+ client(client), obj(obj) {
+
+ // receive position updates
+ slots.connect(obj->sig_message(NETMSG_PLAYER_POSITION), this, &NetworkClientPlayerHelper::on_position);
+ slots.connect(obj->sig_message(NETMSG_PLAYER_DIG), this, &NetworkClientPlayerHelper::on_dig);
+}
+
+void NetworkClientPlayerHelper::on_position (NetworkPacketInput &pkt) {
+ Vector position = pkt.read_vector();
+ Vector velocity = pkt.read_vector();
+ int flags = pkt.read_uint8();
+ float aim = pkt.read_float32();
+
+ Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", position=" << position << ", velocity=" << velocity << ", aim=" << aim << ", [" << flags << "]";
+
+ // just update...
+ _handleUpdate(position, velocity, flags & NETWORK_PHYSICS_INAIR, flags & NETWORK_PHYSICS_FACE_RIGHT, aim);
+}
+
+void NetworkClientPlayerHelper::on_dig (NetworkPacketInput &pkt) {
+ Vector position = pkt.read_vector();
+ float radius = pkt.read_float32();
+
+ Engine::log(INFO, "client_player.on_dig") << "obj=" << obj << ", position=" << position << ", radius=" << radius;
+
+ // just update...
+ _handleDig(position, radius);
+}
+
+
NetworkClientLocalPlayer::NetworkClientLocalPlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position) :
- LocalPlayer(client.state, position, true), client(client), obj(obj) {
+ LocalPlayer(client.state, position, true), NetworkClientPlayerHelper(client, obj) {
- // receive messages
- slots.connect(obj->sig_message(NETMSG_PLAYER_POSITION), this, &NetworkClientLocalPlayer::on_position);
}
void NetworkClientLocalPlayer::handleMove (PlayerInput_Move input) {
@@ -104,37 +133,22 @@
// 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);
+void NetworkClientLocalPlayer::_handleUpdate(Vector position, Vector velocity, bool inAir, bool facingRight, float aim) {
+ updatePhysics(position, velocity, inAir, facingRight, aim);
}
+void NetworkClientLocalPlayer::_handleDig (Vector position, float radius) {
+ handleDig(position, radius);
+}
+
NetworkClientRemotePlayer::NetworkClientRemotePlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position) :
- RemotePlayer(client.state, position, true), client(client), obj(obj) {
+ RemotePlayer(client.state, position, true), NetworkClientPlayerHelper(client, 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) {
+void NetworkClientRemotePlayer::on_quit (NetworkPacketInput &pkt) {
// pkt is empty
(void) pkt;
@@ -143,3 +157,11 @@
client.player_quit(this);
}
+void NetworkClientRemotePlayer::_handleUpdate(Vector position, Vector velocity, bool inAir, bool facingRight, float aim) {
+ updatePhysics(position, velocity, inAir, facingRight, aim);
+}
+
+void NetworkClientRemotePlayer::_handleDig (Vector position, float radius) {
+ handleDig(position, radius);
+}
+
--- a/src/Network/Client.hh Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Client.hh Thu Dec 04 21:59:23 2008 +0000
@@ -26,48 +26,57 @@
NetworkClient (GameState &state, const NetworkAddress &connect_to);
private:
- void on_create (NetworkObject_Client *obj, NetworkMessageID msg_id, NetworkPacket &pkt);
+ void on_create (NetworkObject_Client *obj, NetworkMessageID msg_id, NetworkPacketInput &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);
+ void on_server_hello (NetworkObject_Client *obj, NetworkPacketInput &pkt);
+ void on_player_info (NetworkObject_Client *obj, NetworkPacketInput &pkt);
+ void on_player_join (NetworkObject_Client *obj, NetworkPacketInput &pkt);
public:
void player_quit (NetworkClientRemotePlayer *player);
};
-class NetworkClientLocalPlayer : public LocalPlayer {
- private:
+class NetworkClientPlayerHelper {
+ protected:
NetworkClient &client;
CL_SlotContainer slots;
-
+
NetworkObject_Client *obj;
+ protected:
+ NetworkClientPlayerHelper (NetworkClient &client, NetworkObject_Client *obj);
+
+ private:
+ void on_position (NetworkPacketInput &pkt);
+ void on_dig (NetworkPacketInput &pkt);
+
+ protected:
+ virtual void _handleUpdate (Vector position, Vector velocity, bool inAir, bool facingRight, float aim) = 0;
+ virtual void _handleDig (Vector position, float radius) = 0;
+};
+
+class NetworkClientLocalPlayer : public NetworkClientPlayerHelper, public LocalPlayer {
public:
NetworkClientLocalPlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position);
virtual void handleMove (PlayerInput_Move input);
- private:
- void on_position (NetworkPacket &pkt);
+ protected:
+ virtual void _handleUpdate (Vector position, Vector velocity, bool inAir, bool facingRight, float aim);
+ virtual void _handleDig (Vector position, float radius);
};
-class NetworkClientRemotePlayer : public RemotePlayer {
- private:
- NetworkClient &client;
-
- CL_SlotContainer slots;
-
- NetworkObject_Client *obj;
-
+class NetworkClientRemotePlayer : public NetworkClientPlayerHelper, public RemotePlayer {
public:
NetworkClientRemotePlayer (NetworkClient &client, NetworkObject_Client *obj, Vector position);
private:
- void on_position (NetworkPacket &pkt);
-
- void on_quit (NetworkPacket &pkt);
+ void on_quit (NetworkPacketInput &pkt);
+
+ protected:
+ virtual void _handleUpdate (Vector position, Vector velocity, bool inAir, bool facingRight, float aim);
+ virtual void _handleDig (Vector position, float radius);
};
#endif
--- a/src/Network/Node.cc Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Node.cc Thu Dec 04 21:59:23 2008 +0000
@@ -27,7 +27,7 @@
// delete this;
}
-void NetworkNode::send (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable) {
+void NetworkNode::send (NetworkChannelID channel_id, const NetworkPacketBuffer &pkt, bool reliable) {
assert(channel_id > 0);
// add our header
--- a/src/Network/Node.hh Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Node.hh Thu Dec 04 21:59:23 2008 +0000
@@ -35,7 +35,7 @@
CL_Signal_v0 _sig_disconnected;
public:
- void send (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable = true);
+ void send (NetworkChannelID channel_id, const NetworkPacketBuffer &pkt, bool reliable = true);
const NetworkAddress& getRemoteAddress (void);
--- a/src/Network/Object.cc Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Object.cc Thu Dec 04 21:59:23 2008 +0000
@@ -13,7 +13,7 @@
slot_message = session.sig_chan_message(channel_id).connect(this, &NetworkObjectController::on_message);
}
-void NetworkObjectController::on_message (NetworkPacket &pkt, NetworkNode *node) {
+void NetworkObjectController::on_message (NetworkPacketInput &pkt, NetworkNode *node) {
uint32_t obj_id = pkt.read_uint32();
uint16_t msg_id = pkt.read_uint16();
@@ -40,7 +40,7 @@
return ++id_pool;
}
-void NetworkObject_ServerController::handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node) {
+void NetworkObject_ServerController::handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node) {
(void) obj_id;
(void) msg_id;
(void) pkt;
@@ -59,7 +59,7 @@
}
-void NetworkObject_ClientController::handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node) {
+void NetworkObject_ClientController::handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node) {
// we only communicate with the server
assert(node == server);
@@ -81,7 +81,7 @@
controller.objects[obj_id] = this;
}
-void NetworkObject::buildPacket (NetworkPacket &pkt, NetworkMessageID msg_id, const NetworkPacket &payload) {
+void NetworkObject::buildPacket (NetworkPacketOutput &pkt, NetworkMessageID msg_id, const NetworkPacketBuffer &payload) {
pkt.write_uint32(obj_id);
pkt.write_uint16(msg_id);
pkt.write_packet(payload);
@@ -99,11 +99,11 @@
}
-void NetworkObject_Server::handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt) {
+void NetworkObject_Server::handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacketInput &pkt) {
_map_sig_message[msg_id](node, pkt);
}
-void NetworkObject_Server::send_to (NetworkNode *dst, NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable) {
+void NetworkObject_Server::send_to (NetworkNode *dst, NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, bool reliable) {
NetworkPacket pkt_out;
buildPacket(pkt_out, msg_id, pkt);
@@ -111,11 +111,11 @@
dst->send(controller.channel_id, pkt_out, reliable);
}
-void NetworkObject_Server::send_all (NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable) {
+void NetworkObject_Server::send_all (NetworkMessageID msg_id, const NetworkPacketBuffer &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) {
+void NetworkObject_Server::send_all_except (NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, NetworkNode *black_sheep, bool reliable) {
NetworkPacket pkt_out;
buildPacket(pkt_out, msg_id, pkt);
@@ -132,13 +132,13 @@
// nothing
}
-void NetworkObject_Client::handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt) {
+void NetworkObject_Client::handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacketInput &pkt) {
assert(node == controller.server);
_map_sig_message[msg_id](pkt);
}
-void NetworkObject_Client::send (NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable) {
+void NetworkObject_Client::send (NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, bool reliable) {
NetworkPacket pkt_out;
buildPacket(pkt_out, msg_id, pkt);
--- a/src/Network/Object.hh Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Object.hh Thu Dec 04 21:59:23 2008 +0000
@@ -32,10 +32,10 @@
NetworkObjectController (NetworkSession &session, NetworkChannelID channel_id);
private:
- void on_message (NetworkPacket &pkt, NetworkNode *node);
+ void on_message (NetworkPacketInput &pkt, NetworkNode *node);
protected:
- virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node) = 0;
+ virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node) = 0;
};
class NetworkObject_ServerController : public NetworkObjectController {
@@ -50,7 +50,7 @@
protected:
NetworkObjectID getObjectID (void);
- virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacket &pkt, NetworkNode *node);
+ virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node);
};
class NetworkObject_ClientController : public NetworkObjectController {
@@ -59,16 +59,16 @@
private:
NetworkNode *server;
- CL_Signal_v3<NetworkObject_Client*, NetworkMessageID, NetworkPacket&> _sig_create;
+ CL_Signal_v3<NetworkObject_Client*, NetworkMessageID, NetworkPacketInput&> _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);
+ virtual void handle_create (NetworkObjectID obj_id, NetworkMessageID msg_id, NetworkPacketInput &pkt, NetworkNode *node);
public:
- CL_Signal_v3<NetworkObject_Client*, NetworkMessageID, NetworkPacket&>& sig_create (void) { return _sig_create; }
+ CL_Signal_v3<NetworkObject_Client*, NetworkMessageID, NetworkPacketInput&>& sig_create (void) { return _sig_create; }
};
class NetworkObject {
@@ -81,9 +81,9 @@
protected:
NetworkObject (NetworkObjectController &controller, NetworkObjectID obj_id);
- virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt) = 0;
+ virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacketInput &pkt) = 0;
- void buildPacket (NetworkPacket &pkt, NetworkMessageID msg_id, const NetworkPacket &payload);
+ void buildPacket (NetworkPacketOutput &pkt, NetworkMessageID msg_id, const NetworkPacketBuffer &payload);
};
std::ostream& operator<< (std::ostream &s, const NetworkObject &obj);
@@ -94,20 +94,20 @@
private:
NetworkObject_ServerController &controller;
- std::map<NetworkMessageID, CL_Signal_v2<NetworkNode*, NetworkPacket&> > _map_sig_message;
+ std::map<NetworkMessageID, CL_Signal_v2<NetworkNode*, NetworkPacketInput&> > _map_sig_message;
public:
NetworkObject_Server (NetworkObject_ServerController &controller);
protected:
- virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt);
+ virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacketInput &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);
+ void send_to (NetworkNode *dst, NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, bool reliable = true);
+ void send_all (NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, bool reliable = true);
+ void send_all_except (NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, NetworkNode *black_sheep, bool reliable = true);
- CL_Signal_v2<NetworkNode*, NetworkPacket&>& sig_message (NetworkMessageID msg_id) { return _map_sig_message[msg_id]; }
+ CL_Signal_v2<NetworkNode*, NetworkPacketInput&>& sig_message (NetworkMessageID msg_id) { return _map_sig_message[msg_id]; }
};
class NetworkObject_Client : public NetworkObject {
@@ -116,17 +116,17 @@
private:
NetworkObject_ClientController &controller;
- std::map<NetworkMessageID, CL_Signal_v1<NetworkPacket&> > _map_sig_message;
+ std::map<NetworkMessageID, CL_Signal_v1<NetworkPacketInput&> > _map_sig_message;
protected:
NetworkObject_Client (NetworkObject_ClientController &controller, NetworkObjectID id);
- virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacket &pkt);
+ virtual void handle_packet (NetworkNode *node, NetworkMessageID msg_id, NetworkPacketInput &pkt);
public:
- void send (NetworkMessageID msg_id, const NetworkPacket &pkt, bool reliable = true);
+ void send (NetworkMessageID msg_id, const NetworkPacketBuffer &pkt, bool reliable = true);
- CL_Signal_v1<NetworkPacket&>& sig_message (NetworkMessageID msg_id) { return _map_sig_message[msg_id]; }
+ CL_Signal_v1<NetworkPacketInput&>& sig_message (NetworkMessageID msg_id) { return _map_sig_message[msg_id]; }
};
#endif /* NETWORK_OBJECT_HH */
--- a/src/Network/Packet.cc Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Packet.cc Thu Dec 04 21:59:23 2008 +0000
@@ -4,48 +4,10 @@
#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) {
+/*
+ * NetworkPacketInput
+ */
+template <typename T> T NetworkPacketInput::read_val (void) {
T val;
// read
@@ -55,90 +17,150 @@
return val;
}
-template <typename T> void NetworkPacket::write_val (const T &val) {
- // write
- write(&val, sizeof(T));
-}
-
-uint32_t NetworkPacket::read_uint32 (void) {
+uint32_t NetworkPacketInput::read_uint32 (void) {
return ntohl(read_val<uint32_t>());
}
-uint16_t NetworkPacket::read_uint16 (void) {
+uint16_t NetworkPacketInput::read_uint16 (void) {
return ntohs(read_val<uint16_t>());
}
-uint8_t NetworkPacket::read_uint8 (void) {
+uint8_t NetworkPacketInput::read_uint8 (void) {
return read_val<uint8_t>();
}
-int32_t NetworkPacket::read_int32 (void) {
+int32_t NetworkPacketInput::read_int32 (void) {
return ntohl(read_val<int32_t>());
}
-int16_t NetworkPacket::read_int16 (void) {
+int16_t NetworkPacketInput::read_int16 (void) {
return ntohs(read_val<int16_t>());
}
-int8_t NetworkPacket::read_int8 (void) {
+int8_t NetworkPacketInput::read_int8 (void) {
return read_val<int8_t>();
}
-float NetworkPacket::read_float32 (void) {
+float NetworkPacketInput::read_float32 (void) {
int32_t ival = read_int32();
return *((float *) &ival);
}
-Vector NetworkPacket::read_vector (void) {
+Vector NetworkPacketInput::read_vector (void) {
float fx = read_float32();
float fy = read_float32();
return Vector(fx, fy);
}
-void NetworkPacket::write_uint32 (uint32_t val) {
+/*
+ * NetworkPacketOutput
+ */
+template <typename T> void NetworkPacketOutput::write_val (const T &val) {
+ // write
+ write(&val, sizeof(T));
+}
+
+
+void NetworkPacketOutput::write_uint32 (uint32_t val) {
write_val<uint32_t>(htonl(val));
}
-void NetworkPacket::write_uint16 (uint16_t val) {
+void NetworkPacketOutput::write_uint16 (uint16_t val) {
write_val<uint16_t>(htons(val));
}
-void NetworkPacket::write_uint8 (uint8_t val) {
+void NetworkPacketOutput::write_uint8 (uint8_t val) {
write_val<uint8_t>(val);
}
-void NetworkPacket::write_int32 (int32_t val) {
+void NetworkPacketOutput::write_int32 (int32_t val) {
write_val<int32_t>(htonl(val));
}
-void NetworkPacket::write_int16 (int16_t val) {
+void NetworkPacketOutput::write_int16 (int16_t val) {
write_val<int16_t>(htons(val));
}
-void NetworkPacket::write_int8 (int8_t val) {
+void NetworkPacketOutput::write_int8 (int8_t val) {
write_val<int8_t>(val);
}
-void NetworkPacket::write_float32 (float val) {
+void NetworkPacketOutput::write_float32 (float val) {
write_int32(*((int32_t *) &val));
}
-void NetworkPacket::write_vector (const Vector &vec) {
+void NetworkPacketOutput::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();
+void NetworkPacketOutput::write_packet (const NetworkPacketBuffer &pkt) {
+ // just write() it
+ write(pkt.get_buf(), pkt.get_data_size());
}
+/*
+ * NetworkPacketBuffer
+ */
+NetworkPacketBuffer::NetworkPacketBuffer (char *buf_ptr, size_t buf_size, size_t data_size) :
+ buf_ptr(buf_ptr), buf_size(buf_size), data_size(data_size), offset(0) {
+
+ // nothing
+ if (buf_ptr == NULL)
+ throw NetworkPacketError("buf_ptr may not be NULL");
+}
+
+void NetworkPacketBuffer::check_write_size (size_t item_size) {
+ if (offset + item_size > buf_size)
+ throw NetworkPacketError("not enough space to write");
+
+}
+
+void NetworkPacketBuffer::check_read_size (size_t item_size) {
+ if (offset + item_size > data_size)
+ throw NetworkPacketError("not enough data to read");
+}
+
+void NetworkPacketBuffer::write (const void *ptr, size_t len) {
+ // check buffer overflow
+ check_write_size(len);
+
+ // set value
+ memcpy(buf_ptr + offset, ptr, len);
+
+ // update offset and size
+ offset += len;
+ data_size += len;
+}
+
+void NetworkPacketBuffer::read (void *ptr, size_t len) {
+ // check buffer underflow
+ check_read_size(len);
+
+ // set value
+ memcpy(ptr, buf_ptr + offset, len);
+
+ // update offset
+ offset += len;
+}
+
+/*
+ * NetworkPacket
+ */
+NetworkPacket::NetworkPacket (void) :
+ NetworkPacketBuffer(_buf, NETWORK_PACKET_SIZE, 0)
+{
+
+}
+
+/*
+ * BigNetworkPacket
+ */
+BigNetworkPacket::BigNetworkPacket (size_t size) :
+ NetworkPacketBuffer((char *) malloc(size), size, 0)
+{
+
+}
+
--- a/src/Network/Packet.hh Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Packet.hh Thu Dec 04 21:59:23 2008 +0000
@@ -10,32 +10,25 @@
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);
+// forward-declare for write_packet
+class NetworkPacketBuffer;
- template <typename T> T read_val (void);
- template <typename T> void write_val (const T &val);
-
+/*
+ * Read-interface for network packets
+ */
+class NetworkPacketInput {
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; }
+ /*
+ * Copies len bytes from the packet to ptr, first testing that they exist
+ */
+ virtual void read (void *ptr, size_t len) = 0;
+
+ /*
+ * Convenience function to read() and return the value of the given type
+ */
+ template <typename T> T read_val (void);
- 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
+ // thse handle network-endianlness
uint32_t read_uint32 (void);
uint16_t read_uint16 (void);
uint8_t read_uint8 (void);
@@ -45,8 +38,26 @@
int8_t read_int8 (void);
float read_float32 (void);
+
+ Vector read_vector (void);
+};
+/*
+ * Write-interface for network packets
+ */
+class NetworkPacketOutput {
+ public:
+ /*
+ * Copies len bytes from ptr to the packet, first testing that they fit
+ */
+ virtual void write (const void *ptr, size_t len) = 0;
+ /*
+ * Convenience function to write() the value of the given type-value
+ */
+ template <typename T> void write_val (const T &val);
+
+ // thse handle network-endianlness
void write_uint32 (uint32_t val);
void write_uint16 (uint16_t val);
void write_uint8 (uint8_t val);
@@ -57,10 +68,85 @@
void write_float32 (float val);
- // complex
- Vector read_vector (void);
void write_vector (const Vector &vec);
- void write_packet (const NetworkPacket &pkt);
+
+ /*
+ * This copies the contents of the given packet into this packet
+ */
+ void write_packet (const NetworkPacketBuffer &pkt);
+};
+
+/*
+ * Implements the in-memory seekable buffer used by NetworkPackets.
+ */
+class NetworkPacketBuffer : public NetworkPacketInput, public NetworkPacketOutput {
+ protected:
+ // the pointer to the buffer
+ char *buf_ptr;
+
+ // the buffer size, the amount of data in the buffer, and the current read/write offset
+ size_t buf_size, data_size, offset;
+
+ /*
+ * Assert that the given number of bytes fits into the buffer. Throws NetworkPacketError if not.
+ *
+ * The default implementation just checks offset and buf_size
+ */
+ virtual void check_write_size (size_t item_size);
+
+ /*
+ * Assert that the give number of bytes is available from the buffer. Throws NetworkPacketError if not
+ *
+ * The default implementation just checks offset and data_size
+ */
+ virtual void check_read_size (size_t item_size);
+
+ public:
+ /*
+ * Construct the NetworkPacketBuffer using the given initial buf_ptr and buf_size
+ */
+ NetworkPacketBuffer (char *buf_ptr, size_t buf_size, size_t data_size);
+
+ /*
+ * These memcpy() into/out of the buf_ptr, using ceck_read/write_size
+ */
+ virtual void read (void *ptr, size_t len);
+ virtual void write (const void *ptr, size_t len);
+
+ /*
+ * Accessor functions, used by the actual socket code to read/write the buffer
+ */
+ char* get_buf (void) { return buf_ptr; }
+ const char* get_buf (void) const { return buf_ptr; }
+ size_t get_data_size (void) const { return data_size; }
+ size_t get_buf_size (void) const { return buf_size; }
+
+ /*
+ * Used by the socket code after recv() to mark how many bytes of data the buffer has
+ */
+ void set_data_size (size_t size) { offset = 0; data_size = size; }
+};
+
+/*
+ * The common case is a packet that fits in a single UDP packet, so this just uses a static buffer of a fixed size,
+ * NETWORK_PACKET_SIZE.
+ */
+class NetworkPacket : public NetworkPacketBuffer {
+ private:
+ char _buf[NETWORK_PACKET_SIZE];
+
+ public:
+ NetworkPacket (void);
+};
+
+/*
+ * This is intended for sending bigger packets via TCP; the buffer is allocated on the heap.
+ *
+ * XXX: let the buffer grow as well
+ */
+class BigNetworkPacket : public NetworkPacketBuffer {
+ public:
+ BigNetworkPacket (size_t size);
};
#endif /* NETWORK_PACKET_HH */
--- a/src/Network/Protocol.hh Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Protocol.hh Thu Dec 04 21:59:23 2008 +0000
@@ -14,44 +14,45 @@
enum NetworkPhysicsFlags {
NETWORK_PHYSICS_INAIR = 0x01,
+ NETWORK_PHYSICS_FACE_RIGHT = 0x02,
};
enum NetworkMessage {
- NETMSG_PACKET_INVALID = 0x00,
+ NETMSG_PACKET_INVALID = 0x0000,
/*
* You have joined the game:
*
* Vector initial_position
*/
- NETMSG_SERVER_HELLO = 0x0100,
+ NETMSG_SERVER_HELLO = 0x0100,
/*
* New client has connected to server:
*
* Vector initial_position
*/
- NETMSG_PLAYER_JOIN = 0x0101,
+ NETMSG_PLAYER_JOIN = 0x0101,
/*
* Client has left server:
*
*/
- NETMSG_PLAYER_QUIT = 0x0102,
+ NETMSG_PLAYER_QUIT = 0x0102,
/*
* Client has moved
*
* uint16_t PlayerInput_Move
*/
- NETMSG_CLIENT_MOVE = 0x0201,
+ NETMSG_CLIENT_MOVE = 0x0201,
/*
* Initial player info
*
* Vector initial_position
*/
- NETMSG_PLAYER_INFO = 0x0300,
+ NETMSG_PLAYER_INFO = 0x0300,
/*
* Player position update
@@ -59,8 +60,17 @@
* Vector position
* Vector velocity
* uint8_t NetworkPhysicsFlags
+ * float32 aim
*/
NETMSG_PLAYER_POSITION = 0x0301,
+
+ /*
+ * Terrain update, removeGround
+ *
+ * Vector position
+ * float32 radius
+ */
+ NETMSG_PLAYER_DIG = 0x0302,
};
#endif
--- a/src/Network/Server.cc Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Server.cc Thu Dec 04 21:59:23 2008 +0000
@@ -71,6 +71,21 @@
obj.send_all_except(NETMSG_PLAYER_JOIN, hello_pkt, node, true);
}
+void NetworkServerPlayer::handleDig (Vector position, float radius) {
+ NetworkPacket pkt;
+
+ pkt.write_vector(position);
+ pkt.write_float32(radius);
+
+ Engine::log(INFO, "server_player.handle_dig") << "position=" << position << ", radius=" << radius;
+
+ // tell everyone... make this reliable...
+ obj.send_all(NETMSG_PLAYER_DIG, pkt, true);
+
+ // and carry out the actual dig on the server as well
+ Player::handleDig(position, radius);
+}
+
void NetworkServerPlayer::on_disconnected (void) {
NetworkPacket pkt;
@@ -86,7 +101,7 @@
// delete this;
}
-void NetworkServerPlayer::on_move (NetworkNode *src, NetworkPacket &pkt) {
+void NetworkServerPlayer::on_move (NetworkNode *src, NetworkPacketInput &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;
@@ -106,11 +121,15 @@
void NetworkServerPlayer::send_position_update (void) {
NetworkPacket pkt;
+
+ int flags = (inAir & NETWORK_PHYSICS_INAIR) | (facingRight & NETWORK_PHYSICS_FACE_RIGHT);
+
pkt.write_vector(position);
pkt.write_vector(velocity);
- pkt.write_uint8(inAir & NETWORK_PHYSICS_INAIR);
+ pkt.write_uint8(flags);
+ pkt.write_float32(aim);
- Engine::log(INFO, "server_player.send_position_update") << "obj=" << obj << " -> " << position << "+" << velocity;
+ Engine::log(INFO, "server_player.send_position_update") << "obj=" << obj << " -> " << position << "+" << velocity << " [" << flags << "]";
obj.send_all(NETMSG_PLAYER_POSITION, pkt, false);
}
--- a/src/Network/Server.hh Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Server.hh Thu Dec 04 21:59:23 2008 +0000
@@ -44,9 +44,11 @@
public:
NetworkServerPlayer (NetworkServer &server, NetworkNode *node);
+ virtual void handleDig (Vector position, float radius);
+
private:
void on_disconnected (void);
- void on_move (NetworkNode *node, NetworkPacket &pkt);
+ void on_move (NetworkNode *node, NetworkPacketInput &pkt);
void send_position_update (void);
};
--- a/src/Network/Session.cc Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Session.cc Thu Dec 04 21:59:23 2008 +0000
@@ -58,7 +58,7 @@
nodes.erase(node->getRemoteAddress());
}
-void NetworkSession::handle_message (NetworkPacket &pkt, NetworkNode *node) {
+void NetworkSession::handle_message (NetworkPacketInput &pkt, NetworkNode *node) {
// read the channel id
NetworkChannelID channel_id = pkt.read_uint16();
@@ -80,7 +80,7 @@
_sig_node_connected(client_node);
}
-void NetworkSession::on_udp_packet (NetworkPacket &pkt, const NetworkAddress &addr) {
+void NetworkSession::on_udp_packet (NetworkPacketInput &pkt, const NetworkAddress &addr) {
NetworkNode *node = nodes[addr];
// drop from unknown sources
@@ -93,11 +93,11 @@
handle_message(pkt, node);
}
-void NetworkSession::send_all (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable) {
+void NetworkSession::send_all (NetworkChannelID channel_id, const NetworkPacketBuffer &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) {
+void NetworkSession::send_all_except (NetworkChannelID channel_id, const NetworkPacketBuffer &pkt, const NetworkNode *node, bool reliable) {
for (std::map<NetworkAddress, NetworkNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
if (it->second == node)
continue;
--- a/src/Network/Session.hh Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/Session.hh Thu Dec 04 21:59:23 2008 +0000
@@ -27,7 +27,7 @@
CL_SlotContainer slots;
std::map<NetworkAddress, NetworkNode*> nodes;
- std::map<NetworkChannelID, CL_Signal_v2<NetworkPacket&, NetworkNode *> > _map_sig_chan_message;
+ std::map<NetworkChannelID, CL_Signal_v2<NetworkPacketInput&, NetworkNode *> > _map_sig_chan_message;
public:
NetworkSession (uint64_t magic);
@@ -39,20 +39,20 @@
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);
+ void handle_message (NetworkPacketInput &pkt, NetworkNode *node);
private:
void on_tcp_client (NetworkTCPTransport *client);
- void on_udp_packet (NetworkPacket &pkt, const NetworkAddress &addr);
+ void on_udp_packet (NetworkPacketInput &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);
+ void send_all (NetworkChannelID channel_id, const NetworkPacketBuffer &pkt, bool reliable = true);
+ void send_all_except (NetworkChannelID channel_id, const NetworkPacketBuffer &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]; }
+ CL_Signal_v2<NetworkPacketInput&, NetworkNode *>& sig_chan_message (NetworkChannelID cid) { return _map_sig_chan_message[cid]; }
};
#endif /* NETWORK_SESSION_HH */
--- a/src/Network/TCP.cc Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/TCP.cc Thu Dec 04 21:59:23 2008 +0000
@@ -2,236 +2,9 @@
#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::NetworkTCPTransport (NetworkSocket socket) :
socket(socket), in(socket, NETWORK_TCP_INITIAL_IN_BUF), out(socket, NETWORK_TCP_INITIAL_OUT_BUF) {
@@ -243,13 +16,19 @@
void NetworkTCPTransport::on_read (void) {
- uint16_t prefix;
- NetworkPacket packet;
+ uint16_t length;
+ char *buf_ptr;
// 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);
+ while (in.peek_data<uint16_t>(length, buf_ptr)) {
+ // allocate the NetworkPacketBuffer with the given buf_ptr/length
+ NetworkPacketBuffer packet(buf_ptr, length, length);
+
+ // pass the packet on
_sig_packet(packet);
+
+ // flush it
+ in.flush_data<uint16_t>();
}
}
@@ -263,7 +42,7 @@
_sig_disconnect();
}
-void NetworkTCPTransport::write_packet (const NetworkPacket &packet) {
+void NetworkTCPTransport::write_packet (const NetworkPacketBuffer &packet) {
uint16_t prefix = packet.get_data_size();
if (prefix != packet.get_data_size())
--- a/src/Network/TCP.hh Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/TCP.hh Thu Dec 04 21:59:23 2008 +0000
@@ -6,52 +6,17 @@
#include "Socket.hh"
#include "Address.hh"
#include "Packet.hh"
-#include "../Error.hh"
+#include "Buffer.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;
+ NetworkBufferInput in;
+ NetworkBufferOutput out;
CL_SlotContainer slots;
@@ -63,16 +28,16 @@
void on_write (void);
void on_disconnected (void);
- CL_Signal_v1<NetworkPacket &> _sig_packet;
+ CL_Signal_v1<NetworkPacketInput&> _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);
+ void write_packet (const NetworkPacketBuffer &packet);
- CL_Signal_v1<NetworkPacket&>& sig_packet (void) { return _sig_packet; }
+ CL_Signal_v1<NetworkPacketInput&>& sig_packet (void) { return _sig_packet; }
CL_Signal_v0& sig_disconnect (void) { return _sig_disconnect; }
};
--- a/src/Network/UDP.hh Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Network/UDP.hh Thu Dec 04 21:59:23 2008 +0000
@@ -18,12 +18,12 @@
private:
void on_recv (void);
- CL_Signal_v2<NetworkPacket &, const NetworkAddress&> _sig_packet;
+ CL_Signal_v2<NetworkPacketInput&, 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; }
+ CL_Signal_v2<NetworkPacketInput&, const NetworkAddress&>& sig_packet (void) { return _sig_packet; }
};
#endif /* NETWORK_UDP_HH */
--- a/src/PhysicsObject.cc Thu Dec 04 21:10:41 2008 +0000
+++ b/src/PhysicsObject.cc Thu Dec 04 21:59:23 2008 +0000
@@ -306,12 +306,14 @@
this->facingRight = facingRight;
}
-void PhysicsObject::updatePhysics (Vector position, Vector velocity, bool inAir) {
+void PhysicsObject::updatePhysics (Vector position, Vector velocity, bool inAir, bool facingRight, float aim) {
this->position = position;
this->velocity = velocity;
this->inAir = inAir;
+ this->facingRight = facingRight;
+ this->aim = aim;
}
-
+
Vector PhysicsObject::getPosition () {
return this->position;
}
--- a/src/PhysicsObject.hh Thu Dec 04 21:10:41 2008 +0000
+++ b/src/PhysicsObject.hh Thu Dec 04 21:59:23 2008 +0000
@@ -83,8 +83,10 @@
* @param position New position
* @param velocity New velocity
* @param inAir New inAir value
+ * @param facingRight New facingRight value
+ * @param aim New aim
*/
- void updatePhysics(Vector position, Vector velocity, bool inAir);
+ virtual void updatePhysics(Vector position, Vector velocity, bool inAir, bool facingRight, float aim);
private:
// TODO: I'd be tempted to use some already made ClanLib structure
--- a/src/Player.cc Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Player.cc Thu Dec 04 21:59:23 2008 +0000
@@ -64,7 +64,7 @@
// But this now just segfaults
// world.addObject(new Shot(state, position, true));
- world.removeGround(position, 15);
+ handleDig(position, 15);
}
if (input & INPUT_SHOOT) {
@@ -85,6 +85,10 @@
}
+void Player::handleDig (Vector position, float radius) {
+ world.removeGround(position, radius);
+}
+
void Player::debugInfo (void) {
Engine::log(DEBUG, "Player.debugInfo") << "In air: " << this->inAir;
}
--- a/src/Player.hh Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Player.hh Thu Dec 04 21:59:23 2008 +0000
@@ -18,6 +18,7 @@
void debugInfo ();
virtual void handleMove (PlayerInput_Move input);
+ virtual void handleDig (Vector position, float radius);
void shoot (void);
};
--- a/src/Projectile.cc Thu Dec 04 21:10:41 2008 +0000
+++ b/src/Projectile.cc Thu Dec 04 21:59:23 2008 +0000
@@ -1,7 +1,7 @@
#include "Projectile.hh"
Shot::Shot(GameState &state, Vector position, Vector velocity, bool visible) :
- PhysicsObject((PhysicsWorld &) state, PLAYER_MASS, position, velocity), state(state), visible(visible), destroyed(false) {
+ PhysicsObject(state.world, PLAYER_MASS, position, velocity), state(state), visible(visible), destroyed(false) {
// Looks kind of dumb, for ammunition to have shape
std::vector<Vector> shape(4);
shape[0] = Vector(-1, -1);