From 82023866ab4c7483652e9d4605290e39ced3bec3 Mon Sep 17 00:00:00 2001 From: Magnus Auvinen Date: Thu, 24 May 2007 20:54:08 +0000 Subject: large change. moved around all source. splitted server and client into separate files --- src/engine/packet.h | 288 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 src/engine/packet.h (limited to 'src/engine/packet.h') diff --git a/src/engine/packet.h b/src/engine/packet.h new file mode 100644 index 00000000..6dc99043 --- /dev/null +++ b/src/engine/packet.h @@ -0,0 +1,288 @@ +#include +#include + +// TODO: this is not KISS +class packet +{ +protected: + enum + { + MAX_PACKET_SIZE = 1024, + }; + + // packet data + struct header + { + unsigned msg; + unsigned ack; + unsigned seq; + }; + + unsigned char packet_data[MAX_PACKET_SIZE]; + unsigned char *current; + + // these are used to prepend data in the packet + // used for debugging so we have checks that we + // pack and unpack the same way + enum + { + DEBUG_TYPE_INT=0x1, + DEBUG_TYPE_STR=0x2, + DEBUG_TYPE_RAW=0x3, + }; + + // writes an int to the packet + void write_int_raw(int i) + { + // TODO: check for overflow + *(int*)current = i; + current += sizeof(int); + } + + // reads an int from the packet + int read_int_raw() + { + // TODO: check for overflow + int i = *(int*)current; + current += sizeof(int); + return i; + } + + void debug_insert_mark(int type, int size) + { + write_int_raw((type<<16)|size); + } + + void debug_verify_mark(int type, int size) + { + if(read_int_raw() != ((type<<16) | size)) + dbg_assert(0, "error during packet disassembly"); + } + +public: + packet(unsigned msg=0) + { + current = packet_data; + current += sizeof(header); + ((header*)packet_data)->msg = msg; + } + + void set_header(unsigned ack, unsigned seq) + { + ((header*)packet_data)->ack = ack; + ((header*)packet_data)->seq = seq; + } + + // writes an int to the packet + void write_int(int i) + { + debug_insert_mark(DEBUG_TYPE_INT, 4); + write_int_raw(i); + } + + void write_raw(const char *raw, int size) + { + debug_insert_mark(DEBUG_TYPE_RAW, size); + while(size--) + *current++ = *raw++; + } + + // writes a string to the packet + void write_str(const char *str) + { + debug_insert_mark(DEBUG_TYPE_STR, 0); + int s = strlen(str)+1; + write_int_raw(s); + for(;*str; current++, str++) + *current = *str; + *current = 0; + current++; + } + + // reads an int from the packet + int read_int() + { + debug_verify_mark(DEBUG_TYPE_INT, 4); + return read_int_raw(); + } + + // reads a string from the packet + const char *read_str() + { + debug_verify_mark(DEBUG_TYPE_STR, 0); + int size = read_int_raw(); + const char *s = (const char *)current; + //dbg_msg("packet", "reading string '%s' (%d)", s, size); + current += size; + return s; + } + + const char *read_raw(int size) + { + debug_verify_mark(DEBUG_TYPE_RAW, size); + const char *d = (const char *)current; + current += size; + return d; + } + + // TODO: impelement this + bool is_good() const { return true; } + + unsigned msg() const { return ((header*)packet_data)->msg; } + unsigned seq() const { return ((header*)packet_data)->seq; } + unsigned ack() const { return ((header*)packet_data)->ack; } + + // access functions to get the size and data + int size() const { return (int)(current-(unsigned char*)packet_data); } + int max_size() const { return MAX_PACKET_SIZE; } + void *data() { return packet_data; } +}; + +// +class connection +{ + baselib::socket_udp4 *socket; + baselib::netaddr4 addr; + unsigned seq; + unsigned ack; + unsigned last_ack; + + unsigned counter_sent_bytes; + unsigned counter_recv_bytes; + +public: + void counter_reset() + { + counter_sent_bytes = 0; + counter_recv_bytes = 0; + } + + void counter_get(unsigned *sent, unsigned *recved) + { + *sent = counter_sent_bytes; + *recved = counter_recv_bytes; + } + + void init(baselib::socket_udp4 *socket, const baselib::netaddr4 *addr) + { + this->addr = *addr; + this->socket = socket; + last_ack = 0; + ack = 0; + seq = 0; + counter_reset(); + } + + void send(packet *p) + { + if(p->msg()&(31<<1)) + { + // vital packet + seq++; + // TODO: save packet, we might need to retransmit + } + + p->set_header(ack, seq); + socket->send(&address(), p->data(), p->size()); + counter_sent_bytes += p->size(); + } + + packet *feed(packet *p) + { + counter_recv_bytes += p->size(); + + if(p->msg()&(31<<1)) + { + if(p->seq() == ack+1) + { + // packet in seqence, ack it + ack++; + //dbg_msg("network/connection", "packet in sequence. seq/ack=%x", ack); + return p; + } + else if(p->seq() > ack) + { + // TODO: request resend + // packet loss + dbg_msg("network/connection", "packet loss! seq=%x ack=%x+1", p->seq(), ack); + return p; + } + else + { + // we already got this packet + return 0x0; + } + } + + if(last_ack != p->ack()) + { + // TODO: remove acked packets + } + + return p; + } + + const baselib::netaddr4 &address() const { return addr; } + + void update() + { + } +}; + +//const char *NETWORK_VERSION = "development"; + +enum +{ + NETMSG_VITAL=0x80000000, + NETMSG_CONTEXT_CONNECT=0x00010000, + NETMSG_CONTEXT_GAME=0x00020000, + NETMSG_CONTEXT_GLOBAL=0x00040000, + + // connection phase + NETMSG_CLIENT_CONNECT=NETMSG_CONTEXT_CONNECT|1, + // str32 name + // str32 clan + // str32 password + // str32 skin + + // TODO: These should be implemented to make the server send the map to the client on connect + // NETMSG_CLIENT_FETCH, + // NETMSG_SERVER_MAPDATA, + + NETMSG_SERVER_ACCEPT=NETMSG_CONTEXT_CONNECT|2, + // str32 mapname + + + NETMSG_CLIENT_DONE=NETMSG_VITAL|NETMSG_CONTEXT_CONNECT|3, + // nothing + + // game phase + NETMSG_SERVER_SNAP = NETMSG_CONTEXT_GAME|1, // server will spam these + // int num_parts + // int part + // int size + // data * + + NETMSG_CLIENT_INPUT = NETMSG_CONTEXT_GAME|1, // client will spam these + // int input[MAX_INPUTS] + + NETMSG_SERVER_EVENT = NETMSG_CONTEXT_GAME|NETMSG_VITAL|2, + NETMSG_CLIENT_EVENT = NETMSG_CONTEXT_GAME|NETMSG_VITAL|2, + + NETMSG_CLIENT_CHECKALIVE = NETMSG_CONTEXT_GAME|NETMSG_VITAL|3, // check if client is alive + + NETMSG_CLIENT_ERROR=0x0fffffff, + // str128 reason + + NETMSG_SERVER_ERROR=0x0fffffff, + // str128 reason +}; + +enum +{ + MAX_NAME_LENGTH=32, + MAX_CLANNAME_LENGTH=32, + MAX_INPUT_SIZE=128, + MAX_SNAPSHOT_SIZE=64*1024, + MAX_SNAPSHOT_PACKSIZE=768 +}; -- cgit 1.4.1