From: g0dil Date: Tue, 10 Oct 2006 09:34:29 +0000 (+0000) Subject: git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@129 270642c3-0616-0410... X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=c52cd7d87dbb525c1267aad27391b8b7365dbb57;p=senf.git git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@129 270642c3-0616-0410-b53a-bc976706d245 --- c52cd7d87dbb525c1267aad27391b8b7365dbb57 diff --git a/Packets/.cvsignore b/Packets/.cvsignore new file mode 100644 index 0000000..9064a29 --- /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 0000000..91e80cf --- /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 +// +// 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 0000000..f16bbb3 --- /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 +// +// 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 +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 0000000..480f3cd --- /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 +// +// 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::ptr ptr; + typedef iterator byte_iterator; + + /////////////////////////////////////////////////////////////////////////// + + static void init() {} + static bool check(iterator const & b, iterator const & e) { return true; } + + private: + template + 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 0000000..5701f22 --- /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 0000000..f0e468e --- /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 +// +// 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 +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + namespace pkf = satcom::pkf; + pkf::PacketRegistry::RegistrationProxy + 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 0000000..132e2de --- /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 +// +// 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 +prefix_ satcom::pkf::EthernetPacket::EthernetPacket(Arg const & arg) + : Packet(arg) +{} + +template +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 0000000..ae4fdb2 --- /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 +// +// 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 + struct Parse_Ethernet : public ParserBase + { + template + struct rebind { typedef Parse_Ethernet parser; }; + typedef Iterator byte_iterator; + + Parse_Ethernet() {} + Parse_Ethernet(Iterator const & i) : ParserBase(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, + public PacketRegistryMixin + { + using PacketRegistryMixin::registerInterpreter; + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t::ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + + private: + template + 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 + struct Parse_EthVLan : public ParserBase + { + template + struct rebind { typedef Parse_Ethernet parser; }; + typedef Iterator byte_iterator; + + Parse_EthVLan() {} + Parse_EthVLan(Iterator const & i) : ParserBase(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, + public PacketRegistryMixin + { + using PacketRegistryMixin::registerInterpreter; + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t::ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + + private: + template + 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 0000000..72e16d5 --- /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 +// +// 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 +#include + +#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 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(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(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(data, data+sizeof(data))); + + BOOST_CHECK( p->next()->is() ); + EthVLanPacket::ptr v (p->next()->as()); + 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() ); + 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 0000000..36f879a --- /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 + 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::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 0000000..842fa56 --- /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 +// +// 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 +prefix_ void satcom::pkf::GenericPacket::v_nextInterpreter() + const +{ + this->registerInterpreter(this->end_header(), this->begin_trailer()); +} + +template +prefix_ void satcom::pkf::GenericPacket::v_finalize() +{} + +template +prefix_ void satcom::pkf::GenericPacket::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 0000000..92c9e59 --- /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 +// +// 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 +template +prefix_ satcom::pkf::GenericPacket::GenericPacket(Arg const & arg) +: Packet(arg) +{} + +template +prefix_ void satcom::pkf::GenericPacket::init() +{ + insert(begin(),HEADER,0); + insert(end(),TRAILER,0); +} + +template +prefix_ typename satcom::pkf::GenericPacket::iterator +satcom::pkf::GenericPacket::begin_header() + const +{ + return this->begin(); +} + +template +prefix_ typename satcom::pkf::GenericPacket::iterator +satcom::pkf::GenericPacket::end_header() + const +{ + return this->begin() + HEADER; +} + +template +prefix_ typename satcom::pkf::GenericPacket::size_type +satcom::pkf::GenericPacket::header_len() +{ + return HEADER; +} + +template +prefix_ typename satcom::pkf::GenericPacket::iterator +satcom::pkf::GenericPacket::begin_trailer() + const +{ + return this->end() - TRAILER; +} + +template +prefix_ typename satcom::pkf::GenericPacket::iterator +satcom::pkf::GenericPacket::end_trailer() + const +{ + return this->end(); +} + +template +prefix_ typename satcom::pkf::GenericPacket::size_type +satcom::pkf::GenericPacket::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 0000000..c8cd5d8 --- /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 +// +// 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 + class GenericPacket : public Packet + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef typename Packet::ptr_t::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 + 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 0000000..095a2f9 --- /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 +// +// 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 +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + namespace pkf = satcom::pkf; + pkf::PacketRegistry::RegistrationProxy + 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 0000000..9a8c96f --- /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 +// +// 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 +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 0000000..0f9e296 --- /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 +// +// 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 + struct Parse_IpV4 : public ParserBase + { + template + struct rebind { typedef Parse_IpV4 parser; }; + typedef Iterator byte_iterator; + + Parse_IpV4() {} + Parse_IpV4(Iterator const & i) : ParserBase(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, + public PacketRegistryMixin + { + using PacketRegistryMixin::registerInterpreter; + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t::ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + + private: + template + 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 0000000..fd93c5a --- /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 +// +// 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 +#include + +#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 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(p.tos()), 0x02u ); + BOOST_CHECK_EQUAL( static_cast(p.length()), 0x0304u ); + BOOST_CHECK_EQUAL( static_cast(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(p.ttl()), 0x09u ); + BOOST_CHECK_EQUAL( static_cast(p.protocol()), 0x0Au ); + BOOST_CHECK_EQUAL( static_cast(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(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(p->tos()), 0x02u ); + BOOST_CHECK_EQUAL( static_cast(p->length()), 0x0304u ); + BOOST_CHECK_EQUAL( static_cast(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(p->ttl()), 0x09u ); + BOOST_CHECK_EQUAL( static_cast(p->protocol()), 0x0Au ); + BOOST_CHECK_EQUAL( static_cast(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 0000000..c94f036 --- /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 +// +// 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 // 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(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(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 (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 0000000..c3262ea --- /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 +// +// 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 0000000..edc6518 --- /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 +// +// 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 +#include "ParserBase.hh" + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template +prefix_ typename satcom::pkf::Packet::ptr_t::ptr +satcom::pkf::Packet::create(InputIterator b, InputIterator e) +{ + boost::intrusive_ptr impl (new impl::PacketImpl(b,e),false); + if (!check(impl->data_.begin(),impl->data_.end())) + throw TruncatedPacketException(); + typename ptr_t::ptr p (new OtherPacket(PacketOp_set(impl.get())), false); + return p; +} + +template +prefix_ typename satcom::pkf::Packet::ptr_t::ptr satcom::pkf::Packet::create() +{ + boost::intrusive_ptr impl ( + new impl::PacketImpl(min_bytes(),0)); + typename ptr_t::ptr p (new OtherPacket(PacketOp_set(impl.get())), false); + p->init(); + return p; +} + +template +prefix_ typename satcom::pkf::Packet::ptr_t::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(),0); + typename ptr_t::ptr p (new OuterPacket(PacketOp_set(payload->impl_))); + p->init(); + return p; +} + +template +prefix_ typename satcom::pkf::Packet::ptr_t::ptr satcom::pkf::Packet::reinterpret() +{ + // THIS INVALIDATES this !!!!!!! + if (!check(begin(),end())) + throw TruncatedPacketException(); + typename ptr_t::ptr p (new OtherPacket(PacketOp_replace(this)),false); + return p; +} + +template +prefix_ typename satcom::pkf::Packet::ptr_t::ptr +satcom::pkf::Packet::registerInterpreter(raw_container::iterator begin, + raw_container::iterator end) + const +{ + if (!check(begin,end)) + throw TruncatedPacketException(); + typename ptr_t::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 +prefix_ typename satcom::pkf::Packet::ptr_t::ptr satcom::pkf::Packet::find_next() + const +{ + ptr p (next()); + while (p && !p->is()) + p = p->next(); + return p->as(); +} + +template +prefix_ typename satcom::pkf::Packet::ptr_t::ptr satcom::pkf::Packet::find_prev() + const +{ + ptr p (prev()); + while (p && !p->is()) + p = p->prev(); + return p->as(); +} + +template +prefix_ typename satcom::pkf::Packet::ptr_t::ptr satcom::pkf::Packet::get_next() + const +{ + typename ptr_t::ptr p (find_next()); + BOOST_ASSERT(p); + return p; +} + +template +prefix_ typename satcom::pkf::Packet::ptr_t::ptr satcom::pkf::Packet::get_prev() + const +{ + typename ptr_t::ptr p (find_prev()); + BOOST_ASSERT(p); + return p; +} + +template +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 0000000..364bd17 --- /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 +// +// 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 +prefix_ bool satcom::pkf::Packet::is() + const +{ + return dynamic_cast(this); +} + +template +prefix_ typename satcom::pkf::Packet::ptr_t::ptr satcom::pkf::Packet::as() +{ + return typename ptr_t::ptr(dynamic_cast(this),true); +} + +// This constructor appends a new interreter to the interpreter chain +// of an existing Packet +template +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 +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 0000000..ef25f14 --- /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 +// +// 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 // for boost::noncopyable +#include +#include +#include +#include +#include +#include + +#include "Packet.mpp" +// ////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + namespace impl { template 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::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 + 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(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 + { + + // check does not need to be implemented here, it is + // inherited from the parser + + private: + template + 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, + public satcom::pkf::PacketRegistryMixin + { + using satcom::pkf::Packet::registerInterpreter; + using satcom::pkf::PacketRegsitryMixin::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 raw_container; + typedef boost::shared_ptr interpreter_list_ptr; + typedef std::list 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 struct ptr_t { typedef boost::intrusive_ptr 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::ptr ptr + \endcode + */ + typedef ptr_t::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 + static typename ptr_t::ptr create(InputIterator b, InputIterator e); + + template + static typename ptr_t::ptr create(); + + template + static typename ptr_t::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 typename ptr_t::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 typename ptr_t::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 typename ptr_t::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 typename ptr_t::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 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 typename ptr_t::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. 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 + typename ptr_t::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 + 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 + 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 + typename ptr_t::ptr registerInterpreter( + raw_container::iterator begin, raw_container::iterator end) const; + template + typename ptr_t::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 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 0000000..1520385 --- /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 +// +// 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 +#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 + 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 0000000..3d47d96 --- /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 +// +// 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 +#include +#include + +# 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::ptr reinterpret( BOOST_PP_ENUM( BOOST_PP_ITERATION(), pkARG, ) ); + +#elif BOOST_PP_ITERATION_DEPTH()==1 && BOOST_PP_ITERATION_FLAGS()==2 +/////////////////////////////////////////////////////////////////////////// +// Packet::reinterpret implementation + +template +prefix_ typename satcom::pkf::Packet::ptr_t::ptr +satcom::pkf::Packet::reinterpret( BOOST_PP_ENUM( BOOST_PP_ITERATION(), pkARG, ) ) +{ + if (!OtherPacket::check(begin(),end())) + throw TruncatedPacketException(); + typename ptr_t::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::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 +prefix_ typename satcom::pkf::Packet::ptr_t::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::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::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::ptr satcom::pkf::Packet::create( + InputIterator b, InputIterator e, + BOOST_PP_ENUM( BOOST_PP_ITERATION(), pkARG, ) ) +{ + boost::intrusive_ptr impl (new impl::PacketImpl(b,e),false); + if (!OtherPacket::check(impl->data_.begin(), impl->data_.end())) + throw TruncatedPacketException(); + typename ptr_t::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 0000000..d41e8a0 --- /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 +// +// 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 +#include + +#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(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() ); + BOOST_CHECK( p->as() ); +} + +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() ); + BOOST_CHECK(( !p->is< GenericPacket<4,4> >() )); + BOOST_CHECK(( p->as< GenericPacket<4,6> >() )); + BOOST_CHECK( !p->as() ); + + // check the next packet in the interpreter chain + BOOST_REQUIRE( p->next() ); + BOOST_CHECK( p->next()->is() ); + 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() ); + p->next()->reinterpret< GenericPacket<6> >(); + BOOST_CHECK( p->next()->is< GenericPacket<6> >() ); + BOOST_REQUIRE( p->next()->next() ); + BOOST_CHECK( p->next()->next()->is() ); + 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() ); + + 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 0000000..631d763 --- /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 +// +// 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::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 0000000..e40f3ac --- /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 +// +// 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 +#include "Utils/TypeInfo.hh" + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template +template +prefix_ void satcom::pkf::impl::PacketRegistryImpl::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()))).second ); + // If this assertion fails, the same Packet was registered with two different keys + BOOST_ASSERT( reverseRegistry_.insert( + std::make_pair(satcom::lib::typeIdValue(), key)).second ); +} + +template +prefix_ typename satcom::pkf::impl::PacketRegistryImpl::key_t +satcom::pkf::impl::PacketRegistryImpl::key(satcom::lib::TypeIdValue const & type) +{ + typename ReversePacketMap::iterator i (reverseRegistry_.find(type)); + if (i==reverseRegistry_.end()) + throw PacketTypeNotRegistered(); + return i->second; +} + +template +prefix_ void +satcom::pkf::impl::PkReg_EntryImpl::registerInterpreter(Packet const * p, + Packet::iterator b, + Packet::iterator e) +{ + p->template registerInterpreter(b,e); +} + +template +prefix_ satcom::pkf::Packet::ptr +satcom::pkf::impl::PkReg_EntryImpl::reinterpret(Packet * p) +{ + return p->template reinterpret(); +} + +template +prefix_ typename satcom::pkf::impl::PacketRegistryImpl::Entry * +satcom::pkf::impl::PacketRegistryImpl::lookup(key_t key) +{ + typename PacketMap::iterator i (registry_.find(key)); + if (i==registry_.end()) + return &impl::pkreg_dataEntry; + return i->second.get(); +} + +template +template +prefix_ satcom::pkf::Packet::ptr +satcom::pkf::PacketRegistry::create(typename Tag::key_t key, InputIterator b, + InputIterator e) +{ + Packet::ptr p (Packet::create(b,e)); + return registry().lookup(key)->reinterpret(p.get()); +} + +template +prefix_ typename satcom::pkf::PacketRegistry::Registry & +satcom::pkf::PacketRegistry::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 0000000..8c86ad8 --- /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 +// +// 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 +template +prefix_ void satcom::pkf::PacketRegistry::registerPacket(typename Tag::key_t key) +{ + registry().registerPacket(key); +} + +template +template +prefix_ satcom::pkf::PacketRegistry::RegistrationProxy:: +RegistrationProxy(typename Tag::key_t key) +{ + PacketRegistry::template registerPacket(key); +} + +template +template +prefix_ typename Tag::key_t satcom::pkf::PacketRegistry::key() +{ + return registry().key(satcom::lib::typeIdValue()); +} + +template +template +prefix_ void +satcom::pkf::impl::PacketRegistryImpl::registerInterpreter(Packet * p, + Packet::iterator b, + Packet::iterator e) +{ + p->registerInterpreter(b,e); +} + +template +prefix_ void +satcom::pkf::PacketRegistryMixin::registerInterpreter(typename Tag::key_t key, + Packet::iterator b, + Packet::iterator e) + const +{ + PacketRegistry::registry().lookup(key)->registerInterpreter( + static_cast(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 0000000..94f93b1 --- /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 +// +// 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 +#include // for boost::noncopyable +#include +#include "Packet.hh" + +//#include "PacketRegistry.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + namespace impl { template 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 + PacketRegistry::. + + 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::registerPacket(key_of_somePacket); + p = PacketRegistry::create(some_key,begin,end); + SomeTag::key_t key = PacketRegistry::key(); + \endcode + + Normally, packet classes are registered statically and not + procedurally. To this end, the RegistrationProxy is provided: + \code + PacketRegistry::RegistrationProxy + 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 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 + 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 + 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 + 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 + static Packet::ptr create(typename Tag::key_t key, InputIterator b, InputIterator e); + + private: + typedef impl::PacketRegistryImpl Registry; + static Registry & registry(); + + template 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 + { + using Packet::retgisterInterpreter; + using PacketRegistryMixin::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 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 0000000..2a752b2 --- /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 +// +// 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 + 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 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 + void registerPacket(key_t key); + + key_t key(satcom::lib::TypeIdValue const & type); + + Entry * lookup(key_t key); + + protected: + + private: + template + static void registerInterpreter(Packet * p, Packet::iterator b, Packet::iterator e); + + typedef boost::shared_ptr Entry_ptr; + typedef std::map PacketMap; + typedef std::map ReversePacketMap; + + PacketMap registry_; + ReversePacketMap reverseRegistry_; + }; + + extern PkReg_EntryImpl 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 0000000..4d235c7 --- /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 +// +// 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 +#include "PacketRegistry.hh" +#include "DataPacket.hh" +#include "ParseInt.hh" + +#include +#include + +#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 + { + using PacketRegistryMixin::registerInterpreter; + public: + typedef ptr_t::ptr ptr; + typedef iterator byte_iterator; + + typedef Parse_UInt16 Parse_Type; + + Parse_Type type() const { return Parse_Type(begin()); } + static bool check(iterator b, iterator e) { return true; } + + private: + template + 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::ptr ptr; + typedef iterator byte_iterator; + + static bool check(iterator b, iterator e) { return true; } + + private: + template + 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::ptr ptr; + typedef iterator byte_iterator; + + static bool check(iterator b, iterator e) { return true; } + + private: + template + 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::RegistrationProxy registerFoo ("foo"); + PacketRegistry::RegistrationProxy 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(data, data+sizeof(data))); + BOOST_CHECK( p->next()->is() ); + } + + PacketRegistry::registerPacket(1u); + PacketRegistry::registerPacket(2u); + + BOOST_CHECK_EQUAL( PacketRegistry::key(), 1u ); + BOOST_CHECK_EQUAL( PacketRegistry::key(), 2u ); + BOOST_CHECK_THROW( PacketRegistry::key(), PacketTypeNotRegistered ); + + { + BasePacket::ptr p (Packet::create(data, data+sizeof(data))); + BOOST_CHECK( p->next()->is() ); + } + + data[1] = 0x02; + + { + BasePacket::ptr p (Packet::create(data, data+sizeof(data))); + BOOST_CHECK( p->next()->is() ); + } + + data[0] = 0x01; + + { + BasePacket::ptr p (Packet::create(data, data+sizeof(data))); + BOOST_CHECK( p->next()->is() ); + } + + BOOST_CHECK_EQUAL( PacketRegistry::key(), "foo" ); + BOOST_CHECK( PacketRegistry::create("foo",data,data+sizeof(data)) + ->is() ); + +} + +///////////////////////////////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 0000000..c932dd8 --- /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 +// +// 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 +#if defined(_STLP_ALGORITHM) || (__GNUC__<4 && __GNUC_MINOR__<4) +#define copy_n std::copy_n +#else +#include +#define copy_n __gnu_cxx::copy_n +#endif + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +prefix_ satcom::pkf::Parse_Array::Parse_Array() +{} + +template +prefix_ +satcom::pkf::Parse_Array::Parse_Array(Iterator const & i) + : ParserBase(i) +{} + +template +prefix_ unsigned satcom::pkf::Parse_Array::bytes() +{ + return elements*Parser::bytes(); +} + +template +prefix_ bool +satcom::pkf::Parse_Array::check(Iterator const & e) + const +{ + return e-this->i() >= bytes(); +} + +template +prefix_ void satcom::pkf::Parse_Array::init() + const +{ + iterator e=end(); + for (iterator i=begin(); i!=e; ++i) i->init(); +} + +/////////////////////////////////////////////////////////////////////////// + +template +prefix_ typename satcom::pkf::Parse_Array::size_type +satcom::pkf::Parse_Array::size() +{ + return elements; +} + +template +prefix_ typename satcom::pkf::Parse_Array::iterator +satcom::pkf::Parse_Array::begin() + const +{ + return iterator(this->i()); +} + +template +prefix_ typename satcom::pkf::Parse_Array::iterator +satcom::pkf::Parse_Array::end() + const +{ + return iterator(this->i()+bytes()); +} + +template +prefix_ typename satcom::pkf::Parse_Array::range_type +satcom::pkf::Parse_Array::range() + const +{ + return std::make_pair(begin(),end()); +} + +template +prefix_ typename satcom::pkf::Parse_Array::iterator +satcom::pkf::Parse_Array::value() + const +{ + return begin(); +} + +template +prefix_ typename satcom::pkf::Parse_Array::value_type +satcom::pkf::Parse_Array::operator[](difference_type i) + const +{ + return begin()[i]; +} + +template +template +prefix_ satcom::pkf::Parse_Array const & +satcom::pkf::Parse_Array::operator=(InputIterator const & i) +{ + copy_n(i,size(),begin()); +} + +/////////////////////////////////////////////////////////////////////////// + +template +prefix_ Iterator satcom::pkf::impl::Parse_Array_iterator::raw() + const +{ + return i_; +} + +template +prefix_ Parser satcom::pkf::impl::Parse_Array_iterator::operator[](int i) + const +{ + return (*this+i).dereference(); +} + +template +prefix_ satcom::pkf::impl::Parse_Array_iterator::Parse_Array_iterator() + : i_() +{} + +template +prefix_ satcom::pkf::impl::Parse_Array_iterator:: +Parse_Array_iterator(Iterator const & i) + : i_(i) +{} + +template +prefix_ Parser +satcom::pkf::impl::Parse_Array_iterator::dereference() + const +{ + return Parser(i_); +} + +template +prefix_ bool satcom::pkf::impl::Parse_Array_iterator:: +equal(Parse_Array_iterator const & other) + const +{ + return i_==other.i_; +} + +template +prefix_ int satcom::pkf::impl::Parse_Array_iterator:: +distance_to(Parse_Array_iterator const & other) + const +{ + return (other.i_-i_)/Parser::bytes(); +} + +template +prefix_ void satcom::pkf::impl::Parse_Array_iterator::increment() +{ + i_ += Parser::bytes(); +} + +template +prefix_ void satcom::pkf::impl::Parse_Array_iterator::decrement() +{ + i_ -= Parser::bytes(); +} + +template +prefix_ void +satcom::pkf::impl::Parse_Array_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 0000000..f4a0d41 --- /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 +// +// 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 // for std::pair +#include "ParserBase.hh" + +//#include "ParseArray.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + namespace impl { template class Parse_Array_iterator; } + + /* Parse_Array has the external interface of a container class + */ + template + struct Parse_Array : public ParserBase + { + /////////////////////////////////////////////////////////////////////////// + // Parser interface + + template + struct rebind { typedef Parse_Array 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::parser value_type; + typedef impl::Parse_Array_iterator iterator; + typedef unsigned size_type; + typedef int difference_type; + typedef std::pair 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 + 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 0000000..85e850f --- /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 +// +// 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 + +///////////////////////////////ih.p//////////////////////////////////////// + +template +class satcom::pkf::impl::Parse_Array_iterator + : public boost::iterator_facade< Parse_Array_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 0000000..59a9898 --- /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 +// +// 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 +#include + +#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 0000000..1207eaf --- /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 +// +// 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 +#include +#include + +//#include "ParseInt.mpp" +///////////////////////////////hh.p//////////////////////////////////////// +#include "ParseInt.ih" + +namespace satcom { +namespace pkf { + + template + struct Parse_Int8 + : public impl::ParseIntOps,boost::int8_t>, + public ParserBase + { + template + struct rebind { typedef Parse_Int8 parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 1; } + + Parse_Int8() {} + explicit Parse_Int8(Iterator const & i) : ParserBase(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 + struct Parse_UInt8 + : public impl::ParseIntOps,boost::uint8_t>, + public ParserBase + { + template + struct rebind { typedef Parse_UInt8 parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 1; } + + Parse_UInt8() {} + explicit Parse_UInt8(Iterator const & i) : ParserBase(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 + struct Parse_Int16 + : public impl::ParseIntOps,boost::int16_t>, + public ParserBase + { + template + struct rebind { typedef Parse_Int16 parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 2; } + + Parse_Int16() {} + explicit Parse_Int16(Iterator const & i) : ParserBase(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 + struct Parse_UInt16 + : public impl::ParseIntOps,boost::uint16_t>, + public ParserBase + { + template + struct rebind { typedef Parse_UInt16 parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 2; } + + Parse_UInt16() {} + explicit Parse_UInt16(Iterator const & i) : ParserBase(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 + struct Parse_Int24 + : public impl::ParseIntOps,boost::int32_t>, + public ParserBase + { + template + struct rebind { typedef Parse_Int24 parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 3; } + + Parse_Int24() {} + explicit Parse_Int24(Iterator const & i) : ParserBase(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 + struct Parse_UInt24 + : public impl::ParseIntOps,boost::uint32_t>, + public ParserBase + { + template + struct rebind { typedef Parse_UInt24 parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 3; } + + Parse_UInt24() {} + explicit Parse_UInt24(Iterator const & i) : ParserBase(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 + struct Parse_Int32 + : public impl::ParseIntOps,boost::int32_t>, + public ParserBase + { + template + struct rebind { typedef Parse_Int32 parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 4; } + + Parse_Int32() {} + explicit Parse_Int32(Iterator const & i) : ParserBase(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 + struct Parse_UInt32 + : public impl::ParseIntOps,boost::uint32_t>, + public ParserBase + { + template + struct rebind { typedef Parse_UInt32 parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 4; } + + Parse_UInt32() {} + explicit Parse_UInt32(Iterator const & i) : ParserBase(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 + struct Parse_IntField + : public impl::ParseIntOps,boost::int32_t>, + public ParserBase + { + template + struct rebind { typedef Parse_IntField parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return (end-1)/8+1; } + + Parse_IntField() {} + explicit Parse_IntField(Iterator const & i) : ParserBase(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef boost::int32_t value_type; + + value_type value() const { + value_type v (impl::parse_bitfield::parse(this->i())); + return v&boost::high_bit_mask_t::high_bit ? + v | ~boost::low_bits_mask_t::sig_bits : v; + } + void value(value_type v) { impl::parse_bitfield::write(this->i(),v); } + Parse_IntField const & operator= (value_type other) { value(other); return *this; } + + private: + BOOST_STATIC_ASSERT( start + struct Parse_UIntField + : public impl::ParseIntOps,boost::uint32_t>, + public ParserBase + { + template + struct rebind { typedef Parse_UIntField parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return (end-1)/8+1; } + + Parse_UIntField() {} + explicit Parse_UIntField(Iterator const & i) : ParserBase(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef boost::uint32_t value_type; + + value_type value() const { return impl::parse_bitfield::parse(this->i()); } + void value(value_type v) { impl::parse_bitfield::write(this->i(),v); } + Parse_UIntField const & operator= (value_type other) { value(other); return *this; } + + private: + BOOST_STATIC_ASSERT( start + struct Parse_Flag + : public impl::ParseIntOps,bool>, + public ParserBase + { + template + struct rebind { typedef Parse_Flag parser; }; + typedef Iterator byte_iterator; + + static unsigned bytes() { return 1; } + + Parse_Flag() {} + explicit Parse_Flag(Iterator const & i) : ParserBase(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 0000000..70c5859 --- /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 +// +// 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 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 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(this); } + Derived const & derived() const { return *static_cast(this); }; + }; + + /////////////////////////////////////////////////////////////////////////// + // Network byte order integer extraction + + template + boost::uint16_t parse_uint16(Iterator const & i) + { + return i[1] | i[0]<<8; + } + + template + void write_uint16(Iterator const & i, boost::uint16_t v) + { + i[0] = ( v >> 8 ) & 0xff; + i[1] = ( v ) & 0xff; + } + + template + boost::uint32_t parse_uint24(Iterator const & i) + { + return i[2] | i[1]<<8 | i[0]<<16; + } + + template + 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 + boost::uint32_t parse_uint32(Iterator const & i) + { + return i[3] | i[2]<<8 | i[1]<<16 | i[0]<<24; + } + + template + 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 + 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::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::sig_bits<<(40-end))) + | ((v & boost::low_bits_mask_t::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 + struct parse_bitfield_i + { + static boost::uint32_t parse(Iterator const & i) { + return ( parse_uint32(i+offset)>>(32-end) ) + & boost::low_bits_mask_t::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::sig_bits<<(32-end))) + | ((v & boost::low_bits_mask_t::sig_bits) << (32-end))); + } + }; + + template + struct parse_bitfield_i + { + static boost::uint32_t parse(Iterator const & i) { + return ( parse_uint24(i+offset)>>(24-end) ) + & boost::low_bits_mask_t::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::sig_bits<<(24-end))) + | ((v & boost::low_bits_mask_t::sig_bits) << (24-end))); + } + }; + + template + struct parse_bitfield_i + { + static boost::uint32_t parse(Iterator const & i) { + return ( parse_uint16(i+offset)>>(16-end) ) + & boost::low_bits_mask_t::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::sig_bits<<(16-end))) + | ((v & boost::low_bits_mask_t::sig_bits) << (16-end))); + } + }; + + template + struct parse_bitfield_i + { + static boost::uint32_t parse(Iterator const & i) { + return ( i[offset]>>(8-end) ) + & boost::low_bits_mask_t::sig_bits; + } + + static void write(Iterator const & i, boost::uint32_t v) { + i[offset] = (i[offset] & ~(boost::low_bits_mask_t::sig_bits<<(8-end))) + | ((v & boost::low_bits_mask_t::sig_bits) << (8-end)); + } + }; + + template + struct parse_bitfield + : public parse_bitfield_i + {}; + +}}} + +///////////////////////////////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 0000000..7325359 --- /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 +// +// 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 +#include + +#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(data).value(), -114); + BOOST_CHECK_EQUAL(Parse_Int8(data+1).value(), 47); + BOOST_CHECK_EQUAL(Parse_UInt8(data).value(), 142u); + + BOOST_CHECK_EQUAL(Parse_Int16(data).value(), -29137); + BOOST_CHECK_EQUAL(Parse_Int16(data+1).value(), 12119); + BOOST_CHECK_EQUAL(Parse_UInt16(data).value(), 36399u); + + BOOST_CHECK_EQUAL(Parse_Int24(data).value(), -7458985); + BOOST_CHECK_EQUAL(Parse_Int24(data+1).value(), 3102482); + BOOST_CHECK_EQUAL(Parse_UInt24(data).value(), 9318231u); + + BOOST_CHECK_EQUAL(Parse_Int32(data).value(), -1909500142); + BOOST_CHECK_EQUAL(Parse_Int32(data+1).value(), 794235601); + BOOST_CHECK_EQUAL(Parse_UInt32(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(data).value(0x2f); + BOOST_CHECK_EQUAL( data[0], 0x2f ); + + Parse_Int16(data).value(0xa341); + BOOST_CHECK_EQUAL( data[0], 0xa3 ); + BOOST_CHECK_EQUAL( data[1], 0x41 ); + + Parse_Int24(data).value(0x234567); + BOOST_CHECK_EQUAL( data[0], 0x23 ); + BOOST_CHECK_EQUAL( data[1], 0x45 ); + BOOST_CHECK_EQUAL( data[2], 0x67 ); + + Parse_Int32(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 p1(data); + Parse_UInt16 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

>::parser + { + public: + typedef typename P::template rebind::parser parser; + typedef typename ptr_t::ptr ptr; + + static bool check(iterator b, iterator e) { return true; } + + private: + template + 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

::ptr p (Packet::create< TestPacket

>(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 0000000..7e65fa9 --- /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 +// +// 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 + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template +prefix_ unsigned satcom::pkf::Parse_ListS::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 +prefix_ bool +satcom::pkf::Parse_ListS::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 +prefix_ void satcom::pkf::Parse_ListS::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 + +template +template +prefix_ void +satcom::pkf::Parse_ListS_wrapper::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 +template +prefix_ void +satcom::pkf::Parse_ListS_wrapper::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 +template +prefix_ void +satcom::pkf::Parse_ListS_wrapper::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 0000000..db91757 --- /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 +// +// 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 + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +prefix_ satcom::pkf::Parse_ListS::Parse_ListS() +{} + +template +prefix_ +satcom::pkf::Parse_ListS::Parse_ListS(Iterator const & i) + : ParserBase(i) +{} + +template +prefix_ typename satcom::pkf::Parse_ListS::size_type +satcom::pkf::Parse_ListS::size() + const +{ + return std::distance(begin(),end()); +} + +template +prefix_ bool satcom::pkf::Parse_ListS::empty() + const +{ + return begin()==end(); +} + +template +prefix_ typename satcom::pkf::Parse_ListS::iterator +satcom::pkf::Parse_ListS::begin() + const +{ + return iterator(this->i()); +} + +template +prefix_ typename satcom::pkf::Parse_ListS::iterator +satcom::pkf::Parse_ListS::end() + const +{ + return iterator(); +} + +template +prefix_ typename satcom::pkf::Parse_ListS::range_type +satcom::pkf::Parse_ListS::range() + const +{ + return std::make_pair(begin(),end()); +} + +template +prefix_ typename satcom::pkf::Parse_ListS::range_type +satcom::pkf::Parse_ListS::value() + const +{ + return range(); +} + +/////////////////////////////////////////////////////////////////////////// +// satcom::pkf::impl::Parse_ListS_iterator + +template +prefix_ +satcom::pkf::impl::Parse_ListS_iterator::Parse_ListS_iterator() + : i_(), atEnd_(true) +{} + +template +prefix_ +satcom::pkf::impl::Parse_ListS_iterator:: +Parse_ListS_iterator(Iterator const & i) + : i_(i), atEnd_(false) +{ + atEnd_ = Sentinel::check(dereference()); +} + +template +prefix_ Iterator satcom::pkf::impl::Parse_ListS_iterator::raw() + const +{ + return i_; +} + +template +prefix_ Parser +satcom::pkf::impl::Parse_ListS_iterator::dereference() + const +{ + return Parser(i_); +} + +template +prefix_ bool satcom::pkf::impl::Parse_ListS_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 +prefix_ void satcom::pkf::impl::Parse_ListS_iterator::increment() +{ + BOOST_ASSERT( !atEnd_ ); + i_ += dereference().bytes(); + atEnd_ = Sentinel::check(dereference()); +} + +/////////////////////////////////////////////////////////////////////////// +// satcom::pkf::Parse_ListS_wrapper + +template +template +prefix_ satcom::pkf::Parse_ListS_wrapper:: +Parse_ListS_wrapper(Parse_ListS const & list, Container & container) + : i_(list.i()-container.begin()), container_(container) +{} + +template +prefix_ typename satcom::pkf::Parse_ListS_wrapper::size_type +satcom::pkf::Parse_ListS_wrapper::size() + const +{ + return std::distance(begin(),end()); +} + +template +prefix_ bool satcom::pkf::Parse_ListS_wrapper::empty() + const +{ + return begin()==end(); +} + +template +prefix_ typename satcom::pkf::Parse_ListS_wrapper::iterator +satcom::pkf::Parse_ListS_wrapper::begin() + const +{ + return iterator(container_.begin()+i_); +} + +template +prefix_ typename satcom::pkf::Parse_ListS_wrapper::iterator +satcom::pkf::Parse_ListS_wrapper::end() + const +{ + return iterator(); +} + +template +prefix_ typename satcom::pkf::Parse_ListS_wrapper::range_type +satcom::pkf::Parse_ListS_wrapper::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 0000000..2c75016 --- /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 +// +// 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 // for std::pair +#include +#include // for boost::noncopyable +#include "ParserBase.hh" + +//#include "ParseListS.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + template class Parse_ListS_wrapper; + namespace impl { + template class Parse_ListS_iterator; + } + + template + struct Parse_ListS : public ParserBase + { + /////////////////////////////////////////////////////////////////////////// + // Parser interface + + template + struct rebind { typedef Parse_ListS 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::parser value_type; + typedef Sentinel sentinel; + typedef impl::Parse_ListS_iterator iterator; + typedef unsigned size_type; + typedef int difference_type; + typedef std::pair range_type; + + template + struct wrapper { typedef Parse_ListS_wrapper t; }; + + size_type size() const; + bool empty() const; + + iterator begin() const; + iterator end() const; + range_type range() const; + range_type value() const; + + private: + template friend class Parse_ListS_wrapper; + }; + + /** \brief + + Holds a reference to the container ! + */ + template + 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 iterator; + typedef unsigned size_type; + typedef int difference_type; + typedef std::pair range_type; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + template + Parse_ListS_wrapper(Parse_ListS 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 void insert(iterator pos, Value const & t); + template void insert(iterator pos, size_type n, Value const & t); + template 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 0000000..6dbeb24 --- /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 +// +// 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 + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { +namespace impl { + + template + class Parse_ListS_iterator + : public boost::iterator_facade< Parse_ListS_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 0000000..464b336 --- /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 +// +// 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 +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::pkf; + +namespace { + template + 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,Sentinel_IsZero,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 + struct Parse_LVec + : public Parse_Vector + { + template + struct rebind { typedef Parse_LVec parser; }; + typedef typename SizeParser::template rebind::parser sizeParser; + + Parse_LVec(Iterator const & i) + : Parse_Vector(sizeParser(i),i+sizeParser::bytes()) + {} + + unsigned bytes() const + { return this->Parse_Vector::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(e-this->i())+sizeParser::bytes() >= bytes(); } + }; + + template + 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<>,iterator> Parse_UInt8LVec; + typedef Parse_ListS,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(*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 Container; + typedef Container::iterator iterator; + typedef Parse_LVec,Parse_UInt8<>,iterator> Parse_UInt8LVec; + typedef Parse_ListS,iterator> Parse_UInt8LVecListS; + typedef Parse_UInt8LVecListS::wrapper::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::parser(newdata)); + BOOST_CHECK_EQUAL( w.size(), 4u ); + BOOST_CHECK_EQUAL( w.begin()->size(), 1u ); + BOOST_CHECK_EQUAL( static_cast((*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 0000000..a34f1c9 --- /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 +// +// 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 +template +prefix_ void +satcom::pkf::Parse_Vector_wrapper::insert(iterator pos, + Value const & t) +{ + size_type ix(pos.raw()-container_.begin()); + shift(pos); + Parser(container_.begin()+ix).value(t); +} + +template +template +prefix_ void +satcom::pkf::Parse_Vector_wrapper::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 +template +prefix_ void +satcom::pkf::Parse_Vector_wrapper::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 0000000..86f282f --- /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 +// +// 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 +prefix_ satcom::pkf::Parse_Vector:: +Parse_Vector(SizeParser const & size) + : size_(size) +{} + +template +prefix_ satcom::pkf::Parse_Vector:: +Parse_Vector(size_parser const & size, Iterator const & i) + : ParserBase(i), size_(size) +{} + +template +prefix_ unsigned satcom::pkf::Parse_Vector::bytes() + const +{ + return Parser::bytes()*size(); +} + +template +prefix_ void +satcom::pkf::Parse_Vector::check(Iterator const & e) + const +{ + return e-this->i() >= bytes(); +} + +template +prefix_ void satcom::pkf::Parse_Vector::init() + const +{ + iterator e (end()); + for (iterator i (begin()); i!=e; ++i) i->init(); +} + +/////////////////////////////////////////////////////////////////////////// + +template +prefix_ typename satcom::pkf::Parse_Vector::size_type +satcom::pkf::Parse_Vector::size() + const +{ + return size_.value(); +} + +template +prefix_ bool satcom::pkf::Parse_Vector::empty() + const +{ + return size()==0; +} + +template +prefix_ +typename satcom::pkf::Parse_Vector::iterator +satcom::pkf::Parse_Vector::begin() + const +{ + return iterator(this->i()); +} + +template +prefix_ +typename satcom::pkf::Parse_Vector::iterator +satcom::pkf::Parse_Vector::end() + const +{ + return iterator(this->i()+bytes()); +} + +template +prefix_ +typename satcom::pkf::Parse_Vector::range_type +satcom::pkf::Parse_Vector::range() + const +{ + return std::make_pair(begin(),end()); +} + +template +prefix_ +typename satcom::pkf::Parse_Vector::range_type +satcom::pkf::Parse_Vector::value() + const +{ + return range(); +} + +template +prefix_ +typename satcom::pkf::Parse_Vector::value_type +satcom::pkf::Parse_Vector::operator[](difference_type i) + const +{ + return begin()[i]; +} + +/////////////////////////////////////////////////////////////////////////// +// satcom::pkf::Parse_Vector_wrapper + +template +template +prefix_ satcom::pkf::Parse_Vector_wrapper:: +Parse_Vector_wrapper(Parse_Vector const & vector, Container & container) + : i_(vector.i()-container.begin()), size_i_(vector.size_.i()-container.begin()), + container_(container) +{} + +template +prefix_ typename satcom::pkf::Parse_Vector_wrapper::size_type +satcom::pkf::Parse_Vector_wrapper::size() + const +{ + return SizeParser(container_.begin()+size_i_).value(); +} + +template +prefix_ bool satcom::pkf::Parse_Vector_wrapper::empty() + const +{ + return size() == 0; +} + +template +prefix_ typename satcom::pkf::Parse_Vector_wrapper::iterator +satcom::pkf::Parse_Vector_wrapper::begin() + const +{ + return iterator(container_.begin() + i_); +} + +template +prefix_ typename satcom::pkf::Parse_Vector_wrapper::iterator +satcom::pkf::Parse_Vector_wrapper::end() + const +{ + return iterator(container_.begin() + i_ + Parser::bytes()*size()); +} + +template +prefix_ typename satcom::pkf::Parse_Vector_wrapper::range_type +satcom::pkf::Parse_Vector_wrapper::range() + const +{ + return std::make_pair(begin(), end()); +} + +template +prefix_ typename satcom::pkf::Parse_Vector_wrapper::value_type +satcom::pkf::Parse_Vector_wrapper::operator[](difference_type i) + const +{ + return begin()[i]; +} + +template +prefix_ void satcom::pkf::Parse_Vector_wrapper::shift(iterator pos, + size_type n) +{ + container_.insert(pos.raw(),n*Parser::bytes(),0); + SizeParser(container_.begin()+size_i_) += n; +} + +template +prefix_ void satcom::pkf::Parse_Vector_wrapper::erase(iterator pos, + size_type n) +{ + container_.erase(pos.raw(),pos.raw()+n*Parser::bytes()); + SizeParser(container_.begin()+size_i_) -= n; +} + +template +prefix_ void satcom::pkf::Parse_Vector_wrapper::erase(iterator f, + iterator l) +{ + erase(f,l-f); +} + +template +prefix_ void satcom::pkf::Parse_Vector_wrapper::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 0000000..3b2dc38 --- /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 +// +// 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 // for std::pair +#include +#include // for boost::noncopyable +#include "ParserBase.hh" +#include "ParseArray.hh" // for Parse_Array_iterator + +//#include "ParseVec.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace pkf { + + template class Parse_Vector_wrapper; + + template + struct Parse_Vector : public ParserBase + { + typedef typename SizeParser::template rebind::parser size_parser; + + /////////////////////////////////////////////////////////////////////////// + // Parser interface + + template + struct rebind { typedef Parse_Vector 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::parser value_type; + typedef impl::Parse_Array_iterator iterator; + typedef unsigned size_type; + typedef int difference_type; + typedef std::pair range_type; + + template + struct wrapper { typedef Parse_Vector_wrapper 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 friend class Parse_Vector_wrapper; + }; + + /** \brief + + Holds a reference to the container ! + */ + template + 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 iterator; + typedef unsigned size_type; + typedef int difference_type; + typedef std::pair range_type; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + template + Parse_Vector_wrapper(Parse_Vector 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 + void insert(iterator pos, Value const & t); + template + void insert(iterator pos, size_type n, Value const & t); + template + 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 0000000..4743c2a --- /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 +// +// 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 +#include +#include + +#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_UInt8<>,iterator> Parse_UInt16Vec; + + Parse_UInt8 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(i), *j ); + BOOST_CHECK_EQUAL(i, data+13); +} + +BOOST_AUTO_UNIT_TEST(parseVec_wrapper) +{ + typedef std::vector Container; + typedef Container::iterator iterator; + typedef Parse_UInt8 Parse_Size; + typedef Parse_Vector,Parse_Size,iterator> Parse_UInt16Vec; + typedef Parse_UInt16Vec::wrapper::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(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(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 0000000..5ba7367 --- /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 +// +// 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 +prefix_ Iterator satcom::pkf::ParserBase::i() + const +{ + return static_cast(this)->begin(); +} + +template +prefix_ satcom::pkf::ParserBase::ParserBase(Iterator const & i) + : i_(i) +{} + +template +prefix_ Iterator satcom::pkf::ParserBase::i() + const +{ + return i_; +} + +template +prefix_ bool satcom::pkf::impl::check(Iterator const & b, Iterator const & e, + impl::ParserBase *) +{ + return impl::ParserCheck::fixed_size>::check(b,e); +} + +template +prefix_ bool satcom::pkf::impl::check(Iterator const & b, Iterator const & e, + void *) +{ + return Parser::check(b,e); +} + +template +prefix_ bool satcom::pkf::check(Iterator const & b, Iterator const & e) +{ + return impl::check(b,e,static_cast(0)); +} + +template +prefix_ unsigned satcom::pkf::impl::min_bytes(impl::ParserBase *) +{ + return impl::ParserMinBytes::fixed_size>::bytes(); +} + +template +prefix_ unsigned satcom::pkf::impl::min_bytes(void *) +{ + return 0; +} + +template +prefix_ unsigned satcom::pkf::min_bytes() +{ + return impl::min_bytes(static_cast(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 0000000..69508b7 --- /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 +// +// 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 +#include + +#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 + struct Parser_Example + : protected satcom::pkf::ParserBase + { + // fixed interface of all parser classes + + template + struct rebind { typedef Parse_Example parser; } + typedef Iterator byte_iterator; + + Parse_Example() {} + Parse_Example(Iterator const & i) : ParserBase(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(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 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 ParserBase : 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 + 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 + struct Parser_traits { + typedef Parser parser; + typedef typename Parser::byte_iterator byte_iterator; + static const bool fixed_size = impl::Parser_traits_fixed_size::fixed_size; + + template + struct rebind { + typedef typename Parser::template rebind::parser parser; + }; + }; + + template + bool check(Iterator const & b, Iterator const & e); + + template + 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 0000000..3cb5eb1 --- /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 +// +// 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 + struct Parser_traits_sentinel + { int v[N]; }; + + template + 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 + Parser_traits_sentinel<2> Parser_traits_fixed_size_check(T); + + template + Parser_traits_sentinel<1> Parser_traits_fixed_size_check(R (T::*)()); + + template + bool check(Iterator const & b, Iterator const & e, ParserBase *); + + template + bool check(Iterator const & b, Iterator const & e, void *); + + template + struct ParserCheck { + template + static unsigned check(Iterator const & b, Iterator const & e) + { return Parser::check(b,e); } + }; + + template + struct ParserCheck { + template + static unsigned check(Iterator const & b, Iterator const & e) + { return unsigned(e-b) >= Parser::bytes(); } + }; + + template + unsigned min_bytes(ParserBase *); + + template + unsigned min_bytes(void *); + + template + struct ParserMinBytes { + static unsigned bytes() { return Parser::min_bytes(); } + }; + + template + struct ParserMinBytes { + 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 0000000..dca6b77 --- /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 +// +// 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 +#include + +#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 + struct Parse_Test : public pkf::ParserBase + { + template + struct rebind { typedef Parse_Test parser; }; + typedef Iterator byte_iterator; + + Parse_Test() {} + Parse_Test(Iterator const & i) : pkf::ParserBase(i) {} + + static unsigned bytes() { return 14; } + + /////////////////////////////////////////////////////////////////////////// + + }; + + template + struct Parse_Test2 : public pkf::ParserBase + { + template + struct rebind { typedef Parse_Test parser; }; + typedef Iterator byte_iterator; + + Parse_Test2() {} + Parse_Test2(Iterator const & i) : pkf::ParserBase(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 >(), 14u ); + BOOST_CHECK( pkf::check< Parse_Test >(0,14) ); + BOOST_CHECK( ! pkf::check< Parse_Test >(2,15) ); + + BOOST_CHECK_EQUAL( pkf::min_bytes< Parse_Test2 >(), 10u ); + BOOST_CHECK( pkf::check< Parse_Test2 >(2,13) ); + BOOST_CHECK( pkf::check< Parse_Test2 >(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 0000000..f50b44d --- /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 +// +// 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(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 0000000..a652af0 --- /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 +// +// 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 +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 0000000..2518110 --- /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 +// +// 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 struct Parse_RTCP_RR; + template struct Parse_RTCP_SR; + template struct Parse_RTCP_SDES; + template struct Parse_RTCP_BYE; + template struct Parse_RTCP_APP; + + + template + struct Parse_RTCP : public ParserBase + { + template + struct rebind { typedef Parse_RTCP parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP() {} + Parse_RTCP(Iterator const & i) : ParserBase(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(b).bytes(); } + + }; + + template + struct Parse_RTCP_RB : public ParserBase + { + template + struct rebind { typedef Parse_RTCP_RB parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_RB() {} + Parse_RTCP_RB(Iterator const & i) : ParserBase(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 + struct Parse_RTCP_RR : public Parse_RTCP + { + template + struct rebind { typedef Parse_RTCP_RR parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_RR() {} + Parse_RTCP_RR(Iterator const & i) : Parse_RTCP(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt32 < Iterator > Parse_32bit; + typedef Parse_Vector < Parse_RTCP_RB<>, typename Parse_RTCP::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 + struct Parse_RTCP_SR : public Parse_RTCP + { + template + struct rebind { typedef Parse_RTCP_SR parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_SR() {} + Parse_RTCP_SR(Iterator const & i) : Parse_RTCP(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt32 < Iterator > Parse_32bit; + typedef Parse_Vector < Parse_RTCP_RB<>, typename Parse_RTCP::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 + struct Parse_RTCP_item : public Parse_RTCP + { + template + struct rebind { typedef Parse_RTCP_item parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_item() {} + Parse_RTCP_item(Iterator const & i) : ParserBase(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 + struct Sentinel_EmptyList { + static bool check(List a) { return a.empty(); } + }; + + template + struct Parse_RTCP_chunk : public Parse_RTCP + { + template + struct rebind { typedef Parse_RTCP_chunk parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_chunk() {} + Parse_RTCP_chunk(Iterator const & i) : Parse_RTCP(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt32 < Iterator > Parse_32bit; + typedef Parse_UInt8 < Iterator > Parse_8bit; + typedef Parse_ListS < Parse_RTCP_item<>, Sentinel_EmptyList >, Iterator, IPacket> Parse_itemList; + + Parse_32bit ssrc() const { return Parse_32bit(this->i() ); } + Parse_itemList itemList() const { return Parse_itemList(this->i() + 4 ); } + + }; + + + template + struct Parse_RTCP_SDES : public Parse_RTCP + { + template + struct rebind { typedef Parse_RTCP_SDES parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_SDES() {} + Parse_RTCP_SDES(Iterator const & i) : Parse_RTCP(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_Vector < Parse_RTCP_chunk<>, typename Parse_RTCP::Parse_Count, Iterator > Parse_chunkVec; + + Parse_chunkVec chunkVec() const { return Parse_chunkVec(this->count(), this->i()+4 ); } + + }; + + template + struct Parse_RTCP_BYE : public Parse_RTCP + { + template + struct rebind { typedef Parse_RTCP_BYE parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_BYE() {} + Parse_RTCP_BYE(Iterator const & i) : Parse_RTCP(i) {} + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_Vector < Parse_UInt32<>, typename Parse_RTCP::Parse_Count, Iterator > Parse_ssrcVec; + + Parse_ssrcVec ssrcVec() const { return Parse_ssrcVec(this->count(), this->i()+4 ); } + + }; + + + template + struct Parse_RTCP_APP : public Parse_RTCP + { + template + struct rebind { typedef Parse_RTCP_APP parser; }; + typedef Iterator byte_iterator; + + Parse_RTCP_APP() {} + Parse_RTCP_APP(Iterator const & i) : Parse_RTCP(i) {} + + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt32 < Iterator > Parse_32bit; + typedef Parse_Vector < Parse_UInt32<>, typename Parse_RTCP::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 + { + using Packet::registerInterpreter; + + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t::ptr ptr; + + private: + template + 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 0000000..86e0d0a --- /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 +// +// 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 +#include + +#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 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(p_1.payloadType()), 200u ); + BOOST_CHECK_EQUAL( static_cast(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 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(p_2.payloadType()), 200u ); + BOOST_CHECK_EQUAL( static_cast(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(p_2.rr().rbVec().begin()->fragLost()), 0x05u ); + BOOST_CHECK_EQUAL( static_cast(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(j_2->fragLost()), 0x05u ); + BOOST_CHECK_EQUAL( static_cast(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(j_2->fragLost()), 0x05u ); + BOOST_CHECK_EQUAL( static_cast(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 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(p_3.payloadType()), 201u ); + BOOST_CHECK_EQUAL( static_cast(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(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(j->fragLost()), 0x05u ); + BOOST_CHECK_EQUAL( static_cast(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 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(p_4.payloadType()), 202u ); + BOOST_CHECK_EQUAL( static_cast(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 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(p_5.payloadType()), 203u ); + BOOST_CHECK_EQUAL( static_cast(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 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(p_6.payloadType()), 123u ); + BOOST_CHECK_EQUAL( static_cast(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(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(p_1->payloadType()), 200u ); + BOOST_CHECK_EQUAL( static_cast(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 0000000..593610a --- /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 +// +// 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(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 : \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 p (begin()); + if (!p.check(begin(),end())) + throw TruncatedPacketException(); + + int paddingOctets = 0; + if(get_prev()->padding()){ + paddingOctets = get_prev()->paddingOctet(); + } + registerInterpreter(get_prev()->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 0000000..18633be --- /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 +// +// 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 +prefix_ satcom::pkf::RTPPacket::RTPPacket(Arg const & arg) + : Packet(arg) +{} + +template +prefix_ satcom::pkf::RTPExtensionBasePacket:: +RTPExtensionBasePacket(Arg const & arg) + : Packet(arg) +{} + +template +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 0000000..9f4a6c7 --- /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 +// +// 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 + struct Parse_RTP : public ParserBase + { + template + struct rebind { typedef Parse_RTP parser; }; + typedef Iterator byte_iterator; + + Parse_RTP() {} + Parse_RTP(Iterator const & i) : ParserBase(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(b).bytes(); } + + }; + + struct RTPTypes { + typedef boost::uint16_t key_t; + }; + + class RTPPacket + : public Packet, + public Parse_RTP, + public PacketRegistryMixin + { + using Packet::registerInterpreter; + using PacketRegistryMixin::registerInterpreter; + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t::ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + + typedef Parse_UInt8 < Packet::iterator > Parse_paddingOctet; + + Parse_paddingOctet paddingOctet() const { + return Parse_paddingOctet( end() -1 ); + } + + private: + template + 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 + struct Parse_RTPExtensionBase : public ParserBase + { + template + struct rebind { typedef Parse_RTPExtensionBase parser; }; + typedef Iterator byte_iterator; + + Parse_RTPExtensionBase() {} + Parse_RTPExtensionBase(Iterator const & i) : ParserBase(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(b).bytes(); } + + + }; + + class RTPExtensionBasePacket + : public Packet, + public PacketRegistryMixin + { + using PacketRegistryMixin::registerInterpreter; + using Packet::registerInterpreter; + public: + /////////////////////////////////////////////////////////////////////////// + typedef ptr_t::ptr ptr; + + protected: + template + 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 + struct Parse_RTPUnknownExtension : public Parse_RTPExtensionBase + { + template + struct rebind { typedef Parse_RTPUnknownExtension parser; }; + typedef Iterator byte_iterator; + + Parse_RTPUnknownExtension() {} + Parse_RTPUnknownExtension(Iterator const & i) : ParserBase(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 + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t::ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + + private: + template + 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 0000000..ff3a58d --- /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 +// +// 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 +#include + +#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 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(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(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(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::ptr v (p->next()->as()); + BOOST_CHECK_EQUAL( static_cast(v->proDef()), 0x2021u ); + BOOST_CHECK_EQUAL( static_cast(v->length()), 0x04u ); + BOOST_CHECK_EQUAL( static_cast(v->ext()[0]), 0x24u ); + BOOST_CHECK_EQUAL( static_cast(v->ext()[2]), 0x26u ); + + BOOST_REQUIRE( v->next() ); + DataPacket::ptr d (v->next()->as()); + + 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(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::ptr ip (p->next()->as()); + + BOOST_CHECK_EQUAL( static_cast(ip->protocol()), 0x11u ); + + // UDP + BOOST_REQUIRE( ip->next() ); + BOOST_CHECK( ip->next()->is() ); + + UDPPacket::ptr udp (ip->next()->as()); + + 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() ); + + RTPPacket::ptr rtp (udp->next()->reinterpret()); + + 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(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::ptr ex (rtp->next()->as()); + BOOST_CHECK_EQUAL( static_cast(ex->proDef()), 0x2021u ); + BOOST_CHECK_EQUAL( static_cast(ex->length()), 0x04u ); + BOOST_CHECK_EQUAL( static_cast(ex->ext()[0]), 0x24u ); + BOOST_CHECK_EQUAL( static_cast(ex->ext()[2]), 0x26u ); + + BOOST_REQUIRE( ex->next() ); + DataPacket::ptr pay (ex->next()->as()); + + 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 0000000..f322d3d --- /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 0000000..8749617 --- /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 0000000..7f44028 --- /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 +// +// 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::RegistrationProxy + registerUDPPacket(17); +} + +prefix_ void satcom::pkf::UDPPacket::v_nextInterpreter() + const +{ + registerInterpreter(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 0000000..b49e530 --- /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 +// +// 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 +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 0000000..75cdf79 --- /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 +// +// 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 + struct Parse_UDP : public ParserBase + { + template + struct rebind { typedef Parse_UDP parser; }; + typedef Iterator byte_iterator; + + Parse_UDP() {} + Parse_UDP(Iterator const & i) : ParserBase(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 + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef ptr_t::ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + + private: + template + 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 0000000..afcb77d --- /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 +// +// 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 +#include + +#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 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(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 0000000..3607b8f --- /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 +// +// 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 struct totally_ordered {}; + template struct iterator_facade {}; + template struct intrusive_ptr { T * ptr; }; + template struct shared_ptr { T * ptr; }; + +} + +namespace std { + + struct exception {}; + template struct vector { T * elements; }; + template 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 0000000..baf1b0d --- /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 0000000..ead6517 --- /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 +// +// 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 +#include + +#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 0000000..5b3d1db --- /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 0000000..a3efbe8 Binary files /dev/null and b/Packets/structure.dia differ diff --git a/Packets/typeidvalue.cci b/Packets/typeidvalue.cci new file mode 100644 index 0000000..26d8c4f --- /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 +// +// 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()) +{} + +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 0000000..9c78ae1 --- /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 +// +// 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 +prefix_ satcom::lib::TypeIdValue::TypeIdValue(Type *) + : value_(new ValueImpl()) +{} + +template +prefix_ std::type_info const & satcom::lib::TypeIdValue::ValueImpl::id() +{ + return typeid(Type); +} + +template +prefix_ satcom::lib::TypeIdValue::Value * +satcom::lib::TypeIdValue::ValueImpl::clone() +{ + return new ValueImpl(); +} + +template +prefix_ satcom::lib::TypeIdValue const satcom::lib::typeIdValue() +{ + return TypeIdValue(static_cast(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 0000000..425c14f --- /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 +// +// 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 +#include +#include +#include + +//#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 + { + 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 TypeIdValue(Type *); + + struct Value { + virtual std::type_info const & id() = 0; + virtual Value * clone() = 0; + }; + + template + struct ValueImpl : public Value { + virtual std::type_info const & id(); + virtual Value * clone(); + }; + + boost::scoped_ptr value_; + + template friend TypeIdValue const typeIdValue(); + }; + + TypeIdValue const typeIdValue(); + + template + TypeIdValue const typeIdValue(); + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +#include "typeidvalue.cci" +//#include "typeidvalue.ct" +#include "typeidvalue.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/SConfig b/SConfig new file mode 100644 index 0000000..1a99c31 --- /dev/null +++ b/SConfig @@ -0,0 +1,9 @@ +CXX = "g++-3.4" + +BOOST_INCLUDES = "/usr/local/include/boost-1_33_1" +BOOST_TOOLSET = "gcc" +BOOST_LIBDIR = "/usr/local/lib" + +STLPORT_INCLUDES = "/usr/local/include/stlport" +STLPORT_LIB = "stlport_gcc" +STLPORT_LIBDIR = "/usr/local/lib" diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..77b5b02 --- /dev/null +++ b/SConstruct @@ -0,0 +1,22 @@ +import sys, glob +sys.path.append('satscons') +import SatSCons + +########################################################################### + +SatSCons.UseBoost(); +SatSCons.UseSTLPort(); +SatSCons.UseDoxygen(); +env = SatSCons.MakeEnvironment(); + +env.Append( + CPPPATH = [ '#' ], + LIBS = [ 'iberty' ] +) + +Export('env') + +SConscript(glob.glob("*/SConscript")) + +SatSCons.StandardTargets(env) +SatSCons.GlobalTargets(env) diff --git a/Scheduler/SConscript b/Scheduler/SConscript new file mode 100644 index 0000000..fc9284e --- /dev/null +++ b/Scheduler/SConscript @@ -0,0 +1,10 @@ +Import('env') +import SatSCons + +########################################################################### + +SatSCons.StandardTargets(env) +SatSCons.Lib(env, + library = 'Scheduler', + sources = SatSCons.GlobSources(), + LIBS = [ 'Utils' ]) diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc new file mode 100644 index 0000000..21885f2 --- /dev/null +++ b/Scheduler/Scheduler.cc @@ -0,0 +1,203 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 signal handling +// Here a basic concept of how to add signal support to the scheduler: +// +// Every signal to be reported by the scheduler will be asigned a +// generic signal handler by the scheduler. This signal handler will +// use longjmp (juck) to report this signal back to the scheduler +// main-loop. +// +// To make this safe, the main-loop will look something like: +// +// int signal = setjmp(jmpBuffer_); +// if (signal == 0) { +// // unblock all signals which are registered with the +// // scheduler +// // call epoll +// // block all relevant signals again +// } +// +// // now handle the event +// +// The signal handler is then simply defined as +// +// static void Scheduler::sigHandler(int signal) +// { +// // make sure to restore the signal handler here if +// // necessary +// longjmp(Scheduler::instance().jmpBuffer_,signal); +// } +// +// You should use sigaction to register the signal handlers and define +// a sa_mask so all Scheduler-registered signals are automatically +// *blocked* whenever one of the signals is called (including the +// called signal!). This ensures, that no two signals can be delivered +// on top of each other. And of course any signal registered with the +// scheduler must be blocked as soon as it is registered with the +// scheduler. + +// TODO: Multithreading support +// To support multithreading, the static member Scheduler::instance() +// must return a thread-local value (that is Scheduler::instance() +// must allocate one Scheduler instance per thread) + +// Definition of non-inline non-template functions + +#include "Scheduler.hh" +//#include "Scheduler.ih" + +// Custom includes +#include +#include +#include "Utils/Exception.hh" + +static const int EPollInitialSize = 16; + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ satcom::lib::Scheduler::Scheduler & satcom::lib::Scheduler::instance() +{ + static Scheduler instance; + return instance; +} + +prefix_ satcom::lib::Scheduler::Scheduler() + : epollFd_(epoll_create(EPollInitialSize)) +{ + if (epollFd_<0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::Scheduler::add(int fd, Callback const & cb, EventId eventMask) +{ + FdTable::iterator i (fdTable_.find(fd)); + int action (EPOLL_CTL_MOD); + if (i == fdTable_.end()) { + action = EPOLL_CTL_ADD; + i = fdTable_.insert(std::make_pair(fd, EventSpec())).first; + } + + if (eventMask & EV_READ) i->second.cb_read = cb; + if (eventMask & EV_PRIO) i->second.cb_prio = cb; + if (eventMask & EV_WRITE) i->second.cb_write = cb; + if (eventMask & EV_HUP) i->second.cb_hup = cb; + if (eventMask & EV_ERR) i->second.cb_err = cb; + + epoll_event ev; + memset(&ev,0,sizeof(ev)); + ev.events = i->second.epollMask(); + ev.data.fd = fd; + + if (epoll_ctl(epollFd_, action, fd, &ev)<0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::Scheduler::remove(int fd, EventId eventMask) +{ + FdTable::iterator i (fdTable_.find(fd)); + if (i == fdTable_.end()) + return; + + if (eventMask & EV_READ) i->second.cb_read = 0; + if (eventMask & EV_PRIO) i->second.cb_prio = 0; + if (eventMask & EV_WRITE) i->second.cb_write = 0; + if (eventMask & EV_HUP) i->second.cb_hup = 0; + if (eventMask & EV_ERR) i->second.cb_err = 0; + + epoll_event ev; + memset(&ev,0,sizeof(ev)); + ev.events = i->second.epollMask(); + ev.data.fd = fd; + + int action (EPOLL_CTL_MOD); + if (ev.events==0) { + action = EPOLL_CTL_DEL; + fdTable_.erase(i); + } + + if (epoll_ctl(epollFd_, action, fd, &ev)<0) + throw SystemException(errno); +} + +prefix_ int satcom::lib::Scheduler::EventSpec::epollMask() + const +{ + int mask (0); + if (cb_read) mask |= EPOLLIN; + if (cb_prio) mask |= EPOLLPRI; + if (cb_write) mask |= EPOLLOUT; + if (cb_hup) mask |= EPOLLHUP; + if (cb_err) mask |= EPOLLERR; + return mask; +} + +prefix_ void satcom::lib::Scheduler::process() +{ + terminate_ = false; + while (! terminate_) { + struct epoll_event ev; + int events = epoll_wait(epollFd_, &ev, 1, 1000); + if (events<0) + // Hmm ... man epoll says, it will NOT return with EINTR ?? + throw SystemException(errno); + if (events==0) + continue; + + FdTable::iterator i = fdTable_.find(ev.data.fd); + BOOST_ASSERT (i != fdTable_.end() ); + EventSpec const & spec (i->second); + + if (ev.events & EPOLLIN) { + BOOST_ASSERT(spec.cb_read); + spec.cb_read(ev.data.fd, EV_READ); + } + else if (ev.events & EPOLLPRI) { + BOOST_ASSERT(spec.cb_prio); + spec.cb_prio (ev.data.fd, EV_PRIO); + } + else if (ev.events & EPOLLOUT) { + BOOST_ASSERT(spec.cb_write); + spec.cb_write(ev.data.fd, EV_WRITE); + } + + else if (ev.events & EPOLLHUP) { + BOOST_ASSERT(spec.cb_hup); + spec.cb_hup(ev.data.fd, EV_HUP); + } + else if (ev.events & EPOLLERR) { + BOOST_ASSERT(spec.cb_err); + spec.cb_err(ev.data.fd, EV_ERR); + } + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Scheduler/Scheduler.cci b/Scheduler/Scheduler.cci new file mode 100644 index 0000000..f34286e --- /dev/null +++ b/Scheduler/Scheduler.cci @@ -0,0 +1,44 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "Scheduler.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +prefix_ void satcom::lib::Scheduler::terminate() +{ + terminate_ = true; +} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Scheduler/Scheduler.ct b/Scheduler/Scheduler.ct new file mode 100644 index 0000000..05afa48 --- /dev/null +++ b/Scheduler/Scheduler.ct @@ -0,0 +1,39 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "Scheduler.ih" + +// Custom includes + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Scheduler/Scheduler.cti b/Scheduler/Scheduler.cti new file mode 100644 index 0000000..7ef1148 --- /dev/null +++ b/Scheduler/Scheduler.cti @@ -0,0 +1,55 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "Scheduler.ih" + +// Custom includes +#include + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +prefix_ void satcom::lib::Scheduler::add(Handle const & handle, + typename GenericCallback::Callback const & cb, + EventId eventMask) +{ + add(retrieve_filehandle(handle),boost::bind(cb,handle,_2),eventMask); +} + +template +prefix_ void satcom::lib::Scheduler::remove(Handle const & handle, EventId eventMask) +{ + // retrieve_filehandle is found via ADL + remove(retrieve_filehandle(handle),eventMask); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh new file mode 100644 index 0000000..e731db4 --- /dev/null +++ b/Scheduler/Scheduler.hh @@ -0,0 +1,128 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_Scheduler_ +#define HH_Scheduler_ 1 + +// Custom includes +#include +#include +#include +#include + +//#include "scheduler.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + /** \brief Singleton class to manage the event loop + + This class manages a single select() type event loop. A + customer of this class may register any number of file + descriptiors with this class and pass callback functions to be + called on input, output or error. This functions are specified + using boost::function objects + */ + class Scheduler + : boost::noncopyable + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + enum EventId { EV_NONE=0, + EV_READ=1, EV_PRIO=2, EV_WRITE=4, EV_HUP=8, EV_ERR=16, + EV_ALL=31 }; + + template + struct GenericCallback { + typedef boost::function::param_type, + EventId) > Callback; + }; + typedef GenericCallback::Callback Callback; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + // private default constructor + // no copy constructor + // no copy assignment + // default destructor + // no conversion constructors + + static Scheduler & instance(); + + ///@} + /////////////////////////////////////////////////////////////////////////// + + void add(int fd, Callback const & cb, EventId eventMask = EV_ALL); + void remove(int fd, EventId eventMask = EV_ALL); + + template + void add(Handle const & handle, + typename GenericCallback::Callback const & cb, + EventId eventMask = EV_ALL); + template + void remove(Handle const & handle, EventId eventMask = EV_ALL); + + void process(); + + void terminate(); + + protected: + + private: + Scheduler(); + + struct EventSpec + { + Callback cb_read; + Callback cb_prio; + Callback cb_write; + Callback cb_hup; + Callback cb_err; + + int epollMask() const; + }; + + typedef std::map FdTable; + + FdTable fdTable_; + int epollFd_; + bool terminate_; + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +#include "Scheduler.cci" +#include "Scheduler.ct" +#include "Scheduler.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Scheduler/Scheduler.test.cc b/Scheduler/Scheduler.test.cc new file mode 100644 index 0000000..fb5ae35 --- /dev/null +++ b/Scheduler/Scheduler.test.cc @@ -0,0 +1,249 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "scheduler.test.hh" +//#include "scheduler.test.ih" + +// Custom includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Scheduler.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::lib; + +namespace { + + char const * SOCK_PATH = "/tmp/sched_test.sock"; + + void error(char const * fn, char const * proc="") + { + std::cerr << "\n" << proc << fn << ": " << strerror(errno) << std::endl; + } + + void fail(char const * fn) + { + error(fn,"server: "); + _exit(1); + } + + void server() + { + int sock = socket(PF_UNIX,SOCK_STREAM,0); + if (sock<0) fail("socket"); + struct sockaddr_un sun; + memset(&sun,0,sizeof(sun)); + sun.sun_family = AF_UNIX; + strcpy(sun.sun_path,SOCK_PATH); + if (bind(sock,(struct sockaddr*)&sun,sizeof(sun))<0) fail("bind"); + if (listen(sock,1)<0) fail("listen"); + int conn = accept(sock,0,0); + if (conn < 0) fail("accept"); + + /////////////////////////////////////////////////////////////////////////// + + if (write(conn,"READ",4)<0) fail("write"); + char buffer[1024]; + int size = read(conn,buffer,1024); + if (size<0) fail("read"); + if (size == 5) { + buffer[5] = 0; + if (strcmp(buffer,"WRITE")==0) { + if (write(conn,"OK",2)<0) fail("write"); + } else + if (write(conn,"FAIL",4)<0) fail("write"); + } else + if (write(conn,"FAIL",4)<0) fail("write"); + + /////////////////////////////////////////////////////////////////////////// + + close(conn); + close(sock); + } + + int start_server() + { + unlink(SOCK_PATH); + int pid = fork(); + if (pid == 0) { + server(); + _exit(0); + } + if (pid < 0) { + error("fork"); + return 0; + } + + sleep(1); // Wait for the server socket to be opened + return pid; + } + + bool stop_server(int pid) + { + sleep(1); // Wait for the server to terminate + if (kill(pid,SIGTERM)<0) { + error("kill"); + return false; + } + int status = 0; + if (waitpid(pid,&status,0)<0) { + error("waitpid"); + return false; + } + unlink(SOCK_PATH); + if (WIFSIGNALED(status)) { + std::cerr << "\nserver terminated with signal " << WTERMSIG(status) << std::endl; + return false; + } + if (WEXITSTATUS(status)!=0) { + std::cerr << "\nserver terminated with exit status " << WEXITSTATUS(status) << std::endl; + return false; + } + return true; + } + + char buffer[1024]; + int size; + int event; + + void callback(int fd, Scheduler::EventId ev) + { + event = ev; + switch (event) { + case Scheduler::EV_READ: + size = recv(fd,buffer,1024,0); + break; + case Scheduler::EV_PRIO: + size = recv(fd,buffer,1024,MSG_OOB); + Scheduler::instance().terminate(); + break; + case Scheduler::EV_WRITE: + size = write(fd,buffer,size); + Scheduler::instance().terminate(); + break; + case Scheduler::EV_HUP: + case Scheduler::EV_ERR: + case Scheduler::EV_NONE: + case Scheduler::EV_ALL: + ; + } + Scheduler::instance().terminate(); + } + + struct HandleWrapper + { + HandleWrapper(int fd,std::string const & tag) : fd_(fd), tag_(tag) {} + int fd_; + std::string tag_; + }; + + int retrieve_filehandle(HandleWrapper const & handle) + { + return handle.fd_; + } + + void handleCallback(HandleWrapper const & handle, Scheduler::EventId event) + { + if (handle.tag_ != "TheTag") + return; + callback(handle.fd_,event); + } +} + +BOOST_AUTO_UNIT_TEST(scheduler) +{ + int pid = start_server(); + BOOST_REQUIRE (pid); + + int sock = socket(PF_UNIX,SOCK_STREAM,0); + if (sock<0) { + error("socket"); + BOOST_FAIL("socket"); + } + struct sockaddr_un sun; + memset(&sun,0,sizeof(sun)); + sun.sun_family = AF_UNIX; + strcpy(sun.sun_path,SOCK_PATH); + + if (connect(sock,(struct sockaddr*)&sun,sizeof(sun))<0) { + error("connect"); + BOOST_FAIL("connect"); + } + + /////////////////////////////////////////////////////////////////////////// + + BOOST_CHECK_NO_THROW( Scheduler::instance() ); + + BOOST_CHECK_NO_THROW( Scheduler::instance().add(sock,&callback,Scheduler::EV_READ) ); + event = Scheduler::EV_NONE; + BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); + BOOST_CHECK_EQUAL( event, Scheduler::EV_READ ); + BOOST_REQUIRE_EQUAL( size, 4 ); + buffer[size]=0; + BOOST_CHECK_EQUAL( buffer, "READ" ); + + HandleWrapper handle(sock,"TheTag"); + BOOST_CHECK_NO_THROW( Scheduler::instance().add(handle,&handleCallback,Scheduler::EV_WRITE) ); + strcpy(buffer,"WRITE"); + size=5; + event = Scheduler::EV_NONE; + BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); + BOOST_CHECK_EQUAL( event, Scheduler::EV_WRITE ); + + BOOST_CHECK_NO_THROW( Scheduler::instance().remove(handle,Scheduler::EV_WRITE) ); + event = Scheduler::EV_NONE; + BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); + BOOST_CHECK_EQUAL( event, Scheduler::EV_READ ); + BOOST_REQUIRE_EQUAL( size, 2 ); + buffer[size]=0; + BOOST_CHECK_EQUAL( buffer, "OK" ); + + /////////////////////////////////////////////////////////////////////////// + + close(sock); + + BOOST_CHECK (stop_server(pid)); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Scheduler/main.test.cc b/Scheduler/main.test.cc new file mode 100644 index 0000000..fd4c97a --- /dev/null +++ b/Scheduler/main.test.cc @@ -0,0 +1,43 @@ +// $Id: main.test.cc 32 2006-03-23 16:24:56Z sbund $ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// End: diff --git a/Socket/AddressingPolicy.hh b/Socket/AddressingPolicy.hh new file mode 100644 index 0000000..b13ac1d --- /dev/null +++ b/Socket/AddressingPolicy.hh @@ -0,0 +1,51 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_AddressingPolicy_ +#define HH_AddressingPolicy_ 1 + +// Custom includes +#include "SocketPolicy.hh" + +//#include "AddressingPolicy.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + struct NoAddressingPolicy : public AddressingPolicyBase + {}; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "AddressingPolicy.cci" +//#include "AddressingPolicy.ct" +//#include "AddressingPolicy.cti" +//#include "AddressingPolicy.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/BSDSocketProtocol.cc b/Socket/BSDSocketProtocol.cc new file mode 100644 index 0000000..1176861 --- /dev/null +++ b/Socket/BSDSocketProtocol.cc @@ -0,0 +1,98 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "BSDSocketProtocol.hh" +//#include "BSDSocketProtocol.ih" + +// Custom includes +#include +#include +#include +#include "SocketHandle.hh" + +//#include "BSDSocketProtocol.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ std::pair satcom::lib::BSDSocketProtocol::linger() + const +{ + struct linger ling; + socklen_t len = sizeof(ling); + ::memset(&ling,sizeof(ling),0); + if (::getsockopt(body().fd(),SOL_SOCKET,SO_LINGER,&ling,&len) < 0) + throw SystemException(errno); + return std::make_pair(ling.l_onoff, ling.l_linger); +} + +prefix_ void satcom::lib::BSDSocketProtocol::linger(bool enable, unsigned timeout) + const +{ + struct linger ling; + ling.l_onoff = enable; + ling.l_linger = timeout; + if (::setsockopt(body().fd(),SOL_SOCKET,SO_LINGER,&ling,sizeof(ling)) < 0) + throw SystemException(errno); +} + +prefix_ struct timeval satcom::lib::BSDSocketProtocol::timestamp() + const +{ + // TODO: Check, why this fails with ENOFILE (!!!!) at least when + // called from a tcp socket. Further investigation necessary ... + struct timeval tv; + if (::ioctl(body().fd(), SIOCGSTAMP, &tv) < 0) + throw SystemException(errno); + return tv; +} + +/////////////////////////////////////////////////////////////////////////// + +prefix_ bool satcom::lib::AddressableBSDSocketProtocol::reuseaddr() + const +{ + int value; + socklen_t len (sizeof(value)); + if (::getsockopt(body().fd(),SOL_SOCKET,SO_REUSEADDR,&value,&len) < 0) + throw SystemException(errno); + return value; +} + +prefix_ void satcom::lib::AddressableBSDSocketProtocol::reuseaddr(bool value) + const +{ + int ivalue (value); + if (::setsockopt(body().fd(),SOL_SOCKET,SO_REUSEADDR,&ivalue,sizeof(ivalue)) < 0) + throw SystemException(errno); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "BSDSocketProtocol.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/BSDSocketProtocol.hh b/Socket/BSDSocketProtocol.hh new file mode 100644 index 0000000..3d35599 --- /dev/null +++ b/Socket/BSDSocketProtocol.hh @@ -0,0 +1,68 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_BSDSocketProtocol_ +#define HH_BSDSocketProtocol_ 1 + +// Custom includes +#include +#include "SocketProtocol.hh" + +//#include "BSDSocketProtocol.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + class BSDSocketProtocol + : public virtual SocketProtocol + { + public: + std::pair linger() const; + void linger(bool enable, unsigned timeout) const; + + struct timeval timestamp() const; + }; + + class AddressableBSDSocketProtocol + : public virtual SocketProtocol + { + public: + bool reuseaddr() const; + void reuseaddr(bool value) const; + }; + +}} + + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "BSDSocketProtocol.cci" +//#include "BSDSocketProtocol.ct" +//#include "BSDSocketProtocol.cti" +//#include "BSDSocketProtocol.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/BufferingPolicy.cc b/Socket/BufferingPolicy.cc new file mode 100644 index 0000000..e1c3171 --- /dev/null +++ b/Socket/BufferingPolicy.cc @@ -0,0 +1,81 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "BufferingPolicy.hh" +//#include "BufferingPolicy.ih" + +// Custom includes +#include +#include +#include +#include "Utils/Exception.hh" + +//#include "BufferingPolicy.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ unsigned satcom::lib::SocketBufferingPolicy::rcvbuf(FileHandle handle) +{ + unsigned size; + socklen_t len (sizeof(size)); + if (::getsockopt(handle.fd(),SOL_SOCKET,SO_RCVBUF,&size,&len) < 0) + throw SystemException(errno); + // Linux doubles the bufer size on setting the RCVBUF to cater for internal + // headers. We fix this up here .. (see lkml FAQ) + return size/2; +} + +prefix_ void satcom::lib::SocketBufferingPolicy::rcvbuf(FileHandle handle, unsigned size) +{ + if (::setsockopt(handle.fd(),SOL_SOCKET,SO_RCVBUF,&size,sizeof(size)) < 0) + throw SystemException(errno); +} + +prefix_ unsigned satcom::lib::SocketBufferingPolicy::sndbuf(FileHandle handle) +{ + unsigned size; + socklen_t len (sizeof(size)); + if (::getsockopt(handle.fd(),SOL_SOCKET,SO_SNDBUF,&size,&len) < 0) + throw SystemException(errno); + // Linux doubles the bufer size on setting the SNDBUF to cater for internal + // headers. We fix this up here .. (see lkml FAQ) + return size/2; + +} + +prefix_ void satcom::lib::SocketBufferingPolicy::sndbuf(FileHandle handle, unsigned size) +{ + if (::setsockopt(handle.fd(),SOL_SOCKET,SO_SNDBUF,&size,sizeof(size)) < 0) + throw SystemException(errno); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "BufferingPolicy.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/BufferingPolicy.hh b/Socket/BufferingPolicy.hh new file mode 100644 index 0000000..9dccd88 --- /dev/null +++ b/Socket/BufferingPolicy.hh @@ -0,0 +1,59 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_BufferingPolicy_ +#define HH_BufferingPolicy_ 1 + +// Custom includes +#include "FileHandle.hh" +#include "SocketPolicy.hh" + +//#include "BufferingPolicy.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + // TODO: Should this be dependent on Read / WritePolicy ? + struct SocketBufferingPolicy : public BufferingPolicyBase + { + static unsigned rcvbuf(FileHandle handle); + static void rcvbuf(FileHandle handle, unsigned size); + + static unsigned sndbuf(FileHandle handle); + static void sndbuf(FileHandle handle, unsigned size); + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "BufferingPolicy.cci" +//#include "BufferingPolicy.ct" +//#include "BufferingPolicy.cti" +//#include "BufferingPolicy.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ClientSocketHandle.ct b/Socket/ClientSocketHandle.ct new file mode 100644 index 0000000..1e7fa7b --- /dev/null +++ b/Socket/ClientSocketHandle.ct @@ -0,0 +1,112 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "ClientSocketHandle.ih" + +// Custom includes + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template +prefix_ std::string satcom::lib::ClientSocketHandle::read() +{ + std::string rv; + this->read(rv); + return rv; +} + +template +prefix_ void satcom::lib::ClientSocketHandle::read(std::string & buffer) +{ + unsigned nread = available(); + // FIXME: This is not necessary correct and more or less a hack ... + buffer.assign(nread,0); + unsigned rv = this->read(const_cast(buffer.data()),nread); + if (rv < nread) + buffer.erase(buffer.begin()+rv,buffer.end()); +} + +template +prefix_ std::pair +satcom::lib::ClientSocketHandle::readfrom() +{ + std::string rv; + typename Policy::AddressingPolicy::Address addr; + this->readfrom(rv,addr); + return std::make_pair(rv,addr); +} + +template +prefix_ void satcom::lib::ClientSocketHandle:: +readfrom(std::string & buffer, typename Policy::AddressingPolicy::Address & from) +{ + unsigned nread = available(); + // FIXME: This is not necessary correct and more or less a hack ... + buffer.assign(nread,0); + unsigned rv = this->readfrom(const_cast(buffer.data()), nread, from); + if (rv < nread) + buffer.erase(buffer.begin()+rv,buffer.end()); +} + +template +prefix_ unsigned satcom::lib::ClientSocketHandle::write(std::string const & data) +{ + unsigned written = this->write(data.data(),data.size()); + if (written == 0) + throw SystemException(EPIPE); + // This implementation ensures, we only call blocking() when + // necessary (since it incurs a system call overhead ...) + if (written < data.size() && this->blocking()) + // We need to enforce in the WritePolicy implementation, that + // DatagramFramingPolicy sockets will ALWAYS either write the + // complete datagram or nothing at all + while (written < data.size()) { + unsigned n = this->write(data.data()+written,data.size()-written); + if (n == 0) + throw SystemException(EPIPE); + written += n; + } + return written; +} + +template +prefix_ unsigned satcom::lib::ClientSocketHandle::available() +{ + unsigned nread = this->protocol().available(); + if (nread == 0 && this->blocking()) { + this->waitReadable(); + nread = this->protocol().available(); + } + return nread; +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ClientSocketHandle.cti b/Socket/ClientSocketHandle.cti new file mode 100644 index 0000000..eec7cf7 --- /dev/null +++ b/Socket/ClientSocketHandle.cti @@ -0,0 +1,222 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "ClientSocketHandle.ih" + +// Custom includes +#include + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +template +prefix_ satcom::lib::ClientSocketHandle:: +ClientSocketHandle(ClientSocketHandle other, + typename SocketHandle::template IsCompatible::type *) + : SocketHandle(other,true) +{} + +template +prefix_ satcom::lib::ClientSocketHandle::ClientSocketHandle(FileHandle other, + bool isChecked) + : SocketHandle(other, isChecked) +{} + +template +prefix_ satcom::lib::ClientSocketHandle:: +ClientSocketHandle(std::auto_ptr protocol, int fd) + : SocketHandle(protocol,false) +{ + this->body().fd(fd); +} + +template +template +prefix_ typename satcom::lib::SocketHandle::template IsCompatible::type const & +satcom::lib::ClientSocketHandle::operator=(ClientSocketHandle other) +{ + assign(other); + return *this; +} + +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// reading and writing + +template +prefix_ unsigned satcom::lib::ClientSocketHandle::read(char * buffer, + unsigned size) +{ + return Policy::ReadPolicy::read(*this, buffer, size); +} + +template +prefix_ unsigned satcom::lib::ClientSocketHandle:: +readfrom(char * buffer, unsigned size, typename Policy::AddressingPolicy::Address & from) +{ + return Policy::ReadPolicy::readfrom(*this, buffer, size, from); +} + +template +prefix_ unsigned satcom::lib::ClientSocketHandle::write(char const * buffer, + unsigned size) +{ + return Policy::WritePolicy::write(*this, buffer, size); +} + +template +prefix_ unsigned satcom::lib::ClientSocketHandle:: +writeto(typename boost::call_traits::param_type addr, + std::string const & data) +{ + return this->writeto(addr, data.data(), data.size()); +} + +template +prefix_ unsigned satcom::lib::ClientSocketHandle:: +writeto(typename boost::call_traits::param_type addr, + char const * buffer, unsigned size) +{ + return Policy::WritePolicy::writeto(*this, addr, buffer, size); +} + +/////////////////////////////////////////////////////////////////////////// +// addressing + +template +prefix_ typename Policy::AddressingPolicy::Address +satcom::lib::ClientSocketHandle::peer() +{ + typename Policy::AddressingPolicy::Address addr; + this->peer(addr); + return addr; +} + +template +prefix_ void satcom::lib::ClientSocketHandle:: +peer(typename Policy::AddressingPolicy::Address & addr) +{ + Policy::AddressingPolicy::peer(*this,addr); +} + +template +prefix_ typename Policy::AddressingPolicy::Address +satcom::lib::ClientSocketHandle::local() +{ + typename Policy::AddressingPolicy::Address addr; + this->local(addr); + return addr; +} + +template +prefix_ void satcom::lib::ClientSocketHandle:: +local(typename Policy::AddressingPolicy::Address & addr) +{ + Policy::AddressingPolicy::local(*this,addr); +} + +template +prefix_ void satcom::lib::ClientSocketHandle::connect(AddressParam addr) +{ + Policy::AddressingPolicy::connect(*this,addr); +} + +template +prefix_ void satcom::lib::ClientSocketHandle:: +bind(typename boost::call_traits::param_type addr) +{ + Policy::AddressingPolicy::bind(*this,addr); +} + +/////////////////////////////////////////////////////////////////////////// +// Buffering + +template +prefix_ unsigned satcom::lib::ClientSocketHandle::rcvbuf() +{ + return Policy::BufferingPolicy::rcvbuf(*this); +} + +template +prefix_ void satcom::lib::ClientSocketHandle::rcvbuf(unsigned size) +{ + Policy::BufferingPolicy::rcvbuf(*this,size); +} + +template +prefix_ unsigned satcom::lib::ClientSocketHandle::sndbuf() +{ + return Policy::BufferingPolicy::sndbuf(*this); +} + +template +prefix_ void satcom::lib::ClientSocketHandle::sndbuf(unsigned size) +{ + Policy::BufferingPolicy::sndbuf(*this,size); +} + +/////////////////////////////////////////////////////////////////////////// + +template +prefix_ satcom::lib::ClientSocketHandle +satcom::lib::ClientSocketHandle::cast_static(FileHandle handle) +{ + return ClientSocketHandle(handle, true); +} + +template +prefix_ satcom::lib::ClientSocketHandle +satcom::lib::ClientSocketHandle::cast_dynamic(FileHandle handle) +{ + SocketHandle h (SocketHandle::cast_dynamic(handle)); + if (static_cast(FileHandle::body(h)).isServer()) + throw std::bad_cast(); + return cast_static(handle); +} + +template +prefix_ void satcom::lib::ClientSocketHandle::state(SocketStateMap & map, unsigned lod) +{ + map["handle"] = prettyName(typeid(*this)); + this->body().state(map,lod); +} + +template +prefix_ std::string satcom::lib::ClientSocketHandle::dumpState(unsigned lod) +{ + SocketStateMap map; + state(map,lod); + return detail::dumpState(map); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ClientSocketHandle.hh b/Socket/ClientSocketHandle.hh new file mode 100644 index 0000000..0e670ab --- /dev/null +++ b/Socket/ClientSocketHandle.hh @@ -0,0 +1,156 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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: Move all not template-parameter dependent code into a +// non-template base class + +#ifndef HH_ClientSocketHandle_ +#define HH_ClientSocketHandle_ 1 + +// Custom includes +#include +#include "SocketHandle.hh" + +//#include "ClientSocketHandle.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + template class ServerSocketHandle; + + /** \brief + */ + template + class ClientSocketHandle + : public SocketHandle + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef typename Policy::AddressingPolicy::Address Address; + typedef typename boost::call_traits

::param_type AddressParam; + typedef ServerSocketHandle ServerSocketHandle; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + // no default constructor + // default copy constructor + // default copy assignment + // default destructor + + // conversion constructors + template + ClientSocketHandle(ClientSocketHandle other, + typename SocketHandle::template IsCompatible::type * = 0); + + template + typename SocketHandle::template IsCompatible::type const & + operator=(ClientSocketHandle other); + + ///@} + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + ///\name reading and writing + ///@{ + + // read from socket (connected or unconnected) + std::string read (); + void read (std::string & buffer); + unsigned read (char * buffer, unsigned size); + + // read from unconnected socket returning peer address + std::pair + readfrom (); + void readfrom (std::string & buffer, Address & from); + unsigned readfrom (char * buffer, unsigned size, Address & from); + + // write to connected socket + unsigned write (std::string const & data); + unsigned write (char const * buffer, unsigned size); + + // write to unconnected socket + unsigned writeto (AddressParam addr, std::string const & data); + unsigned writeto (AddressParam addr, char const * buffer, unsigned size); + + ///@} + + /////////////////////////////////////////////////////////////////////////// + ///\name Addressing + ///@{ + + void connect (AddressParam addr); + void bind (AddressParam addr); + + Address peer (); + void peer (Address & addr); + Address local (); + void local (Address & addr); + + ///@} + + /////////////////////////////////////////////////////////////////////////// + ///\name Buffering + ///@{ + + unsigned rcvbuf (); + void rcvbuf (unsigned size); + unsigned sndbuf (); + void sndbuf (unsigned size); + + ///@} + + static ClientSocketHandle cast_static(FileHandle handle); + static ClientSocketHandle cast_dynamic(FileHandle handle); + + // we need to override both since SocketHandle is *not* polymorphic + void state(SocketStateMap & map, unsigned lod=0); + std::string dumpState(unsigned lod=0); + + protected: + ClientSocketHandle(FileHandle other, bool isChecked); + explicit ClientSocketHandle(std::auto_ptr protocol, + int fd = -1); + + private: + unsigned available(); + + friend class satcom::lib::ServerSocketHandle; + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "ClientSocketHandle.cci" +#include "ClientSocketHandle.ct" +#include "ClientSocketHandle.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ClientSocketHandle.test.cc b/Socket/ClientSocketHandle.test.cc new file mode 100644 index 0000000..e82c57d --- /dev/null +++ b/Socket/ClientSocketHandle.test.cc @@ -0,0 +1,139 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "ClientSocketHandle.test.hh" +//#include "ClientSocketHandle.test.ih" + +// Custom includes +#include "SocketPolicy.test.hh" +#include "SocketProtocol.test.hh" +#include "ClientSocketHandle.hh" +#include "AddressingPolicy.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + + namespace sl = satcom::lib; + + class MySocketHandle + : public sl::ClientSocketHandle + { + public: + MySocketHandle() + : sl::ClientSocketHandle( + std::auto_ptr(new sl::test::SomeProtocol())) + {} + }; +} + +BOOST_AUTO_UNIT_TEST(clientSocketHandle) +{ + BOOST_CHECKPOINT("Constructing socket handle"); + MySocketHandle myh; + + // conversion to other socket handles + { + typedef sl::MakeSocketPolicy< + sl::test::SomeFramingPolicy, + sl::test::SomeReadPolicy, + sl::test::SomeWritePolicy + >::policy OtherSocketPolicy; + typedef sl::SocketHandle OtherSocketHandle; + + BOOST_CHECKPOINT("Copy-constructing socket handle"); + OtherSocketHandle osh (myh); + BOOST_CHECKPOINT("Assigning socket handle"); + osh = myh; + typedef sl::ClientSocketHandle SomeSocketHandle; + BOOST_CHECKPOINT("static_casting socket handle"); + SomeSocketHandle ssh = + sl::static_socket_cast(osh); + BOOST_CHECK_NO_THROW( sl::dynamic_socket_cast(osh) ); + typedef sl::ClientSocketHandle::policy> SomeOtherSocketHandle; + BOOST_CHECK_THROW( sl::dynamic_socket_cast(osh), + std::bad_cast ); + } + + // reading and writing + BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.read(), "TEST-READ" ) ); + { + std::string buf("FOO-BAR"); + BOOST_CHECK_NO_THROW( myh.read(buf) ); + BOOST_CHECK_EQUAL( buf, "TEST-READ" ); + } + { + char buf[11]; + ::strcpy(buf,"0123456789"); + BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.read(buf,10), 9u ) ); + BOOST_CHECK_EQUAL( buf, "TEST-READ9" ); + } + + BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.readfrom().first, "TEST-READ" ) ); + { + std::string buf("FOO-BAR"); + unsigned addr; + BOOST_CHECK_NO_THROW( myh.readfrom(buf,addr) ); + BOOST_CHECK_EQUAL( buf, "TEST-READ" ); + } + { + char buf[11]; + unsigned addr; + ::strcpy(buf,"0123456789"); + BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.readfrom(buf,10,addr), 9u ) ); + BOOST_CHECK_EQUAL( buf, "TEST-READ9" ); + } + + BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.write("TEST-WRITE"), 10u ) ); + BOOST_CHECK_THROW( myh.write("TEST"),satcom::lib::SystemException ); + BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.write("TEST-WRITE9",10), 10u ) ); + BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.writeto(0,"TEST-WRITE"), 10u ) ); + BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.writeto(0,"TEST-WRITE9",10), 10u ) ); + + BOOST_CHECK_NO_THROW( myh.connect(0) ); + BOOST_CHECK_NO_THROW( myh.bind(0) ); + BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.peer(), 1u ) ); + BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.local(), 2u ) ); + + BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.rcvbuf(), 0u ) ); + BOOST_CHECK_NO_THROW( myh.rcvbuf(1) ); + BOOST_CHECK_NO_THROW( BOOST_CHECK_EQUAL( myh.sndbuf(), 0u ) ); + BOOST_CHECK_NO_THROW( myh.sndbuf(1) ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/CommunicationPolicy.cc b/Socket/CommunicationPolicy.cc new file mode 100644 index 0000000..8523966 --- /dev/null +++ b/Socket/CommunicationPolicy.cc @@ -0,0 +1,74 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "CommunicationPolicy.hh" +//#include "CommunicationPolicy.ih" + +// Custom includes +#include +#include +#include +#include "Utils/Exception.hh" +#include "ServerSocketHandle.hh" + +//#include "CommunicationPolicy.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ void satcom::lib::ConnectedCommunicationPolicy::listen(FileHandle handle, + unsigned backlog) +{ + ::listen(handle.fd(),backlog); +} + +prefix_ int satcom::lib::ConnectedCommunicationPolicy::do_accept(FileHandle handle, + struct sockaddr * addr, + unsigned len) +{ + int rv = -1; + do { + rv = ::accept(handle.fd(),addr,&len); + if (rv < 0) + switch (errno) { + case EWOULDBLOCK: + return -1; + break; + case EINTR: + break; + default: + throw SystemException(errno); + } + } while (rv<0); + return rv; +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "CommunicationPolicy.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/CommunicationPolicy.cti b/Socket/CommunicationPolicy.cti new file mode 100644 index 0000000..f3be50d --- /dev/null +++ b/Socket/CommunicationPolicy.cti @@ -0,0 +1,48 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "CommunicationPolicy.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +prefix_ int satcom::lib::ConnectedCommunicationPolicy:: +accept(ServerSocketHandle handle, + typename ServerSocketHandle::Address & address, + typename IfAddressingPolicyIsNot::type *) +{ + return do_accept(handle,address.sockaddr_p(),address.sockaddr_len()); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/CommunicationPolicy.hh b/Socket/CommunicationPolicy.hh new file mode 100644 index 0000000..e5ad207 --- /dev/null +++ b/Socket/CommunicationPolicy.hh @@ -0,0 +1,68 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_CommunicationPolicy_ +#define HH_CommunicationPolicy_ 1 + +// Custom includes +#include "SocketPolicy.hh" +#include "AddressingPolicy.hh" +#include "FileHandle.hh" + +//#include "CommunicationPolicy.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +struct sockaddr; + +namespace satcom { +namespace lib { + + template class ServerSocketHandle; + + struct ConnectedCommunicationPolicy : public CommunicationPolicyBase + { + static void listen(FileHandle handle, unsigned backlog); + template + static int accept(ServerSocketHandle handle, + typename ServerSocketHandle::Address & address, + typename IfAddressingPolicyIsNot::type * = 0); + private: + static int do_accept(FileHandle handle, struct sockaddr * addr, unsigned len); + }; + + struct UnconnectedCommunicationPolicy : public CommunicationPolicyBase + {}; + +}} + + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "CommunicationPolicy.cci" +//#include "CommunicationPolicy.ct" +#include "CommunicationPolicy.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/Doxyfile b/Socket/Doxyfile new file mode 100644 index 0000000..3a08b63 --- /dev/null +++ b/Socket/Doxyfile @@ -0,0 +1,273 @@ +# Doxyfile 1.4.2 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = "" +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 = +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/Socket/FileHandle.cc b/Socket/FileHandle.cc new file mode 100644 index 0000000..4865ae6 --- /dev/null +++ b/Socket/FileHandle.cc @@ -0,0 +1,107 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "FileHandle.hh" +//#include "FileHandle.ih" + +// Custom includes +#include +#include +#include +#include +#include +#include "Utils/Exception.hh" + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ void satcom::lib::FileBody::v_close() +{ + if (::close(fd_) != 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::FileBody::v_terminate() +{ + ::close(fd_); +} + +prefix_ bool satcom::lib::FileBody::v_eof() + const +{ + return false; +} + +prefix_ bool satcom::lib::FileBody::v_valid() + const +{ + return true; +} + +prefix_ bool satcom::lib::FileBody::blocking() + const +{ + int flags = ::fcntl(fd(),F_GETFL); + if (flags < 0) throw SystemException(errno); + return ! (flags & O_NONBLOCK); +} + +prefix_ void satcom::lib::FileBody::blocking(bool status) +{ + int flags = ::fcntl(fd(),F_GETFL); + if (flags < 0) throw SystemException(errno); + if (status) flags &= ~O_NONBLOCK; + else flags |= O_NONBLOCK; + if (::fcntl(fd(), F_SETFL, flags) < 0) throw SystemException(errno); +} + +prefix_ bool satcom::lib::FileBody::pollCheck(int fd, bool incoming, bool block) + const +{ + struct ::pollfd pfd; + ::memset(&pfd,0,sizeof(pfd)); + pfd.fd = fd; + pfd.events = incoming?POLLIN:POLLOUT; + int rv = -1; + do { + rv = ::poll(&pfd,1,block?-1:0); + if (rv<0) + switch (errno) { + case EINTR: + break; + default: + throw SystemException(errno); + } + } while (rv<0); + return rv>0; +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/FileHandle.cci b/Socket/FileHandle.cci new file mode 100644 index 0000000..f633fdf --- /dev/null +++ b/Socket/FileHandle.cci @@ -0,0 +1,243 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "FileHandle.ih" + +// Custom includes +#include +#include "Utils/Exception.hh" + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::FileBody + +prefix_ satcom::lib::FileBody::FileBody(int fd) + : fd_(fd) +{} + +prefix_ satcom::lib::FileBody::~FileBody() +{ + if (valid()) + try { + close(); + } + catch (...) { + terminate(); + } +} + +prefix_ void satcom::lib::FileBody::close() +{ + if (!valid()) + throw SystemException(EBADF); + v_close(); + fd_ = -1; +} + +prefix_ void satcom::lib::FileBody::terminate() +{ + if (valid()) { + v_terminate(); + fd_ = -1; + } +} + +prefix_ int satcom::lib::FileBody::fd() + const +{ + return fd_; +} + +prefix_ void satcom::lib::FileBody::fd(int fd) +{ + fd_ = fd; +} + +prefix_ bool satcom::lib::FileBody::eof() + const +{ + return v_eof(); +} + +prefix_ bool satcom::lib::FileBody::valid() + const +{ + return fd_!=-1 && v_valid(); +} + +prefix_ bool satcom::lib::FileBody::readable() + const +{ + return pollCheck(fd(),true); +} + +prefix_ void satcom::lib::FileBody::waitReadable() + const +{ + pollCheck(fd(),true,true); +} + +prefix_ bool satcom::lib::FileBody::writeable() + const +{ + return pollCheck(fd(),false); +} + +prefix_ void satcom::lib::FileBody::waitWriteable() + const +{ + pollCheck(fd(),false,true); +} + +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::FileHandle + +prefix_ void satcom::lib::FileHandle::close() +{ + body().close(); +} + +prefix_ void satcom::lib::FileHandle::terminate() +{ + body().terminate(); +} + +prefix_ bool satcom::lib::FileHandle::readable() + const +{ + return body().readable(); +} + +prefix_ void satcom::lib::FileHandle::waitReadable() + const +{ + body().waitReadable(); +} + +prefix_ bool satcom::lib::FileHandle::writeable() + const +{ + return body().writeable(); +} + +prefix_ void satcom::lib::FileHandle::waitWriteable() + const +{ + body().waitWriteable(); +} + +prefix_ bool satcom::lib::FileHandle::blocking() + const +{ + return body().blocking(); +} + +prefix_ void satcom::lib::FileHandle::blocking(bool status) +{ + body().blocking(status); +} + +prefix_ bool satcom::lib::FileHandle::eof() + const +{ + return body().eof(); +} + +prefix_ bool satcom::lib::FileHandle::valid() + const +{ + return body().valid(); +} + +prefix_ satcom::lib::FileHandle::operator bool () + const +{ + return valid() && !eof(); +} + +prefix_ bool satcom::lib::FileHandle::operator!() + const +{ + return ! (valid() && !eof()); +} + +prefix_ int satcom::lib::FileHandle::fd() + const +{ + return body().fd(); +} + +prefix_ satcom::lib::FileHandle::FileHandle(std::auto_ptr body) + : body_(body.release()) +{} + +prefix_ satcom::lib::FileBody & satcom::lib::FileHandle::body() +{ + return *body_; +} + +prefix_ satcom::lib::FileBody const & satcom::lib::FileHandle::body() + const +{ + return *body_; +} + +prefix_ satcom::lib::FileBody & satcom::lib::FileHandle::body(FileHandle & handle) +{ + return handle.body(); +} + +prefix_ satcom::lib::FileBody const & +satcom::lib::FileHandle::body(FileHandle const & handle) +{ + return handle.body(); +} + +prefix_ void satcom::lib::FileHandle::fd(int fd) +{ + body().fd(fd); +} + +prefix_ satcom::lib::FileHandle::FileHandle +satcom::lib::FileHandle::cast_static(FileHandle handle) +{ + return handle; +} + +prefix_ satcom::lib::FileHandle +satcom::lib::FileHandle::cast_dynamic(FileHandle handle) +{ + return handle; +} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/FileHandle.hh b/Socket/FileHandle.hh new file mode 100644 index 0000000..1f29b89 --- /dev/null +++ b/Socket/FileHandle.hh @@ -0,0 +1,106 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_FileHandle_ +#define HH_FileHandle_ 1 + +// Custom includes +#include // std::auto_ptr + +//#include "FileHandle.mpp" +///////////////////////////////hh.p//////////////////////////////////////// +#include "FileHandle.ih" + +namespace satcom { +namespace lib { + + /** \brief + */ + class FileHandle + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + // protected default constructor + // default copy constructor + // default copy assignment + // default destructor + + // no conversion constructors + + ///@} + /////////////////////////////////////////////////////////////////////////// + + void close(); + void terminate(); + + bool readable() const; + void waitReadable() const; + bool writeable() const; + void waitWriteable() const; + + bool blocking() const; + void blocking(bool status); + + bool eof() const; + bool valid() const; + + operator bool () const; + bool operator!() const; + + int fd() const; + + static FileHandle cast_static(FileHandle handle); + static FileHandle cast_dynamic(FileHandle handle); + + protected: + explicit FileHandle(std::auto_ptr body); + + FileBody & body(); + FileBody const & body() const; + static FileBody & body(FileHandle & handle); + static FileBody const & body(FileHandle const & handle); + + void fd(int fd); + + private: + FileBody::ptr body_; + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +#include "FileHandle.cci" +//#include "FileHandle.ct" +//#include "FileHandle.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/FileHandle.ih b/Socket/FileHandle.ih new file mode 100644 index 0000000..8e59737 --- /dev/null +++ b/Socket/FileHandle.ih @@ -0,0 +1,103 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_FileHandle_ +#define IH_FileHandle_ 1 + +// Custom includes +#include +#include "Utils/intrusive_refcount.hh" + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + /** \brief + */ + class FileBody + : public satcom::lib::intrusive_refcount + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef boost::intrusive_ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + explicit FileBody(int fd=-1); + virtual ~FileBody(); + + // no copy + // no conversion constructors + + ///@} + /////////////////////////////////////////////////////////////////////////// + + int fd() const; + void fd(int fd); + + void close(); + void terminate(); + + bool readable() const; + void waitReadable() const; + bool writeable() const; + void waitWriteable() const; + + bool blocking() const; + void blocking(bool status); + + bool eof() const; + bool valid() const; + + private: + /////////////////////////////////////////////////////////////////////////// + // Virtual interface for subclasses to override + + virtual void v_close(); + virtual void v_terminate(); + virtual bool v_eof() const; + virtual bool v_valid() const; + + + protected: + + private: + bool pollCheck(int fd, bool incoming, bool block=false) const; + + int fd_; + }; + +}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/FileHandle.test.cc b/Socket/FileHandle.test.cc new file mode 100644 index 0000000..c86a26b --- /dev/null +++ b/Socket/FileHandle.test.cc @@ -0,0 +1,115 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "FileHandle.test.hh" +//#include "FileHandle.test.ih" + +// Custom includes +#include +#include +#include +#include "FileHandle.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + class FHandle : public satcom::lib::FileHandle + { + public: + FHandle(int fd=-1) + : satcom::lib::FileHandle(std::auto_ptr( + new satcom::lib::FileBody(fd))) {} + FHandle(std::string name) + : satcom::lib::FileHandle(std::auto_ptr( + new satcom::lib::FileBody())) + { + int rv = ::open(name.c_str(),O_RDWR|O_NONBLOCK) ; + if (rv<0) + throw satcom::lib::SystemException(errno); + fd(rv); + } + }; +} + +BOOST_AUTO_UNIT_TEST(fileHandle) +{ + try { + { + FHandle fh("/dev/null"); + BOOST_CHECK(fh.fd() != -1); + BOOST_CHECK(fh.valid()); + BOOST_CHECK(fh); + BOOST_CHECK(!!fh); + + FHandle fh2(fh); + BOOST_CHECK_EQUAL(fh.fd(), fh2.fd()); + + BOOST_CHECK(fh.writeable()); + BOOST_CHECK_NO_THROW(fh.close()); + BOOST_CHECK_THROW(fh.close(),satcom::lib::SystemException); + BOOST_CHECK_NO_THROW(fh.terminate()); + } + + { + FHandle fh("/dev/zero"); + BOOST_CHECK(fh.readable()); + } + + { + int fds[2]; + BOOST_REQUIRE(pipe(fds) == 0); + + FHandle fh(fds[0]); + BOOST_CHECK(!fh.readable()); + + // Set non-blocking IO and fill the pipe buffer + int flags = fcntl(fds[1],F_GETFL,0); + if (flags == -1) + BOOST_FAIL(strerror(errno)); + if (fcntl(fds[1],F_SETFL,flags|O_NONBLOCK) == -1) + BOOST_FAIL(strerror(errno)); + char buffer[1024]; + while (write(fds[1],buffer,1024) == 1024) ; + + FHandle fh2(fds[1]); + BOOST_CHECK(!fh.writeable()); + } + } + catch (std::exception const & ex) { + BOOST_FAIL(ex.what()); + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/FramingPolicy.hh b/Socket/FramingPolicy.hh new file mode 100644 index 0000000..96a4b98 --- /dev/null +++ b/Socket/FramingPolicy.hh @@ -0,0 +1,53 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_FramingPolicy_ +#define HH_FramingPolicy_ 1 + +// Custom includes +#include "SocketPolicy.hh" + +//#include "FramingPolicy.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + struct StreamFramingPolicy : public FramingPolicyBase + {}; + + struct DatagramFramingPolicy : public FramingPolicyBase + {}; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "FramingPolicy.cci" +//#include "FramingPolicy.ct" +//#include "FramingPolicy.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/GenericAddressingPolicy.cc b/Socket/GenericAddressingPolicy.cc new file mode 100644 index 0000000..abb99f5 --- /dev/null +++ b/Socket/GenericAddressingPolicy.cc @@ -0,0 +1,96 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "GenericAddressingPolicy.hh" +//#include "GenericAddressingPolicy.ih" + +// Custom includes +#include +#include +#include "Utils/Exception.hh" + +//#include "GenericAddressingPolicy.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ void satcom::lib::GenericAddressingPolicy_Base::do_local(FileHandle handle, + struct sockaddr * addr, + unsigned len) +{ + if (::getsockname(handle.fd(),addr,&len) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::GenericAddressingPolicy_Base::do_peer(FileHandle handle, + struct sockaddr * addr, + unsigned len) +{ + if (::getpeername(handle.fd(),addr,&len) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::GenericAddressingPolicy_Base::do_bind(FileHandle handle, + struct sockaddr const * addr, + unsigned len) +{ + if (::bind(handle.fd(),addr,len) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::GenericAddressingPolicy_Base::do_connect(FileHandle handle, + struct sockaddr const * addr, + unsigned len) +{ + while(1) { + if (::connect(handle.fd(),addr,len) < 0) + switch (errno) { + case EINPROGRESS: { + handle.waitWriteable(); + int err = 0; + socklen_t len = sizeof(err); + if (::getsockopt(handle.fd(),SOL_SOCKET,SO_ERROR,&err,&len) < 0) + throw SystemException(errno); + if (err != 0) + throw SystemException(err); + return; + } + case EINTR: + break; + default: + throw SystemException(errno); + } + else + return; + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "GenericAddressingPolicy.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/GenericAddressingPolicy.cti b/Socket/GenericAddressingPolicy.cti new file mode 100644 index 0000000..cb0d400 --- /dev/null +++ b/Socket/GenericAddressingPolicy.cti @@ -0,0 +1,76 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "GenericAddressingPolicy.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::GenericAddressingPolicy
+ +template +template +prefix_ void satcom::lib::GenericAddressingPolicy
:: +peer(SocketHandle handle, Address & addr, + typename IfCommunicationPolicyIs::type *) +{ + addr.clear(); + do_peer(handle,addr.sockaddr_p(),addr.sockaddr_len()); +} + +template +template +prefix_ void satcom::lib::GenericAddressingPolicy
:: +connect(SocketHandle handle, Address const & addr, + typename IfCommunicationPolicyIs::type *) +{ + do_connect(handle,addr.sockaddr_p(),addr.sockaddr_len()); +} + +template +prefix_ void satcom::lib::GenericAddressingPolicy
::local(FileHandle handle, + Address & addr) +{ + addr.clear(); + do_local(handle,addr.sockaddr_p(),addr.sockaddr_len()); +} + +template +prefix_ void satcom::lib::GenericAddressingPolicy
::bind(FileHandle handle, + Address const & addr) +{ + do_bind(handle,addr.sockaddr_p(),addr.sockaddr_len()); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/GenericAddressingPolicy.hh b/Socket/GenericAddressingPolicy.hh new file mode 100644 index 0000000..da55c11 --- /dev/null +++ b/Socket/GenericAddressingPolicy.hh @@ -0,0 +1,74 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_GenericAddressingPolicy_ +#define HH_GenericAddressingPolicy_ 1 + +// Custom includes +#include "SocketHandle.hh" +#include "FileHandle.hh" +#include "SocketPolicy.hh" +#include "CommunicationPolicy.hh" + +//#include "GenericAddressingPolicy.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + struct GenericAddressingPolicy_Base + { + static void do_local(FileHandle handle, struct sockaddr * addr, unsigned len); + static void do_peer(FileHandle handle, struct sockaddr * addr, unsigned len); + static void do_bind(FileHandle handle, struct sockaddr const * addr, unsigned len); + static void do_connect(FileHandle handle, struct sockaddr const * addr, unsigned len); + }; + + template + struct GenericAddressingPolicy + : private GenericAddressingPolicy_Base + { + template + static void peer(SocketHandle handle, Address & addr, + typename IfCommunicationPolicyIs::type * = 0); + static void local(FileHandle handle, Address & addr); + + template + static void connect(SocketHandle handle, Address const & addr, + typename IfCommunicationPolicyIs::type * = 0); + static void bind(FileHandle handle, Address const & addr); + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "GenericAddressingPolicy.cci" +//#include "GenericAddressingPolicy.ct" +#include "GenericAddressingPolicy.cti" +//#include "GenericAddressingPolicy.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/INetAddressing.cc b/Socket/INetAddressing.cc new file mode 100644 index 0000000..b2e8edf --- /dev/null +++ b/Socket/INetAddressing.cc @@ -0,0 +1,87 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "INetAddressing.hh" +//#include "INetAddressing.ih" + +// Custom includes +#include +#include +#include +#include + +//#include "INetAddressing.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ satcom::lib::INet4Address::INet4Address(std::string host, unsigned port) +{ + clear(); + // TODO: gethostbyname einbauen + if (::inet_aton(host.c_str(), &addr_.sin_addr) == 0) + throw InvalidINetAddressException(); + addr_.sin_port = htons(port); +} + +prefix_ std::string satcom::lib::INet4Address::str() + const +{ + std::stringstream s; + s << host() << ':' << port(); + return s.str(); +} + +prefix_ void satcom::lib::INet4Address::clear() +{ + ::memset(&addr_,0,sizeof(addr_)); + addr_.sin_family = AF_INET; +} + +prefix_ void satcom::lib::INet4Address::assignString(std::string address) +{ + clear(); + // TODO: gethostbyname einbauen + unsigned i = address.find(':'); + if (i == std::string::npos) + throw InvalidINetAddressException(); + if (::inet_aton(std::string(address,0,i).c_str(), &addr_.sin_addr) == 0) + throw InvalidINetAddressException(); + try { + // Replace lexical_cast with strtoul ? + addr_.sin_port = htons(boost::lexical_cast< ::u_int16_t >(std::string(address,i+1))); + } + catch (boost::bad_lexical_cast const & ex) { + throw InvalidINetAddressException(); + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "INetAddressing.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/INetAddressing.cci b/Socket/INetAddressing.cci new file mode 100644 index 0000000..a04def2 --- /dev/null +++ b/Socket/INetAddressing.cci @@ -0,0 +1,96 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 + +// Custom includes +#include + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +prefix_ satcom::lib::INet4Address::INet4Address() +{ + clear(); +} + +prefix_ satcom::lib::INet4Address::INet4Address(char const * address) +{ + assignString(address); +} + +prefix_ satcom::lib::INet4Address::INet4Address(std::string address) +{ + assignString(address); +} + +prefix_ bool satcom::lib::INet4Address::operator==(INet4Address const & other) + const +{ + return addr_.sin_port == other.addr_.sin_port && + addr_.sin_addr.s_addr == other.addr_.sin_addr.s_addr; +} + +prefix_ std::string satcom::lib::INet4Address::host() + const +{ + // FIXME: thread safety? + return std::string(::inet_ntoa(addr_.sin_addr)); +} + +prefix_ unsigned satcom::lib::INet4Address::port() + const +{ + return ntohs(addr_.sin_port); +} + +prefix_ struct sockaddr * satcom::lib::INet4Address::sockaddr_p() +{ + return reinterpret_cast(&addr_); +} + +prefix_ struct sockaddr const * satcom::lib::INet4Address::sockaddr_p() + const +{ + return reinterpret_cast(&addr_); +} + +prefix_ unsigned satcom::lib::INet4Address::sockaddr_len() + const +{ + return sizeof(addr_); +} + +prefix_ std::ostream & satcom::lib::operator<<(std::ostream & os, INet4Address const & addr) +{ + os << addr.str(); + return os; +} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/INetAddressing.hh b/Socket/INetAddressing.hh new file mode 100644 index 0000000..28a8a59 --- /dev/null +++ b/Socket/INetAddressing.hh @@ -0,0 +1,114 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_INetAddressing_ +#define HH_INetAddressing_ 1 + +// Custom includes +#include +#include +#include +#include "SocketPolicy.hh" +#include "ClientSocketHandle.hh" +#include "CommunicationPolicy.hh" +#include "GenericAddressingPolicy.hh" + +//#include "INetAddressing.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + // TODO: Implement real INet4Address datatype and + // rename this one to INet4SockAddress ... + + class INet4Address + { + public: + INet4Address(); + INet4Address(char const * address); + INet4Address(std::string address); + INet4Address(std::string host, unsigned port); + + bool operator==(INet4Address const & other) const; + + std::string str() const; + std::string host() const; + unsigned port() const; + + // TODO: Interface + + void clear(); + + struct sockaddr * sockaddr_p(); + struct sockaddr const * sockaddr_p() const; + unsigned sockaddr_len() const; + + private: + void assignString(std::string addr); + + struct ::sockaddr_in addr_; + }; + + std::ostream & operator<<(std::ostream & os, INet4Address const & addr); + + class INet6Address + { + // TODO: Implement + }; + + struct INet4AddressingPolicy + : public AddressingPolicyBase, + private GenericAddressingPolicy + { + typedef INet4Address Address; + + using GenericAddressingPolicy::peer; + using GenericAddressingPolicy::local; + using GenericAddressingPolicy::connect; + using GenericAddressingPolicy::bind; + }; + + struct INet6AddressingPolicy : public AddressingPolicyBase + { + typedef INet6Address Address; + + // TODO: Implement + }; + + struct InvalidINetAddressException : public std::exception + { char const * what() const throw() { return "invalid inet address"; } }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +#include "INetAddressing.cci" +//#include "INetAddressing.ct" +//#include "INetAddressing.cti" +//#include "INetAddressing.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/INetAddressing.test.cc b/Socket/INetAddressing.test.cc new file mode 100644 index 0000000..dea7b88 --- /dev/null +++ b/Socket/INetAddressing.test.cc @@ -0,0 +1,89 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "INetAddressing.test.hh" +//#include "INetAddressing.test.ih" + +// Custom includes +#include "INetAddressing.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +BOOST_AUTO_UNIT_TEST(inet4Address) +{ + using satcom::lib::INet4Address; + using satcom::lib::InvalidINetAddressException; + + { + INet4Address addr; + + addr = "127.0.0.1:12345"; + } + + { + INet4Address addr1("127.0.0.1:12345"); + INet4Address addr2(std::string("127.0.0.1:12345")); + INet4Address addr3("127.0.0.1",12345); + } + + BOOST_CHECK_EQUAL( INet4Address("127.0.0.1:12345"), INet4Address("127.0.0.1",12345) ); + + BOOST_CHECK_THROW( INet4Address("127.0.0.1"), InvalidINetAddressException ); + BOOST_CHECK_THROW( INet4Address("foo@bar:12345"), InvalidINetAddressException ); + BOOST_CHECK_THROW( INet4Address("127.0.0.1:1234a"), InvalidINetAddressException ); + BOOST_CHECK_THROW( INet4Address("foo@bar",12345), InvalidINetAddressException ); + + BOOST_CHECK_EQUAL( INet4Address("127.0.0.1:12345").host(), "127.0.0.1" ); + BOOST_CHECK_EQUAL( INet4Address("127.0.0.1:12345").port(), 12345u ); + BOOST_CHECK_EQUAL( INet4Address("127.0.0.1:12345").str(), "127.0.0.1:12345" ); + + { + INet4Address addr("127.0.0.1:12345"); + BOOST_CHECK_EQUAL( reinterpret_cast< ::sockaddr_in * >(addr.sockaddr_p())->sin_port, + htons(12345) ); + BOOST_CHECK_EQUAL( reinterpret_cast< ::sockaddr_in * >(addr.sockaddr_p())->sin_addr.s_addr, + htonl(INADDR_LOOPBACK) ); + + std::stringstream s; + s << addr; + BOOST_CHECK_EQUAL( s.str(), "127.0.0.1:12345" ); + } +} + +BOOST_AUTO_UNIT_TEST(inet6Address) +{ +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/INetProtocol.cc b/Socket/INetProtocol.cc new file mode 100644 index 0000000..b66e15d --- /dev/null +++ b/Socket/INetProtocol.cc @@ -0,0 +1,159 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "INetProtocol.hh" +//#include "INetProtocol.ih" + +// Custom includes +#include +#include +#include // for if_nametoindex +#include "Utils/Exception.hh" + +//#include "INetProtocol.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::INet4Protocol + +prefix_ void satcom::lib::IPv4Protocol::connect(INet4Address const & address) + const +{ + if (::connect(body().fd(),address.sockaddr_p(), address.sockaddr_len()) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::IPv4Protocol::bind(INet4Address const & address) + const +{ + if (::bind(body().fd(),address.sockaddr_p(), address.sockaddr_len()) < 0) + throw SystemException(errno); +} + +prefix_ bool satcom::lib::IPv4Protocol::mcLoop() + const +{ + int value; + socklen_t len (sizeof(value)); + if (::getsockopt(body().fd(),SOL_IP,IP_MULTICAST_LOOP,&value,&len) < 0) + throw SystemException(errno); + return value; +} + +prefix_ void satcom::lib::IPv4Protocol::mcLoop(bool value) + const +{ + int ivalue (value); + if (::setsockopt(body().fd(),SOL_IP,IP_MULTICAST_LOOP,&ivalue,sizeof(ivalue)) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::IPv4Protocol::mcAddMembership(INet4Address const & mcAddr) + const +{ + struct ip_mreqn mreqn; + mreqn.imr_multiaddr = reinterpret_cast(mcAddr.sockaddr_p())->sin_addr; + mreqn.imr_address.s_addr = htons(INADDR_ANY); + mreqn.imr_ifindex = 0; + if (::setsockopt(body().fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::IPv4Protocol::mcAddMembership(INet4Address const & mcAddr, + INet4Address const & localAddr) + const +{ + struct ip_mreqn mreqn; + mreqn.imr_multiaddr = reinterpret_cast(mcAddr.sockaddr_p())->sin_addr; + mreqn.imr_address = reinterpret_cast(localAddr.sockaddr_p())->sin_addr; + mreqn.imr_ifindex = 0; + if (::setsockopt(body().fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::IPv4Protocol::mcDropMembership(INet4Address const & mcAddr) + const +{ + struct ip_mreqn mreqn; + mreqn.imr_multiaddr = reinterpret_cast(mcAddr.sockaddr_p())->sin_addr; + mreqn.imr_address.s_addr = htons(INADDR_ANY); + mreqn.imr_ifindex = 0; + if (::setsockopt(body().fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::IPv4Protocol::mcDropMembership(INet4Address const & mcAddr, + INet4Address const & localAddr) + const +{ + struct ip_mreqn mreqn; + mreqn.imr_multiaddr = reinterpret_cast(mcAddr.sockaddr_p())->sin_addr; + mreqn.imr_address = reinterpret_cast(localAddr.sockaddr_p())->sin_addr; + mreqn.imr_ifindex = 0; + if (::setsockopt(body().fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::IPv4Protocol::mcIface(std::string iface) + const +{ + struct ip_mreqn mreqn; + ::memset(&mreqn,sizeof(mreqn),0); + if (!iface.empty()) { + mreqn.imr_ifindex = if_nametoindex(iface.c_str()); + if (mreqn.imr_ifindex == 0) + throw SystemException(EINVAL); + } + if (::setsockopt(body().fd(),SOL_IP,IP_MULTICAST_IF,&mreqn,sizeof(mreqn)) < 0) + throw SystemException(errno); +} + +prefix_ unsigned satcom::lib::IPv4Protocol::mcTTL() + const +{ + int value; + socklen_t len (sizeof(value)); + if (::getsockopt(body().fd(),SOL_IP,IP_MULTICAST_TTL,&value,&len) < 0) + throw SystemException(errno); + return value; +} + +prefix_ void satcom::lib::IPv4Protocol::mcTTL(unsigned value) + const +{ + if (::setsockopt(body().fd(),SOL_IP,IP_MULTICAST_TTL,&value,sizeof(value)) < 0) + throw SystemException(errno); +} + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "INetProtocol.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/INetProtocol.hh b/Socket/INetProtocol.hh new file mode 100644 index 0000000..a5a3cd6 --- /dev/null +++ b/Socket/INetProtocol.hh @@ -0,0 +1,89 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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: what about OOB data? das OOB Data block receipt of normal data ? + +// TODO: Implement IP_RECVERR / MSG_ERRQUEUE. This should be placed +// into an additional protocol class since IP_RECVERR is only valid +// for SOCK_DGRAM (UDP) and not SOCK_STREAM (TCP) sockets + +#ifndef HH_INetProtocol_ +#define HH_INetProtocol_ 1 + +// Custom includes +#include "SocketProtocol.hh" +#include "INetAddressing.hh" +#include "ClientSocketHandle.hh" +#include "CommunicationPolicy.hh" + +//#include "INetProtocol.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + class IPv4Protocol + : public virtual SocketProtocol + { + public: + void connect(INet4Address const & address) const; + void bind(INet4Address const & address) const; + + unsigned mcTTL() const; + void mcTTL(unsigned value) const; + + bool mcLoop() const; + void mcLoop(bool value) const; + + // TODO: Is it safe, not to allow setting the interface + // index on add/drop? what does it do (especially if + // the local addres is given ?) + + // TODO: move all multicast-methods into an extra + // IPv4MulticastProtocol class + + void mcAddMembership(INet4Address const & mcAddr) const; + void mcAddMembership(INet4Address const & mcAddr, INet4Address const & localAddr) const; + + void mcDropMembership(INet4Address const & mcAddr) const; + void mcDropMembership(INet4Address const & mcAddr, INet4Address const & localAddr) const; + + void mcIface(std::string iface = std::string()) const; + }; + + class IPv6Protocol + : public virtual SocketProtocol + {}; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "INetProtocol.cci" +//#include "INetProtocol.ct" +//#include "INetProtocol.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/LLAddressing.cc b/Socket/LLAddressing.cc new file mode 100644 index 0000000..6ef9508 --- /dev/null +++ b/Socket/LLAddressing.cc @@ -0,0 +1,128 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "LLAddressing.hh" +#include "LLAddressing.ih" + +// Custom includes +#include +#include + +#include +#include + +#include "Utils/Exception.hh" + +//#include "LLAddressing.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ unsigned char satcom::lib::detail::hexnibble(char c) +{ + if (c>='0' && c<='9') + return c - '0'; + if (c>='A' && c<='F') + return c - 'A' + 10; + if (c>='a' && c<='f') + return c - 'a' + 10; + throw InvalidLLSocketAddressException(); +} + +prefix_ std::string satcom::lib::LLSocketAddress::interface() + const +{ + if (addr_.sll_ifindex == 0) + return std::string(); + char name[IFNAMSIZ]; + if (! ::if_indextoname(addr_.sll_ifindex, name)) + throw InvalidLLSocketAddressException(); + return std::string(name); +} + +/* +{ + if (addr_.sll_halen == 0) + return std::string(); + std::stringstream s; + + unsigned char const * i = &addr_.sll_addr[0]; + while (1) { + s << std::hex << std::setw(2) << std::setfill('0') << unsigned(*i); + ++i; + if (i == &addr_.sll_addr[addr_.sll_halen]) break; + s << '-'; + } + return s.str(); +} +*/ + + +/* +prefix_ void satcom::lib::LLSocketAddress::address(std::string address) +{ + typedef boost::split_iterator StringSplitIterator; + StringSplitIterator i = boost::make_split_iterator(address, boost::token_finder(boost::is_any_of("-: "))); + unsigned char * j = &addr_.sll_addr[0]; + for (; ! i.eof() && addr_.sll_halen<8; ++i, ++j, ++addr_.sll_halen) { + if ( i->size() != 2 || ! boost::all(*i, boost::is_xdigit()) ) + throw InvalidLLSocketAddressException(); + *j = hex(*i); + } + if (! i.eof()) + throw InvalidLLSocketAddressException(); +} +*/ + +prefix_ void satcom::lib::LLSocketAddress::interface(std::string interface) +{ + if (! interface.empty()) { + addr_.sll_ifindex = if_nametoindex(interface.c_str()); + if (addr_.sll_ifindex == 0) + throw InvalidLLSocketAddressException(); + } +} + + +prefix_ satcom::lib::detail::LLAddressFromStringRange +satcom::lib::llAddress(std::string address) +{ + detail::StringSplitIterator i = + boost::make_split_iterator(address, boost::token_finder(boost::is_any_of("-: "))); + detail::StringSplitIterator i_end; + + detail::HexSplitIterator j (i,detail::HexConverter()); + detail::HexSplitIterator j_end (i_end); + + return detail::LLAddressFromStringRange(j,j_end); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "LLAddressing.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/LLAddressing.cci b/Socket/LLAddressing.cci new file mode 100644 index 0000000..3de8a5e --- /dev/null +++ b/Socket/LLAddressing.cci @@ -0,0 +1,113 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 + +// Custom includes +#include +#include + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +prefix_ satcom::lib::LLSocketAddress::LLSocketAddress() +{ + clear(); +} + +prefix_ satcom::lib::LLSocketAddress::LLSocketAddress(unsigned protocol, std::string interface) +{ + clear(); + this->protocol(protocol); + this->interface(interface); +} + +prefix_ satcom::lib::LLSocketAddress::LLSocketAddress(std::string interface) +{ + clear(); + this->interface(interface); +} + +prefix_ void satcom::lib::LLSocketAddress::clear() +{ + ::memset(&addr_,0,sizeof(addr_)); + addr_.sll_family = AF_PACKET; +} + +prefix_ unsigned satcom::lib::LLSocketAddress::protocol() + const +{ + return ntohs(addr_.sll_protocol); +} + +prefix_ unsigned satcom::lib::LLSocketAddress::arptype() + const +{ + // TODO: Check, wether this is returned in network or host byte + // order + return ntohs(addr_.sll_hatype); +} + +prefix_ unsigned satcom::lib::LLSocketAddress::pkttype() + const +{ + // TODO: Check, wether this is returned in network or host byte + // order + return ntohs(addr_.sll_pkttype); +} + +prefix_ satcom::lib::LLSocketAddress::LLAddress satcom::lib::LLSocketAddress::address() + const +{ + return LLAddress(&addr_.sll_addr[0], &addr_.sll_addr[addr_.sll_halen]); +} + +prefix_ void satcom::lib::LLSocketAddress::protocol(unsigned protocol) +{ + addr_.sll_protocol = htons(protocol); +} + +prefix_ struct sockaddr * satcom::lib::LLSocketAddress::sockaddr_p() +{ + return reinterpret_cast(&addr_); +} + +prefix_ struct sockaddr const * satcom::lib::LLSocketAddress::sockaddr_p() + const +{ + return reinterpret_cast(&addr_); +} + +prefix_ unsigned satcom::lib::LLSocketAddress::sockaddr_len() + const +{ + return sizeof(addr_); +} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/LLAddressing.ct b/Socket/LLAddressing.ct new file mode 100644 index 0000000..cf38dd4 --- /dev/null +++ b/Socket/LLAddressing.ct @@ -0,0 +1,86 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "LLAddressing.ih" + +// Custom includes +#include +#include +#include + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template +prefix_ void satcom::lib::LLSocketAddress::address(ForwardRange const & address) +{ + if (boost::size(address) > sizeof(addr_.sll_addr)) + throw InvalidLLSocketAddressException(); + typename boost::range_const_iterator::type i (boost::begin(address)); + ::memset(&addr_.sll_addr[0],sizeof(addr_.sll_addr),0); + addr_.sll_halen = 0; + for (; i != boost::end(address) && addr_.sll_halen<8; ++i, ++addr_.sll_halen) + addr_.sll_addr[addr_.sll_halen] = *i; + if (i != boost::end(address)) + throw InvalidLLSocketAddressException(); +} + +template +prefix_ std::string +satcom::lib::llAddress(ForwardRange const & address, + typename boost::enable_if< boost::is_class >::type *) +{ + if (boost::empty(address)) + return std::string(); + std::stringstream s; + typename boost::range_const_iterator< ForwardRange >::type i (boost::begin(address)); + while (1) { + s << std::hex << std::setw(2) << std::setfill('0') << unsigned(*i); + ++ i; + if (i == boost::end(address)) + break; + s << '-'; + } + return s.str(); +} + +template +prefix_ unsigned char satcom::lib::detail::HexConverter::operator()(ForwardRange const & v) + const +{ + if (boost::size(v) != 2) + throw InvalidLLSocketAddressException(); + typename boost::range_iterator< ForwardRange >::type i (boost::begin(v)); + unsigned char n1 = hexnibble(*i) << 4; + return n1 + hexnibble(*(++i)); +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/LLAddressing.cti b/Socket/LLAddressing.cti new file mode 100644 index 0000000..c1a5e68 --- /dev/null +++ b/Socket/LLAddressing.cti @@ -0,0 +1,50 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "LLAddressing.ih" + +// Custom includes +#include // for std::copy + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +prefix_ satcom::lib::LLSocketAddress:: +LLSocketAddress(ForwardRange const & address, std::string interface, + typename boost::enable_if_c::value >::type *) +{ + clear(); + this->address(address); + this->interface(interface); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/LLAddressing.hh b/Socket/LLAddressing.hh new file mode 100644 index 0000000..ce699be --- /dev/null +++ b/Socket/LLAddressing.hh @@ -0,0 +1,138 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_LLAddressing_ +#define HH_LLAddressing_ 1 + +// Custom includes +#include +#include +#include + +#include +#include + +#include "SocketPolicy.hh" +#include "FileHandle.hh" +#include "GenericAddressingPolicy.hh" + +//#include "LLAddressing.mpp" +#include "LLAddressing.ih" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + class LLSocketAddress + { + public: + // Right now we use an arbitrary ForwardRange (see Boost.Range) + // as the representation for a hardware address. The restrictions + // for the range are: + // a) the range must never be larger than 8 elements + // b) the value_type must be convertible to unsigend char + // and really we need only a single-pass range. + // + // Since a hardware address is so short (a maximum of 8 + // bytes), in the aftermath I think a simple container holding + // a maximum of 8 unsigned chars (e.g. Boost.Array with + // additional length parameter) will be much simpler and + // probably even more efficient. This should have a conversion + // constructor from an arbitrary ForwardRange to make it + // compatible e.g. with the Packet library. + // + // However, since I have implemented it already as it is now, + // I'll leave it as it is ... + + typedef boost::iterator_range LLAddress; + + LLSocketAddress(); + // And this is for bind + explicit LLSocketAddress(unsigned protocol, std::string interface=""); + explicit LLSocketAddress(std::string interface); + // This is for sending packets .. + // We must use enable_if here, so this constructor will not hide + // above constructor if passed a plain int or short argument + template + explicit LLSocketAddress(ForwardRange const & address, std::string interface="", + typename boost::enable_if_c::value >::type * = 0); + + void clear(); + + unsigned protocol() const; + std::string interface() const; + unsigned arptype() const; + unsigned pkttype() const; + LLAddress address() const; + + // The mutating interface is purposely restricted to allow only + // changing those members, which are sensible to be changed. + + template + void address(ForwardRange const & address); + void interface(std::string interface); + void protocol(unsigned protocol); + + struct sockaddr * sockaddr_p(); + struct sockaddr const * sockaddr_p() const; + unsigned sockaddr_len() const; + + private: + struct ::sockaddr_ll addr_; + }; + + detail::LLAddressFromStringRange llAddress(std::string address); + // The enable_if condition here allows only for classes as range. + // However, excluding zero-terminated strings (which we want to + // pass to above) I cannot think of a non-class ForwardRange + // except for academic cases + template + std::string llAddress(ForwardRange const & address, + typename boost::enable_if< boost::is_class >::type * = 0); + + class LLAddressingPolicy + : public AddressingPolicyBase, + private GenericAddressingPolicy + { + public: + typedef LLSocketAddress Address; + + using GenericAddressingPolicy::local; + using GenericAddressingPolicy::bind; + }; + + struct InvalidLLSocketAddressException : public std::exception + { char const * what() const throw() { return "invalid ll address"; } }; +}} + +///////////////////////////////hh.e//////////////////////////////////////// +#include "LLAddressing.cci" +#include "LLAddressing.ct" +#include "LLAddressing.cti" +//#include "LLAddressing.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/LLAddressing.ih b/Socket/LLAddressing.ih new file mode 100644 index 0000000..57ec8b1 --- /dev/null +++ b/Socket/LLAddressing.ih @@ -0,0 +1,56 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_LLAddressing_ +#define IH_LLAddressing_ 1 + +// Custom includes +#include + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace satcom { +namespace lib { +namespace detail { + + struct HexConverter { + typedef unsigned char result_type; + template + result_type operator()(ForwardRange const & v) const; + }; + + typedef boost::split_iterator StringSplitIterator; + typedef boost::transform_iterator< HexConverter, StringSplitIterator > HexSplitIterator; + typedef boost::iterator_range LLAddressFromStringRange; + + unsigned char hexnibble(char c); + +}}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/LLAddressing.test.cc b/Socket/LLAddressing.test.cc new file mode 100644 index 0000000..cdbbe45 --- /dev/null +++ b/Socket/LLAddressing.test.cc @@ -0,0 +1,85 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "LLAddressing.test.hh" +//#include "LLAddressing.test.ih" + +// Custom includes +#include "LLAddressing.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +BOOST_AUTO_UNIT_TEST(llAddress) +{ + { + satcom::lib::LLSocketAddress a; + + BOOST_CHECK_EQUAL( a.protocol(), 0u ); + BOOST_CHECK_EQUAL( a.interface(), "" ); + BOOST_CHECK_EQUAL( a.arptype(), 0u ); + BOOST_CHECK_EQUAL( a.pkttype(), 0u ); + BOOST_CHECK_EQUAL( a.address(), "" ); + + a.address(satcom::lib::llAddress("05-10-1A-2f-25-30")); + BOOST_CHECK_EQUAL( satcom::lib::llAddress(a.address()), "05-10-1a-2f-25-30" ); + a.interface("lo"); + BOOST_CHECK_EQUAL( a.interface(), "lo" ); + a.protocol(123); + BOOST_CHECK_EQUAL( a.protocol(), 123u ); + } + + { + satcom::lib::LLSocketAddress a ( + satcom::lib::llAddress("11-12-13-14-15-16"), "lo"); + + BOOST_CHECK_EQUAL( a.protocol(), 0u ); + BOOST_CHECK_EQUAL( a.interface(), "lo" ); + BOOST_CHECK_EQUAL( a.arptype(), 0u ); + BOOST_CHECK_EQUAL( a.pkttype(), 0u ); + BOOST_CHECK_EQUAL( satcom::lib::llAddress(a.address()), "11-12-13-14-15-16" ); + } + + { + satcom::lib::LLSocketAddress a (123, "lo"); + + BOOST_CHECK_EQUAL( a.protocol(), 123u ); + BOOST_CHECK_EQUAL( a.interface(), "lo" ); + BOOST_CHECK_EQUAL( a.arptype(), 0u ); + BOOST_CHECK_EQUAL( a.pkttype(), 0u ); + BOOST_CHECK_EQUAL( satcom::lib::llAddress(a.address()), "" ); + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/PacketSocketHandle.cc b/Socket/PacketSocketHandle.cc new file mode 100644 index 0000000..4dc8791 --- /dev/null +++ b/Socket/PacketSocketHandle.cc @@ -0,0 +1,127 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "PacketSocketHandle.hh" +#include "PacketSocketHandle.ih" + +// Custom includes +#include +#include +#include +#include +#include +#include +#include + +//#include "PacketSocketHandle.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ void satcom::lib::PacketProtocol::init_client(SocketType type, int protocol) + const +{ + int socktype = SOCK_RAW; + if (type == DatagramSocket) + socktype = SOCK_DGRAM; + if (protocol == -1) + protocol = ETH_P_ALL; + int sock = ::socket(PF_PACKET, socktype, htons(protocol)); + if (sock < 0) + throw SystemException(errno); + body().fd(sock); +} + +prefix_ std::auto_ptr satcom::lib::PacketProtocol::clone() + const +{ + return std::auto_ptr(new PacketProtocol()); +} + +prefix_ unsigned satcom::lib::PacketProtocol::available() + const +{ + if (! body().readable()) + return 0; + ssize_t l = ::recv(body().fd(),0,0,MSG_PEEK | MSG_TRUNC); + if (l < 0) + throw SystemException(errno); + return l; +} + +prefix_ bool satcom::lib::PacketProtocol::eof() + const +{ + return false; +} + +prefix_ void satcom::lib::PacketProtocol::promisc(std::string interface, PromiscMode mode) + const +{ + // The interface is really stupid: as far as i understand, it is possible to + // enable PROMISC and ALLMULTI seperately, however PROMISC is really a superset + // of ALLMULTI ... grmpf ... therefore we allways set/reset both to implement sane + // semantics + + struct packet_mreq mreq; + mreq.mr_ifindex = ::if_nametoindex(interface.c_str()); + if (mreq.mr_ifindex == 0) + throw SystemException(EINVAL); + mreq.mr_alen = 0; + + mreq.mr_type = PACKET_MR_PROMISC; + int command = mode == Promiscuous ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP; + if (::setsockopt(body().fd(),SOL_PACKET,command,&mreq,sizeof(mreq)) < 0) + throw SystemException(errno); + + mreq.mr_type = PACKET_MR_ALLMULTI; + command = mode == AllMulticast ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP; + if (::setsockopt(body().fd(),SOL_PACKET,command,&mreq,sizeof(mreq)) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::PacketProtocol::do_mc_i(std::string interface, + detail::LLAddressCopier const & copier, bool add) + const +{ + struct packet_mreq mreq; + mreq.mr_ifindex = ::if_nametoindex(interface.c_str()); + if (mreq.mr_ifindex == 0) + throw SystemException(EINVAL); + mreq.mr_type = PACKET_MR_MULTICAST; + mreq.mr_alen = copier(&mreq.mr_address[0]); + if (::setsockopt(body().fd(),SOL_PACKET, + add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP, + &mreq, sizeof(mreq)) < 0) + throw SystemException(errno); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "PacketSocketHandle.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/PacketSocketHandle.ct b/Socket/PacketSocketHandle.ct new file mode 100644 index 0000000..964ca76 --- /dev/null +++ b/Socket/PacketSocketHandle.ct @@ -0,0 +1,53 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "PacketSocketHandle.ih" + +// Custom includes + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template +prefix_ unsigned +satcom::lib::detail::Range_LLAddressCopier::operator()(unsigned char * target) + const +{ + std::size_t len (0); + typename boost::range_const_iterator::type i (boost::begin(range_)); + for (; i != boost::end(range_) && len<8; ++i, ++len, ++target) + *target = *i; + if (i != boost::end(range_)) + throw InvalidLLSocketAddressException(); + return len; +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/PacketSocketHandle.cti b/Socket/PacketSocketHandle.cti new file mode 100644 index 0000000..a612e18 --- /dev/null +++ b/Socket/PacketSocketHandle.cti @@ -0,0 +1,70 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "PacketSocketHandle.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +prefix_ void satcom::lib::PacketProtocol::mcAdd(std::string interface, + ForwardRange const & address) + const +{ + do_mc(interface,address,true); +} + +template +prefix_ void satcom::lib::PacketProtocol::mcDrop(std::string interface, + ForwardRange const & address) + const +{ + do_mc(interface,address,false); +} + +template +prefix_ satcom::lib::detail::Range_LLAddressCopier:: +Range_LLAddressCopier(ForwardRange const & range) + : range_ (range) +{} + +template +prefix_ void satcom::lib::PacketProtocol::do_mc(std::string interface, + ForwardRange const & address, bool add) + const +{ + detail::Range_LLAddressCopier copier (address); + do_mc_i(interface, copier, add); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/PacketSocketHandle.hh b/Socket/PacketSocketHandle.hh new file mode 100644 index 0000000..179d7aa --- /dev/null +++ b/Socket/PacketSocketHandle.hh @@ -0,0 +1,98 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_PacketSocketHandle_ +#define HH_PacketSocketHandle_ 1 + +// Custom includes +#include "SocketPolicy.hh" +#include "SocketProtocol.hh" +#include "ProtocolClientSocketHandle.hh" +#include "LLAddressing.hh" +#include "FramingPolicy.hh" +#include "CommunicationPolicy.hh" +#include "ReadWritePolicy.hh" +#include "BufferingPolicy.hh" +#include "BSDSocketProtocol.hh" + +//#include "PacketSocketHandle.mpp" +#include "PacketSocketHandle.ih" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + typedef MakeSocketPolicy< + LLAddressingPolicy, + DatagramFramingPolicy, + UnconnectedCommunicationPolicy, + ReadablePolicy, + WriteablePolicy, + SocketBufferingPolicy + >::policy Packet_Policy; + + class PacketProtocol + : public ConcreteSocketProtocol, + public BSDSocketProtocol + { + public: + enum SocketType { RawSocket, DatagramSocket }; + + void init_client(SocketType type = RawSocket, int protocol = -1) const; + + std::auto_ptr clone() const; + + enum PromiscMode { Promiscuous, AllMulticast, None }; + + void promisc(std::string interface, PromiscMode mode) const; + // See LLSocketAddress for a discussion/rationale for + // ForwardRange here + template + void mcAdd(std::string interface, ForwardRange const & address) const; + template + void mcDrop(std::string interface, ForwardRange const & address) const; + + unsigned available() const; + bool eof() const; + + private: + template + void do_mc(std::string interface, ForwardRange const & address, bool add) const; + void do_mc_i(std::string interface, detail::LLAddressCopier const & copier, bool add) const; + }; + + typedef ProtocolClientSocketHandle PacketSocketHandle; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "PacketSocketHandle.cci" +#include "PacketSocketHandle.ct" +#include "PacketSocketHandle.cti" +//#include "PacketSocketHandle.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/PacketSocketHandle.ih b/Socket/PacketSocketHandle.ih new file mode 100644 index 0000000..cc121b0 --- /dev/null +++ b/Socket/PacketSocketHandle.ih @@ -0,0 +1,60 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_PacketSocketHandle_ +#define IH_PacketSocketHandle_ 1 + +// Custom includes + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace satcom { +namespace lib { +namespace detail { + + struct LLAddressCopier + { + virtual ~LLAddressCopier() {} + virtual unsigned operator()(unsigned char * target) const = 0; + }; + + template + struct Range_LLAddressCopier + : public LLAddressCopier + { + Range_LLAddressCopier(ForwardRange const & range); + + unsigned operator()(unsigned char * target) const; + + ForwardRange const & range_; + }; + +}}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/PacketSocketHandle.test.cc b/Socket/PacketSocketHandle.test.cc new file mode 100644 index 0000000..fb10346 --- /dev/null +++ b/Socket/PacketSocketHandle.test.cc @@ -0,0 +1,85 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "PacketSocketHandle.test.hh" +//#include "PacketSocketHandle.test.ih" + +#include "PacketSocketHandle.hh" + +// Custom includes +#include +#include + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +BOOST_AUTO_UNIT_TEST(packetSocketHandle) +{ + // We have a Problem here .. packet sockets are only allowed for root + if (getuid() != 0) { + BOOST_WARN_MESSAGE(false, "Cannot test satcom::lib::PacketSocketHandle as non-root user"); + return; + } + + { + satcom::lib::PacketSocketHandle sock; + + BOOST_CHECK_NO_THROW( sock.bind(satcom::lib::LLSocketAddress("lo")) ); + satcom::lib::LLSocketAddress a; + BOOST_CHECK_NO_THROW( sock.local(a) ); + BOOST_CHECK_EQUAL( a.interface(), "lo" ); + + // How am I supposed to test read and write .. grmpf .. + + // TODO: There are some failures here ... need to investigate + /* + BOOST_CHECK_NO_THROW( sock.protocol().promisc( + "lo",satcom::lib::PacketProtocol::Promiscuous) ); + BOOST_CHECK_NO_THROW( sock.protocol().promisc( + "lo",satcom::lib::PacketProtocol::AllMulticast) ); + BOOST_CHECK_NO_THROW( sock.protocol().promisc( + "lo",satcom::lib::PacketProtocol::None) ); + */ + + BOOST_CHECK_NO_THROW( sock.protocol().mcAdd( + "lo",satcom::lib::llAddress("01-02-03-04-05-06")) ); + BOOST_CHECK_NO_THROW( sock.protocol().mcDrop( + "lo",satcom::lib::llAddress("01-02-03-04-05-06")) ); + + BOOST_CHECK_NO_THROW( sock.protocol().available() ); + BOOST_CHECK( ! sock.eof() ); + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ProtocolClientSocketHandle.cti b/Socket/ProtocolClientSocketHandle.cti new file mode 100644 index 0000000..0f01b88 --- /dev/null +++ b/Socket/ProtocolClientSocketHandle.cti @@ -0,0 +1,102 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "ProtocolClientSocketHandle.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +prefix_ satcom::lib::ProtocolClientSocketHandle::ProtocolClientSocketHandle() + : ClientSocketHandle( + std::auto_ptr(new SocketProtocol())) +{ + this->protocol().init_client(); +} + +#define BOOST_PP_ITERATION_PARAMS_1 (4, (1, 9, "Socket/ProtocolClientSocketHandle.mpp", 2)) +#include BOOST_PP_ITERATE() + +template +prefix_ satcom::lib::ProtocolClientSocketHandle:: +ProtocolClientSocketHandle(FileHandle other, bool isChecked) + : ClientSocketHandle(other, isChecked) +{} + +template +prefix_ SocketProtocol const & +satcom::lib::ProtocolClientSocketHandle::protocol() +{ + BOOST_ASSERT( dynamic_cast(&this->body().protocol()) ); + // Need dynamic_cast here, since satcom::lib::SocketProtocol is a + // virtual base + return dynamic_cast(this->body().protocol()); +} + +template +prefix_ satcom::lib::ProtocolClientSocketHandle +satcom::lib::ProtocolClientSocketHandle::cast_static(FileHandle handle) +{ + return ProtocolClientSocketHandle(handle,true); +} + +template +prefix_ satcom::lib::ProtocolClientSocketHandle +satcom::lib::ProtocolClientSocketHandle::cast_dynamic(FileHandle handle) +{ + ClientSocketHandle h( + ClientSocketHandle::cast_dynamic(handle)); + // throw std::bad_cast if the protocol is invalid + dynamic_cast(static_cast(FileHandle::body(h)).protocol()); + return cast_static(handle); +} + +template +prefix_ void +satcom::lib::ProtocolClientSocketHandle::state(SocketStateMap & map, + unsigned lod) +{ + map["handle"] = prettyName(typeid(*this)); + this->body().state(map,lod); +} + +template +prefix_ std::string +satcom::lib::ProtocolClientSocketHandle::dumpState(unsigned lod) +{ + SocketStateMap map; + state(map,lod); + return detail::dumpState(map); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ProtocolClientSocketHandle.hh b/Socket/ProtocolClientSocketHandle.hh new file mode 100644 index 0000000..eeca1e7 --- /dev/null +++ b/Socket/ProtocolClientSocketHandle.hh @@ -0,0 +1,89 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_ProtocolClientSocketHandle_ +#define HH_ProtocolClientSocketHandle_ 1 + +// Custom includes +#include "ClientSocketHandle.hh" + +#include "ProtocolClientSocketHandle.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + template class ProtocolServerSocketHandle; + + /** \brief + */ + template + class ProtocolClientSocketHandle + : public ClientSocketHandle + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef SocketProtocol Protocol; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + ProtocolClientSocketHandle(); + +# define BOOST_PP_ITERATION_PARAMS_1 (4, (1, 9, "Socket/ProtocolClientSocketHandle.mpp", 1)) +# include BOOST_PP_ITERATE() + + ///@} + /////////////////////////////////////////////////////////////////////////// + + Protocol const & protocol(); + + static ProtocolClientSocketHandle cast_static(FileHandle handle); + static ProtocolClientSocketHandle cast_dynamic(FileHandle handle); + + void state(SocketStateMap & map, unsigned lod=0); + std::string dumpState(unsigned lod=0); + + protected: + ProtocolClientSocketHandle(FileHandle other, bool isChecked); + + private: + friend class ProtocolServerSocketHandle; + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "ProtocolClientSocketHandle.cci" +//#include "ProtocolClientSocketHandle.ct" +#include "ProtocolClientSocketHandle.cti" +#include "ProtocolClientSocketHandle.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ProtocolClientSocketHandle.mpp b/Socket/ProtocolClientSocketHandle.mpp new file mode 100644 index 0000000..2804682 --- /dev/null +++ b/Socket/ProtocolClientSocketHandle.mpp @@ -0,0 +1,93 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 +#ifndef MPP_ProtocolClientSocketHandle_ + +// Custom includes +#include +#include +#include + +//////////////////////////////mpp.p//////////////////////////////////////// +// Local Macros + +#define mpp_PCSH_Arg(z,n,data) BOOST_PP_CAT(A,n) const & BOOST_PP_CAT(a,n) + +#define mpp_PCSH_TemplateParameters() BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A ) +#define mpp_PCSH_MethodParameters() BOOST_PP_ENUM(BOOST_PP_ITERATION(), mpp_PCSH_Arg, ) +#define mpp_PCSH_CallParameters() BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), a ) + +////// +#endif +#else +/////////////////////////////////////////////////////////////////////////// + +////// +#if BOOST_PP_ITERATION_FLAGS()==1 +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::ProtocolClientSocketHandle:: +// ProtocolClientSocketHandle (constructor) declaration + +template < mpp_PCSH_TemplateParameters() > +ProtocolClientSocketHandle( mpp_PCSH_MethodParameters() ); + +////// +#elif BOOST_PP_ITERATION_FLAGS()==2 +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::ProtocolClientSocketHandle:: +// ProtocolClientSocketHandle (constructor) implementation + +template +template < mpp_PCSH_TemplateParameters() > +prefix_ satcom::lib::ProtocolClientSocketHandle:: +ProtocolClientSocketHandle( mpp_PCSH_MethodParameters() ) + : ClientSocketHandle( + std::auto_ptr(new SocketProtocol())) +{ + this->protocol().init_client( mpp_PCSH_CallParameters() ); +} + +////// +#endif +#endif +#if !BOOST_PP_IS_ITERATING +#ifdef MPP_PCSH__ProtocolClientSocketHandle_ +/////////////////////////////////////////////////////////////////////////// +// Undefine local Macros + +#undef mpp_PCSH_Arg +#undef mpp_PCSH_TemplateParameters +#undef mpp_PCSH_MethodParameters +#undef mpp_PCSH_CallParameters + +//////////////////////////////mpp_PCSH_.e//////////////////////////////////////// +#else +#define MPP_PCSH__ProtocolClientSocketHandle_ 1 +#endif +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ProtocolClientSocketHandle.test.cc b/Socket/ProtocolClientSocketHandle.test.cc new file mode 100644 index 0000000..be924ce --- /dev/null +++ b/Socket/ProtocolClientSocketHandle.test.cc @@ -0,0 +1,77 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "ProtocolClientSocketHandle.test.hh" +//#include "ProtocolClientSocketHandle.test.ih" + +// Custom includes +#include "ProtocolClientSocketHandle.hh" +#include "SocketProtocol.test.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + struct MyProtocol : public satcom::lib::test::SomeProtocol + { + using satcom::lib::test::SomeProtocol::init_client; + void init_client(char const *,unsigned) const {} + }; +} + +BOOST_AUTO_UNIT_TEST(protocolClientSocketHandle) +{ + typedef satcom::lib::ProtocolClientSocketHandle MySocketHandle; + + { + typedef satcom::lib::MakeSocketPolicy< + satcom::lib::test::SomeFramingPolicy, + satcom::lib::test::SomeReadPolicy, + satcom::lib::test::SomeWritePolicy + >::policy OtherSocketPolicy; + typedef satcom::lib::SocketHandle OtherSocketHandle; + + MySocketHandle h; + h.protocol(); + + OtherSocketHandle osh (h); + h = satcom::lib::static_socket_cast(osh); + } + + { + MySocketHandle hh("foo.bar.c",1234); + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ProtocolServerSocketHandle.cti b/Socket/ProtocolServerSocketHandle.cti new file mode 100644 index 0000000..76bb242 --- /dev/null +++ b/Socket/ProtocolServerSocketHandle.cti @@ -0,0 +1,109 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "ProtocolServerSocketHandle.ih" + +// Custom includes +#include "ProtocolClientSocketHandle.hh" + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +prefix_ satcom::lib::ProtocolServerSocketHandle::ProtocolServerSocketHandle() + : ServerSocketHandle( + std::auto_ptr(new SocketProtocol())) +{} + +#define BOOST_PP_ITERATION_PARAMS_1 (4, (1, 9, "Socket/ProtocolServerSocketHandle.mpp", 2)) +#include BOOST_PP_ITERATE() + +template +prefix_ SocketProtocol const & +satcom::lib::ProtocolServerSocketHandle::protocol() +{ + BOOST_ASSERT( dynamic_cast(&this->body().protocol()) ); + // Need dynamic_cast here, since satcom::lib::SocketProtocol is a + // virtual base + return dynamic_cast(this->body().protocol()); +} + +template +prefix_ satcom::lib::ProtocolClientSocketHandle +satcom::lib::ProtocolServerSocketHandle::accept() +{ + return ProtocolClientSocketHandle( + FileHandle(this->ServerSocketHandle::accept()),true); +} + +template +prefix_ satcom::lib::ProtocolServerSocketHandle +satcom::lib::ProtocolServerSocketHandle::cast_static(FileHandle handle) +{ + return ProtocolServerSocketHandle(handle,true); +} + +template +prefix_ satcom::lib::ProtocolServerSocketHandle +satcom::lib::ProtocolServerSocketHandle::cast_dynamic(FileHandle handle) +{ + ServerSocketHandle h( + ServerSocketHandle::cast_dynamic(handle)); + // throw std::bad_cast if the protocol is invalid + dynamic_cast(static_cast(FileHandle::body(h)).protocol()); + return cast_static(handle); +} + +template +prefix_ void +satcom::lib::ProtocolServerSocketHandle::state(SocketStateMap & map, + unsigned lod) +{ + map["handle"] = prettyName(typeid(*this)); + this->body().state(map,lod); +} + +template +prefix_ std::string +satcom::lib::ProtocolServerSocketHandle::dumpState(unsigned lod) +{ + SocketStateMap map; + state(map,lod); + return detail::dumpState(map); +} + +template +prefix_ satcom::lib::ProtocolServerSocketHandle:: +ProtocolServerSocketHandle(FileHandle other, bool isChecked) + : ServerSocketHandle(other,isChecked) +{} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ProtocolServerSocketHandle.hh b/Socket/ProtocolServerSocketHandle.hh new file mode 100644 index 0000000..c42ee11 --- /dev/null +++ b/Socket/ProtocolServerSocketHandle.hh @@ -0,0 +1,90 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_ProtocolServerSocketHandle_ +#define HH_ProtocolServerSocketHandle_ 1 + +// Custom includes +#include "ServerSocketHandle.hh" + +#include "ProtocolServerSocketHandle.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + template class ProtocolClientSocketHandle; + + /** \brief + */ + template + class ProtocolServerSocketHandle + : public ServerSocketHandle + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef SocketProtocol Protocol; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + ProtocolServerSocketHandle(); + +# define BOOST_PP_ITERATION_PARAMS_1 (4, (1, 9, "Socket/ProtocolServerSocketHandle.mpp", 1)) +# include BOOST_PP_ITERATE() + + ///@} + /////////////////////////////////////////////////////////////////////////// + + Protocol const & protocol(); + + ProtocolClientSocketHandle accept(); + + static ProtocolServerSocketHandle cast_static(FileHandle handle); + static ProtocolServerSocketHandle cast_dynamic(FileHandle handle); + + void state(SocketStateMap & map, unsigned lod=0); + std::string dumpState(unsigned lod=0); + + protected: + ProtocolServerSocketHandle(FileHandle other, bool isChecked); + + private: + + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "ProtocolServerSocketHandle.cci" +//#include "ProtocolServerSocketHandle.ct" +#include "ProtocolServerSocketHandle.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ProtocolServerSocketHandle.mpp b/Socket/ProtocolServerSocketHandle.mpp new file mode 100644 index 0000000..029a995 --- /dev/null +++ b/Socket/ProtocolServerSocketHandle.mpp @@ -0,0 +1,93 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 +#ifndef MPP_PSSH__ProtocolServerSocketHandle_ + +// Custom includes +#include +#include +#include + +//////////////////////////////mpp_PSSH_.p//////////////////////////////////////// +// Local Macros + +#define mpp_PSSH_Arg(z,n,data) BOOST_PP_CAT(A,n) const & BOOST_PP_CAT(a,n) + +#define mpp_PSSH_TemplateParameters() BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), class A ) +#define mpp_PSSH_MethodParameters() BOOST_PP_ENUM(BOOST_PP_ITERATION(), mpp_PSSH_Arg, ) +#define mpp_PSSH_CallParameters() BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), a ) + +////// +#endif +#else +/////////////////////////////////////////////////////////////////////////// + +////// +#if BOOST_PP_ITERATION_FLAGS()==1 +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::ProtocolServerSocketHandle:: +// ProtocolServerSocketHandle (constructor) declaration + +template < mpp_PSSH_TemplateParameters() > +ProtocolServerSocketHandle( mpp_PSSH_MethodParameters() ); + +////// +#elif BOOST_PP_ITERATION_FLAGS()==2 +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::ProtocolServerSocketHandle:: +// ProtocolServerSocketHandle (constructor) implementation + +template +template < mpp_PSSH_TemplateParameters() > +prefix_ satcom::lib::ProtocolServerSocketHandle:: +ProtocolServerSocketHandle( mpp_PSSH_MethodParameters() ) + : ServerSocketHandle( + std::auto_ptr(new SocketProtocol())) +{ + this->protocol().init_server( mpp_PSSH_CallParameters() ); +} + +////// +#endif +#endif +#if !BOOST_PP_IS_ITERATING +#ifdef MPP_PSSH__ProtocolServerSocketHandle_ +/////////////////////////////////////////////////////////////////////////// +// Undefine local Macros + +#undef mpp_PSSH_Arg +#undef mpp_PSSH_TemplateParameters +#undef mpp_PSSH_MethodParameters +#undef mpp_PSSH_CallParameters + +//////////////////////////////mpp_PSSH_.e//////////////////////////////////////// +#else +#define MPP_PSSH__ProtocolServerSocketHandle_ 1 +#endif +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ProtocolServerSocketHandle.test.cc b/Socket/ProtocolServerSocketHandle.test.cc new file mode 100644 index 0000000..22b6cb4 --- /dev/null +++ b/Socket/ProtocolServerSocketHandle.test.cc @@ -0,0 +1,90 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "ProtocolServerSocketHandle.test.hh" +//#include "ProtocolServerSocketHandle.test.ih" + +// Custom includes +#include "ProtocolServerSocketHandle.hh" +#include "SocketProtocol.test.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + + struct MyProtocol : public satcom::lib::test::SomeProtocol + { + using satcom::lib::test::SomeProtocol::init_server; + void init_server(char const *,unsigned) const {} + }; +} + +BOOST_AUTO_UNIT_TEST(protocolServerSocketHandle) +{ + typedef satcom::lib::ProtocolServerSocketHandle MySocketHandle; + + { + typedef satcom::lib::MakeSocketPolicy< + satcom::lib::test::SomeFramingPolicy, + satcom::lib::test::SomeReadPolicy, + satcom::lib::test::SomeWritePolicy + >::policy OtherSocketPolicy; + typedef satcom::lib::SocketHandle OtherSocketHandle; + + MySocketHandle h; + h.protocol(); + + OtherSocketHandle osh (h); + h = satcom::lib::static_socket_cast(osh); + + MySocketHandle::ClientSocketHandle client = h.accept(); + BOOST_CHECK_EQUAL( client.fd(), -1 ); + + BOOST_CHECK_EQUAL( h.dumpState(), + "handle: satcom::lib::ProtocolServerSocketHandle<(anonymous namespace)::MyProtocol>\n" + "file.handle: -1\n" + "file.refcount: 2\n" + "socket.policy: satcom::lib::SocketPolicy\n" + "socket.protocol: (anonymous namespace)::MyProtocol\n" + "socket.server: true\n" ); + + } + + { + MySocketHandle h("foo.bar.c",1234); + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ReadWritePolicy.cc b/Socket/ReadWritePolicy.cc new file mode 100644 index 0000000..4f772e4 --- /dev/null +++ b/Socket/ReadWritePolicy.cc @@ -0,0 +1,130 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "ReadWritePolicy.hh" +//#include "ReadWritePolicy.ih" + +// Custom includes +#include +#include +#include +#include + + +//#include "ReadWritePolicy.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ unsigned satcom::lib::ReadablePolicy::read(FileHandle handle, char * buffer, + unsigned size) +{ + int rv = -1; + do { + rv = ::read(handle.fd(), buffer, size); + if (rv < 0) + switch(errno) { + case EINTR: + break; + case EAGAIN: + // This means, the socket is non-blocking an no data was available + rv = 0; + break; + default: + throw SystemException(errno); + } + } while (rv<0); + return rv; +} + +prefix_ unsigned satcom::lib::ReadablePolicy::do_readfrom(FileHandle handle, char * buffer, + unsigned size, + struct ::sockaddr * addr, socklen_t len) +{ + int rv = -1; + do { + rv = ::recvfrom(handle.fd(),buffer, size, 0, addr, &len); + if (rv < 0) + switch (errno) { + case EINTR: + break; + case EAGAIN: + rv = 0; + break; + default: + throw SystemException(errno); + } + } while (rv<0); + return rv; +} + +prefix_ unsigned satcom::lib::WriteablePolicy::do_write(FileHandle handle, char const * buffer, + unsigned size) +{ + int rv = -1; + do { + rv = ::write(handle.fd(), buffer, size); + if (rv < 0) + switch (errno) { + case EINTR: + break; + case EAGAIN: + rv = 0; + break; + default: + throw SystemException(errno); + } + } while (rv<0); + return rv; +} + +prefix_ unsigned satcom::lib::WriteablePolicy::do_writeto(FileHandle handle, + char const * buffer, unsigned size, + struct sockaddr * addr, socklen_t len) +{ + int rv = -1; + do { + rv = ::sendto(handle.fd(), buffer, size, 0, addr, len); + if (rv < 0) + switch (errno) { + case EINTR: + break; + case EAGAIN: + rv = 0; + break; + default: + throw SystemException(errno); + } + } while (rv<0); + return rv; +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "ReadWritePolicy.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ReadWritePolicy.cti b/Socket/ReadWritePolicy.cti new file mode 100644 index 0000000..f4f7f84 --- /dev/null +++ b/Socket/ReadWritePolicy.cti @@ -0,0 +1,66 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "ReadWritePolicy.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +prefix_ unsigned satcom::lib::ReadablePolicy:: +readfrom(ClientSocketHandle handle, char * buffer, unsigned size, + typename Policy::AddressingPolicy::Address & address, + typename IfCommunicationPolicyIs::type *) +{ + return do_rcvfrom(handle, buffer, size, address.sockaddr_p(), address.sockaddr_len()); +} + +template +prefix_ unsigned satcom::lib::WriteablePolicy:: +write(ClientSocketHandle handle, char const * buffer, unsigned size, + typename IfCommunicationPolicyIs::type *) +{ + return do_write(handle,buffer,size); +} + +template +prefix_ unsigned satcom::lib::WriteablePolicy:: +writeto(ClientSocketHandle handle, + typename boost::call_traits::param_type addr, + char const * buffer, unsigned size, + typename IfCommunicationPolicyIs::type *) +{ + return do_writeto(handle, buffer, size, addr.sockaddr_p(), addr.sockaddr_len()); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ReadWritePolicy.hh b/Socket/ReadWritePolicy.hh new file mode 100644 index 0000000..fa49481 --- /dev/null +++ b/Socket/ReadWritePolicy.hh @@ -0,0 +1,90 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_ReadWritePolicy_ +#define HH_ReadWritePolicy_ 1 + +// Custom includes +#include "SocketPolicy.hh" +#include "ClientSocketHandle.hh" +#include "CommunicationPolicy.hh" + +//#include "ReadWritePolicy.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +// TODO: ReadWritePolicy.test.cc ... + +struct sockaddr; + +namespace satcom { +namespace lib { + + struct ReadablePolicy : public ReadPolicyBase + { + static unsigned read(FileHandle handle, char * buffer, unsigned size); + template + static unsigned readfrom(ClientSocketHandle handle, char * buffer, unsigned size, + typename Policy::AddressingPolicy::Address & address, + typename IfCommunicationPolicyIs::type * = 0); + + private: + static unsigned do_readfrom(FileHandle handle, char * buffer, unsigned size, + struct ::sockaddr * addr, socklen_t len); + }; + + struct NotReadablePolicy : public ReadPolicyBase + {}; + + struct WriteablePolicy : public WritePolicyBase + { + template + static unsigned write(ClientSocketHandle handle, char const * buffer, unsigned size, + typename IfCommunicationPolicyIs::type * = 0); + template + static unsigned writeto(ClientSocketHandle handle, + typename boost::call_traits::param_type addr, + char const * buffer, unsigned size, + typename IfCommunicationPolicyIs::type * = 0); + + private: + static unsigned do_write(FileHandle handle, char const * buffer, unsigned size); + static unsigned do_writeto(FileHandle handle, char const * buffer, unsigned size, + struct sockaddr * addr, socklen_t len); + }; + + struct NotWriteablePolicy : public WritePolicyBase + {}; + +}} + + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "ReadWritePolicy.cci" +//#include "ReadWritePolicy.ct" +#include "ReadWritePolicy.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SConscript b/Socket/SConscript new file mode 100644 index 0000000..1375a71 --- /dev/null +++ b/Socket/SConscript @@ -0,0 +1,15 @@ +Import('env') +import SatSCons + +########################################################################### + +sources = SatSCons.GlobSources() + +SatSCons.StandardTargets(env) + +SatSCons.Lib(env, + library = 'Socket', + sources = sources, + LIBS = [ 'Utils' ]) + +SatSCons.Doxygen(env,sources) diff --git a/Socket/ServerSocketHandle.cti b/Socket/ServerSocketHandle.cti new file mode 100644 index 0000000..0887c90 --- /dev/null +++ b/Socket/ServerSocketHandle.cti @@ -0,0 +1,160 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "ServerSocketHandle.ih" + +// Custom includes +#include + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +template +prefix_ satcom::lib::ServerSocketHandle:: +ServerSocketHandle(ServerSocketHandle other, + typename SocketHandle::template IsCompatible::type *) + : SocketHandle(other,true) +{} + +template +prefix_ satcom::lib::ServerSocketHandle:: +ServerSocketHandle(std::auto_ptr protocol) + : SocketHandle(protocol,true) +{} + +template +template +prefix_ typename satcom::lib::SocketHandle::template IsCompatible::type const & +satcom::lib::ServerSocketHandle::operator=(ServerSocketHandle other) +{ + assign(other); + return *this; +} + +/////////////////////////////////////////////////////////////////////////// +// Server socket interface + +template +prefix_ void satcom::lib::ServerSocketHandle::bind(AddressParam addr) +{ + Policy::AddressingPolicy::bind(*this,addr); +} + +template +prefix_ void satcom::lib::ServerSocketHandle::listen(unsigned backlog) +{ + Policy::CommunicationPolicy::listen(*this,backlog); +} + +template +prefix_ typename satcom::lib::ServerSocketHandle::Address +satcom::lib::ServerSocketHandle::local() +{ + typename Policy::AddressingPolicy::Address addr; + this->local(addr); + return addr; +} + +template +prefix_ void satcom::lib::ServerSocketHandle::local(Address & addr) +{ + Policy::AddressingPolicy::local(*this,addr); +} + +template +prefix_ typename satcom::lib::ServerSocketHandle::ClientSocketHandle +satcom::lib::ServerSocketHandle::accept() +{ + Address address; + return acceptfrom(address); +} + +template +prefix_ std::pair::ClientSocketHandle, + typename satcom::lib::ServerSocketHandle::Address> +satcom::lib::ServerSocketHandle::acceptfrom() +{ + + Address address; + ClientSocketHandle handle = accept(address); + return std::make_pair(handle,address); +} + +template +prefix_ typename satcom::lib::ServerSocketHandle::ClientSocketHandle +satcom::lib::ServerSocketHandle::acceptfrom(Address & addr) +{ + return ClientSocketHandle(this->protocol().clone(), + Policy::CommunicationPolicy::accept(*this,addr)); +} + +/////////////////////////////////////////////////////////////////////////// + +template +prefix_ satcom::lib::ServerSocketHandle::ServerSocketHandle(FileHandle other, + bool isChecked) + : SocketHandle(other, isChecked) +{} + +template +prefix_ satcom::lib::ServerSocketHandle +satcom::lib::ServerSocketHandle::cast_static(FileHandle handle) +{ + return ServerSocketHandle(handle,true); +} + +template +prefix_ satcom::lib::ServerSocketHandle +satcom::lib::ServerSocketHandle::cast_dynamic(FileHandle handle) +{ + SocketHandle h (SocketHandle::cast_dynamic(handle)); + if (! static_cast(FileHandle::body(handle)).isServer()) + throw std::bad_cast(); + return cast_static(handle); +} + +template +prefix_ void satcom::lib::ServerSocketHandle::state(SocketStateMap & map, unsigned lod) +{ + map["handle"] = prettyName(typeid(*this)); + this->body().state(map,lod); +} + +template +prefix_ std::string satcom::lib::ServerSocketHandle::dumpState(unsigned lod) +{ + SocketStateMap map; + state(map,lod); + return detail::dumpState(map); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ServerSocketHandle.hh b/Socket/ServerSocketHandle.hh new file mode 100644 index 0000000..42a6bae --- /dev/null +++ b/Socket/ServerSocketHandle.hh @@ -0,0 +1,125 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_ServerSocketHandle_ +#define HH_ServerSocketHandle_ 1 + +// Custom includes +#include +#include +#include "SocketHandle.hh" +#include "CommunicationPolicy.hh" +#include "AddressingPolicy.hh" + +//#include "ServerSocketHandle.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + template class ClientSocketHandle; + + /** \brief + */ + template + class ServerSocketHandle + : public SocketHandle + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef typename Policy::AddressingPolicy::Address Address; + typedef typename boost::call_traits
::param_type AddressParam; + typedef ClientSocketHandle ClientSocketHandle; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + // no default constructor + // default copy constructor + // default copy assignment + // default destructor + + // conversion constructors + template + ServerSocketHandle(ServerSocketHandle other, + typename SocketHandle::template IsCompatible::type * = 0); + + template + typename SocketHandle::template IsCompatible::type const & + operator=(ServerSocketHandle other); + + ///@} + /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// + ///\name Server socket interface + ///@{ + + void bind (AddressParam addr); + void listen (unsigned backlog=0); + + Address local (); + void local (Address & addr); + + // If the handle is non-blocking, accept will NOT block. If no connection + // is available to be returned, accept will return a ClientSocketHandle + // which is not valid() + ClientSocketHandle + accept (); + std::pair + acceptfrom (); + ClientSocketHandle + acceptfrom (Address & addr); + + ///@} + + static ServerSocketHandle cast_static(FileHandle handle); + static ServerSocketHandle cast_dynamic(FileHandle handle); + + // we need to override both since SocketHandle is *not* polymorphic + void state(SocketStateMap & map, unsigned lod=0); + std::string dumpState(unsigned lod=0); + + protected: + ServerSocketHandle(FileHandle other, bool isChecked); + explicit ServerSocketHandle(std::auto_ptr protocol); + + private: + + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "ServerSocketHandle.cci" +//#include "ServerSocketHandle.ct" +#include "ServerSocketHandle.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/ServerSocketHandle.test.cc b/Socket/ServerSocketHandle.test.cc new file mode 100644 index 0000000..299524f --- /dev/null +++ b/Socket/ServerSocketHandle.test.cc @@ -0,0 +1,101 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "ServerSocketHandle.test.hh" +//#include "ServerSocketHandle.test.ih" + +// Custom includes +#include "ServerSocketHandle.hh" +#include "ClientSocketHandle.hh" +#include "SocketProtocol.test.hh" +#include "AddressingPolicy.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + + namespace sl = satcom::lib; + + class MySocketHandle + : public sl::ServerSocketHandle + { + public: + MySocketHandle() + : sl::ServerSocketHandle( + std::auto_ptr(new sl::test::SomeProtocol())) + {} + }; +} + +BOOST_AUTO_UNIT_TEST(serverSocketHandle) +{ + typedef sl::MakeSocketPolicy< + sl::test::SomeFramingPolicy, + sl::test::SomeReadPolicy, + sl::test::SomeWritePolicy + >::policy OtherSocketPolicy; + typedef sl::SocketHandle OtherSocketHandle; + + MySocketHandle myh; + OtherSocketHandle osh (myh); + osh = myh; + + typedef sl::ServerSocketHandle SomeSocketHandle; + SomeSocketHandle ssh = sl::static_socket_cast(osh); + + typedef sl::ServerSocketHandle::policy> SomeOtherSocketHandle; + typedef sl::ClientSocketHandle OtherClientHandle; + + BOOST_CHECK_NO_THROW( sl::dynamic_socket_cast(osh) ); + BOOST_CHECK_THROW( sl::dynamic_socket_cast(osh), + std::bad_cast ); + BOOST_CHECK_THROW( sl::dynamic_socket_cast(osh), + std::bad_cast ); + + BOOST_CHECK_NO_THROW( myh.bind(0) ); + BOOST_CHECK_EQUAL( myh.local(), 2u ); + + { + MySocketHandle::ClientSocketHandle client = myh.accept(); + BOOST_CHECK_EQUAL( client.fd(), -1 ); + } + +} + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketHandle.cc b/Socket/SocketHandle.cc new file mode 100644 index 0000000..186953a --- /dev/null +++ b/Socket/SocketHandle.cc @@ -0,0 +1,146 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "SocketHandle.hh" +#include "SocketHandle.ih" + +// Custom includes +#include +#include +#include "Utils/TypeInfo.hh" + +//#include "SocketHandle.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ void satcom::lib::SocketBody::v_close() +{ + if (::shutdown(fd(),SHUT_RDWR) < 0) + throw SystemException(errno); + if (::close(fd()) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::SocketBody::v_terminate() +{ + struct linger ling; + ling.l_onoff = 0; + ling.l_linger = 0; + + // We purposely IGNORE any errors: this method is used to try and + // terminate the connection ignoring any possible problems + + ::setsockopt(fd(),SOL_SOCKET,SO_LINGER,&ling,sizeof(ling)); + ::shutdown(fd(),SHUT_RDWR); + ::close(fd()); +} + +prefix_ bool satcom::lib::SocketBody::v_eof() + const +{ + return protocol().eof(); +} + +prefix_ void satcom::lib::SocketBody::state(SocketStateMap & map, unsigned lod) +{ + map["file.handle"] = fd(); + map["file.refcount"] = refcount(); + map["socket.server"] = isServer(); + map["socket.protocol"] = prettyName(typeid(protocol())); + map["socket.policy"] = prettyName(typeid(protocol().policy())); + protocol().state(map,lod); +} + +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::detail::StateMapOrdering + +namespace { + bool contains(std::string::iterator b, std::string::iterator e, char c) + { + for (; b != e; ++b) + if (*b == c) + return true; + return false; + } +} + +prefix_ bool satcom::lib::detail::StateMapOrdering::operator()(std::string a1, std::string a2) + const +{ + std::string::iterator i1 (a1.begin()); + std::string::iterator const i1_end (a1.end()); + std::string::iterator i2 (a2.begin()); + std::string::iterator const i2_end (a2.end()); + for(; i1 != i1_end && i2 != i2_end && *i1 == *i2; ++i1, ++i2) ; + if (i1 == i1_end) { + if (i2 == i2_end) + // the strings are equal + return false; + if (contains(i2,i2_end,'.')) + // the longer string is a sub-'directory' of the shorter + return true; + return *i1 < *i2; + } + else if (i2 == i2_end) { // && i1 != i1_end + if (contains(i1,i1_end,'.')) + // the longer string is a sub-'directory' of the shorter + return false; + return *i1 < *i2; + } + if (contains(i1,i1_end,'.')) { + if (contains(i2,i2_end,'.')) + return *i1 < *i2; + return false; + } + else if (contains(i2,i2_end,'.')) + return true; + return *i1 < *i2; +} + +prefix_ std::string satcom::lib::detail::dumpState(SocketStateMap const & map) +{ + std::stringstream s; + SocketStateMap::const_iterator i (map.begin()); + SocketStateMap::const_iterator i_end (map.end()); + for (; i != i_end; ++i) + s << i->first << ": " << i->second << "\n"; + return s.str(); +} + +template +prefix_ std::ostream & satcom::lib::operator<<(std::ostream & os, SocketHandle handle) +{ + os << handle.dumpState(); + return os; +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "SocketHandle.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketHandle.cci b/Socket/SocketHandle.cci new file mode 100644 index 0000000..f036df1 --- /dev/null +++ b/Socket/SocketHandle.cci @@ -0,0 +1,78 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "SocketHandle.ih" + +// Custom includes +#include "Utils/Exception.hh" +#include "SocketProtocol.hh" + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +prefix_ satcom::lib::SocketBody::SocketBody(std::auto_ptr protocol, + bool isServer) + : protocol_(protocol), isServer_(isServer) +{ + BOOST_ASSERT( ! protocol_->body_ ); + protocol_->body_ = this; +} + +prefix_ satcom::lib::SocketBody::SocketBody(std::auto_ptr protocol, + bool isServer, int fd) + : FileBody(fd), protocol_(protocol), isServer_(isServer) +{ + BOOST_ASSERT( ! protocol_->body_ ); + protocol_->body_ = this; +} + +prefix_ satcom::lib::SocketProtocol const & satcom::lib::SocketBody::protocol() + const +{ + return *protocol_; +} + +prefix_ bool satcom::lib::SocketBody::isServer() +{ + return isServer_; +} + +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::detail::ConvertibleString + +prefix_ satcom::lib::detail::ConvertibleString::ConvertibleString() +{} + +prefix_ satcom::lib::detail::ConvertibleString::ConvertibleString(bool v) + : std::string(v ? "true" : "false") +{} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketHandle.ct b/Socket/SocketHandle.ct new file mode 100644 index 0000000..9a90bd8 --- /dev/null +++ b/Socket/SocketHandle.ct @@ -0,0 +1,50 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "SocketHandle.ih" + +// Custom includes +#include + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template +prefix_ satcom::lib::detail::ConvertibleString & +satcom::lib::detail::ConvertibleString::operator+=(ConvertibleString const & other) +{ + if (!empty()) + this->std::string::operator+=(", "); + this->std::string::operator+=(other); + return *this; +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketHandle.cti b/Socket/SocketHandle.cti new file mode 100644 index 0000000..dde5bf7 --- /dev/null +++ b/Socket/SocketHandle.cti @@ -0,0 +1,188 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "SocketHandle.ih" + +// Custom includes +#include +#include +#include "Utils/TypeInfo.hh" + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +template +prefix_ satcom::lib::SocketHandle::SocketHandle(SocketHandle other, + typename IsCompatible::type *) + : FileHandle(other) +{} + +template +template +prefix_ typename satcom::lib::SocketHandle::template IsCompatible::type const & +satcom::lib::SocketHandle::operator=(SocketHandle other) +{ + assign(other); + return *this; +} + +template +prefix_ +satcom::lib::SocketHandle::SocketHandle(std::auto_ptr protocol, + bool isServer) + : FileHandle(std::auto_ptr(new SocketBody(protocol,isServer))) +{} + +template +prefix_ satcom::lib::SocketHandle::SocketHandle(FileHandle other, bool isChecked) + : FileHandle(other) +{ + BOOST_ASSERT( isChecked ); + BOOST_ASSERT( dynamic_cast(&FileHandle::body()) ); +} + +template +prefix_ satcom::lib::SocketBody & satcom::lib::SocketHandle::body() +{ + BOOST_ASSERT( dynamic_cast(&FileHandle::body()) ); + return static_cast(FileHandle::body()); +} + +template +prefix_ satcom::lib::SocketBody const & satcom::lib::SocketHandle::body() + const +{ + BOOST_ASSERT( dynamic_cast(&FileHandle::body()) ); + return static_cast(FileHandle::body()); +} + +template +prefix_ satcom::lib::SocketProtocol const & satcom::lib::SocketHandle::protocol() + const +{ + return body().protocol(); +} + +template +prefix_ void satcom::lib::SocketHandle::assign(FileHandle other) +{ + FileHandle::operator=(other); +} + +template +prefix_ satcom::lib::SocketHandle +satcom::lib::SocketHandle::cast_static(FileHandle handle) +{ + return SocketHandle(handle,true); +} + +template +prefix_ satcom::lib::SocketHandle +satcom::lib::SocketHandle::cast_dynamic(FileHandle handle) +{ + // throws bad_cast if the body is not a SocketBody + SocketBody & body (dynamic_cast(FileHandle::body(handle))); + // throws bad_cast if the poplicy is not compatible + SocketPolicy::checkBaseOf(body.protocol().policy()); + return cast_static(handle); +} + +template +prefix_ Target satcom::lib::static_socket_cast(Source handle) +{ + BOOST_STATIC_ASSERT(( + boost::is_convertible::value && + boost::is_convertible::value && + ( boost::is_convertible::value || + boost::is_convertible::value ) )); + BOOST_ASSERT( check_socket_cast(handle) ); + return Target::cast_static(handle); +} + +template +prefix_ Target satcom::lib::dynamic_socket_cast(Source handle) +{ + BOOST_STATIC_ASSERT(( + boost::is_convertible::value && + boost::is_convertible::value && + ( boost::is_convertible::value || + boost::is_convertible::value ) )); + return Target::cast_dynamic(handle); +} + +template +prefix_ bool satcom::lib::check_socket_cast(Source handle) +{ + BOOST_STATIC_ASSERT(( + boost::is_convertible::value && + boost::is_convertible::value && + ( boost::is_convertible::value || + boost::is_convertible::value ) )); + // we don't have a non-throwing variant of cast_dynamic + // for two reasons: + // a) since the handle is passed back by value, we cannot return + // something like a null handle + // b) it is simpler to implement cast_dynamic throwig bad_cast on + // failure than implementing cast_check + try { + Target::cast_dynamic(handle); + } + catch (std::bad_cast const &) { + return false; + } + return true; +} + +template +prefix_ void satcom::lib::SocketHandle::state(SocketStateMap & map, unsigned lod) +{ + map["handle"] = prettyName(typeid(*this)); + body().state(map,lod); +} + +template +prefix_ std::string satcom::lib::SocketHandle::dumpState(unsigned lod) +{ + SocketStateMap map; + state(map,lod); + return detail::dumpState(map); +} + +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::detail::ConvertibleString + +template +prefix_ satcom::lib::detail::ConvertibleString::ConvertibleString(T const & other) + : std::string(boost::lexical_cast(other)) +{} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketHandle.hh b/Socket/SocketHandle.hh new file mode 100644 index 0000000..f56e7d4 --- /dev/null +++ b/Socket/SocketHandle.hh @@ -0,0 +1,122 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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: Create a SocketHandleBase class and move some non-Policy +// dependent code there + +#ifndef HH_SocketHandle_ +#define HH_SocketHandle_ 1 + +// Custom includes +#include // std::auto_ptr +#include "FileHandle.hh" +#include "SocketPolicy.hh" + +//#include "SocketHandle.mpp" +#include "SocketHandle.ih" +///////////////////////////////hh.p//////////////////////////////////////// +#include "SocketHandle.ih" + +namespace satcom { +namespace lib { + + /** \brief + */ + template + class SocketHandle + : public FileHandle + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef SocketPolicy Policy; + + template + struct IsCompatible + : public boost::enable_if< SocketPolicyIsBaseOf, + SocketHandle > + {}; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + // default copy constructor + // default copy assignment + // default destructor + + // conversion constructors + template + SocketHandle(SocketHandle other, + typename IsCompatible::type * = 0); + + ///@} + /////////////////////////////////////////////////////////////////////////// + + template + typename IsCompatible::type const & operator=(SocketHandle other); + + static SocketHandle cast_static(FileHandle handle); + static SocketHandle cast_dynamic(FileHandle handle); + + void state(SocketStateMap & map, unsigned lod=0); + std::string dumpState(unsigned lod=0); + + protected: + explicit SocketHandle(std::auto_ptr protocol, bool isServer); + SocketHandle(FileHandle other, bool isChecked); + + SocketBody & body(); + SocketBody const & body() const; + SocketProtocol const & protocol() const; + + void assign(FileHandle other); + + private: + + }; + + template + std::ostream & operator<<(std::ostream & os, SocketHandle handle); + + template + Target static_socket_cast(Source handle); + + template + Target dynamic_socket_cast(Source handle); + + template + bool check_socket_cast(Source handle); +}} + +///////////////////////////////hh.e//////////////////////////////////////// +#include "SocketHandle.cci" +#include "SocketHandle.ct" +#include "SocketHandle.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketHandle.ih b/Socket/SocketHandle.ih new file mode 100644 index 0000000..f2e2a32 --- /dev/null +++ b/Socket/SocketHandle.ih @@ -0,0 +1,111 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_SocketHandle_ +#define IH_SocketHandle_ 1 + +// Custom includes +#include +#include +#include +#include "FileHandle.hh" + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + class SocketProtocol; + + namespace detail { + + class ConvertibleString : public std::string + { + public: + ConvertibleString(); + ConvertibleString(bool v); + template + ConvertibleString(T const & other); + template + ConvertibleString & operator+= (ConvertibleString const & other); + }; + + struct StateMapOrdering + : public std::binary_function + { + bool operator()(std::string a1, std::string a2) const; + }; + + } + + typedef std::map< std::string, detail::ConvertibleString, detail::StateMapOrdering > SocketStateMap; + + namespace detail { + std::string dumpState(SocketStateMap const & map); + } + + class SocketBody + : public FileBody + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef boost::intrusive_ptr ptr; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + explicit SocketBody(std::auto_ptr protocol, bool isServer); + SocketBody(std::auto_ptr protocol, bool isServer, int fd); + + // no copy + // no conversion constructors + + ///@} + /////////////////////////////////////////////////////////////////////////// + + SocketProtocol const & protocol() const; + bool isServer(); + + void state(SocketStateMap & map, unsigned lod); + + private: + virtual void v_close(); + virtual void v_terminate(); + virtual bool v_eof() const; + + boost::scoped_ptr protocol_; + bool isServer_; + }; + +}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketHandle.test.cc b/Socket/SocketHandle.test.cc new file mode 100644 index 0000000..cc2def8 --- /dev/null +++ b/Socket/SocketHandle.test.cc @@ -0,0 +1,107 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "SocketHandle.test.hh" +//#include "SocketHandle.test.ih" + +// Custom includes +#include "SocketHandle.hh" +#include "SocketProtocol.test.hh" +#include "AddressingPolicy.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + namespace sl = satcom::lib; + + class MySocketHandle + : public sl::SocketHandle + { + public: + MySocketHandle() + : sl::SocketHandle( + std::auto_ptr(new sl::test::SomeProtocol()),false) + {} + }; + + class FDHandle + : public satcom::lib::FileHandle + { + public: + FDHandle() + : satcom::lib::FileHandle(std::auto_ptr( + new satcom::lib::FileBody())) {} + }; +} + +BOOST_AUTO_UNIT_TEST(socketHandle) +{ + typedef sl::MakeSocketPolicy< + sl::test::SomeCommunicationPolicy, + sl::test::SomeReadPolicy + >::policy OtherSocketPolicy; + typedef sl::SocketHandle OtherSocketHandle; + + MySocketHandle myh; + OtherSocketHandle osh (myh); + osh = myh; + + typedef sl::SocketHandle SomeSocketHandle; + SomeSocketHandle ssh = satcom::lib::static_socket_cast(osh); + + BOOST_CHECK_NO_THROW( satcom::lib::dynamic_socket_cast(osh) ); + + typedef sl::SocketHandle< sl::MakeSocketPolicy< + OtherSocketPolicy, + satcom::lib::NoAddressingPolicy + >::policy> SomeOtherSocketHandle; + + BOOST_CHECK_THROW( satcom::lib::dynamic_socket_cast(osh), + std::bad_cast ); + BOOST_CHECK_THROW( satcom::lib::dynamic_socket_cast( + satcom::lib::FileHandle(FDHandle())), + std::bad_cast ); + + BOOST_CHECK_EQUAL( myh.dumpState(), + "handle: satcom::lib::SocketHandle >\n" + "file.handle: -1\n" + "file.refcount: 3\n" + "socket.policy: satcom::lib::SocketPolicy\n" + "socket.protocol: satcom::lib::test::SomeProtocol\n" + "socket.server: false\n" ); + +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketPolicy.ct b/Socket/SocketPolicy.ct new file mode 100644 index 0000000..b2b2944 --- /dev/null +++ b/Socket/SocketPolicy.ct @@ -0,0 +1,54 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "SocketPolicy.ih" + +// Custom includes + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +#define SP_TemplateArgs(x1,x2,n,SomePolicy) BOOST_PP_COMMA_IF(n) class BOOST_PP_CAT(SomePolicy,_) +#define SP_TemplateParams(x1,x2,n,SomePolicy) BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(SomePolicy,_) + +template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SATLIB_SOCKET_POLICIES ) > +prefix_ void satcom::lib::SocketPolicy< BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateParams, , SATLIB_SOCKET_POLICIES ) >:: +checkBaseOf(SocketPolicyBase const & other) +{ +# define SP_CheckPolicy(x1,x2,SomePolicy) dynamic_cast(other.BOOST_PP_CAT(the,SomePolicy)()); + BOOST_PP_SEQ_FOR_EACH( SP_CheckPolicy, , SATLIB_SOCKET_POLICIES ) +# undef SP_CheckPolicy +} + +#undef SP_TemplateArgs +#undef SP_TemplateParams + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketPolicy.hh b/Socket/SocketPolicy.hh new file mode 100644 index 0000000..a2a0c05 --- /dev/null +++ b/Socket/SocketPolicy.hh @@ -0,0 +1,75 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_SocketPolicy_ +#define HH_SocketPolicy_ 1 + +// Custom includes + +//#include "SocketPolicy.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + // This may be adapted to change the supported policies (however, + // ClientSocketHandle and ServerSocketHandle will probably have to + // be adjusted accordingly). However, AddressingPolicy MUST always + // be the first Policy member ... + +# define SATLIB_SOCKET_POLICIES \ + (AddressingPolicy) \ + (FramingPolicy) \ + (CommunicationPolicy) \ + (ReadPolicy) \ + (WritePolicy) \ + (BufferingPolicy) + + // The implementation file will for each Policy declared above + // define the following (SomePolicy is one of the above): + // + // struct SomePolicyBase; + // typedef UndefinedSomePolicy; + // template SomePolicyIs< SocketPolicy, Axis > + // template IfSomePolicyIs< SocketPolicy, Axis > + // template IfSomePolicyIsNot< SocketPolicy, Axis > + // + // Additionally the following are defined: + // + // class SocketPolicyBase + // template SocketPolicy< ..policies.. > + // template MakeSocketPolicy< ..args.. > + // template SocketPolicyIsBaseOf< Base, Derived > +}} + +//////////////////////////////hh.e//////////////////////////////////////// +#include "SocketPolicy.ih" +//#include "SocketPolicy.cci" +#include "SocketPolicy.ct" +//#include "SocketPolicy.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketPolicy.ih b/Socket/SocketPolicy.ih new file mode 100644 index 0000000..58fcba3 --- /dev/null +++ b/Socket/SocketPolicy.ih @@ -0,0 +1,255 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_SocketPolicy_ +#define IH_SocketPolicy_ 1 + +// Custom includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include // for enable_if + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + +# define SATLIB_SOCKET_POLICIES_N BOOST_PP_SEQ_SIZE( SATLIB_SOCKET_POLICIES ) + + // This REALLY is bad ... but we just need an Address member in + // AddressingPolicyBase as long as ClientSocketHandle / + // ServerSocketHandle don't make use of enable_if for each and + // every member they define ... + + struct AddressingPolicyBase + { + virtual ~ AddressingPolicyBase() {} + + class Address + { + private: + Address(); + }; + }; + +# define SP_DeclareBase(x1,x2,SomePolicy) \ + struct BOOST_PP_CAT(SomePolicy,Base) \ + { virtual ~ BOOST_PP_CAT(SomePolicy,Base) () {} }; \ + typedef BOOST_PP_CAT(SomePolicy,Base) BOOST_PP_CAT(Unspecified,SomePolicy); + + BOOST_PP_SEQ_FOR_EACH( SP_DeclareBase, , BOOST_PP_SEQ_POP_FRONT( SATLIB_SOCKET_POLICIES ) ) + +# undef SP_DeclareBase + + struct SocketPolicyBase + { + virtual ~SocketPolicyBase() {} + +# define SP_DeclareTypedef(x1,x2,SomePolicy) \ + typedef BOOST_PP_CAT(SomePolicy,Base) SomePolicy; \ + BOOST_PP_CAT(SomePolicy,Base) BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); \ + virtual BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const \ + { return BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); } + + BOOST_PP_SEQ_FOR_EACH( SP_DeclareTypedef, , SATLIB_SOCKET_POLICIES ) + +# undef SP_DeclareTypedef + }; + +# define SP_TemplateArgs(x1,x2,n,SomePolicy) \ + BOOST_PP_COMMA_IF( n ) \ + class BOOST_PP_CAT(SomePolicy,_) = BOOST_PP_CAT(SomePolicy,Base) + + template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SATLIB_SOCKET_POLICIES ) > + struct SocketPolicy + : public SocketPolicyBase + { +# define SP_DeclarePolicyMember(x1,x2,SomePolicy) \ + typedef BOOST_PP_CAT(SomePolicy,_) SomePolicy; \ + SomePolicy BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); \ + BOOST_PP_CAT(SomePolicy,Base) const & BOOST_PP_CAT(the,SomePolicy) () const \ + { return BOOST_PP_CAT(BOOST_PP_CAT(the,SomePolicy),_); } + + BOOST_PP_SEQ_FOR_EACH( SP_DeclarePolicyMember, , SATLIB_SOCKET_POLICIES ) +# undef SP_DeclarePolicyMember + + static void checkBaseOf(SocketPolicyBase const & other); + }; + +# undef SP_TemplateArgs + +namespace impl { + + struct nil {}; + + template + struct SocketPolicy_rv + { int v[N+1]; }; + + template + struct MakeSocketPolicy_merge + {}; + +# define SP_DeclareMakeSocketPolicy_merge_member(r,n,m,SomePolicy) \ + BOOST_PP_COMMA_IF( m ) \ + BOOST_PP_IIF( BOOST_PP_EQUAL(n,m), Policy, typename Base::SomePolicy ) + +# define BOOST_PP_LOCAL_LIMITS (0, BOOST_PP_DEC( SATLIB_SOCKET_POLICIES_N ) ) +# define BOOST_PP_LOCAL_MACRO(n) \ + SocketPolicy_rv MakeSocketPolicy_merge_(BOOST_PP_CAT( BOOST_PP_SEQ_ELEM( n, SATLIB_SOCKET_POLICIES ),Base)*); \ + \ + template \ + struct MakeSocketPolicy_merge)> \ + { \ + typedef SocketPolicy< \ + BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareMakeSocketPolicy_merge_member, n, SATLIB_SOCKET_POLICIES ) \ + > type; \ + }; + +# include BOOST_PP_LOCAL_ITERATE() + +# undef SP_DeclareMakeSocketPolicy_merge_member + + struct MakeSocketPolicy_fold + { + template + struct apply + : MakeSocketPolicy_merge(0)))> + {}; + + template + struct apply + { + typedef Base type; + }; + }; + + template + struct MakeSocketPolicy_impl + { + typedef typename boost::mpl::fold< Vector, Base, MakeSocketPolicy_fold >::type policy; + }; + +# define SP_DeclareArguments(x1,x2,n,SomePolicy) \ + BOOST_PP_COMMA_IF( n ) \ + typename Base::SomePolicy * + + template + SocketPolicy_rv<1> SocketPolicy_checkcompat_( + BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SATLIB_SOCKET_POLICIES ) ); + +# undef SP_DeclareArguments + + template + SocketPolicy_rv<2> SocketPolicy_checkcompat_( + BOOST_PP_ENUM_PARAMS( SATLIB_SOCKET_POLICIES_N, void * BOOST_PP_INTERCEPT ) ); + + template + struct SocketPolicy_checkcompat + : public boost::false_type + {}; + + template<> + struct SocketPolicy_checkcompat)> + : public boost::true_type + {}; + + +# define SP_DeclareArguments(x1,x2,n,SomePolicy) \ + BOOST_PP_COMMA_IF( n ) \ + static_cast(0) + + template + struct SocketPolicy_compatibility + : public SocketPolicy_checkcompat< sizeof( + SocketPolicy_checkcompat_( + BOOST_PP_SEQ_FOR_EACH_I( SP_DeclareArguments, , SATLIB_SOCKET_POLICIES ) )) > + {}; + +} // namespace impl + + template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SATLIB_SOCKET_POLICIES_N, class T, satcom::lib::impl::nil ) > + class MakeSocketPolicy + : public boost::mpl::if_< boost::is_convertible< T0*, SocketPolicyBase* >, + impl::MakeSocketPolicy_impl< T0, boost::mpl::vector< BOOST_PP_ENUM_SHIFTED_PARAMS( SATLIB_SOCKET_POLICIES_N, T ) > >, + impl::MakeSocketPolicy_impl< SocketPolicy<>, + boost::mpl::vector< BOOST_PP_ENUM_PARAMS( SATLIB_SOCKET_POLICIES_N, T ) > > >::type + {}; + + template + struct SocketPolicyIsBaseOf + : public boost::mpl::if_< boost::mpl::and_< boost::is_convertible< BasePolicy*, SocketPolicyBase* >, + boost::is_convertible< DerivedPolicy*, SocketPolicyBase* > >, + impl::SocketPolicy_compatibility, + boost::false_type >::type + {}; + +# define SP_DefineConditions(x1,x2,SomePolicy) \ + template \ + struct BOOST_PP_CAT(SomePolicy,Is) \ + : public boost::is_convertible< typename Policy::SomePolicy*, Trait* > \ + {}; \ + \ + template \ + struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),Is) \ + : public boost::enable_if< BOOST_PP_CAT(SomePolicy,Is) > \ + {}; \ + \ + template \ + struct BOOST_PP_CAT(BOOST_PP_CAT(If,SomePolicy),IsNot) \ + : public boost::enable_if_c< ! BOOST_PP_CAT(SomePolicy,Is)::value > \ + {}; + + BOOST_PP_SEQ_FOR_EACH( SP_DefineConditions, , SATLIB_SOCKET_POLICIES ) + +# undef SP_DefineConditions + +}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketPolicy.test.cc b/Socket/SocketPolicy.test.cc new file mode 100644 index 0000000..af167a4 --- /dev/null +++ b/Socket/SocketPolicy.test.cc @@ -0,0 +1,140 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "SocketPolicy.test.hh" +//#include "SocketPolicy.test.ih" + +// Custom includes +#include "SocketPolicy.hh" +#include "SocketPolicy.test.hh" + +#include +#include +#include +#include +#include // enable_if + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +using namespace satcom::lib; + +namespace { + struct INetAddressingPolicy : public AddressingPolicyBase {}; + struct UnixAddressingPolicy : public AddressingPolicyBase {}; + + struct StreamFramingPolicy : public FramingPolicyBase {}; + struct DgramFramingPolicy : public FramingPolicyBase {}; + + struct ConnectedCommunicationPolicy : public CommunicationPolicyBase {}; + struct UnconnectedCommunicationPolicy : public CommunicationPolicyBase {}; + + struct ReadablePolicy : public ReadPolicyBase {}; + struct UnreadablePolicy : public ReadPolicyBase {}; + + struct WritablePolicy : public WritePolicyBase {}; + struct UnwritablePolicy : public WritePolicyBase {}; + + struct SocketBufferingPolicy : public BufferingPolicyBase {}; + + template + struct ConvertibleValue + { + ConvertibleValue() {} + ConvertibleValue(ConvertibleValue const & other) {} + + template + ConvertibleValue(ConvertibleValue const & other, + typename boost::enable_if< SocketPolicyIsBaseOf >::type * = 0) + {} + + ConvertibleValue const & operator=(ConvertibleValue const & other) + { return *this; } + + template + typename boost::enable_if< SocketPolicyIsBaseOf, + ConvertibleValue >::type const & + operator=(ConvertibleValue const & other) + { return *this; } + }; + +} + +BOOST_AUTO_UNIT_TEST(socketPolicy) +{ + // All these checks are really compile-time checks ... + + typedef MakeSocketPolicy< + UnixAddressingPolicy, + ConnectedCommunicationPolicy, + ReadablePolicy>::policy Policy1; + + typedef SocketPolicy< + UnixAddressingPolicy, + UnspecifiedFramingPolicy, + ConnectedCommunicationPolicy, + ReadablePolicy, + UnspecifiedWritePolicy, + UnspecifiedBufferingPolicy> Policy2; + + BOOST_MPL_ASSERT(( boost::is_same )); + + typedef MakeSocketPolicy< + Policy1, + UnspecifiedCommunicationPolicy>::policy Policy3; + + typedef SocketPolicy< + UnixAddressingPolicy, + UnspecifiedFramingPolicy, + UnspecifiedCommunicationPolicy, + ReadablePolicy, + UnspecifiedWritePolicy, + UnspecifiedBufferingPolicy> Policy4; + + BOOST_MPL_ASSERT(( boost::is_same )); + BOOST_MPL_ASSERT_NOT(( boost::is_same )); + + BOOST_MPL_ASSERT(( SocketPolicyIsBaseOf )); + BOOST_MPL_ASSERT_NOT(( SocketPolicyIsBaseOf )); + BOOST_MPL_ASSERT_NOT(( SocketPolicyIsBaseOf )); + + // The following should fail at compile time + // BOOST_MPL_ASSERT(( SocketPolicyIsBaseOf )); + + ConvertibleValue p1; + ConvertibleValue p3(p1); + + p3 = p1; + // The following should fail at compile time + // p1 = p3; +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketPolicy.test.hh b/Socket/SocketPolicy.test.hh new file mode 100644 index 0000000..cebba2d --- /dev/null +++ b/Socket/SocketPolicy.test.hh @@ -0,0 +1,130 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_SocketPolicy_test_ +#define HH_SocketPolicy_test_ 1 + +// Custom includes +#include "SocketPolicy.hh" +#include "FileHandle.hh" + +//#include "SocketPolicy.test.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { +namespace test { + + struct SomeAddressingPolicy : public satcom::lib::AddressingPolicyBase + { + typedef unsigned Address; + + static void peer(FileHandle handle, unsigned & addr) + { addr=1; } + static void local(FileHandle, unsigned & addr) + { addr=2; } + static void connect(FileHandle, unsigned addr) + {} + static void bind(FileHandle, unsigned addr) + {} + }; + + struct SomeFramingPolicy : public satcom::lib::FramingPolicyBase + {}; + + struct SomeCommunicationPolicy : public satcom::lib::CommunicationPolicyBase + { + static int accept(FileHandle handle, unsigned & addr) + { addr = 3; return -1; } + }; + + struct SomeReadPolicy : public satcom::lib::ReadPolicyBase + { + static unsigned const TEST_SIZE = 9; + + static unsigned read(FileHandle handle, char * buffer, unsigned size) + { + int const n (size::policy SomeSocketPolicy; + +}}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "SocketPolicy.test.cci" +//#include "SocketPolicy.test.ct" +//#include "SocketPolicy.test.cti" +//#include "SocketPolicy.test.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketProtocol.cc b/Socket/SocketProtocol.cc new file mode 100644 index 0000000..f82cd5f --- /dev/null +++ b/Socket/SocketProtocol.cc @@ -0,0 +1,46 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "SocketProtocol.hh" +//#include "SocketProtocol.ih" + +// Custom includes + +//#include "SocketProtocol.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ void satcom::lib::SocketProtocol::state(SocketStateMap & map, unsigned lod) + const +{} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "SocketProtocol.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketProtocol.cci b/Socket/SocketProtocol.cci new file mode 100644 index 0000000..a10def6 --- /dev/null +++ b/Socket/SocketProtocol.cci @@ -0,0 +1,54 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "SocketProtocol.ih" + +// Custom includes +#include + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +prefix_ satcom::lib::SocketProtocol::SocketProtocol() + : body_(0) +{} + +prefix_ satcom::lib::SocketProtocol::~SocketProtocol() +{} + +prefix_ satcom::lib::SocketBody & satcom::lib::SocketProtocol::body() + const +{ + BOOST_ASSERT( body_ ); + return *body_; +} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketProtocol.cti b/Socket/SocketProtocol.cti new file mode 100644 index 0000000..f2b3287 --- /dev/null +++ b/Socket/SocketProtocol.cti @@ -0,0 +1,51 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "SocketProtocol.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +prefix_ satcom::lib::ConcreteSocketProtocol::~ConcreteSocketProtocol() +{} + +template +prefix_ typename satcom::lib::ConcreteSocketProtocol::Policy const & +satcom::lib::ConcreteSocketProtocol::policy() + const +{ + return policy_; +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketProtocol.hh b/Socket/SocketProtocol.hh new file mode 100644 index 0000000..4dbd95b --- /dev/null +++ b/Socket/SocketProtocol.hh @@ -0,0 +1,122 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_SocketProtocol_ +#define HH_SocketProtocol_ 1 + +// Custom includes +#include +// TODO: this is really bad. This includes and predefs should be restructured +#include "SocketHandle.ih" + +//#include "SocketProtocol.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + class SocketPolicyBase; + + class SocketProtocol : boost::noncopyable + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + SocketProtocol(); + virtual ~SocketProtocol() = 0; + + // default default constructor + // no copy + // no conversion constructors + + ///@} + /////////////////////////////////////////////////////////////////////////// + + SocketBody & body() const; + virtual SocketPolicyBase const & policy() const = 0; + + /////////////////////////////////////////////////////////////////////////// + // Virtual interface + + virtual std::auto_ptr clone() const = 0; + virtual unsigned available() const = 0; + virtual bool eof() const = 0; + virtual void state(SocketStateMap & map, unsigned lod) const; + + protected: + + private: + // backpointer to owning SocketBody instance + SocketBody * body_; + friend class SocketBody; + }; + + template + class ConcreteSocketProtocol + : public virtual SocketProtocol + { + public: + /////////////////////////////////////////////////////////////////////////// + // Types + + typedef SocketPolicy Policy; + + /////////////////////////////////////////////////////////////////////////// + ///\name Structors and default members + ///@{ + + ~ConcreteSocketProtocol() = 0; + + // no default constructor + // no copy + // no conversion constructors + + ///@} + /////////////////////////////////////////////////////////////////////////// + + Policy const & policy() const; + + protected: + + private: + Policy policy_; + + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +#include "SocketProtocol.cci" +//#include "SocketProtocol.ct" +#include "SocketProtocol.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketProtocol.test.cc b/Socket/SocketProtocol.test.cc new file mode 100644 index 0000000..fdd880c --- /dev/null +++ b/Socket/SocketProtocol.test.cc @@ -0,0 +1,56 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "SocketProtocol.test.hh" +//#include "SocketProtocol.test.ih" + +// Custom includes +#include "SocketProtocol.hh" +#include "SocketPolicy.hh" +#include "SocketProtocol.test.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +BOOST_AUTO_UNIT_TEST(socketProtocol) +{ + satcom::lib::test::SomeProtocol protocol; + + // This would fail an assertion ... + // BOOST_CHECK( protocol.body() == 0 ); + + protocol.policy(); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/SocketProtocol.test.hh b/Socket/SocketProtocol.test.hh new file mode 100644 index 0000000..047a6a9 --- /dev/null +++ b/Socket/SocketProtocol.test.hh @@ -0,0 +1,68 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_SocketProtocol_test_ +#define HH_SocketProtocol_test_ 1 + +// Custom includes +#include "SocketProtocol.hh" +#include "SocketPolicy.test.hh" +#include "ProtocolClientSocketHandle.hh" + +//#include "SocketProtocol.test.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { +namespace test { + + class SomeProtocol + : public ConcreteSocketProtocol + { + public: + ~SomeProtocol() {} + + void init_client() const {} + void init_server() const {} + + std::auto_ptr clone() const + { return std::auto_ptr(new SomeProtocol()); } + unsigned available() const + { return Policy::ReadPolicy::TEST_SIZE; } + bool eof() const + { return false; } + }; + +}}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "SocketProtocol.test.cci" +//#include "SocketProtocol.test.ct" +//#include "SocketProtocol.test.cti" +//#include "SocketProtocol.test.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/TCPProtocol.cc b/Socket/TCPProtocol.cc new file mode 100644 index 0000000..f444ac3 --- /dev/null +++ b/Socket/TCPProtocol.cc @@ -0,0 +1,97 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "TCPProtocol.hh" +//#include "TCPProtocol.ih" + +// Custom includes +#include +#include +#include +#include +#include // for SIOCINQ / SIOCOUTQ +#include "SocketHandle.hh" + +//#include "TCPProtocol.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ bool satcom::lib::TCPProtocol::nodelay() + const +{ + int value; + socklen_t len (sizeof(value)); + if (::getsockopt(body().fd(),SOL_TCP,TCP_NODELAY,&value,&len) < 0) + throw SystemException(errno); + return value; +} + +prefix_ void satcom::lib::TCPProtocol::nodelay(bool value) + const +{ + int ivalue (value); + if (::setsockopt(body().fd(),SOL_TCP,TCP_NODELAY,&ivalue,sizeof(ivalue)) < 0) + throw SystemException(errno); +} + +prefix_ unsigned satcom::lib::TCPProtocol::siocinq() + const +{ + int n; + if (::ioctl(body().fd(),SIOCINQ,&n) < 0) + throw SystemException(errno); + return n; +} + +prefix_ unsigned satcom::lib::TCPProtocol::siocoutq() + const +{ + int n; + if (::ioctl(body().fd(),SIOCOUTQ,&n) < 0) + throw SystemException(errno); + return n; +} + +prefix_ unsigned satcom::lib::TCPProtocol::available() + const +{ + return siocinq(); +} + +prefix_ bool satcom::lib::TCPProtocol::eof() + const +{ + return body().readable() && available()==0; +} + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "TCPProtocol.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/TCPProtocol.hh b/Socket/TCPProtocol.hh new file mode 100644 index 0000000..adf029f --- /dev/null +++ b/Socket/TCPProtocol.hh @@ -0,0 +1,60 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_TCPProtocol_ +#define HH_TCPProtocol_ 1 + +// Custom includes +#include "SocketProtocol.hh" + +//#include "TCPProtocol.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + class TCPProtocol + : public virtual SocketProtocol + { + public: + bool nodelay() const; + void nodelay(bool value) const; + + unsigned siocinq() const; + unsigned siocoutq() const; + unsigned available() const; + bool eof() const; + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "TCPProtocol.cci" +//#include "TCPProtocol.ct" +//#include "TCPProtocol.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/TCPSocketHandle.cc b/Socket/TCPSocketHandle.cc new file mode 100644 index 0000000..0eb1446 --- /dev/null +++ b/Socket/TCPSocketHandle.cc @@ -0,0 +1,90 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "TCPSocketHandle.hh" +//#include "TCPSocketHandle.ih" + +// Custom includes +#include +#include +#include + +#include "Utils/Exception.hh" + +//#include "TCPSocketHandle.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ void satcom::lib::TCPv4SocketProtocol::init_client() + const +{ + int sock = ::socket(PF_INET,SOCK_STREAM,0); + if (sock < 0) + throw SystemException(errno); + body().fd(sock); +} + +prefix_ void +satcom::lib::TCPv4SocketProtocol::init_client(INet4Address const & address) + const +{ + init_client(); + connect(address); +} + +prefix_ void satcom::lib::TCPv4SocketProtocol::init_server() + const +{ + int sock = ::socket(PF_INET,SOCK_STREAM,0); + if (sock < 0) + throw SystemException(errno); + body().fd(sock); +} + +prefix_ void satcom::lib::TCPv4SocketProtocol::init_server(INet4Address const & address, + unsigned backlog) + const +{ + init_server(); + bind(address); + reuseaddr(true); + if (::listen(body().fd(),backlog) < 0) + throw SystemException(errno); +} + +prefix_ std::auto_ptr satcom::lib::TCPv4SocketProtocol::clone() + const +{ + return std::auto_ptr(new TCPv4SocketProtocol()); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "TCPSocketHandle.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/TCPSocketHandle.hh b/Socket/TCPSocketHandle.hh new file mode 100644 index 0000000..5d3b2c0 --- /dev/null +++ b/Socket/TCPSocketHandle.hh @@ -0,0 +1,107 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 possibly non-blocking connect and SO_ERROR in the +// protocol interface + +#ifndef HH_TCPSocketHandle_ +#define HH_TCPSocketHandle_ 1 + +// Custom includes +#include "INetProtocol.hh" +#include "TCPProtocol.hh" +#include "BSDSocketProtocol.hh" +#include "FramingPolicy.hh" +#include "CommunicationPolicy.hh" +#include "ReadWritePolicy.hh" +#include "BufferingPolicy.hh" +#include "ProtocolClientSocketHandle.hh" +#include "ProtocolServerSocketHandle.hh" + +//#include "TCPSocketHandle.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + typedef MakeSocketPolicy< + INet4AddressingPolicy, + StreamFramingPolicy, + ConnectedCommunicationPolicy, + ReadablePolicy, + WriteablePolicy, + SocketBufferingPolicy + >::policy TCPv4Socket_Policy; + + class TCPv4SocketProtocol + : public ConcreteSocketProtocol, + public IPv4Protocol, + public TCPProtocol, + public BSDSocketProtocol, + public AddressableBSDSocketProtocol + { + public: + /////////////////////////////////////////////////////////////////////////// + // internal interface + + void init_client() const; + void init_client(INet4Address const & address) const; + void init_server() const; + void init_server(INet4Address const & address, unsigned backlog=1) const; + + std::auto_ptr clone() const; + }; + + typedef ProtocolClientSocketHandle TCPv4ClientSocketHandle; + typedef ProtocolServerSocketHandle TCPv4ServerSocketHandle; + + typedef MakeSocketPolicy< + TCPv4Socket_Policy, + INet6AddressingPolicy + >::policy TCPv6Socket_Policy; + + class TCPv6SocketProtocol + : public ConcreteSocketProtocol, + public IPv6Protocol, + public TCPProtocol, + public BSDSocketProtocol, + public AddressableBSDSocketProtocol + { + // TODO: Implement + }; + + typedef ProtocolClientSocketHandle TCPv6ClientSocketHandle; + typedef ProtocolServerSocketHandle TCPv6ServerSocketHandle; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "TCPSocketHandle.cci" +//#include "TCPSocketHandle.ct" +//#include "TCPSocketHandle.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/TCPSocketHandle.test.cc b/Socket/TCPSocketHandle.test.cc new file mode 100644 index 0000000..2a8659b --- /dev/null +++ b/Socket/TCPSocketHandle.test.cc @@ -0,0 +1,239 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "TCPSocketHandle.test.hh" +//#include "TCPSocketHandle.test.ih" + +// Custom includes +#include +#include +#include +#include +#include +#include +#include "TCPSocketHandle.hh" +#include + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + + void error(char const * fn, char const * proc="") + { + std::cerr << "\n" << proc << fn << ": " << strerror(errno) << std::endl; + } + + void fail(char const * fn) + { + error(fn,"server: "); + _exit(1); + } + + int server_pid = 0; + + void start(void (*fn)()) + { + server_pid = ::fork(); + if (server_pid < 0) BOOST_FAIL("fork()"); + if (server_pid == 0) { + (*fn)(); + _exit(0); + } + } + + void wait() + { + int status; + if (waitpid(server_pid,&status,0)<0) + BOOST_FAIL("waitpid()"); + BOOST_CHECK_EQUAL( status , 0 ); + } + + void stop() + { + kill(server_pid,9); + wait(); + } + +} + +/////////////////////////////////////////////////////////////////////////// + +namespace { + + void server() + { + int serv = socket(PF_INET,SOCK_STREAM,0); + if (serv<0) fail("socket()"); + int v = 1; + if (setsockopt(serv,SOL_SOCKET,SO_REUSEADDR,&v,sizeof(v))<0) + fail("setsockopt()"); + struct sockaddr_in sin; + sin.sin_family = AF_INET; + sin.sin_port = htons(12345); + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if (bind(serv,(struct sockaddr *)&sin,sizeof(sin))<0) fail("bind()"); + if (listen(serv,1)<0) fail("listen()"); + int sock = accept(serv,0,0); + if (sock < 0) fail("accept()"); + + char buffer[1024]; + while (1) { + int n = read(sock,buffer,1024); + if (n == 4 && strncmp(buffer,"QUIT",4) == 0) + break; + write(sock,buffer,n); + } + + if (shutdown(sock, SHUT_RDWR) < 0) fail("shutdown()"); + if (close(sock) < 0) fail("close()"); + if (close(serv) < 0) fail("close()"); + } + +} + +BOOST_AUTO_UNIT_TEST(tcpv4ClientSocketHandle) +{ + { + satcom::lib::TCPv4ClientSocketHandle sock; + + BOOST_CHECK_THROW( sock.connect(satcom::lib::INet4Address("127.0.0.1:12345")), satcom::lib::SystemException ); + BOOST_CHECK_THROW( sock.protocol().connect("127.0.0.1:12345"), satcom::lib::SystemException ); + } + + { + start(server); + satcom::lib::TCPv4ClientSocketHandle sock; + BOOST_CHECK_NO_THROW( sock.bind("127.0.0.1:23456") ); + BOOST_CHECK_NO_THROW( sock.connect("127.0.0.1:12345") ); + BOOST_CHECK( sock.peer() == "127.0.0.1:12345" ); + BOOST_CHECK( sock.local() == "127.0.0.1:23456" ); + BOOST_CHECK( sock.blocking() ); + BOOST_CHECK_NO_THROW( sock.rcvbuf(2048) ); + BOOST_CHECK_EQUAL( sock.rcvbuf(), 2048u ); + BOOST_CHECK_NO_THROW( sock.sndbuf(2048) ); + BOOST_CHECK_EQUAL( sock.sndbuf(), 2048u ); + BOOST_CHECK_NO_THROW( sock.write("TEST-WRITE") ); + BOOST_CHECK_EQUAL( sock.read(), "TEST-WRITE" ); + // this fails with ENOFILE ... why ???? + // BOOST_CHECK_NO_THROW( sock.protocol().timestamp() ); + BOOST_CHECK( !sock.eof() ); + sock.write("QUIT"); + sleep(1); + stop(); + sleep(1); + BOOST_CHECK_EQUAL( sock.read(), "" ); + BOOST_CHECK( sock.eof() ); + BOOST_CHECK( !sock ); + } + + { + satcom::lib::TCPv4ClientSocketHandle sock; + + // Since this is a TCP socket, most of the calls will fail or + // are at least not sensible ... + // I'll have to move those to a UDPSocket test ... they should + // realy only be in the UDP Protocol implementation + BOOST_CHECK_NO_THROW( sock.protocol().mcTTL() ); + BOOST_CHECK_THROW( sock.protocol().mcTTL(1), satcom::lib::SystemException ); + BOOST_CHECK_NO_THROW( sock.protocol().mcLoop() ); + BOOST_CHECK_NO_THROW( sock.protocol().mcLoop(false) ); + BOOST_CHECK_NO_THROW( sock.protocol().mcAddMembership("224.0.0.1:0") ); + BOOST_CHECK_NO_THROW( sock.protocol().mcAddMembership("224.0.0.1:0","127.0.0.1:0") ); + BOOST_CHECK_NO_THROW( sock.protocol().mcDropMembership("224.0.0.1:0","127.0.0.1:0") ); + BOOST_CHECK_NO_THROW( sock.protocol().mcDropMembership("224.0.0.1:0") ); + BOOST_CHECK_THROW( sock.protocol().mcIface("lo"), satcom::lib::SystemException ); + + // The following setsockopts are hard to REALLY test ... + BOOST_CHECK_NO_THROW( sock.protocol().nodelay(true) ); + BOOST_CHECK( sock.protocol().nodelay() ); + BOOST_CHECK_EQUAL( sock.protocol().siocinq(), 0u ); + BOOST_CHECK_EQUAL( sock.protocol().siocoutq(), 0u ); + + BOOST_CHECK_NO_THROW( sock.protocol().reuseaddr(true) ); + BOOST_CHECK( sock.protocol().reuseaddr() ); + BOOST_CHECK_NO_THROW( sock.protocol().linger(true,0) ); + BOOST_CHECK( sock.protocol().linger() == std::make_pair(true, 0u) ); + } +} + +/////////////////////////////////////////////////////////////////////////// + +namespace { + + void client() + { + int sock = socket(PF_INET,SOCK_STREAM,0); + if (sock<0) fail("socket()"); + struct sockaddr_in sin; + sin.sin_family = AF_INET; + sin.sin_port = htons(12346); + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if (connect(sock,(struct sockaddr *)&sin,sizeof(sin)) < 0) + fail("connect()"); + + char buffer[1024]; + while (1) { + int n = read(sock,buffer,1024); + if (n == 4 && strncmp(buffer,"QUIT",4) == 0) + break; + write(sock,buffer,n); + } + + if (shutdown(sock, SHUT_RDWR) < 0) fail("shutdown()"); + if (close(sock) < 0) fail("close()"); + } + +} + +BOOST_AUTO_UNIT_TEST(tcpv4ServerSocketHandle) +{ + { + BOOST_CHECKPOINT("Opening server socket"); + satcom::lib::TCPv4ServerSocketHandle server ("127.0.0.1:12346"); + BOOST_CHECKPOINT("Starting client"); + start(client); + + BOOST_CHECKPOINT("Accepting connection"); + satcom::lib::TCPv4ClientSocketHandle client = server.accept(); + BOOST_CHECK_NO_THROW(client.write("QUIT")); + + BOOST_CHECKPOINT("Stopping client"); + sleep(1); + stop(); + } +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/main.test.cc b/Socket/main.test.cc new file mode 100644 index 0000000..fd4c97a --- /dev/null +++ b/Socket/main.test.cc @@ -0,0 +1,43 @@ +// $Id: main.test.cc 32 2006-03-23 16:24:56Z sbund $ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// End: diff --git a/Utils/Exception.cc b/Utils/Exception.cc new file mode 100644 index 0000000..a534910 --- /dev/null +++ b/Utils/Exception.cc @@ -0,0 +1,47 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "Exception.hh" +//#include "Exception.ih" + +// Custom includes +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ char const * satcom::lib::SystemException::what() + const throw() +{ + return std::strerror(this->err); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Utils/Exception.hh b/Utils/Exception.hh new file mode 100644 index 0000000..6c3e8b1 --- /dev/null +++ b/Utils/Exception.hh @@ -0,0 +1,54 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_Exception_ +#define HH_Exception_ 1 + +// Custom includes +#include + +//#include "Exception.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + struct SystemException : public std::exception + { + SystemException(int err_) : err(err_) {}; + virtual char const * what() const throw(); + int err; + }; + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "Exception.cci" +//#include "Exception.ct" +//#include "Exception.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Utils/SConscript b/Utils/SConscript new file mode 100644 index 0000000..81cb37c --- /dev/null +++ b/Utils/SConscript @@ -0,0 +1,7 @@ +Import('env') +import SatSCons + +########################################################################### + +SatSCons.StandardTargets(env) +SatSCons.Lib(env, 'Utils', SatSCons.GlobSources()) diff --git a/Utils/TypeInfo.cc b/Utils/TypeInfo.cc new file mode 100644 index 0000000..c6860f5 --- /dev/null +++ b/Utils/TypeInfo.cc @@ -0,0 +1,62 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "TypeInfo.hh" +//#include "TypeInfo.ih" + +// Custom includes +#include "malloc.h" +#define HAVE_DECL_BASENAME 1 +#define HAVE_DECL_ASPRINTF 1 +#define HAVE_DECL_VASPRINTF 1 +#include "impl/demangle.h" + +//#include "TypeInfo.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + + +// WARNING: This is completely g++ and libiberty dependent. The demangling +// interface isn't even explicitly exportet from libiberty. However, it is +// *EXTREMELY* helpful for debugging ... + +prefix_ std::string satcom::lib::prettyName(std::type_info const & type) +{ + char const * mangled = type.name(); + char * demangled = ::cplus_demangle(mangled,DMGL_TYPES|DMGL_AUTO); + std::string name (demangled ? demangled : mangled); + if (demangled) + ::free(demangled); + return name; +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "TypeInfo.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Utils/TypeInfo.hh b/Utils/TypeInfo.hh new file mode 100644 index 0000000..72168b6 --- /dev/null +++ b/Utils/TypeInfo.hh @@ -0,0 +1,51 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_TypeInfo_ +#define HH_TypeInfo_ 1 + +// Custom includes +#include +#include + +//#include "TypeInfo.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + std::string prettyName(std::type_info const & type); + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "TypeInfo.cci" +//#include "TypeInfo.ct" +//#include "TypeInfo.cti" +//#include "TypeInfo.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Utils/TypeInfo.test.cc b/Utils/TypeInfo.test.cc new file mode 100644 index 0000000..74218af --- /dev/null +++ b/Utils/TypeInfo.test.cc @@ -0,0 +1,67 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "TypeInfo.test.hh" +//#include "TypeInfo.test.ih" + +// Custom includes +#include "TypeInfo.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace test { + + struct Base { + virtual ~Base() {} + }; + + template + struct Foo : public Base + {}; + + enum Blub { A, B, C }; +} + +BOOST_AUTO_UNIT_TEST(prettyName) +{ + typedef test::Foo< test::Foo, 10> TestType; + TestType ob; + test::Base const & baseOb(ob); + + BOOST_CHECK_EQUAL( satcom::lib::prettyName(typeid(int)), "int"); + BOOST_CHECK_EQUAL( satcom::lib::prettyName(typeid(baseOb)), "test::Foo, 10>" ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Utils/impl/demangle.h b/Utils/impl/demangle.h new file mode 100644 index 0000000..b3b8c58 --- /dev/null +++ b/Utils/impl/demangle.h @@ -0,0 +1,533 @@ +/* Defs for interface to demanglers. + Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, + 2003, 2004 Free Software Foundation, Inc. + + 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, 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 !defined (DEMANGLE_H) +#define DEMANGLE_H + +#include "libiberty.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Options passed to cplus_demangle (in 2nd parameter). */ + +#define DMGL_NO_OPTS 0 /* For readability... */ +#define DMGL_PARAMS (1 << 0) /* Include function args */ +#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ +#define DMGL_JAVA (1 << 2) /* Demangle as Java rather than C++. */ +#define DMGL_VERBOSE (1 << 3) /* Include implementation details. */ +#define DMGL_TYPES (1 << 4) /* Also try to demangle type encodings. */ + +#define DMGL_AUTO (1 << 8) +#define DMGL_GNU (1 << 9) +#define DMGL_LUCID (1 << 10) +#define DMGL_ARM (1 << 11) +#define DMGL_HP (1 << 12) /* For the HP aCC compiler; + same as ARM except for + template arguments, etc. */ +#define DMGL_EDG (1 << 13) +#define DMGL_GNU_V3 (1 << 14) +#define DMGL_GNAT (1 << 15) + +/* If none of these are set, use 'current_demangling_style' as the default. */ +#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT) + +/* Enumeration of possible demangling styles. + + Lucid and ARM styles are still kept logically distinct, even though + they now both behave identically. The resulting style is actual the + union of both. I.E. either style recognizes both "__pt__" and "__rf__" + for operator "->", even though the first is lucid style and the second + is ARM style. (FIXME?) */ + +extern enum demangling_styles +{ + no_demangling = -1, + unknown_demangling = 0, + auto_demangling = DMGL_AUTO, + gnu_demangling = DMGL_GNU, + lucid_demangling = DMGL_LUCID, + arm_demangling = DMGL_ARM, + hp_demangling = DMGL_HP, + edg_demangling = DMGL_EDG, + gnu_v3_demangling = DMGL_GNU_V3, + java_demangling = DMGL_JAVA, + gnat_demangling = DMGL_GNAT +} current_demangling_style; + +/* Define string names for the various demangling styles. */ + +#define NO_DEMANGLING_STYLE_STRING "none" +#define AUTO_DEMANGLING_STYLE_STRING "auto" +#define GNU_DEMANGLING_STYLE_STRING "gnu" +#define LUCID_DEMANGLING_STYLE_STRING "lucid" +#define ARM_DEMANGLING_STYLE_STRING "arm" +#define HP_DEMANGLING_STYLE_STRING "hp" +#define EDG_DEMANGLING_STYLE_STRING "edg" +#define GNU_V3_DEMANGLING_STYLE_STRING "gnu-v3" +#define JAVA_DEMANGLING_STYLE_STRING "java" +#define GNAT_DEMANGLING_STYLE_STRING "gnat" + +/* Some macros to test what demangling style is active. */ + +#define CURRENT_DEMANGLING_STYLE current_demangling_style +#define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO) +#define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU) +#define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID) +#define ARM_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_ARM) +#define HP_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_HP) +#define EDG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_EDG) +#define GNU_V3_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_V3) +#define JAVA_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_JAVA) +#define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT) + +/* Provide information about the available demangle styles. This code is + pulled from gdb into libiberty because it is useful to binutils also. */ + +extern const struct demangler_engine +{ + const char *const demangling_style_name; + const enum demangling_styles demangling_style; + const char *const demangling_style_doc; +} libiberty_demanglers[]; + +extern char * +cplus_demangle PARAMS ((const char *mangled, int options)); + +extern int +cplus_demangle_opname PARAMS ((const char *opname, char *result, int options)); + +extern const char * +cplus_mangle_opname PARAMS ((const char *opname, int options)); + +/* Note: This sets global state. FIXME if you care about multi-threading. */ + +extern void +set_cplus_marker_for_demangling PARAMS ((int ch)); + +extern enum demangling_styles +cplus_demangle_set_style PARAMS ((enum demangling_styles style)); + +extern enum demangling_styles +cplus_demangle_name_to_style PARAMS ((const char *name)); + +/* V3 ABI demangling entry points, defined in cp-demangle.c. */ +extern char* +cplus_demangle_v3 PARAMS ((const char* mangled, int options)); + +extern char* +java_demangle_v3 PARAMS ((const char* mangled)); + + +enum gnu_v3_ctor_kinds { + gnu_v3_complete_object_ctor = 1, + gnu_v3_base_object_ctor, + gnu_v3_complete_object_allocating_ctor +}; + +/* Return non-zero iff NAME is the mangled form of a constructor name + in the G++ V3 ABI demangling style. Specifically, return an `enum + gnu_v3_ctor_kinds' value indicating what kind of constructor + it is. */ +extern enum gnu_v3_ctor_kinds + is_gnu_v3_mangled_ctor PARAMS ((const char *name)); + + +enum gnu_v3_dtor_kinds { + gnu_v3_deleting_dtor = 1, + gnu_v3_complete_object_dtor, + gnu_v3_base_object_dtor +}; + +/* Return non-zero iff NAME is the mangled form of a destructor name + in the G++ V3 ABI demangling style. Specifically, return an `enum + gnu_v3_dtor_kinds' value, indicating what kind of destructor + it is. */ +extern enum gnu_v3_dtor_kinds + is_gnu_v3_mangled_dtor PARAMS ((const char *name)); + +/* The V3 demangler works in two passes. The first pass builds a tree + representation of the mangled name, and the second pass turns the + tree representation into a demangled string. Here we define an + interface to permit a caller to build their own tree + representation, which they can pass to the demangler to get a + demangled string. This can be used to canonicalize user input into + something which the demangler might output. It could also be used + by other demanglers in the future. */ + +/* These are the component types which may be found in the tree. Many + component types have one or two subtrees, referred to as left and + right (a component type with only one subtree puts it in the left + subtree). */ + +enum demangle_component_type +{ + /* A name, with a length and a pointer to a string. */ + DEMANGLE_COMPONENT_NAME, + /* A qualified name. The left subtree is a class or namespace or + some such thing, and the right subtree is a name qualified by + that class. */ + DEMANGLE_COMPONENT_QUAL_NAME, + /* A local name. The left subtree describes a function, and the + right subtree is a name which is local to that function. */ + DEMANGLE_COMPONENT_LOCAL_NAME, + /* A typed name. The left subtree is a name, and the right subtree + describes that name as a function. */ + DEMANGLE_COMPONENT_TYPED_NAME, + /* A template. The left subtree is a template name, and the right + subtree is a template argument list. */ + DEMANGLE_COMPONENT_TEMPLATE, + /* A template parameter. This holds a number, which is the template + parameter index. */ + DEMANGLE_COMPONENT_TEMPLATE_PARAM, + /* A constructor. This holds a name and the kind of + constructor. */ + DEMANGLE_COMPONENT_CTOR, + /* A destructor. This holds a name and the kind of destructor. */ + DEMANGLE_COMPONENT_DTOR, + /* A vtable. This has one subtree, the type for which this is a + vtable. */ + DEMANGLE_COMPONENT_VTABLE, + /* A VTT structure. This has one subtree, the type for which this + is a VTT. */ + DEMANGLE_COMPONENT_VTT, + /* A construction vtable. The left subtree is the type for which + this is a vtable, and the right subtree is the derived type for + which this vtable is built. */ + DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, + /* A typeinfo structure. This has one subtree, the type for which + this is the tpeinfo structure. */ + DEMANGLE_COMPONENT_TYPEINFO, + /* A typeinfo name. This has one subtree, the type for which this + is the typeinfo name. */ + DEMANGLE_COMPONENT_TYPEINFO_NAME, + /* A typeinfo function. This has one subtree, the type for which + this is the tpyeinfo function. */ + DEMANGLE_COMPONENT_TYPEINFO_FN, + /* A thunk. This has one subtree, the name for which this is a + thunk. */ + DEMANGLE_COMPONENT_THUNK, + /* A virtual thunk. This has one subtree, the name for which this + is a virtual thunk. */ + DEMANGLE_COMPONENT_VIRTUAL_THUNK, + /* A covariant thunk. This has one subtree, the name for which this + is a covariant thunk. */ + DEMANGLE_COMPONENT_COVARIANT_THUNK, + /* A Java class. This has one subtree, the type. */ + DEMANGLE_COMPONENT_JAVA_CLASS, + /* A guard variable. This has one subtree, the name for which this + is a guard variable. */ + DEMANGLE_COMPONENT_GUARD, + /* A reference temporary. This has one subtree, the name for which + this is a temporary. */ + DEMANGLE_COMPONENT_REFTEMP, + /* A standard substitution. This holds the name of the + substitution. */ + DEMANGLE_COMPONENT_SUB_STD, + /* The restrict qualifier. The one subtree is the type which is + being qualified. */ + DEMANGLE_COMPONENT_RESTRICT, + /* The volatile qualifier. The one subtree is the type which is + being qualified. */ + DEMANGLE_COMPONENT_VOLATILE, + /* The const qualifier. The one subtree is the type which is being + qualified. */ + DEMANGLE_COMPONENT_CONST, + /* The restrict qualifier modifying a member function. The one + subtree is the type which is being qualified. */ + DEMANGLE_COMPONENT_RESTRICT_THIS, + /* The volatile qualifier modifying a member function. The one + subtree is the type which is being qualified. */ + DEMANGLE_COMPONENT_VOLATILE_THIS, + /* The const qualifier modifying a member function. The one subtree + is the type which is being qualified. */ + DEMANGLE_COMPONENT_CONST_THIS, + /* A vendor qualifier. The left subtree is the type which is being + qualified, and the right subtree is the name of the + qualifier. */ + DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL, + /* A pointer. The one subtree is the type which is being pointed + to. */ + DEMANGLE_COMPONENT_POINTER, + /* A reference. The one subtree is the type which is being + referenced. */ + DEMANGLE_COMPONENT_REFERENCE, + /* A complex type. The one subtree is the base type. */ + DEMANGLE_COMPONENT_COMPLEX, + /* An imaginary type. The one subtree is the base type. */ + DEMANGLE_COMPONENT_IMAGINARY, + /* A builtin type. This holds the builtin type information. */ + DEMANGLE_COMPONENT_BUILTIN_TYPE, + /* A vendor's builtin type. This holds the name of the type. */ + DEMANGLE_COMPONENT_VENDOR_TYPE, + /* A function type. The left subtree is the return type. The right + subtree is a list of ARGLIST nodes. Either or both may be + NULL. */ + DEMANGLE_COMPONENT_FUNCTION_TYPE, + /* An array type. The left subtree is the dimension, which may be + NULL, or a string (represented as DEMANGLE_COMPONENT_NAME), or an + expression. The right subtree is the element type. */ + DEMANGLE_COMPONENT_ARRAY_TYPE, + /* A pointer to member type. The left subtree is the class type, + and the right subtree is the member type. CV-qualifiers appear + on the latter. */ + DEMANGLE_COMPONENT_PTRMEM_TYPE, + /* An argument list. The left subtree is the current argument, and + the right subtree is either NULL or another ARGLIST node. */ + DEMANGLE_COMPONENT_ARGLIST, + /* A template argument list. The left subtree is the current + template argument, and the right subtree is either NULL or + another TEMPLATE_ARGLIST node. */ + DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, + /* An operator. This holds information about a standard + operator. */ + DEMANGLE_COMPONENT_OPERATOR, + /* An extended operator. This holds the number of arguments, and + the name of the extended operator. */ + DEMANGLE_COMPONENT_EXTENDED_OPERATOR, + /* A typecast, represented as a unary operator. The one subtree is + the type to which the argument should be cast. */ + DEMANGLE_COMPONENT_CAST, + /* A unary expression. The left subtree is the operator, and the + right subtree is the single argument. */ + DEMANGLE_COMPONENT_UNARY, + /* A binary expression. The left subtree is the operator, and the + right subtree is a BINARY_ARGS. */ + DEMANGLE_COMPONENT_BINARY, + /* Arguments to a binary expression. The left subtree is the first + argument, and the right subtree is the second argument. */ + DEMANGLE_COMPONENT_BINARY_ARGS, + /* A trinary expression. The left subtree is the operator, and the + right subtree is a TRINARY_ARG1. */ + DEMANGLE_COMPONENT_TRINARY, + /* Arguments to a trinary expression. The left subtree is the first + argument, and the right subtree is a TRINARY_ARG2. */ + DEMANGLE_COMPONENT_TRINARY_ARG1, + /* More arguments to a trinary expression. The left subtree is the + second argument, and the right subtree is the third argument. */ + DEMANGLE_COMPONENT_TRINARY_ARG2, + /* A literal. The left subtree is the type, and the right subtree + is the value, represented as a DEMANGLE_COMPONENT_NAME. */ + DEMANGLE_COMPONENT_LITERAL, + /* A negative literal. Like LITERAL, but the value is negated. + This is a minor hack: the NAME used for LITERAL points directly + to the mangled string, but since negative numbers are mangled + using 'n' instead of '-', we want a way to indicate a negative + number which involves neither modifying the mangled string nor + allocating a new copy of the literal in memory. */ + DEMANGLE_COMPONENT_LITERAL_NEG +}; + +/* Types which are only used internally. */ + +struct demangle_operator_info; +struct demangle_builtin_type_info; + +/* A node in the tree representation is an instance of a struct + demangle_component. Note that the field names of the struct are + not well protected against macros defined by the file including + this one. We can fix this if it ever becomes a problem. */ + +struct demangle_component +{ + /* The type of this component. */ + enum demangle_component_type type; + + union + { + /* For DEMANGLE_COMPONENT_NAME. */ + struct + { + /* A pointer to the name (which need not NULL terminated) and + its length. */ + const char *s; + int len; + } s_name; + + /* For DEMANGLE_COMPONENT_OPERATOR. */ + struct + { + /* Operator. */ + const struct demangle_operator_info *op; + } s_operator; + + /* For DEMANGLE_COMPONENT_EXTENDED_OPERATOR. */ + struct + { + /* Number of arguments. */ + int args; + /* Name. */ + struct demangle_component *name; + } s_extended_operator; + + /* For DEMANGLE_COMPONENT_CTOR. */ + struct + { + /* Kind of constructor. */ + enum gnu_v3_ctor_kinds kind; + /* Name. */ + struct demangle_component *name; + } s_ctor; + + /* For DEMANGLE_COMPONENT_DTOR. */ + struct + { + /* Kind of destructor. */ + enum gnu_v3_dtor_kinds kind; + /* Name. */ + struct demangle_component *name; + } s_dtor; + + /* For DEMANGLE_COMPONENT_BUILTIN_TYPE. */ + struct + { + /* Builtin type. */ + const struct demangle_builtin_type_info *type; + } s_builtin; + + /* For DEMANGLE_COMPONENT_SUB_STD. */ + struct + { + /* Standard substitution string. */ + const char* string; + /* Length of string. */ + int len; + } s_string; + + /* For DEMANGLE_COMPONENT_TEMPLATE_PARAM. */ + struct + { + /* Template parameter index. */ + long number; + } s_number; + + /* For other types. */ + struct + { + /* Left (or only) subtree. */ + struct demangle_component *left; + /* Right subtree. */ + struct demangle_component *right; + } s_binary; + + } u; +}; + +/* People building mangled trees are expected to allocate instances of + struct demangle_component themselves. They can then call one of + the following functions to fill them in. */ + +/* Fill in most component types with a left subtree and a right + subtree. Returns non-zero on success, zero on failure, such as an + unrecognized or inappropriate component type. */ + +extern int +cplus_demangle_fill_component PARAMS ((struct demangle_component *fill, + enum demangle_component_type, + struct demangle_component *left, + struct demangle_component *right)); + +/* Fill in a DEMANGLE_COMPONENT_NAME. Returns non-zero on success, + zero for bad arguments. */ + +extern int +cplus_demangle_fill_name PARAMS ((struct demangle_component *fill, + const char *, int)); + +/* Fill in a DEMANGLE_COMPONENT_BUILTIN_TYPE, using the name of the + builtin type (e.g., "int", etc.). Returns non-zero on success, + zero if the type is not recognized. */ + +extern int +cplus_demangle_fill_builtin_type PARAMS ((struct demangle_component *fill, + const char *type_name)); + +/* Fill in a DEMANGLE_COMPONENT_OPERATOR, using the name of the + operator and the number of arguments which it takes (the latter is + used to disambiguate operators which can be both binary and unary, + such as '-'). Returns non-zero on success, zero if the operator is + not recognized. */ + +extern int +cplus_demangle_fill_operator PARAMS ((struct demangle_component *fill, + const char *opname, int args)); + +/* Fill in a DEMANGLE_COMPONENT_EXTENDED_OPERATOR, providing the + number of arguments and the name. Returns non-zero on success, + zero for bad arguments. */ + +extern int +cplus_demangle_fill_extended_operator PARAMS ((struct demangle_component *fill, + int numargs, + struct demangle_component *nm)); + +/* Fill in a DEMANGLE_COMPONENT_CTOR. Returns non-zero on success, + zero for bad arguments. */ + +extern int +cplus_demangle_fill_ctor PARAMS ((struct demangle_component *fill, + enum gnu_v3_ctor_kinds kind, + struct demangle_component *name)); + +/* Fill in a DEMANGLE_COMPONENT_DTOR. Returns non-zero on success, + zero for bad arguments. */ + +extern int +cplus_demangle_fill_dtor PARAMS ((struct demangle_component *fill, + enum gnu_v3_dtor_kinds kind, + struct demangle_component *name)); + +/* This function translates a mangled name into a struct + demangle_component tree. The first argument is the mangled name. + The second argument is DMGL_* options. This returns a pointer to a + tree on success, or NULL on failure. On success, the third + argument is set to a block of memory allocated by malloc. This + block should be passed to free when the tree is no longer + needed. */ + +extern struct demangle_component * +cplus_demangle_v3_components PARAMS ((const char *mangled, + int options, + void **mem)); + +/* This function takes a struct demangle_component tree and returns + the corresponding demangled string. The first argument is DMGL_* + options. The second is the tree to demangle. The third is a guess + at the length of the demangled string, used to initially allocate + the return buffer. The fourth is a pointer to a size_t. On + success, this function returns a buffer allocated by malloc(), and + sets the size_t pointed to by the fourth argument to the size of + the allocated buffer (not the length of the returned string). On + failure, this function returns NULL, and sets the size_t pointed to + by the fourth argument to 0 for an invalid tree, or to 1 for a + memory allocation error. */ + +extern char * +cplus_demangle_print PARAMS ((int options, + const struct demangle_component *tree, + int estimated_length, + size_t *p_allocated_size)); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* DEMANGLE_H */ diff --git a/Utils/impl/membind.hh b/Utils/impl/membind.hh new file mode 100644 index 0000000..ef18500 --- /dev/null +++ b/Utils/impl/membind.hh @@ -0,0 +1,63 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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. +// +// NEVER INCLUDE DIRECTLY !! INCLUDE satcom/membind.hh + +#if !BOOST_PP_IS_ITERATING + +#include +#include +#include + +template +boost::function membind(R (T::* fn)(),scOBTYPE ob) +{ + return boost::bind(fn,ob); +} + +// for BOOST_PP_ITERATION() in 2..9 do +#define BOOST_PP_ITERATION_PARAMS_1 (4, (2, 9, "Utils/impl/membind.hh", 1)) +#include BOOST_PP_ITERATE() +#elif BOOST_PP_ITERATION_DEPTH()==1 && BOOST_PP_ITERATION_FLAGS()==1 +// {{ + +#define scARG(z,n,d) BOOST_PP_CAT(d,n) +#define scPARAMS(d) BOOST_PP_ENUM_SHIFTED(BOOST_PP_ITERATION(),scARG,d) + +template < typename R, typename T, scPARAMS(typename A) > +boost::function +membind(R (T::* fn)( scPARAMS(A) ), scOBTYPE ob) +{ + return boost::bind(fn, ob, scPARAMS(_) ); +} + +#undef scPARAMS +#undef scARG + +// } +#endif +// done + + +// Local Variables: +// mode: c++ +// End: diff --git a/Utils/intrusive_refcount.cci b/Utils/intrusive_refcount.cci new file mode 100644 index 0000000..a6a9d1a --- /dev/null +++ b/Utils/intrusive_refcount.cci @@ -0,0 +1,79 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "intrusive_refcount.ih" + +// Custom includes +#include + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +prefix_ satcom::lib::intrusive_refcount::refcount_t satcom::lib::intrusive_refcount::refcount() +{ + return refcount_; +} + +prefix_ bool satcom::lib::intrusive_refcount::is_shared() +{ + return refcount()>1; +} + +prefix_ satcom::lib::intrusive_refcount::intrusive_refcount() + : refcount_(0) +{} + +prefix_ satcom::lib::intrusive_refcount::~intrusive_refcount() +{} + +prefix_ void satcom::lib::intrusive_refcount::add_ref() +{ + ++refcount_; +} + +prefix_ bool satcom::lib::intrusive_refcount::release() +{ + BOOST_ASSERT(refcount_>0); + return --refcount_ == 0; +} + +prefix_ void satcom::lib::intrusive_ptr_add_ref(intrusive_refcount* p) +{ + p->add_ref(); +} + +prefix_ void satcom::lib::intrusive_ptr_release(intrusive_refcount* p) +{ + if (p->release()) + delete p; +} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Utils/intrusive_refcount.hh b/Utils/intrusive_refcount.hh new file mode 100644 index 0000000..a63dbe6 --- /dev/null +++ b/Utils/intrusive_refcount.hh @@ -0,0 +1,76 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_intrusive_refcount_ +#define HH_intrusive_refcount_ 1 + +// Custom includes +#include + +//#include "intrusive_refcount.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + /** \brief + */ + class intrusive_refcount + : public boost::noncopyable + { + public: + typedef unsigned refcount_t; + + virtual ~intrusive_refcount(); + + refcount_t refcount(); + bool is_shared(); + + protected: + intrusive_refcount(); + + private: + void add_ref(); + bool release(); + + refcount_t refcount_; + + friend void satcom::lib::intrusive_ptr_add_ref(intrusive_refcount* p); + friend void satcom::lib::intrusive_ptr_release(intrusive_refcount* p); + }; + + void intrusive_ptr_add_ref(intrusive_refcount* p); + void intrusive_ptr_release(intrusive_refcount* p); + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +#include "intrusive_refcount.cci" +//#include "intrusive_refcount.ct" +//#include "intrusive_refcount.cti" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Utils/intrusive_refcount.test.cc b/Utils/intrusive_refcount.test.cc new file mode 100644 index 0000000..f09e4bc --- /dev/null +++ b/Utils/intrusive_refcount.test.cc @@ -0,0 +1,84 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "intrusive_refcount.test.hh" +//#include "intrusive_refcount.test.ih" + +// Custom includes +#include "intrusive_refcount.hh" +#include + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + struct Tester + : public satcom::lib::intrusive_refcount + { + typedef boost::intrusive_ptr ptr; + + Tester() { ++counter; } + ~Tester() { --counter; } + + static unsigned counter; + }; + + unsigned Tester::counter = 0; +} + +BOOST_AUTO_UNIT_TEST(intrusive_refcount) +{ + BOOST_CHECK_EQUAL(Tester::counter,0u); + + Tester::ptr p (new Tester); + BOOST_CHECK_EQUAL(Tester::counter,1u); + BOOST_CHECK_EQUAL(p->refcount(),1u); + BOOST_CHECK_EQUAL(p->is_shared(),false); + + { + Tester::ptr pp (p); + BOOST_CHECK_EQUAL(Tester::counter,1u); + BOOST_CHECK_EQUAL(p->refcount(),2u); + BOOST_CHECK_EQUAL(p->is_shared(),true); + } + + BOOST_CHECK_EQUAL(Tester::counter,1u); + BOOST_CHECK_EQUAL(p->refcount(),1u); + BOOST_CHECK_EQUAL(p->is_shared(),false); + + p = 0; + BOOST_CHECK_EQUAL(Tester::counter,0u); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Utils/main.test.cc b/Utils/main.test.cc new file mode 100644 index 0000000..fd4c97a --- /dev/null +++ b/Utils/main.test.cc @@ -0,0 +1,43 @@ +// $Id: main.test.cc 32 2006-03-23 16:24:56Z sbund $ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// End: diff --git a/Utils/membind.hh b/Utils/membind.hh new file mode 100644 index 0000000..e624e76 --- /dev/null +++ b/Utils/membind.hh @@ -0,0 +1,54 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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_membind_ +#define HH_membind_ 1 + +// Custom includes +#include +#include + +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + +#define scOBTYPE T * +#include "Utils/impl/membind.hh" +#undef scOBTYPE + +#define scOBTYPE T & +#include "Utils/impl/membind.hh" +#undef scOBTYPE + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "membind.cci" +//#include "membind.ct" +//#include "membind.cti" +#endif + + +// Local Variables: +// mode: c++ +// End: diff --git a/Utils/membind.test.cc b/Utils/membind.test.cc new file mode 100644 index 0000000..7c05954 --- /dev/null +++ b/Utils/membind.test.cc @@ -0,0 +1,72 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// 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 "membind.test.hh" +//#include "membind.test.ih" + +// Custom includes +#include +#include +#include "Utils/membind.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + + struct Test { + char const * meth1() { + return "meth1()"; + } + + std::string meth2(int foo, int bar) { + std::stringstream s; + s << "meth2(" << foo << "," << bar << ")"; + return s.str(); + } + }; + +} + +BOOST_AUTO_UNIT_TEST(membind) +{ + Test instance; + boost::function f1 (satcom::lib::membind(&Test::meth1,instance)); + boost::function f2 (satcom::lib::membind(&Test::meth2,instance)); + + BOOST_CHECK_EQUAL( f1(), "meth1()" ); + BOOST_CHECK_EQUAL( f2(1,2), "meth2(1,2)" ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/satscons/BoostUnitTests.py b/satscons/BoostUnitTests.py new file mode 100644 index 0000000..6976e12 --- /dev/null +++ b/satscons/BoostUnitTests.py @@ -0,0 +1,37 @@ +import SCons.Script.SConscript +import SCons.Defaults +import os.path +import os + +def BoostUnitTests(env, target, source, test_source=None, LIBS = [], DEPENDS = [], **kw): + path, name = os.path.split(target) + if test_source: + if type(test_source) is not type([]): + test_source = [ test_source ] + else: + test_source = [] + testEnv = env.Copy(**kw) + testEnv.Prepend(LIBS = '$BOOSTTESTLIB') + testEnv.Prepend(LIBS = LIBS) + sources = [] + if source: + sources = sources + env.Object(source) + sources = sources + test_source + binName = os.path.join(path,'.' + os.path.splitext(name)[0]+'.bin') + testRunner = testEnv.Program(binName, sources) + stamp = os.path.join(path,'.' + os.path.splitext(name)[0]+'.stamp') + if DEPENDS: + env.Depends(testRunner, DEPENDS) + return env.Command([ target, stamp ], testRunner, + [ '( $SOURCE $BOOSTTESTARGS 2>&1 && touch ${TARGETS[1]} ) | tee ${TARGETS[0]}' ]) + +def dispatcher(*arg,**kw): + return BoostUnitTests(*arg,**kw) + +def generate(env): + env['BOOSTTESTLIB'] = 'boost_unit_test_framework' + env['BOOSTTESTARGS'] = [ '--build_info=yes', '--log_level=test_suite' ] + env.__class__.BoostUnitTests = dispatcher + +def exists(env): + return 1 diff --git a/satscons/Doxyfile.template b/satscons/Doxyfile.template new file mode 100644 index 0000000..3a08b63 --- /dev/null +++ b/satscons/Doxyfile.template @@ -0,0 +1,273 @@ +# Doxyfile 1.4.2 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = "" +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 = +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/satscons/Doxygen.py b/satscons/Doxygen.py new file mode 100644 index 0000000..975bbe0 --- /dev/null +++ b/satscons/Doxygen.py @@ -0,0 +1,31 @@ +import SCons.Script.SConscript +import SCons.Builder +import SCons.Defaults +import os.path + +def replace_ext(n,ext): + base,ext = os.path.splitext(n) + return base+ext + +def Doxygen(env, target, source, image=[]): + path, name = os.path.split(str(target)) + stamp = os.path.join(path, '.'+name+'.stamp') + dir = env.Dir(target) + env.Depends(dir, + [ env.Command(os.path.splitext(img)[0]+".png", img, + [ 'TERM=dumb make -f imgconvert.mak $TARGET' ]) + for img in image ] + + [ env.Command(stamp, source, + [ 'cd $TARGET.dir && $DOXYGENCOM', + 'cd $TARGET.dir/doc/html && (sed -ne \'1,//p\' \' \' -k4 && sed -ne \'/<\\/table>/,$$p\' annotated.html.new && mv annotated.html.new annotated.html', + 'touch $TARGET' ], + source_scanner = SCons.Defaults.ObjSourceScan) ]) + env.Clean(stamp, dir) + return dir + +def generate(env): + env['DOXYGENCOM'] = 'doxygen' + env.__class__.Doxygen = Doxygen + +def exists(env): + return 1 diff --git a/satscons/SConscript.template b/satscons/SConscript.template new file mode 100644 index 0000000..771c9be --- /dev/null +++ b/satscons/SConscript.template @@ -0,0 +1,10 @@ +Import('env') +import SatSCons + +########################################################################### + +SatSCons.StandardTargets(env) + +# SatSCons.Lib(env, + library = 'Test', + sources = SatSCons.GlobSources()) diff --git a/satscons/SConstruct.template b/satscons/SConstruct.template new file mode 100644 index 0000000..51e4564 --- /dev/null +++ b/satscons/SConstruct.template @@ -0,0 +1,21 @@ +import sys, glob +sys.path.append('satscons') +import SatSCons + +########################################################################### + +SatSCons.UseBoost(); +SatSCons.UseSTLPort(); +SatSCons.UseDoxygen(); +env = SatSCons.MakeEnvironment(); + +env.Append( + CPPPATH = [ '#' ] +) + +Export('env') + +SConscript(glob.glob("*/SConscript")) + +SatSCons.StandardTargets(env) +SatSCons.GlobalTargets(env) diff --git a/satscons/SatSCons.py b/satscons/SatSCons.py new file mode 100644 index 0000000..12eb6cf --- /dev/null +++ b/satscons/SatSCons.py @@ -0,0 +1,172 @@ +import os.path, SCons.Options, SCons.Environment, SCons.Script.SConscript, glob + +opts = None +finalizers = [] + +def InitOpts(): + global opts + if opts is not None: return + opts = SCons.Options.Options('SConfig') + opts.Add('CXX', 'C++ compiler to use', 'g++') + opts.Add(SCons.Options.BoolOption('final','Enable optimization',0)) + +def Finalizer(f): + global finalizers + finalizers.append(f) + +def UseBoost(): + global opts + InitOpts() + opts.Add('BOOST_INCLUDES', 'Boost include directory', '') + opts.Add('BOOST_VARIANT', 'The boost variant to use', '') + opts.Add('BOOST_TOOLSET', 'The boost toolset to use', '') + opts.Add('BOOST_LIBDIR', 'The directory of the boost libraries', '') + Finalizer(FinalizeBoost) + +def FinalizeBoost(env): + env.Tool('BoostUnitTests', [os.path.split(__file__)[0]]) + + if env['BOOST_TOOLSET']: + runtime = "" + if not env['final'] : runtime += "gd" + if env['STLPORT_LIB'] : runtime += "p" + if runtime: runtime = "-" + runtime + env['BOOST_VARIANT'] = "-" + env['BOOST_TOOLSET'] + runtime + + env['BOOSTTESTLIB'] = 'libboost_unit_test_framework' + env['BOOST_VARIANT'] + + env.Append(LIBPATH = [ '$BOOST_LIBDIR' ], + CPPPATH = [ '$BOOST_INCLUDES' ]) + +def UseSTLPort(): + global opts + InitOpts() + opts.Add('STLPORT_INCLUDES', 'STLport include directory', '') + opts.Add('STLPORT_LIB', 'Name of the stlport library or empty to not use stlport', '') + opts.Add('STLPORT_LIBDIR', 'The directory of the stlport libraries','') + Finalizer(FinalizeSTLPort) + +def FinalizeSTLPort(env): + env['STLPORT_DEBUGLIB'] = '' + if env['STLPORT_LIB']: + env['STLPORT_DEBUGLIB'] = env['STLPORT_LIB'] + '_stldebug' + env.Append(LIBPATH = [ '$STLPORT_LIBDIR' ], + CPPPATH = [ '$STLPORT_INCLUDES' ]) + if env['final']: + env.Append(LIBS = [ '$STLPORT_LIB' ]) + else: + env.Append(LIBS = [ '$STLPORT_DEBUGLIB' ], + CPPDEFINES = [ '_STLP_DEBUG' ]) + +def UseDoxygen(): + Finalizer(FinalizeDoxygen) + +def FinalizeDoxygen(env): + env.Tool('Doxygen', [os.path.split(__file__)[0]]) + +def MakeEnvironment(): + global opts, finalizers + InitOpts() + env = SCons.Environment.Environment(options=opts) + if SCons.Script.SConscript.Arguments.get('final'): + env['final'] = 1 + env.Help(opts.GenerateHelpText(env)) + #conf = env.Configure() + #env = conf.env + if os.environ.has_key('SSH_AUTH_SOCK'): + env.Append( ENV = { 'SSH_AUTH_SOCK': os.environ['SSH_AUTH_SOCK'] } ) + + for finalizer in finalizers: + finalizer(env) + + env.Append(CXXFLAGS = [ '-Wall', '-Woverloaded-virtual', '-Wno-long-long', + '-pedantic', '-ansi' ], + LOCALLIBDIR = [ '#' ], + LIBPATH = [ '$LOCALLIBDIR' ]) + + if env['final']: + env.Append(CXXFLAGS = [ '-O3' ], + CPPDEFINES = [ 'NDEBUG' ]) + else: + env.Append(CXXFLAGS = [ '-O0', '-g', '-fno-inline' ], + LINKFLAGS = [ '-g' ]) + + #return conf.Finish() + return env + +def GlobSources(): + testSources = glob.glob("*.test.cc") + sources = [ x for x in glob.glob("*.cc") if x not in testSources ] + return (sources, testSources) + +def StandardTargets(env): + all = env.Alias('all') + env.Clean(all, [ '.sconsign', '.sconf_temp', 'config.log', 'ChangeLog.bak', '.clean' + ] + glob.glob("*~")) + env.Depends(all, '.') + +def GlobalTargets(env): + command = "find -name .svn -prune -o \( -name '*.hh' -o -name '*.ih' -o -name '*.cc' -o -name '*.cci' -o -name '*.ct' -o -name '*.cti' -o -name '*.mpp' \) -print " \ + "| xargs -r awk -F '//' '/%s/{print ARGV[ARGIND] \":\" FNR \":\" $2}' > $TARGET" + env.AlwaysBuild(env.Command('TODOS',None,[ command % 'TODO' ])) + env.AlwaysBuild(env.Command('FIXMES',None,[ command % ' FIXME' ])) + env.AlwaysBuild(env.Command('BUGS',None,[ command % 'BUG' ] )) + env.Alias('status',[ 'TODOS', 'FIXMES', 'BUGS' ]) + +def LibPath(lib): return '$LOCALLIBDIR/lib%s.a' % lib + +def Objects(env, sources, testSources = None, LIBS = []): + if type(sources) == type(()): + testSources = sources[1] + sources = sources[0] + + objects = None + if sources: + objects = env.Object(sources) + + if testSources: + test = env.BoostUnitTests( + target = 'test.log', + source = sources, + test_source = testSources, + LIBS = LIBS, + DEPENDS = [ env.File(LibPath(x)) for x in LIBS ]) + env.Alias('all_tests', test) + # Hmm ... here I'd like to use an Alias instead of a file + # however the alias does not seem to live in the subdirectory + # which breaks 'scons -u test' + env.Alias(env.File('test'), test) + + return objects + +def Doxygen(env, sources, testSources = None): + if type(sources) == type(()): + testSources = sources[1] + sources = sources[0] + + doc = env.Doxygen( + target = 'doc', + source = sources ) + + env.Alias('all_docs', doc) + return doc + +def Lib(env, library, sources, testSources = None, LIBS = []): + objects = Objects(env,sources,testSources,LIBS=LIBS) + lib = None + if objects: + lib = env.Library(env.File(LibPath(library)),objects) + env.Default(lib) + env.Append(ALLLIBS = library) + return lib + +def Binary(env, binary, sources, testSources = None, LIBS = []): + objects = Objects(env,sources,testSources,LIBS=LIBS) + program = None + if objects: + progEnv = env.Copy() + progEnv.Prepend(LIBS = LIBS) + program = progEnv.Program(target=binary,source=objects) + env.Default(program) + env.Depends(program, [ env.File(LibPath(x)) for x in LIBS ]) + return program diff --git a/satscons/__init__.py b/satscons/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/satscons/nodeglob.py b/satscons/nodeglob.py new file mode 100644 index 0000000..feb19ba --- /dev/null +++ b/satscons/nodeglob.py @@ -0,0 +1,28 @@ +import fnmatch +import os + +def glob(match): + """Similar to glob.glob, except globs SCons nodes, and thus sees + generated files and files from build directories. Basically, it sees + anything SCons knows about. A key subtlety is that since this function + operates on generated nodes as well as source nodes on the filesystem, + it needs to be called after builders that generate files you want to + include.""" + def fn_filter(node): + fn = str(node) + return fnmatch.fnmatch(os.path.basename(fn), match) + + here = Dir('.') + + children = here.all_children() + nodes = map(File, filter(fn_filter, children)) + node_srcs = [n.srcnode() for n in nodes] + + src = here.srcnode() + if src is not here: + src_children = map(File, filter(fn_filter, src.all_children())) + for s in src_children: + if s not in node_srcs: + nodes.append(File(os.path.basename(str(s)))) + + return nodes diff --git a/satscons/pdflatex.py b/satscons/pdflatex.py new file mode 100644 index 0000000..bbb129b --- /dev/null +++ b/satscons/pdflatex.py @@ -0,0 +1,99 @@ +import SCons.Defaults + +import md5, os.path +import SCons.Action, SCons.Builder, SCons.Util, SCons.Errors, SCons.Environment + +PDFLaTeXAction = SCons.Action.CommandAction("$PDFLATEXCOM") + +# copied from Action.py ... changed to tage explicit path-names as +# target/source instead of node objects +def my_executeCommand(cmd_list, target, source, env): + import SCons.Util + escape = env.get('ESCAPE', lambda x: x) + if env.has_key('SHELL'): shell = env['SHELL'] + else: raise SCons.Errors.UserError('Missing SHELL construction variable.') + if env.has_key('PIPE_BUILD'): + pipe_build = 1 + if env.has_key('PSPAWN'): pspawn = env['PSPAWN'] + else: raise SCons.Errors.UserError('Missing PSPAWN construction variable.') + if env.has_key('PSTDOUT'): pstdout = env['PSTDOUT'] + else: raise SCons.Errors.UserError('Missing PSTDOUT construction variable.') + if env.has_key('PSTDERR'): pstderr = env['PSTDERR'] + else: raise SCons.Errors.UserError('Missing PSTDOUT construction variable.') + else: + pipe_build = 0 + if env.has_key('SPAWN'): spawn = env['SPAWN'] + else: raise SCons.Errors.UserError('Missing SPAWN construction variable.') + # Here, replaced the source and target argumnets with a dict argument + cmd_list = env.subst_list(cmd_list, 0, dict = { 'TARGET': target, 'TARGETS': [ target ], + 'SOURCE': source, 'SOURCES': [ source ] }) + for cmd_line in cmd_list: + if len(cmd_line): + try: ENV = env['ENV'] + except KeyError: + global default_ENV + if not default_ENV: + import SCons.Environment + default_ENV = SCons.Environment.Environment()['ENV'] + ENV = default_ENV + for key, value in ENV.items(): + if SCons.Util.is_List(value): + value = SCons.Util.flatten(value) + ENV[key] = string.join(map(str, value), os.pathsep) + elif not SCons.Util.is_String(value): + ENV[key] = str(value) + cmd_line = SCons.Util.escape_list(cmd_line, escape) + if pipe_build: ret = pspawn( shell, escape, cmd_line[0], cmd_line, + ENV, pstdout, pstderr ) + else: ret = spawn(shell, escape, cmd_line[0], cmd_line, ENV) + if ret: return ret + return 0 + +def TeXchecksum(files): + m = md5.new() + for f in files: + try: + m.update(file(f,"rb").read()) + except IOError: pass + return m.digest() + +def TeXPdfAction(target, source, env): + src = os.path.abspath(str(source[0])) + path, pdf = os.path.split(str(target[0])) + base, ext = os.path.splitext(pdf) + cwd = os.getcwd() + if path: os.chdir(path) + checkfiles = [ base + ext for ext in env["TEXCHECKEXT"] ] + checksum = TeXchecksum(checkfiles) + rv = 0 + for i in range(env["TEXMAXRECURSE"]+1): + if i==env["TEXMAXRECURSE"]: + print "\nWARNING: TeX recursion depth exceeded. They generated file may not be final.\n" + break + rv = my_executeCommand("$PDFLATEXCOM", pdf, src, env) + if rv: break + new_checksum = TeXchecksum(checkfiles) + if new_checksum == checksum: break + checksum = new_checksum + os.chdir(cwd) + return rv + +class TeXPdfBuilder(SCons.Builder.BuilderBase) : + def __call__(self, env, target = None, source = SCons.Builder._null, **kw): + tlist = SCons.Builder.BuilderBase.__call__(self, env, target, source, **kw) + exts = env["TEXCHECKEXT"] + env["TEXCLEANEXT"] + for t in tlist: + base, ext = os.path.splitext(str(t)) + for ext in exts: + env.Clean(t,base+ext) + return tlist + + +def generate(env): + env['TEXCHECKEXT'] = [ '.aux', '.toc' ] + env['TEXCLEANEXT'] = [ '.log', '.dvi' ] + env['TEXMAXRECURSE'] = 5 + env['BUILDERS']['PDF'] = TeXPdfBuilder(action = TeXPdfAction, suffix='.pdf') + +def exists(env): + return 1 diff --git a/satscons/satconf.py b/satscons/satconf.py new file mode 100644 index 0000000..bf67150 --- /dev/null +++ b/satscons/satconf.py @@ -0,0 +1,2 @@ +import SCons.Options, SCons.SConf, SCons.Environment +