From b9eecb0bba1457392212e072f604d350ed8e7def Mon Sep 17 00:00:00 2001 From: sbund <sbund@wiback.org> Date: Mon, 9 Oct 2006 12:56:31 +0000 Subject: [PATCH] --- Packets/.cvsignore | 10 + Packets/DataPacket.cc | 54 +++ Packets/DataPacket.cti | 44 ++ Packets/DataPacket.hh | 79 ++++ Packets/Doxyfile | 273 +++++++++++++ Packets/EthernetPacket.cc | 114 ++++++ Packets/EthernetPacket.cti | 49 +++ Packets/EthernetPacket.hh | 152 +++++++ Packets/EthernetPacket.test.cc | 95 +++++ Packets/FUTURE | 71 ++++ Packets/GenericPacket.ct | 57 +++ Packets/GenericPacket.cti | 98 +++++ Packets/GenericPacket.hh | 91 +++++ Packets/IpV4Packet.cc | 83 ++++ Packets/IpV4Packet.cti | 46 +++ Packets/IpV4Packet.hh | 119 ++++++ Packets/IpV4Packet.test.cc | 110 +++++ Packets/Packet.cc | 295 ++++++++++++++ Packets/Packet.cci | 195 +++++++++ Packets/Packet.ct | 152 +++++++ Packets/Packet.cti | 73 ++++ Packets/Packet.hh | 706 +++++++++++++++++++++++++++++++++ Packets/Packet.ih | 143 +++++++ Packets/Packet.mpp | 134 +++++++ Packets/Packet.test.cc | 247 ++++++++++++ Packets/PacketRegistry.cc | 43 ++ Packets/PacketRegistry.ct | 107 +++++ Packets/PacketRegistry.cti | 83 ++++ Packets/PacketRegistry.hh | 206 ++++++++++ Packets/PacketRegistry.ih | 108 +++++ Packets/PacketRegistry.test.cc | 171 ++++++++ Packets/ParseArray.cti | 206 ++++++++++ Packets/ParseArray.hh | 91 +++++ Packets/ParseArray.ih | 69 ++++ Packets/ParseArray.test.cc | 67 ++++ Packets/ParseInt.hh | 320 +++++++++++++++ Packets/ParseInt.ih | 219 ++++++++++ Packets/ParseInt.test.cc | 241 +++++++++++ Packets/ParseListS.ct | 121 ++++++ Packets/ParseListS.cti | 201 ++++++++++ Packets/ParseListS.hh | 165 ++++++++ Packets/ParseListS.ih | 69 ++++ Packets/ParseListS.test.cc | 174 ++++++++ Packets/ParseVec.ct | 81 ++++ Packets/ParseVec.cti | 224 +++++++++++ Packets/ParseVec.hh | 175 ++++++++ Packets/ParseVec.test.cc | 153 +++++++ Packets/ParserBase.cti | 96 +++++ Packets/ParserBase.hh | 296 ++++++++++++++ Packets/ParserBase.ih | 99 +++++ Packets/ParserBase.test.cc | 104 +++++ Packets/RTCPPacket.cc | 51 +++ Packets/RTCPPacket.cti | 44 ++ Packets/RTCPPacket.hh | 315 +++++++++++++++ Packets/RTCPPacket.test.cc | 339 ++++++++++++++++ Packets/RTPPacket.cc | 105 +++++ Packets/RTPPacket.cti | 56 +++ Packets/RTPPacket.hh | 224 +++++++++++ Packets/RTPPacket.test.cc | 246 ++++++++++++ Packets/SConscript | 9 + Packets/TODO | 15 + Packets/UDPPacket.cc | 66 +++ Packets/UDPPacket.cti | 46 +++ Packets/UDPPacket.hh | 96 +++++ Packets/UDPPacket.test.cc | 81 ++++ Packets/docstub.hh | 59 +++ Packets/imgconvert.mak | 179 +++++++++ Packets/main.test.cc | 43 ++ Packets/satcom.css | 310 +++++++++++++++ Packets/structure.dia | Bin 0 -> 3582 bytes Packets/typeidvalue.cci | 78 ++++ Packets/typeidvalue.cti | 63 +++ Packets/typeidvalue.hh | 103 +++++ 73 files changed, 9907 insertions(+) create mode 100644 Packets/.cvsignore create mode 100644 Packets/DataPacket.cc create mode 100644 Packets/DataPacket.cti create mode 100644 Packets/DataPacket.hh create mode 100644 Packets/Doxyfile create mode 100644 Packets/EthernetPacket.cc create mode 100644 Packets/EthernetPacket.cti create mode 100644 Packets/EthernetPacket.hh create mode 100644 Packets/EthernetPacket.test.cc create mode 100644 Packets/FUTURE create mode 100644 Packets/GenericPacket.ct create mode 100644 Packets/GenericPacket.cti create mode 100644 Packets/GenericPacket.hh create mode 100644 Packets/IpV4Packet.cc create mode 100644 Packets/IpV4Packet.cti create mode 100644 Packets/IpV4Packet.hh create mode 100644 Packets/IpV4Packet.test.cc create mode 100644 Packets/Packet.cc create mode 100644 Packets/Packet.cci create mode 100644 Packets/Packet.ct create mode 100644 Packets/Packet.cti create mode 100644 Packets/Packet.hh create mode 100644 Packets/Packet.ih create mode 100644 Packets/Packet.mpp create mode 100644 Packets/Packet.test.cc create mode 100644 Packets/PacketRegistry.cc create mode 100644 Packets/PacketRegistry.ct create mode 100644 Packets/PacketRegistry.cti create mode 100644 Packets/PacketRegistry.hh create mode 100644 Packets/PacketRegistry.ih create mode 100644 Packets/PacketRegistry.test.cc create mode 100644 Packets/ParseArray.cti create mode 100644 Packets/ParseArray.hh create mode 100644 Packets/ParseArray.ih create mode 100644 Packets/ParseArray.test.cc create mode 100644 Packets/ParseInt.hh create mode 100644 Packets/ParseInt.ih create mode 100644 Packets/ParseInt.test.cc create mode 100644 Packets/ParseListS.ct create mode 100644 Packets/ParseListS.cti create mode 100644 Packets/ParseListS.hh create mode 100644 Packets/ParseListS.ih create mode 100644 Packets/ParseListS.test.cc create mode 100644 Packets/ParseVec.ct create mode 100644 Packets/ParseVec.cti create mode 100644 Packets/ParseVec.hh create mode 100644 Packets/ParseVec.test.cc create mode 100644 Packets/ParserBase.cti create mode 100644 Packets/ParserBase.hh create mode 100644 Packets/ParserBase.ih create mode 100644 Packets/ParserBase.test.cc create mode 100644 Packets/RTCPPacket.cc create mode 100644 Packets/RTCPPacket.cti create mode 100644 Packets/RTCPPacket.hh create mode 100644 Packets/RTCPPacket.test.cc create mode 100644 Packets/RTPPacket.cc create mode 100644 Packets/RTPPacket.cti create mode 100644 Packets/RTPPacket.hh create mode 100644 Packets/RTPPacket.test.cc create mode 100644 Packets/SConscript create mode 100644 Packets/TODO create mode 100644 Packets/UDPPacket.cc create mode 100644 Packets/UDPPacket.cti create mode 100644 Packets/UDPPacket.hh create mode 100644 Packets/UDPPacket.test.cc create mode 100644 Packets/docstub.hh create mode 100644 Packets/imgconvert.mak create mode 100644 Packets/main.test.cc create mode 100644 Packets/satcom.css create mode 100644 Packets/structure.dia create mode 100644 Packets/typeidvalue.cci create mode 100644 Packets/typeidvalue.cti create mode 100644 Packets/typeidvalue.hh diff --git a/Packets/.cvsignore b/Packets/.cvsignore new file mode 100644 index 000000000..9064a2949 --- /dev/null +++ b/Packets/.cvsignore @@ -0,0 +1,10 @@ +SConfig +.doc.stamp +.test.stamp +.sconf_temp +.sconsign +config.log +doc +test +structure.png +.clean diff --git a/Packets/DataPacket.cc b/Packets/DataPacket.cc new file mode 100644 index 000000000..91e80cfb3 --- /dev/null +++ b/Packets/DataPacket.cc @@ -0,0 +1,54 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline non-template functions + +#include "DataPacket.hh" +//#include "DataPacket.ih" + +// Custom includes + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ void satcom::pkf::DataPacket::v_nextInterpreter() + const +{} + +prefix_ void satcom::pkf::DataPacket::v_finalize() +{} + +prefix_ void satcom::pkf::DataPacket::v_dump(std::ostream & os) + const +{ + os << "Payload:\n" + << " size : " << size() << "\n"; +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/DataPacket.cti b/Packets/DataPacket.cti new file mode 100644 index 000000000..f16bbb3c0 --- /dev/null +++ b/Packets/DataPacket.cti @@ -0,0 +1,44 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +//#include "DataPacket.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <class Arg> +prefix_ satcom::pkf::DataPacket::DataPacket(Arg const & arg) + : Packet(arg) +{} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/DataPacket.hh b/Packets/DataPacket.hh new file mode 100644 index 000000000..480f3cd85 --- /dev/null +++ b/Packets/DataPacket.hh @@ -0,0 +1,79 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_DataPacket_ +#define HH_DataPacket_ 1 + +// Custom includes +#include "Packet.hh" + +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + /** \brief Non-interpreted Packet + + A DataPacket is an uninterpreted blob of data. It is terminal + in the sense, that no further packet header may follow after + this packet. A DataPacket implements the abstract Packet + interface and nothing more. + */ + class DataPacket : public Packet + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t<DataPacket>::ptr ptr; + typedef iterator byte_iterator; + + /////////////////////////////////////////////////////////////////////////// + + static void init() {} + static bool check(iterator const & b, iterator const & e) { return true; } + + private: + template <class Arg> + DataPacket(Arg const & arg); + + virtual void v_nextInterpreter() const; + virtual void v_finalize(); + virtual void v_dump(std::ostream & os) const; + + friend class Packet; + }; + + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "DataPacket.cci" +//#include "DataPacket.ct" +#include "DataPacket.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/Doxyfile b/Packets/Doxyfile new file mode 100644 index 000000000..5701f22f0 --- /dev/null +++ b/Packets/Doxyfile @@ -0,0 +1,273 @@ +# Doxyfile 1.4.2 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = "SatCom PacketFramework: Packet library" +PROJECT_NUMBER = "Version 0.0.1" +OUTPUT_DIRECTORY = doc +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = NO +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = /share/izo/home/stefan/group/FhG/Seminar/example/ +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = YES +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = YES +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = YES +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = . +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.C \ + *.CC \ + *.C++ \ + *.II \ + *.I++ \ + *.H \ + *.HH \ + *.H++ \ + *.CS \ + *.PHP \ + *.PHP3 \ + *.M \ + *.MM \ + *.cci \ + *.ct \ + *.cti \ + *.ih +RECURSIVE = NO +EXCLUDE = doc +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = *.test.cc +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = satcom.css +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +SEARCH_INCLUDES = YES +INCLUDE_PATH = libs +INCLUDE_FILE_PATTERNS = +PREDEFINED = DOXYGEN +EXPAND_AS_DEFINED = DefineCommand +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = NO +HAVE_DOT = YES +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = NO +DIRECTORY_GRAPH = NO +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 800 +MAX_DOT_GRAPH_HEIGHT = 1200 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = YES +GENERATE_LEGEND = YES +DOT_CLEANUP = NO +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/Packets/EthernetPacket.cc b/Packets/EthernetPacket.cc new file mode 100644 index 000000000..f0e468e0a --- /dev/null +++ b/Packets/EthernetPacket.cc @@ -0,0 +1,114 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline non-template functions + +#include "EthernetPacket.hh" +//#include "EthernetPacket.ih" + +// Custom includes +#include <iomanip> +#include <boost/format.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + namespace pkf = satcom::pkf; + pkf::PacketRegistry<pkf::EtherTypes>::RegistrationProxy<pkf::EthVLanPacket> + registerEthVLanPacket(0x8100); +} + +prefix_ void satcom::pkf::EthernetPacket::v_nextInterpreter() + const +{ + // TODO: Add LLC/SNAP support -> only use the registry + // for type() values >=1536, otherwise expect an LLC header + registerInterpreter(type(),begin()+bytes(),end()); +} + +namespace { + + void dumpmac(std::ostream & os, satcom::pkf::EthernetPacket::Parse_MAC mac) + { + for (unsigned i = 0; i < 6; ++i) { + if (i > 0) + os << ':'; + os << std::hex << std::setw(2) << std::setfill('0') + << unsigned(mac[i]); + } + } + +} + +prefix_ void satcom::pkf::EthernetPacket::v_dump(std::ostream & os) + const +{ + if (type() <= 1500) + os << "Ethernet 802.3"; + else if (type() >= 0x600) + os << "Ethernet II (DIX)"; + else + os << "Ethernet 802.3 (bad ethertype >1500 and <1536)"; + os << ": \n" + << " destination : "; + dumpmac(os,destination()); + os << "\n" + << " source : "; + dumpmac(os,source()); + os << "\n" + << " ethertype : " << std::hex << std::setw(4) << std::setfill('0') + << unsigned(type()) << "\n" << std::dec; +} + +prefix_ void satcom::pkf::EthernetPacket::v_finalize() +{} + +prefix_ void satcom::pkf::EthVLanPacket::v_nextInterpreter() + const +{ + // TODO: Add LLC/SNAP support -> only use the registry + // for type() values >=1536, otherwise expect an LLC header + registerInterpreter(type(),begin()+bytes(),end()); +} + +prefix_ void satcom::pkf::EthVLanPacket::v_finalize() +{} + +prefix_ void satcom::pkf::EthVLanPacket::v_dump(std::ostream & os) + const +{ + os << "Ethernet 802.1q (VLAN):\n" + << " priority : " << priority() << "\n" + << " cfi : " << cfi() << "\n" + << " vlan-ID : " << vlanId() << "\n" + << " ethertype : " << boost::format("%04x") % type() << "\n"; +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/EthernetPacket.cti b/Packets/EthernetPacket.cti new file mode 100644 index 000000000..132e2de81 --- /dev/null +++ b/Packets/EthernetPacket.cti @@ -0,0 +1,49 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +//#include "EthernetPacket.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <class Arg> +prefix_ satcom::pkf::EthernetPacket::EthernetPacket(Arg const & arg) + : Packet(arg) +{} + +template <class Arg> +prefix_ satcom::pkf::EthVLanPacket::EthVLanPacket(Arg const & arg) + : Packet(arg) +{} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/EthernetPacket.hh b/Packets/EthernetPacket.hh new file mode 100644 index 000000000..ae4fdb280 --- /dev/null +++ b/Packets/EthernetPacket.hh @@ -0,0 +1,152 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_EthernetPacket_ +#define HH_EthernetPacket_ 1 + +// Custom includes +#include "Packet.hh" +#include "ParseInt.hh" +#include "ParseArray.hh" +#include "PacketRegistry.hh" + +//#include "EthernetPacket.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + template <class Iterator=nil, class IPacket=nil> + struct Parse_Ethernet : public ParserBase<Iterator,IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_Ethernet<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_Ethernet() {} + Parse_Ethernet(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + static unsigned bytes() { return 14; } + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_Array < 6, Parse_UInt8<>, Iterator > Parse_MAC; + typedef Parse_UInt16 < Iterator > Parse_Type; + + Parse_MAC destination() const { return Parse_MAC (this->i() ); } + Parse_MAC source() const { return Parse_MAC (this->i() + Parse_MAC::size() ); } + Parse_Type type() const { return Parse_Type (this->i() + 2*Parse_MAC::size() ); } + }; + + struct EtherTypes { + typedef boost::uint16_t key_t; + }; + + class EthernetPacket + : public Packet, + public Parse_Ethernet<Packet::iterator, EthernetPacket>, + public PacketRegistryMixin<EtherTypes,EthernetPacket> + { + using PacketRegistryMixin<EtherTypes,EthernetPacket>::registerInterpreter; + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t<EthernetPacket>::ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + + private: + template <class Arg> + EthernetPacket(Arg const & arg); + + virtual void v_nextInterpreter() const; + virtual void v_finalize(); + virtual void v_dump(std::ostream & os) const; + + friend class Packet; + }; + + template <class Iterator=nil, class IPacket=nil> + struct Parse_EthVLan : public ParserBase<Iterator,IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_Ethernet<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_EthVLan() {} + Parse_EthVLan(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + static unsigned bytes() { return 4; } + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UIntField < 0, 3, Iterator > Parse_Priority; + typedef Parse_Flag < 3, Iterator > Parse_CFI; + typedef Parse_UIntField < 4, 16, Iterator > Parse_VLanId; + typedef Parse_UInt16 < Iterator > Parse_Type; + + Parse_Priority priority() const { return Parse_Priority(this->i()); } + Parse_CFI cfi() const { return Parse_CFI(this->i()); } + Parse_VLanId vlanId() const { return Parse_VLanId(this->i()); } + Parse_Type type() const { return Parse_Type(this->i()+2); } + }; + + class EthVLanPacket + : public Packet, + public Parse_EthVLan<Packet::iterator, EthVLanPacket>, + public PacketRegistryMixin<EtherTypes, EthVLanPacket> + { + using PacketRegistryMixin<EtherTypes, EthVLanPacket>::registerInterpreter; + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t<EthVLanPacket>::ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + + private: + template <class Arg> + EthVLanPacket(Arg const & arg); + + virtual void v_nextInterpreter() const; + virtual void v_finalize(); + virtual void v_dump(std::ostream & os) const; + + friend class Packet; + }; + +}} + + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "EthernetPacket.cci" +//#include "EthernetPacket.ct" +#include "EthernetPacket.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/EthernetPacket.test.cc b/Packets/EthernetPacket.test.cc new file mode 100644 index 000000000..72e16d5cb --- /dev/null +++ b/Packets/EthernetPacket.test.cc @@ -0,0 +1,95 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Unit tests + +//#include "EthernetPacket.test.hh" +//#include "EthernetPacket.test.ih" + +// Custom includes +#include "EthernetPacket.hh" + +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::pkf; + +BOOST_AUTO_UNIT_TEST(ethernetPacket_parser) +{ + unsigned char data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // destination MAC + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, // source MAC + 0x10, 0x11 }; // EtherType + typedef unsigned char * iterator; + Parse_Ethernet<iterator> p(data); + + BOOST_CHECK_EQUAL( p.destination()[2], 0x03 ); + BOOST_CHECK_EQUAL( p.source()[3], 0x0A ); + BOOST_CHECK_EQUAL( p.type(), 0x1011 ); +} + +BOOST_AUTO_UNIT_TEST(ethernetPacket_packet) +{ + unsigned char data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // destination MAC + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, // source MAC + 0x10, 0x11 }; // EtherType + EthernetPacket::ptr p (Packet::create<EthernetPacket>(data, data+sizeof(data))); + + BOOST_CHECK_EQUAL( p->destination()[3], 0x04 ); + BOOST_CHECK_EQUAL( p->source()[0], 0x07 ); + BOOST_CHECK_EQUAL( p->type(), 0x1011 ); + + BOOST_CHECK_THROW( Packet::create<EthernetPacket>(data, data+sizeof(data)-1), + TruncatedPacketException ); +} + +BOOST_AUTO_UNIT_TEST(ethernetPacket_chain) +{ + unsigned char data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // destination MAC + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, // source MAC + 0x81, 0x00, // EtherType: VLan + 0x92, 0x34, // VLAN prio, cfi, id + 0xab, 0xcd, // EtherType + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4 }; // Payload + + EthernetPacket::ptr p (Packet::create<EthernetPacket>(data, data+sizeof(data))); + + BOOST_CHECK( p->next()->is<EthVLanPacket>() ); + EthVLanPacket::ptr v (p->next()->as<EthVLanPacket>()); + BOOST_CHECK_EQUAL( v->priority(), 4u ); + BOOST_CHECK( v->cfi() ); + BOOST_CHECK_EQUAL( v->vlanId(), 0x234u ); + BOOST_CHECK_EQUAL( v->type(), 0xabcd ); + BOOST_CHECK( v->next()->is<DataPacket>() ); + BOOST_CHECK_EQUAL( *v->next()->begin(), 0xf0 ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/FUTURE b/Packets/FUTURE new file mode 100644 index 000000000..36f879a4d --- /dev/null +++ b/Packets/FUTURE @@ -0,0 +1,71 @@ +Optimize the PacketRegistry using a vtable like approach. This vtable +approach should be implemented as a generic vtable library: + +Every class which shall be extensible needs to inheriv from the vtable +base class. This base class adds an integer member to the class. This +baseclass uses the CRTP pattern to initialize this integer to a type +specific value. + +To get theese values, we use a typeid registry. The typeid-registry is +a tempalte struct with the class as template arg and a single static +member fn. This fn has a member variable of type 'typeid sequence +value'. The constructor of this type will automatically allocate the +next free typeid integer. This can then efficiently be returned by the +static retrieval function: + + template <class T> + struct satcom::vtable::impl::TypeRegistry + { + static unsigned id() { + static satcom::vtable::impl::AutoTypeId typeid; + return typeid.id(); + } + }; + + struct satcom::vtable::impl::AutoTypeId + { + AutoTypeId() : id(nextAutoTypeId()) {} + unsigned id; + }; + + unsigned nextAutoTypeId() + { + static unsigned id(0); + return id++; + } + +This setup will assign id's uniquely. The Id's will be ordered by the +first TypeRegistry::id() call. To get the Type id of a type, just call +satcom::vtable::impl::TypeRegistry<SomeType>::id(). + +The above is bogus ... we don't register the extensible types, we +register the extensions which are arbitrary types. + +The typeid assigned to the extension type is used as an index into a +vtable. This vtable is in the simplest case, just an std::vector of +void*. To assign an extension to a specific type, we just add some +instance of the registered extension type to the vtable of the +to-be-extended type using the slot given by the typeid of the +extension type. To get the extension, we just look up the id of the +extension type and cast the value from the vtable vector to the +appropriate type. All this is O(1) and does not depend on the number +of extensions or on the number of extended classes. + +The extension vtables are created inside a static method of a +templated class (template arg is the extensible class). Additionally, +the extensible class must CRTP-wise inherit the vtable baseclass, +which will add a vtable pointer to the extensible class and initialize +it automatically to point to the correct vtable. + +To make this even more efficient, all vtables should be kept in a +list. This allows to keep all vtables to the same size. Then no range +checking must be done on accessing the vtable, since all vtables are +all as long as the largest extension id. This of course makes the +Operation of registering a new extension type O(n), but that should +not be a problem since extensions are registered once during program +startup. As a reward, the lookup performance is increased: it is only +a memory access to find the extension-type id(the address is fixed at +compile time) followed by an indexed access to the vtable, where the +vtable address is fetched using another memory access. This differs +from a compiler-generated vtable access only by a single memory +access. diff --git a/Packets/GenericPacket.ct b/Packets/GenericPacket.ct new file mode 100644 index 000000000..842fa56a8 --- /dev/null +++ b/Packets/GenericPacket.ct @@ -0,0 +1,57 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline template functions + +//#include "GenericPacket.ih" + +// Custom includes + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template <unsigned HEADER, unsigned TRAILER> +prefix_ void satcom::pkf::GenericPacket<HEADER,TRAILER>::v_nextInterpreter() + const +{ + this->registerInterpreter<DataPacket>(this->end_header(), this->begin_trailer()); +} + +template <unsigned HEADER, unsigned TRAILER> +prefix_ void satcom::pkf::GenericPacket<HEADER,TRAILER>::v_finalize() +{} + +template <unsigned HEADER, unsigned TRAILER> +prefix_ void satcom::pkf::GenericPacket<HEADER,TRAILER>::v_dump(std::ostream & os) + const +{ + // TODO: implement v_dump() +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/GenericPacket.cti b/Packets/GenericPacket.cti new file mode 100644 index 000000000..92c9e5968 --- /dev/null +++ b/Packets/GenericPacket.cti @@ -0,0 +1,98 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +//#include "GenericPacket.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <unsigned HEADER, unsigned TRAILER> +template <class Arg> +prefix_ satcom::pkf::GenericPacket<HEADER,TRAILER>::GenericPacket(Arg const & arg) +: Packet(arg) +{} + +template <unsigned HEADER, unsigned TRAILER> +prefix_ void satcom::pkf::GenericPacket<HEADER,TRAILER>::init() +{ + insert(begin(),HEADER,0); + insert(end(),TRAILER,0); +} + +template <unsigned HEADER, unsigned TRAILER> +prefix_ typename satcom::pkf::GenericPacket<HEADER,TRAILER>::iterator +satcom::pkf::GenericPacket<HEADER,TRAILER>::begin_header() + const +{ + return this->begin(); +} + +template <unsigned HEADER, unsigned TRAILER> +prefix_ typename satcom::pkf::GenericPacket<HEADER,TRAILER>::iterator +satcom::pkf::GenericPacket<HEADER,TRAILER>::end_header() + const +{ + return this->begin() + HEADER; +} + +template <unsigned HEADER, unsigned TRAILER> +prefix_ typename satcom::pkf::GenericPacket<HEADER,TRAILER>::size_type +satcom::pkf::GenericPacket<HEADER,TRAILER>::header_len() +{ + return HEADER; +} + +template <unsigned HEADER, unsigned TRAILER> +prefix_ typename satcom::pkf::GenericPacket<HEADER,TRAILER>::iterator +satcom::pkf::GenericPacket<HEADER,TRAILER>::begin_trailer() + const +{ + return this->end() - TRAILER; +} + +template <unsigned HEADER, unsigned TRAILER> +prefix_ typename satcom::pkf::GenericPacket<HEADER,TRAILER>::iterator +satcom::pkf::GenericPacket<HEADER,TRAILER>::end_trailer() + const +{ + return this->end(); +} + +template <unsigned HEADER, unsigned TRAILER> +prefix_ typename satcom::pkf::GenericPacket<HEADER,TRAILER>::size_type +satcom::pkf::GenericPacket<HEADER,TRAILER>::trailer_len() +{ + return TRAILER; +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/GenericPacket.hh b/Packets/GenericPacket.hh new file mode 100644 index 000000000..c8cd5d891 --- /dev/null +++ b/Packets/GenericPacket.hh @@ -0,0 +1,91 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_GenericPacket_ +#define HH_GenericPacket_ 1 + +// Custom includes +#include "Packet.hh" + +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + /** \brief General packet comprised of header, trailer and payload + + This class implements a generic packet with three sections: a + header, a trailer and a payload section. The header and + trailer are not interpreted in any way. The payload can be + manually chained to any packet interpreter. + */ + template <unsigned HEADER, unsigned TRAILER=0> + class GenericPacket : public Packet + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef typename Packet::ptr_t<GenericPacket>::ptr ptr; + typedef iterator byte_iterator; + + /////////////////////////////////////////////////////////////////////////// + + void init(); + + iterator begin_header() const; + iterator end_header() const; + static size_type header_len(); + + iterator begin_trailer() const; + iterator end_trailer() const; + static size_type trailer_len(); + + static bool check(iterator const & b, iterator const & e) + { return unsigned(e - b) >= HEADER + TRAILER; } + + protected: + + private: + template <class Arg> + GenericPacket(Arg const & arg); + + virtual void v_nextInterpreter() const; + virtual void v_finalize(); + virtual void v_dump(std::ostream & os) const; + + friend class Packet; + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "GenericPacket.cci" +#include "GenericPacket.ct" +#include "GenericPacket.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/IpV4Packet.cc b/Packets/IpV4Packet.cc new file mode 100644 index 000000000..095a2f9ec --- /dev/null +++ b/Packets/IpV4Packet.cc @@ -0,0 +1,83 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline non-template functions + +#include "IpV4Packet.hh" +//#include "IpV4Packet.ih" +#include "EthernetPacket.hh" + +// Custom includes +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + namespace pkf = satcom::pkf; + pkf::PacketRegistry<pkf::EtherTypes>::RegistrationProxy<pkf::IpV4Packet> + registerIpV4Packet(0x0800); +} + +prefix_ void satcom::pkf::IpV4Packet::v_nextInterpreter() + const +{ + registerInterpreter(protocol(),begin()+bytes(),end()); +} + +prefix_ void satcom::pkf::IpV4Packet::v_finalize() +{} + +prefix_ void satcom::pkf::IpV4Packet::v_dump(std::ostream & os) + const +{ + struct in_addr in; + in.s_addr = htonl(source()); + std::string src (inet_ntoa(in)); + in.s_addr = htonl(destination()); + std::string dst (inet_ntoa(in)); + os << "Internet protocol Version 4:\n" + << " version : " << version() << "\n" + << " IHL : " << ihl() << "\n" + << " TOS : " << unsigned(tos()) << "\n" + << " length : " << length() << "\n" + << " identifier : " << identifier() << "\n" + << " DF : " << df() << "\n" + << " MF : " << mf() << "\n" + << " fragment : " << frag() << "\n" + << " TTL : " << unsigned(ttl()) << "\n" + << " protocol : " << unsigned(protocol()) << "\n" + << " CRC : " << std::hex << crc() << std::dec << "\n" + << " source : " << src << "\n" + << " destination : " << dst << "\n"; +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/IpV4Packet.cti b/Packets/IpV4Packet.cti new file mode 100644 index 000000000..9a8c96f58 --- /dev/null +++ b/Packets/IpV4Packet.cti @@ -0,0 +1,46 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +//#include "IpV4Packet.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <class Arg> +prefix_ satcom::pkf::IpV4Packet::IpV4Packet(Arg const & arg) + : Packet(arg) +{} + + + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/IpV4Packet.hh b/Packets/IpV4Packet.hh new file mode 100644 index 000000000..0f9e296f6 --- /dev/null +++ b/Packets/IpV4Packet.hh @@ -0,0 +1,119 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_IpV4Packet_ +#define HH_IpV4Packet_ 1 + +// Custom includes +#include "Packet.hh" +#include "ParseInt.hh" +#include "ParseArray.hh" +#include "PacketRegistry.hh" + +//#include "IpV4Packet.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + template <class Iterator=nil, class IpV4Packet=nil> + struct Parse_IpV4 : public ParserBase<Iterator,IpV4Packet> + { + template <class I, class P=nil> + struct rebind { typedef Parse_IpV4<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_IpV4() {} + Parse_IpV4(Iterator const & i) : ParserBase<Iterator,IpV4Packet>(i) {} + + static unsigned bytes() { return 20; } + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UIntField < 0, 4, Iterator > Parse_Version; + typedef Parse_UIntField < 4, 8, Iterator > Parse_IHL; + typedef Parse_UInt8 < Iterator > Parse_8bit; + typedef Parse_UInt16 < Iterator > Parse_16bit; + typedef Parse_Flag < 0, Iterator > Parse_R; + typedef Parse_Flag < 1, Iterator > Parse_DF; + typedef Parse_Flag < 2, Iterator > Parse_MF; + typedef Parse_UIntField < 3, 16, Iterator > Parse_Frag; + typedef Parse_UInt32 < Iterator > Parse_32bit; + + Parse_Version version() const { return Parse_Version (this->i() ); } + Parse_IHL ihl() const { return Parse_IHL (this->i() ); } + Parse_8bit tos() const { return Parse_8bit (this->i() + 1 ); } + Parse_16bit length() const { return Parse_16bit (this->i() + 2 ); } + Parse_16bit identifier() const { return Parse_16bit (this->i() + 4 ); } + Parse_R reserved() const { return Parse_R (this->i() + 6 ); } + Parse_DF df() const { return Parse_DF (this->i() + 6 ); } + Parse_MF mf() const { return Parse_MF (this->i() + 6 ); } + Parse_Frag frag() const { return Parse_Frag (this->i() + 6 ); } + Parse_8bit ttl() const { return Parse_8bit (this->i() + 8 ); } + Parse_8bit protocol() const { return Parse_8bit (this->i() + 9 ); } + Parse_16bit crc() const { return Parse_16bit (this->i() + 10 ); } + Parse_32bit source() const { return Parse_32bit (this->i() + 12 ); } + Parse_32bit destination() const { return Parse_32bit (this->i() + 16 ); } + }; + + struct IpV4Types { + typedef boost::uint16_t key_t; + }; + + class IpV4Packet + : public Packet, + public Parse_IpV4<Packet::iterator,IpV4Packet>, + public PacketRegistryMixin<IpV4Types,IpV4Packet> + { + using PacketRegistryMixin<IpV4Types,IpV4Packet>::registerInterpreter; + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t<IpV4Packet>::ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + + private: + template <class Arg> + IpV4Packet(Arg const & arg); + + virtual void v_nextInterpreter() const; + virtual void v_finalize(); + virtual void v_dump(std::ostream & os) const; + + friend class Packet; + }; +}} + + +///////////////////////////////hh.e//////////////////////////////////////// +//#include IpV4Packet.cci" +//#include "IpV4Packet.ct" +#include "IpV4Packet.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/IpV4Packet.test.cc b/Packets/IpV4Packet.test.cc new file mode 100644 index 000000000..fd93c5ac6 --- /dev/null +++ b/Packets/IpV4Packet.test.cc @@ -0,0 +1,110 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Unit tests + +//#include "IpV4Packet.test.hh" +//#include "IpV4Packet.test.ih" + +// Custom includes +#include "IpV4Packet.hh" + +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::pkf; + +BOOST_AUTO_UNIT_TEST(ipV4Packet_parser) +{ + unsigned char data[] = { 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, + 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18 + }; + + typedef unsigned char * iterator; + Parse_IpV4<iterator> p(data); + + BOOST_CHECK_EQUAL( p.version(), 0x00u ); + BOOST_CHECK_EQUAL( p.ihl(), 0x01u ); + // the static_cast is to silence gcc-3.3 + BOOST_CHECK_EQUAL( static_cast<unsigned>(p.tos()), 0x02u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p.length()), 0x0304u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p.identifier()), 0x0506u ); + BOOST_CHECK_EQUAL( p.reserved(), 0 ); + BOOST_CHECK_EQUAL( p.df(), 0 ); + BOOST_CHECK_EQUAL( p.mf(), 0 ); + BOOST_CHECK_EQUAL( p.frag(), 0x0708u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p.ttl()), 0x09u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p.protocol()), 0x0Au ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p.crc()), 0x0B0Cu ); + BOOST_CHECK_EQUAL( p.source(), 0x11121314u ); + BOOST_CHECK_EQUAL( p.destination(), 0x15161718u ); + +} + + +BOOST_AUTO_UNIT_TEST(ipV4Packet_packet) +{ + + unsigned char data[] = { 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, + 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18 + }; + + IpV4Packet::ptr p (Packet::create<IpV4Packet>(data, data+sizeof(data))); + + BOOST_CHECK_EQUAL( p->version(), 0x00u ); + BOOST_CHECK_EQUAL( p->ihl(), 0x01u ); + // the static_cast is to silence gcc-3.3 + BOOST_CHECK_EQUAL( static_cast<unsigned>(p->tos()), 0x02u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p->length()), 0x0304u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p->identifier()), 0x0506u ); + BOOST_CHECK_EQUAL( p->reserved(), 0 ); + BOOST_CHECK_EQUAL( p->df(), 0 ); + BOOST_CHECK_EQUAL( p->mf(), 0 ); + BOOST_CHECK_EQUAL( p->frag(), 0x0708u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p->ttl()), 0x09u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p->protocol()), 0x0Au ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p->crc()), 0x0B0Cu ); + BOOST_CHECK_EQUAL( p->source(), 0x11121314u ); + BOOST_CHECK_EQUAL( p->destination(), 0x15161718u ); + + +} + + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/Packet.cc b/Packets/Packet.cc new file mode 100644 index 000000000..c94f0368a --- /dev/null +++ b/Packets/Packet.cc @@ -0,0 +1,295 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline non-template functions + +#include "Packet.hh" +#include "Packet.ih" + +// Custom includes +#include <boost/utility.hpp> // for next/prior + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// REFERENCE COUNTING +/////////////////////////////////////////////////////////////////////////// + +// We manage TWO reference counts: +// +// - The first reference counts lives wihin PacketImpl. It counts the +// number of references to the PacketImpl instance +// +// - The second reference count lives with the Packet interpreters. It +// counts the number of external references to the Packet facades. +// +// The PacketImpl refcount is always the sum of all it's Packet +// interpreter member refcounts. +// +// The Packet facades are referenced from two sides: +// +// - From the user. These references are counted in the Packet +// refcount. +// +// - From the list of interpreters. These references are *not* +// counted. +// +// The Packet facades have an impl_ member. This is set to non-0 only, +// as long as the Packet is a list member. The Packet may be deleted, +// when impl_ == 0 and refcount_ == 0. + +// class ListPacketDeleter + +// This is the custom deleter used for the pointers in the +// interpreters list. This deleter is only called, when the Packet is +// removed from the interpreters list. +prefix_ void satcom::pkf::impl::ListPacketDeleter::operator()(Packet * p) +{ + PacketImpl * impl = PacketImpl::impl(p); + if (impl->releaseInterpreter(p)) + delete impl; +} + +// struct PacketImpl + +prefix_ satcom::pkf::Packet::interpreter_list::iterator +satcom::pkf::impl::PacketImpl::appendInterpreter(Packet * p) +{ + BOOST_ASSERT( p->impl_ == 0 ); + + this->refcount_ += p->refcount_; + SATCOM_PKF_REFC_MSG("] PacketImpl::appendInterpreter (" << this << "): refcount_ = " << refcount_ << "\n"); + p->impl_ = this; + this->interpreters_.push_back( + boost::shared_ptr<Packet>(p, impl::ListPacketDeleter())); + + p->self_ = boost::prior(this->interpreters_.end()); + return p->self_; +} + +prefix_ satcom::pkf::Packet::interpreter_list::iterator +satcom::pkf::impl::PacketImpl::prependInterpreter(Packet * p) +{ + BOOST_ASSERT( p->impl_ == 0 ); + + this->refcount_ += p->refcount_; + SATCOM_PKF_REFC_MSG("] PacketImpl::prependInterpreter (" << this << "): refcount_ = " << refcount_ << "\n"); + p->impl_ = this; + this->interpreters_.push_front( + boost::shared_ptr<Packet>(p, pkf::impl::ListPacketDeleter())); + + p->self_ = this->interpreters_.begin(); + return p->self_; +} + +// Called, whenever a Packet is removed from the list by the +// ListPacketDeleter; +prefix_ bool satcom::pkf::impl::PacketImpl::releaseInterpreter(Packet * p) +{ + // We have to be extra careful here: This method might be called + // AFTER the PacketImpl instance has already been destructed while + // destructing the interpreters list !! + // If p->refcount_ is > 0 however we know, that this->refcount_ + // must also be > 0 ... + // So we have to make sure never to access this if p->refcount_==0 + BOOST_ASSERT( p->impl_ == this ); + bool rv (false); + if (p->refcount_ > 0) { + this->refcount_ -= p->refcount_; + rv = !this->refcount_; + SATCOM_PKF_REFC_MSG("] PacketImpl::releaseInterpreter (" << this << "): refcount_ = " << refcount_ << "\n"); + } + if (p->unlink()) + delete p; + return rv; +} + +namespace { + bool whenceCmp(unsigned a, unsigned b, bool end, satcom::pkf::Packet::Whence whence) + { + using satcom::pkf::Packet; + return ((whence == Packet::OUTSIDE && ! end) + || whence == Packet::BEFORE + || (whence == Packet::INSIDE && end)) ? a>=b : a>b; + } +} + +prefix_ void +satcom::pkf::impl::PacketImpl::updateIterators(Packet::size_type index, + Packet::difference_type n, + Packet::interpreter_list::iterator self, + Packet::Whence whence) +{ + Packet::interpreter_list::iterator i (interpreters_.begin()); + Packet::interpreter_list::iterator const e (interpreters_.end()); + Packet::Whence w (whence == Packet::AUTO ? Packet::INSIDE : whence); + for (;i!=e;++i) { + if (whenceCmp((*i)->end_,index,true,w)) + if (n<0 && (*i)->end_ < index-n) + (*i)->end_ = index; + else + (*i)->end_ += n; + if (whenceCmp((*i)->begin_,index,false,w)) + if (n<0 && (*i)->begin_ < index-n) + (*i)->begin_ = index; + else + (*i)->begin_ += n; + if (i == self && whence == Packet::AUTO) w = Packet::OUTSIDE; + BOOST_ASSERT( (*i)->end_ >= (*i)->begin_ ); + } +} + +prefix_ void satcom::pkf::impl::PacketImpl::packet_add_ref(Packet const * p) +{ + p->add_ref(); + if (p->impl_) + p->impl_->add_ref(); +} + +prefix_ void satcom::pkf::impl::PacketImpl::packet_release(Packet * p) +{ + bool del (p->release()); + if (p->impl_ && p->impl_->release()) + // In this case, del is certainly false here. p might + // however get deleted now. + delete p->impl_; + if (del) + delete p; +} + +/////////////////////////////////////////////////////////////////////////// +// class Packet + +prefix_ satcom::pkf::Packet::ptr satcom::pkf::Packet::next() + const +{ + interpreter_list::iterator n = boost::next(this->self_); + if (n == this->impl_->interpreters_.end()) { + if (this->parsed_) + return ptr(0); + // FIXME: v_nextInterpreter return bool? new Interpreter to be + // added ? hmm ... this however is quite suboptimal ... + this->v_nextInterpreter(); + this->parsed_ = true; + n = boost::next(this->self_); + if (n == this->impl_->interpreters_.end()) + return ptr(0); + } + // Re-converting the Packet to a smart pointer is correct here, + // since the shared_ptr really uses the intrusive refcount which + // makes this operation safe ... + return ptr(n->get(),true); +} + +prefix_ satcom::pkf::Packet::ptr satcom::pkf::Packet::last() + const +{ + Packet * p = this->impl_->interpreters_.back().get(); + while (! p->parsed_) { + Packet * pp = p->next().get(); + if (pp) p = pp; + } + // Re-converting the to a smart pointer is correct here, since the + // shared_ptr really uses the intrusive refcount which makes this + // operation safe ... + return ptr(p,true); +} + +prefix_ void satcom::pkf::Packet::i_registerInterpreter(Packet * p) + const +{ + BOOST_ASSERT( !p->impl_ ); + this->impl_->truncateInterpretersAfter(this); + this->impl_->appendInterpreter(p); + this->parsed_ = true; +} + +prefix_ void satcom::pkf::Packet::i_replaceInterpreter(Packet * p) +{ + BOOST_ASSERT( !p->impl_ ); + // We need to increment the refcount of impl_ beforehand, + // otherwise it might get deleted by the truncateInterpreters call + boost::intrusive_ptr<impl::PacketImpl> impl (this->impl_,true); + impl->truncateInterpreters(this); + impl->appendInterpreter(p); +} + +prefix_ void satcom::pkf::Packet::i_setInterpreter(impl::PacketImpl * i) +{ + // Using prependInterpreter makes this usable for both, the + // create-from-data and wrap-packet constructors + i->prependInterpreter(this); +} + +prefix_ void satcom::pkf::Packet::insert(iterator pos, byte v, Whence whence) +{ + size_type index(pos-impl_->data_.begin()); + BOOST_ASSERT( index >= begin_ && index <= end_); + impl_->data_.insert(pos,v); + impl_->updateIterators(index,1,self_,whence); +} + +prefix_ void satcom::pkf::Packet::insert(iterator pos, size_type n, byte v, Whence whence) +{ + size_type index(pos-impl_->data_.begin()); + BOOST_ASSERT( index >= begin_ && index <= end_ ); + impl_->data_.insert(pos,n,v); + impl_->updateIterators(index,n,self_,whence); +} + +prefix_ void satcom::pkf::Packet::erase(iterator pos) +{ + size_type index(pos-impl_->data_.begin()); + BOOST_ASSERT( index >= begin_ && index < end_ ); + impl_->data_.erase(pos); + impl_->updateIterators(index,-1,self_,INSIDE); +} + +prefix_ void satcom::pkf::Packet::erase(iterator first, iterator last) +{ + size_type index(first-impl_->data_.begin()); + size_type sz(last-first); + BOOST_ASSERT( index >= begin_ && index < end_ && sz <= end_-index ); + // FIXME: Here we should assert, that no bytes belonging to the + // next iterator are deleted ... + impl_->data_.erase(first,last); + impl_->updateIterators(index,-sz,self_,INSIDE); +} + +prefix_ void satcom::pkf::Packet::dump(std::ostream & os) + const +{ + v_dump(os); + ptr p (next()); + if (p) + p->dump(os); +} + +//////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/Packet.cci b/Packets/Packet.cci new file mode 100644 index 000000000..c3262eace --- /dev/null +++ b/Packets/Packet.cci @@ -0,0 +1,195 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline non-template functions + +#include "Packet.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +prefix_ satcom::pkf::impl::PacketImpl::PacketImpl() + : data_(), interpreters_(), refcount_(1) +{ + SATCOM_PKF_REFC_MSG("] PacketImpl::PacketImpl (" << this << "): refcount_ = 1\n"); +} + +prefix_ satcom::pkf::impl::PacketImpl::PacketImpl(unsigned size, Packet::byte initValue) + : data_(size,initValue), interpreters_(), refcount_(1) +{ + SATCOM_PKF_REFC_MSG("] PacketImpl::PacketImpl (" << this << "): refcount_ = 1\n"); +} + +prefix_ satcom::pkf::impl::PacketImpl::~PacketImpl() +{ + BOOST_ASSERT( !refcount_ ); + SATCOM_PKF_REFC_MSG("] PacketImpl::~PacketImpl (" << this << ")\n"); +} + +// PacketImpl::add_ref and PacketImpl::release are only called from +// intrusive_ptr_add_ref and intrusive_ptr_release +prefix_ void satcom::pkf::impl::PacketImpl::add_ref() +{ + ++refcount_; + SATCOM_PKF_REFC_MSG("] PacketImpl::add_ref (" << this << "): refcount_ = " << refcount_ << "\n"); +} + +prefix_ bool satcom::pkf::impl::PacketImpl::release() +{ + BOOST_ASSERT( refcount_ > 0 ); + --refcount_; + SATCOM_PKF_REFC_MSG("] PacketImpl::release (" << this << "): refcount_ = " << refcount_ << "\n"); + return ! refcount_; +} + +prefix_ void satcom::pkf::impl::PacketImpl::truncateInterpreters(Packet const * p) +{ + BOOST_ASSERT( p->impl_ == this ); + this->interpreters_.erase(p->self_,this->interpreters_.end()); +} + +prefix_ void satcom::pkf::impl::PacketImpl::truncateInterpretersAfter(Packet const * p) +{ + BOOST_ASSERT( p->impl_ == this ); + this->interpreters_.erase(boost::next(p->self_),this->interpreters_.end()); +} + +prefix_ satcom::pkf::impl::PacketImpl* satcom::pkf::impl::PacketImpl::impl(Packet const * p) +{ + return p->impl_; +} + +/* +prefix_ std::ostream & satcom::pkf::operator<<(std::ostream & os, Packet const & packet) +{ + packet.dump(os); + return os; +} +*/ + +// These methods are called by the user codes Packet::ptr's. They +// refcount both the Packet and the owning PacketImpl. +prefix_ void satcom::pkf::intrusive_ptr_add_ref(Packet const * p) +{ + impl::PacketImpl::packet_add_ref(p); +} + +prefix_ void satcom::pkf::intrusive_ptr_release(Packet * p) +{ + impl::PacketImpl::packet_release(p); +} + +prefix_ void satcom::pkf::impl::intrusive_ptr_add_ref(PacketImpl * p) +{ + p->add_ref(); +} + +prefix_ void satcom::pkf::impl::intrusive_ptr_release(PacketImpl * p) +{ + if (p->release()) + delete p; +} + +/////////////////////////////////////////////////////////////////////////// +// class Packet + +prefix_ satcom::pkf::Packet::iterator satcom::pkf::Packet::begin() + const +{ + return impl_->data_.begin()+begin_; +} + +prefix_ satcom::pkf::Packet::iterator satcom::pkf::Packet::end() + const +{ + return impl_->data_.begin()+end_; +} + +prefix_ size_t satcom::pkf::Packet::size() + const +{ + return end_-begin_; +} + +prefix_ satcom::pkf::Packet::ptr satcom::pkf::Packet::prev() + const +{ + if (this->self_ == this->impl_->interpreters_.begin()) + return ptr(0); + // Re-converting the to a smart pointer is correct here, since the + // shared_ptr really uses the intrusive refcount which makes this + // operation safe ... + return ptr(boost::prior(this->self_)->get(),true); +} + +prefix_ satcom::pkf::Packet::ptr satcom::pkf::Packet::head() + const +{ + // Re-converting the to a smart pointer is correct here, since the + // shared_ptr really uses the intrusive refcount which makes this + // operation safe ... + return ptr(this->impl_->interpreters_.front().get(),true); +} + +prefix_ satcom::pkf::Packet::~Packet() +{ + // FIXME: This is bad ... we cannot check this since this + // assertion fails at the moment if the Packet constructor throws + // ... hrmpf ... we really need to initialize refcount_ to 0 and + // remove the 'false' argument to the ptr constructor in ::create + // BOOST_ASSERT( !this->refcount_ && !this->impl_ ); + SATCOM_PKF_REFC_MSG("] Packet::~Packet (" << this << ")\n"); +} + +prefix_ void satcom::pkf::Packet::add_ref() + const +{ + ++this->refcount_; + SATCOM_PKF_REFC_MSG("] Packet::add_ref (" << this << "): refcount_ = " << this->refcount_ << "\n"); +} + +prefix_ bool satcom::pkf::Packet::release() +{ + BOOST_ASSERT( this->refcount_ > 0 ); + --this->refcount_; + SATCOM_PKF_REFC_MSG("] Packet::release (" << this << "): refcount_ = " << this->refcount_ << "\n"); + return !this->refcount_ && !this->impl_; +} + +prefix_ bool satcom::pkf::Packet::unlink() +{ + SATCOM_PKF_REFC_MSG("] Packet::unlink (" << this << "): refcount_ = " << this->refcount_ << "\n"); + this->impl_ = 0; + this->begin_ = this->end_; + return !this->refcount_; +} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/Packet.ct b/Packets/Packet.ct new file mode 100644 index 000000000..edc6518f9 --- /dev/null +++ b/Packets/Packet.ct @@ -0,0 +1,152 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline template functions + +#include "Packet.ih" + +// Custom includes +#include <algorithm> +#include "ParserBase.hh" + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template <class OtherPacket, class InputIterator> +prefix_ typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr +satcom::pkf::Packet::create(InputIterator b, InputIterator e) +{ + boost::intrusive_ptr<impl::PacketImpl> impl (new impl::PacketImpl(b,e),false); + if (!check<OtherPacket>(impl->data_.begin(),impl->data_.end())) + throw TruncatedPacketException(); + typename ptr_t<OtherPacket>::ptr p (new OtherPacket(PacketOp_set(impl.get())), false); + return p; +} + +template <class OtherPacket> +prefix_ typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr satcom::pkf::Packet::create() +{ + boost::intrusive_ptr<impl::PacketImpl> impl ( + new impl::PacketImpl(min_bytes<OtherPacket>(),0)); + typename ptr_t<OtherPacket>::ptr p (new OtherPacket(PacketOp_set(impl.get())), false); + p->init(); + return p; +} + +template <class OuterPacket> +prefix_ typename satcom::pkf::Packet::ptr_t<OuterPacket>::ptr +satcom::pkf::Packet::create(Packet::ptr payload) +{ + // TODO: should I instead of using head() throw away all + // interpreters before payload? ... probably yes ... + payload->insert(payload->head()->begin(),min_bytes<OuterPacket>(),0); + typename ptr_t<OuterPacket>::ptr p (new OuterPacket(PacketOp_set(payload->impl_))); + p->init(); + return p; +} + +template <class OtherPacket> +prefix_ typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr satcom::pkf::Packet::reinterpret() +{ + // THIS INVALIDATES this !!!!!!! + if (!check<OtherPacket>(begin(),end())) + throw TruncatedPacketException(); + typename ptr_t<OtherPacket>::ptr p (new OtherPacket(PacketOp_replace(this)),false); + return p; +} + +template <class OtherPacket> +prefix_ typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr +satcom::pkf::Packet::registerInterpreter(raw_container::iterator begin, + raw_container::iterator end) + const +{ + if (!check<OtherPacket>(begin,end)) + throw TruncatedPacketException(); + typename ptr_t<OtherPacket>::ptr p ( + new OtherPacket(PacketOp_register(begin-impl_->data_.begin(), + end-impl_->data_.begin(), + this)), + false); + return p; +} + +#define BOOST_PP_ITERATION_PARAMS_1 (4, (1, 9, "Packets/Packet.mpp", 4)) +#include BOOST_PP_ITERATE() + +template <class OtherPacket> +prefix_ typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr satcom::pkf::Packet::find_next() + const +{ + ptr p (next()); + while (p && !p->is<OtherPacket>()) + p = p->next(); + return p->as<OtherPacket>(); +} + +template <class OtherPacket> +prefix_ typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr satcom::pkf::Packet::find_prev() + const +{ + ptr p (prev()); + while (p && !p->is<OtherPacket>()) + p = p->prev(); + return p->as<OtherPacket>(); +} + +template <class OtherPacket> +prefix_ typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr satcom::pkf::Packet::get_next() + const +{ + typename ptr_t<OtherPacket>::ptr p (find_next<OtherPacket>()); + BOOST_ASSERT(p); + return p; +} + +template <class OtherPacket> +prefix_ typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr satcom::pkf::Packet::get_prev() + const +{ + typename ptr_t<OtherPacket>::ptr p (find_prev<OtherPacket>()); + BOOST_ASSERT(p); + return p; +} + +template <class InputIterator> +prefix_ void satcom::pkf::Packet::insert(iterator pos, InputIterator f, InputIterator l, + Whence whence) +{ + size_type index(pos-impl_->data_.begin()); + BOOST_ASSERT( index >= begin_ && index <= end_ ); + size_type sz (impl_->data_.size()); + impl_->data_.insert(pos,f,l); + impl_->updateIterators(index,impl_->data_.size()-sz,self_,whence); +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/Packet.cti b/Packets/Packet.cti new file mode 100644 index 000000000..364bd1702 --- /dev/null +++ b/Packets/Packet.cti @@ -0,0 +1,73 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +#include "Packet.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <typename OtherPacket> +prefix_ bool satcom::pkf::Packet::is() + const +{ + return dynamic_cast<OtherPacket const *>(this); +} + +template <typename OtherPacket> +prefix_ typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr satcom::pkf::Packet::as() +{ + return typename ptr_t<OtherPacket>::ptr(dynamic_cast<OtherPacket*>(this),true); +} + +// This constructor appends a new interreter to the interpreter chain +// of an existing Packet +template <class Operation> +prefix_ satcom::pkf::Packet::Packet(Operation const & arg) + : impl_(0), begin_(arg.begin()), end_(arg.end()), self_(), + parsed_(false), refcount_(1) +{ + SATCOM_PKF_REFC_MSG("] Packet::Packet (" << this << "): refcount_ = 1\n"); + // FIXME: This is not exception safe, if an exception is thrown in + // the derived class constuctor, the effects of this call must be + // undone which is not possible in a simple way. + arg(this); +} + +template <class InputIterator> +prefix_ satcom::pkf::impl::PacketImpl::PacketImpl(InputIterator begin, InputIterator end) + : data_(begin, end), interpreters_(), refcount_(1) +{ + SATCOM_PKF_REFC_MSG("] PacketImpl::PacketImpl (" << this << "): refcount_ = 1\n") +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/Packet.hh b/Packets/Packet.hh new file mode 100644 index 000000000..ef25f14b4 --- /dev/null +++ b/Packets/Packet.hh @@ -0,0 +1,706 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// TODO: Implement assign() method akin to reinterpret(). However, +// instead of using the data already present, assign() will replace +// the date of the current packet with the given Packet. + +// TODO: Implement wrapping-constructor. Somehow we want to have a +// constructor, which allows creating a chain of packet interpreters +// with as little overhead as possible. + +// TODO: Document the additional concrete Packet facade requirements +// explicitly and not only within the Parser requirements (check(), +// bytes() and min_bytes() members ...) + +// TODO: Implement special container replacing vector which manages +// some headroom to allow efficient insertion of elements at the +// beginning. This really is just another type of deque +// implementation. + + +/** \mainpage The SatCom Packet Framework + + \section arch Overall Architecture + + The general Architecture of the Packet Framework (pkf for short) + is seperated into two components: The basic packet handling and + the parser framework. + + The basic packet handling implements a packet interpreter + chain. Every packet is represented as a chain of interpreters + where each interpreter is a facade looking into the same + packet. Each interpreter will interpret a specific header of a + packet. For example, an ethernet frame might have an interpreter + chain consisting of EthernetPacket, IPPacket, UDPPacket and + DataPacket. Each of these interpreters will interpret a section of + the raw data bytes. The interpreter ranges overlap since every + packet also includes it's payload. + + The parser framework is used to interpret the raw bytes of a + specific packet and parse the values present in that packet. For + example, Parse_Ethernet will parse the ethernet source MAC, + destination MAC and ethertype given any random access iterator to + the first byte of the ethernet frame. Parsers are extremely light + classes. They are temporary classes passed around by value. In + most cases, they are just comprised of a single pointer adorned + with type information. + + \section handling Packet Handling + + The packet handling is implemented within + satcom::pkf::Packet. This class is the baseclass to all packet + interpreter facades. To implement a new packet type, publically + derive from satcom::pkf::Packet and implement the virtual + interface (see the class documentation for details). + + \section framework Parser Framework + + The parser framework provides an abstract framwork to parse packet + oriented data. A Parser is a template class taking an arbitrary + iterator as input and allowing random access to data elements of + the interpreted type, like source and destination MAC of an + ethernet frame. The parser framework is to be used hierarchically + and recursively, the parser methods should return further parsers + which can return further parsers and so on. + + The parser framework contains some basic parsers to be used to + build up more complex parsers: + + - ParseInt.hh: Lots of parsers for integer numbers like + satcom::pkf::Parse_UInt8, for integer bitfields like + satcom::pkf::Parse_UIntField and satcom::pkf::Parse_Flag to + parse boolean flags. + + - ParseArray.hh: The satcom::pkf::Parse_Array parser to parse + arbitrary fixed-size arrays of fixed-size elements (that is + sub-parsers). + + - ParseVec.hh: The satcom::pkf::Parse_Vector parser to parse + dynamically sized arrays of fixed-size elements (that is + sub-parsers). + + See satcom::pkf::ParserBase for further information. + + \section stuff Other Utilities + + The pkf also comprises some additional utilities to support the + development of packet classes. + + The satcom::pkf::PacketRegistry implements a registry of packets + keyed by an arbitrary type. The registry is used to find a packet + type given some kind of id (like the ethertype value from the + ethernet header). Together with it's support classes (especially + satcom::pkf::PacketRegistryMixin) this class greatly simplifies + implementing the needed table lookups. + */ + +/** \file + \brief Main packet interface + */ + +#ifndef HH_Packet_ +#define HH_Packet_ 1 + +// Custom includes +#include <boost/utility.hpp> // for boost::noncopyable +#include <boost/cstdint.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/intrusive_ptr.hpp> +#include <list> +#include <vector> +#include <iostream> + +#include "Packet.mpp" +// ////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + namespace impl { template <class OtherPacket> class PkReg_EntryImpl; } + namespace impl { class PacketImpl; } + + /** \brief Basic interface to all packet facades + + \section packet_overview Overview + + This class is the base class of all Packets. It implements the + generic Packet interface and provides the packet management + framework. satcom::pkf::Packet manages the necessary memory + resources and controlls the chain of packet interpreters. + + The Packet user always interfaces with the pkf via a Packet + derived class. This is the only external entity ever held by a + library user. The interface is implemented using a reference + counted smart pointer, so resource management is quasi + automatic. + + \image html "../../structure.png" Overview + + Internally, every Packet references a PacketImpl instance which + manages the raw packet data and the interpreter list. This raw + data is interpreted by the concrete Packet derived class + according to the definition of that derived class's packet + type (i.e. EthernetPacket or UDPPacket). + + Packet provides several interfaces: + + - Creation of Packet instances: create() + + - Access to the chain of interpreters: next(), prev(), head(), + last(), find_next(), find_prev(), get_next(), get_prev(), + is(), as() and reinterpret() + + - Access to the raw packet data: begin(), end(), size(), + insert() and erase() + + - An interface to the derived class: v_nextInterpreter(), + v_finalize(), registerInterpreter() + + + \section packet_der Implementing new Packet facades + + To implement a new Packet facade, publically derive from + Packet. You need to implement the following minimal interface: + + - You need to provide a new #ptr typedef + + - You have to implement v_nextInterpreter() and v_finalize() + + - The constructor should be private + + - You must make Packet a \c friend of the new Packet facade + + - You must implement a static check() method which validates + a byte region as your new Packet + + \code + class ExamplePacket + : public satcom::pkf::Packet + { + public: + typedef ptr_t<ExamplePacket>::ptr ptr; + + static bool check(Packet::iterator begin, Packet::iterator end) + { + // Validate, that the region [begin,end) can be + // interpreted as an ExamplePacket without risking + // memory access violations. + } + + private: + template <class Arg> + ExamplePacket(Arg arg [, other args ... ]) + : satcom::pkf::Packet(arg) + {} + + virtual void v_nextInterpreter() const + { + // NextPacketType and header_length of course + // depend on the packet type + registerInterpreter<NextPacketType>(begin()+header_length, end()); + } + + virtual void v_finalize() + { + // calculate checksum etc + } + + friend class satcom::pkf::Packet; + }; + \endcode + + Please do not implement the methods inline to not clutter up + the header file. This is done here in the example to simplify + it. If a class is to be registered in some + satcom:pkf::PacketRegistry, it must not take any additional + constructor parameters. + + After having implemented the bare framework, the most comman + way to implement access to the packets specific data is to use + the parser framework by additionally inheriting a + corresponding parser. This also automatically implements the + check() method, which is provided by the Parser. + + In the following example we only show the differences from the + previous example: + + \code + class ExamplePacket + : public satcom::pkf::Packet, + public Parse_Example<satcom::pkf::Packet::iterator, + ExamplePacket> + { + + // check does not need to be implemented here, it is + // inherited from the parser + + private: + template <class InputIterator> + ExamplePacket(InputIterator begin, InputIterator end) + : satcom::pkf::Packet(begin,end) + {} + }; + \endcode + + See the satcom::pkf::ParserBase Documentation for how to + implement Parse_Example. + + The implementation of v_nextInterpreter most of the time + relies on some packet registry. This is simplified using the + satcom::pkf::PacketRegistryMixin class as follows. Again, we + only show the differences from the preceding Example: + + \code + struct ExampleRegistry { + type boost::uint16_t key_t; + }; + + class ExamplePacket + : public satcom::pkf::Packet, + public Parse_Example<satcom::pkf::Packet::iterator, + ExamplePacket>, + public satcom::pkf::PacketRegistryMixin<ExampleRegistry, + ExamplePacket> + { + using satcom::pkf::Packet::registerInterpreter; + using satcom::pkf::PacketRegsitryMixin<ExampleRegistry,ExamplePacket>::registerInterpreter; + private: + virtual void v_nextInterpreter() const + { + // nextType() is defined in Parse_Example and + // returns the key in the ExampleRegistry of the + // next Packet. + registerInterpreter(nextType(),begin()+header_length, end()); + } + }; + \endcode + + For further details on the packet registry, see + satcom::pkf::PacketRegistry. + + \section packet_impl Implementation details + + The Packet interface is implemented to minimize overhead as + far as possible without getting to complex. One area for + improvement ist the container class used to hold the raw + data. This currently is an \a std::vector. This could be + imporved by either allocating some headroom/tailroom in the + vector and using this when inserting data at the beginning or + end. Alternatively, a new container class (like the + satcom::lib::deque_list) could be used to support zero-copy + semantics. + + At the moment, we leave the implementation at + std::vector. This container is very simple and especially it + can directly be sent out using the operating system since a \a + vector stores data at contiguous memory locations. An \a + std::deque could be used with \a writev(), however since we + have no access to the implementation details of the \a deque, + we cannot construct the \a writev() data structures. + + The interpreter list managed by Packet is lazy, meaning packet + interpreter facades are added only when requestd by next(), + last() or find_next(). v_nextInterpreter() is called if + necessary by these methods to complete the interpreter chain. + + To implement the automatic memory management, every Packet + facade is reference counted. Additionally, the number of + (indirect) references to PacketImpl is counted. This allows to + manage the PacketImpl instance automatically. To make this + work, it is necessary to ensure throughout the Packet code, + that the reference count of a Packet is not accidentally + decremented to zero. Also, the internal pointers from the + interpreter list to the Packet facades must not be + counted. They are therefore implemented differently ( + boost::shared_ptr vs. boost::intrusive_ptr). The choice of + boost::intrusive_ptr for the externaly visible smart pointer + for all Packet facades is taken to reduce the overhead (an + intrusive_ptr is only the size of an ordinary pointer, a + smart_ptr has the size of two pointers). + + \nosubgrouping + */ + class Packet : boost::noncopyable + { + public: + ///\name Types + ///@{ + typedef boost::uint8_t byte; //!< single byte datatype + ///@} + + private: + ///\name Implementation + ///@{ + // These types are implementation details. They are however + // needed to provide the correct typedefs for the user + // interface. Hiding these classes would incur a huge + // additional indirection overhead. + + typedef std::vector<byte> raw_container; + typedef boost::shared_ptr<Packet> interpreter_list_ptr; + typedef std::list<satcom::pkf::Packet::interpreter_list_ptr> interpreter_list; + typedef unsigned refcount_t; + + ///@} + + public: + + /////////////////////////////////////////////////////////////////////////// + ///\name Types + ///@{ + + /** \brief smart pointer template for all Packet classes + + This struct is just a template typedef. It defines the + smart pointer used for all Packet classes. + */ + template <class T> struct ptr_t { typedef boost::intrusive_ptr<T> ptr; }; + + /** \brief smart pointer to the Packet facades + + Every derived class \e must redeclare this member for it's + derived type: + \code + typedef ptr_t<DerivedClass>::ptr ptr + \endcode + */ + typedef ptr_t<Packet>::ptr ptr; + typedef raw_container::iterator iterator; //!< raw data iterator + typedef raw_container::size_type size_type; + typedef raw_container::difference_type difference_type; + + ///@} + + // //////////////////////////////////////////////////////////////////////// + + ///\name Creating packets + ///@{ + + /** \brief create new Packet + + This method is used to create a new Packet. All Packet + instances are created via this method, they are \e never + created directly from the Packet derived class. + + \param OtherPacket Type of Packet to create, a Packet + derived class + \param b begin iterator of byte range to create the Packet + from + \param e corresponding end iterator + \return smart pointer to new packet + \throws TruncatedPacketException The data cannot be parsed + securely (the data might be trunctated or just + plain invalid) + */ + template <class OtherPacket, class InputIterator> + static typename ptr_t<OtherPacket>::ptr create(InputIterator b, InputIterator e); + + template <class OtherPacket> + static typename ptr_t<OtherPacket>::ptr create(); + + template <class OuterPacket> + static typename ptr_t<OuterPacket>::ptr create(Packet::ptr payload); + + ///@} + + ///\name Interpreter chain + ///@{ + + /** \brief get next packet from the interpreter chain + \return smart pointer to next packet or 0 if last packet */ + ptr next() const; + /** \brief get previous packet from the interpreter chain + \return smart pointer to previous packet or 0 if last packet */ + ptr prev() const; + /** \brief first packet of the interpreter chain + \return smart pointer to first packet */ + ptr head() const; + /** \brief get last packet of the interpreter chain + \return smart pointer to last packet */ + ptr last() const; + + /** \brief first packet of given type after the current packet + \return smart pointer to first following packet of type \a + OtherPacket or 0, if no such packet exists */ + template <class OtherPacket> typename ptr_t<OtherPacket>::ptr find_next() const; + /** \brief first packet of given type before the current packet + \return smart pointer to first preceding packet of type \a + OtherPacket or 0, if no such packet exists */ + template <class OtherPacket> typename ptr_t<OtherPacket>::ptr find_prev() const; + + /** \brief first packet of given type after the current packet + \return smart pointer to first following packet of type \a + OtherPacket. \e Assert's, that a packet of this type exists */ + template <class OtherPacket> typename ptr_t<OtherPacket>::ptr get_next() const; + /** \brief first packet of given type before the current packet + \return smart pointer to first preceding packet of type \a + OtherPacket. \e Assert's, that a packet of this type exists */ + template <class OtherPacket> typename ptr_t<OtherPacket>::ptr get_prev() const; + + /** \brief check, wether the packet is of the given type + \return true, if packt is of type \a OtherPacket, false + otherwise */ + template <class OtherPacket> bool is() const; + /** \brief cast packet pointer to the given type + \return a properly cast smart pointer if packet is of type + \a OtherPacket. Otherwise return 0 */ + template <class OtherPacket> typename ptr_t<OtherPacket>::ptr as(); + + /** \brief replace current packet interpreter + + This method will \e replace the current packet facade in + the interpreter list with a new interpreter given by \a + OtherPacket. + + \attention This invalidates the packet instance \e + this</b>. You must ensure, not to use the Packet instance + any further after this call + + \return smart pointer to a \e new packet facade + \throws TruncatedPacketException there is not enough data + to savely interpret the packet as the given type. The + original packet is \e not invalidated + */ + template <class OtherPacket> + typename ptr_t<OtherPacket>::ptr reinterpret(); + + ///@} + + ///\name Raw packet data + ///@{ + + /** \brief begin interator of raw packet data + + This iterator allows access to the raw data interpreted by + the packet facade. This \e includes any header possibly + interpreted by the derived packet instance. To access the + payload of the packet, use next()->begin(). + + \return random access iterator to the begin of the raw + data */ + iterator begin() const; + /** \brief past-the-end iterator of raw packet data + + This iterator allows access to the raw data interpreted by + the packet facade. This \e includes any header possibly + interpreted by the derived packet instance. To access the + payload of the packet, use next()->end(). + + \return random access past-the-end iterator of the raw + data */ + iterator end() const; + /** \brief raw data size of packet + \return size of the raw data interpreted by this + packet in bytes. This is \e not necessarily the size of + the complete packet, use head()->size() for this. */ + size_t size() const; + + // Modifying the raw packet data + + // FIXME: Make all data mutators protected + + typedef enum { AUTO, BEFORE, INSIDE, OUTSIDE, AFTER } Whence; + + /** \brief insert single byte \a v before pos + + \attention The change will \e not be validated by the + derived packet instance. This method is mostly to be used + by the derived class implementation and their helper + classes. */ + void insert(iterator pos, byte v, Whence whence = AUTO); + /** \brief insert \a n copies of byte \a v before pos + + \attention The change will \e not be validated by the + derived packet instance. This method is mostly to be used + by the derived class implementation and their helper + classes. */ + void insert(iterator pos, size_type n, byte v, Whence whence = AUTO); + /** \brief insert a copy of the given range before pos + + \attention The change will \e not be validated by the + derived packet instance. This method is mostly to be used + by the derived class implementation and their helper + classes. */ + template <class InputIterator> + void insert(iterator pos, InputIterator f, InputIterator l, Whence whence = AUTO); + + /** \brief erase single byte + + \attention The change will \e not be validated by the + derived packet instance. This method is mostly to be used + by the derived class implementation and their helper + classes. */ + void erase(iterator pos); + /** \brief erase range + + \attention The change will \e not be validated by the + derived packet instance. This method is mostly to be used + by the derived class implementation and their helper + classes. */ + void erase(iterator first, iterator last); + + ///@} + + void dump(std::ostream & os) const; + + protected: + ///\name Derived class interface + ///@{ + + /** \brief create new interpreter facade for an existing packet + + This constructor is called, when a new interpreter is to + be added to the interpreter chain. The constructor is + called indirectly from registerInterpreter() or + reinterpret() via the derived classes template + constructor. + */ + template <class Operation> + Packet(Operation const & arg); + virtual ~Packet(); + + private: + /** \brief create next packet interpreter + + This method is called by next(), last() or find_next() to + create any missing interpreters in the interpreter + chain. This method must be overridden in the derived class + to register the next packet interpreter in the interpreter + chain with the packet framework. + + To register the new interpreter, use + registerInterpreter() to create the new Packet + instance. The new instance is automatically added to the + interpreter chain after the current interpreter. + + See also satcom::pkf::PacketRegistryMixin on how to + use a Registry to find the next interpreters implementing + class. + */ + virtual void v_nextInterpreter() const = 0; + + /** \brief finalize packet for sending + + This method is called by the packet framework to let the + interpreter facade do some final calculations/packet + cleanup before the packet is sent out or digested in some + other way. This is the place to calcaulate checksums and + such. + + This method is autmatically called for all interpreters on + the interpreter chain. + */ + virtual void v_finalize() = 0; + + virtual void v_dump(std::ostream & os) const = 0; + + protected: + /** \brief add interpreter to interpreter chain + + This method is used by v_nextInterpreter() in the derived + classes to add a new interpreter to the interpreter + chain. This method will call \c OtherPacket's constructor + with the correct arguments and insert the new interpreter + into the interpreter list. This method is used, if no + further arguments are to be passed to the \c OtherPacket + constructor. If additional arguments are necessary, just + add them after \c end. The compiler will then choose the + correct overload to use. + */ + template <class OtherPacket> + typename ptr_t<OtherPacket>::ptr registerInterpreter( + raw_container::iterator begin, raw_container::iterator end) const; + template <class OtherPacket, class A0> + typename ptr_t<OtherPacket>::ptr registerInterpreter( + raw_container::iterator begin, raw_container::iterator end, + A0 const & a0) const; + +# define BOOST_PP_ITERATION_PARAMS_1 (4, (2, 9, "Packets/Packet.mpp", 3)) +# include BOOST_PP_ITERATE() + + ///@} + + private: + + ///\name Implementation + ///@{ + + void add_ref() const; + bool release(); + bool unlink(); + + struct PacketOp_register; + friend class PacketOp_register; + void i_registerInterpreter(Packet * p) const; + + struct PacketOp_replace; + friend class PacketOp_replace; + void i_replaceInterpreter(Packet * p); + + struct PacketOp_set; + friend class PacketOp_set; + void i_setInterpreter(impl::PacketImpl * i); + + private: + friend class impl::PacketImpl; + template <class OtherPacket> friend class impl::PkReg_EntryImpl; + + impl::PacketImpl* impl_; + size_type begin_; + size_type end_; + interpreter_list::iterator self_; + mutable bool parsed_; + mutable refcount_t refcount_; + + ///@} + }; + + /** \brief dump packet to stream + \related Packet */ + // std::ostream & operator<<(std::ostream & os, Packet const & packet); + + /** \brief smart pointer handling + \relates Packet */ + void intrusive_ptr_add_ref(Packet const *); + /** \brief smart pointer handling + \relates Packet */ + void intrusive_ptr_release(Packet *); + + struct TruncatedPacketException : public std::exception + { virtual char const * what() const throw() { return "truncated packet"; } }; + +}} + +// ////////////////////////////hh.e//////////////////////////////////////// +#include "Packet.cci" +#include "Packet.ct" +#include "Packet.cti" + +#include "Packet.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/Packet.ih b/Packets/Packet.ih new file mode 100644 index 000000000..15203859a --- /dev/null +++ b/Packets/Packet.ih @@ -0,0 +1,143 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef IH_Packet_ +#define IH_Packet_ 1 + +// Custom includes + +///////////////////////////////ih.p//////////////////////////////////////// + +#ifdef SATCOM_PKF_REFC_DEBUG +#include <iostream> +#define SATCOM_PKF_REFC_MSG(x) std::cerr << x +#else +#define SATCOM_PKF_REFC_MSG(x) +#endif + +namespace satcom { +namespace pkf { +namespace impl { + + // This deleter is used in the PacketImpl list holding the + // Packet's. It only decrements the Packet refcount. If this + // drops to 0 (i.e. the packet is removed from the list and no + // external reference exists) the packet ist deleted. + // + // Since this is called, when the packet is removed from the + // list, we set the impl_ member to 0 to mark, that the packet + // is now orphaned and every use should throw an exception ... + // + // To make this work we must make sure, that the packet + // refcount is incremented when we add the packet to the list. + struct ListPacketDeleter { + void operator()(Packet * p); + }; + + struct PacketImpl + { + Packet::raw_container data_; + Packet::interpreter_list interpreters_; + Packet::refcount_t refcount_; + + PacketImpl(); + PacketImpl(unsigned size, Packet::byte initValue); + ~PacketImpl(); + template <class InputIterator> + PacketImpl(InputIterator begin, InputIterator end); + + void add_ref(); + bool release(); + + Packet::interpreter_list::iterator appendInterpreter(Packet * p); + Packet::interpreter_list::iterator prependInterpreter(Packet * p); + bool releaseInterpreter(Packet * p); + void truncateInterpreters(Packet const * p); + void truncateInterpretersAfter(Packet const * p); + + void updateIterators(Packet::size_type index, Packet::difference_type n, + Packet::interpreter_list::iterator self, + Packet::Whence whence); + + /////////////////////////////////////////////////////////////////////////// + // These are here to simplify the friend declaration in Packet + + static void packet_add_ref(Packet const * p); + static void packet_release(Packet * p); + static PacketImpl* impl(Packet const * p); + static Packet::interpreter_list::iterator self(Packet const * p); + }; + + // These methods are used internally to keep PacketImpl_ alive during + // method invocations + void intrusive_ptr_add_ref(PacketImpl * p); + void intrusive_ptr_release(PacketImpl * p); +}}} + + +struct satcom::pkf::Packet::PacketOp_register +{ + size_type b; + size_type e; + const Packet * p; + + PacketOp_register(size_type b_, size_type e_, const Packet * p_) + : b(b_), e(e_), p(p_) {} + + size_type begin() const { return b; } + size_type end() const { return e; } + void operator ()(Packet * self) const + { p->i_registerInterpreter(self); } +}; + +struct satcom::pkf::Packet::PacketOp_replace +{ + Packet * p; + + PacketOp_replace(Packet * p_) : p(p_) {} + + size_type begin() const { return p->begin_; } + size_type end() const { return p->end_; } + void operator()(Packet * self) const + { p->i_replaceInterpreter(self); } +}; + +struct satcom::pkf::Packet::PacketOp_set +{ + impl::PacketImpl * i; + + PacketOp_set(impl::PacketImpl * i_) : i(i_) {} + + size_type begin() const { return 0; } + size_type end() const { return i->data_.size(); } + void operator()(Packet * self) const + { self->i_setInterpreter(i); } +}; + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/Packet.mpp b/Packets/Packet.mpp new file mode 100644 index 000000000..3d47d96bf --- /dev/null +++ b/Packets/Packet.mpp @@ -0,0 +1,134 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#if !BOOST_PP_IS_ITERATING + +// Custom includes +#include <boost/preprocessor/iteration/iterate.hpp> +#include <boost/preprocessor/enum.hpp> +#include <boost/preprocessor/cat.hpp> + +# ifndef MPP_Packet_ +# define MPP_Packet_ +# define pkARG(z,n,data) BOOST_PP_CAT(A,n) const & BOOST_PP_CAT(a,n) +# else +# undef pkARG +# endif + +#else +//////////////////////////////mpp.p//////////////////////////////////////// + +#if BOOST_PP_ITERATION_DEPTH()==1 && BOOST_PP_ITERATION_FLAGS()==1 +/////////////////////////////////////////////////////////////////////////// +// Packet::reinterpret member template declaration + +template < class OtherPacket, BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A) > +typename ptr_t<OtherPacket>::ptr reinterpret( BOOST_PP_ENUM( BOOST_PP_ITERATION(), pkARG, ) ); + +#elif BOOST_PP_ITERATION_DEPTH()==1 && BOOST_PP_ITERATION_FLAGS()==2 +/////////////////////////////////////////////////////////////////////////// +// Packet::reinterpret implementation + +template <class OtherPacket, BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A) > +prefix_ typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr +satcom::pkf::Packet::reinterpret( BOOST_PP_ENUM( BOOST_PP_ITERATION(), pkARG, ) ) +{ + if (!OtherPacket::check(begin(),end())) + throw TruncatedPacketException(); + typename ptr_t<OtherPacket>::ptr p ( + new OtherPacket(PacketOp_replace(this), + BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), a ) ), + false); + return p; +} + +#elif BOOST_PP_ITERATION_DEPTH()==1 && BOOST_PP_ITERATION_FLAGS()==3 +/////////////////////////////////////////////////////////////////////////// +// Packet::registerInterpreter member template declaration + +template < class OtherPacket, BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A) > +typename ptr_t<OtherPacket>::ptr registerInterpreter( + raw_container::iterator begin, raw_container::iterator end, + BOOST_PP_ENUM( BOOST_PP_ITERATION(), pkARG, ) ) const; + +#elif BOOST_PP_ITERATION_DEPTH()==1 && BOOST_PP_ITERATION_FLAGS()==4 +/////////////////////////////////////////////////////////////////////////// +// Packet::registerIterpreter implementation + +template <class OtherPacket, BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A) > +prefix_ typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr +satcom::pkf::Packet::registerInterpreter(raw_container::iterator begin, + raw_container::iterator end, + BOOST_PP_ENUM( BOOST_PP_ITERATION(), pkARG, ) ) + const +{ + if (!OtherPacket::check(begin,end)) + throw TruncatedPacketException(); + typename ptr_t<OtherPacket>::ptr p ( + new OtherPacket(PacketOp_register(begin-impl_->data_.begin(), + end-impl_->data_.begin(), + this), + BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), a) ), + false); + return p; +} + +#elif BOOST_PP_ITERATION_DEPTH()==1 && BOOST_PP_ITERATION_FLAGS()==5 +/////////////////////////////////////////////////////////////////////////// +// Packet::create declaration + +template < class OtherPacket, class InputIterator, + BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A) > +static typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr create( + InputIterator b, InputIterator e, + BOOST_PP_ENUM( BOOST_PP_ITERATION(), pkARG, ) ); + +#elif BOOST_PP_ITERATION_DEPTH()==1 && BOOST_PP_ITERATION_FLAGS()==6 +/////////////////////////////////////////////////////////////////////////// +// Packet::create implementation + +template < class OtherPacket, class InputIterator, + BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A) > +typename satcom::pkf::Packet::ptr_t<OtherPacket>::ptr satcom::pkf::Packet::create( + InputIterator b, InputIterator e, + BOOST_PP_ENUM( BOOST_PP_ITERATION(), pkARG, ) ) +{ + boost::intrusive_ptr<impl::PacketImpl> impl (new impl::PacketImpl(b,e),false); + if (!OtherPacket::check(impl->data_.begin(), impl->data_.end())) + throw TruncatedPacketException(); + typename ptr_t<OtherPacket>::ptr p ( + new OtherPacket(PacketOp_set(impl.get()), + BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), a) ), + false); + return p; +} + +#endif + +//////////////////////////////mpp.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/Packet.test.cc b/Packets/Packet.test.cc new file mode 100644 index 000000000..d41e8a0aa --- /dev/null +++ b/Packets/Packet.test.cc @@ -0,0 +1,247 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Unit tests + +//#include "Packet.test.hh" +//#include "Packet.test.ih" + +// Custom includes +#include "Packet.hh" +#include "DataPacket.hh" +#include "GenericPacket.hh" + +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::pkf; + +// Since Packet is abstract, we can only test the Packet interface using +// a simple implementation: DataPacket and GenericPacket. + +namespace { + + Packet::byte data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; + + bool compare(Packet::iterator b, Packet::iterator e, unsigned o=0) + { + unsigned i (o); + for (; b!=e; ++b, ++i) + if (i>=sizeof(data) || *b != data[i]) + return false; + return true; + } + +} + +BOOST_AUTO_UNIT_TEST(Packet_DataPacket) +{ + Packet::ptr p (Packet::create<DataPacket>(data, data+sizeof(data))); + + BOOST_REQUIRE( p ); + BOOST_CHECK_EQUAL( p->size(), sizeof(data) ); + BOOST_CHECK( compare(p->begin(), p->end()) ); + + *p->begin() = 20; + BOOST_CHECK( !compare(p->begin(), p->end()) ); + BOOST_CHECK_EQUAL( *p->begin(), 20 ); + + BOOST_CHECK( !p->next() ); + BOOST_CHECK( !p->prev() ); + BOOST_CHECK_EQUAL( p->head(), p ); + BOOST_CHECK_EQUAL( p->last(), p ); + + BOOST_CHECK( p->is<DataPacket>() ); + BOOST_CHECK( p->as<DataPacket>() ); +} + +BOOST_AUTO_UNIT_TEST(Packet_GenericPacket) +{ + GenericPacket<4,6>::ptr p (Packet::create< GenericPacket<4,6> >(data, data+sizeof(data))); + + // check, that the packet was constructed corretly + BOOST_REQUIRE( p ); + BOOST_CHECK_EQUAL( p->size(), sizeof(data) ); + BOOST_CHECK( compare(p->begin(), p->end()) ); + BOOST_CHECK_EQUAL( p->header_len(), 4u ); + BOOST_CHECK( compare(p->begin_header(), p->end_header()) ); + BOOST_CHECK_EQUAL( p->trailer_len(), 6u ); + BOOST_CHECK( compare(p->begin_trailer(), p->end_trailer(), sizeof(data)-6) ); + + // check the first packet in the interpreter chain + BOOST_CHECK_EQUAL( p->head(), p ); + BOOST_CHECK( !p->prev() ); + BOOST_CHECK(( p->is< GenericPacket<4,6> >() )); + BOOST_CHECK( !p->is<DataPacket>() ); + BOOST_CHECK(( !p->is< GenericPacket<4,4> >() )); + BOOST_CHECK(( p->as< GenericPacket<4,6> >() )); + BOOST_CHECK( !p->as<DataPacket>() ); + + // check the next packet in the interpreter chain + BOOST_REQUIRE( p->next() ); + BOOST_CHECK( p->next()->is<DataPacket>() ); + BOOST_CHECK(( !p->next()->is< GenericPacket<4,6> >() )); + + // check the contents of the second interpreter + BOOST_CHECK_EQUAL( p->next()->size(), sizeof(data)-10 ); + BOOST_CHECK( compare(p->next()->begin(), p->next()->end(), 4) ); + + // validate, that the two interpreters share the same data + // container + *p->next()->begin() = 20; + BOOST_CHECK( !compare(p->next()->begin(), p->next()->end(), 4) ); + BOOST_CHECK( *p->next()->begin() == 20 ); + BOOST_CHECK( !compare(p->begin(), p->end()) ); + BOOST_CHECK( *(p->begin()+4) == 20 ); + + // We need require here. If this fails, p->last() will probably + // run into an endless loop ... + BOOST_REQUIRE( !p->next()->next() ); + BOOST_CHECK_EQUAL( p->next(), p->last() ); +} + +BOOST_AUTO_UNIT_TEST(Packet_Reinterpret) +{ + Packet::ptr p (Packet::create< GenericPacket<4,4> >(data, data+sizeof(data))); + + BOOST_CHECK( p->next()->is<DataPacket>() ); + p->next()->reinterpret< GenericPacket<6> >(); + BOOST_CHECK( p->next()->is< GenericPacket<6> >() ); + BOOST_REQUIRE( p->next()->next() ); + BOOST_CHECK( p->next()->next()->is<DataPacket>() ); + BOOST_CHECK( !p->next()->next()->next() ); + + BOOST_CHECK_EQUAL( p->next()->next()->size(), sizeof(data)-14 ); + BOOST_CHECK( compare(p->next()->next()->begin(), + p->next()->next()->end(), 10) ); + + p = p->reinterpret< GenericPacket<8,2> >(); + BOOST_REQUIRE( p->next() ); + BOOST_CHECK( p->next()->is<DataPacket>() ); + + BOOST_CHECK_EQUAL( p->next()->size(), sizeof(data)-10 ); + BOOST_CHECK( compare(p->next()->begin(), p->next()->end(), 8) ); +} + +BOOST_AUTO_UNIT_TEST(Packet_InsertErase) +{ + Packet::ptr p (Packet::create< GenericPacket<7,3> >(data, data+sizeof(data))); + p->next()->reinterpret< GenericPacket<4> >(); + + BOOST_CHECK_EQUAL( p->size(), 20u ); + BOOST_CHECK_EQUAL( p->next()->size(), 10u ); + BOOST_CHECK_EQUAL( p->next()->next()->size(), 6u ); + + BOOST_CHECK_EQUAL( p->next()->next()->begin()[0], 11 ); + BOOST_CHECK_EQUAL( p->end()[-1], 19 ); + BOOST_CHECK_EQUAL( p->next()->end()[-1], 16 ); + BOOST_CHECK_EQUAL( p->next()->next()->end()[-1], 16 ); + + p->next()->insert(p->next()->begin()+2, data, data+6); + + BOOST_CHECK_EQUAL( p->size(), 26u ); + BOOST_CHECK_EQUAL( p->next()->size(), 16u ); + BOOST_CHECK_EQUAL( p->next()->next()->size(), 6u ); + + BOOST_CHECK( compare(p->begin(), p->begin()+9) ); + BOOST_CHECK( compare(p->begin()+9, p->begin()+15) ); + BOOST_CHECK( compare(p->begin()+15, p->end(), 9) ); + BOOST_CHECK( compare(p->next()->begin(), p->next()->begin()+2, 7) ); + BOOST_CHECK( compare(p->next()->begin()+2, p->next()->begin()+8) ); + BOOST_CHECK( compare(p->next()->begin()+8, p->next()->end(), 9) ); + BOOST_CHECK( compare(p->next()->next()->begin(), p->next()->next()->end(), 11) ); + + p->next()->erase( p->next()->begin()+2, p->next()->begin()+8 ); + + BOOST_CHECK_EQUAL( p->size(), 20u ); + BOOST_CHECK_EQUAL( p->next()->size(), 10u ); + BOOST_CHECK_EQUAL( p->next()->next()->size(), 6u ); + + BOOST_CHECK( compare(p->begin(), p->end()) ); + BOOST_CHECK( compare(p->next()->begin(), p->next()->end(), 7) ); + BOOST_CHECK( compare(p->next()->next()->begin(), p->next()->next()->end(), 11) ); + + p->next()->insert(p->next()->begin()+4, data, data+2); + + BOOST_CHECK_EQUAL( p->size(), 22u ); + BOOST_CHECK_EQUAL( p->next()->size(), 12u ); + BOOST_CHECK_EQUAL( p->next()->next()->size(), 6u ); + + BOOST_CHECK( compare(p->next()->next()->begin(), p->next()->next()->end(), 11) ); + + p->next()->erase(p->next()->begin()+4, p->next()->begin()+6); + + BOOST_CHECK_EQUAL( p->size(), 20u ); + BOOST_CHECK_EQUAL( p->next()->size(), 10u ); + BOOST_CHECK_EQUAL( p->next()->next()->size(), 6u ); + + BOOST_CHECK( compare(p->begin(), p->end()) ); + BOOST_CHECK( compare(p->next()->begin(), p->next()->end(), 7) ); + BOOST_CHECK( compare(p->next()->next()->begin(), p->next()->next()->end(), 11) ); + + p->next()->next()->insert(p->next()->begin()+5, data, data+4); + + BOOST_CHECK_EQUAL( p->size(), 24u ); + BOOST_CHECK_EQUAL( p->next()->size(), 14u ); + BOOST_CHECK_EQUAL( p->next()->next()->size(), 10u ); + + BOOST_CHECK( compare(p->next()->next()->begin(), p->next()->next()->begin()+1, 11) ); + BOOST_CHECK( compare(p->next()->next()->begin()+1, p->next()->next()->begin()+5) ); + BOOST_CHECK( compare(p->next()->next()->begin()+5, p->end(), 12) ); + + p->next()->erase(p->next()->begin()+3, p->next()->begin()+9); + + BOOST_CHECK_EQUAL( p->size(), 18u ); + BOOST_CHECK_EQUAL( p->next()->size(), 8u ); + BOOST_CHECK_EQUAL( p->next()->next()->size(), 5u ); + + BOOST_CHECK( compare(p->next()->next()->begin(), p->next()->next()->end(), 12) ); + BOOST_CHECK( compare(p->begin(), p->begin()+10) ); + BOOST_CHECK( compare(p->begin()+10, p->end(), 12) ); + + p->erase(p->begin()+5, p->end()); + + BOOST_CHECK_EQUAL( p->size(), 5u ); + BOOST_CHECK_EQUAL( p->next()->size(), 0u ); + BOOST_CHECK_EQUAL( p->next()->next()->size(), 0u ); +} + +BOOST_AUTO_UNIT_TEST(Packet_new) +{ + Packet::ptr p (Packet::create< GenericPacket<10,4> >()); + BOOST_CHECK_EQUAL(p->size(), 14u); + Packet::ptr p2 (Packet::create< GenericPacket<2,2> >(p)); + BOOST_CHECK_EQUAL(p2->size(),18u); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/PacketRegistry.cc b/Packets/PacketRegistry.cc new file mode 100644 index 000000000..631d76391 --- /dev/null +++ b/Packets/PacketRegistry.cc @@ -0,0 +1,43 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline non-template funPacketRegistry.ons + +#include "PacketRegistry.hh" +#include "PacketRegistry.ih" + +// Custom includes + +#define prefix_ +///////////////////////////////PacketRegistry..p//////////////////////////////////////// + +satcom::pkf::impl::PkReg_EntryImpl<satcom::pkf::DataPacket> + satcom::pkf::impl::pkreg_dataEntry; + +///////////////////////////////PacketRegistry..e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/PacketRegistry.ct b/Packets/PacketRegistry.ct new file mode 100644 index 000000000..e40f3ac12 --- /dev/null +++ b/Packets/PacketRegistry.ct @@ -0,0 +1,107 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline template funPacketRegistry.ons + +#include "PacketRegistry.ih" + +// Custom includes +#include <iostream> +#include "Utils/TypeInfo.hh" + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template <class KeyType> +template <class OtherPacket> +prefix_ void satcom::pkf::impl::PacketRegistryImpl<KeyType>::registerPacket(key_t key) +{ + // If this assertion fails, a Packet was registered with an already known key + BOOST_ASSERT( registry_.insert(std::make_pair( + key, Entry_ptr(new impl::PkReg_EntryImpl<OtherPacket>()))).second ); + // If this assertion fails, the same Packet was registered with two different keys + BOOST_ASSERT( reverseRegistry_.insert( + std::make_pair(satcom::lib::typeIdValue<OtherPacket>(), key)).second ); +} + +template <class KeyType> +prefix_ typename satcom::pkf::impl::PacketRegistryImpl<KeyType>::key_t +satcom::pkf::impl::PacketRegistryImpl<KeyType>::key(satcom::lib::TypeIdValue const & type) +{ + typename ReversePacketMap::iterator i (reverseRegistry_.find(type)); + if (i==reverseRegistry_.end()) + throw PacketTypeNotRegistered(); + return i->second; +} + +template <class OtherPacket> +prefix_ void +satcom::pkf::impl::PkReg_EntryImpl<OtherPacket>::registerInterpreter(Packet const * p, + Packet::iterator b, + Packet::iterator e) +{ + p->template registerInterpreter<OtherPacket>(b,e); +} + +template <class OtherPacket> +prefix_ satcom::pkf::Packet::ptr +satcom::pkf::impl::PkReg_EntryImpl<OtherPacket>::reinterpret(Packet * p) +{ + return p->template reinterpret<OtherPacket>(); +} + +template <class KeyType> +prefix_ typename satcom::pkf::impl::PacketRegistryImpl<KeyType>::Entry * +satcom::pkf::impl::PacketRegistryImpl<KeyType>::lookup(key_t key) +{ + typename PacketMap::iterator i (registry_.find(key)); + if (i==registry_.end()) + return &impl::pkreg_dataEntry; + return i->second.get(); +} + +template <class Tag> +template <class InputIterator> +prefix_ satcom::pkf::Packet::ptr +satcom::pkf::PacketRegistry<Tag>::create(typename Tag::key_t key, InputIterator b, + InputIterator e) +{ + Packet::ptr p (Packet::create<DataPacket>(b,e)); + return registry().lookup(key)->reinterpret(p.get()); +} + +template <class Tag> +prefix_ typename satcom::pkf::PacketRegistry<Tag>::Registry & +satcom::pkf::PacketRegistry<Tag>::registry() +{ + static Registry registry; + return registry; +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/PacketRegistry.cti b/Packets/PacketRegistry.cti new file mode 100644 index 000000000..8c86ad89a --- /dev/null +++ b/Packets/PacketRegistry.cti @@ -0,0 +1,83 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template funPacketRegistry.ons + +#include "PacketRegistry.ih" + +// Custom includes +#include "Packet.hh" + +#define prefix_ inline +///////////////////////////////PacketRegistry..p/////////////////////////////////////// + +template <class Tag> +template <class OtherPacket> +prefix_ void satcom::pkf::PacketRegistry<Tag>::registerPacket(typename Tag::key_t key) +{ + registry().registerPacket<OtherPacket>(key); +} + +template <class Tag> +template <class OtherPacket> +prefix_ satcom::pkf::PacketRegistry<Tag>::RegistrationProxy<OtherPacket>:: +RegistrationProxy(typename Tag::key_t key) +{ + PacketRegistry<Tag>::template registerPacket<OtherPacket>(key); +} + +template <class Tag> +template <class OtherPacket> +prefix_ typename Tag::key_t satcom::pkf::PacketRegistry<Tag>::key() +{ + return registry().key(satcom::lib::typeIdValue<OtherPacket>()); +} + +template <class KeyType> +template <class OtherPacket> +prefix_ void +satcom::pkf::impl::PacketRegistryImpl<KeyType>::registerInterpreter(Packet * p, + Packet::iterator b, + Packet::iterator e) +{ + p->registerInterpreter<OtherPacket>(b,e); +} + +template <class Tag, class Derived> +prefix_ void +satcom::pkf::PacketRegistryMixin<Tag,Derived>::registerInterpreter(typename Tag::key_t key, + Packet::iterator b, + Packet::iterator e) + const +{ + PacketRegistry<Tag>::registry().lookup(key)->registerInterpreter( + static_cast<Derived const * const>(this),b,e); +} + +///////////////////////////////PacketRegistry..e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/PacketRegistry.hh b/Packets/PacketRegistry.hh new file mode 100644 index 000000000..94f93b1fb --- /dev/null +++ b/Packets/PacketRegistry.hh @@ -0,0 +1,206 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// TODO: Add parameterless create() method + +#ifndef HH_PacketRegistryImpl_ +#define HH_PacketRegistryImpl_ 1 + +// Custom includes +#include <map> +#include <boost/utility.hpp> // for boost::noncopyable +#include <boost/shared_ptr.hpp> +#include "Packet.hh" + +//#include "PacketRegistry.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + namespace impl { template <class key> class PacketRegistryImpl; } + + /** \brief Packet registration facility + + The PacketRegistry provides a generic facility to associate an + arbitrary key with Packets. Example keys are Ethertype or IP + protocols. + + Every PacketRegistry is identified by a type tag: + \code + struct SomeTag { + typedef some_key_type key_t; + }; + \endcode + The key type can be an arbitrary valuetype. The PacketRegistry + for this Tag can then be accessed using + <code>PacketRegistry<SomeTag>::</code>. + + The PacketRegistry class has only static members and provides + access to the packet registry. It allows to register Packet + classes and to create new Packets given a key. Methods are + also provided to find the key of a Packet type. + + \code + PacketRegistry<SomeTag>::registerPacket<SomePacket>(key_of_somePacket); + p = PacketRegistry<SomeTag>::create(some_key,begin,end); + SomeTag::key_t key = PacketRegistry<SomeTag>::key<SomePacket>(); + \endcode + + Normally, packet classes are registered statically and not + procedurally. To this end, the RegistrationProxy is provided: + \code + PacketRegistry<SomeTag>::RegistrationProxy<SomePacket> + registerSomePacket (key_of_somePacket); + \endcode + This global variable declaration will register \c SomePacket + with the \c SomeTag registry under the key \c + key_of_somePacket. The variable \c registerSomePacket is a + dummy. It's only function is to force the call of it's + constructor during global construction time. + + The PacketRegistry's purpose is mostly to assist in + implementing the \v v_nextInterpreter() member of packet + facades. This is further supported by the PacketRegistryMixin + class. + */ + template <class Tag> + class PacketRegistry + { + public: + // TODO: This fails to work within a library since the linker will + // remove all unused object files ... + /** \brief Statically register a packet type in a PacketRegistry + */ + template <class OtherPacket> + struct RegistrationProxy + { + RegistrationProxy(typename Tag::key_t key); + }; + + /** \brief Register new packet type + + Register \c OtherPacket in the packet registry \c Tag + under the given \c key. + + \par Preconditions: + The given \c key must be unique and not be assigned to + any other packet class in this registry. + The Packet must not already be registered in the registry. + + \param OtherPacket packet to regiser + \param key key of the packet + */ + template <class OtherPacket> + static void registerPacket(typename Tag::key_t key); + + /** \brief Find key of a packet + + Return the key of \c OtherPacket as registered in the \c + Tag registry + + \param OtherPacket packet of which the key is requested + \returns key of the packet + \throws PacketTypeNotRegistered if the packet type is not + found in the registry. + */ + template <class OtherPacket> + static typename Tag::key_t key(); + + /** \brief Create new Packet + + \param key Key of packet type to create instance of + \param b begin iterator argument to Packet::create() + \param e end iterator argment to Packet::create() + \returns new Instance of the packet type registered under + key or DataPacket, if the key is not registered. + */ + template <class InputIterator> + static Packet::ptr create(typename Tag::key_t key, InputIterator b, InputIterator e); + + private: + typedef impl::PacketRegistryImpl<typename Tag::key_t> Registry; + static Registry & registry(); + + template <class T, class D> friend class PacketRegistryMixin; + }; + + /** \brief Helper class for v_nextInterpreter implementations + + This class is a helper class which is to be inherited from in + a packet facade which wants to register a new interpreter with + the packet framework depending on a packet registry. + + This mixin class provides a new registerInterpreter + implementation which can be used besides the methods provided + bei satcom::pkf::Packet to add a new interpreter to the + interpreter chain. + + \code + class SomePacket + : public Packet, + private PacketRegistryMixin<SomeTag,SomePacket> + { + using Packet::retgisterInterpreter; + using PacketRegistryMixin<SomeTag,SomePacket>::registerInterpreter; + + virtual void v_nextInterpreter() + { + registerInterpreter(some_key_value, subpacket_begin, subpacket_end); + } + }; + \endcode + This example is not complete, it only contains the parts + concerned with PacketRegistryMixin. + */ + template <class Tag, class Derived> + class PacketRegistryMixin + { + protected: + /** \brief add interpreter to interpreter chain + + This method is used by v_nextInterpreter() to add a new + interpreter to the interpreter chain (see the Packet + reference for more). Instead of specifying the type of + packet to use as a template argument it is specified using + the \c key value from the \c Tag registry + */ + void registerInterpreter(typename Tag::key_t key, + Packet::iterator b, Packet::iterator e) const; + }; + + struct PacketTypeNotRegistered : public std::exception + { virtual char const * what() const throw() { return "packet type not registered"; } }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "PacketRegistry.cci" +#include "PacketRegistry.ct" +#include "PacketRegistry.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/PacketRegistry.ih b/Packets/PacketRegistry.ih new file mode 100644 index 000000000..2a752b2c6 --- /dev/null +++ b/Packets/PacketRegistry.ih @@ -0,0 +1,108 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef IH_PacketRegistryImpl_ +#define IH_PacketRegistryImpl_ 1 + +// Custom includes +#include "Packet.hh" +#include "DataPacket.hh" +#include "typeidvalue.hh" + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { +namespace impl { + + struct PkReg_Entry { + virtual void registerInterpreter(Packet const * p, + Packet::iterator b, Packet::iterator e) = 0; + virtual Packet::ptr reinterpret(Packet * p) = 0; + }; + + template <class OtherPacket> + struct PkReg_EntryImpl + : public PkReg_Entry + { + virtual void registerInterpreter(Packet const * p, Packet::iterator b, Packet::iterator e); + virtual Packet::ptr reinterpret(Packet * p); + }; + + + template <class KeyType> + class PacketRegistryImpl : private boost::noncopyable + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef KeyType key_t; + + typedef impl::PkReg_Entry Entry; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + // default default constructor + // no copy constructor + // no copy assignment + // default destructor + // no conversion constructors + + ///@} + /////////////////////////////////////////////////////////////////////////// + + template <class OtherPacket> + void registerPacket(key_t key); + + key_t key(satcom::lib::TypeIdValue const & type); + + Entry * lookup(key_t key); + + protected: + + private: + template <class OtherPacket> + static void registerInterpreter(Packet * p, Packet::iterator b, Packet::iterator e); + + typedef boost::shared_ptr<Entry> Entry_ptr; + typedef std::map<key_t, Entry_ptr> PacketMap; + typedef std::map<satcom::lib::TypeIdValue, key_t> ReversePacketMap; + + PacketMap registry_; + ReversePacketMap reverseRegistry_; + }; + + extern PkReg_EntryImpl<DataPacket> pkreg_dataEntry; + +}}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/PacketRegistry.test.cc b/Packets/PacketRegistry.test.cc new file mode 100644 index 000000000..4d235c705 --- /dev/null +++ b/Packets/PacketRegistry.test.cc @@ -0,0 +1,171 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Unit tests + +//#include "PacketRegistry.test.hh" +//#include "PacketRegistry.test.ih" + +// Custom includes +#include <string> +#include "PacketRegistry.hh" +#include "DataPacket.hh" +#include "ParseInt.hh" + +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + + using namespace satcom::pkf; + + struct BaseTag { + typedef unsigned key_t; + }; + + struct StringTag { + typedef std::string key_t; + }; + + class BasePacket + : public Packet, public PacketRegistryMixin<BaseTag,BasePacket> + { + using PacketRegistryMixin<BaseTag,BasePacket>::registerInterpreter; + public: + typedef ptr_t<BasePacket>::ptr ptr; + typedef iterator byte_iterator; + + typedef Parse_UInt16<iterator> Parse_Type; + + Parse_Type type() const { return Parse_Type(begin()); } + static bool check(iterator b, iterator e) { return true; } + + private: + template <class Arg> + BasePacket(Arg const & arg) : Packet(arg) {} + + virtual void v_nextInterpreter() const + { registerInterpreter(type(), begin()+2, end()); } + virtual void v_finalize() {} + virtual void v_dump(std::ostream & os) const {} + + friend class Packet; + }; + + class FooPacket : public Packet + { + public: + typedef ptr_t<FooPacket>::ptr ptr; + typedef iterator byte_iterator; + + static bool check(iterator b, iterator e) { return true; } + + private: + template <class Arg> + FooPacket(Arg const & arg) : Packet(arg) {} + + virtual void v_nextInterpreter() const {} + virtual void v_finalize() {} + virtual void v_dump(std::ostream & os) const {} + + friend class Packet; + }; + + class BarPacket : public Packet + { + public: + typedef ptr_t<BarPacket>::ptr ptr; + typedef iterator byte_iterator; + + static bool check(iterator b, iterator e) { return true; } + + private: + template <class Arg> + BarPacket(Arg const & arg) : Packet(arg) {} + + virtual void v_nextInterpreter() const {} + virtual void v_finalize() {} + virtual void v_dump(std::ostream & os) const {} + + friend class Packet; + }; + + namespace reg { + PacketRegistry<StringTag>::RegistrationProxy<FooPacket> registerFoo ("foo"); + PacketRegistry<StringTag>::RegistrationProxy<BarPacket> registerBar ("bar"); + } + +} + +BOOST_AUTO_UNIT_TEST(packetRegistry_test) +{ + unsigned char data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; + + { + BasePacket::ptr p (Packet::create<BasePacket>(data, data+sizeof(data))); + BOOST_CHECK( p->next()->is<DataPacket>() ); + } + + PacketRegistry<BaseTag>::registerPacket<FooPacket>(1u); + PacketRegistry<BaseTag>::registerPacket<BarPacket>(2u); + + BOOST_CHECK_EQUAL( PacketRegistry<BaseTag>::key<FooPacket>(), 1u ); + BOOST_CHECK_EQUAL( PacketRegistry<BaseTag>::key<BarPacket>(), 2u ); + BOOST_CHECK_THROW( PacketRegistry<BaseTag>::key<DataPacket>(), PacketTypeNotRegistered ); + + { + BasePacket::ptr p (Packet::create<BasePacket>(data, data+sizeof(data))); + BOOST_CHECK( p->next()->is<FooPacket>() ); + } + + data[1] = 0x02; + + { + BasePacket::ptr p (Packet::create<BasePacket>(data, data+sizeof(data))); + BOOST_CHECK( p->next()->is<BarPacket>() ); + } + + data[0] = 0x01; + + { + BasePacket::ptr p (Packet::create<BasePacket>(data, data+sizeof(data))); + BOOST_CHECK( p->next()->is<DataPacket>() ); + } + + BOOST_CHECK_EQUAL( PacketRegistry<StringTag>::key<FooPacket>(), "foo" ); + BOOST_CHECK( PacketRegistry<StringTag>::create("foo",data,data+sizeof(data)) + ->is<FooPacket>() ); + +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseArray.cti b/Packets/ParseArray.cti new file mode 100644 index 000000000..c932dd831 --- /dev/null +++ b/Packets/ParseArray.cti @@ -0,0 +1,206 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +#include "ParseArray.ih" + +// Custom includes +#include <algorithm> +#if defined(_STLP_ALGORITHM) || (__GNUC__<4 && __GNUC_MINOR__<4) +#define copy_n std::copy_n +#else +#include <ext/algorithm> +#define copy_n __gnu_cxx::copy_n +#endif + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <unsigned elements, class Parser, class Iterator, class IPacket> +prefix_ satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::Parse_Array() +{} + +template <unsigned elements, class Parser, class Iterator, class IPacket> +prefix_ +satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::Parse_Array(Iterator const & i) + : ParserBase<Iterator,IPacket>(i) +{} + +template <unsigned elements, class Parser, class Iterator, class IPacket> +prefix_ unsigned satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::bytes() +{ + return elements*Parser::bytes(); +} + +template <unsigned elements, class Parser, class Iterator, class IPacket> +prefix_ bool +satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::check(Iterator const & e) + const +{ + return e-this->i() >= bytes(); +} + +template <unsigned elements, class Parser, class Iterator, class IPacket> +prefix_ void satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::init() + const +{ + iterator e=end(); + for (iterator i=begin(); i!=e; ++i) i->init(); +} + +/////////////////////////////////////////////////////////////////////////// + +template <unsigned elements, class Parser, class Iterator, class IPacket> +prefix_ typename satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::size_type +satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::size() +{ + return elements; +} + +template <unsigned elements, class Parser, class Iterator, class IPacket> +prefix_ typename satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::iterator +satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::begin() + const +{ + return iterator(this->i()); +} + +template <unsigned elements, class Parser, class Iterator, class IPacket> +prefix_ typename satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::iterator +satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::end() + const +{ + return iterator(this->i()+bytes()); +} + +template <unsigned elements, class Parser, class Iterator, class IPacket> +prefix_ typename satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::range_type +satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::range() + const +{ + return std::make_pair(begin(),end()); +} + +template <unsigned elements, class Parser, class Iterator, class IPacket> +prefix_ typename satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::iterator +satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::value() + const +{ + return begin(); +} + +template <unsigned elements, class Parser, class Iterator, class IPacket> +prefix_ typename satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::value_type +satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::operator[](difference_type i) + const +{ + return begin()[i]; +} + +template <unsigned elements, class Parser, class Iterator, class IPacket> +template <class InputIterator> +prefix_ satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket> const & +satcom::pkf::Parse_Array<elements,Parser,Iterator,IPacket>::operator=(InputIterator const & i) +{ + copy_n(i,size(),begin()); +} + +/////////////////////////////////////////////////////////////////////////// + +template <class Parser, class Iterator> +prefix_ Iterator satcom::pkf::impl::Parse_Array_iterator<Parser,Iterator>::raw() + const +{ + return i_; +} + +template <class Parser, class Iterator> +prefix_ Parser satcom::pkf::impl::Parse_Array_iterator<Parser,Iterator>::operator[](int i) + const +{ + return (*this+i).dereference(); +} + +template <class Parser, class Iterator> +prefix_ satcom::pkf::impl::Parse_Array_iterator<Parser,Iterator>::Parse_Array_iterator() + : i_() +{} + +template <class Parser, class Iterator> +prefix_ satcom::pkf::impl::Parse_Array_iterator<Parser,Iterator>:: +Parse_Array_iterator(Iterator const & i) + : i_(i) +{} + +template <class Parser, class Iterator> +prefix_ Parser +satcom::pkf::impl::Parse_Array_iterator<Parser,Iterator>::dereference() + const +{ + return Parser(i_); +} + +template <class Parser, class Iterator> +prefix_ bool satcom::pkf::impl::Parse_Array_iterator<Parser,Iterator>:: +equal(Parse_Array_iterator const & other) + const +{ + return i_==other.i_; +} + +template <class Parser, class Iterator> +prefix_ int satcom::pkf::impl::Parse_Array_iterator<Parser,Iterator>:: +distance_to(Parse_Array_iterator const & other) + const +{ + return (other.i_-i_)/Parser::bytes(); +} + +template <class Parser, class Iterator> +prefix_ void satcom::pkf::impl::Parse_Array_iterator<Parser,Iterator>::increment() +{ + i_ += Parser::bytes(); +} + +template <class Parser, class Iterator> +prefix_ void satcom::pkf::impl::Parse_Array_iterator<Parser,Iterator>::decrement() +{ + i_ -= Parser::bytes(); +} + +template <class Parser, class Iterator> +prefix_ void +satcom::pkf::impl::Parse_Array_iterator<Parser,Iterator>::advance(int n) +{ + i_ += n*Parser::bytes(); +} + +#undef copy_n +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseArray.hh b/Packets/ParseArray.hh new file mode 100644 index 000000000..f4a0d4110 --- /dev/null +++ b/Packets/ParseArray.hh @@ -0,0 +1,91 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_ParseArray_ +#define HH_ParseArray_ 1 + +// Custom includes +#include <utility> // for std::pair +#include "ParserBase.hh" + +//#include "ParseArray.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + namespace impl { template <class,class> class Parse_Array_iterator; } + + /* Parse_Array has the external interface of a container class + */ + template <unsigned elements, class Parser, class Iterator=nil, class IPacket=nil> + struct Parse_Array : public ParserBase<Iterator,IPacket> + { + /////////////////////////////////////////////////////////////////////////// + // Parser interface + + template <class I=nil, class P=nil> + struct rebind { typedef Parse_Array<elements,Parser,I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_Array(); + explicit Parse_Array(Iterator const & i); + + static unsigned bytes(); + bool check(Iterator const & e) const; + void init() const; + + /////////////////////////////////////////////////////////////////////////// + // Container interface + + typedef typename Parser::template rebind<Iterator>::parser value_type; + typedef impl::Parse_Array_iterator<value_type,Iterator> iterator; + typedef unsigned size_type; + typedef int difference_type; + typedef std::pair<iterator,iterator> range_type; + + static size_type size(); + + iterator begin() const; + iterator end() const; + range_type range() const; + iterator value() const; + + value_type operator[](difference_type i) const; + + template <class InputIterator> + Parse_Array const & operator= (InputIterator const & i); + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "ParseArray.cci" +//#include "ParseArray.ct" +#include "ParseArray.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseArray.ih b/Packets/ParseArray.ih new file mode 100644 index 000000000..85e850f16 --- /dev/null +++ b/Packets/ParseArray.ih @@ -0,0 +1,69 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef IH_ParseArray_ +#define IH_ParseArray_ 1 + +// Custom includes +#include <boost/iterator/iterator_facade.hpp> + +///////////////////////////////ih.p//////////////////////////////////////// + +template <class Parser, class Iterator> +class satcom::pkf::impl::Parse_Array_iterator + : public boost::iterator_facade< Parse_Array_iterator<Parser,Iterator>, + Parser, + boost::random_access_traversal_tag, + Parser > +{ +public: + Parse_Array_iterator(); + explicit Parse_Array_iterator(Iterator const & i); + + // Needed to elide the []-proxy of iterator_facade + Parser operator[](int i) const; + + Iterator raw() const; + +protected: + +private: + friend class boost::iterator_core_access; + + Parser dereference() const; + bool equal(Parse_Array_iterator const & other) const; + int distance_to(Parse_Array_iterator const & other) const; + void increment(); + void decrement(); + void advance(int n); + + Iterator i_; +}; + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseArray.test.cc b/Packets/ParseArray.test.cc new file mode 100644 index 000000000..59a9898fc --- /dev/null +++ b/Packets/ParseArray.test.cc @@ -0,0 +1,67 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Unit tests + +//#include "ParseArray.test.hh" +//#include "ParseArray.test.ih" + +// Custom includes +#include "ParseArray.hh" +#include "ParseInt.hh" + +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::pkf; + +BOOST_AUTO_UNIT_TEST(parseArray_test) +{ + unsigned char data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; + typedef unsigned char * iterator; + typedef Parse_Array<6,Parse_UInt8<>,iterator> Parse_UInt8Array6; + Parse_UInt8Array6 v (data); + BOOST_CHECK_EQUAL( v[0], 0x00 ); + BOOST_CHECK_EQUAL( v[5], 0x05 ); + BOOST_CHECK_EQUAL( *v.begin(), 0x00 ); + Parse_UInt8Array6::iterator i1 (v.begin()); + Parse_UInt8Array6::iterator i2 (v.begin()); + ++i1; + BOOST_CHECK_EQUAL( *i1, 0x01 ); + BOOST_CHECK_EQUAL( i1[-1], 0x00 ); + BOOST_CHECK_EQUAL( i1-i2, 1 ); + BOOST_CHECK_EQUAL( i2-i1, -1 ); + --i1; + BOOST_CHECK( i1==i2 ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseInt.hh b/Packets/ParseInt.hh new file mode 100644 index 000000000..1207eafe9 --- /dev/null +++ b/Packets/ParseInt.hh @@ -0,0 +1,320 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_ParseInt_ +#define HH_ParseInt_ 1 + +// Custom includes +#include "ParserBase.hh" +#include <boost/cstdint.hpp> +#include <boost/static_assert.hpp> +#include <boost/integer/integer_mask.hpp> + +//#include "ParseInt.mpp" +///////////////////////////////hh.p//////////////////////////////////////// +#include "ParseInt.ih" + +namespace satcom { +namespace pkf { + + template <class Iterator=nil, class IPacket=nil> + struct Parse_Int8 + : public impl::ParseIntOps<Parse_Int8<Iterator,IPacket>,boost::int8_t>, + public ParserBase<Iterator,IPacket> + { + template <class I=nil, class P=nil> + struct rebind { typedef Parse_Int8<I,P> parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 1; } + + Parse_Int8() {} + explicit Parse_Int8(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef boost::int8_t value_type; + + value_type value() const { return this->i()[0]; } + void value(value_type v) { this->i()[0] = v; } + Parse_Int8 const & operator= (value_type other) { value(other); return *this; } + }; + + template <class Iterator=nil, class IPacket=nil> + struct Parse_UInt8 + : public impl::ParseIntOps<Parse_UInt8<Iterator,IPacket>,boost::uint8_t>, + public ParserBase<Iterator,IPacket> + { + template <class I=nil, class P=nil> + struct rebind { typedef Parse_UInt8<I,P> parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 1; } + + Parse_UInt8() {} + explicit Parse_UInt8(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef boost::uint8_t value_type; + + value_type value() const { return this->i()[0]; } + void value(value_type v) { this->i()[0] = v; } + Parse_UInt8 const & operator= (value_type other) { value(other); return *this; } + }; + + template <class Iterator=nil, class IPacket=nil> + struct Parse_Int16 + : public impl::ParseIntOps<Parse_Int16<Iterator,IPacket>,boost::int16_t>, + public ParserBase<Iterator,IPacket> + { + template <class I=nil, class P=nil> + struct rebind { typedef Parse_Int16<I,P> parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 2; } + + Parse_Int16() {} + explicit Parse_Int16(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef boost::int16_t value_type; + + value_type value() const { return impl::parse_uint16(this->i()); } + void value(value_type v) { impl::write_uint16(this->i(),v); } + Parse_Int16 const & operator= (value_type other) { value(other); return *this; } + }; + + template <class Iterator=nil, class IPacket=nil> + struct Parse_UInt16 + : public impl::ParseIntOps<Parse_UInt16<Iterator,IPacket>,boost::uint16_t>, + public ParserBase<Iterator,IPacket> + { + template <class I=nil, class P=nil> + struct rebind { typedef Parse_UInt16<I,P> parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 2; } + + Parse_UInt16() {} + explicit Parse_UInt16(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef boost::uint16_t value_type; + + value_type value() const { return impl::parse_uint16(this->i()); } + void value(value_type v) { impl::write_uint16(this->i(),v); } + Parse_UInt16 const & operator= (value_type other) { value(other); return *this; } + }; + + template <class Iterator=nil, class IPacket=nil> + struct Parse_Int24 + : public impl::ParseIntOps<Parse_Int24<Iterator,IPacket>,boost::int32_t>, + public ParserBase<Iterator,IPacket> + { + template <class I=nil, class P=nil> + struct rebind { typedef Parse_Int24<I,P> parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 3; } + + Parse_Int24() {} + explicit Parse_Int24(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef boost::int32_t value_type; + + value_type value() const { + value_type v (impl::parse_uint24(this->i())); return v&0x800000 ? v|0xff000000 : v; } + void value(value_type v) { impl::write_uint24(this->i(),v); } + Parse_Int24 const & operator= (value_type other) { value(other); return *this; } + }; + + template <class Iterator=nil, class IPacket=nil> + struct Parse_UInt24 + : public impl::ParseIntOps<Parse_UInt24<Iterator,IPacket>,boost::uint32_t>, + public ParserBase<Iterator,IPacket> + { + template <class I=nil, class P=nil> + struct rebind { typedef Parse_UInt24<I,P> parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 3; } + + Parse_UInt24() {} + explicit Parse_UInt24(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef boost::uint32_t value_type; + + value_type value() const { return impl::parse_uint24(this->i()); } + void value(value_type v) { impl::write_uint24(this->i(),v); } + Parse_UInt24 const & operator= (value_type other) { value(other); return *this; } + }; + + template <class Iterator=nil, class IPacket=nil> + struct Parse_Int32 + : public impl::ParseIntOps<Parse_Int32<Iterator,IPacket>,boost::int32_t>, + public ParserBase<Iterator,IPacket> + { + template <class I=nil, class P=nil> + struct rebind { typedef Parse_Int32<I,P> parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 4; } + + Parse_Int32() {} + explicit Parse_Int32(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef boost::int32_t value_type; + + value_type value() const { return impl::parse_uint32(this->i()); } + void value(value_type v) { impl::write_uint32(this->i(),v); } + Parse_Int32 const & operator= (value_type other) { value(other); return *this; } + }; + + template <class Iterator=nil, class IPacket=nil> + struct Parse_UInt32 + : public impl::ParseIntOps<Parse_UInt32<Iterator,IPacket>,boost::uint32_t>, + public ParserBase<Iterator,IPacket> + { + template <class I=nil, class P=nil> + struct rebind { typedef Parse_UInt32<I,P> parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 4; } + + Parse_UInt32() {} + explicit Parse_UInt32(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef boost::uint32_t value_type; + + value_type value() const { return impl::parse_uint32(this->i()); } + void value(value_type v) { impl::write_uint32(this->i(),v); } + Parse_UInt32 const & operator= (value_type other) { value(other); return *this; } + }; + + template <unsigned start, unsigned end, class Iterator=nil, class IPacket=nil> + struct Parse_IntField + : public impl::ParseIntOps<Parse_IntField<start,end,Iterator,IPacket>,boost::int32_t>, + public ParserBase<Iterator,IPacket> + { + template <class I=nil, class P=nil> + struct rebind { typedef Parse_IntField<start,end,I,P> parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return (end-1)/8+1; } + + Parse_IntField() {} + explicit Parse_IntField(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef boost::int32_t value_type; + + value_type value() const { + value_type v (impl::parse_bitfield<Iterator,start,end>::parse(this->i())); + return v&boost::high_bit_mask_t<end-start-1>::high_bit ? + v | ~boost::low_bits_mask_t<end-start>::sig_bits : v; + } + void value(value_type v) { impl::parse_bitfield<Iterator,start,end>::write(this->i(),v); } + Parse_IntField const & operator= (value_type other) { value(other); return *this; } + + private: + BOOST_STATIC_ASSERT( start<end ); + BOOST_STATIC_ASSERT( end-start<=32 ); + }; + + template <unsigned start, unsigned end, class Iterator=nil, class IPacket=nil> + struct Parse_UIntField + : public impl::ParseIntOps<Parse_UIntField<start,end,Iterator,IPacket>,boost::uint32_t>, + public ParserBase<Iterator,IPacket> + { + template <class I=nil, class P=nil> + struct rebind { typedef Parse_UIntField<start,end,I,P> parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return (end-1)/8+1; } + + Parse_UIntField() {} + explicit Parse_UIntField(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef boost::uint32_t value_type; + + value_type value() const { return impl::parse_bitfield<Iterator,start,end>::parse(this->i()); } + void value(value_type v) { impl::parse_bitfield<Iterator,start,end>::write(this->i(),v); } + Parse_UIntField const & operator= (value_type other) { value(other); return *this; } + + private: + BOOST_STATIC_ASSERT( start<end ); + BOOST_STATIC_ASSERT( end-start<=32 ); + }; + + template <unsigned bit, class Iterator=nil, class IPacket=nil> + struct Parse_Flag + : public impl::ParseIntOps<Parse_Flag<bit,Iterator,IPacket>,bool>, + public ParserBase<Iterator,IPacket> + { + template <class I=nil, class P=nil> + struct rebind { typedef Parse_Flag<bit,I,P> parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 1; } + + Parse_Flag() {} + explicit Parse_Flag(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef bool value_type; + + value_type value() const { return this->i()[bit/8] & (1<<(7-(bit%8))); } + void value(value_type v) { + if (v) this->i()[0] |= 1<<(7-(bit%8)); + else this->i()[0] &= ~(1<<(7-(bit%8))); + } + Parse_Flag const & operator= (value_type other) { value(other); return *this; } + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "ParseInt.cci" +//#include "ParseInt.ct" +//#include "ParseInt.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseInt.ih b/Packets/ParseInt.ih new file mode 100644 index 000000000..70c5859a5 --- /dev/null +++ b/Packets/ParseInt.ih @@ -0,0 +1,219 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef IH_ParseInt_ +#define IH_ParseInt_ 1 + +// Custom includes + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { +namespace impl { + + /////////////////////////////////////////////////////////////////////////// + // Integer operators + + template <class Derived, class Value> + class ParseIntOps + { + public: + typedef Value value_type; + + operator Value () const { return derived().value(); } + +# define unary(op) \ + Value operator op () const { return op derived().value(); } +# define mutator(op) \ + template <class Other> Derived const & operator op ## = (Other other) \ + { derived().value( derived().value() op other ); return derived(); } + + unary(~) + unary(!) + unary(-) + + mutator(+) + mutator(-) + mutator(*) + mutator(/) + mutator(%) + mutator(<<) + mutator(>>) + mutator(&) + mutator(|) + mutator(^) + +# undef unary +# undef mutator + + Derived const & operator ++ () + { derived().value( derived.value()+1 ); return derived(); } + Derived const & operator -- () + { derived().value( derived.value()-1 ); return derived(); } + + private: + Derived & derived() { return *static_cast<Derived *>(this); } + Derived const & derived() const { return *static_cast<Derived const *>(this); }; + }; + + /////////////////////////////////////////////////////////////////////////// + // Network byte order integer extraction + + template <class Iterator> + boost::uint16_t parse_uint16(Iterator const & i) + { + return i[1] | i[0]<<8; + } + + template <class Iterator> + void write_uint16(Iterator const & i, boost::uint16_t v) + { + i[0] = ( v >> 8 ) & 0xff; + i[1] = ( v ) & 0xff; + } + + template <class Iterator> + boost::uint32_t parse_uint24(Iterator const & i) + { + return i[2] | i[1]<<8 | i[0]<<16; + } + + template <class Iterator> + void write_uint24(Iterator const & i, boost::uint32_t v) + { + i[0] = ( v >> 16 ) & 0xff; + i[1] = ( v >> 8 ) & 0xff; + i[2] = ( v ) & 0xff; + } + + template <class Iterator> + boost::uint32_t parse_uint32(Iterator const & i) + { + return i[3] | i[2]<<8 | i[1]<<16 | i[0]<<24; + } + + template <class Iterator> + void write_uint32(Iterator const & i, boost::uint32_t v) + { + i[0] = ( v >> 24 ) & 0xff; + i[1] = ( v >> 16 ) & 0xff; + i[2] = ( v >> 8 ) & 0xff; + i[3] = ( v ) & 0xff; + } + + /////////////////////////////////////////////////////////////////////////// + // bitfield extraction + + template <class Iterator, unsigned offset, unsigned endb, unsigned start, unsigned end> + struct parse_bitfield_i + { + static boost::uint32_t parse(Iterator const & i) { + return ( ( ( parse_uint32(i+offset+1)>>(40-end) ) // Beware of sign extension !! + & boost::low_bits_mask_t<32-(40-end)>::sig_bits ) + | (i[offset]<<(32-(40-end))) ) + & boost::low_bits_mask_t<end-start>::sig_bits; + } + + static void write(Iterator const & i, boost::uint32_t v) { + write_uint32(i+offset+1, + (parse_uint32(i+offset+1) & ~(boost::low_bits_mask_t<end-8>::sig_bits<<(40-end))) + | ((v & boost::low_bits_mask_t<end-8>::sig_bits) << (40-end))); + i[offset] = (i[offset] & ~(boost::low_bits_mask_t<8-start>::sig_bits)) + | ((v>>(end-8)) & boost::low_bits_mask_t<8-start>::sig_bits); + } + }; + + template <class Iterator, unsigned offset, unsigned start, unsigned end> + struct parse_bitfield_i<Iterator, offset, 3, start, end> + { + static boost::uint32_t parse(Iterator const & i) { + return ( parse_uint32(i+offset)>>(32-end) ) + & boost::low_bits_mask_t<end-start>::sig_bits; + } + + static void write(Iterator const & i, boost::uint32_t v) { + write_uint32(i+offset, + (parse_uint32(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(32-end))) + | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (32-end))); + } + }; + + template <class Iterator, unsigned offset, unsigned start, unsigned end> + struct parse_bitfield_i<Iterator, offset, 2, start, end> + { + static boost::uint32_t parse(Iterator const & i) { + return ( parse_uint24(i+offset)>>(24-end) ) + & boost::low_bits_mask_t<end-start>::sig_bits; + } + + static void write(Iterator const & i, boost::uint32_t v) { + write_uint24(i+offset, + (parse_uint24(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(24-end))) + | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (24-end))); + } + }; + + template <class Iterator, unsigned offset, unsigned start, unsigned end> + struct parse_bitfield_i<Iterator, offset, 1, start, end> + { + static boost::uint32_t parse(Iterator const & i) { + return ( parse_uint16(i+offset)>>(16-end) ) + & boost::low_bits_mask_t<end-start>::sig_bits; + } + + static void write(Iterator const & i, boost::uint32_t v) { + write_uint16(i+offset, + (parse_uint16(i+offset) & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(16-end))) + | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (16-end))); + } + }; + + template <class Iterator, unsigned offset, unsigned start, unsigned end> + struct parse_bitfield_i<Iterator, offset, 0, start, end> + { + static boost::uint32_t parse(Iterator const & i) { + return ( i[offset]>>(8-end) ) + & boost::low_bits_mask_t<end-start>::sig_bits; + } + + static void write(Iterator const & i, boost::uint32_t v) { + i[offset] = (i[offset] & ~(boost::low_bits_mask_t<end-start>::sig_bits<<(8-end))) + | ((v & boost::low_bits_mask_t<end-start>::sig_bits) << (8-end)); + } + }; + + template <class Iterator, unsigned start, unsigned end> + struct parse_bitfield + : public parse_bitfield_i<Iterator,start/8,(end-1)/8-start/8,start%8,end-8*(start/8)> + {}; + +}}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseInt.test.cc b/Packets/ParseInt.test.cc new file mode 100644 index 000000000..732535907 --- /dev/null +++ b/Packets/ParseInt.test.cc @@ -0,0 +1,241 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Unit tests + +//#include "ParseInt.test.hh" +//#include "ParseInt.test.ih" + +// Custom includes +#include "ParseInt.hh" +#include "Packet.hh" + +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::pkf; + +BOOST_AUTO_UNIT_TEST(parseInt_fixedSizes) +{ + unsigned char data[] = { 0x8e, 0x2f, 0x57, 0x12, 0xd1 }; + typedef unsigned char * iterator; + + BOOST_CHECK_EQUAL(Parse_Int8<iterator>(data).value(), -114); + BOOST_CHECK_EQUAL(Parse_Int8<iterator>(data+1).value(), 47); + BOOST_CHECK_EQUAL(Parse_UInt8<iterator>(data).value(), 142u); + + BOOST_CHECK_EQUAL(Parse_Int16<iterator>(data).value(), -29137); + BOOST_CHECK_EQUAL(Parse_Int16<iterator>(data+1).value(), 12119); + BOOST_CHECK_EQUAL(Parse_UInt16<iterator>(data).value(), 36399u); + + BOOST_CHECK_EQUAL(Parse_Int24<iterator>(data).value(), -7458985); + BOOST_CHECK_EQUAL(Parse_Int24<iterator>(data+1).value(), 3102482); + BOOST_CHECK_EQUAL(Parse_UInt24<iterator>(data).value(), 9318231u); + + BOOST_CHECK_EQUAL(Parse_Int32<iterator>(data).value(), -1909500142); + BOOST_CHECK_EQUAL(Parse_Int32<iterator>(data+1).value(), 794235601); + BOOST_CHECK_EQUAL(Parse_UInt32<iterator>(data).value(), 2385467154u); +} + +BOOST_AUTO_UNIT_TEST(parseInt_bits) +{ + // 0 1 2 3 4 + // 012345678901234567890123456789012345678901234567 + // -------- -------- -------- + // 011000111101011101011010001100011010010001000110 + unsigned char data[] = { 0x63, 0xd7, 0x5a, 0x31, 0xa4, 0x46 }; + typedef unsigned char * iterator; + + // 1 byte + BOOST_CHECK_EQUAL((Parse_UIntField<2,7,iterator>(data).value()), 17u); + BOOST_CHECK_EQUAL((Parse_IntField<2,7,iterator>(data).value()), -15); + BOOST_CHECK_EQUAL((Parse_UIntField<3,7,iterator>(data).value()), 1u); + BOOST_CHECK_EQUAL((Parse_IntField<3,7,iterator>(data).value()), 1); + BOOST_CHECK_EQUAL((Parse_UIntField<0,8,iterator>(data).value()), 99u); + + // 2 byte + BOOST_CHECK_EQUAL((Parse_UIntField<5,12,iterator>(data).value()), 61u); + BOOST_CHECK_EQUAL((Parse_UIntField<0,12,iterator>(data).value()), 1597u); + BOOST_CHECK_EQUAL((Parse_UIntField<8,13,iterator>(data).value()), 26u); + BOOST_CHECK_EQUAL((Parse_UIntField<8,16,iterator>(data).value()), 215u); + BOOST_CHECK_EQUAL((Parse_UIntField<0,16,iterator>(data).value()), 25559u); + + // 3 byte + BOOST_CHECK_EQUAL((Parse_UIntField<6,20,iterator>(data).value()), 15733u); + BOOST_CHECK_EQUAL((Parse_IntField<6,20,iterator>(data).value()), -651); + BOOST_CHECK_EQUAL((Parse_UIntField<13,22,iterator>(data).value()), 470u); + + // 4 byte + BOOST_CHECK_EQUAL((Parse_UIntField<3,28,iterator>(data).value()), 4027811u); + BOOST_CHECK_EQUAL((Parse_UIntField<13,38,iterator>(data).value()), 30837865u); + BOOST_CHECK_EQUAL((Parse_UIntField<8,40,iterator>(data).value()), 3613012388u); + BOOST_CHECK_EQUAL((Parse_IntField<8,40,iterator>(data).value()), -681954908); + + // 5 byte + BOOST_CHECK_EQUAL((Parse_UIntField<3,34,iterator>(data).value()), 257779910u); + BOOST_CHECK_EQUAL((Parse_IntField<13,41,iterator>(data).value()), -21732536); + + // single bit + BOOST_CHECK_EQUAL((Parse_Flag<32,iterator>(data).value()), true); + BOOST_CHECK_EQUAL((Parse_Flag<12,iterator>(data).value()), false); +} + +BOOST_AUTO_UNIT_TEST(parseInt_assign) +{ + unsigned char data[] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; + typedef unsigned char * iterator; + + Parse_Int8<iterator>(data).value(0x2f); + BOOST_CHECK_EQUAL( data[0], 0x2f ); + + Parse_Int16<iterator>(data).value(0xa341); + BOOST_CHECK_EQUAL( data[0], 0xa3 ); + BOOST_CHECK_EQUAL( data[1], 0x41 ); + + Parse_Int24<iterator>(data).value(0x234567); + BOOST_CHECK_EQUAL( data[0], 0x23 ); + BOOST_CHECK_EQUAL( data[1], 0x45 ); + BOOST_CHECK_EQUAL( data[2], 0x67 ); + + Parse_Int32<iterator>(data).value(0xfedcba98); + BOOST_CHECK_EQUAL( data[0], 0xfe ); + BOOST_CHECK_EQUAL( data[1], 0xdc ); + BOOST_CHECK_EQUAL( data[2], 0xba ); + BOOST_CHECK_EQUAL( data[3], 0x98 ); + + Parse_IntField<2,6,iterator>(data).value(0x3); + BOOST_CHECK_EQUAL( data[0], 0xce ); + BOOST_CHECK_EQUAL( data[1], 0xdc ); + + Parse_IntField<6,9,iterator>(data).value(0x2); + BOOST_CHECK_EQUAL( data[0], 0xcd ); + BOOST_CHECK_EQUAL( data[1], 0x5c ); + BOOST_CHECK_EQUAL( data[2], 0xba ); + + Parse_IntField<2,21,iterator>(data).value(0x13d75); + BOOST_CHECK_EQUAL( data[0], 0xc9 ); + BOOST_CHECK_EQUAL( data[1], 0xeb ); + BOOST_CHECK_EQUAL( data[2], 0xaa ); + BOOST_CHECK_EQUAL( data[3], 0x98 ); + + Parse_UIntField<4,34,iterator>(data).value(0x268ad497u); + BOOST_CHECK_EQUAL( (Parse_UIntField<4,34,iterator>(data).value()), 0x268ad497u ); +} + +BOOST_AUTO_UNIT_TEST(parseInt_operators) +{ + unsigned char data[] = { 0x63, 0xd7, 0x5a, 0x31, 0xa4, 0x46 }; + + Parse_UInt24<unsigned char *> p1(data); + Parse_UInt16<unsigned char *> p2(data+3); + + BOOST_CHECK_EQUAL( ~p1, 4288424101u ); + BOOST_CHECK ( !!p1 ); + BOOST_CHECK_EQUAL( -p1, -6543194u ); + + p1 += 0x10; + BOOST_CHECK_EQUAL( p1, 6543210u ); + p1 -= 0x10; + BOOST_CHECK_EQUAL( p1, 6543194u ); + + p1 += p2; + BOOST_CHECK_EQUAL( p1, 6555902u ); + p2 += p1; + // Here some idiotic automatic promotion from unsigned short -> + // int happens in the second macro parameter ... hrmpf ... + BOOST_CHECK_EQUAL( p2, 15010 ); + + p1 = 0x123456u; + BOOST_CHECK_EQUAL( data[0], 0x12 ); + BOOST_CHECK_EQUAL( data[1], 0x34 ); + BOOST_CHECK_EQUAL( data[2], 0x56 ); + BOOST_CHECK_EQUAL( data[3], 0x3a ); + + // I stop here ... this is absolutely identical for all other + // operators and all other integer types. If really some error pops + // up, I'll add a check here ... +} + +namespace { + + template < class P > + class TestPacket + : public Packet, public P::template rebind< Packet::iterator,TestPacket<P> >::parser + { + public: + typedef typename P::template rebind<Packet::iterator,TestPacket>::parser parser; + typedef typename ptr_t<TestPacket>::ptr ptr; + + static bool check(iterator b, iterator e) { return true; } + + private: + template <class Arg> + TestPacket(Arg const & arg) + : Packet(arg) {} + + virtual void v_nextInterpreter() const {} + virtual void v_finalize() {} + virtual void v_dump(std::ostream &) const {} + + friend class Packet; + }; + + template < class P > + typename P::value_type packetCheck() + { + unsigned char data[] = { 0x8e, 0x2f, 0x57, 0x12, 0xd1 }; + typename TestPacket<P>::ptr p (Packet::create< TestPacket<P> >(data, data+sizeof(data))); + return p->value(); + } + +} + +BOOST_AUTO_UNIT_TEST(parseInt_inherited) +{ + BOOST_CHECK_EQUAL(packetCheck< Parse_Int8<> >(), -114); + BOOST_CHECK_EQUAL(packetCheck< Parse_UInt8<> >(), 142u); + + BOOST_CHECK_EQUAL(packetCheck< Parse_Int16<> >(), -29137); + BOOST_CHECK_EQUAL(packetCheck< Parse_UInt16<> >(), 36399u); + + BOOST_CHECK_EQUAL(packetCheck< Parse_Int24<> >(), -7458985); + BOOST_CHECK_EQUAL(packetCheck< Parse_UInt24<> >(), 9318231u); + + BOOST_CHECK_EQUAL(packetCheck< Parse_Int32<> >(), -1909500142); + BOOST_CHECK_EQUAL(packetCheck< Parse_UInt32<> >(), 2385467154u); + + BOOST_CHECK_EQUAL((packetCheck< Parse_IntField<3,28> >()), 14873969); + BOOST_CHECK_EQUAL((packetCheck< Parse_UIntField<3,28> >()), 14873969u); + BOOST_CHECK_EQUAL((packetCheck< Parse_Flag<11> >()), false); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseListS.ct b/Packets/ParseListS.ct new file mode 100644 index 000000000..7e65fa968 --- /dev/null +++ b/Packets/ParseListS.ct @@ -0,0 +1,121 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline template functions + +#include "ParseListS.ih" + +// Custom includes +#include <algorithm> + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template <class Parser, class Sentinel, class Iterator, class IPacket> +prefix_ unsigned satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::bytes() + const +{ + iterator i (begin()); + iterator e (end()); + size_type s (0); + for (; i!=e; ++i) + s += i->bytes(); + // The sentinel is not part of the range + // but it's part of the list !! + return s+i->bytes(); +} + +template <class Parser, class Sentinel, class Iterator, class IPacket> +prefix_ bool +satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::check(Iterator const & e) + const +{ + byte_iterator i (this->i()); + for (;;) { + value_type v (i); + if (!v.check(e)) return false; + if (sentinel::check(v)) return true; + size_type s (v.bytes()); + if (s==0) return false; + i += s; + } +} + +template <class Parser, class Sentinel, class Iterator, class IPacket> +prefix_ void satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::init() + const +{ + iterator i (begin()); + iterator e (end()); + for (;i!=e; ++i) + i->init(); + // The sentinel is not part of the range + // but it's part of the list !! + i->init(); +} + +/////////////////////////////////////////////////////////////////////////// +// satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container> + +template <class Parser, class Sentinel, class Container> +template <class Value> +prefix_ void +satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>::insert(iterator pos, + Value const & t) +{ + // FIXME: What, if pos == end() / default constructed iterator ? + size_type ix (pos.raw()-container_.begin()); + container_.insert(pos.raw(),t.bytes(),0); + Parser(container_.begin()+ix).value(t); +} + +template <class Parser, class Sentinel, class Container> +template <class Value> +prefix_ void +satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>::insert(iterator pos, size_type n, + Value const & t) +{ + size_type ix (pos.raw()-container_.begin()); + container_.insert(pos.raw(),n*t.bytes(),0); + typename Container::iterator i (container_.begin()+ix); + for (; n; ++i, --n) + Parser(i).value(t); +} + +template <class Parser, class Sentinel, class Container> +template <class InputIterator> +prefix_ void +satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>::insert(iterator pos, + InputIterator f, + InputIterator l) +{ + for (;f!=l;++f,++pos) insert(pos,*f); +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseListS.cti b/Packets/ParseListS.cti new file mode 100644 index 000000000..db917578e --- /dev/null +++ b/Packets/ParseListS.cti @@ -0,0 +1,201 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +#include "ParseListS.ih" + +// Custom includes +#include <boost/assert.hpp> + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <class Parser, class Sentinel, class Iterator, class IPacket> +prefix_ satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::Parse_ListS() +{} + +template <class Parser, class Sentinel, class Iterator, class IPacket> +prefix_ +satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::Parse_ListS(Iterator const & i) + : ParserBase<Iterator,IPacket>(i) +{} + +template <class Parser, class Sentinel, class Iterator, class IPacket> +prefix_ typename satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::size_type +satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::size() + const +{ + return std::distance(begin(),end()); +} + +template <class Parser, class Sentinel, class Iterator, class IPacket> +prefix_ bool satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::empty() + const +{ + return begin()==end(); +} + +template <class Parser, class Sentinel, class Iterator, class IPacket> +prefix_ typename satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::iterator +satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::begin() + const +{ + return iterator(this->i()); +} + +template <class Parser, class Sentinel, class Iterator, class IPacket> +prefix_ typename satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::iterator +satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::end() + const +{ + return iterator(); +} + +template <class Parser, class Sentinel, class Iterator, class IPacket> +prefix_ typename satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::range_type +satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::range() + const +{ + return std::make_pair(begin(),end()); +} + +template <class Parser, class Sentinel, class Iterator, class IPacket> +prefix_ typename satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::range_type +satcom::pkf::Parse_ListS<Parser,Sentinel,Iterator,IPacket>::value() + const +{ + return range(); +} + +/////////////////////////////////////////////////////////////////////////// +// satcom::pkf::impl::Parse_ListS_iterator<Parser,Sentinel,Iterator> + +template <class Parser, class Sentinel, class Iterator> +prefix_ +satcom::pkf::impl::Parse_ListS_iterator<Parser,Sentinel,Iterator>::Parse_ListS_iterator() + : i_(), atEnd_(true) +{} + +template <class Parser, class Sentinel, class Iterator> +prefix_ +satcom::pkf::impl::Parse_ListS_iterator<Parser,Sentinel,Iterator>:: +Parse_ListS_iterator(Iterator const & i) + : i_(i), atEnd_(false) +{ + atEnd_ = Sentinel::check(dereference()); +} + +template <class Parser, class Sentinel, class Iterator> +prefix_ Iterator satcom::pkf::impl::Parse_ListS_iterator<Parser,Sentinel,Iterator>::raw() + const +{ + return i_; +} + +template <class Parser, class Sentinel, class Iterator> +prefix_ Parser +satcom::pkf::impl::Parse_ListS_iterator<Parser,Sentinel,Iterator>::dereference() + const +{ + return Parser(i_); +} + +template <class Parser, class Sentinel, class Iterator> +prefix_ bool satcom::pkf::impl::Parse_ListS_iterator<Parser,Sentinel,Iterator>:: +equal(Parse_ListS_iterator const & other) + const +{ + // !! We cannot compare the to iterators if either + // !! Iterator is atEnd_, since one of the iterators + // !! might be a default-constructed iterator and + // !! iterators can only be compared with each other + // !! if both point to the *same* valid container + if (atEnd_ || other.atEnd_) return atEnd_ == other.atEnd_; + return i_ == other.i_; +} + +template <class Parser, class Sentinel, class Iterator> +prefix_ void satcom::pkf::impl::Parse_ListS_iterator<Parser,Sentinel,Iterator>::increment() +{ + BOOST_ASSERT( !atEnd_ ); + i_ += dereference().bytes(); + atEnd_ = Sentinel::check(dereference()); +} + +/////////////////////////////////////////////////////////////////////////// +// satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container> + +template <class Parser, class Sentinel, class Container> +template <class P, class S, class I, class IP> +prefix_ satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>:: +Parse_ListS_wrapper(Parse_ListS<P,S,I,IP> const & list, Container & container) + : i_(list.i()-container.begin()), container_(container) +{} + +template <class Parser, class Sentinel, class Container> +prefix_ typename satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>::size_type +satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>::size() + const +{ + return std::distance(begin(),end()); +} + +template <class Parser, class Sentinel, class Container> +prefix_ bool satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>::empty() + const +{ + return begin()==end(); +} + +template <class Parser, class Sentinel, class Container> +prefix_ typename satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>::iterator +satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>::begin() + const +{ + return iterator(container_.begin()+i_); +} + +template <class Parser, class Sentinel, class Container> +prefix_ typename satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>::iterator +satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>::end() + const +{ + return iterator(); +} + +template <class Parser, class Sentinel, class Container> +prefix_ typename satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>::range_type +satcom::pkf::Parse_ListS_wrapper<Parser,Sentinel,Container>::range() + const +{ + return std::make_pair(begin(),end()); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseListS.hh b/Packets/ParseListS.hh new file mode 100644 index 000000000..2c75016b4 --- /dev/null +++ b/Packets/ParseListS.hh @@ -0,0 +1,165 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_ParseListS_ +#define HH_ParseListS_ 1 + +// Custom includes +#include <utility> // for std::pair +#include <boost/iterator/iterator_facade.hpp> +#include <boost/utility.hpp> // for boost::noncopyable +#include "ParserBase.hh" + +//#include "ParseListS.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + template <class Parser, class Sentinel, class Container> class Parse_ListS_wrapper; + namespace impl { + template <class Parser, class Sentinel, class Container> class Parse_ListS_iterator; + } + + template <class Parser, class Sentinel, class Iterator=nil, class IPacket=nil> + struct Parse_ListS : public ParserBase<Iterator,IPacket> + { + /////////////////////////////////////////////////////////////////////////// + // Parser interface + + template <class I=nil, class P=nil> + struct rebind { typedef Parse_ListS<Parser,Sentinel,I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_ListS(); + Parse_ListS(Iterator const & i); + + unsigned bytes() const; + bool check(Iterator const & e) const; + void init() const; + + /////////////////////////////////////////////////////////////////////////// + // Container interface + + typedef typename Parser::template rebind<Iterator>::parser value_type; + typedef Sentinel sentinel; + typedef impl::Parse_ListS_iterator<value_type,sentinel,byte_iterator> iterator; + typedef unsigned size_type; + typedef int difference_type; + typedef std::pair<iterator,iterator> range_type; + + template <class Container> + struct wrapper { typedef Parse_ListS_wrapper<value_type, Sentinel, Container> t; }; + + size_type size() const; + bool empty() const; + + iterator begin() const; + iterator end() const; + range_type range() const; + range_type value() const; + + private: + template <class P, class S, class C> friend class Parse_ListS_wrapper; + }; + + /** \brief + + Holds a reference to the container ! + */ + template <class Parser, class Sentinel, class Container> + class Parse_ListS_wrapper + : public boost::noncopyable + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef Container container; + typedef Sentinel sentinel; + typedef typename Parser::byte_iterator byte_iterator; + typedef Parser value_type; + typedef impl::Parse_ListS_iterator<value_type,sentinel,byte_iterator> iterator; + typedef unsigned size_type; + typedef int difference_type; + typedef std::pair<iterator,iterator> range_type; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + template <class P, class S, class I, class IP> + Parse_ListS_wrapper(Parse_ListS<P,S,I,IP> const & list, Container & container); + + // no default constructor + // no copy + // default destructor + // no conversion constructors + + ///@} + /////////////////////////////////////////////////////////////////////////// + ///\name Accessors + ///@{ + + size_type size() const; + bool empty() const; + + iterator begin() const; + iterator end() const; + range_type range() const; + + ///@} + /////////////////////////////////////////////////////////////////////////// + ///\name Mutators + ///@{ + + template <class Value> void insert(iterator pos, Value const & t); + template <class Value> void insert(iterator pos, size_type n, Value const & t); + template <class InputIterator> void insert(iterator pos, InputIterator f, InputIterator l); + + void erase(iterator pos, size_type n=1); + void erase(iterator f, iterator l); + void clear(); + + ///@} + + protected: + + private: + + size_type i_; + Container & container_; + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "ParseListS.cci" +#include "ParseListS.ct" +#include "ParseListS.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseListS.ih b/Packets/ParseListS.ih new file mode 100644 index 000000000..6dbeb24d6 --- /dev/null +++ b/Packets/ParseListS.ih @@ -0,0 +1,69 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef IH_ParseListS_ +#define IH_ParseListS_ 1 + +// Custom includes +#include <boost/iterator/iterator_facade.hpp> + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { +namespace impl { + + template <class Parser, class Sentinel, class Iterator> + class Parse_ListS_iterator + : public boost::iterator_facade< Parse_ListS_iterator<Parser,Sentinel,Iterator>, + Parser, + boost::forward_traversal_tag, + Parser > + { + public: + Parse_ListS_iterator(); + explicit Parse_ListS_iterator(Iterator const & i); + + Iterator raw() const; + + private: + friend class boost::iterator_core_access; + + Parser dereference() const; + bool equal(Parse_ListS_iterator const & other) const; + void increment(); + + Iterator i_; + bool atEnd_; + }; + +}}} + + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseListS.test.cc b/Packets/ParseListS.test.cc new file mode 100644 index 000000000..464b33620 --- /dev/null +++ b/Packets/ParseListS.test.cc @@ -0,0 +1,174 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Unit tests + +//#include "ParseListS.test.hh" +//#include "ParseListS.test.ih" + +// Custom includes +#include "ParseListS.hh" +#include "ParseInt.hh" +#include "ParseVec.hh" + +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/assign.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::pkf; + +namespace { + template <class Value> + struct Sentinel_IsZero { + static bool check(Value v) { return v==0; } + }; +} + +BOOST_AUTO_UNIT_TEST(parse_ListS_simple) +{ + unsigned char data[] = { 0x01, 0x02, 0x03, 0x04, 0x00 }; + typedef unsigned char * iterator; + typedef Parse_ListS<Parse_UInt8<>,Sentinel_IsZero<unsigned char>,iterator> Parse_UInt8ListS; + + Parse_UInt8ListS l (data); + Parse_UInt8ListS::iterator i (l.begin()); + Parse_UInt8ListS::iterator e (l.end()); + for (iterator c (data); *c; ++c) { + BOOST_REQUIRE( i!=e ); + BOOST_CHECK_EQUAL( *c, *i ); + ++i; + } + BOOST_CHECK( i==e ); + + BOOST_CHECK_EQUAL( l.bytes(), 5u ); + BOOST_CHECK_EQUAL( l.size(), 4u ); + BOOST_CHECK( !l.empty() ); +} + +namespace { + // LVec is a vector with the length living directly before the vector + template <class Parser, class SizeParser, class Iterator=nil, class IPacket=nil> + struct Parse_LVec + : public Parse_Vector<Parser, SizeParser,Iterator,IPacket> + { + template <class I=nil, class P=nil> + struct rebind { typedef Parse_LVec<Parser,SizeParser,I,P> parser; }; + typedef typename SizeParser::template rebind<Iterator>::parser sizeParser; + + Parse_LVec(Iterator const & i) + : Parse_Vector<Parser,SizeParser,Iterator,IPacket>(sizeParser(i),i+sizeParser::bytes()) + {} + + unsigned bytes() const + { return this->Parse_Vector<Parser,SizeParser,Iterator,IPacket>::bytes() + sizeParser::bytes(); } + bool check(Iterator const & e) const + // BEWARE .. this->i() points to the Vector not the SizeParser ... hrmpf ... + { return e>=this->i() && static_cast<unsigned>(e-this->i())+sizeParser::bytes() >= bytes(); } + }; + + template <class Array> + struct Sentinel_EmptyArray { + static bool check(Array a) { return a.empty(); } + }; +} + +BOOST_AUTO_UNIT_TEST(parse_ListS_complex) +{ + unsigned char data[] = { 0x02, 0x01, 0x02, + 0x03, 0x11, 0x12, 0x13, + 0x04, 0x21, 0x22, 0x23, 0x24, + 0x00 }; + + typedef unsigned char * iterator; + typedef Parse_LVec<Parse_UInt8<>,Parse_UInt8<>,iterator> Parse_UInt8LVec; + typedef Parse_ListS<Parse_UInt8LVec,Sentinel_EmptyArray<Parse_UInt8LVec>,iterator> Parse_UInt8LVecListS; + + Parse_UInt8LVecListS l (data); + BOOST_CHECK( l.check(data+13) ); + + Parse_UInt8LVecListS::iterator i (l.begin()); + Parse_UInt8LVecListS::iterator e (l.end()); + for (unsigned n (0); n<3; ++n) { + BOOST_REQUIRE( i!=e ); + BOOST_CHECK_EQUAL( i->size(), n+2 ); + Parse_UInt8LVec::iterator j (i->begin()); + Parse_UInt8LVec::iterator je (i->end()); + for (unsigned m (0); m<n+2; ++m, ++j) { + BOOST_CHECK( j!=je ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(*j), 16*n+m+1 ); + } + BOOST_CHECK( j==je ); + ++i; + } + BOOST_CHECK( i==e ); + + BOOST_CHECK_EQUAL( l.size(), 3u ); + BOOST_CHECK_EQUAL( l.bytes(), 13u ); + BOOST_CHECK( !l.empty() ); +} + +BOOST_AUTO_UNIT_TEST(parse_ListS_wrapper) +{ + typedef std::vector<unsigned char> Container; + typedef Container::iterator iterator; + typedef Parse_LVec<Parse_UInt8<>,Parse_UInt8<>,iterator> Parse_UInt8LVec; + typedef Parse_ListS<Parse_UInt8LVec, Sentinel_EmptyArray<Parse_UInt8LVec>,iterator> Parse_UInt8LVecListS; + typedef Parse_UInt8LVecListS::wrapper<Container>::t Parse_UInt8LVecListSWrap; + + using namespace boost::assign; + + Container data; + data += + 0x02, 0x01, 0x02, + 0x03, 0x11, 0x12, 0x13, + 0x04, 0x21, 0x22, 0x23, 0x24, + 0x00; + + Parse_UInt8LVecListS l (data.begin()); + Parse_UInt8LVecListSWrap w (l,data); + + BOOST_CHECK_EQUAL( w.size(), 3u ); + BOOST_CHECK ( !w.empty() ); + BOOST_CHECK ( w.begin() != w.end() ); + BOOST_CHECK ( w.range() == std::make_pair(w.begin(), w.end()) ); + +#if 0 + unsigned char newdata[] = { 0x01, 0x00 }; + + w.insert(w.begin(),Parse_UInt8LVec::rebind<unsigned char*>::parser(newdata)); + BOOST_CHECK_EQUAL( w.size(), 4u ); + BOOST_CHECK_EQUAL( w.begin()->size(), 1u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>((*w.begin())[0]), 0x00u ); +#endif +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseVec.ct b/Packets/ParseVec.ct new file mode 100644 index 000000000..a34f1c9ae --- /dev/null +++ b/Packets/ParseVec.ct @@ -0,0 +1,81 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline template funPacketRegistry.ons + +//#include "ParseVec.ih" + +// Custom includes + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template <class Parser, class SizeParser, class Container> +template <class Value> +prefix_ void +satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::insert(iterator pos, + Value const & t) +{ + size_type ix(pos.raw()-container_.begin()); + shift(pos); + Parser(container_.begin()+ix).value(t); +} + +template <class Parser, class SizeParser, class Container> +template <class Value> +prefix_ void +satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::insert(iterator pos, + size_type n, + Value const & t) +{ + size_type ix(pos.raw()-container_.begin()); + shift(pos,n); + typename Container::iterator j (container_.begin()+ix); + for (; n; --n, j+=Parser::bytes()) + Parser(j).value(t); +} + +template <class Parser, class SizeParser, class Container> +template <class InputIterator> +prefix_ void +satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::insert(iterator pos, + InputIterator f, + InputIterator l) +{ + // FIXME: This is HORRIBLY inefficient ... we need to specialize + // for random_aPacketRegistry.ess and forward iterators, where we can count the distance + + size_type ix(pos.raw()-container_.begin()); + for (;f!=l;++f) { + insert(container_.begin()+ix,*f); + ix += Parser::bytes(); + } +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseVec.cti b/Packets/ParseVec.cti new file mode 100644 index 000000000..86f282f14 --- /dev/null +++ b/Packets/ParseVec.cti @@ -0,0 +1,224 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +//#include "ParseVec.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <class Parser, class SizeParser, class Iterator, class IPacket> +prefix_ satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>:: +Parse_Vector(SizeParser const & size) + : size_(size) +{} + +template <class Parser, class SizeParser, class Iterator, class IPacket> +prefix_ satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>:: +Parse_Vector(size_parser const & size, Iterator const & i) + : ParserBase<Iterator,IPacket>(i), size_(size) +{} + +template <class Parser, class SizeParser, class Iterator, class IPacket> +prefix_ unsigned satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::bytes() + const +{ + return Parser::bytes()*size(); +} + +template <class Parser, class SizeParser, class Iterator, class IPacket> +prefix_ void +satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::check(Iterator const & e) + const +{ + return e-this->i() >= bytes(); +} + +template <class Parser, class SizeParser, class Iterator, class IPacket> +prefix_ void satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::init() + const +{ + iterator e (end()); + for (iterator i (begin()); i!=e; ++i) i->init(); +} + +/////////////////////////////////////////////////////////////////////////// + +template <class Parser, class SizeParser, class Iterator, class IPacket> +prefix_ typename satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::size_type +satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::size() + const +{ + return size_.value(); +} + +template <class Parser, class SizeParser, class Iterator, class IPacket> +prefix_ bool satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::empty() + const +{ + return size()==0; +} + +template <class Parser, class SizeParser, class Iterator, class IPacket> +prefix_ +typename satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::iterator +satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::begin() + const +{ + return iterator(this->i()); +} + +template <class Parser, class SizeParser, class Iterator, class IPacket> +prefix_ +typename satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::iterator +satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::end() + const +{ + return iterator(this->i()+bytes()); +} + +template <class Parser, class SizeParser, class Iterator, class IPacket> +prefix_ +typename satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::range_type +satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::range() + const +{ + return std::make_pair(begin(),end()); +} + +template <class Parser, class SizeParser, class Iterator, class IPacket> +prefix_ +typename satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::range_type +satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::value() + const +{ + return range(); +} + +template <class Parser, class SizeParser, class Iterator, class IPacket> +prefix_ +typename satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::value_type +satcom::pkf::Parse_Vector<Parser,SizeParser,Iterator,IPacket>::operator[](difference_type i) + const +{ + return begin()[i]; +} + +/////////////////////////////////////////////////////////////////////////// +// satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container> + +template <class Parser, class SizeParser, class Container> +template <class P, class SP, class I, class IP> +prefix_ satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>:: +Parse_Vector_wrapper(Parse_Vector<P,SP,I,IP> const & vector, Container & container) + : i_(vector.i()-container.begin()), size_i_(vector.size_.i()-container.begin()), + container_(container) +{} + +template <class Parser, class SizeParser, class Container> +prefix_ typename satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::size_type +satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::size() + const +{ + return SizeParser(container_.begin()+size_i_).value(); +} + +template <class Parser, class SizeParser, class Container> +prefix_ bool satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::empty() + const +{ + return size() == 0; +} + +template <class Parser, class SizeParser, class Container> +prefix_ typename satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::iterator +satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::begin() + const +{ + return iterator(container_.begin() + i_); +} + +template <class Parser, class SizeParser, class Container> +prefix_ typename satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::iterator +satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::end() + const +{ + return iterator(container_.begin() + i_ + Parser::bytes()*size()); +} + +template <class Parser, class SizeParser, class Container> +prefix_ typename satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::range_type +satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::range() + const +{ + return std::make_pair(begin(), end()); +} + +template <class Parser, class SizeParser, class Container> +prefix_ typename satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::value_type +satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::operator[](difference_type i) + const +{ + return begin()[i]; +} + +template <class Parser, class SizeParser, class Container> +prefix_ void satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::shift(iterator pos, + size_type n) +{ + container_.insert(pos.raw(),n*Parser::bytes(),0); + SizeParser(container_.begin()+size_i_) += n; +} + +template <class Parser, class SizeParser, class Container> +prefix_ void satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::erase(iterator pos, + size_type n) +{ + container_.erase(pos.raw(),pos.raw()+n*Parser::bytes()); + SizeParser(container_.begin()+size_i_) -= n; +} + +template <class Parser, class SizeParser, class Container> +prefix_ void satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::erase(iterator f, + iterator l) +{ + erase(f,l-f); +} + +template <class Parser, class SizeParser, class Container> +prefix_ void satcom::pkf::Parse_Vector_wrapper<Parser,SizeParser,Container>::clear() +{ + container_.erase(container_.begin()+i_,container_.begin()+i_+size()*Parser::bytes()); + SizeParser(container_.begin()+size_i_) = 0; +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseVec.hh b/Packets/ParseVec.hh new file mode 100644 index 000000000..3b2dc3827 --- /dev/null +++ b/Packets/ParseVec.hh @@ -0,0 +1,175 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_ParseVec_ +#define HH_ParseVec_ 1 + +// Custom includes +#include <utility> // for std::pair +#include <boost/iterator/iterator_facade.hpp> +#include <boost/utility.hpp> // for boost::noncopyable +#include "ParserBase.hh" +#include "ParseArray.hh" // for Parse_Array_iterator + +//#include "ParseVec.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + template <class Parser, class SizeParser, class Container> class Parse_Vector_wrapper; + + template <class Parser, class SizeParser, class Iterator=nil, class IPacket=nil> + struct Parse_Vector : public ParserBase<Iterator,IPacket> + { + typedef typename SizeParser::template rebind<Iterator>::parser size_parser; + + /////////////////////////////////////////////////////////////////////////// + // Parser interface + + template <class I=nil, class P=nil> + struct rebind { typedef Parse_Vector<Parser,SizeParser,I,P> parser; }; + typedef Iterator byte_iterator; + + explicit Parse_Vector(SizeParser const & size); + Parse_Vector(size_parser const & size, Iterator const & i); + + unsigned bytes() const; + void check(Iterator const & e) const; + void init() const; + + /////////////////////////////////////////////////////////////////////////// + // Container interface + + typedef typename Parser::template rebind<Iterator>::parser value_type; + typedef impl::Parse_Array_iterator<value_type,Iterator> iterator; + typedef unsigned size_type; + typedef int difference_type; + typedef std::pair<iterator,iterator> range_type; + + template <class Container> + struct wrapper { typedef Parse_Vector_wrapper<value_type, size_parser, Container> t; }; + + size_type size() const; + bool empty() const; + + iterator begin() const; + iterator end() const; + range_type range() const; + range_type value() const; + + value_type operator[](difference_type i) const; + + private: + size_parser size_; + + template <class P, class SP, class C> friend class Parse_Vector_wrapper; + }; + + /** \brief + + Holds a reference to the container ! + */ + template <class Parser, class SizeParser, class Container> + class Parse_Vector_wrapper + : public boost::noncopyable + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef Container container; + typedef SizeParser size_parser; + typedef typename Parser::byte_iterator byte_iterator; + typedef Parser value_type; + typedef impl::Parse_Array_iterator<value_type,byte_iterator> iterator; + typedef unsigned size_type; + typedef int difference_type; + typedef std::pair<iterator,iterator> range_type; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + template <class P, class SP, class I, class IP> + Parse_Vector_wrapper(Parse_Vector<P,SP,I,IP> const & vector, Container & container); + + // no default constructor + // no copy + // default destructor + // no conversion constructors + + ///@} + /////////////////////////////////////////////////////////////////////////// + ///\name APacketRegistry.essors + ///@{ + + size_type size() const; + bool empty() const; + + iterator begin() const; + iterator end() const; + range_type range() const; + + value_type operator[](difference_type i) const; + + ///@} + /////////////////////////////////////////////////////////////////////////// + ///\name Mutators + ///@{ + + void shift(iterator pos, size_type n=1); + template <class Value> + void insert(iterator pos, Value const & t); + template <class Value> + void insert(iterator pos, size_type n, Value const & t); + template <class InputIterator> + void insert(iterator pos, InputIterator f, InputIterator l); + + void erase(iterator pos, size_type n=1); + void erase(iterator f, iterator l); + void clear(); + + ///@} + + protected: + + private: + + size_type i_; + size_type size_i_; + Container & container_; + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "ParseVec.cci" +#include "ParseVec.ct" +#include "ParseVec.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParseVec.test.cc b/Packets/ParseVec.test.cc new file mode 100644 index 000000000..4743c2ae8 --- /dev/null +++ b/Packets/ParseVec.test.cc @@ -0,0 +1,153 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Unit tests + +//#include "ParseVec.test.hh" +//#include "ParseVec.test.ih" + +// Custom includes +#include "ParseVec.hh" +#include "ParseInt.hh" + +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> +#include <boost/assign.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::pkf; + +BOOST_AUTO_UNIT_TEST(parseVec_test) +{ + unsigned char data[] = { 0x03, // size + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, // data + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25 }; + typedef unsigned char * iterator; + typedef Parse_Vector<Parse_UInt16<>,Parse_UInt8<>,iterator> Parse_UInt16Vec; + + Parse_UInt8<iterator> sizeParser (data); + Parse_UInt16Vec v (sizeParser, data+1); + + BOOST_CHECK_EQUAL( v[0], 0x1011 ); + BOOST_CHECK_EQUAL( v[2], 0x1415 ); + BOOST_CHECK_EQUAL( v.size(), 3u ); + BOOST_CHECK_EQUAL( v.bytes(), 6u ); + data[0] = 0x06; + BOOST_CHECK_EQUAL( v.size(), 6u ); + BOOST_CHECK_EQUAL( v.bytes(), 12u ); + + iterator i (data+1); + Parse_UInt16Vec::iterator j (v.begin()); + Parse_UInt16Vec::iterator e (v.end()); + for (;j!=e;++j, i+=2) + BOOST_CHECK_EQUAL( Parse_UInt16<iterator>(i), *j ); + BOOST_CHECK_EQUAL(i, data+13); +} + +BOOST_AUTO_UNIT_TEST(parseVec_wrapper) +{ + typedef std::vector<unsigned char> Container; + typedef Container::iterator iterator; + typedef Parse_UInt8<iterator> Parse_Size; + typedef Parse_Vector<Parse_UInt16<>,Parse_Size,iterator> Parse_UInt16Vec; + typedef Parse_UInt16Vec::wrapper<Container>::t Parse_UInt16VecWrap; + + using namespace boost::assign; + + Container data; + data += + 0x03, // size + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, // data + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25; + + Parse_Size sizeParser (data.begin()); + Parse_UInt16Vec v (sizeParser, data.begin()+1); + Parse_UInt16VecWrap w (v,data); + + BOOST_CHECK_EQUAL( w[0], 0x1011 ); + BOOST_CHECK_EQUAL( w[2], 0x1415 ); + BOOST_CHECK_EQUAL( w.size(), 3u ); + data[0] = 0x06; + BOOST_CHECK_EQUAL( w.size(), 6u ); + + { + iterator i (data.begin()+1); + Parse_UInt16VecWrap::iterator j (w.begin()); + Parse_UInt16VecWrap::iterator e (w.end()); + for (;j!=e;++j, i+=2) + BOOST_CHECK_EQUAL( Parse_UInt16<iterator>(i), *j ); + BOOST_CHECK_EQUAL(data.end()-i, 0); + } + + w.shift(w.begin()+1); + BOOST_CHECK_EQUAL( w.size(), 7u ); + BOOST_CHECK_EQUAL( w[0], 0x1011 ); + BOOST_CHECK_EQUAL( w[1], 0 ); + BOOST_CHECK_EQUAL( w[2], 0x1213 ); + + w.insert(w.begin()+3, 2u, 0xfffe); + BOOST_CHECK_EQUAL( w.size(), 9u ); + BOOST_CHECK_EQUAL( w[2], 0x1213 ); + BOOST_CHECK_EQUAL( w[3], 0xfffe ); + BOOST_CHECK_EQUAL( w[4], 0xfffe ); + BOOST_CHECK_EQUAL( w[5], 0x1415 ); + + w.erase(w.begin()+3, w.begin()+5); + BOOST_CHECK_EQUAL( w.size(), 7u ); + + w.erase(w.begin()+1); + BOOST_CHECK_EQUAL( w.size(), 6u ); + + { + iterator i (data.begin()+1); + Parse_UInt16VecWrap::iterator j (w.begin()); + Parse_UInt16VecWrap::iterator e (w.end()); + for (;j!=e;++j, i+=2) + BOOST_CHECK_EQUAL( Parse_UInt16<iterator>(i), *j ); + BOOST_CHECK_EQUAL(data.end()-i, 0); + } + + w.clear(); + BOOST_CHECK_EQUAL( w.size(), 0u ); + BOOST_CHECK( w.begin() == w.end() ); + BOOST_CHECK_EQUAL( data.size(), 1u ); +} + +// This really belongs into ParserBase.test.cc but it's simpler here +BOOST_AUTO_UNIT_TEST(parserTraits_test) +{ + // Really, this could be checked by BOOST_STATIC_ASSERT since + // it's compile-time ... + BOOST_CHECK( Parser_traits< Parse_UInt32<> >::fixed_size ); + BOOST_CHECK( (! Parser_traits< Parse_Vector< Parse_UInt16<>,Parse_UInt16<> > >::fixed_size) ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParserBase.cti b/Packets/ParserBase.cti new file mode 100644 index 000000000..5ba7367e8 --- /dev/null +++ b/Packets/ParserBase.cti @@ -0,0 +1,96 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +//#include "ParserBase.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <class Iterator, class IPacket> +prefix_ Iterator satcom::pkf::ParserBase<Iterator,IPacket>::i() + const +{ + return static_cast<IPacket const *>(this)->begin(); +} + +template <class Iterator> +prefix_ satcom::pkf::ParserBase<Iterator,satcom::pkf::nil>::ParserBase(Iterator const & i) + : i_(i) +{} + +template <class Iterator> +prefix_ Iterator satcom::pkf::ParserBase<Iterator,satcom::pkf::nil>::i() + const +{ + return i_; +} + +template <class Parser, class Iterator> +prefix_ bool satcom::pkf::impl::check(Iterator const & b, Iterator const & e, + impl::ParserBase *) +{ + return impl::ParserCheck<Parser,Parser_traits<Parser>::fixed_size>::check(b,e); +} + +template <class Parser, class Iterator> +prefix_ bool satcom::pkf::impl::check(Iterator const & b, Iterator const & e, + void *) +{ + return Parser::check(b,e); +} + +template <class Parser, class Iterator> +prefix_ bool satcom::pkf::check(Iterator const & b, Iterator const & e) +{ + return impl::check<Parser,Iterator>(b,e,static_cast<Parser*>(0)); +} + +template <class Parser> +prefix_ unsigned satcom::pkf::impl::min_bytes(impl::ParserBase *) +{ + return impl::ParserMinBytes<Parser,Parser_traits<Parser>::fixed_size>::bytes(); +} + +template <class Parser> +prefix_ unsigned satcom::pkf::impl::min_bytes(void *) +{ + return 0; +} + +template <class Parser> +prefix_ unsigned satcom::pkf::min_bytes() +{ + return impl::min_bytes<Parser>(static_cast<Parser*>(0)); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParserBase.hh b/Packets/ParserBase.hh new file mode 100644 index 000000000..69508b7cd --- /dev/null +++ b/Packets/ParserBase.hh @@ -0,0 +1,296 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief Parser framework + */ + +#ifndef HH_ParserBase_ +#define HH_ParserBase_ 1 + +// Custom includes +#include <utility> +#include <boost/type_traits/is_member_function_pointer.hpp> + +#include "ParserBase.ih" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + namespace impl { struct ParserBase; } + + struct nil {}; + + /** \brief Parser framework + + This class is the baseclass for all parser classes of the + parser framework. The parser framework is used to interpret + byte-oriented data from arbitrary random access iterators. The + framework is hierarchical in the sense, that parsers can be + arbitrarily nested. + + All parser framework classes are as lightweight as + possible. Most parser classes only have a single iterator as + data member and (depending on the container) therefore have + the same size as a single pointer. Parsers are therefore + conceptually and in essence simply pointers decorated with + type information. + + It is very important for parser classes to be lightweight and + to have only simple constructors since parsers are passed + around by value. Parser instances most of the time are + temporaries. However, since they are only 'decorated' + pointers, this should not have any performance impact. + + To implement a new parser, write a template implementing the + following members: + + \code + template <class Iterator=nil, class IPacket=nil> + struct Parser_Example + : protected satcom::pkf::ParserBase<Iterator,IPacket> + { + // fixed interface of all parser classes + + template <class I=nil, class P=nil> + struct rebind { typedef Parse_Example<I,P> parser; } + typedef Iterator byte_iterator; + + Parse_Example() {} + Parse_Example(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + [static] unsigned bytes() + { + // return the size of the parsed header. This + // method must be declared static if the size is + // constant, otherwise it must be a non-static + // member + return 14; + } + + static bool check(Iterator const & begin, Iterator const & end) + { + BOOST_ASSERT( end>=begin ); + // return true, if the data in the range [begin,end) + // can be safely interpreted by the parser without + // causing invalid memory access. This means, + // check, wether the data is truncated + return static_cast<unsigned>(end-begin) >= bytes(); + } + + // optional, only needed if bytes() is non-static + static unsigned min_bytes() + { + // return the minimum size of the header. This + // is the amount of space needed to allocate + // an otherwise empty packet + return 10; + } + + // optional + void init() + { + // initialize the packet if necessary + } + + // optional + void init(Iterator b, Iterator e) + { + // initialize the packet with given payload + } + + // example methods to parse fields + + typedef Parse_UInt16 < Iterator > Parse_Field1; + typedef Parse_Array < 3, Parse_UInt32<>, Iterator > Parser_Field2 + + Parse_Field1 field1() const { return Parse_Field1 (this->i()); } + Parse_Field2 field2() const { return Parse_Field2 (this->i()+2); } + }; + \endcode + + Every parser must have some mandatory fixed members which are: + + - struct rebind: This structure allows the parser to be + converted to a parser of the same type but with a different + iterator. Parser may have more than the two standard + template parameters. These parameters must then be added in + front of the standard parameters. The rebind structure must + however always have only two parameters. Additional + parameters must be provided from the outside template + + - byte_iterator: A typedef for the Iterator class used + + - Non Iterator constructor: This constructor is only used when + the parser is inherited into a Packet class. + + - Iterator constructor: This constructor must call the + corresponding ParserBase constructor. + + - unsigned bytes() member: This member must return the number + of bytes the parser interprets. This will be the size of the + implemented header. If the header has a fixed size, this + member must be static, if it is dynamic the member must be + non-static + + - static bool check(Iterator b, Iterator e) member: This + method must return true \e only if the range [b,e) contains + a \e complete packet, that is, e-b >= bytes(). However, the + call to bytes() might involve accessing data bytes which + might not exist. The bytes() call cannot check this (it has + no access to the \e end of the valid range). To keep the + performance up, the validity check is performed once. The + parser has to ensure, that validity is maintained even when + changing the values. Validity in this context does not + imply, that the packet is semantically correct, it only + implies, that the packet can be parsed without risking + invalid memory access. + + - The min_bytes() member is optional. It is only used, if the + Parser implements a non-fixed-size Packet, that is, if the + bytes() member is non-static. In this case, min_bytes() has + to be implemented and must return the amount of space + necessary to construct an empty instance. The construction + will proceed by first allocating the necessary space + somewhere, initializing this space with all zeros. Then a + Parser instance is created at that space and the Parsers + init() method is called. + + - The init() member is optional. If all-zero initialization of + a new Packet is enough, this member can be + skipped. Otherwise, the init() member can assume to have + access to a min_buytes() sized area which is all-zero + initialized. + + - The init(Packet::ptr payload) member is optional. By default + it just calls the init() member. Here, special + initialization regarding the payload may be done. As for + min_bytes(Packet::ptr), the argument type is allowed to be + templatized or may be a specific packet ptr thereby + restricting the permissible payload packet types. + + - The parser then contains any additional methods to parse the + header constituents. + + ParserBase provides the parser classes with access to the + packet iterator. This class is templatized on the Iterator + type and an optional baseclass type. + + If the baseclass is given, it is used to access the iterator + directly using 'begin'. If it is not given, the instance has + to be constructed with an iterator. + + This implementation ensures, that a parser can either be + inherited into a Packet class or be used as a temporary. + */ + template <class Iterator, class IPacket=nil> + class ParserBase : public impl::ParserBase + { + public: + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + // default default constructor + // default copy constructor + // default copy assignment + // default destructor + // no conversion constructors + + ///@} + /////////////////////////////////////////////////////////////////////////// + + Iterator i() const; + static void init() {}; + + private: + + }; + + template <class Iterator> + class ParserBase<Iterator,nil> : public impl::ParserBase + { + public: + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + explicit ParserBase(Iterator const & i); + + // no default constructor + // default copy constructor + // default copy assignment + // default destructor + // no conversion constructors + + ///@} + /////////////////////////////////////////////////////////////////////////// + + Iterator i() const; + static void init() {} + template <class SomePacket> + static void init(typename SomePacket::ptr) {} + + private: + + Iterator i_; + }; + + /** \brief Addtiional Parser information + + Parser_traits provids abstract information about an unknown + parser. Besides the information already available within the + Parser it provides an additional 'fixed_sized' member which is + true if and only if the Parser has a static bytes() member. + */ + template <class Parser> + struct Parser_traits { + typedef Parser parser; + typedef typename Parser::byte_iterator byte_iterator; + static const bool fixed_size = impl::Parser_traits_fixed_size<Parser>::fixed_size; + + template <class I=nil, class P=nil> + struct rebind { + typedef typename Parser::template rebind<I,P>::parser parser; + }; + }; + + template <class Parser, class Iterator> + bool check(Iterator const & b, Iterator const & e); + + template <class Parser> + unsigned min_bytes(); + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "ParserBase.cci" +//#include "ParserBase.ct" +#include "ParserBase.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParserBase.ih b/Packets/ParserBase.ih new file mode 100644 index 000000000..3cb5eb129 --- /dev/null +++ b/Packets/ParserBase.ih @@ -0,0 +1,99 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef IH_ParserBase_ +#define IH_ParserBase_ 1 + +// Custom includes + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { +namespace impl { + + struct ParserBase {}; + + template <unsigned N> + struct Parser_traits_sentinel + { int v[N]; }; + + template <class Parser> + struct Parser_traits_fixed_size { + // This differentiates between bytes being a static or + // non-static member of Parser ... + static const bool fixed_size = sizeof( + Parser_traits_fixed_size_check(&Parser::bytes))-sizeof(Parser_traits_sentinel<1>); + }; + + template <class T> + Parser_traits_sentinel<2> Parser_traits_fixed_size_check(T); + + template <class R,class T> + Parser_traits_sentinel<1> Parser_traits_fixed_size_check(R (T::*)()); + + template <class Parser, class Iterator> + bool check(Iterator const & b, Iterator const & e, ParserBase *); + + template <class Parser, class Iterator> + bool check(Iterator const & b, Iterator const & e, void *); + + template <class Parser, bool Fixed> + struct ParserCheck { + template <class Iterator> + static unsigned check(Iterator const & b, Iterator const & e) + { return Parser::check(b,e); } + }; + + template <class Parser> + struct ParserCheck<Parser,true> { + template <class Iterator> + static unsigned check(Iterator const & b, Iterator const & e) + { return unsigned(e-b) >= Parser::bytes(); } + }; + + template <class Parser> + unsigned min_bytes(ParserBase *); + + template <class Parser> + unsigned min_bytes(void *); + + template <class Parser, bool Fixed> + struct ParserMinBytes { + static unsigned bytes() { return Parser::min_bytes(); } + }; + + template <class Parser> + struct ParserMinBytes<Parser,true> { + static unsigned bytes() { return Parser::bytes(); } + }; + +}}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/ParserBase.test.cc b/Packets/ParserBase.test.cc new file mode 100644 index 000000000..dca6b77b2 --- /dev/null +++ b/Packets/ParserBase.test.cc @@ -0,0 +1,104 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Unit tests + +//#include "ParserBase.test.hh" +//#include "ParserBase.test.ih" + +// Custom includes +#include "ParserBase.hh" +#include "Packet.hh" + +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace pkf = satcom::pkf; + +// The non-inherited Version is extensively tested in PaseInt.test.hh + +BOOST_AUTO_UNIT_TEST(parserBase_inherited) +{ + // TODO: Implement +} + +namespace { + + template <class Iterator=pkf::nil, class IPacket=pkf::nil> + struct Parse_Test : public pkf::ParserBase<Iterator,IPacket> + { + template <class I=pkf::nil, class P=pkf::nil> + struct rebind { typedef Parse_Test<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_Test() {} + Parse_Test(Iterator const & i) : pkf::ParserBase<Iterator,IPacket>(i) {} + + static unsigned bytes() { return 14; } + + /////////////////////////////////////////////////////////////////////////// + + }; + + template <class Iterator=pkf::nil, class IPacket=pkf::nil> + struct Parse_Test2 : public pkf::ParserBase<Iterator,IPacket> + { + template <class I=pkf::nil, class P=pkf::nil> + struct rebind { typedef Parse_Test<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_Test2() {} + Parse_Test2(Iterator const & i) : pkf::ParserBase<Iterator,IPacket>(i) {} + + unsigned bytes() const { return 14; } + static unsigned check(Iterator a, Iterator b) + { return true; } + static unsigned min_bytes() { return 10; } + + /////////////////////////////////////////////////////////////////////////// + + }; + +} + +BOOST_AUTO_UNIT_TEST(parserBase_construction) +{ + BOOST_CHECK_EQUAL( pkf::min_bytes< Parse_Test<int> >(), 14u ); + BOOST_CHECK( pkf::check< Parse_Test<int> >(0,14) ); + BOOST_CHECK( ! pkf::check< Parse_Test<int> >(2,15) ); + + BOOST_CHECK_EQUAL( pkf::min_bytes< Parse_Test2<int> >(), 10u ); + BOOST_CHECK( pkf::check< Parse_Test2<int> >(2,13) ); + BOOST_CHECK( pkf::check< Parse_Test2<int> >(2,12) ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/RTCPPacket.cc b/Packets/RTCPPacket.cc new file mode 100644 index 000000000..f50b44dc1 --- /dev/null +++ b/Packets/RTCPPacket.cc @@ -0,0 +1,51 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline non-template functions + +#include "RTCPPacket.hh" +//#include "RTCPPacket.ih" + +// Custom includes + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + + +prefix_ void satcom::pkf::RTCPPacket::v_nextInterpreter() + const +{ + registerInterpreter<DataPacket>(begin()+bytes(),end()); +} + +prefix_ void satcom::pkf::RTCPPacket::v_finalize() +{} + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/RTCPPacket.cti b/Packets/RTCPPacket.cti new file mode 100644 index 000000000..a652af010 --- /dev/null +++ b/Packets/RTCPPacket.cti @@ -0,0 +1,44 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +//#include "RTCPPacket.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <class Arg> +prefix_ satcom::pkf::RTCPPacket::RTCPPacket(Arg const & arg) + : Packet(arg) +{} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/RTCPPacket.hh b/Packets/RTCPPacket.hh new file mode 100644 index 000000000..2518110de --- /dev/null +++ b/Packets/RTCPPacket.hh @@ -0,0 +1,315 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version.b +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_RTCPPacket_ +#define HH_RTCPPacket_ 1 + +// Custom includes +#include "Packet.hh" +#include "ParseInt.hh" +#include "ParseArray.hh" +#include "ParseListS.hh" +#include "ParseVec.hh" +#include "PacketRegistry.hh" + +//#include "RTCPPacket.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + template <class I=nil,class P=nil> struct Parse_RTCP_RR; + template <class I=nil,class P=nil> struct Parse_RTCP_SR; + template <class I=nil,class P=nil> struct Parse_RTCP_SDES; + template <class I=nil,class P=nil> struct Parse_RTCP_BYE; + template <class I=nil,class P=nil> struct Parse_RTCP_APP; + + + template <class Iterator=nil, class IPacket=nil> + struct Parse_RTCP : public ParserBase<Iterator,IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_RTCP<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP() {} + Parse_RTCP(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UIntField < 0, 2, Iterator > Parse_Version; + typedef Parse_Flag < 2, Iterator > Parse_P; + typedef Parse_UIntField < 3, 8, Iterator > Parse_Count; + typedef Parse_UInt8 < Iterator > Parse_PT; + typedef Parse_UInt16 < Iterator > Parse_Length; + + typedef Parse_RTCP_RR < Iterator > Parse_RTCP_RR; + typedef Parse_RTCP_SR < Iterator > Parse_RTCP_SR; + typedef Parse_RTCP_SDES < Iterator > Parse_RTCP_SDES; + typedef Parse_RTCP_BYE < Iterator > Parse_RTCP_BYE; + typedef Parse_RTCP_APP < Iterator > Parse_RTCP_APP; + + Parse_Version version() const { return Parse_Version (this->i() ); } + Parse_P padding() const { return Parse_P (this->i() ); } + Parse_Count count() const { return Parse_Count (this->i() ); } + Parse_PT payloadType() const { return Parse_PT (this->i() + 1 ); } + Parse_Length length() const { return Parse_Length (this->i() + 2 ); } + + Parse_RTCP_RR rr() { return Parse_RTCP_RR (this->i() ); } + Parse_RTCP_SR sr() { return Parse_RTCP_SR (this->i() ); } + Parse_RTCP_SDES sdes() { return Parse_RTCP_SDES (this->i() ); } + Parse_RTCP_BYE bye() { return Parse_RTCP_BYE (this->i() ); } + Parse_RTCP_APP app() { return Parse_RTCP_APP (this->i() ); } + + /////////////////////////////////////////////////////////////////////////// + + unsigned int bytes() const { return 32 + (4 * length()); } + static bool check(Iterator const & b, Iterator const & e) + { return e-b >= 4 and unsigned(e-b) >= Parse_RTCP<Iterator>(b).bytes(); } + + }; + + template <class Iterator=nil, class IPacket=nil> + struct Parse_RTCP_RB : public ParserBase<Iterator,IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_RTCP_RB<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_RB() {} + Parse_RTCP_RB(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt32 < Iterator > Parse_32bit; + typedef Parse_UInt8 < Iterator > Parse_8bit; + typedef Parse_Array < 3, Parse_UInt8<>, Iterator > Parse_24bit; + + Parse_32bit ssrc() const { return Parse_32bit(this->i() ); } + Parse_8bit fragLost() const { return Parse_8bit(this->i()+4 ); } + Parse_24bit cnpl() const { return Parse_24bit(this->i()+5 ); } + Parse_32bit ehsnr() const { return Parse_32bit(this->i()+8 ); } + Parse_32bit LSR() const { return Parse_32bit(this->i()+12); } + Parse_32bit DLSR() const { return Parse_32bit(this->i()+16); } + + /////////////////////////////////////////////////////////////////////////// + + static unsigned int bytes() { return 20; } + + }; + + template <class Iterator, class IPacket> + struct Parse_RTCP_RR : public Parse_RTCP<Iterator, IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_RTCP_RR<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_RR() {} + Parse_RTCP_RR(Iterator const & i) : Parse_RTCP<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt32 < Iterator > Parse_32bit; + typedef Parse_Vector < Parse_RTCP_RB<>, typename Parse_RTCP<Iterator,IPacket>::Parse_Count, Iterator > Parse_rbVec; + + Parse_32bit ssrc() const { return Parse_32bit(this->i()+ 4 ); } + + Parse_32bit ntp_msb() const { return Parse_32bit(this->i()+ 8 ); } + Parse_32bit ntp_lsb() const { return Parse_32bit(this->i()+ 12 ); } + Parse_32bit timestamp() const { return Parse_32bit(this->i()+ 16 ); } + Parse_32bit spcount() const { return Parse_32bit(this->i()+ 20 ); } + Parse_32bit socount() const { return Parse_32bit(this->i()+ 24 ); } + + Parse_rbVec rbVec() const { return Parse_rbVec(this->count(), this->i() + 28 ); } + + }; + + template <class Iterator, class IPacket> + struct Parse_RTCP_SR : public Parse_RTCP<Iterator, IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_RTCP_SR<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_SR() {} + Parse_RTCP_SR(Iterator const & i) : Parse_RTCP<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt32 < Iterator > Parse_32bit; + typedef Parse_Vector < Parse_RTCP_RB<>, typename Parse_RTCP<Iterator,IPacket>::Parse_Count, Iterator > Parse_rbVec; + + Parse_32bit ssrc() const { return Parse_32bit(this->i()+ 4 ); } + Parse_rbVec rbVec() const { return Parse_rbVec(this->count(), this->i() + 8 ); } + + }; + + template <class Iterator=nil, class IPacket=nil> + struct Parse_RTCP_item : public Parse_RTCP<Iterator,IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_RTCP_item<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_item() {} + Parse_RTCP_item(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt8 < Iterator > Parse_8bit; + typedef Parse_UInt32 < Iterator > Parse_32bit; + typedef Parse_Vector < Parse_UInt8<>, Parse_UInt8<>, Iterator > Parse_desc; + + Parse_8bit typeField() const { return Parse_8bit(this->i() ); } + Parse_8bit length() const { return Parse_8bit(this->i()+1 ); } + Parse_desc desc() const { return Parse_desc(this->length(), this->i()+2 ); } + + + + }; + + template <class List> + struct Sentinel_EmptyList { + static bool check(List a) { return a.empty(); } + }; + + template <class Iterator=nil, class IPacket=nil> + struct Parse_RTCP_chunk : public Parse_RTCP<Iterator, IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_RTCP_chunk<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_chunk() {} + Parse_RTCP_chunk(Iterator const & i) : Parse_RTCP<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt32 < Iterator > Parse_32bit; + typedef Parse_UInt8 < Iterator > Parse_8bit; + typedef Parse_ListS < Parse_RTCP_item<>, Sentinel_EmptyList<Parse_RTCP_item<> >, Iterator, IPacket> Parse_itemList; + + Parse_32bit ssrc() const { return Parse_32bit(this->i() ); } + Parse_itemList itemList() const { return Parse_itemList(this->i() + 4 ); } + + }; + + + template <class Iterator, class IPacket> + struct Parse_RTCP_SDES : public Parse_RTCP<Iterator, IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_RTCP_SDES<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_SDES() {} + Parse_RTCP_SDES(Iterator const & i) : Parse_RTCP<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_Vector < Parse_RTCP_chunk<>, typename Parse_RTCP<Iterator,IPacket>::Parse_Count, Iterator > Parse_chunkVec; + + Parse_chunkVec chunkVec() const { return Parse_chunkVec(this->count(), this->i()+4 ); } + + }; + + template <class Iterator, class IPacket> + struct Parse_RTCP_BYE : public Parse_RTCP<Iterator,IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_RTCP_BYE<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_BYE() {} + Parse_RTCP_BYE(Iterator const & i) : Parse_RTCP<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_Vector < Parse_UInt32<>, typename Parse_RTCP<Iterator,IPacket>::Parse_Count, Iterator > Parse_ssrcVec; + + Parse_ssrcVec ssrcVec() const { return Parse_ssrcVec(this->count(), this->i()+4 ); } + + }; + + + template <class Iterator, class IPacket> + struct Parse_RTCP_APP : public Parse_RTCP<Iterator,IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_RTCP_APP<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_APP() {} + Parse_RTCP_APP(Iterator const & i) : Parse_RTCP<Iterator,IPacket>(i) {} + + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt32 < Iterator > Parse_32bit; + typedef Parse_Vector < Parse_UInt32<>, typename Parse_RTCP<Iterator,IPacket>::Parse_Length, Iterator > Parse_dataVec; + + Parse_32bit ssrc() const { return Parse_32bit(this->i()+4); } + Parse_32bit name() const { return Parse_32bit(this->i()+8); } +// this->length()-3 + Parse_dataVec appData() const { return Parse_dataVec(this->length(), this->i()+12 ); } + + }; + + + class RTCPPacket + : public Packet, + public Parse_RTCP<Packet::iterator, RTCPPacket> + { + using Packet::registerInterpreter; + + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t<RTCPPacket>::ptr ptr; + + private: + template <class Arg> + RTCPPacket(Arg const & arg); + + virtual void v_nextInterpreter() const; + virtual void v_finalize(); + + friend class Packet; + }; + +}} + + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "RTCPPacket.cci" +//#include "RTCPPacket.ct" +#include "RTCPPacket.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/RTCPPacket.test.cc b/Packets/RTCPPacket.test.cc new file mode 100644 index 000000000..86e0d0a1e --- /dev/null +++ b/Packets/RTCPPacket.test.cc @@ -0,0 +1,339 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Unit tests + +//#include "RTCPPacket.test.hh" +//#include "RTCPPacket.test.ih" + +// Custom includes +#include "RTCPPacket.hh" + +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::pkf; + +BOOST_AUTO_UNIT_TEST(rtcpPacket_parser) +{ + + // RTCP RR (no RB) + unsigned char data_1[] = { + 0x80, 0xc8, 0x00, 0x06, + 0xe5, 0x70, 0xaa, 0x18, + 0xc7, 0xc2, 0xb2, 0x00, + 0xc3, 0xd7, 0x0e, 0x96, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x0d, 0xc8 + + }; + + typedef unsigned char * iterator_1; + Parse_RTCP<iterator_1> p_1(data_1); + + BOOST_CHECK_EQUAL( p_1.version(), 2u ); + BOOST_CHECK_EQUAL( p_1.padding(), 0 ); + BOOST_CHECK_EQUAL( p_1.count(), 0u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_1.payloadType()), 200u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_1.length()), 0x0006u ); + + BOOST_CHECK_EQUAL(p_1.rr().ssrc(), 0xe570aa18u ); + + BOOST_CHECK_EQUAL(p_1.rr().ntp_msb(), 0xc7c2b200u ); + BOOST_CHECK_EQUAL(p_1.rr().ntp_lsb(), 0xc3d70e96u ); + BOOST_CHECK_EQUAL(p_1.rr().timestamp(), 0x00u ); + BOOST_CHECK_EQUAL(p_1.rr().spcount(), 0x01u ); + BOOST_CHECK_EQUAL(p_1.rr().socount(), 0x0dc8u ); + + + // TODO RTCP RR + unsigned char data_2[] = { + 0x82, 0xc8, 0x00, 0x06, + 0xe5, 0x70, 0xaa, 0x18, + 0xc7, 0xc2, 0xb2, 0x00, + 0xc3, 0xd7, 0x0e, 0x96, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x0d, 0xc8, + + 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, + 0x20, 0x21, 0x22, 0x23, + + 0x99, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, + 0x20, 0x21, 0x22, 0x23 + + }; + + typedef unsigned char * iterator_2; + Parse_RTCP<iterator_2> p_2(data_2); + + BOOST_CHECK_EQUAL( p_2.version(), 2u ); + BOOST_CHECK_EQUAL( p_2.padding(), 0 ); + BOOST_CHECK_EQUAL( p_2.count(), 2u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_2.payloadType()), 200u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_2.length()), 0x0006u ); + + BOOST_CHECK_EQUAL(p_2.rr().ssrc(), 0xe570aa18u ); + + BOOST_CHECK_EQUAL(p_2.rr().ntp_msb(), 0xc7c2b200u ); + BOOST_CHECK_EQUAL(p_2.rr().ntp_lsb(), 0xc3d70e96u ); + BOOST_CHECK_EQUAL(p_2.rr().timestamp(), 0x00u ); + BOOST_CHECK_EQUAL(p_2.rr().spcount(), 0x01u ); + BOOST_CHECK_EQUAL(p_2.rr().socount(), 0x0dc8u ); + + BOOST_CHECK_EQUAL( p_2.rr().rbVec().size(), 0x02u ); + + + BOOST_CHECK_EQUAL( p_2.rr().rbVec().begin()->ssrc(), 0x01020304u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_2.rr().rbVec().begin()->fragLost()), 0x05u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_2.rr().rbVec().begin()->cnpl()[0]), 0x06u ); + BOOST_CHECK_EQUAL( p_2.rr().rbVec().begin()->ehsnr(), 0x09101112u ); + BOOST_CHECK_EQUAL( p_2.rr().rbVec().begin()->LSR(), 0x13141516u ); + BOOST_CHECK_EQUAL( p_2.rr().rbVec().begin()->DLSR(), 0x20212223u ); + + typedef unsigned char * iterator; + typedef Parse_UIntField < 3, 8, iterator > Parse_Count; + typedef Parse_Vector < Parse_RTCP_RB<>, Parse_Count, iterator > Parse_rbVec; + + Parse_rbVec::iterator j_2 (p_2.rr().rbVec().begin()); + + BOOST_CHECK_EQUAL( j_2->ssrc(), 0x01020304u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(j_2->fragLost()), 0x05u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(j_2->cnpl()[0]), 0x06u ); + BOOST_CHECK_EQUAL( j_2->ehsnr(), 0x09101112u ); + BOOST_CHECK_EQUAL( j_2->LSR(), 0x13141516u ); + BOOST_CHECK_EQUAL( j_2->DLSR(), 0x20212223u ); + + ++j_2; + + BOOST_CHECK_EQUAL( j_2->ssrc(), 0x99020304u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(j_2->fragLost()), 0x05u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(j_2->cnpl()[0]), 0x06u ); + BOOST_CHECK_EQUAL( j_2->ehsnr(), 0x09101112u ); + BOOST_CHECK_EQUAL( j_2->LSR(), 0x13141516u ); + BOOST_CHECK_EQUAL( j_2->DLSR(), 0x20212223u ); + + + + + + + // RTCP SR + unsigned char data_3[] = { + 0x82, 0xc9, 0x00, 0x06, + 0xe5, 0x70, 0xaa, 0x18, + + 0x99, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, + 0x20, 0x21, 0x22, 0x23, + + 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x10, 0x11, 0x12, + 0x13, 0x14, 0x15, 0x16, + 0x20, 0x21, 0x22, 0x23 + + }; + + typedef unsigned char * iterator_3; + Parse_RTCP<iterator_3> p_3(data_3); + + BOOST_CHECK_EQUAL( p_3.version(), 2u ); + BOOST_CHECK_EQUAL( p_3.padding(), 0 ); + BOOST_CHECK_EQUAL( p_3.count(), 2u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_3.payloadType()), 201u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_3.length()), 0x0006u ); + + BOOST_CHECK_EQUAL( p_3.sr().ssrc(), 0xe570aa18u ); + BOOST_CHECK_EQUAL( p_3.sr().rbVec().size(), 0x02u ); + + + typedef unsigned char * iterator; + typedef Parse_UIntField < 3, 8, iterator > Parse_Count; + typedef Parse_Vector < Parse_RTCP_RB<>, Parse_Count, iterator > Parse_rbVec; + + Parse_rbVec::iterator j (p_3.rr().rbVec().begin()); + BOOST_CHECK_EQUAL( j->ssrc(), 0x01020304u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(j->fragLost()), 0x05u ); + BOOST_CHECK_EQUAL( j->ehsnr(), 0x09101112u ); + BOOST_CHECK_EQUAL( j->LSR(), 0x13141516u ); + BOOST_CHECK_EQUAL( j->DLSR(), 0x20212223u ); + + ++j; + +#if 0 + BOOST_CHECK_EQUAL( j->ssrc(), 0x99020304u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(j->fragLost()), 0x05u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(j->cnpl()[0]), 0x06u ); + BOOST_CHECK_EQUAL( j->ehsnr(), 0x09101112u ); + BOOST_CHECK_EQUAL( j->LSR(), 0x13141516u ); + BOOST_CHECK_EQUAL( j->DLSR(), 0x20212223u ); +#endif + + // TODO RTCP SDES + + unsigned char data_4[] = { + 0x81, 0xca, 0x00, 0x04, + 0xe5, 0x70, 0xaa, 0x18, + 0x01, 0x09, 0x39, 0x30, + 0x31, 0x31, 0x33, 0x35, + 0x37, 0x36, 0x37, 0x00 + + }; + + typedef unsigned char * iterator_4; + Parse_RTCP<iterator_4> p_4(data_4); + + BOOST_CHECK_EQUAL( p_4.version(), 2u ); + BOOST_CHECK_EQUAL( p_4.padding(), 0 ); + BOOST_CHECK_EQUAL( p_4.count(), 1u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_4.payloadType()), 202u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_4.length()), 0x0004u ); + + BOOST_CHECK_EQUAL( p_4.sdes().chunkVec().size(), 0x01u ); +#if 0 + Parse_RTCP_SDES::Parse_itemList::iterator j_4 (p_4.sdes().chunkVec().begin()); + +// TODO -> ask Stefan + + // BOOST_CHECK_EQUAL( p_4.sdes().chunkList()[0].ssrc(), 0xe570aa18u); + // BOOST_CHECK_EQUAL( p_4.sdes().chunkList()[0].itemList().size(), 0x01u); + // BOOST_CHECK( p_4.sdes().chunkList()[0].itemList().check(data_4+20) ); + // BOOST_CHECK_EQUAL(p.sdes().chunkList()[0].chunkList().size(), 1); + +//item +// typeField(), 0x01u +// length(), 0x09u +// desc(), 0x393031313335373637u + +#endif + + + // RTCP BYE + unsigned char data_5[] = { + 0x82, 0xcb, 0x00, 0x06, + + 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08 + + }; + + typedef unsigned char * iterator_5; + Parse_RTCP<iterator_5> p_5(data_5); + + BOOST_CHECK_EQUAL( p_5.version(), 2u ); + BOOST_CHECK_EQUAL( p_5.padding(), 0 ); + BOOST_CHECK_EQUAL( p_5.count(), 2u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_5.payloadType()), 203u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_5.length()), 0x0006u ); + + BOOST_CHECK_EQUAL( p_5.bye().ssrcVec().size(), 0x02u ); + + BOOST_CHECK_EQUAL( p_5.bye().ssrcVec()[0], 0x01020304u ); + BOOST_CHECK_EQUAL( p_5.bye().ssrcVec()[1], 0x05060708u ); + + + // RTCP APP + unsigned char data_6[] = { + 0x82, 0x7b, 0x00, 0x05, + + 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x10, 0x11, 0x12, + 0x00, 0x00, 0x00, 0x08 + + }; + + typedef unsigned char * iterator_6; + Parse_RTCP<iterator_6> p_6(data_6); + + BOOST_CHECK_EQUAL( p_6.version(), 2u ); + BOOST_CHECK_EQUAL( p_6.padding(), 0 ); + BOOST_CHECK_EQUAL( p_6.count(), 2u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_6.payloadType()), 123u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_6.length()), 0x0005u ); + + BOOST_CHECK_EQUAL( p_6.app().ssrc(), 0x01020304u ); + BOOST_CHECK_EQUAL( p_6.app().name(), 0x05060708u ); +#if 0 + BOOST_CHECK_EQUAL( p_6.app().appData().size(), 2u ); +#endif + BOOST_CHECK_EQUAL( p_6.app().appData()[0], 0x09101112u ); + BOOST_CHECK_EQUAL( p_6.app().appData()[1], 0x08u ); + +} + + +BOOST_AUTO_UNIT_TEST(rtcpPacket_packet) +{ +#if 0 + unsigned char data_1[] = { + 0x80, 0xc8, 0x00, 0x06, + 0xe5, 0x70, 0xaa, 0x18, + 0xc7, 0xc2, 0xb2, 0x00, + 0xc3, 0xd7, 0x0e, 0x96, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x0d, 0xc8 + + }; + + RTCPPacket::ptr p_1 (Packet::create<RTCPPacket>(data_1, data_1+sizeof(data_1))); + + BOOST_CHECK_EQUAL( p_1->version(), 2u ); + BOOST_CHECK_EQUAL( p_1->padding(), 0 ); + BOOST_CHECK_EQUAL( p_1->count(), 0u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_1->payloadType()), 200u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(p_1->length()), 0x0006u ); + + BOOST_CHECK_EQUAL(p_1->rr().ssrc(), 0xe570aa18u ); + + BOOST_CHECK_EQUAL(p_1->rr().ntp_msb(), 0xc7c2b200u ); + BOOST_CHECK_EQUAL(p_1->rr().ntp_lsb(), 0xc3d70e96u ); + BOOST_CHECK_EQUAL(p_1->rr().timestamp(), 0x00u ); + BOOST_CHECK_EQUAL(p_1->rr().spcount(), 0x01u ); + BOOST_CHECK_EQUAL(p_1->rr().socount(), 0x0dc8u ); +#endif + +} + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/RTPPacket.cc b/Packets/RTPPacket.cc new file mode 100644 index 000000000..593610ae9 --- /dev/null +++ b/Packets/RTPPacket.cc @@ -0,0 +1,105 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline non-template functions + +#include "RTPPacket.hh" +//#include "RTPPacket.ih" + +// Custom includes + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + + +prefix_ void satcom::pkf::RTPPacket::v_nextInterpreter() + const +{ + + if(extension()){ + Packet::registerInterpreter<RTPUnknownExtensionPacket>(begin()+bytes(),end()); + }else{ + + int paddingOctets = 0; + if(padding()){ + paddingOctets = paddingOctet(); + } + registerInterpreter(payloadType(),begin()+bytes(),end()-paddingOctets); + } +} + +prefix_ void satcom::pkf::RTPPacket::v_finalize() +{} + +prefix_ void satcom::pkf::RTPPacket::v_dump(std::ostream & os) + const +{ + os << "RTP:\n" + << " version : " << version() << "\n" + << " padding : " << padding() << "\n" + << " extension : " << extension() << "\n" + << " csrc count : " << csrcCount() << "\n" + << " marker : " << marker() << "\n" + << " payload type : " << payloadType() << "\n" + << " sequence nr : " << seqNumber() << "\n" + << " timestamp : " << timestamp() << "\n" + << " ssrc : " << ssrc() << "\n" + << " csrc list : <not shown>\n"; +} + +prefix_ void satcom::pkf::RTPExtensionBasePacket::v_nextInterpreter() + const +{ + + // We don't want to inherit Parse_RTPExtensionBase to avoid + // virtual inheritance problems. Since we need the size of the + // extension, we just allocate ourselves a ExtensionBase parser + + Parse_RTPExtensionBase<iterator> p (begin()); + if (!p.check(begin(),end())) + throw TruncatedPacketException(); + + int paddingOctets = 0; + if(get_prev<RTPPacket>()->padding()){ + paddingOctets = get_prev<RTPPacket>()->paddingOctet(); + } + registerInterpreter(get_prev<RTPPacket>()->payloadType(),begin()+p.bytes(),end()-paddingOctets); +} + +prefix_ void satcom::pkf::RTPExtensionBasePacket::v_dump(std::ostream & os) + const +{ + os << "RTP extension packet:\n" + << " content not shown\n"; +} + +prefix_ void satcom::pkf::RTPUnknownExtensionPacket::v_finalize() +{} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/RTPPacket.cti b/Packets/RTPPacket.cti new file mode 100644 index 000000000..18633bec5 --- /dev/null +++ b/Packets/RTPPacket.cti @@ -0,0 +1,56 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +//#include "RTPPacket.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <class Arg> +prefix_ satcom::pkf::RTPPacket::RTPPacket(Arg const & arg) + : Packet(arg) +{} + +template <class Arg> +prefix_ satcom::pkf::RTPExtensionBasePacket:: +RTPExtensionBasePacket(Arg const & arg) + : Packet(arg) +{} + +template <class Arg> +prefix_ satcom::pkf::RTPUnknownExtensionPacket:: +RTPUnknownExtensionPacket(Arg const & arg) + : RTPExtensionBasePacket(arg) +{} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/RTPPacket.hh b/Packets/RTPPacket.hh new file mode 100644 index 000000000..9f4a6c787 --- /dev/null +++ b/Packets/RTPPacket.hh @@ -0,0 +1,224 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version.b +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_RTPPacket_ +#define HH_RTPPacket_ 1 + +// Custom includes +#include "Packet.hh" +#include "ParseInt.hh" +#include "ParseArray.hh" +#include "ParseVec.hh" +#include "PacketRegistry.hh" + +//#include "RTPPacket.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + template <class Iterator=nil, class IPacket=nil> + struct Parse_RTP : public ParserBase<Iterator,IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_RTP<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_RTP() {} + Parse_RTP(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UIntField < 0, 2, Iterator > Parse_Version; + typedef Parse_Flag < 2, Iterator > Parse_P; + typedef Parse_Flag < 3, Iterator > Parse_X; + typedef Parse_UIntField < 4, 8, Iterator > Parse_CC; + typedef Parse_Flag < 0, Iterator > Parse_M; + typedef Parse_UIntField < 1, 8, Iterator > Parse_PT; + typedef Parse_UInt16 < Iterator > Parse_Seq; + typedef Parse_UInt32 < Iterator > Parse_32bit; + typedef Parse_Vector < Parse_32bit, Parse_CC, Iterator > Parse_CCVec; + + Parse_Version version() const { return Parse_Version (this->i() ); } + Parse_P padding() const { return Parse_P (this->i() ); } + Parse_X extension() const { return Parse_X (this->i() ); } + Parse_CC csrcCount() const { return Parse_CC (this->i() ); } + Parse_M marker() const { return Parse_M (this->i() + 1 ); } + Parse_PT payloadType() const { return Parse_PT (this->i() + 1 ); } + Parse_Seq seqNumber() const { return Parse_Seq (this->i() + 2 ); } + Parse_32bit timestamp() const { return Parse_32bit (this->i() + 4 ); } + Parse_32bit ssrc() const { return Parse_32bit (this->i() + 8 ); } + Parse_CCVec csrcList() const { return Parse_CCVec (csrcCount(), this->i() + 12 ); } + + + + /////////////////////////////////////////////////////////////////////////// + + unsigned int bytes() const { return 12 + ( 4 * csrcCount()); } + static bool check(Iterator const & b, Iterator const & e) + { return e-b>= 12 and unsigned(e-b) >= Parse_RTP<Iterator>(b).bytes(); } + + }; + + struct RTPTypes { + typedef boost::uint16_t key_t; + }; + + class RTPPacket + : public Packet, + public Parse_RTP<Packet::iterator, RTPPacket>, + public PacketRegistryMixin<RTPTypes,RTPPacket> + { + using Packet::registerInterpreter; + using PacketRegistryMixin<RTPTypes,RTPPacket>::registerInterpreter; + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t<RTPPacket>::ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt8 < Packet::iterator > Parse_paddingOctet; + + Parse_paddingOctet paddingOctet() const { + return Parse_paddingOctet( end() -1 ); + } + + private: + template <class Arg> + RTPPacket(Arg const & arg); + + virtual void v_nextInterpreter() const; + virtual void v_finalize(); + virtual void v_dump(std::ostream & os) const; + + friend class Packet; + }; + + + + template <class Iterator=nil, class IPacket=nil> + struct Parse_RTPExtensionBase : public ParserBase<Iterator,IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_RTPExtensionBase<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_RTPExtensionBase() {} + Parse_RTPExtensionBase(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt16 < Iterator > Parse_16bit; + + Parse_16bit proDef() const { return Parse_16bit(this->i()); }; + Parse_16bit length() const { return Parse_16bit(this->i()+2); }; + + unsigned int bytes() const { return 4 + length(); } + static bool check(Iterator const & b, Iterator const & e) + { return e-b>=4 && unsigned(e-b) >= Parse_RTPExtensionBase<Iterator>(b).bytes(); } + + + }; + + class RTPExtensionBasePacket + : public Packet, + public PacketRegistryMixin<RTPTypes, RTPExtensionBasePacket> + { + using PacketRegistryMixin<RTPTypes,RTPExtensionBasePacket>::registerInterpreter; + using Packet::registerInterpreter; + public: + /////////////////////////////////////////////////////////////////////////// + typedef ptr_t<RTPExtensionBasePacket>::ptr ptr; + + protected: + template <class Arg> + RTPExtensionBasePacket(Arg const & arg); + + private: + virtual void v_nextInterpreter() const; + virtual void v_finalize() = 0; + virtual void v_dump(std::ostream & os) const; + + friend class Packet; + + }; + + + template <class Iterator=nil, class IPacket=nil> + struct Parse_RTPUnknownExtension : public Parse_RTPExtensionBase<Iterator,IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_RTPUnknownExtension<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_RTPUnknownExtension() {} + Parse_RTPUnknownExtension(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt16 < Iterator > Parse_16bit; + typedef Parse_UInt8 < Iterator > Parse_8bit; + typedef Parse_Vector < Parse_8bit, Parse_16bit, Iterator > Parse_ext; + + Parse_ext ext() const { return Parse_ext (this->length(), this->i() + 4 ); } + + }; + + class RTPUnknownExtensionPacket + : public RTPExtensionBasePacket, + public Parse_RTPUnknownExtension<Packet::iterator, RTPUnknownExtensionPacket> + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t<RTPUnknownExtensionPacket>::ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + + private: + template <class Arg> + RTPUnknownExtensionPacket(Arg const & arg); + + //virtual void v_nextInterpreter() const; + virtual void v_finalize(); + + friend class RTPExtensionBasePacket; + friend class Packet; + }; + +}} + + +///////////////////////////////hh.e//////////////////////////////////////// +//#include RTPPacket.cci" +//#include "RTPPacket.ct" +#include "RTPPacket.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/RTPPacket.test.cc b/Packets/RTPPacket.test.cc new file mode 100644 index 000000000..ff3a58d82 --- /dev/null +++ b/Packets/RTPPacket.test.cc @@ -0,0 +1,246 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Unit tests + +//#include "RTPPacket.test.hh" +//#include "RTPPacket.test.ih" + +// Custom includes +#include "RTPPacket.hh" + +#include "EthernetPacket.hh" +#include "IpV4Packet.hh" +#include "UDPPacket.hh" + +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::pkf; + +BOOST_AUTO_UNIT_TEST(rtpPacket_parser) +{ + unsigned char data[] = { 0x13, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, + + 0x11, 0x12, 0x13, 0x14, // CSRC 1 + 0x15, 0x16, 0x17, 0x18, // CSRC 2 + 0x19, 0x1A, 0x1B, 0x1C // CSRC 3 + + }; + + typedef unsigned char * iterator; + Parse_RTP<iterator> p(data); + + BOOST_CHECK_EQUAL( p.version(), 0x00u ); + BOOST_CHECK_EQUAL( p.padding(), 0 ); + BOOST_CHECK_EQUAL( p.extension(), 1 ); + BOOST_CHECK_EQUAL( p.csrcCount(), 0x03u ); + BOOST_CHECK_EQUAL( p.marker(), 0 ); + BOOST_CHECK_EQUAL( p.payloadType(), 0x02u ); + // the static_cast is to silence gcc-3.3 + BOOST_CHECK_EQUAL( static_cast<unsigned>(p.seqNumber()), 0x0304u ); + BOOST_CHECK_EQUAL( p.timestamp(), 0x05060708u ); + BOOST_CHECK_EQUAL( p.ssrc(), 0x090A0B0Cu ); + + BOOST_CHECK_EQUAL( p.csrcList()[0], 0x11121314u ); + BOOST_CHECK_EQUAL( p.csrcList()[1], 0x15161718u ); + BOOST_CHECK_EQUAL( p.csrcList()[2], 0x191A1B1Cu ); + + +} + + +BOOST_AUTO_UNIT_TEST(rtpPacket_packet) +{ + unsigned char data[] = { 0x33, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, + + 0x11, 0x12, 0x13, 0x14, // CSRC 1 + 0x15, 0x16, 0x17, 0x18, // CSRC 2 + 0x19, 0x1A, 0x1B, 0x1C, // CSRC 3 + + 0x20, 0x21, 0x00, 0x04, // ex + 0x24, 0x25, 0x26, 0x27, // ex + + 0x20, 0x21, 0x08, 0x23, // paylaod + 0x20, 0x00, 0x00, 0x03 // payload + + }; + + RTPPacket::ptr p (Packet::create<RTPPacket>(data, data+sizeof(data))); + + BOOST_CHECK_EQUAL( p->version(), 0x00u ); + BOOST_CHECK_EQUAL( p->padding(), 1 ); + BOOST_CHECK_EQUAL( p->extension(), 1 ); + BOOST_CHECK_EQUAL( p->csrcCount(), 0x03u ); + BOOST_CHECK_EQUAL( p->marker(), 0 ); + BOOST_CHECK_EQUAL( p->payloadType(), 0x02u ); + // the static_cast is to silence gcc-3.3 + BOOST_CHECK_EQUAL( static_cast<unsigned>(p->seqNumber()), 0x0304u ); + BOOST_CHECK_EQUAL( p->timestamp(), 0x05060708u ); + BOOST_CHECK_EQUAL( p->ssrc(), 0x090A0B0Cu ); + + BOOST_CHECK_EQUAL( p->paddingOctet(), 3 ); + + BOOST_CHECK_EQUAL( p->csrcList()[0], 0x11121314u ); + BOOST_CHECK_EQUAL( p->csrcList()[1], 0x15161718u ); + BOOST_CHECK_EQUAL( p->csrcList()[2], 0x191A1B1Cu ); + + BOOST_REQUIRE( p->next() ); + BOOST_CHECK( p->next()->is<RTPUnknownExtensionPacket>() ); + + RTPUnknownExtensionPacket::ptr v (p->next()->as<RTPUnknownExtensionPacket>()); + BOOST_CHECK_EQUAL( static_cast<unsigned>(v->proDef()), 0x2021u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(v->length()), 0x04u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(v->ext()[0]), 0x24u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(v->ext()[2]), 0x26u ); + + BOOST_REQUIRE( v->next() ); + DataPacket::ptr d (v->next()->as<DataPacket>()); + + BOOST_CHECK_EQUAL( d->size(), 5u ); + +} + + + +BOOST_AUTO_UNIT_TEST(eth_rtpPacket_packet) +{ + unsigned char data[] = { + + // Ethernet + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // destination MAC + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, // source MAC + 0x08, 0x00, // EtherType: IPv4 0x08 + + // IPv4 + 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x11, 0x0B, 0x0C, // EtherType: UDP 0x11 + 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, + + // UDP + 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + + // RTP + 0x33, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, + + 0x11, 0x12, 0x13, 0x14, // CSRC 1 + 0x15, 0x16, 0x17, 0x18, // CSRC 2 + 0x19, 0x1A, 0x1B, 0x1C, // CSRC 3 + + 0x20, 0x21, 0x00, 0x04, // ex + 0x24, 0x25, 0x26, 0x27, // ex + + 0x20, 0x21, 0x08, 0x23, // paylaod + 0x20, 0x00, 0x00, 0x03 // payload + + }; + + // Ethernet + EthernetPacket::ptr p (Packet::create<EthernetPacket>(data, data+sizeof(data))); + + BOOST_CHECK_EQUAL( p->destination()[3], 0x04 ); + BOOST_CHECK_EQUAL( p->source()[0], 0x07 ); + BOOST_CHECK_EQUAL( p->type(), 0x0800 ); + + // IP + BOOST_REQUIRE( p->next() ); + BOOST_CHECK( p->next()->is<IpV4Packet>() ); + + IpV4Packet::ptr ip (p->next()->as<IpV4Packet>()); + + BOOST_CHECK_EQUAL( static_cast<unsigned>(ip->protocol()), 0x11u ); + + // UDP + BOOST_REQUIRE( ip->next() ); + BOOST_CHECK( ip->next()->is<UDPPacket>() ); + + UDPPacket::ptr udp (ip->next()->as<UDPPacket>()); + + BOOST_CHECK_EQUAL( udp->source(), 0x0102 ); + BOOST_CHECK_EQUAL( udp->destination(), 0x0304 ); + BOOST_CHECK_EQUAL( udp->length(), 0x0506 ); + BOOST_CHECK_EQUAL( udp->crc(), 0x0708 ); + + + // RTP + BOOST_REQUIRE( udp->next() ); + BOOST_CHECK( udp->next()->is<DataPacket>() ); + + RTPPacket::ptr rtp (udp->next()->reinterpret<RTPPacket>()); + + BOOST_CHECK_EQUAL( rtp->version(), 0x00u ); + BOOST_CHECK_EQUAL( rtp->padding(), 1 ); + BOOST_CHECK_EQUAL( rtp->extension(), 1 ); + BOOST_CHECK_EQUAL( rtp->csrcCount(), 0x03u ); + BOOST_CHECK_EQUAL( rtp->marker(), 0 ); + BOOST_CHECK_EQUAL( rtp->payloadType(), 0x02u ); + // the static_cast is to silence gcc-3.3 + BOOST_CHECK_EQUAL( static_cast<unsigned>(rtp->seqNumber()), 0x0304u ); + BOOST_CHECK_EQUAL( rtp->timestamp(), 0x05060708u ); + BOOST_CHECK_EQUAL( rtp->ssrc(), 0x090A0B0Cu ); + + BOOST_CHECK_EQUAL( rtp->paddingOctet(), 3 ); + + BOOST_CHECK_EQUAL( rtp->csrcList()[0], 0x11121314u ); + BOOST_CHECK_EQUAL( rtp->csrcList()[1], 0x15161718u ); + BOOST_CHECK_EQUAL( rtp->csrcList()[2], 0x191A1B1Cu ); + + BOOST_REQUIRE( rtp->next() ); + BOOST_CHECK( rtp->next()->is<RTPUnknownExtensionPacket>() ); + + RTPUnknownExtensionPacket::ptr ex (rtp->next()->as<RTPUnknownExtensionPacket>()); + BOOST_CHECK_EQUAL( static_cast<unsigned>(ex->proDef()), 0x2021u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(ex->length()), 0x04u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(ex->ext()[0]), 0x24u ); + BOOST_CHECK_EQUAL( static_cast<unsigned>(ex->ext()[2]), 0x26u ); + + BOOST_REQUIRE( ex->next() ); + DataPacket::ptr pay (ex->next()->as<DataPacket>()); + + BOOST_CHECK_EQUAL( pay->size(), 5u ); + +} + + + + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/SConscript b/Packets/SConscript new file mode 100644 index 000000000..f322d3db8 --- /dev/null +++ b/Packets/SConscript @@ -0,0 +1,9 @@ +Import('env') +import SatSCons + +########################################################################### + +sources = SatSCons.GlobSources() +SatSCons.StandardTargets(env) +SatSCons.Lib(env, 'Packets', sources) +SatSCons.Doxygen(env,sources) diff --git a/Packets/TODO b/Packets/TODO new file mode 100644 index 000000000..87496174f --- /dev/null +++ b/Packets/TODO @@ -0,0 +1,15 @@ +Klasse für IPv6 (v4?) Adressen als Parser und als value type + +Bessere check implementierung ? +check umbauen: check() static machen und vor dem DerivedPacket() constructor +aufrufen. DerivedPacket() constructor darf dann keine exception mehr +auslösen + +ParseListS wrapper implementieren. + +--------------------------------------------------------------------------- +Obsolete: + +reference-counting: Packet's mit 0 refcount erstellen und dann in +create hochzählen. Was spricht eigentlich dagegen ??? + --> Hrmpf .. doch ziemlich kompliziert, ich glaube, das lasse ich diff --git a/Packets/UDPPacket.cc b/Packets/UDPPacket.cc new file mode 100644 index 000000000..7f44028a5 --- /dev/null +++ b/Packets/UDPPacket.cc @@ -0,0 +1,66 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline non-template functions + +#include "UDPPacket.hh" +//#include "UDPPacket.ih" +#include "IpV4Packet.hh" + +// Custom includes +#include "DataPacket.hh" + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// +namespace { + namespace pkf = satcom::pkf; + pkf::PacketRegistry<pkf::IpV4Types>::RegistrationProxy<pkf::UDPPacket> + registerUDPPacket(17); +} + +prefix_ void satcom::pkf::UDPPacket::v_nextInterpreter() + const +{ + registerInterpreter<DataPacket>(begin()+bytes(),end()); +} + +prefix_ void satcom::pkf::UDPPacket::v_finalize() +{} + +prefix_ void satcom::pkf::UDPPacket::v_dump(std::ostream & os) + const +{ + os << "UDP:\n" + << " source port : " << source() << "\n" + << " dest port : " << destination() << "\n" + << " length : " << length() << "\n" + << " crc : " << std::hex << crc() << std::dec << "\n"; +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/UDPPacket.cti b/Packets/UDPPacket.cti new file mode 100644 index 000000000..b49e53088 --- /dev/null +++ b/Packets/UDPPacket.cti @@ -0,0 +1,46 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +//#include "UDPPacket.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <class Arg> +prefix_ satcom::pkf::UDPPacket::UDPPacket(Arg const & arg) + : Packet(arg) +{} + + + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/UDPPacket.hh b/Packets/UDPPacket.hh new file mode 100644 index 000000000..75cdf79b0 --- /dev/null +++ b/Packets/UDPPacket.hh @@ -0,0 +1,96 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_UDPPacket_ +#define HH_UDPPacket_ 1 + +// Custom includes +#include "Packet.hh" +#include "ParseInt.hh" +#include "ParseArray.hh" +#include "PacketRegistry.hh" + +//#include "UDPPacket.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + template <class Iterator=nil, class IPacket=nil> + struct Parse_UDP : public ParserBase<Iterator,IPacket> + { + template <class I, class P=nil> + struct rebind { typedef Parse_UDP<I,P> parser; }; + typedef Iterator byte_iterator; + + Parse_UDP() {} + Parse_UDP(Iterator const & i) : ParserBase<Iterator,IPacket>(i) {} + + static unsigned bytes() { return 8; } + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt16 < Iterator > Parse_16bit; + + Parse_16bit source() const { return Parse_16bit (this->i() ); } + Parse_16bit destination() const { return Parse_16bit (this->i() + 2 ); } + Parse_16bit length() const { return Parse_16bit (this->i() + 4 ); } + Parse_16bit crc() const { return Parse_16bit (this->i() + 6 ); } + + }; + + class UDPPacket + : public Packet, + public Parse_UDP<Packet::iterator, UDPPacket> + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t<UDPPacket>::ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + + private: + template <class Arg> + UDPPacket(Arg const & arg); + + virtual void v_nextInterpreter() const; + virtual void v_finalize(); + virtual void v_dump(std::ostream & os) const; + + friend class Packet; + }; +}} + + +///////////////////////////////hh.e//////////////////////////////////////// +//#include UDPPacket.cci" +//#include "UDPPacket.ct" +#include "UDPPacket.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/UDPPacket.test.cc b/Packets/UDPPacket.test.cc new file mode 100644 index 000000000..afcb77d40 --- /dev/null +++ b/Packets/UDPPacket.test.cc @@ -0,0 +1,81 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Unit tests + +//#include "UDPPacket.test.hh" +//#include "UDPPacket.test.ih" + +// Custom includes +#include "UDPPacket.hh" + +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::pkf; + +BOOST_AUTO_UNIT_TEST(udpPacket_parser) +{ + unsigned char data[] = { 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08 + }; + + typedef unsigned char * iterator; + Parse_UDP<iterator> p(data); + + BOOST_CHECK_EQUAL( p.source(), 0x0102 ); + BOOST_CHECK_EQUAL( p.destination(), 0x0304 ); + BOOST_CHECK_EQUAL( p.length(), 0x0506 ); + BOOST_CHECK_EQUAL( p.crc(), 0x0708 ); + +} + + +BOOST_AUTO_UNIT_TEST(udpPacket_packet) +{ + + unsigned char data[] = { 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08 + }; + + UDPPacket::ptr p (Packet::create<UDPPacket>(data, data+sizeof(data))); + + BOOST_CHECK_EQUAL( p->source(), 0x0102 ); + BOOST_CHECK_EQUAL( p->destination(), 0x0304 ); + BOOST_CHECK_EQUAL( p->length(), 0x0506 ); + BOOST_CHECK_EQUAL( p->crc(), 0x0708 ); + +} + + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/docstub.hh b/Packets/docstub.hh new file mode 100644 index 000000000..3607b8f08 --- /dev/null +++ b/Packets/docstub.hh @@ -0,0 +1,59 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_docstub_ +#define HH_docstub_ 1 + +// Custom includes + +//#include "docstub.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace boost { + + struct noncopyable {}; + template <class Derived> struct totally_ordered {}; + template <class Derived, class Value, class Traversal, class Reference> struct iterator_facade {}; + template <class T> struct intrusive_ptr { T * ptr; }; + template <class T> struct shared_ptr { T * ptr; }; + +} + +namespace std { + + struct exception {}; + template <class T> struct vector { T * elements; }; + template <class T> struct list { T * elements; }; + +} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "docstub.cci" +//#include "docstub.ct" +//#include "docstub.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/imgconvert.mak b/Packets/imgconvert.mak new file mode 100644 index 000000000..baf1b0de6 --- /dev/null +++ b/Packets/imgconvert.mak @@ -0,0 +1,179 @@ + +PSTOPNG_DPI := 100 + +CLEAN_FILE := $(shell pwd)/.clean +clean := clean() { \ + touch $(CLEAN_FILE); \ + for file in "$$@"; do \ + grep "^$$file"'$$' $(CLEAN_FILE) >/dev/null || echo $$file >>$(CLEAN_FILE); \ + done \ +}; clean + +cmd := run() { tput bold; echo -e "--[ $$* ]"; tput sgr0; } && run +do := run() { tput bold; echo -e "--[ $$* ]"; tput sgr0; "$$@"; } && run +eval := run() { tput bold; echo -e "--[ $$* ]"; tput sgr0; eval "$$@"; } && run + +Q := @ + +%.rawtex: %.stxt + $(Q)$(clean) $@ + $(Q)$(cmd) "rest2latex $< >$@"; \ + rest2latex \ + --language=de \ + --documentclass=scrreprt \ + --documentoptions="10pt,a4paper,DIV10" \ + --table-style=booktabs \ + --use-verbatim-when-possible \ + --use-latex-footnotes \ + --use-latex-toc \ + --no-section-numbering \ + --stylesheet=default.sty \ + --exit-status=2 \ + $< \ + > $@ || (rm -f $@; exit 1) + +%.tex: %.rawtex + $(Q)$(clean) $@ + $(Q)$(cmd) "rawfilter $< >$@"; \ + sed -e 's/\.\(png\|gif\|jpg\)/.pdf/g' \ + -e 's/\[htbp\]/\[tbp\]/g' $< >$@ \ + || (rm -f $@; exit 1) + +%.html: %.stxt + $(Q)$(clean) $@ + $(Q)$(cmd) "rest2html $< >$@"; \ + up="`echo $< | sed -r -e 's,^[^/]*$$,,' -e 's,/[^/]+$$,/,' -e 's,[^/]+,..,g'`"; \ + rest2html \ + --language=de \ + --exit-status=2 \ + --stylesheet-path="$${up}default.css" \ + $< \ + > $@ || (rm -f $@; exit 1) + +%.pdf: %.tex + $(Q)( \ + dir="$$(dirname $<)"; \ + up="echo $$dir | sed -e 's,[^/]\+,..,g"; \ + [ -n "$$dir" ] && dir="$$dir/"; \ + stem="$$(basename $*)"; \ + tex="$$(basename $<)"; \ + pdf="$$(basename $@)"; \ + $(clean) $${dir}texput.log; \ + cd "$$dir"; \ + repeat=5; \ + origfiles="$$(find $$stem.* ! \( -name $$pdf -o -name $$stem.log \) \ + -maxdepth 0 -printf '%p-%TY%Tm%Td%TH%TM%TS\n')"; \ + while [ $$repeat -gt 0 ]; do \ + $(cmd) "pdflatex --interaction nonstopmode $$tex"; \ + TEXINPUTS=.:$$up: pdflatex --interaction nonstopmode $$tex; \ + pdfexit=$$?; \ + auxfiles=$$((echo $$origfiles | tr ' ' '\n'; \ + find $$stem.* ! \( -name $$pdf -o -name $$stem.log \) \ + -maxdepth 0 -printf '%p-%TY%Tm%Td%TH%TM%TS\n') \ + | sort | uniq -u | sed -e 's/-[0-9]*$$//' | sort -u ); \ + for f in $$auxfiles; do \ + $(clean) $$dir$$f; \ + done; \ + $(clean) $*.log $@; \ + [ $$pdfexit -ne 0 ] && exit $$pdfexit; \ + newauxsum=`md5sum $$auxfiles | md5sum 2>/dev/null`; \ + [ "$$auxsum" = "$$newauxsum" ] && break; \ + auxsum="$$newauxsum"; \ + repeat=$$[ $$repeat - 1 ]; \ + done; \ + ) || (rm -f $@; exit 1) + +%.png: %.sxd + $(Q)$(clean) $@ + $(Q)$(cmd) "(openoffice) sxdtopng $<"; \ + openoffice -invisible "macro:///Local.Conversion.ConvertDrawToPNG($(shell realpath $<))" + +%.pdf: %.sxd + $(Q)$(clean) $@ + $(Q)$(cmd) "(openoffice) sxdtopdf $<"; \ + openoffice -invisible "macro:///Local.Conversion.ConvertDrawToPDF($(shell realpath $<))" + +%.pdf: %.sxc + $(Q)$(clean) $@ + $(Q)$(cmd) "(openoffice) sxctopdf $<"; \ + openoffice -invisible "macro:///Local.Conversion.ConvertCalcToPDF($(shell realpath $<))" + +%.ps: %.pdf + $(Q)$(clean) $@ + $(Q)$(cmd) "pdftops $< >$@"; \ + pdftops -eps -nocrop -noshrink -nocenter $< - | pstops - >$@ || (rm -f $@; exit 1) + +%.png: %.ps + $(Q)$(clean) $@ + $(Q)$(cmd) "pstopng $< >$@"; \ + bb=$$(grep -i '^%%BoundingBox:' $< | head -1 | sed -e 's/^%%BoundingBox: *//i'); \ + bbx=$${bb% *}; \ + bbx=$${bbx##* }; \ + bby=$${bb##* }; \ + pngx=$$(dc -e "$$bbx $(PSTOPNG_DPI) * 8 * 75.45 / p"); \ + pngy=$$(dc -e "$$bby $(PSTOPNG_DPI) * 8 * 75.45 / p"); \ + pstopnm -xborder 0 -yborder 0 -portrait -nocrop -stdout -xsize $$pngx -ysize $$pngy $< \ + | pnmscale -reduce 8 \ + | pnmtopng >$@ \ + || (rm -f $@; exit 1) + +%.gif: %.png + $(Q)$(clean) $@ + $(Q)$(cmd) "pngtogif $< >$@" + $(Q)pngtopnm $< | ppmquant 256 | ppmtogif >$@ || ( rm -f $@; exit 1) + +%.pdf: %.dot + $(Q)$(clean) $@ + $(Q)$(eval) "dot -Tfig $< | fig2dev -L pdf -f Helvetica >$@" || ( rm -f $@; exit 1 ) + +%.pdf: %.neato + $(Q)$(clean) $@ + $(Q)$(eval) "neato -Tfig $< | fig2dev -L pdf -f Helvetica >$@" || ( rm -f $@; exit 1 ) + +%.eps: %.dia + $(Q)$(clean) $@ + $(Q)$(do) dia -t eps -e $@ $< + +%.pdf: %.eps + $(Q)$(clean) $@ + $(Q)$(do) epstopdf --outfile=$@ $< + +%.d: %.stxt + $(Q)$(clean) $@ + $(Q) \ + $(cmd) "makedep $<"; \ + base="$$(dirname $<)"; \ + [ -n "$$base" ] && base="$${base}/"; \ + function scaninc { \ + local includes; \ + [ -r $$1 ] || return; \ + includes="$$(sed -n -e 's/^.. \+include:: *//' -e T -e p $$1)"; \ + for include in $$includes; do \ + echo $$base$$include; \ + scaninc $$base$$include; \ + done \ + }; \ + includes="$$(scaninc $<)"; \ + figures="$$(sed -n -e "s,^.. \+figure:: *,$$base," -e T -e p $< $$includes)"; \ + \ + echo "$*_Includes := $$(echo $$includes)" >$@; \ + echo "$*_Figures := $$(echo $$figures)" >>$@; \ + echo "$*_PDFs := $$(echo $$figures | sed -e 's/\.\(gif\|png\|jpg\)/.pdf/g')" >>$@; \ + echo '$@: Makefile $< $$($*_Includes)' >>$@; \ + echo '$*.html: $< $$($*_Includes)' >>$@; \ + echo '$*_html: $*.html $$($*_Figures)' >>$@; \ + echo '$*.tex: $< $$($*_Includes)' >>$@; \ + echo '$*.pdf: $*.tex $$($*_PDFs) $(TEX_STYLE)' >>$@ + +########################################################################### + +clean: + $(Q)if [ -r $(CLEAN_FILE) ]; then \ + $(cmd) "xargs rm -f <.clean && rm -f .clean"; \ + xargs rm -f <$(CLEAN_FILE) && rm -f $(CLEAN_FILE); \ + fi + +# Local Variables: +# mode: makefile +# makefile-backslash-column: 100 +# End: diff --git a/Packets/main.test.cc b/Packets/main.test.cc new file mode 100644 index 000000000..ead651764 --- /dev/null +++ b/Packets/main.test.cc @@ -0,0 +1,43 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline non-template functions + +//#include "test.hh" +//#include "test.ih" + +// Custom includes +#define BOOST_AUTO_TEST_MAIN +#include <boost/test/auto_unit_test.hpp> +#include <boost/test/test_tools.hpp> + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// End: diff --git a/Packets/satcom.css b/Packets/satcom.css new file mode 100644 index 000000000..5b3d1dbee --- /dev/null +++ b/Packets/satcom.css @@ -0,0 +1,310 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Geneva, Arial, Helvetica, sans-serif; +} +BODY,TD { + font-size: 90%; +} +H1 { + text-align: center; + font-size: 160%; +} +H2 { + font-size: 120%; +} +H3 { + font-size: 100%; +} +CAPTION { font-weight: bold } +DIV.qindex { + width: 100%; + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.nav { + width: 100%; + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code:link { text-decoration: none; font-weight: normal; color: #0000FF} +A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF} +A.codeRef:link { font-weight: normal; color: #0000FF} +A.codeRef:visited { font-weight: normal; color: #0000FF} +A:hover { text-decoration: none; background-color: #f2f2ff } +DL.el { margin-left: -1cm } +.fragment { + font-family: Fixed, monospace; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +TD.md { background-color: #F4F4FB; font-weight: bold; } +TD.mdPrefix { + background-color: #F4F4FB; + color: #606060; + font-size: 80%; +} +TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; } +TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; } +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } +BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} +TD.indexkey { + background-color: #eeeeff; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #eeeeff; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { text-align: center; } +IMG.formulaDsp { } +IMG.formulaInl { vertical-align: middle; } +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +.mdTable { + border: 1px solid #868686; + background-color: #F4F4FB; + width: 100%; +} +.mdRow { + padding: 8px 10px; +} +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #eeeeff; +} +TD.tiny { font-size: 75%; +} +a { + color: #252E78; +} +a:visited { + color: #3D2185; +} +.dirtab { padding: 4px; + border-collapse: collapse; + border: 1px solid #b0b0b0; +} +TH.dirtab { background: #eeeeff; + font-weight: bold; +} +HR { height: 1px; + border: none; + border-top: 1px solid black; +} diff --git a/Packets/structure.dia b/Packets/structure.dia new file mode 100644 index 0000000000000000000000000000000000000000..a3efbe86ae9c1ed0785ba93145c48462b71184e3 GIT binary patch literal 3582 zcmZveXD}QLx5tUqmeHcOhsCm@Mz7IhS6LyeMeh>5hE<{yWm%orl^`O75M7k$qC|~g z)#%a7>fAi{oq0dpx#vG~<~MU@{^xu;=lqjMM)1Euv}^gycTSoy>_^q;hbobztCGrz zEq7;yiGpFjbmfyCb)BRNVZP@A@+sE%22mAQ4J3`ehl0JQPol{n_Fy^nye*38mF(i( zK@e@Sa?C(5r)X6lVEItMLVsl|M6QK1{N)|W^YlEf!LtoJ61BgBHKP;K!m|z5wKQ`s zmTYae3=YP{k<u$wMoH=$NVY%zb8r-{N>7|!Ke~3ln?JT0L_EO-#5w1~qa^j#8_ry1 z%}Ejuf<xGJZ!vs_H$L(sI_}@~Rs{65u#ua=*Ta1~&LK@@>oo>&z4>w*#s#qLL7@NC zuUqDc_uGh^9g`N*o<B{(Xyr<(*H0&Z--a1G89jHW5O(%#zeo#DmvKG*W@PCI`~-k9 zsXojXrS{%wO*mpxO?#g)o6nsjZR)LAf41t^_^jP4&APE$6c-Zu<#oCw`T7?3syq8* z+s{K!CRUZ*P+u^Bv|T%YC)@6fPIL2gUWRTL@Z9gvH>IwMA2b=4ZI$)*sZ`eoB}uso zp0`tMd}*n*KfUNv*p)@ZISquEi>k-aG1NJnZLRy>bTRFE8e84{PP_D8j`Mpdi(UV7 z;ZC1rHre-O(fIBc{PYSgbPR`E@BdOinib?&dKw3!FIDK6xd~ydMESMa<-X3_lkO2g z&7a=*=y~eijxBicM#V?=iOoE{o0w2>s1531BMuH=TA90xP4}~32p_kR1ERM!=f?Jr z9c9B<O=oPULV}fUWkeRRp^0wp#yDz^QNe{%&`4^hg(XdF61~qNUR|mzvZ;0cF|>mF zn-61*9Gy`=^K*8zG|ocKf$yAH9Pg_(#|>XuI|5tiOC*}l1es>IcE>wa+8WxARoV_- z^*GcmVjk{c49lcWz}o0@+xC^wPIuPD>h*j9ixHs6u7Q@`;p4y<T;My>_^$%EMq6j^ zf-bzOPR?lrmq)ln^A~zwjoKub{h)vxr_xP;wc~>}9qGlADeDE;fK}oV%6GiMgm4@| zoTHI+{~wSFjY-BDh-)&FcpZ>WvCUb-Y7Y1~Bm{x(kmXZMi*%|GS>=-aN?T4m$O%{z zmm+)6qeznrjD`#ZRjg(bgDu4RnDlB{bNVu!vgjG&St>2NqI=onuRq4SS;h8MNT48{ zYQf9msy>Mt(R>dzah7vGykE3Q^7~{KOlewnG1FX7Cg7+WUYdB!v}whVI++39$q-ov zIYvQ0GW*Y)Ks!m+5i!Yp#8MA4T&IPo_73Zs9!o_duMesgg^}SYk*CekZSNk0N`bml zHr)C$4dV$f%4xIMxIo>ReD?!8vLMm5#8gFI-VzDvYs<}+Kfq4fkLB|}gT~(Cqoxv~ zGzIJXFj+^27T<&_tlKES;c;7@iHN7oDM7#?d0@I&KxiYdLZX}3N~qJ(9MQf@U|U1k zoKJ_F-6u&WD(sw{?&C6#+r{)>hSkA3PcNO$5>J;54h3~1bzjFu&WbcsdQLJ9VD<7b zCMY8dpc3&qH@Puq#ehvDDvM7hy@jic-Ny@8dD~AV=lOcjj6p%(OD7t2{CB|^;8J{8 z)mX#y<LYc#_!GIBFPQ%k%)N3u5jPzw>icsDvg-YV5UVaa_rGjp30y^7voG==i@C<N zBO0WIN1L<36)T(GwEX2Q7sZGN!LHriz-nALO2(GM)NpS!5Vef8J%Q+Mq!<2<a+#-_ zH`0+l3J?r|Z&EF9x{&d-%G7M!oG69&6R%uE3F9k^8jGh#6zOrtoC-NmI8pB4<;%?h zUu#Zpk$_^3;$;J>uxEG8jh4ka9T0{6R4%fs8SZc55AC8>*X^1#6k8ajPuvo5LaRGH z{Z8T=RtB;T0GOgiVLQMz_3>M4RRA!JUjrjb8x)XC&V3R+dS4Arru1KEPZ~Ay2Py## zl>-D#b1a9TyyMFEM)uxIB}h-@l4iHR4}9C21_9*I*r>g_SR>8hFfrh6i$14Y(TNxR zFQB@!n~#lOx<@Im+q+JHTn8|ny5DIBE8|d-Nbw_ti2E&m4^H*(7&Jkh<KSovO|aS~ z`CI<~z{R#YeBvUSD50@59VSGFfb+A9MLrEs3fY`VOdD2%8&Z<Y<i=tC2@4|qkA>PQ z`Tv2o$o}IQ7Mn*s*uj*R-H`1%jaXM#5i-pT0STKENZL;}UQlM!3Xptnq_9q}FoT*U z6mRE{zL{>%8@=?@1@?gsHcnUsPbprC6!&PX_f|?1My;AJ_E5|4HQ5F`sYnBcuZ>RS zoP^hGSS$8Zur|GTG-p4j{#H4b4K$A`a?-w%OUdJQ?4OuS)ta@WdL%I!7n2N*9SPyw zM4gFI1CCYx|8(+wJ!0Y6h6$r<fPT(9nzeC<2PYa{@-`ou)Zg_FXIeCcCl8IkCC4$& z0DB*!Z+0`wC{gH})i+ly-{!Zv14cdWIB!CjhO!xQ?O&j2e{Q<5_|$by2Q^Cz3qWgw z^7iToh4Dk_!Om=rH`Vq<hxTlRTzNmTkP%)36(&X*<Ge`){8eFZit!#9+ORX6FaUbi zmY}5}A-76?O3$;N3RoEeHQ|IW@<sOIgJC4|GttLqfkJ*ro_t-KCz7l5#@1CkJNJgJ zmU)J*RMmB@7goFEbvq&`cU9`mHN?<)WmSU_sZ2gxz$5RYwm0#iUd;zfvDyS$4cbYN z4Gph=;oWxkY;YbwL3z!W_b%B|_q7pzl@K{Iag#JfKGCYMx3ynaDjZbEvIw6%ugu}g zHJ&Vc#j#K(`k46ARF*>nKw_~;8Y&01p50BSL0<9pXA3%A4J1^HO8p5zE2qu84ab#8 zv7LM-PpCPh$lOy=ch3Ypa=kbBtxtjh{PPWLY|Vob<nTvQdpzP~-E97renakq=rG{` z9@B~rWTt&+%{qIbZ5rsM?>z4!4f4D99TS}a<CWgm3#J)|DZE&y0YHfV%AKdAIVvNM z2|YeiiWO(`5BQnvG?yeyH=Onm;;-t~_TyI++BnaQ!y+m*@~`S?4JTB!&xnwou-OYS z>azt6lX(|#v3$6-eNmCfi+QjrhMN1+=NfQ6CmH0gT+1Pb<EqfL4z<ha5WI<4d8*Ou z#qQI{G&?P8gB1t&eh!V9wpTzp+LiCXEcAAyVX^BR0xJvM_eg<f7|)m*Wq_<)5YQ)c zVehDPFt}UU-0ZIdi0ZS#V0*R?-?K{u-*q)p@Q8jCEEYv@&jMj2#td29<lQxI3@M?@ zUJS0uNc0Ex98;sGZ!di)pN!RJcqOhKtvQxf#cV7oC#Rn)3-7J{Iny*?PVIbkLTO1V z*W>>I*6_Q_cl7v_y=6Gwc}pQ+E-x>O=#KD~=$iB##nZx|ctsu1d)wt!Px7YpPK?a? zlczb=-xBq~KTD5N+{O-e9-UuYQiIccbi$msl-+*kz6j~ETT<)@dUZ^&;qCV9wevpr z$TZR`MY|rjDl|{(tnK)(1v{B6jThIFO3F^J>+U0*>U?=5q?CgVzIHpWxTgz?9i)e@ zXMF*pS(!4cj{vW=L`v)ii+Xr?`|hjBmPVE}7BWLcT#@HTzF{P_4JWnOE}p}91=D!8 zPb^((3?rXBV@!P>4ictQ_Pu6~tXnd5DbYp_&B^A*4tOhwcOpI6?SFFCU5Z^jjLQU{ z*&-{(ndYhKvt<ZmSA!I+%9UU0@qzF&3U;*X5z|ztYIbS`s|SO=Lp4C}Ueao$L?cV} zC(Ac5sK8if3Yx)K#f>XKsoGz(yPhfuxO>?&nnMkDON{eQ;Rl54yDj(FpE-G{+xa>~ z(`K*@B++PiaY@s(V1B))wwt4c*vp^g3=vgxVEkuTI7R5@n4z)!0iGl>y!Bcc4~8sY z{En8=_WyPeu4dVb`Na;=x0KmXX2;`8Xemq%rs=)+Vty*+&LvGrW2W~SZ8UT2OpVkd zraHERjnmsq3nqqA=vqIUe`lv+GIRf0-AwH}S8a}+;R>M%E5O~nFafdbz8K8|f*_#p zq(Fcn%)#s4arr#W`1mU{6?H|3*%2@D1;w9MT7Rf*grC^}V*tC5BB#=eW{<-|-s>aH zUXsD2PhY<qSbcGRU){DIS`(C$Z9D71*vmBWeCLxer7p5Z_jjmpfrAc<Xm{<dTCB`_ z#N4xI%sKeix!}v$kR@rNuQU_&NW!n;pL!Q&J3DHt@?06V2+Ty;Lfn27<~bIq`)tS9 zKT~u_&-tWEd&eG`RG`ANQ=fItfHX!)DGg_waFklEFkh01Wcg1`R$<a>@12u2@% zG)ZzPHZ}pBujg<vYc7o?$If;j_(J8gWIijmJ`LI~UCz`#l{6`ql)BB>Bo{RT!FEQa z+LdMaF5OT0Ng09(89wgS6sj#CK45Q*C~bMJljAVUYl7Xha~9ZqVCeZ8M|^5H?Z>TZ zF0}>C{u9X_0htHtVH$s}n7Csm*DrAze-8?mnkcv0loF#xe*@W}6~06~Hr@c2Po~t> zl~MKpoLY>wlD*SPmgA>2Cq_MC*Hw+brg)-PMa<2r8~>as>ZK^#_Dj5O!fNl};PZRw zlqi-jNb;#^d4r}h#9B(#tt>Kw>odWLzc7LKEOix)3=W$g9-G}1R7sPS^rkc)tG^rG wF?<zxEY-@03qi_Y!)p|RLG4L@-~6B}aQo+QC+O#wSL=86b*p99078QQ0slqhi~s-t literal 0 HcmV?d00001 diff --git a/Packets/typeidvalue.cci b/Packets/typeidvalue.cci new file mode 100644 index 000000000..26d8c4fe8 --- /dev/null +++ b/Packets/typeidvalue.cci @@ -0,0 +1,78 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline non-template functions + +//#include "typeidvalue.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +prefix_ satcom::lib::TypeIdValue::TypeIdValue() + : value_(new ValueImpl<void>()) +{} + +prefix_ satcom::lib::TypeIdValue::TypeIdValue(TypeIdValue const & other) +{ + value_.reset(other.value_->clone()); +} + +prefix_ satcom::lib::TypeIdValue const & +satcom::lib::TypeIdValue::operator=(TypeIdValue const & other) +{ + value_.reset(other.value_->clone()); + return *this; +} + +prefix_ bool satcom::lib::TypeIdValue::operator==(TypeIdValue const & other) + const +{ + return value_->id() == other.value_->id(); +} + +prefix_ bool satcom::lib::TypeIdValue::operator<(TypeIdValue const & other) + const +{ + return value_->id().before(other.value_->id()); +} + +prefix_ std::string satcom::lib::TypeIdValue::name() + const +{ + return std::string(value_->id().name()); +} + +prefix_ satcom::lib::TypeIdValue const satcom::lib::typeIdValue() +{ + return TypeIdValue(); +} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/typeidvalue.cti b/Packets/typeidvalue.cti new file mode 100644 index 000000000..9c78ae1e5 --- /dev/null +++ b/Packets/typeidvalue.cti @@ -0,0 +1,63 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of inline template functions + +//#include "typeidvalue.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template <class Type> +prefix_ satcom::lib::TypeIdValue::TypeIdValue(Type *) + : value_(new ValueImpl<Type>()) +{} + +template <class Type> +prefix_ std::type_info const & satcom::lib::TypeIdValue::ValueImpl<Type>::id() +{ + return typeid(Type); +} + +template <class Type> +prefix_ satcom::lib::TypeIdValue::Value * +satcom::lib::TypeIdValue::ValueImpl<Type>::clone() +{ + return new ValueImpl<Type>(); +} + +template <class Type> +prefix_ satcom::lib::TypeIdValue const satcom::lib::typeIdValue() +{ + return TypeIdValue(static_cast<Type*>(0)); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Packets/typeidvalue.hh b/Packets/typeidvalue.hh new file mode 100644 index 000000000..425c14fbb --- /dev/null +++ b/Packets/typeidvalue.hh @@ -0,0 +1,103 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_typeidvalue_ +#define HH_typeidvalue_ 1 + +// Custom includes +#include <typeinfo> +#include <string> +#include <boost/scoped_ptr.hpp> +#include <boost/operators.hpp> + +//#include "typeidvalue.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + /** \brief Wrapper to use types as key's in a map + */ + class TypeIdValue : public boost::totally_ordered<TypeIdValue> + { + public: + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + // my default constructor + // my copy constructor + // my copy assignment + // default destructor + // no conversion constructors + + TypeIdValue(); + TypeIdValue(TypeIdValue const & other); + TypeIdValue const & operator=(TypeIdValue const & other); + + ///@} + /////////////////////////////////////////////////////////////////////////// + + bool operator==(TypeIdValue const & other) const; + bool operator<(TypeIdValue const & other) const; + + std::string name() const; + + protected: + + private: + template <class Type> TypeIdValue(Type *); + + struct Value { + virtual std::type_info const & id() = 0; + virtual Value * clone() = 0; + }; + + template <class Type> + struct ValueImpl : public Value { + virtual std::type_info const & id(); + virtual Value * clone(); + }; + + boost::scoped_ptr<Value> value_; + + template <class Type> friend TypeIdValue const typeIdValue(); + }; + + TypeIdValue const typeIdValue(); + + template <class Type> + TypeIdValue const typeIdValue(); + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +#include "typeidvalue.cci" +//#include "typeidvalue.ct" +#include "typeidvalue.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: -- GitLab