Search:

SENF Extensible Network Framework

  • Home
  • Download
  • Wiki
  • BerliOS
  • ChangeLog
  • Browse SVN
  • Bug Tracker
  • Overview
  • Examples
  • HowTos
  • Glossary
  • PPI
  • Packets
  • Scheduler
  • Socket
  • Utils
  • Console
  • Daemon
  • Logger
  • Termlib
  • Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

PacketImpl.cc

Go to the documentation of this file.
00001 // $Id: PacketImpl.cc 1742 2010-11-04 14:51:56Z g0dil $
00002 //
00003 // Copyright (C) 2007
00004 // Fraunhofer (FOKUS)
00005 // Competence Center NETwork research (NET), St. Augustin, GERMANY
00006 //     Stefan Bund <g0dil@berlios.de>
00007 //
00008 // This program is free software; you can redistribute it and/or modify
00009 // it under the terms of the GNU General Public License as published by
00010 // the Free Software Foundation; either version 2 of the License, or
00011 // (at your option) any later version.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the
00020 // Free Software Foundation, Inc.,
00021 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00026 #include "PacketImpl.ih"
00027 
00028 // Custom includes
00029 #include <iterator>
00030 #include <map>
00031 #include <string>
00032 #include <boost/format.hpp>
00033 #include <senf/Utils/String.hh>
00034 #include "Packets.hh"
00035 
00036 //#include "PacketImpl.mpp"
00037 #define prefix_
00038 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00039 
00040 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00041 // senf::detail::PacketImpl
00042 
00043 prefix_ senf::detail::PacketImpl::~PacketImpl()
00044 {
00045     // We increment refcount_ to ensure, release() won't call delete again
00046     ++refcount_;
00047     eraseInterpreters(interpreters_.begin(), interpreters_.end());
00048 }
00049 
00050 prefix_ void senf::detail::PacketImpl::release()
00051 {
00052     SENF_ASSERT(refcount_ >= 1, "Internal failure: Releasing dead PacketImpl ??");
00053     // uah ... we need to be extremely careful here. If refcount_ is 1, we want to commit suicide,
00054     // however the destructor will remove all PacketInterpreters from the list and will thereby
00055     // decrement refcount -> only decrement refcount_ when *not* calling delete (otherwise
00056     // the assert above will fail)
00057     if (refcount_ == 1)
00058         delete this;
00059     else
00060         -- refcount_;
00061 }
00062 
00063 // interpreter chain
00064 
00065 prefix_ void senf::detail::PacketImpl::appendInterpreter(PacketInterpreterBase * p)
00066 {
00067     interpreters_.push_back(*p);
00068     p->assignImpl(this);
00069 }
00070 
00071 prefix_ void senf::detail::PacketImpl::prependInterpreter(PacketInterpreterBase * p)
00072 {
00073     interpreters_.push_front(*p);
00074     p->assignImpl(this);
00075 }
00076 
00077 prefix_ void senf::detail::PacketImpl::prependInterpreter(PacketInterpreterBase * p,
00078                                                           PacketInterpreterBase * before)
00079 {
00080     interpreter_list::iterator i (interpreter_list::current(*before));
00081     interpreters_.insert(i, *p);
00082     p->assignImpl(this);
00083 }
00084 
00085 // Data container
00086 
00087 prefix_ void senf::detail::PacketImpl::clear(PacketData * self)
00088 {
00089     PacketInterpreterBase * n (next(static_cast<PacketInterpreterBase*>(self)));
00090     if (n)
00091         truncateInterpreters(n);
00092     iterator first (boost::next(begin(),self->begin_));
00093     data_.erase(first, boost::next(begin(),self->end_));
00094     updateIterators(self,self->begin_,-self->size());
00095 }
00096 
00097 // private members
00098 
00099 prefix_ void senf::detail::PacketImpl::eraseInterpreters(interpreter_list::iterator b,
00100                                                          interpreter_list::iterator e)
00101 {
00102     while (b!=e) {
00103         interpreter_list::iterator i (b++);
00104         PacketInterpreterBase * p (&(*i));
00105         interpreters_.erase(i);
00106         p->releaseImpl(); // might call PacketImpl::release and might delete p
00107     }
00108 }
00109 
00110 prefix_ void senf::detail::PacketImpl::updateIterators(PacketData * self, difference_type pos,
00111                                                        difference_type n)
00112 {
00113     // I hate to change the PacketData representation from here, I would have preferred to let
00114     // PacketData have authority over this but trying that just get's to convoluted so I choose the
00115     // simple solution and made PacketImpl a friend of PacketData.
00116 
00117     interpreter_list::iterator i (interpreters_.begin());
00118 
00119     // There are three types of packets
00120     // a) Those which come before 'self' in the interpreter chain
00121     // b) 'self'
00122     // c) Those that come afterwards
00123     // For a), the change must be inside the packet since 'self' must be within those packets
00124     // For b), the change must also be within since that's the packet we are changing
00125     // For c), the change must be outside the packet (we don't allow an upper packet to mess with
00126     // the the data owned by a packet further down the chain). It can be before or after the
00127     // packet.
00128 
00129     // a)
00130     for (; &(*i) != static_cast<PacketInterpreterBase*>(self); ++i) i->end_ += n;
00131 
00132     // b)
00133     i->end_ += n;
00134 
00135     // c)
00136     interpreter_list::iterator const i_end (interpreters_.end());
00137     if (++i != i_end)
00138         if (pos <= difference_type(i->begin_))
00139             // pos is before the packet, it must then be before all further packets ...
00140             for (; i != i_end; ++i) {
00141                 i->begin_ += n;
00142                 i->end_ += n;
00143             }
00144         // else pos is after the packet and we don't need to change anything ...
00145 }
00146 
00147 // Annotations
00148 
00149 prefix_ void senf::detail::PacketImpl::dumpAnnotations(std::ostream & os)
00150 {
00151     for (AnnotationRegistry::iterator i (AnnotationRegistry::instance().begin());
00152          i != AnnotationRegistry::instance().end(); ++i) {
00153         void * antn (annotation(*i));
00154         if (antn)
00155             AnnotationRegistry::instance().dump(*i, os, antn);
00156     }
00157 }
00158 
00159 prefix_ void senf::detail::PacketImpl::clearAnnotations()
00160 {
00161     ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
00162     complexAnnotations_.clear();
00163 }
00164 
00165 prefix_ void senf::detail::PacketImpl::assignAnnotations(PacketImpl const & other)
00166 {
00167     std::copy(&other.simpleAnnotations_[0], &other.simpleAnnotations_[0] +
00168             sizeof(simpleAnnotations_)/sizeof(simpleAnnotations_[0]), simpleAnnotations_);
00169     complexAnnotations_.assign(
00170             other.complexAnnotations_.begin(), other.complexAnnotations_.end());
00171 }
00172 
00173 prefix_ void * senf::detail::PacketImpl::complexAnnotation(AnnotationRegistry::key_type key)
00174 {
00175     SENF_ASSERT( key < 0, "complexAnnotation called with invalid key");
00176     return (ComplexAnnotations::size_type(-key-1) >= complexAnnotations_.size()
00177             || complexAnnotations_.is_null(-key-1))
00178         ? 0 : complexAnnotations_[-key-1].get();
00179 }
00180 
00181 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00182 // senf::detail::AnnotationRegistry
00183 
00184 prefix_ void senf::detail::AnnotationRegistry::dump(key_type key, std::ostream & os,
00185                                                     void * annotation)
00186     const
00187 {
00188     Registry::const_iterator i (registry_.find(key));
00189     if (i != registry_.end()) {
00190         os << fieldName(i->second->v_name());
00191         i->second->v_dump(os, annotation);
00192         os << "\n";
00193     }
00194 }
00195 
00196 prefix_ void senf::detail::AnnotationRegistry::dumpRegistrations(std::ostream & os)
00197 {
00198     boost::format fmt ("%-56.56s  %-4.4s  %-7.7s  %5d\n");
00199     os << "SENF_PACKET_ANNOTATION_SLOTS = " << SENF_PACKET_ANNOTATION_SLOTS << "\n"
00200        << "SENF_PACKET_ANNOTATION_SLOTSIZE = " << SENF_PACKET_ANNOTATION_SLOTSIZE << "\n";
00201     os << fmt % "TYPE" % "FAST" % "COMPLEX" % "SIZE";
00202 
00203     for (Index::const_iterator i (index_.begin()), i_end (index_.end()); i != i_end; ++i) {
00204         key_type key (i->second);
00205         std::string nm (i->first);
00206         if (nm.size() > 56) nm.erase(nm.begin(), nm.begin()+nm.size()-32);
00207         os << fmt
00208             % nm
00209             % (key >= 0 ? "yes" : "no")
00210             % (isComplex(key) ? "yes" : "no")
00211             % size(key);
00212     }
00213 }
00214 
00215 prefix_ void senf::dumpPacketAnnotationRegistry(std::ostream & os)
00216 {
00217     senf::detail::AnnotationRegistry::instance().dumpRegistrations(os);
00218 }
00219 
00220 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00221 #undef prefix_
00222 //#include "PacketImpl.mpp"
00223 
00224 
00225 // Local Variables:
00226 // mode: c++
00227 // fill-column: 100
00228 // c-file-style: "senf"
00229 // indent-tabs-mode: nil
00230 // ispell-local-dictionary: "american"
00231 // compile-command: "scons -u test"
00232 // comment-column: 40
00233 // End:

Contact: senf-dev@lists.berlios.de | © 2006-2010 Fraunhofer Institute for Open Communication Systems, Network Research