X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fprotocol.cpp;fp=source%2Fprotocol.cpp;h=1a21c9e96913ac57a4379b9d0be8cf39ecfaf2cd;hb=ef23ca71babc753231bb2dd197be6dd7099d9804;hp=0000000000000000000000000000000000000000;hpb=861c4e9c54df7594a362013fdf6b1e048e935ae4;p=libs%2Fnet.git diff --git a/source/protocol.cpp b/source/protocol.cpp new file mode 100644 index 0000000..1a21c9e --- /dev/null +++ b/source/protocol.cpp @@ -0,0 +1,242 @@ +/* $Id$ + +This file is part of libmspnet +Copyright © 2009 Mikkosoft Productions, Mikko Rasa +Distributed under the LGPL +*/ + +#include +#include +#include +#include "protocol.h" + +using namespace std; + +namespace { + +template +class Assembler +{ +public: + static char *assemble(const T &v, char *, char *); + static const char *disassemble(T &, const char *, const char *); +}; + +template +class Assembler > +{ +public: + static char *assemble(const vector &v, char *, char *); + static const char *disassemble(vector &, const char *, const char *); +}; + +template +char *Assembler::assemble(const T &v, char *data, char *end) +{ + // XXX Assumes little-endian + const char *ptr=reinterpret_cast(&v)+sizeof(T); + for(unsigned i=0; i +char *Assembler::assemble(const string &v, char *data, char *end) +{ + data=Assembler::assemble(v.size(), data, end); + if(end-data(v.size())) + throw Msp::Exception("Out of buffer space"); + memcpy(data, v.data(), v.size()); + return data+v.size(); +} + +template +char *Assembler >::assemble(const vector &v, char *data, char *end) +{ + data=Assembler::assemble(v.size(), data, end); + for(typename vector::const_iterator i=v.begin(); i!=v.end(); ++i) + data=Assembler::assemble(*i, data, end); + return data; +} + +template +const char *Assembler::disassemble(T &v, const char *data, const char *end) +{ + char *ptr=reinterpret_cast(&v)+sizeof(T); + for(unsigned i=0; i +const char *Assembler::disassemble(string &v, const char *data, const char *end) +{ + unsigned short size; + data=Assembler::disassemble(size, data, end); + if(end-data +const char *Assembler >::disassemble(vector &v, const char *data, const char *end) +{ + /* We assume that the vector is in pristine state - this holds because the + only code path leading here is from PacketDef

::disassemble, which creates + a new packet. */ + unsigned short size; + data=Assembler::disassemble(size, data, end); + for(unsigned i=0; i::disassemble(u, data, end); + v.push_back(u); + } + return data; +} + +} + +namespace Msp { +namespace Net { + +Protocol::Protocol(unsigned npi): + next_packet_id(npi) +{ } + +Protocol::~Protocol() +{ + for(map::iterator i=packet_class_defs.begin(); i!=packet_class_defs.end(); ++i) + delete i->second; +} + +void Protocol::add_packet(PacketDefBase &pdef) +{ + PacketDefBase *&ptr=packet_class_defs[pdef.get_class_id()]; + if(ptr) + delete ptr; + ptr=&pdef; + packet_id_defs[pdef.get_id()]=&pdef; +} + +const Protocol::PacketDefBase &Protocol::get_packet_by_class(unsigned id) const +{ + PacketMap::const_iterator i=packet_class_defs.find(id); + if(i==packet_class_defs.end()) + throw KeyError("Unknown packet class", lexical_cast(id)); + return *i->second; +} + +const Protocol::PacketDefBase &Protocol::get_packet_by_id(unsigned id) const +{ + PacketMap::const_iterator i=packet_id_defs.find(id); + if(i==packet_id_defs.end()) + throw KeyError("Unknown packet ID", lexical_cast(id)); + return *i->second; +} + +unsigned Protocol::disassemble(ReceiverBase &rcv, const char *data, unsigned size) const +{ + const unsigned char *udata=reinterpret_cast(data); + unsigned id=(udata[0]<<8)+udata[1]; + unsigned psz=(udata[2]<<8)+udata[3]; + if(psz>size) + throw InvalidParameterValue("Not enough data for packet"); + const PacketDefBase &pdef=get_packet_by_id(id); + const char *ptr=pdef.disassemble(rcv, data+4, data+psz); + return ptr-data; +} + +unsigned Protocol::get_packet_size(const char *data, unsigned size) const +{ + if(size<4) + return 0; + const unsigned char *udata=reinterpret_cast(data); + return (udata[2]<<8)+udata[3]; +} + +unsigned Protocol::get_hash() const +{ + // TODO + return 123; +} + +void Protocol::assemble_header(char *buf, unsigned id, unsigned size) +{ + buf[0]=(id>>8)&0xFF; + buf[1]=id&0xFF; + buf[2]=(size>>8)&0xFF; + buf[3]=size&0xFF; +} + +template +char *Protocol::assemble_field(const T &v, char *d, char *e) +{ return Assembler::assemble(v, d, e); } + +template char *Protocol::assemble_field<>(const char &v, char *d, char *e); +template char *Protocol::assemble_field<>(const signed char &v, char *d, char *e); +template char *Protocol::assemble_field<>(const unsigned char &v, char *d, char *e); +template char *Protocol::assemble_field<>(const short &v, char *d, char *e); +template char *Protocol::assemble_field<>(const unsigned short &v, char *d, char *e); +template char *Protocol::assemble_field<>(const int &v, char *d, char *e); +template char *Protocol::assemble_field<>(const unsigned &v, char *d, char *e); +template char *Protocol::assemble_field<>(const long &v, char *d, char *e); +template char *Protocol::assemble_field<>(const unsigned long &v, char *d, char *e); +template char *Protocol::assemble_field<>(const float &v, char *d, char *e); +template char *Protocol::assemble_field<>(const double &v, char *d, char *e); +template char *Protocol::assemble_field<>(const string &v, char *d, char *e); +template char *Protocol::assemble_field<>(const vector &v, char *d, char *e); +template char *Protocol::assemble_field<>(const vector &v, char *d, char *e); +template char *Protocol::assemble_field<>(const vector &v, char *d, char *e); +template char *Protocol::assemble_field<>(const vector &v, char *d, char *e); +template char *Protocol::assemble_field<>(const vector &v, char *d, char *e); +template char *Protocol::assemble_field<>(const vector &v, char *d, char *e); +template char *Protocol::assemble_field<>(const vector &v, char *d, char *e); +template char *Protocol::assemble_field<>(const vector &v, char *d, char *e); +template char *Protocol::assemble_field<>(const vector &v, char *d, char *e); +template char *Protocol::assemble_field<>(const vector &v, char *d, char *e); +template char *Protocol::assemble_field<>(const vector &v, char *d, char *e); +template char *Protocol::assemble_field<>(const vector &v, char *d, char *e); + +template +const char *Protocol::disassemble_field(T &v, const char *d, const char *e) +{ return Assembler::disassemble(v, d, e); } + +template const char *Protocol::disassemble_field<>(char &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(signed char &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(unsigned char &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(short &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(unsigned short &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(int &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(unsigned &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(long &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(unsigned long &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(float &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(double &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(string &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(vector &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(vector &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(vector &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(vector &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(vector &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(vector &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(vector &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(vector &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(vector &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(vector &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(vector &v, const char *d, const char *e); +template const char *Protocol::disassemble_field<>(vector &v, const char *d, const char *e); + +unsigned Protocol::PacketDefBase::next_class_id=1; + +} // namespace Net +} // namespace Msp