(save-excursion
(back-to-indentation)
(if (and (looking-at "namespace")
- (looking-at ".*{")
- (not (looking-at ".*}")))
- [0] '+)))
+ (looking-at ".*{")
+ (not (looking-at ".*}")))
+ [0] '+)))
(defconst senf-c-style
'((c-basic-offset . 4)
(c-backslash-column . 98)
- (c-cleanup-list . (empty-defun-braces
- defun-close-semi
- list-close-comma
- scope-operator))
+ (c-cleanup-list . (empty-defun-braces
+ defun-close-semi
+ list-close-comma
+ scope-operator))
(c-hanging-braces-alist . ((namespace-open after)
(namespace-close before after)
(brace-list-open)
(c-add-style "senf" senf-c-style)
(set (make-local-variable 'ccide-file-vars)
- '(( fill-column . 100 )
- ( comment-column . 40 )
- ( c-file-style . "senf" )
- ( indent-tabs-mode . nil )
- ( ispell-local-dictionary . "american" )
- ( compile-command . "scons -u test") ))
+ '((fill-column . 100)
+ (comment-column . 40)
+ (c-file-style . "senf")
+ (indent-tabs-mode . nil)
+ (ispell-local-dictionary . "american")
+ (compile-command . "scons -u test")))
(set (make-local-variable 'ccide-default-copyright)
(concat "//\n"
is ignored (Those are the file local variables and local words)."
(let ((f (get-text-property (point) 'face)))
(and (memq f flyspell-prog-text-faces)
- (not (save-excursion
- (beginning-of-line)
- (looking-at "\\(//\\)?#")))
- (not (let ((l (max (point-min) (- (point-max) 4096))))
- (and (< l (point))
- (save-excursion (search-backward "\f" l t))))))))
+ (not (save-excursion
+ (beginning-of-line)
+ (looking-at "\\(//\\)?#")))
+ (not (let ((l (max (point-min) (- (point-max) 4096))))
+ (and (< l (point))
+ (save-excursion (search-backward "\f" l t))))))))
(defun flyspell-cc-mode ()
"Torn on `flyspell-mode` for comments and strings in C/C++ mode."
(insert "#include <senf/Utils/auto_unit_test.hh>"))))
(add-hook 'ccide-new-file-hooks 'senf-new-file-hook nil t)
+
+\f
+// Local Variables:
+// indent-tabs-mode: nil
+// End:
sec_filter.flags |= DMX_CHECK_CRC;
handle.protocol().setSectionFilter( &sec_filter );
-
+
senf::Scheduler::instance().add(
handle, senf::membind(&MySniffer::dumpSection, this));
}
pes_filter.pes_type = DMX_PES_OTHER;
pes_filter.flags = DMX_IMMEDIATE_START;
demuxHandle.protocol().setPESFilter( &pes_filter );
-
+
senf::Scheduler::instance().add(
dvrHandle, senf::membind(&ULEdec::handleEvent, this));
-
+
this->receiver_state = Idle;
this->priv_sndu_type_1 = false;
}
senf::TransportPacket ts_packet (
senf::TransportPacket::create(188, senf::noinit));
dvrHandle.read( ts_packet.data() );
-
+
// Check TS error conditions: sync_byte, transport_error_indicator, scrambling_control.
if ( (ts_packet->sync_byte() != senf::TransportPacketType::SYNC_BYTE) ||
(ts_packet->transport_error_indicator() == true) ||
// drop partly decoded SNDU, reset state, resync on PUSI.
return;
}
-
+
handleTSPacket(ts_packet);
}
private:
typedef senf::PacketData::iterator iterator;
-
+
enum ReceiverState {
Idle,
Reassembly
};
-
+
senf::DVBDemuxPESHandle demuxHandle;
senf::DVBDvrHandle dvrHandle;
-
+
senf::SNDUPacket snduPacket;
-
+
ReceiverState receiver_state;
unsigned char priv_tscc;
bool priv_sndu_type_1;
void handleEvent(senf::Scheduler::EventId event);
void handleTSPacket(senf::TransportPacket tsPacket);
void handleSNDUPacket();
-
+
iterator readNewSNDUPacket(iterator i, const iterator i_end);
iterator readContSNDUPacket(iterator i, const iterator i_end);
iterator readRawSNDUPacketData(iterator i, iterator const i_end);
-
- inline bool isSDNUPacketComplete();
+
+ inline bool isSDNUPacketComplete();
inline iterator::difference_type snduPacketBytesLeft();
-
+
};
struct ULEdecException : public senf::Exception
{
- ULEdecException(std::string const & what)
+ ULEdecException(std::string const & what)
: senf::Exception(what) {}
};
int main(int argc, char const * argv[])
-{
+{
try {
std::ofstream f1 ("233.132.152.1.txt");
std::ofstream f2 ("233.132.152.2.txt");
-
+
MCSniffer sniffer1 (
senf::INet4Address::from_string("233.132.152.1"), f1);
MCSniffer sniffer2 (
senf::INet4Address::from_string("233.132.152.2"), f2);
-
+
senf::scheduler::process();
}
catch (std::exception const & ex) {
return 0;
}
-
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
//#include "MCSniffer.mpp"
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
MCReader(unsigned n, std::string const & name, UDPSocket::Address const & group);
};
-prefix_ MCReader::MCReader(unsigned n, std::string const & name_,
+prefix_ MCReader::MCReader(unsigned n, std::string const & name_,
UDPSocket::Address const & group)
: name (name_), socket (),
- event (name, senf::membind(&MCReader::handler, this), socket,
+ event (name, senf::membind(&MCReader::handler, this), socket,
senf::scheduler::FdEvent::EV_READ)
{
socket.protocol().reuseaddr(true);
unsigned count;
void handler();
-
+
public:
- MCWriter(std::string const & name, UDPSocket::Address const & group,
+ MCWriter(std::string const & name, UDPSocket::Address const & group,
senf::ClockService::clock_type interval);
};
struct SystemException : public senf::Exception
{ SystemException() : senf::Exception("IfSetup::SystemException") {} };
-
+
};
prefix_ IfSetup::IfSetup(std::string const & iface_)
try {
boost::scoped_ptr<IfSetup> setup (
(argc != 2 || std::string(argv[1]) != "-n") ? new IfSetup("dummy0") : 0);
-
+
senf::scheduler::SignalEvent sigint (SIGINT, &sigintHandler);
UDPSocket::Address g1 ("225.1:43434");
This example application implements a simple PPI application: It will read UDP packets from an
input port and will forward them to another port at a fixed packet rate. If the input stream
does not provide enough packets, empty UDP packets will be sent instead.
-
+
\section run Running the example
Running the example is a little bit more complicated since we need to provide example UDP
<pre>
# nc -u -l -p 44345
</pre>
-
+
The next command starts the \c ratestuffer
<pre>
# cd .../Examples/RateStuffer
\skip class
\until rateFilter
-
- First the needed modules are declared. We have
+
+ First the needed modules are declared. We have
- the \a barrier to discard incoming packets sent to fast
- the \a queue to receive incoming packets and create throttling notifications
- the \a generator to create the stuffing packets
The constructor now initializes all the local objects. We pass the template \a packet to the \a
generator and set the timing \a interval of the \a rateFilter.
-
+
The \a input and \a output connector references are bound to the corresponding connectors we
want to expose: \a input to the \a barrier's \a input and \a output to the \a rateFilter's \a
output.
\until udpSink
The \ref senf::ppi::connect() calls setup the necessary connections.
-
+
The module setup is complete, \ref senf::ppi::run() is called to enter the event loop.
\until }
};
RateFilter::RateFilter(senf::ClockService::clock_type interval)
- : timer(interval)
+ : timer(interval)
{
route(input,timer);
route(timer,output);
connector::PassiveInput<> & input;
connector::ActiveOutput<> & output;
- RateStuffer(senf::ClockService::clock_type interval,
+ RateStuffer(senf::ClockService::clock_type interval,
senf::Packet packet,
unsigned high = 1,
unsigned low = 0)
queue.qdisc(ppi::ThresholdQueueing(high,low));
}
};
-
+
// ////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////
senf::INet4SocketAddress("localhost:44345"));
module::ActiveSocketSource<> udpSource ( inputSocket );
- RateStuffer stuffer ( 1000000000ul,
+ RateStuffer stuffer ( 1000000000ul,
senf::DataPacket::create(std::string("<idle>\n")),
2u, 1u );
module::PassiveSocketSink<> udpSink ( outputSocket );
\until #include <senf/Scheduler/Scheduler.hh>
The example includes two implementations, one using blocking calls and a while loop, the other
- using the senf::Scheduler for asynchronous event notification. They are implemented in
- \c loop_main() and \c scheduler_main(). They will be documented below. For now, we skip these
+ using the senf::Scheduler for asynchronous event notification. They are implemented in
+ \c loop_main() and \c scheduler_main(). They will be documented below. For now, we skip these
implementations and go straight to the \c main() function
\skip int main(
backtrace of the exception origin in the debugger.
We now create a packet socket and bind it to the interface given as second command line argument.
- A packet socket is a linux specific type of socket which returns ethernet packets directly from
+ A packet socket is a linux specific type of socket which returns ethernet packets directly from
the network wire. By uncommenting the last line, you may switch the interface into promiscuous mode.
\until //
\until sock.read
\doc the following section is obsolete!
-
+
Lets digest this line step by step: We declare a variable named \c packet as a smart pointer to
an \c EthernetPacket instance. \c ptr is a typedef member of all Packet classes for the
corresponding smart pointer type. We then initialize this pointer with a call to the static \c
\until }
Calling the Schedulers <tt> \link senf::Scheduler::process process()\endlink </tt> method will
- start the event loop. This call does not return (ok, it does return in special cases if
- \c senf::Scheduler::terminate() is called which does not apply here). The Callback Function is
+ start the event loop. This call does not return (ok, it does return in special cases if
+ \c senf::Scheduler::terminate() is called which does not apply here). The Callback Function is
the \c readFromClient() Function, which is declared as private here and will be called whenever
an event on the socket is encountered. The scheduler passes the event ID to the function.
0xff
);
tsPacket.finalize();
-
+
output.write( tsPacket);
-
+
advance_max( begin, 184, sec_end);
advance_max( end, 184, sec_end);
} while (begin != end);
{
SENF_PPI_MODULE(Psi2TsModule);
-public:
+public:
senf::ppi::connector::PassiveInput<> input;
senf::ppi::connector::ActiveOutput<senf::TransportPacket> output;
Psi2TsModule(unsigned pid, senf::ClockService::clock_type timout=0);
void onRequest();
-
+
private:
enum state {IDLE, PROC, WAIT};
typedef senf::PacketData::iterator iterator;
BOOST_CHECK_EQUAL( tsPacket->continuity_counter(), counter );
if (pusi)
BOOST_CHECK_EQUAL( tsPacket->pointer_field(), 0x0u );
-
+
}
template<class InputIterator, class T>
{
return std::find_if( first, last, boost::lambda::_1 != value) == last;
}
-
+
SENF_AUTO_UNIT_TEST(one_section_to_one_transportpacket)
{
senf::ppi::module::debug::PassiveSink sink;
unsigned PID = 42;
Psi2TsModule psi2ts (PID);
-
+
senf::ppi::connect( source, psi2ts);
senf::ppi::connect( psi2ts, sink);
senf::ppi::init();
-
+
std::string sec_data ( "psi2ts_test: one_section_to_one_transportpacket");
senf::Packet sec_packet (senf::DataPacket::create(sec_data));
sec_packet.finalize();
-
+
source.submit(sec_packet);
BOOST_CHECK_EQUAL( sink.size(), 1u);
senf::TransportPacket ts_packet = sink.pop_front().as<senf::TransportPacket>();
check_transportpacket_header( ts_packet, true, PID, 1);
senf::PacketData & ts_payload_data = ts_packet.next().data();
- BOOST_CHECK_EQUAL_COLLECTIONS(
- ts_payload_data.begin(),
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ ts_payload_data.begin(),
boost::next( ts_payload_data.begin(), sec_data.size()),
sec_data.begin(),
sec_data.end());
BOOST_CHECK( equal_elements(
- boost::next( ts_payload_data.begin(), ts_payload_data.size()),
+ boost::next( ts_payload_data.begin(), ts_payload_data.size()),
ts_payload_data.end(),
0xffu));
}
senf::ppi::module::debug::PassiveSink sink;
unsigned PID = 42;
Psi2TsModule psi2ts (PID);
-
+
senf::ppi::connect( source, psi2ts);
senf::ppi::connect( psi2ts, sink);
senf::ppi::init();
-
+
std::string sec_data ( 183, 0x42);
std::string sec_data2 ( "psi2ts_test: one_section_to_two_transportpackets");
sec_data.append( sec_data2);
senf::Packet sec_packet (senf::DataPacket::create(sec_data));
sec_packet.finalize();
-
+
source.submit( sec_packet);
BOOST_CHECK_EQUAL( sink.size(), 2u);
senf::PacketData & ts_payload_data1 = ts_packet.next().data();
BOOST_CHECK( equal_elements( ts_payload_data1.begin(), ts_payload_data1.end(), 0x42));
-
+
ts_packet = sink.pop_front().as<senf::TransportPacket>();
check_transportpacket_header( ts_packet, false, PID, 2);
senf::PacketData & ts_payload_data2 = ts_packet.next().data();
- BOOST_CHECK_EQUAL_COLLECTIONS(
- ts_payload_data2.begin(),
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ ts_payload_data2.begin(),
boost::next( ts_payload_data2.begin(), sec_data2.size()),
sec_data2.begin(),
sec_data2.end());
BOOST_CHECK( equal_elements(
- boost::next( ts_payload_data2.begin(), sec_data2.size()),
+ boost::next( ts_payload_data2.begin(), sec_data2.size()),
ts_payload_data2.end(),
0xffu));
}
senf::ppi::module::debug::PassiveSink sink;
unsigned PID = 42;
Psi2TsModule psi2ts (PID);
-
+
senf::ppi::connect( source, psi2ts);
senf::ppi::connect( psi2ts, sink);
senf::ppi::init();
-
+
std::string sec_data ( "many_sections_to_many_transportpackets");
senf::Packet sec_packet (senf::DataPacket::create(sec_data));
sec_packet.finalize();
-
+
unsigned NUMBER_OF_SECTIONS = 42u;
for (unsigned i=1; i<=NUMBER_OF_SECTIONS; i++) {
source.submit( sec_packet);
for (unsigned i=1; i<=NUMBER_OF_SECTIONS; i++) {
senf::TransportPacket ts_packet = sink.pop_front().as<senf::TransportPacket>();
- check_transportpacket_header( ts_packet, true, PID, i%16);
+ check_transportpacket_header( ts_packet, true, PID, i%16);
}
}
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-/** \mainpage Defining and using a new 'libPacket' Packet Type
+/** \mainpage Defining and using a new 'libPacket' Packet Type
This howto will introduce the facilities needed to define a new packet type. As example, the
- \c GREPacket type is defined.
+ \c GREPacket type is defined.
\autotoc
\li It implements packet invariants
To define a new packet type, we need to implement two classes which together provide all this
- information:
+ information:
\li a \e parser (a class derived from senf::PacketParserBase). This class defines the data
fields of the packet header and may also provide additional packet specific functionality.
SENF_PARSER_BITFIELD ( version, 3, unsigned );
SENF_PARSER_BITFIELD ( protocolType, 16, unsigned );
\endcode
-
+
This is a correct \c GREPacket header definition, but there is room for a small optimization:
Since the \a protocolType field is exactly 2 bytes wide and is aligned on a byte boundary, we
can define it as a UInt16 field (instead of a bitfield):
-
+
\code
SENF_PARSER_BITFIELD ( checksumPresent, 1, bool );
SENF_PARSER_SKIP_BITS ( 12 );
suitable for a single optional field as well as for an optional contiguous sequence of fields.
In our GRE example, there are two fields which need to be enabled/disabled en bloc. We first
- define an auxiliary sub-parser which combines the two fields.
+ define an auxiliary sub-parser which combines the two fields.
\code
struct GREPacketParser_OptFields : public senf::PacketParserBase
{
# include SENF_FIXED_PARSER()
-
+
// typedef checksum_t uint16_t; XXX defined automatically???
SENF_PARSER_FIELD ( checksum, senf::UInt16Parser );
p.protocolType() = 0x86dd;
p.optionalFields().get<1>().checksum() = 12345u;
\endcode
-
+
This code has two problems:
\li accessing the checksum field is quite unwieldy
\li changing the checksumPresent() value will break the parser
the selector (here \a checksumPresent) is changed, since the variant parser must ensure that the
header data stays consistent. Whenever the checksumPresent field is enabled, the variant parser
needs to insert additional 4 bytes of data. And it must remove those bytes whenever the
- checksumPresent field is disabled.
+ checksumPresent field is disabled.
\subsection howto_newpacket_parser_fixvariant Fixing access by providing custom accessor members
sub-parsers.
In this case however, we still want to allow the user to change the field value, albeit not
- directly. We will need to go through the collection parser, in this case the variant.
+ directly. We will need to go through the collection parser, in this case the variant.
The syntax for accessing a variant is quite cumbersome. Therefore we adjust the variant
definition to generate a more usable interface:
only access \a checksum() if the \a checksumPresent() field is set. Otherwise, the behavior is
undefined (in debug builds, the parser will terminate the application with an assert).
-
+
\subsection howto_newpacket_parser_add Providing additional functionality
We have now implemented parsing all the header fields. However, often packets would benefit from
\code
#include <senf/Utils/IpChecksum.hh>
- checksum_t::checksum_t::value_type calculateChecksum() const
+ checksum_t::checksum_t::value_type calculateChecksum() const
{
- if (!checksumEnabled())
+ if (!checksumEnabled())
return 0;
senf::IpChecksum cs;
This code just implements what is defined in the RFC: The checksum covers the complete GRE
packet including it's header with the checksum field temporarily set to 0. Instead of really
- changing the checksum field we manually pass the correct data to \a cs.
+ changing the checksum field we manually pass the correct data to \a cs.
We use the special <tt>i(</tt><i>offset</i><tt>)</tt> helper to get iterators \a offset number
of bytes into the data. This helper has the additional benefit of range-checking the returned
\code
#include <senf/Packets.hh>
-
+
struct GREPacketParser_OptFields : public senf::PacketParserBase
{
# include SENF_FIXED_PARSER()
// In the implementation (.cc) file:
#include <senf/Utils/IpChecksum.hh>
-
+
GREPacketParser::checksum_t::value_type GREPacketParser::calculateChecksum() const
{
- if (!checksumEnabled())
+ if (!checksumEnabled())
return 0;
validate(6);
typedef senf::PacketTypeMixin<GREPacketType, EtherTypes> mixin;
typedef senf::ConcretePacket<GREPacketType> packet;
typedef senf::GREPacketParser parser;
-
+
using mixin::nextPacketRange;
using mixin::nextPacketType;
using mixin::init;
The next block of statements imports all the default implementations provided by the mixin
class:
-
+
\li \a nextPacketRange provides information about where the next packet lives within the GRE
packet.
\li \a nextPacketType provides the type of the next packet from information in the GRE packet.
GREPacketParser::init.
\li \a initSize is called to find the size of an empty (newly create) GRE packet. This is also
provided by GREPacketParser.
-
+
With these default implementations provided by the mixin, only a few additional members are
needed to complete the \c GREPacketType: \a nextPacketKey, \a finalize, and \a dump.
\endcode
But wait -- what is \c GREPacket ? This question is answered a few section further down.
-
+
The last thing we need to do is, we need to set the \a protocolType() field to the correct value
when packets are newly created or changed. This is done within \a finalize:
have to be updated to be correct. This is the responsibility of the \a finalize() member.
\code
- static void finalize(packet p)
+ static void finalize(packet p)
{
p->protocolType() << key(p.next(senf::nothrow));
if (p->checksumPresent())
For diagnostic purposes, every packet should provide a meaningful \a dump() member which writes
out the complete packet. This member is simple to implement and is often very helpful when
tracking down problems.
-
+
\code
#include <boost/io/ios_state.hpp>
<< p->protocolType() << "\n";
if (p->checksumPresent())
os << " checksum : 0x" << std::hex << std::setw(4)
- << std::setfill('0') << p->checksum() << "\n";
+ << std::setfill('0') << p->checksum() << "\n";
}
\endcode
-
+
This member is quite straight forward. We should try to adhere to the formating standard shown
above: The first line should be the type of packet/header being dumped followed by one line for
each protocol field. The colon's should be aligned at column 33 with the field name indented by
- 2 spaces.
+ 2 spaces.
The \c boost::ios_all_saver is just used to ensure, that the stream formatting state is restored
correctly at the end of the method. An instance of this type will save the stream state when
typedef senf::PacketTypeMixin<GREPacketType, EtherTypes> mixin;
typedef senf::ConcretePacket<GREPacketType> packet;
typedef senf::GREPacketParser parser;
-
+
using mixin::nextPacketRange;
using mixin::nextPacketType;
using mixin::init;
using mixin::initSize;
static key_t nextPacketKey(packet p) { return p->protocolType(); }
-
+
static void finalize(packet p) {
- p->protocolType() << key(p.next(senf::nothrow));
+ p->protocolType() << key(p.next(senf::nothrow));
if (p->checksumPresent()) p->checksum() << p->calculateChecksum();
}
-
+
static void dump(packet p, std::ostream & os);
};
typedef GREPacketType::packet GREPacket;
-
+
// In the implementation (.cc) file:
#include <senf/Packets/DefaultBundle/EthernetPacket.hh>
<< p->protocolType() << "\n";
if (p->checksumPresent())
os << " checksum : 0x" << std::hex << std::setw(4)
- << std::setfill('0') << p->checksum() << "\n";
+ << std::setfill('0') << p->checksum() << "\n";
}
\endcode
needs to obey to be considered valid. If the packet is not valid it cannot be parsed and should
be dropped. We can't drop it here but if the packet is invalid, we certainly must refrain from
trying to parser any payload since we cannot assume the packet to have the format we assume our
- GRE packet to have.
+ GRE packet to have.
There are two conditions defined in the RFC which render a GRE packet invalid: If one of the \a
reserved0() fields first 5 bits is set or if the version is not 0. We will add a \a valid()
factory_t nextPacketType(packet p) { return p->valid() ? lookup(p->protocolType()) : no_factory(); }
\endcode
-
+
As we see, this is still quite simple. \c factory_t is provided by senf::PacketTypeBase. For our
purpose it is an opaque type which somehow enables the packet library to create a new packet of
a specified packet type. The \c factory_t has a special value, \c no_factory() which stands for
senf::EtherTypes registry ? Here one way to do this:
\code
- factory_t nextPacketType(packet p) {
+ factory_t nextPacketType(packet p) {
if (p->valid()) {
if (p->protocolType() == 0x6558) return senf::EthernetPacket::factory();
else return lookup(p->protocolType());
#define HH_GREPacket_
#include <senf/Packets.hh>
-
+
struct GREPacketParser_OptFields : public senf::PacketParserBase
{
# include SENF_FIXED_PARSER()
typedef senf::PacketTypeMixin<GREPacketType, EtherTypes> mixin;
typedef senf::ConcretePacket<GREPacketType> packet;
typedef senf::GREPacketParser parser;
-
+
using mixin::nextPacketRange;
using mixin::init;
using mixin::initSize;
- factory_t nextPacketType(packet p)
+ factory_t nextPacketType(packet p)
{ return p->valid() ? lookup(p->protocolType()) : no_factory(); }
-
+
static void finalize(packet p) {
p->protocolType() << key(p.next(senf::nothrow));
if (p->checksumPresent()) p->checksum() << p->calculateChecksum();
}
-
+
static void dump(packet p, std::ostream & os);
};
typedef GREPacketType::packet GREPacket;
-
+
#endif
\endcode
GREPacketParser::checksum_t::checksum_t::value_type GREPacketParser::calculateChecksum() const
{
- if (!checksumEnabled())
+ if (!checksumEnabled())
return 0;
validate(6);
<< p->protocolType() << "\n";
if (p->checksumPresent())
os << " checksum : 0x" << std::hex << std::setw(4)
- << std::setfill('0') << p->checksum() << "\n";
+ << std::setfill('0') << p->checksum() << "\n";
}
\endcode
senf::TapSocketHandle tap ("tap0");
senf::ConnectedRawV6ClientSocketHandle osock (47u, senf::INet6SocketAddress(argv[1]));
-
+
while (true) {
senf::EthernetPacket eth (senf::EthernetPacket::create(senf::noinit));
isock.read(eth.data(),0u);
}
\endcode
-
+
\section howto_newpacket_further Further reading
Lets start with references to the important API's (Use the <i>List of all members</i> link to
When implementing new packet's, the following information will be helpful:
<table class="senf fixedcolumn">
-
+
<tr><td>senf::PacketTypeBase</td> <td>here you find a description of the members which need to
be implemented to provide a 'packet type'. Most of these members will normally be provided by
the mixin helper.</td></tr>
use it.</td></tr>
<tr><td>\ref packetparser</td> <td>This section describes the packet parser facility.</td></tr>
-
+
<tr><td>\link packetparsermacros Packet parser macros\endlink</td> <td>A complete list and
documentation of all the packet parser macros.</td></tr>
-
+
<tr><td>\ref parseint, \n \ref parsecollection</td> <td>There are several lists of available
reusable packet parsers. However, these lists are not complete as there are other protocol
specific reusable parsers (without claiming to be exhaustive: senf::INet4AddressParser,
\section senfutil_overview Building Projects using SENF
- When building projects using %senf, SENFSCons has a very simple helper module
+ When building projects using %senf, SENFSCons has a very simple helper module
\ref senf_senfutil "senfutil.py" to make the building of libraries utilizing %senf simpler.
\see \ref senf_senfutil
CXXFLAGS_final = [ '-O2' ],
CXXFLAGS_normal = [ '-O0', '-g' ],
CXXFLAGS_debug = [ '$CXXFLAGS_normal' ],
-
+
LINKFLAGS_normal = [ '-Wl,-S' ],
LOGLEVELS_debug = [ 'senf::log::Debug||VERBOSE' ],
# Build objects from sources
objects = env.Object(sources)
-
+
# Build main binary
env.Default( env.Program( target='example', source=objects + ['main.cc'] ) )
where \e optional_stream and \e optional_area are optional fully scoped C++ names (e.g. \c
senf::log::Debug) and \e level is the loglevel. There must be \e no whitespace in a single
specification, multiple specifications are either specified using an array or separated with
- whitespace.
+ whitespace.
\section senf_senfutil_default Default options
# Build main target, e.g. a Binary with additional sources which are not part of the unit test
env.Program('example', objects+extra_sources)
-
+
# Build unit tests including additional test sources
env.BoostUnitTest('test', objects+tests)
\endcode
-
+
It is important to exclude the \c main function from the unit-test build since the boost unit
test library provides it's own.
The \c senfutil.Doxygen utility autogenerates a \c Doxyfile.
- The utility will search for a SENF documentation in the \c senfdoc and \c %senf subdirectories
+ The utility will search for a SENF documentation in the \c senfdoc and \c %senf subdirectories
as well as via the senfutil module directory and some other standard locations. If SENF
- documentation is found, the SENF tagfiles will automatically be added. Links will be resolved
+ documentation is found, the SENF tagfiles will automatically be added. Links will be resolved
to the documentation found.
\c senfutil.Doxygen takes some additional optional keyword arguments:
</pre>
in the \c %senf directory. This assumes, that you want to build the library with your default
- gcc and requires the boost libraries to be available in the system include paths. If this is
+ gcc and requires the boost libraries to be available in the system include paths. If this is
not the case, you can take a look at <tt>SConfig.template</tt> file. Copy this file to
<tt>SConfig</tt> and comment out all the variables you don't want to change (The \e values in
the template file are just arbitrary examples).
\ref senf_setup
\section senf_conventions Coding Conventions
-
+
Here we have laid down the coding conventions used throughout the SENF framework. Please ad here
to these conventions when changing or adding code. If you use emacs, you can use the C++ IDE for
emacs from http://g0dil.de which greatly simplifies following these conventions.
\par Rationale:
This simplifies finding the implementation/header for a given class and also reduces the
size of each single file.
-
+
The implementation is divided into a number of different files:
<table class="glossary"> <tr><td>\c .h</td><td>C public header</td></tr>
<tr><td>\c .cci</td><td>C++ implementation of inline non-template functions and
members</td></tr>
-
+
<tr><td>\c .cti</td><td>C++ implementation of inline template functions and members</td></tr>
<tr><td>\c .mpp</td><td>Special include file used for external iteration by the
\li When defining simple exception classes, the 'what()' member may be defined inline if it
returns a string constant.
\li It may be OK to use inline implementations for one-line implementations in internal
- headers.
+ headers.
\li The Packet library allows inline implementations for the definition of parsers since doing
so outside the declaration just gets to verbose and parsers definitions are quite length but
very simple and straight forward.
// $Id$
//
-// Copyright (C) 2007
+// Copyright (C) 2007
// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
// Stefan Bund <g0dil@berlios.de>
namespace module = senf::ppi::module;
namespace scheduler = senf::scheduler;
-namespace {
+namespace {
void run(senf::ClockService::clock_type t) {
scheduler::TimerEvent timeout(
"test-timeout", &scheduler::terminate, scheduler::now() + t);
ppi::connect( source, feeder );
ppi::connect( feeder, sink );
- senf::ClockService::clock_type start (senf::ClockService::now());
+ senf::ClockService::clock_type start (senf::ClockService::now());
run( senf::ClockService::seconds(1));
- std::cerr << "\nActiveFeeder: "
+ std::cerr << "\nActiveFeeder: "
<< (sink.size()*1e9)/(senf::ClockService::now()-start)
<< " packets/s" << std::endl;
BOOST_CHECK( sink.size() > 0);
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
connectorSetup(connector::ActiveOutput<> & conn, AnnotationType const & key)
{
if (this->connectors().find(key) != this->connectors().end())
- throw DuplicateKeyException(key);
+ throw DuplicateKeyException(key);
route(input, conn);
return key;
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
senf::MACAddress mac;
- bool operator< (TargetInterface const & other)
+ bool operator< (TargetInterface const & other)
{ return mac < other.mac; }
- TargetInterface(senf::MACAddress const & m)
+ TargetInterface(senf::MACAddress const & m)
: mac (m) {}
};
\ingroup routing_modules
\todo Call Module::v_init() on every connection change and remove disconnected connections
- from the container
+ from the container
*/
template <class AnnotationType>
- class AnnotationRouter
- : public Module,
+ class AnnotationRouter
+ : public Module,
public MultiConnectorMixin< AnnotationRouter<AnnotationType>,
connector::ActiveOutput<>,
AnnotationType >
AnnotationRouter();
struct DuplicateKeyException : public senf::Exception
- { DuplicateKeyException(AnnotationType const & key)
+ { DuplicateKeyException(AnnotationType const & key)
: senf::Exception("Duplicate senf::ppi::module::AnnotationRouter routing key ")
{ append( senf::str(key)); } };
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
debug::PassiveSink sink2;
AnnotationRouter router;
-
+
ppi::connect(source, router);
ppi::connect(router, 1, sink1);
ppi::connect(router, 2, sink2);
-
- BOOST_CHECK_THROW( connect(router, 2, sink2),
+
+ BOOST_CHECK_THROW( connect(router, 2, sink2),
module::AnnotationRouter<IntAnnotation>::DuplicateKeyException);
ppi::init();
senf::ppi::connect(router, 1, sink1);
senf::ppi::init();
source.submit(p1);
-
+
BOOST_CHECK_EQUAL( sink1.size(), 2u );
BOOST_CHECK_EQUAL( sink2.size(), 1u );
}
BOOST_CHECK( sink.request() != p );
BOOST_CHECK( sink.request().data()[0] == p.data()[0] );
BOOST_CHECK( sink.request().data()[0] == p.data()[0] );
-
+
data[0] = 0xcd;
senf::Packet p2 (senf::DataPacket::create(data));
source.replacePacket( p2);
prefix_ void senf::ppi::connector::Connector::connect(Connector & target)
{
// The connector is not registered -> route() or noroute() statement missing
- SENF_ASSERT( module_ &&
+ SENF_ASSERT( module_ &&
"senf::ppi::connector::Connector::connect(): (source) "
"Missing route() or noroute()" );
// The connector is already connected
"senf::ppi::connector::Connector::connect(): (target) "
"duplicate connection" );
if (! (packetTypeID() == typeid(void) ||
- target.packetTypeID() == typeid(void) ||
+ target.packetTypeID() == typeid(void) ||
packetTypeID() == target.packetTypeID()) )
- throw IncompatibleConnectorsException()
- << ": " << prettyName(packetTypeID())
+ throw IncompatibleConnectorsException()
+ << ": " << prettyName(packetTypeID())
<< " [in module " << prettyName(typeid(*module_)) << "] "
<< ", " << prettyName(target.packetTypeID())
<< " [in module " << prettyName(typeid(*target.module_)) << "]";
-
+
peer_ = & target;
target.peer_ = this;
return;
SENF_LOG_BLOCK(({
std::string type (prettyName(p.typeId().id()));
- log << "PPI packet trace: " << label << " 0x" << std::hex << p.id() << " "
- << type.substr(21, type.size()-22) << " on " << & module() << " "
+ log << "PPI packet trace: " << label << " 0x" << std::hex << p.id() << " "
+ << type.substr(21, type.size()-22) << " on " << & module() << " "
<< prettyName(typeid(module())) << " connector 0x" << this << "\n";
if (traceState_ == TRACE_CONTENTS)
p.dump(log);
if (traceState_ == NO_TRACING)
return;
SENF_LOG_BLOCK(({
- log << "PPI throttling trace: " << label << " " << type << " on " << & module()
+ log << "PPI throttling trace: " << label << " " << type << " on " << & module()
<< " " << prettyName(typeid(module())) << " connector 0x" << this << "\n";
}));
}
namespace senf { namespace ppi { namespace connector {
- SENF_CONSOLE_REGISTER_ENUM_MEMBER(
+ SENF_CONSOLE_REGISTER_ENUM_MEMBER(
Connector, TraceState, (NO_TRACING)(TRACE_IDS)(TRACE_CONTENTS) );
}}}
prefix_ void senf::ppi::connector::PassiveConnector::notifyUnthrottle()
{
- if (std::find_if(routes_.begin(), routes_.end(),
+ if (std::find_if(routes_.begin(), routes_.end(),
boost::bind(&ForwardingRoute::throttled, _1)) == routes_.end()) {
remoteThrottled_ = false;
if (!nativeThrottled_)
// senf::ppi::connector::GenericPassiveInput
////////////////////////////////////////
-// private members
+// private members
prefix_ void senf::ppi::connector::GenericPassiveInput::v_enqueueEvent()
{
routes_.erase(i);
}
-// public members
+// public members
prefix_ bool senf::ppi::connector::PassiveConnector::nativeThrottled()
const
const
{
// Cannot peek() head of empty queue
- SENF_ASSERT( ! queue_.empty() &&
+ SENF_ASSERT( ! queue_.empty() &&
"senf::ppi::connector::InputConnector: cannot call peek() on empty queue" );
return queue_.back();
}
We therefore have 4 connector types each of which is parameterized by the type of packet
traversing the connector:
\li senf::ppi::connector::ActiveInput
- \li senf::ppi::connector::ActiveOutput
- \li senf::ppi::connector::PassiveInput
+ \li senf::ppi::connector::ActiveOutput
+ \li senf::ppi::connector::PassiveInput
\li senf::ppi::connector::PassiveOutput.
Connectors are declared as module data members and are then externally connected to other
senf::ppi::connector::ActiveInputJack<senf::EthernetPacket> input;
senf::ppi::connector::ActiveOutputJack<senf::EthernetPacket> output;
- MyGroup()
+ MyGroup()
: queue (), analyzer (), input (queue.input), output (analyzer.output)
{
senf::ppi::connect(queue, analyzer);
void throttleTrace(char const * label, char const * type);
void unregisterConnector();
-
+
private:
virtual std::type_info const & packetTypeID();
-
+
virtual void v_disconnected() const;
void setModule(module::Module & module);
typedef std::vector<ForwardingRoute*> NotifyRoutes;
NotifyRoutes notifyRoutes_;
- bool throttled_;
+ bool throttled_;
friend class senf::ppi::ForwardingRoute;
friend class PassiveConnector;
#else
/** \brief Connector actively reading packets
-
+
\tparam PacketType Type of packet to read. Defaults to senf::Packet
The %ActiveInput %connector template reads data actively from a connected %module. This
- class is completely implemented via it's base-class, GenericActiveInput, the only
- difference is that read packets are returned as \a PacketType instead of generic
+ class is completely implemented via it's base-class, GenericActiveInput, the only
+ difference is that read packets are returned as \a PacketType instead of generic
senf::Packet references.
\see GenericActiveInput \n
\tparam PacketType Type of packet to read. Defaults to senf::Packet
The %PassiveInput %connector template receives packets sent to it from a connected
- %module. This class is completely implemented via it's base-class, GenericPassiveInput,
+ %module. This class is completely implemented via it's base-class, GenericPassiveInput,
the only difference is that read packets are returned as \a PacketType instead of generic
senf::Packet references.
\tparam PacketType Type of packet to send. Defaults to senf::Packet
- The %ActiveOutput %connector template sends data actively to a connected %module. This
+ The %ActiveOutput %connector template sends data actively to a connected %module. This
class is completely implemented via it's base-class, GenericActiveOutput, the only
difference is that it only sends packets of type \a PacketType.
\tparam PacketType Type of packet to send. Defaults to senf::Packet
- The %PassiveOutput %connector template provides data passively to a connected %module
- whenever signaled. This class is completely implemented via it's base-class,
- GenericPassiveOutput, the only difference is that it only sends packets of type
+ The %PassiveOutput %connector template provides data passively to a connected %module
+ whenever signaled. This class is completely implemented via it's base-class,
+ GenericPassiveOutput, the only difference is that it only sends packets of type
\a PacketType.
\see GenericPassiveOutput \n
{
public:
typedef PacketType Type;
-
+
Type operator()();
Type read();
};
{
public:
typedef PacketType Type;
-
+
void operator()(Type p);
void write(Type p);
};
target.input.throttle();
BOOST_CHECK( target.input.throttled() );
BOOST_CHECK( target.input.nativeThrottled() );
-
+
target.input.unthrottle();
BOOST_CHECK( ! target.input.throttled() );
BOOST_CHECK( ! target.input.nativeThrottled() );
}
namespace {
-
+
bool called = false;
-
+
void handler() { called = true; }
}
// peek() is implicitly tested within the Active/PassiveSink implementation
BOOST_CHECK_EQUAL ( & target.input.peer(), & source.output );
-
+
BOOST_CHECK( target.input.begin() == target.input.end() );
BOOST_CHECK_EQUAL( target.input.queueSize(), 0u );
BOOST_CHECK( target.input.empty() );
ppi::init();
BOOST_CHECK_EQUAL( & target.input.peer(), & source.output );
-
+
target.input.throttle();
senf::Packet p (senf::DataPacket::create());
source.submit(p);
-
+
BOOST_CHECK_EQUAL( target.counter, 0u );
BOOST_CHECK( target.input );
BOOST_CHECK_EQUAL( target.input.queueSize(), 1u );
target.input.unthrottle();
BOOST_CHECK( target.input );
BOOST_CHECK_EQUAL( target.counter, 1u );
-
+
BOOST_CHECK( target.input() == p );
BOOST_CHECK( ! target.input );
-
+
source.submit(p);
-
+
BOOST_CHECK_EQUAL( target.counter, 2u );
BOOST_CHECK( target.input.throttled() );
BOOST_CHECK( target.input() == p );
source.submit(p);
BOOST_CHECK( target.request() == p );
-
+
// connect() is tested indirectly via ppi::connect
}
ppi::connect(source,target);
ppi::init();
-
+
BOOST_CHECK_EQUAL( & source.output.peer(), & target.input );
BOOST_CHECK( source.output );
target.input.throttle();
senf::Packet p (senf::DataPacket::create());
source.submit(p);
-
+
BOOST_CHECK( true );
}
ppi::connect(source,target);
ppi::init();
-
+
senf::IGNORE( target.request() );
-
+
BOOST_CHECK( true );
}
{
TypedPassiveInput<> input;
TypedActiveOutput<MyPacket> output;
- BOOST_CHECK_THROW( ppi::connect(output, input),
+ BOOST_CHECK_THROW( ppi::connect(output, input),
ppi::connector::IncompatibleConnectorsException );
}
{
TypedPassiveInput<MyPacket> input;
TypedActiveOutput<> output;
- BOOST_CHECK_THROW( ppi::connect(output, input),
+ BOOST_CHECK_THROW( ppi::connect(output, input),
ppi::connector::IncompatibleConnectorsException );
}
{
TypedActiveOutput<> output;
SENF_CHECK_NO_THROW( ppi::connect(output, input) );
}
- {
+ {
TypedPassiveInput<> input;
debug::ActiveSource output;
SENF_CHECK_NO_THROW( ppi::connect(output, input) );
ppi::connect(source, target);
ppi::init();
-
+
BOOST_CHECK( source.output );
senf::Packet p (senf::DataPacket::create());
source.submit(p);
- BOOST_CHECK( target.front() == p );
+ BOOST_CHECK( target.front() == p );
BOOST_CHECK_EQUAL( target.size(), 1u );
}
ppi::connect(source, target);
ppi::init();
-
+
BOOST_CHECK( ! source.output );
target.unthrottle();
BOOST_CHECK( source.output );
source.submit(p);
BOOST_CHECK( target.input );
-
+
target.input.disconnect();
ppi::init();
-
+
BOOST_CHECK( ! target.input );
}
{
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
private:
void request();
-
+
Queue packets_;
};
ppi::connect(source, sink);
ppi::init();
-
+
senf::PacketData::byte data[] = { 0x13u, 0x24u, 0x35u };
senf::Packet p (senf::DataPacket::create(data));
BOOST_CHECK( ! sink.input.throttled() );
BOOST_CHECK_EQUAL( sink.size(), 1u );
BOOST_CHECK( ! sink.empty() );
- BOOST_CHECK_EQUAL(
+ BOOST_CHECK_EQUAL(
debug::PassiveSink::size_type(std::distance(sink.begin(),sink.end())),
sink.size() );
BOOST_CHECK( *sink.begin() == p );
senf::Packet p (senf::DataPacket::create(data));
source.submit(p);
-
+
BOOST_CHECK_EQUAL( source.size(), 1u );
BOOST_CHECK_EQUAL( sink.request(), p );
BOOST_CHECK_EQUAL( source.size(), 0u );
senf::PacketData::byte data[] = { 0x13u, 0x24u, 0x35u };
source.submit( senf::DataPacket::create(data) );
senf::ppi::run();
-
+
BOOST_CHECK( ! logTarget.str().empty() );
}
source.submit(p);
source.submit(p);
-
+
BOOST_CHECK( true );
}
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
Since ActiveDuplicator allows any number of incoming packet streams, the input connectors
are dynamically managed. A special senf::ppi::connect() overload is used to dynamically
- create the needed input connectors. This hides this extra functionality from the user.
+ create the needed input connectors. This hides this extra functionality from the user.
\code
senf::ppi::module::ActiveDuplicator dup;
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
using boost::lambda::_1;
namespace l = boost::lambda;
-
+
SENF_ASSERT(
std::find_if(registrations_.begin(), registrations_.end(),
- l::bind(&detail::EventBindingBase::descriptor_,_1) == &event)
+ l::bind(&detail::EventBindingBase::descriptor_,_1) == &event)
== registrations_.end());
}
for (; i != i_end; ++i)
if ((*i)->throttled())
break;
- if (i != i_end)
+ if (i != i_end)
return;
throttled_ = false;
enabled(true);
namespace ppi {
namespace detail { class EventBindingBase; }
-
+
/** \defgroup event_group Events
Events provide notification of events outside the PPI framework: I/O activity, Timers
All events are derived from EventImplementation which is based on EventDescriptor.
\see EventImplementation \n
- \ref ppi_events
+ \ref ppi_events
*/
// Implementation: The concrete EventDescriptor implementation will need to set things up so
// some callback (within the EventDescriptor implementation) will be called when the event
// happens. This setup happens in 'v_enable()'. This internal handler sets up an EventType
- // instance if needed and calls 'callback()'.
+ // instance if needed and calls 'callback()'.
//
// 'callback()' will access the EventBinding wrapper to find the user-callback to signal. It
// will do any needed internal processing, call that user callback and clean up afterwards.
The EventDescriptor base-class provides an interface to control events.
\see \ref ppi_events
- */
+ */
class EventDescriptor
{
public:
friend class ForwardingRoute;
friend class detail::EventBindingBase;
};
-
+
/** \brief Internal: Callback forwarders
*/
template <class EventType, class Self>
private:
detail::EventBinding<EventType> & binding();
};
-
+
#ifndef DOXYGEN
template <class Self>
/** \brief Event implementation base class
- EventImplementation provides the base-class for all Event implementations.
+ EventImplementation provides the base-class for all Event implementations.
\code
class SomeEvent : public EventImplementation<SomeEventArg>
{
void cb() {
// Build event argument
- SomeEventArg arg (...);
+ SomeEventArg arg (...);
// Call the event callback
callback(arg);
}
*/
template <class EventType>
class EventImplementation
- : public EventDescriptor,
+ : public EventDescriptor,
public EventImplementationHelper< EventType, EventImplementation<EventType> >
{
public:
module::Module & module() const; ///< Module in which the event is registered
EventManager & manager() const; ///< EventManager of the event
-
+
protected:
EventImplementation();
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////cci.p///////////////////////////////////////
prefix_ senf::ppi::IOEvent::IOEvent()
- : fd_ (-1),
+ : fd_ (-1),
event_ ("senf::ppi::IOEvent", boost::bind(&IOEvent::cb,this,_1))
{}
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
template <class Handle>
prefix_ senf::ppi::IOEvent::IOEvent(Handle handle, unsigned events)
- : fd_ (-1), event_ ("senf::ppi::IOEvent", boost::bind(&IOEvent::cb,this,_1))
+ : fd_ (-1), event_ ("senf::ppi::IOEvent", boost::bind(&IOEvent::cb,this,_1))
{
set(handle,events);
}
type of event is specified using the \a events mask with values from EventFlags.
There are two types of flags:
-
+
\li <em>Event flags</em> (\ref Read, \ref Prio, \ref Write) specify the type of event. The
callback will be called whenever one of the specified events occurs on the filehandle
\li <em>Error flags</em> (\ref Hup, \ref Err) specify some type of error condition on the
// This is stupid, however there is no way to import the Scheduler::EventId enum together
// with the enumeration symbols
- enum EventFlags {
+ enum EventFlags {
Read = scheduler::FdEvent::EV_READ /**< FileHandle is readable */
, Prio = scheduler::FdEvent::EV_PRIO /**< FileHandle priority data is readable */
, Write = scheduler::FdEvent::EV_WRITE /**< FileHandle is writable */
private:
virtual void v_enable();
virtual void v_disable();
-
+
void cb(int event);
int fd_;
scheduler::FdEvent event_;
};
-
+
}}
///////////////////////////////hh.e////////////////////////////////////////
An IdleEvent is signaled continually and repeatedly while enabled. It will consume 100% of
available CPU resources. The resource usage is controlled by adequate event throttling.
-
+
\ingroup event_group
*/
class IdleEvent
virtual void v_disable();
void cb();
-
+
scheduler::TimerEvent timer_;
};
explicit IntervalTimer(ClockService::clock_type interval,
unsigned eventsPerInterval=1);
IntervalTimer();
-
+
///@}
///////////////////////////////////////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
prefix_ senf::ppi::connector::ActiveInputJack<senf::Packet>::
ActiveInputJack(GenericActiveInput & input)
- : GenericActiveInputJack (input)
+ : GenericActiveInputJack (input)
{}
prefix_ senf::ppi::connector::ActiveInputJack<senf::Packet>::
ActiveInputJack(GenericActiveInputJack input)
- : GenericActiveInputJack (input.connector())
+ : GenericActiveInputJack (input.connector())
{}
prefix_ void senf::ppi::connector::ActiveInputJack<senf::Packet>::reset(GenericActiveInput & input)
prefix_ senf::ppi::connector::ActiveOutputJack<senf::Packet>::
ActiveOutputJack(GenericActiveOutput & output)
- : GenericActiveOutputJack (output)
+ : GenericActiveOutputJack (output)
{}
prefix_ senf::ppi::connector::ActiveOutputJack<senf::Packet>::
ActiveOutputJack(GenericActiveOutputJack & output)
- : GenericActiveOutputJack (output.connector())
+ : GenericActiveOutputJack (output.connector())
{}
prefix_ void senf::ppi::connector::ActiveOutputJack<senf::Packet>::reset(GenericActiveOutput & output)
prefix_ senf::ppi::connector::PassiveInputJack<senf::Packet>::
PassiveInputJack(GenericPassiveInput & input)
- : GenericPassiveInputJack (input)
+ : GenericPassiveInputJack (input)
{}
prefix_ senf::ppi::connector::PassiveInputJack<senf::Packet>::
PassiveInputJack(GenericPassiveInputJack & input)
- : GenericPassiveInputJack (input.connector())
+ : GenericPassiveInputJack (input.connector())
{}
prefix_ void senf::ppi::connector::PassiveInputJack<senf::Packet>::reset(GenericPassiveInput & input)
prefix_ senf::ppi::connector::PassiveOutputJack<senf::Packet>::
PassiveOutputJack(GenericPassiveOutput & output)
- : GenericPassiveOutputJack (output)
+ : GenericPassiveOutputJack (output)
{}
prefix_ senf::ppi::connector::PassiveOutputJack<senf::Packet>::
PassiveOutputJack(GenericPassiveOutputJack & output)
- : GenericPassiveOutputJack (output.connector())
+ : GenericPassiveOutputJack (output.connector())
{}
prefix_ void
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
: private boost::noncopyable, private ppi::detail::DisableStandardConnect
{};
- /** \brief Jack referencing an ActiveInput
+ /** \brief Jack referencing an ActiveInput
\see \ref ppi_jacks */
class GenericActiveInputJack
: public Jack
private:
GenericPassiveInput * input_;
};
-
+
/** \brief Jack referencing a PassiveOutput
\see \ref ppi_jacks */
class GenericPassiveOutputJack
public:
explicit ActiveInputJack(ActiveInput<PacketType> & input);
explicit ActiveInputJack(ActiveInput<> & input);
-
+
explicit ActiveInputJack(ActiveInputJack & input);
explicit ActiveInputJack(ActiveInputJack<> & input);
void reset(ActiveInput<PacketType> & input);
void reset(ActiveInput<> & input);
-
+
void reset(ActiveInputJack & input);
void reset(ActiveInputJack<> & input);
};
void connect(T & source, connector::GenericPassiveInputJack & target,
typename boost::disable_if< boost::is_base_of<connector::Jack, T> >::type * = 0);
- void connect(connector::GenericActiveOutputJack & source,
+ void connect(connector::GenericActiveOutputJack & source,
connector::GenericPassiveInputJack & target);
- void connect(connector::GenericPassiveOutputJack & source,
+ void connect(connector::GenericPassiveOutputJack & source,
connector::GenericActiveInputJack & target);
- void connect(connector::GenericActiveOutputJack & source,
+ void connect(connector::GenericActiveOutputJack & source,
connector::GenericPassiveInput & target);
- void connect(connector::GenericPassiveOutputJack & source,
+ void connect(connector::GenericPassiveOutputJack & source,
connector::GenericActiveInput & target);
- void connect(connector::GenericActiveOutput & source,
+ void connect(connector::GenericActiveOutput & source,
connector::GenericPassiveInputJack & target);
- void connect(connector::GenericPassiveOutput & source,
+ void connect(connector::GenericPassiveOutput & source,
connector::GenericActiveInputJack & target);
#endif
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace {
- class ActiveDummyForward
+ class ActiveDummyForward
: public senf::ppi::module::Module
{
SENF_PPI_MODULE(ActiveDummyForward);
{ ++n; output(input()); }
};
- class PassiveDummyForward
+ class PassiveDummyForward
: public senf::ppi::module::Module
{
SENF_PPI_MODULE(PassiveDummyForward);
PassiveGroup()
: input (forward1.input), output (forward1.output) {}
-
+
void flip()
{
input.reset(forward2.input);
senf::ppi::connect(source, group);
senf::ppi::connect(group, sink);
-
+
senf::ppi::init();
-
+
{
senf::Packet p (senf::DataPacket::create());
source.submit(p);
group.flip();
senf::ppi::init();
-
+
{
senf::Packet p (senf::DataPacket::create());
source.submit(p);
BOOST_CHECK_EQUAL( group.forward1.n, 1u );
BOOST_CHECK_EQUAL( group.forward2.n, 1u );
}
-
+
{
PassiveGroup group;
senf::ppi::module::debug::ActiveSource source;
if (priority < 0) {
priority = connectors().size() + priority;
- if (priority < 0)
+ if (priority < 0)
priority = 0;
}
if (priority >= int(connectors().size())-1)
return;
-
+
connectors().insert(connectors().begin()+priority, connectors().pop_back().release());
}
sink.input.throttle();
BOOST_CHECK( ! source1 );
BOOST_CHECK( ! source2 );
-
+
source1.submit(p);
source2.submit(p);
BOOST_CHECK_EQUAL( sink.size(), 2u );
senf::Packet p1 (senf::DataPacket::create());
senf::Packet p2 (senf::DataPacket::create());
-
+
source1.submit(p1);
BOOST_CHECK( sink );
source2.submit(p2);
ppi::connect(source3, join, 0);
ppi::connect(source4, join, -2);
// Ordering now: source3, source1, source4, source2
-
+
senf::Packet p3 (senf::DataPacket::create());
senf::Packet p4 (senf::DataPacket::create());
-
+
source4.submit(p4);
source3.submit(p3);
source2.submit(p2);
It is possible to connect two active or passive connectors with each other using a special
adaptor module (senf::ppi::module::PassiveQueue or senf::ppi::module::ActiveFeeder
respectively).
-
+
Additionally, the connectors must be type-compatible: Either one (or both) of the connectors
must be untyped (they accept arbitrary senf::Packet's, the optional tempalte argument is empty),
- or they both accept the same type of packet. This check is performed at runtime.
+ or they both accept the same type of packet. This check is performed at runtime.
To complete our simplified example: Lets connect senf::ppi::module::ActiveSocketReader and
senf::ppi::module::PassiveSocketWriter to our example module:
prefix_ void senf::ppi::module::Module::registerConnector(connector::Connector & connector)
{
- if (std::find(connectorRegistry_.begin(), connectorRegistry_.end(), &connector)
+ if (std::find(connectorRegistry_.begin(), connectorRegistry_.end(), &connector)
== connectorRegistry_.end()) {
connectorRegistry_.push_back(&connector);
connector.setModule(*this);
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
- \brief Module public header
+ \brief Module public header
*/
#ifndef HH_SENF_PPI_Module_
/** \namespace senf::ppi::module
\brief PPI Modules
-
+
The modules build the PPI core. The PPI provides a set of general purpose infrastructure
modules. For concrete applications, additional application specific processing modules need
to be implemented.
\section module_impl Implementing Modules
-
+
All modules derive from senf::ppi::module::Module. See this class for a documentation on how
to write new modules.
senf::ppi::Module is the base-class of all PPI modules. It provides the module implementation
with interfaces to several PPI facilities:
-
+
\li Connector management
\li Flow management (routing)
\li Event handling
senf::ppi::connector::PassiveInput<> input;
senf::ppi::connector::ActiveOutput<> output;
- SomeModule(senf::FileHandle h)
- : handle ( h ),
+ SomeModule(senf::FileHandle h)
+ : handle ( h ),
event ( handle, senf::ppi::IOEvent::Read )
{
// Set up routing. If some connector is not routed you need to explicitly state this
#ifndef DOXYGEN
template <class Source, class Target>
- Route<Source, Target> & route(Source & source, Target & target);
+ Route<Source, Target> & route(Source & source, Target & target);
#else
Route<connector::InputConnector, connector::OutputConnector> &
route(connector::InputConnector & input, connector::OutputConnector & output);
incoming data (connector or event)
\param[in] output Data target, object which controls
outgoing data (connector or event)
- \returns Route instance describing this route
+ \returns Route instance describing this route
\see \ref ppi_throttling
\note The real implementation is not provided by three
overloads but by a single template member */
event is signaled.).
This event routing allows to automatically
- enable/disable the event on throttling notifications.
+ enable/disable the event on throttling notifications.
\see \ref route() */
generated whenever the event is signaled).
This event routing allows to automatically
- enable/disable the event on throttling notifications.
+ enable/disable the event on throttling notifications.
\see \ref route() */
#endif
information for terminal connectors</em>.
See the route() documentation for more on routing
-
+
\param[in] connector Terminal connector to declare */
#ifndef DOXYGEN
\param[in] target The handler to call whenever the
event is signaled
- \param[in] descriptor The type of event to register
+ \param[in] descriptor The type of event to register
\note The real implementation has the second arguments
type as an additional template parameter. */
#endif
virtual void v_init(); ///< Called after module setup
/**< This member is called directly before the PPI (resumes)
execution. It is called after connections have been
- setup before entering the PPI main loop.
+ setup before entering the PPI main loop.
You may overload this member. Your overload should
always call the base-class implementation. */
public:
#endif
void destroy();
-
+
private:
EventManager & eventManager() const;
ModuleManager & moduleManager() const;
-
+
void registerConnector(connector::Connector & connector);
void unregisterConnector(connector::Connector & connector);
void unregisterEvent(EventDescriptor & event);
/** \brief Define PPI Module
- Every module must begin by using this macro.
+ Every module must begin by using this macro.
\see senf::ppi::module::Module
*/
void timeout() {
senf::scheduler::terminate();
}
-
+
class InitTest : public ppi::module::Module
{
SENF_PPI_MODULE(InitTest);
SENF_AUTO_UNIT_TEST(delayedInit)
{
MakeInit maker;
- senf::scheduler::TimerEvent timer (
+ senf::scheduler::TimerEvent timer (
"delayedInit timer",
senf::membind(&MakeInit::make, &maker),
senf::ClockService::now() + senf::ClockService::milliseconds(250) );
// private members
prefix_ senf::ppi::ModuleManager::ModuleManager()
- : running_(false), terminate_(false),
+ : running_(false), terminate_(false),
initRunner_ ("senf::ppi::init", membind(&ModuleManager::init, this),
scheduler::EventHook::PRE, false)
{
initQueue_.push_back(&i);
initRunner_.enable();
// This call ensures, that the senf::ppi::init() handler is called as next handler
- // after this handler returns (this works since the senf::ppi::init() handler is registered as
+ // after this handler returns (this works since the senf::ppi::init() handler is registered as
// PRE hook and thus has very high priority)
senf::scheduler::yield();
}
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
/** \brief Base class providing simple monitor %module support
- A monitor %module is a \ref senf::ppi::module::Module "module" which needs information
- about traversing packets but does not really act on the packets. Because of this, it is
- \e optional to connect the output: If the output is not connected, the packets will be
+ A monitor %module is a \ref senf::ppi::module::Module "module" which needs information
+ about traversing packets but does not really act on the packets. Because of this, it is
+ \e optional to connect the output: If the output is not connected, the packets will be
silently dropped.
This allows to add monitor modules either into an existing chain or add them using an
- ActiveDuplicator.
+ ActiveDuplicator.
To write a monitor %module, derive from senf::ppi::module::MonitorModule instead of
senf::ppi::module and implement v_handlePacket():
void throttle();
void unthrottle();
};
-
+
}}}
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////cc.p////////////////////////////////////////
namespace {
-
+
class PacketCounter : public senf::ppi::module::MonitorModule<>
{
SENF_PPI_MODULE(PacketCounter);
senf::ppi::module::debug::ActiveSource source;
senf::ppi::module::debug::PassiveSink sink;
PacketCounter counter;
-
+
senf::ppi::connect(source, counter);
senf::ppi::connect(counter, sink);
senf::ppi::init();
-
+
senf::Packet p (senf::DataPacket::create());
BOOST_CHECK_EQUAL( counter.count, 0u );
senf::ppi::init();
senf::Packet p (senf::DataPacket::create());
-
+
BOOST_CHECK_EQUAL( counter.count, 0u );
source.submit(p);
BOOST_CHECK_EQUAL( counter.count, 1u );
senf::ppi::init();
senf::Packet p (senf::DataPacket::create());
-
+
BOOST_CHECK_EQUAL( counter.count, 0u );
source.submit(p);
BOOST_CHECK_EQUAL( counter.count, 1u );
BOOST_CHECK( source );
source.submit(p);
BOOST_CHECK_EQUAL( counter.count, 3u );
-
+
}
///////////////////////////////cc.e////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace senf {
namespace ppi {
-
+
#ifdef DOXYGEN
// For exposition only.
template <class MultiConnectorSource, class Target, class A1>
MultiConnectorSource::ConnectorType & connect(
MultiConnectorSource & source, A1 const & a1, Target & target);
-
+
/** \brief Connect arbitrary source to MultiConnector target
Additional implementations with 0..SENF_MULTI_CONNECTOR_MAX_ARGS arguments.
This mixin provides a module with support for a runtime configurable number of input or
output connectors.
\code
- class MyModule
+ class MyModule
: public senf::ppi::module::Module,
public senf::ppi::module::MultiConnectorMixin<
MyModule, senf::ppi::connector::ActiveInput<> >
route(input, output);
input.onThrottle(&MyModule::doThrottle);
}
-
+
// Optional
void connectorDestroy(senf::ppi::connector::ActiveInput const & input)
{
}
void doThrottle()
- {
+ {
// ...
}
allocate a new connector
\code
MyModule muModule;
-
+
senf::ppi::connect(someModule, myModule);
\endcode
Some modules will expect additional arguments to be passed (see below)
Implementing \c connectorDestroy now is \e mandatory. The signature is changed to take a
pointer as argument
\code
- class MyModule
+ class MyModule
: public senf::ppi::module::Module,
public senf::ppi::module::MultiConnectorMixin<
MyModule, senf::ppi::connector::ActiveInput<>, void, void >
successfully, otherwise your code will break.
*/
- template <class Self_,
- class ConnectorType_,
- class KeyType_=void,
+ template <class Self_,
+ class ConnectorType_,
+ class KeyType_=void,
class ContainerType_=typename detail::MultiConnectorDefaultContainer<
KeyType_,ConnectorType_>::type>
- class MultiConnectorMixin
+ class MultiConnectorMixin
: private detail::MultiConnectorSelectBase<ConnectorType_>::type
{
public:
friend class detail::MultiConnectorMixinAccess;
friend class detail::MultiConnectorWrapper<Self_,ConnectorType_>;
-
+
ContainerType_ connectors_;
};
{
public:
typedef ConnectorType_ ConnectorType;
-
+
protected:
typedef ContainerType_ ContainerType;
# include BOOST_PP_ITERATE()
void disconnected(ConnectorType_ const & c);
-
+
friend class detail::MultiConnectorMixinAccess;
friend class detail::MultiConnectorWrapper<Self_,ConnectorType_>;
ContainerType_ connectors_;
};
- template <class Self_,
+ template <class Self_,
class ConnectorType_>
class MultiConnectorMixin<Self_,ConnectorType_,void,void>
: private detail::MultiConnectorSelectBase<ConnectorType_>::type
};
#endif
-
+
}}}
///////////////////////////////hh.e////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
};
template <class KeyType, class ConnectorType>
- struct MultiConnectorDefaultContainer
- {
- typedef boost::ptr_map<KeyType, ConnectorType> type;
+ struct MultiConnectorDefaultContainer
+ {
+ typedef boost::ptr_map<KeyType, ConnectorType> type;
};
template <class Module, class Connector>
#ifndef DOXYGEN
template <class ConnectorType>
- struct MultiConnectorDefaultContainer<void,ConnectorType>
- {
+ struct MultiConnectorDefaultContainer<void,ConnectorType>
+ {
typedef boost::ptr_vector<ConnectorType> type;
};
template <class ConnectorType>
struct MultiConnectorSelectBase
- : public boost::mpl::if_<
+ : public boost::mpl::if_<
boost::is_base_of<connector::InputConnector, ConnectorType>,
ppi::detail::DisableStandardInput, ppi::detail::DisableStandardOutput >
{};
template <class T> senf::mpl::rv<0> isMulticonnector(...);
template <class T> senf::mpl::rv<1> isMulticonnector(
- typename boost::enable_if<boost::is_base_of<connector::OutputConnector,
- typename T::ConnectorType>,
+ typename boost::enable_if<boost::is_base_of<connector::OutputConnector,
+ typename T::ConnectorType>,
int>::type);
template <class T> senf::mpl::rv<2> isMulticonnector(
- typename boost::enable_if<boost::is_base_of<connector::InputConnector,
- typename T::ConnectorType>,
+ typename boost::enable_if<boost::is_base_of<connector::InputConnector,
+ typename T::ConnectorType>,
int>::type);
template <class T, unsigned N>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// Custom includes
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/control/if.hpp>
-#include <boost/preprocessor/facilities/empty.hpp>
+#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
-#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
// senf::ppi::module::detail::MultiConnectorMixinAccess member declaration 1..MAX_ARGS
template <class Module mpp_TplParamsKomma()>
-static typename Module::ConnectorType &
+static typename Module::ConnectorType &
newConnector(Module & module mpp_FnParamsKomma());
// ////////////////////////////////////////////////////////////////////////
// senf::ppi::module::detail::MultiConnectorMixinAccess members
template <class Module mpp_TplParamsKomma()>
-typename Module::ConnectorType &
+typename Module::ConnectorType &
senf::ppi::module::detail::MultiConnectorMixinAccess::newConnector(
Module & module mpp_FnParamsKomma())
{
#undef mpp_TplParamsKomma
#undef mpp_TplParams_
#undef mpp_TplParams
-
+
// ////////////////////////////////////////////////////////////////////////
/*
(save-excursion (re-search-backward "^// Undefine local Macros")
(forward-line 1) (delete-region (point) (progn (search-forward
"// ////") (forward-line -1) (point))) (insert "\n") (let ((b (point))
- (e (progn (insert (save-excursion (re-search-backward
+ (e (progn (insert (save-excursion (re-search-backward
"^// Local Macros") (search-forward "#define") (beginning-of-line)
(buffer-substring (point) (progn (search-forward "// ////")
(search-backward "#define") (forward-line 1) (point))))) (point))))
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
UserContainerModule()
{
- noroute(input);
+ noroute(input);
input.onRequest(&UserContainerModule::request);
}
void connectorDestroy(ConnectorType const * c)
{
Connectors::iterator i (
- std::find_if(connectors_.begin(), connectors_.end(),
+ std::find_if(connectors_.begin(), connectors_.end(),
boost::bind(&Connectors::value_type::get,_1) == c));
if (i != connectors_.end())
connectors_.erase(i);
}
Connectors connectors_;
-
+
friend class module::MultiConnectorMixin<UserContainerModule, connector::ActiveOutput<>, void, void>;
};
-
+
struct IntAnnotation {
int value;
bool operator<(IntAnnotation const & other) const { return value < other.value; }
module::PassiveJoin join2;
module::AnnotationRouter<IntAnnotation> router;
UserContainerModule module;
-
+
ppi::connect(source, join1);
ppi::connect(join1, router);
ppi::connect(router, 1, join2);
ppi::connect(join2, module);
ppi::connect(module, sink);
-
+
senf::Packet p (senf::DataPacket::create());
p.annotation<IntAnnotation>().value = 1;
prefix_ void senf::ppi::ThresholdQueueing::update(connector::GenericPassiveInput & input, Event event)
{
switch (event) {
- case ENQUEUE:
+ case ENQUEUE:
if (input.queueSize() >= high_)
input.throttle();
break;
virtual ~QueueingDiscipline();
enum Event { ENQUEUE, DEQUEUE }; ///< Possible queueing events
-
+
virtual void update(connector::GenericPassiveInput & input, Event event) = 0;
///< Calculate new queueing state
/**< Whenever the queue is manipulated, this member is
called to calculate the new throttling state. The
member must call \a input's \c throttle() or \c
unthrottle() member to set the new throttling state.
-
+
\param[in] input Connector holding the queue
\param[in] event Type of event triggering the update */
};
The ThresholdQueueing QueueingDiscipline is a simple queueing discipline which throttles the
input as soon the number of packets in the queue reaches the \a high threshold. The input
- will be unthrottled when the number of packets drops to the \a low threshold.
+ will be unthrottled when the number of packets drops to the \a low threshold.
The default queueing discipline is ThresholdQueueing(1,0).
*/
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
prefix_ void senf::ppi::module::RateAnalyzer::startStatistics(senf::ClockService::clock_type interval)
{
timer_.interval(interval);
- factor_ = double(senf::ClockService::in_nanoseconds(interval)) /
+ factor_ = double(senf::ClockService::in_nanoseconds(interval)) /
double(senf::ClockService::in_nanoseconds(
senf::ClockService::seconds(1)));
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
senf::RateAnalyzer analyzer;
senf::Statistics packets;
senf::Statistics packetSize;
-
+
analyzer.signals.packetsPerSecond.connect(packets);
analyzer.signals.bytesPerPacket.connect(packetSize);
///\{
RateAnalyzer();
-
+
///\}
///////////////////////////////////////////////////////////////////////////
// Statistics signals
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////cc.p////////////////////////////////////////
namespace {
-
+
unsigned calls (0u);
float ppss[] = { 13.333333f, 20.f, 13.333333f, 20.f, 13.333333f, 20.f };
if (calls >= sizeof(ppss) / sizeof(ppss[0]))
senf::scheduler::terminate();
}
-
+
void collectBPS(float bytesPerSecond)
{
bps += bytesPerSecond;
senf::ppi::connect(filter, analyzer);
senf::ppi::run();
-
+
BOOST_CHECK_EQUAL( calls, 6u );
pps /= calls;
///////////////////////////////cc.p////////////////////////////////////////
senf::ppi::module::RateFilter::RateFilter(senf::ClockService::clock_type interval)
- : timer_(interval)
+ : timer_(interval)
{
route(input, timer_);
route(timer_, output);
RateFilter(senf::ClockService::clock_type interval);
void interval(senf::ClockService::clock_type interval);
senf::ClockService::clock_type interval() const;
-
+
connector::ActiveInput<> input;
connector::ActiveOutput<> output;
module::RateFilter rateFilter ( senf::ClockService::milliseconds(100) );
debug::PassiveSource source;
debug::PassiveSink sink;
-
+
ppi::connect(source, rateFilter);
ppi::connect(rateFilter, sink);
-
+
std::string data ("TEST");
senf::Packet p (senf::DataPacket::create(data));
for (int i=0; i<10; i++)
- source.submit(p);
-
+ source.submit(p);
+
senf::scheduler::TimerEvent timer (
"rateFilter test timer", &timeout,
senf::ClockService::now() + senf::ClockService::milliseconds(250));
-
+
senf::ppi::run();
BOOST_CHECK_EQUAL( rateFilter.interval(), senf::ClockService::milliseconds(100) );
module::RateFilter rateFilter ( senf::ClockService::milliseconds(100) );
debug::PassiveSource source;
debug::PassiveSink sink;
-
+
ppi::connect(source, rateFilter);
ppi::connect(rateFilter, sink);
-
+
std::string data ("TEST");
senf::Packet p (senf::DataPacket::create(data));
for (int i=0; i<10; i++)
- source.submit(p);
-
+ source.submit(p);
+
senf::scheduler::TimerEvent timeoutTimer (
"rateFilter test timer", &timeout,
senf::ClockService::now() + senf::ClockService::milliseconds(675));
-
+
RateFilter_IntervalChanger intervalChanger (rateFilter);
- senf::scheduler::TimerEvent timer ( "RateFilter_IntervalChanger timer",
+ senf::scheduler::TimerEvent timer ( "RateFilter_IntervalChanger timer",
senf::membind(&RateFilter_IntervalChanger::changeInterval, intervalChanger),
senf::ClockService::now() + senf::ClockService::milliseconds(250));
-
+
senf::ppi::run();
BOOST_CHECK_EQUAL( rateFilter.interval(), senf::ClockService::milliseconds(200) );
forwarded from active to passive connectors. This may
be disabled by setting the authoThrottling state to \c
false.
-
+
Routing from/to an event to/from a passive connector
will automatically create throttling notifications on
the connector whenever the event is disabled. Routing
/**< This member checks only the automatic throttling
state. If autoThrottling() is \c false, this member
will always return \c false. */
-
+
protected:
ForwardingRoute(module::Module & module);
namespace ppi {
/** \brief Route descriptor
-
+
Route instances are created by Module::route statements. The Route class provides an
interface to manipulate the flow processing.
private:
typedef detail::RouteImplementation<Source,Target> Base;
typedef detail::RouteImplementation<Source,Target> Implementation;
-
+
Route(module::Module & module, Source & source, Target & target);
friend class module::Module;
struct RoutingTraitsImplementation
{
BOOST_STATIC_ASSERT((boost::is_base_of<connector::Connector, Connector>::value));
-
+
static bool const event = false;
static bool const notifySource = boost::is_base_of<
connector::InputConnector, Connector>::value;
static bool const dataTarget = boost::is_base_of<
connector::OutputConnector, Connector>::value;
-
+
typedef Connector type;
};
// for Events
template <class Object>
struct RoutingTraits
- : public RoutingTraitsImplementation<Object,
+ : public RoutingTraitsImplementation<Object,
boost::is_convertible<Object*,
EventDescriptor*>::value>
{};
- // This is the generic route implementation for all routes. It just provides access to the
+ // This is the generic route implementation for all routes. It just provides access to the
// source and target.
template <class Source, class Target, class Base>
class BaseRouteImplementation
: public BaseRouteImplementation<Source, Target, ForwardingRoute>
{
typedef BaseRouteImplementation<Source, Target, ForwardingRoute> Base;
-
+
protected:
ForwardingRouteImplementation(module::Module & module, Source & source, Target & target);
~ForwardingRouteImplementation();
};
// This helper class finds the base-class suitable for a specific route. Routes are classified
- // into two groups:
+ // into two groups:
// 1) A forwarding routes is a routed which forwards notifications from a notifySource to a
// notifyTarget. Forwarding routes are implemneted using ForwardingRouteImplementation
// 2) Non-forwarding routes don't forward notifications. They are implemented directly
static bool const isForwarding = (srcTrait::notifySource && trgTrait::notifyTarget)
|| (srcTrait::notifyTarget && trgTrait::notifySource);
-
+
typedef typename boost::mpl::if_c<
- isForwarding,
- ForwardingRouteImplementation<Source,Target>,
+ isForwarding,
+ ForwardingRouteImplementation<Source,Target>,
BaseRouteImplementation<Source,Target,RouteBase> >::type base;
};
- // RouteImplementation2 has two purposes:
+ // RouteImplementation2 has two purposes:
// 1) Ensure, that routing is always from a data source to a data target
// 2) To find the correct base-class. This is delegated to RouteImplementationBase
template <class Source, class Target>
{
typedef typename RouteImplementationBase<Source,Target>::base Base;
- BOOST_STATIC_ASSERT( RoutingTraits<Source>::dataSource &&
+ BOOST_STATIC_ASSERT( RoutingTraits<Source>::dataSource &&
RoutingTraits<Target>::dataTarget );
protected:
ppi::DebugEvent event;
ppi::ForwardingRoute * rt;
-
+
RouteTester() : events(0), throttles(0) {
route( activeIn, activeOut ); // non-forwarding
rt = & route( activeIn, passiveOut ); // forward throttling
void throttleRequest() {
++ throttles;
}
-
+
void unthrottleRequest() {
-- throttles;
}
passiveSink.input.unthrottle();
BOOST_CHECK( activeSource );
BOOST_CHECK( tester.event.enabled() );
-
+
// Now throttle the passive source by exhausting the queue
-
+
BOOST_CHECK( p1 == activeSink.request() );
BOOST_CHECK( passiveSource.output.throttled() );
BOOST_CHECK( ! tester.activeIn );
BOOST_CHECK( tester.passiveOut.throttled() );
BOOST_CHECK( ! activeSink );
BOOST_CHECK( ! tester.event.enabled() );
-
+
passiveSource.submit(p1);
BOOST_CHECK( activeSink );
BOOST_CHECK( tester.event.enabled() );
void timeout() {
senf::scheduler::terminate();
}
-
+
// just a helper class for the test
struct ModuleConnector {
module::PriorityJoin & join_;
}
boost::scoped_ptr<module::PassiveQueue> queue;
};
-
+
class TestSink : public module::Module
{
SENF_PPI_MODULE(TestSink);
module::ActiveFeeder feeder;
module::PriorityJoin join;
module::CloneSource source1 (senf::DataPacket::create());
-
+
ppi::connect( source1, join);
ppi::connect( join, feeder);
ppi::connect( feeder, sink);
-
+
ModuleConnector moduleConnector ( join);
- senf::scheduler::TimerEvent timer (
+ senf::scheduler::TimerEvent timer (
"connect_runtime timer",
senf::membind(&ModuleConnector::connect, &moduleConnector),
senf::ClockService::now() + senf::ClockService::milliseconds(250));
-
+
senf::scheduler::TimerEvent timeoutTimer (
"connect_runtime test timeoutTimer", &timeout,
senf::ClockService::now() + senf::ClockService::milliseconds(500));
-
+
senf::ppi::run();
-
+
BOOST_CHECK( true );
}
namespace senf {
namespace ppi {
-namespace detail {
+namespace detail {
struct DisableStandardInput {};
struct DisableStandardOutput {};
struct DisableStandardConnect : public DisableStandardInput, public DisableStandardOutput {};
\throws connector::IncompatibleConnectorsException if the two connectors are not type
compatible.
-
+
\see \ref ppi_connections
*/
void connect(connector::OutputConnector & source, connector::InputConnector & target, ...);
#endif
-#ifndef DOXYGEN
+#ifndef DOXYGEN
template <class T, class C>
void connect(T & source, C & target,
typename boost::disable_if< boost::is_base_of<detail::DisableStandardInput, T2> >:: type * = 0);
#endif
-
+
/** \brief Start the network
Calling senf::ppi::run() will start processing the network. The main event loop is managed
void run();
/** \brief Manually initialize the network
-
+
For debugging purposes, it is sometimes simpler to not use senf::ppi::run() but instead
drive the network via explicit calls using the debug modules. However, it is still necessary
to initialize the network. This operation is performed by senf::ppi::init().
protocolId_ = dest.port();
}
-prefix_ void senf::ppi::IPv4SourceForcingDgramWriter::operator()(Handle handle,
+prefix_ void senf::ppi::IPv4SourceForcingDgramWriter::operator()(Handle handle,
Packet const & packet)
{
sendtoandfrom(
protocolId_ = dest.port();
}
-prefix_ void senf::ppi::IPv6SourceForcingDgramWriter::operator()(Handle handle,
+prefix_ void senf::ppi::IPv6SourceForcingDgramWriter::operator()(Handle handle,
Packet const & packet)
{
sendtoandfrom(
///////////////////////////////////////////////////////////////////////////
// senf::ppi::ConnectedDgramWriter
-prefix_ void senf::ppi::ConnectedDgramWriter::operator()(Handle handle,
+prefix_ void senf::ppi::ConnectedDgramWriter::operator()(Handle handle,
Packet const & packet)
{
handle.write(packet.data());
This read helper will read a datagram from a datagram socket. This datagram will then be
interpreted as a packet of type \a Packet as defined in the packet library. \a Packet
- defaults to DataPacket (type DataPacketType), which will place the data uninterpreted
+ defaults to DataPacket (type DataPacketType), which will place the data uninterpreted
into a packet data structure.
*/
template <class Packet=DataPacket, unsigned MaxSize=0u>
\ingroup io_modules
*/
template <class Reader=DgramReader<> >
- class ActiveSocketSource
+ class ActiveSocketSource
: public Module
{
SENF_PPI_MODULE(ActiveSocketSource);
public:
typedef typename Reader::Handle Handle; ///< Handle type requested by the reader
- connector::ActiveOutput<typename Reader::PacketType> output;
+ connector::ActiveOutput<typename Reader::PacketType> output;
///< Output connector to which the data received is written
-
+
ActiveSocketSource(); ///< Create non-connected reader
/**< The reader will be disabled until a socket is set
\pre Requires \a Reader to be default constructible */
void handle(Handle handle); ///< Set handle
/**< Assigning an empty or in-valid() handle will disable
the module until a new, valid handle is assigned. */
-
+
private:
void read();
-
+
Handle handle_;
IOEvent event_;
Reader reader_;
BOOST_REQUIRE( ! sink.empty() );
BOOST_CHECK_EQUAL( sink.front().data().size(), data.size() );
- BOOST_CHECK( std::equal( sink.front().data().begin(), sink.front().data().end(),
+ BOOST_CHECK( std::equal( sink.front().data().begin(), sink.front().data().end(),
data.begin()) );
}
{
SENF_PPI_MODULE(ThrottleBarrier);
public:
-
+
connector::PassiveInput<> input;
connector::ActiveOutput<> output;
struct Callback
{
typedef boost::function<void (Arg)> type;
-
+
template <class Owner, class FnClass>
static type make(void (FnClass::* memfn )(), Owner & owner);
template <class Owner, class FnClass, class FnArg>
struct Callback<void>
{
typedef boost::function<void ()> type;
-
+
template <class Owner, class FnClass>
static type make(void (FnClass::* memfn )(), Owner & owner);
template <class Owner>
EventManager & manager() const;
module::Module & module() const;
-
+
protected:
- EventBindingBase(EventManager & manager, module::Module & module,
+ EventBindingBase(EventManager & manager, module::Module & module,
EventDescriptor & descriptor);
void eventTime(ClockService::clock_type time);
void callback(EventArg event, ClockService::clock_type time);
void callback(EventArg event);
-
+
private:
Self & self();
};
public:
void callback(ClockService::clock_type time);
void callback();
-
+
private:
Self & self();
};
/** \brief Internal: Association Event - Module - Handler, event type specific */
template <class EventType>
class EventBinding
- : public EventBindingBase,
+ : public EventBindingBase,
public EventBindingHelper<EventType, EventBinding<EventType> >
{
public:
#endif
- namespace module {
- class Module;
+ namespace module {
+ class Module;
namespace detail {
template <class Source, class Target> class RouteHelper;
}
// $Id$
//
-// Copyright (C) 2007
+// Copyright (C) 2007
// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
// Stefan Bund <g0dil@berlios.de>
SENF_PACKET_TLV_REGISTRY_REGISTER( senf::WLANSupportedRatesInfoElementParser );
-prefix_ void senf::WLANPowerConstraintInfoElementParser::dump(std::ostream & os)
+prefix_ void senf::WLANPowerConstraintInfoElementParser::dump(std::ostream & os)
const
{
os << " WLAN PowerConstraint Information Element\n"
<< " value: " << unsigned(value()) << "\n";
}
-prefix_ void senf::WLANSSIDInfoElementParser::dump(std::ostream & os)
+prefix_ void senf::WLANSSIDInfoElementParser::dump(std::ostream & os)
const
{
os << " WLAN SSID Information Element\n"
<< " value: " << value() << "\n";
}
-prefix_ void senf::WLANSupportedRatesInfoElementParser::dump(std::ostream & os)
+prefix_ void senf::WLANSupportedRatesInfoElementParser::dump(std::ostream & os)
const
{
os << " WLAN SupportedRates Information Element\n"
SENF_PARSER_FIELD ( type, UInt8Parser );
SENF_PARSER_FIELD ( length, UInt8Parser );
SENF_PARSER_FINALIZE ( WLANInfoElementParser );
-
+
typedef GenericTLVParserRegistry<WLANInfoElementParser> Registry;
};
typedef GenericTLVParserBase<WLANInfoElementParser> WLANGenericInfoElementParser;
-
+
struct WLANSSIDInfoElementParser
: public WLANInfoElementParser
{
SENF_PARSER_GOTO ( length );
SENF_PARSER_FIELD ( value, StringParser<UInt8Parser> );
SENF_PARSER_FINALIZE ( WLANSSIDInfoElementParser );
-
+
SENF_PARSER_INIT() {
type() = typeId;
- }
+ }
static const type_t::value_type typeId = 0x00u;
-
+
void dump(std::ostream & os) const;
};
-
+
struct WLANSupportedRatesInfoElementParser
: public WLANInfoElementParser
{
# include SENF_PARSER()
SENF_PARSER_INHERIT ( WLANInfoElementParser );
- // we just skip the value here. If somebody needs the information he has to implement
- // this strange information element hisself.
+ // we just skip the value here. If somebody needs the information he has to implement
+ // this strange information element hisself.
SENF_PARSER_SKIP ( length(), 0 );
SENF_PARSER_FINALIZE ( WLANSupportedRatesInfoElementParser );
-
+
SENF_PARSER_INIT() {
type() = typeId;
- }
+ }
static const type_t::value_type typeId = 0x01u;
-
+
void dump(std::ostream & os) const;
};
-
+
struct WLANPowerConstraintInfoElementParser
: public WLANInfoElementParser
{
SENF_PARSER_INHERIT ( WLANInfoElementParser );
SENF_PARSER_FIELD ( value, UInt8Parser );
SENF_PARSER_FINALIZE ( WLANPowerConstraintInfoElementParser );
-
+
SENF_PARSER_INIT() {
type() = typeId;
length() = 1;
- }
+ }
static const type_t::value_type typeId = 0x20u;
-
+
void dump(std::ostream & os) const;
};
}
DUMP_OPTIONAL_FIELD( fhss, unsigned, "FHSS" );
DUMP_OPTIONAL_FIELD( dbmAntennaSignal, signed, "antenna signal (dBm)" );
DUMP_OPTIONAL_FIELD( dbmAntennaNoise, signed, "antenna noise (dBm)" );
- DUMP_OPTIONAL_FIELD( lockQuality, unsigned, "lock quality" );
+ DUMP_OPTIONAL_FIELD( lockQuality, unsigned, "lock quality" );
DUMP_OPTIONAL_FIELD( txAttenuation, unsigned, "tx attenuation" );
DUMP_OPTIONAL_FIELD( dbTxAttenuation, unsigned, "tx attenuation (dB)" );
DUMP_OPTIONAL_FIELD( dbmTxAttenuation, signed, "tx attenuation (dBm)" );
{
size_type h (senf::bytes(p.parser()));
size_type t (p->flagsPresent() && p->flags().fcsAtEnd() ? 4 : 0);
- return p.size() < h+t
- ? no_range()
+ return p.size() < h+t
+ ? no_range()
: optional_range( range(p.data().begin() + h, p.data().end() - t) );
}
\par Fields:
\ref RadiotapPacketParser
\image html RadiotapPacket.png
-
+
\see http://www.radiotap.org/
-
+
\ingroup protocolbundle_80211
*/
struct RadiotapPacketType
0x00 ,0x00 ,0x1a ,0x00, 0x6f, 0x18, 0x00, 0x00,
0x02, 0xe6, 0x8a, 0xdf, 0x12, 0x00, 0x00, 0x00,
0x12, 0x0c, 0xc8, 0x14, 0x40, 0x01, 0xc3, 0xa0,
- 0x02, 0x23,
+ 0x02, 0x23,
0x00, 0x00, 0x00, 0x00,
};
senf::RadiotapPacket p (senf::RadiotapPacket::create(data));
{
/* radiotap packet from ath9k with atheros card*/
unsigned char data[] = {
- 0x00, 0x00, 0x20, 0x00, 0x6f, 0x48, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x6f, 0x48, 0x00, 0x00,
0x87, 0xbb, 0x91, 0x7c, 0x3b, 0x00, 0x00, 0x00,
0x00, 0x04, 0x85, 0x09, 0x80, 0x04, 0xb2, 0xa1,
0x00, 0x00, 0x00, 0x00, 0xd5, 0x1a, 0xf7, 0x94,
prefix_ void senf::WLANBeaconPacketType::dump(packet p, std::ostream &os)
{
- boost::io::ios_all_saver ias(os);
+ boost::io::ios_all_saver ias(os);
os << "WLAN beacon frame:\n"
<< senf::fieldName("timestamp") << unsigned( p->timestamp()) << "\n"
<< senf::fieldName("beaconInterval") << unsigned( p->beaconInterval()) << "\n";
SENF_PARSER_FIELD( ssidIE, WLANSSIDInfoElementParser );
WLANSSIDInfoElementParser::value_t ssid() const { return ssidIE().value(); }
-
+
SENF_PARSER_FIELD( supportedRatesIE, WLANSupportedRatesInfoElementParser );
-
+
SENF_PARSER_LIST ( ieList, packetSize(), WLANGenericInfoElementParser );
-
+
SENF_PARSER_FINALIZE( WLANBeaconPacketParser );
};
-
+
/** \brief WLAN Beacon frame packet
\par Packet type (typedef):
BOOST_CHECK_EQUAL( p->ssidIE().length(), 5);
BOOST_CHECK_EQUAL( p->ssidIE().value().value(), "boxC1");
BOOST_CHECK_EQUAL( p->ssid().value(), "boxC1");
-
+
typedef senf::WLANBeaconPacket::Parser::ieList_t::container ieListContainer_t;
ieListContainer_t ieListContainer (p->ieList());
BOOST_CHECK_EQUAL( ieListContainer.size(), 5);
-
+
ieListContainer_t::iterator i ( ieListContainer.begin());
BOOST_CHECK_EQUAL( i->type(), 0x03); //DS parameter set
++i;
BOOST_CHECK_EQUAL( i->type(), 0xdd); //vendor specific
BOOST_CHECK_EQUAL( i->length(), 0x18);
BOOST_CHECK_EQUAL( boost::size(i->value()), 0x18);
-
+
unsigned char value[] = {
0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x88, 0x00,
0x02, 0xa3, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00,
};
SENF_CHECK_EQUAL_COLLECTIONS( value, value+sizeof(value),
boost::begin(i->value()), boost::end(i->value()) );
-
+
std::ostringstream oss (std::ostringstream::out);
SENF_CHECK_NO_THROW( p.dump( oss ));
}
p->timestamp() << 0x0000009C4CAA303AuLL;
p->beaconInterval() << 100u;
p->ssidIE().value() << "boxC1";
-
+
typedef senf::WLANBeaconPacket::Parser::ieList_t::container ieListContainer_t;
ieListContainer_t ieListContainer (p->ieList());
senf::WLANPowerConstraintInfoElementParser ie (
ieListContainer.push_back_space().init<senf::WLANPowerConstraintInfoElementParser>() );
- ie.value() << 0x42;
-
+ ie.value() << 0x42;
+
p.finalizeThis();
-
+
unsigned char data[] = {
0x3a, 0x30, 0xaa, 0x4c, 0x9c, 0x00, 0x00, 0x00, //timestamp
0x64, 0x00, //beacon interval
if ( p.order() ) os << " order";
if ( !(p.toDS() || p.fromDS() || p.moreFrag() || p.retry() || p.pwrMgt() ||
- p.moreData() || p.protectedFrame() || p.order()) )
+ p.moreData() || p.protectedFrame() || p.order()) )
os << " none";
os << "\n"
<< " duration : " << unsigned(p.duration()) << "\n";
{
switch (dsBits()) {
case 0 :
- case 2 :
+ case 2 :
return addr1();
- default:
+ default:
return addr3();
}
}
return addr2();
// TODO wds frames
// case 3 : return addr4();
- default:
+ default:
return addr3();
}
}
boost::uint16_t sequenceNumber() const {
return (uint16_t)(seqNumber_2()) << 4 | seqNumber_1();
};
-
+
void sequenceNumber(boost::uint16_t sn);
};
boost::uint16_t sequenceNumber() const {
return (uint16_t)(seqNumber_2()) << 4 | seqNumber_1();
};
-
+
void sequenceNumber(boost::uint16_t sn);
// TODO fourth address field in case of WDS
using mixin::initSize;
using mixin::nextPacketRange;
- static factory_t nextPacketType(packet p) {
- return p->subtype() == 0 || p->subtype() == 8
- ? LlcSnapPacket::factory()
+ static factory_t nextPacketType(packet p) {
+ return p->subtype() == 0 || p->subtype() == 8
+ ? LlcSnapPacket::factory()
: no_factory();
}
SENF_CHECK_NO_THROW( p->bssid() = senf::MACAddress::from_string("00:1a:4d:3e:c7:5c") );
SENF_CHECK_NO_THROW(p->sequenceNumber(4095u));
-
+
BOOST_CHECK_EQUAL( p->type(), 2u );
BOOST_CHECK_EQUAL( p->sequenceNumber(), 4095u );
}
0xa3, 0x40, 0x00, 0x27, 0xa4, 0x00, 0x00, 0x42,
0x43, 0x5e, 0x00, 0x62, 0x32, 0x2f, 0x00, 0xa0,
0x00, 0xdd, 0x09, 0x00, 0x03, 0x7f, 0x01, 0x01,
- 0x00, 0x24, 0xff, 0x7f,
+ 0x00, 0x24, 0xff, 0x7f,
};
senf::WLANPacket_MgtFrame p (senf::WLANPacket_MgtFrame::create(data));
SENF_AUTO_UNIT_TEST(WLANPacket_ctrlFrame_packet)
{
unsigned char data[] = {
- 0xd4, 0x00, 0x00, 0x00,
- 0x00, 0x0b, 0x6b, 0x57, 0x06, 0xb0,
+ 0xd4, 0x00, 0x00, 0x00,
+ 0x00, 0x0b, 0x6b, 0x57, 0x06, 0xb0,
0x4f, 0xda, // What is this ?
};
senf::WLANPacket_CtrlFrame p (senf::WLANPacket_CtrlFrame::create()) ;
p->receiverAddress() = senf::MACAddress::from_string("00:1a:4d:3e:c7:5c");
p->set_ack();
-
+
BOOST_CHECK_EQUAL( p->type(), 1u);
BOOST_CHECK_EQUAL( p->subtype(), 13u);
}
<< senf::fieldName(" more fragments") << p->moreFragment() << "\n"
<< senf::fieldName(" fragment number") << p->fragmentNr() << "\n"
<< senf::fieldName(" message ID (MID)") << unsigned( p->messageId()) << "\n"
- << senf::fieldName(" sid") << unsigned( p->sid()) << "\n"
+ << senf::fieldName(" sid") << unsigned( p->sid()) << "\n"
<< senf::fieldName(" opcode") << unsigned( p->opcode()) << "\n"
- << senf::fieldName(" aid") << unsigned( p->aid()) << "\n"
+ << senf::fieldName(" aid") << unsigned( p->aid()) << "\n"
<< senf::fieldName(" transaction id") << unsigned( p->transactionId()) << "\n"
<< senf::fieldName(" payload length") << unsigned( p->payloadLength()) << "\n";
p->src_mihfId().dump( os);
# define SENF_MIH_PACKET_REGISTRY_REGISTER( packet ) \
SENF_PACKET_REGISTRY_REGISTER( \
senf::MIHMessageRegistry, packet::type::MESSAGE_ID, packet )
-
-
+
+
/** \brief Parse a MIH packet
Parser implementing the MIH header. The fields implemented are:
SENF_PARSER_BITFIELD ( sid, 4, unsigned );
SENF_PARSER_BITFIELD ( opcode, 2, unsigned );
SENF_PARSER_BITFIELD ( aid, 10, unsigned );
-
+
SENF_PARSER_SKIP_BITS ( 4 );
SENF_PARSER_BITFIELD ( transactionId, 12, unsigned );
SENF_PARSER_FIELD_RO ( payloadLength, UInt16Parser );
-
+
SENF_PARSER_GOTO_OFFSET( 8, 8); // just to limit the offset calculation
-
+
// Source MIHF Id
SENF_PARSER_FIELD ( src_mihfId, MIHFSrcIdTLVParser );
// Destination MIHF Id
mihPacket->sid() = 4;
mihPacket->opcode() = 3;
mihPacket->aid() = 42;
- BOOST_CHECK_EQUAL( mihPacket->messageId(), 0x4c2a );
+ BOOST_CHECK_EQUAL( mihPacket->messageId(), 0x4c2a );
}
SENF_AUTO_UNIT_TEST(MIHPacket_create_eth)
mihPacket->src_mihfId().value( "senf@berlios.de");
mihPacket->dst_mihfId().value( "test");
mihPacket.finalizeThis();
-
+
unsigned char data[] = {
// MIH header
0x10, 0x54, 0x00, 0x00, 0x00, 0x15, 0x00, 0x19,
mihPacket->dst_mihfId().maxIdLength(128);
mihPacket->dst_mihfId().value( std::string(128, 'x'));
mihPacket.finalizeThis();
- // packet size is now MIH header (8 bytes) + src MIHIFId TLV (18 bytes) +
- // dst MIHIFId TLV (1 byte type + 2 byte TLV length + 1 byte id length + 128 id value)
- BOOST_CHECK_EQUAL( mihPacket.size(), unsigned(8 + 18 + 1+2+1+128));
+ // packet size is now MIH header (8 bytes) + src MIHIFId TLV (18 bytes) +
+ // dst MIHIFId TLV (1 byte type + 2 byte TLV length + 1 byte id length + 128 id value)
+ BOOST_CHECK_EQUAL( mihPacket.size(), unsigned(8 + 18 + 1+2+1+128));
BOOST_CHECK_EQUAL( mihPacket->payloadLength(), 18 + 1+2+1+128);
BOOST_CHECK_EQUAL( mihPacket->dst_mihfId().length(), 1+128);
BOOST_CHECK_EQUAL( senf::bytes(mihPacket->dst_mihfId()), 1+2+1+128);
mihPacket->dst_mihfId().maxIdLength(129);
mihPacket->dst_mihfId().value( std::string(129, 'x'));
mihPacket.finalizeThis();
- // packet size is now MIH header (8 bytes) + src MIHIFId TLV (18 bytes) +
- // dst MIHIFId TLV (1 byte type + 2 byte TLV length + 2 byte id length + 128 id value)
- BOOST_CHECK_EQUAL( mihPacket.size(), unsigned(8 + 18 + 1+2+2+129));
+ // packet size is now MIH header (8 bytes) + src MIHIFId TLV (18 bytes) +
+ // dst MIHIFId TLV (1 byte type + 2 byte TLV length + 2 byte id length + 128 id value)
+ BOOST_CHECK_EQUAL( mihPacket.size(), unsigned(8 + 18 + 1+2+2+129));
BOOST_CHECK_EQUAL( mihPacket->payloadLength(), 18 + 1+2+2+129);
BOOST_CHECK_EQUAL( mihPacket->dst_mihfId().length(), 2+129);
BOOST_CHECK_EQUAL( senf::bytes(mihPacket->dst_mihfId()), 1+2+2+129);
mihPacket.finalizeThis();
SENF_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data),
mihPacket.data().begin(), mihPacket.data().end() );
-
+
std::ostringstream oss (std::ostringstream::out);
SENF_CHECK_NO_THROW( mihPacket.dump( oss));
}
BOOST_CHECK_EQUAL( tlv2.type(), 0x0c);
BOOST_CHECK_EQUAL( tlv2.length(), 0x04u);
BOOST_CHECK_EQUAL( tlv2.value().size(), 0x04);
-
+
std::ostringstream oss (std::ostringstream::out);
SENF_CHECK_NO_THROW( mihPayload.dump( oss));
}
MIHGenericPayloadPacket mihPayload (MIHGenericPayloadPacket::createAfter(mihPacket));
MIHGenericPayloadPacket::Parser::tlvList_t::container tlvListContainer (
mihPayload->tlvList() );
-
+
unsigned char tlv1_value[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
MIHGenericTLVParser tlv1 ( tlvListContainer.push_back_space());
0x1a, 0x2b, 0x3c, 0x4d // value
};
SENF_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data),
- mihPacket.data().begin(), mihPacket.data().end() );
+ mihPacket.data().begin(), mihPacket.data().end() );
}
///////////////////////////////////////////////////////////////////////////
// MIHFId
prefix_ senf::MIHFId::MIHFId()
- : boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
+ : boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
senf::INet6Address, std::string, senf::EUI64 > ( boost::blank())
{ }
prefix_ senf::MIHFId::MIHFId(senf::MACAddress const & addr)
- : boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
+ : boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
senf::INet6Address, std::string, senf::EUI64 > ( addr)
{ }
prefix_ senf::MIHFId::MIHFId(senf::INet4Address const & addr)
- : boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
+ : boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
senf::INet6Address, std::string, senf::EUI64 > ( addr)
{ }
prefix_ senf::MIHFId::MIHFId(senf::INet6Address const & addr)
- : boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
+ : boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
senf::INet6Address, std::string, senf::EUI64 > ( addr)
{ }
prefix_ senf::MIHFId::MIHFId(std::string const & addr)
- : boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
+ : boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
senf::INet6Address, std::string, senf::EUI64 > ( addr)
{ }
prefix_ senf::MIHFId::MIHFId(senf::EUI64 const & addr)
- : boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
+ : boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
senf::INet6Address, std::string, senf::EUI64 > ( addr)
{ }
}
prefix_ bool senf::MIHFId::operator<(senf::MIHFId const & other)
- const
+ const
{
if (type() != other.type()) return type() < other.type();
return boost::apply_visitor( LessThanVisitor(), *this, other);
namespace senf {
- class MIHFId
- : public boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
+ class MIHFId
+ : public boost::variant< boost::blank, senf::MACAddress, senf::INet4Address,
senf::INet6Address, std::string, senf::EUI64 >,
public boost::less_than_comparable<MIHFId>,
public boost::equality_comparable<MIHFId>
static MIHFId const Multicast; ///< The multicast (empty) MIHF Id
static MIHFId const None; ///< The multicast (empty) MIHF Id
enum Type { Empty, MACAddress, INet4Address, INet6Address, String, EUI64 };
-
+
MIHFId(); ///< Create empty instance.
- MIHFId(senf::MACAddress const & addr); ///< Construct id with given MACAddress
+ MIHFId(senf::MACAddress const & addr); ///< Construct id with given MACAddress
MIHFId(senf::INet4Address const & addr); ///< Construct id with given INet4Address
MIHFId(senf::INet6Address const & addr); ///< Construct id with given INet6Address
MIHFId(std::string const & addr); ///< Construct id with given String
MIHFId(senf::EUI64 const & addr); ///< Construct id with given EUI64
-
+
Type type() const;
bool operator==(MIHFId const & other) const;
- bool operator<(MIHFId const & other) const;
-
+ bool operator<(MIHFId const & other) const;
+
private:
struct GetTypeVisitor : public boost::static_visitor<Type> {
Type operator()(boost::blank const &) const { return Empty; }
const
{
// the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
- if (maxl > 253)
+ if (maxl > 253)
throw std::length_error("maximum length of a MIHF_ID is 253 octets");
protect(), idLength_().capacity( maxl);
maxLength( maxl + senf::bytes(idLength_()));
}
prefix_ senf::safe_data_iterator senf::MIHFIdTLVParser::resizeValueField(
- MIHTLVLengthParser::value_type size)
+ MIHTLVLengthParser::value_type size)
{
MIHTLVLengthParser::value_type current_length ( idLength());
idLength_() << size;
{
size_type str_size (id.size());
// the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
- if (str_size > 253)
+ if (str_size > 253)
throw std::length_error("maximum length of a MIHF_ID is 253 octets");
- safe_data_iterator si = resizeValueField( str_size);
+ safe_data_iterator si = resizeValueField( str_size);
std::copy( id.begin(), id.end(), si);
}
case Success:
os << " (Success)" << std::endl;
return;
- case UnspecifiedFailure:
+ case UnspecifiedFailure:
os << " (Unspecified Failure)" << std::endl;
return;
case Rejected:
///////////////////////////////////////////////////////////////////////////
// senf::MIHTLVLengthParser
-prefix_ senf::MIHTLVLengthParser::value_type senf::MIHTLVLengthParser::value() const
+prefix_ senf::MIHTLVLengthParser::value_type senf::MIHTLVLengthParser::value() const
{
switch (bytes() ) {
case 1:
};
}
-prefix_ void senf::MIHTLVLengthParser::value(value_type const & v)
+prefix_ void senf::MIHTLVLengthParser::value(value_type const & v)
{
switch (bytes() ) {
case 1:
case 4:
return UInt24Parser::max_value + 128;
case 5:
- return UInt32Parser::max_value;
+ return UInt32Parser::max_value;
default:
throw( MIHTLVLengthException());
};
}
-prefix_ senf::MIHTLVLengthParser const & senf::MIHTLVLengthParser::operator= (value_type other)
+prefix_ senf::MIHTLVLengthParser const & senf::MIHTLVLengthParser::operator= (value_type other)
{
value(other);
- return *this;
+ return *this;
}
-prefix_ void senf::MIHTLVLengthParser::init() const
+prefix_ void senf::MIHTLVLengthParser::init() const
{
defaultInit();
extended_length_flag() = false;
///////////////////////////////////////////////////////////////////////////
// MIHTLVLengthParser
-prefix_ senf::MIHTLVLengthParser::size_type senf::MIHTLVLengthParser::bytes() const
+prefix_ senf::MIHTLVLengthParser::size_type senf::MIHTLVLengthParser::bytes() const
{
return 1 + ( length_field()<=128 ? 0 : fixed_length_field());
}
///////////////////////////////////////////////////////////////////////////
// MIHFIdTLVParser
-prefix_ senf::PacketParserBase::data_iterator senf::MIHFIdTLVParser::valueBegin()
+prefix_ senf::PacketParserBase::data_iterator senf::MIHFIdTLVParser::valueBegin()
const
{
return i( idValue_offset());
return EUI64::from_data( getNAIDecodedIterator( valueBegin(), valueEnd()));
}
-prefix_ bool senf::MIHFIdTLVParser::valueEquals( std::string const &id)
+prefix_ bool senf::MIHFIdTLVParser::valueEquals( std::string const &id)
const
{
return id == valueAsString();
///////////////////////////////////////////////////////////////////////////
// MIHBaseTLVParser
-prefix_ void senf::MIHBaseTLVParser::maxLength(MIHTLVLengthParser::value_type maxl)
+prefix_ void senf::MIHBaseTLVParser::maxLength(MIHTLVLengthParser::value_type maxl)
const
{
protect(), length_().capacity(maxl);
}
-prefix_ void senf::MIHBaseTLVParser::finalize()
+prefix_ void senf::MIHBaseTLVParser::finalize()
{
protect(), length_().finalize();
};
{
Self * self ( static_cast<Self *>(this));
self->protect(), self->listSize_().finalize();
- typename Self::length_t::value_type size (
+ typename Self::length_t::value_type size (
senf::bytes(self->listSize_()) + senf::bytes(self->value()));
self->maxLength( size);
self->length_() << size;
}
-
+
///////////////////////////////ct.e////////////////////////////////////////
#undef prefix_
{}
template <class OutputIterator>
-prefix_ void senf::MIHFIdTLVParser::binaryNAIEncoder<OutputIterator>::operator()(boost::uint8_t v)
+prefix_ void senf::MIHFIdTLVParser::binaryNAIEncoder<OutputIterator>::operator()(boost::uint8_t v)
{
*i_++ = '\\';
*i_++ = v;
// senf::MIHFIdTLVParser
template <class OutputIterator>
-prefix_ boost::function_output_iterator<senf::MIHFIdTLVParser::binaryNAIEncoder<OutputIterator> >
-senf::MIHFIdTLVParser::getNAIEncodedOutputIterator(OutputIterator i)
+prefix_ boost::function_output_iterator<senf::MIHFIdTLVParser::binaryNAIEncoder<OutputIterator> >
+senf::MIHFIdTLVParser::getNAIEncodedOutputIterator(OutputIterator i)
{
return boost::make_function_output_iterator(binaryNAIEncoder<OutputIterator>(i));
}
template <class Iterator>
-prefix_ boost::filter_iterator<senf::MIHFIdTLVParser::binaryNAIDecoder, Iterator>
-senf::MIHFIdTLVParser::getNAIDecodedIterator(Iterator begin, Iterator end)
+prefix_ boost::filter_iterator<senf::MIHFIdTLVParser::binaryNAIDecoder, Iterator>
+senf::MIHFIdTLVParser::getNAIDecodedIterator(Iterator begin, Iterator end)
{
return boost::make_filter_iterator<binaryNAIDecoder>(begin, end);
}
-
+
///////////////////////////////cti.e///////////////////////////////////////
#undef prefix_
namespace senf {
struct MIHTLVLengthException : public senf::Exception
- {
- MIHTLVLengthException()
- : senf::Exception("MIHTLVLengthException") {}
+ {
+ MIHTLVLengthException()
+ : senf::Exception("MIHTLVLengthException") {}
};
-
- class MIHTLVLengthParser
+
+ class MIHTLVLengthParser
: public detail::packet::IntParserOps<MIHTLVLengthParser, boost::uint32_t>,
public PacketParserBase
{
value_type value() const;
void value(value_type const & v);
-
+
MIHTLVLengthParser const & operator= (value_type other);
size_type bytes() const;
void init() const;
void finalize();
void capacity(value_type v);
value_type capacity() const;
-
+
private:
void resize_(size_type size);
- };
-
+ };
+
/** \brief Base class for MIH TLV parsers
-
+
MIHBaseTLVParser is the abstract base class for MIH TLV parsers. It defines the
- \ref type() field as an \ref senf::UInt8Parser and the \ref length() field as a
- MIHTLVLengthParser. The length field is read-only.
-
- To create your own \c TLVParser you have to inherit from MIHBaseTLVParser (don't
- forget \ref SENF_PARSER_INHERIT) and define the \c value field. In the following example
- the value is a vector of MacAddresses:
+ \ref type() field as an \ref senf::UInt8Parser and the \ref length() field as a
+ MIHTLVLengthParser. The length field is read-only.
+
+ To create your own \c TLVParser you have to inherit from MIHBaseTLVParser (don't
+ forget \ref SENF_PARSER_INHERIT) and define the \c value field. In the following example
+ the value is a vector of MacAddresses:
\code
struct MacAddressesTLVParser : public MIHBaseTLVParser {
- # include SENF_PARSER()
+ # include SENF_PARSER()
SENF_PARSER_INHERIT ( MIHBaseTLVParser );
SENF_PARSER_VECTOR ( value, bytes(length), senf::MACAddressParser );
SENF_PARSER_FINALIZE( MacAddressesTLVParser );
};
\endcode
-
- You have to adjust the maximum length value with the \ref maxLength function
+
+ You have to adjust the maximum length value with the \ref maxLength function
before the length value is set. The default maximum value is 128. So, in the above
example adding more than 21 MACAddresses to the vector will throw a TLVLengthException
if you don't call \c maxLength( \e some_value) before.
-
+
\see MIHTLVLengthParser \n
MIHGenericTLVParser \n
*/
SENF_PARSER_FIELD ( type, UInt8Parser );
SENF_PARSER_FIELD_RO ( length, MIHTLVLengthParser );
SENF_PARSER_FINALIZE ( MIHBaseTLVParser );
-
+
/** \brief shrink size of the TLV length field to minimum
-
+
The size of the length field will be decreased to minimum necessary to hold
the current length value.
*/
void finalize();
-
+
typedef GenericTLVParserRegistry<MIHBaseTLVParser> Registry;
-
+
protected:
/** \brief set maximum value of TLV length field
-
+
The size of the length field will be increased if necessary.
\param v maximum value of length field
*/
void maxLength(MIHTLVLengthParser::value_type maxl) const;
};
-
-
+
+
/** \brief Parser for a generic TLV packet
*/
struct MIHGenericTLVParser
defaultInit();
maxLength( MIHTLVLengthParser::max_value);
}
-
+
using base::init;
using base::maxLength;
};
-
-
+
+
/** \brief Base class for list TLV parser
- */
- struct MIHBaseListTLVParser
+ */
+ struct MIHBaseListTLVParser
: public MIHBaseTLVParser
{
# include SENF_PARSER()
template <class Self>
struct MIHListTLVParserMixin
{
- void finalize();
+ void finalize();
};
-
-
+
+
/** \brief Parse a MIHF_ID
Note that the maximum length of a MIHF_ID is 253 octets (see F.3.11 in 802.21)
We could set maxLength in init(), but for the most MIHF_IDs the default
maximum length of 128 should be enough.
-
+
\note you must call maxIdLength( 253) *before* setting MIHF_IDs values longer
than 128.
-
+
\see MIHFId
*/
class MIHFIdTLVParser : public MIHBaseTLVParser
SENF_PARSER_LABEL ( idValue );
SENF_PARSER_SKIP ( idLength(), 0 );
SENF_PARSER_FINALIZE ( MIHFIdTLVParser );
-
+
public:
///\name Value setters
///@{
void value( MIHFId const & id);
-
+
void value( std::string const & id );
void value( senf::MACAddress const & addr);
void value( senf::INet4Address const & addr);
void value( senf::INet6Address const & addr);
- void value( senf::EUI64 const & addr);
+ void value( senf::EUI64 const & addr);
///@}
///\name Value getters
///@{
MIHFId valueAs( MIHFId::Type type) const;
-
+
std::string valueAsString() const;
senf::MACAddress valueAsMACAddress() const;
senf::INet4Address valueAsINet4Address() const;
senf::INet6Address valueAsINet6Address() const;
senf::EUI64 valueAsEUI64() const;
///@}
-
+
///\name Value comparisons
///@{
bool valueEquals( MIHFId const & id) const;
-
+
bool valueEquals( std::string const & id ) const;
bool valueEquals( senf::MACAddress const & addr) const;
bool valueEquals( senf::INet4Address const & addr) const;
bool valueEquals( senf::INet6Address const & addr) const;
bool valueEquals( senf::EUI64 const & addr) const;
///@}
-
+
void dump(std::ostream & os) const;
void maxIdLength(boost::uint8_t maxl) const;
void finalize();
private:
/// resize the packet after the length field to given size
senf::safe_data_iterator resizeValueField(MIHTLVLengthParser::value_type size);
-
+
data_iterator valueBegin() const;
data_iterator valueEnd() const;
void operator()(boost::uint8_t v);
OutputIterator & i_;
};
-
+
template <class OutputIterator>
- static boost::function_output_iterator<binaryNAIEncoder<OutputIterator> >
+ static boost::function_output_iterator<binaryNAIEncoder<OutputIterator> >
getNAIEncodedOutputIterator(OutputIterator i);
struct binaryNAIDecoder {
bool operator()(boost::uint8_t v);
bool readNextByte_;
};
-
+
template <class Iterator>
- static boost::filter_iterator<binaryNAIDecoder, Iterator>
+ static boost::filter_iterator<binaryNAIDecoder, Iterator>
getNAIDecodedIterator(Iterator begin, Iterator end);
-
+
struct ValueSetterVisitor : public boost::static_visitor<> {
MIHFIdTLVParser & parser;
ValueSetterVisitor( MIHFIdTLVParser & p) : parser(p) {}
parser.value( id);
}
};
-
+
struct ValueEqualsVisitor : public boost::static_visitor<bool> {
MIHFIdTLVParser const & parser;
ValueEqualsVisitor( MIHFIdTLVParser const & p) : parser(p) {}
struct MIHFSrcIdTLVParser : public MIHFIdTLVParser
{
MIHFSrcIdTLVParser(data_iterator i, state_type s) : MIHFIdTLVParser(i,s) {}
-
+
void init() const {
defaultInit();
type() << typeId+0;
static type_t::value_type const typeId = 1;
void dump(std::ostream & os) const;
};
-
+
/** \brief Parser for 802.21 destination MIHF_ID TLV
*/
struct MIHFDstIdTLVParser : public MIHFIdTLVParser
{
MIHFDstIdTLVParser(data_iterator i, state_type s) : MIHFIdTLVParser(i,s) {}
-
+
void init() const {
defaultInit();
type() << typeId+0;
static type_t::value_type const typeId = 2;
void dump(std::ostream & os) const;
};
-
+
/** \brief Parser for 802.21 Status TLV
*/
struct MIHStatusTLVParser : public MIHBaseTLVParser
SENF_PARSER_INHERIT ( MIHBaseTLVParser );
SENF_PARSER_FIELD ( value, UInt8Parser );
SENF_PARSER_FINALIZE( MIHStatusTLVParser );
-
+
SENF_PARSER_INIT() {
defaultInit();
type() << typeId+0;
}
static type_t::value_type const typeId = 3;
void dump(std::ostream & os) const; ///< dump string representation to given stream
-
- enum StatusCode {
+
+ enum StatusCode {
Success, UnspecifiedFailure, Rejected, AuthorizationFailure, NetworkError };
};
-
+
struct MIHRegisterReqCodeTLVParser : public MIHBaseTLVParser
{
# include SENF_PARSER()
SENF_PARSER_INHERIT ( MIHBaseTLVParser );
SENF_PARSER_FIELD ( value, UInt8Parser );
SENF_PARSER_FINALIZE ( MIHRegisterReqCodeTLVParser );
-
+
SENF_PARSER_INIT() {
defaultInit();
type() = typeId+0;
length_() = 1;
}
- static type_t::value_type const typeId = 11;
+ static type_t::value_type const typeId = 11;
void dump(std::ostream & os) const; ///< dump string representation to given stream
-
+
enum RequestCode { Registration, ReRegistration };
};
-
+
struct MIHValidTimeIntervalTLVParser : public MIHBaseTLVParser
{
# include SENF_PARSER()
SENF_PARSER_INHERIT ( MIHBaseTLVParser );
SENF_PARSER_FIELD ( value, UInt32Parser );
SENF_PARSER_FINALIZE ( MIHValidTimeIntervalTLVParser );
-
+
SENF_PARSER_INIT() {
defaultInit();
type() = typeId+0;
0x01, // type
0x81, // first and last bit set => one byte length following
0x0A, // length (10 = 138 bytes value follows)
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
- 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
- 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
- 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+ 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
- 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
- 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
+ 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
+ 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63,
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d,
- 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
- 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81,
+ 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81,
0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89
};
PacketInterpreterBase::ptr p (PacketInterpreter<VoidPacket>::create(data));
0x0c, // length
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67 // value
};
- SENF_CHECK_EQUAL_COLLECTIONS(
+ SENF_CHECK_EQUAL_COLLECTIONS(
data, data+sizeof(data), tlvPacket.data().begin(), tlvPacket.data().end() );
}
{}
template <class ElementParser>
-prefix_ ElementParser
+prefix_ ElementParser
senf::detail::ArrayParser_iterator<ElementParser>::operator[](int i)
const
{
// iterator_facade interface
template <class ElementParser>
-prefix_ ElementParser
+prefix_ ElementParser
senf::detail::ArrayParser_iterator<ElementParser>::dereference()
const
{
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
typedef PrefixAuxParserPolicy ParserPolicy;
static PacketParserBase::size_type const aux_bytes = P::fixed_bytes;
-
+
typename P::value_type aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
void aux(typename P::value_type const & v, PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
typedef FixedAuxParserPolicy ParserPolicy;
static PacketParserBase::size_type const aux_bytes = 0;
-
+
typename P::value_type aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
void aux(typename P::value_type const & v, PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
};
template <class P> struct DynamicWrapperAuxParserPolicy;
-
+
/** \brief Internal: Dynamic aux-parser policy
Place auxiliary field at a variable distance before the container/collection
DynamicAuxParserPolicy(P p);
DynamicAuxParserPolicy(WrapperPolicy const & other);
-
+
typename P::value_type aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
void aux(typename P::value_type const & v, PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
static PacketParserBase::size_type const aux_bytes = 0;
DynamicWrapperAuxParserPolicy(ParserPolicy const & other);
-
+
typename P::value_type aux(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
void aux(typename P::value_type const & v, PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
PacketParserBase::data_iterator adjust(PacketParserBase::data_iterator i, PacketParserBase::state_type s) const;
typedef TransformAuxParserPolicy<typename Policy::ParserPolicy, Transform> ParserPolicy;
static PacketParserBase::size_type const aux_bytes = Policy::aux_bytes;
-
+
TransformAuxParserPolicy();
template <class Arg> TransformAuxParserPolicy(Arg const & arg);
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
UInt16VectorParser v (p.data().begin(), &p.data());
-
+
BOOST_REQUIRE_EQUAL( v.size(), p.data().size()/2 );
BOOST_CHECK_EQUAL( v[0], 0x1011u );
BOOST_CHECK_EQUAL( v[1], 0x1213u );
w.erase(w.begin()+3, w.begin()+5);
BOOST_CHECK_EQUAL( w.size(), p.data().size()/2 );
- senf::UInt16Parser::value_type data2[] =
+ senf::UInt16Parser::value_type data2[] =
{ 0x1011u, 0x0000u, 0x1213u, 0x2223u, 0x2425u };
- BOOST_CHECK_EQUAL_COLLECTIONS( w.begin(), w.end(),
+ BOOST_CHECK_EQUAL_COLLECTIONS( w.begin(), w.end(),
data2, data2+sizeof(data2)/sizeof(data2[0]) );
}
}
w.erase(boost::next(w.begin(),3), boost::next(w.begin(),5));
BOOST_CHECK_EQUAL( w.size(), p.data().size()/2 );
- senf::UInt16Parser::value_type data2[] =
+ senf::UInt16Parser::value_type data2[] =
{ 0x1011u, 0x0000u, 0x1213u, 0x2223u, 0x2425u };
- BOOST_CHECK_EQUAL_COLLECTIONS( w.begin(), w.end(),
+ BOOST_CHECK_EQUAL_COLLECTIONS( w.begin(), w.end(),
data2, data2+sizeof(data2)/sizeof(data2[0]) );
}
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace senf {
- /** \brief Parse an Ethernet MAC address
+ /** \brief Parse an Ethernet MAC address
The ethernet MAC is returned by value as a 6-byte sequence
struct MACAddressParser : public PacketParserBase
{
MACAddressParser(data_iterator i, state_type s) : PacketParserBase(i,s,fixed_bytes) {}
-
+
///////////////////////////////////////////////////////////////////////////
typedef MACAddress value_type;
MACAddressParser const & operator= (value_type const & other) { value(other); return *this; }
};
-
+
/** \brief Parse an Ethernet packet
Parser implementing an ethernet header.
/** \brief EtherType registry
This registry registers packet types with their EtherType number.
-
+
\see <a href="http://www.iana.org/assignments/ethernet-numbers">Ethernet numbers</a> \n
\ref PacketRegistry
*/
static factory_t nextPacketType(packet p);
/// Dump given EthernetPacket in readable form to given output stream
- static void dump(packet p, std::ostream & os);
+ static void dump(packet p, std::ostream & os);
static void finalize(packet p);
};
*/
typedef ConcretePacket<EthernetPacketType> EthernetPacket;
-
+
/** \brief Parse an ethernet VLAN tag
-
+
Parser interpreting the ethernet VLAN tag. Fields are
\see EthVLanPacketType
\par Fields:
\ref EthVLanPacketParser
\image html EthVLanPacket.png
-
+
\par Associated registries:
\ref EtherTypes
\ingroup protocolbundle_default
*/
struct EthVLanPacketType
- : public PacketTypeBase,
+ : public PacketTypeBase,
public PacketTypeMixin<EthVLanPacketType, EtherTypes>
{
#ifndef DOXYGEN
/** \todo Add LLC/SNAP support -> only use the registry
for type() values >=1536, otherwise expect an LLC header */
- static key_t nextPacketKey(packet p)
+ static key_t nextPacketKey(packet p)
{ return p->type(); }
/// Dump given EthVLanPacket in readable form to given output stream
SENF_PACKET_REGISTRY_REGISTER( senf::IpTypes, 58, senf::ICMPv6Packet);
-prefix_ boost::uint16_t senf::ICMPv6PacketParser::calcChecksum()
+prefix_ boost::uint16_t senf::ICMPv6PacketParser::calcChecksum()
const
{
senf::IPv6Packet ipv6 (packet().rfind<senf::IPv6Packet>(senf::nothrow));
if (! ipv6) return 0u;
-
+
senf::IpChecksum summer;
////////////////////////////////////////
// IPv6 pseudo header
- summer.feed( ipv6->source().i(),
+ summer.feed( ipv6->source().i(),
ipv6->source().i() + senf::IPv6Packet::Parser::source_t::fixed_bytes );
// need support for HopByHop routing header -> the destination used here must be the *final*
// destination ...
- summer.feed( ipv6->destination().i(),
+ summer.feed( ipv6->destination().i(),
ipv6->destination().i() + senf::IPv6PacketParser::destination_t::fixed_bytes );
// packet length
boost::uint32_t size (data().size());
//#include "ICMPv6Packet.mpp"
///////////////////////////////hh.p////////////////////////////////////////
-namespace senf
+namespace senf
{
struct ICMPv6PacketParser : public PacketParserBase
{
SENF_PARSER_FIELD ( type, UInt8Parser );
SENF_PARSER_FIELD ( code, UInt8Parser );
SENF_PARSER_FIELD ( checksum, UInt16Parser );
-
+
SENF_PARSER_FINALIZE ( ICMPv6PacketParser );
-
+
boost::uint16_t calcChecksum() const;
};
-
+
struct ICMPTypes {
// ICMP type registry
typedef boost::uint8_t key_t;
\par Fields:
\ref ICMPv6PacketParser
\image html ICMPv6Packet.png
-
+
\par Associated registries:
\ref ICMPTypes
\ingroup protocolbundle_default
*/
- struct ICMPv6PacketType
+ struct ICMPv6PacketType
: public PacketTypeBase,
public PacketTypeMixin<ICMPv6PacketType, ICMPTypes>
{
typedef PacketTypeMixin<ICMPv6PacketType, ICMPTypes> mixin;
typedef ConcretePacket<ICMPv6PacketType> packet;
typedef ICMPv6PacketParser parser;
-
+
using mixin::nextPacketRange;
using mixin::nextPacketType;
using mixin::init;
using mixin::initSize;
-
+
static void dump(packet p, std::ostream & os);
-
- static key_t nextPacketKey(packet p) {
+
+ static key_t nextPacketKey(packet p) {
return p->type();
}
-
+
static void finalize(packet p) {
p->type() << key(p.next(senf::nothrow));
p->checksum() << p->calcChecksum();
}
};
-
+
/** \brief ICMPv6 packet typedef
\ingroup protocolbundle_default
*/
SENF_CHECK_NO_THROW( pListenerReport.dump( oss));
unsigned char dataListenerQuery[] = {
- 0x82, 0x00, 0xf7, 0xd6, 0x27, 0x10, 0x00, 0x00,
+ 0x82, 0x00, 0xf7, 0xd6, 0x27, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x7d, 0x00, 0x00
BOOST_CHECK_EQUAL( pListenerQuery.next().size(), 24u );
SENF_CHECK_NO_THROW( pListenerQuery.dump( oss));
-
+
unsigned char dataEchoRequest[] = {
0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07
};
BOOST_CHECK_EQUAL( pEchoRequest.next().size(), 4u );
SENF_CHECK_NO_THROW( pEchoRequest.dump( oss));
-
+
unsigned char dataEchoReply[] = {
0x81, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x4d
};
-
+
senf::ICMPv6Packet pEchoReply ( senf::ICMPv6Packet::create(dataEchoReply) );
BOOST_CHECK_EQUAL( pEchoReply->type(), 0x81 );
BOOST_CHECK_EQUAL( pEchoReply->code(), 0x00 );
BOOST_CHECK_EQUAL( pEchoReply.next().size(), 4u );
SENF_CHECK_NO_THROW( pEchoReply.dump( oss));
-
-
+
+
unsigned char dataErrDestUnreachable[] = {
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-
+
senf::ICMPv6Packet pErrDestUnreachable ( senf::ICMPv6Packet::create(dataErrDestUnreachable) );
BOOST_CHECK_EQUAL( pErrDestUnreachable->type(), 0x01 );
BOOST_CHECK_EQUAL( pErrDestUnreachable->code(), 0x00 );
BOOST_CHECK_EQUAL( pErrDestUnreachable.next().size(), 4u );
SENF_CHECK_NO_THROW( pErrDestUnreachable.dump( oss));
-
-
+
+
unsigned char dataErrTooBig[] = {
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xd8
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xd8
};
-
+
senf::ICMPv6Packet pErrTooBig ( senf::ICMPv6Packet::create(dataErrTooBig) );
BOOST_CHECK_EQUAL( pErrTooBig->type(), 0x02 );
BOOST_CHECK_EQUAL( pErrTooBig->code(), 0x00 );
BOOST_CHECK_EQUAL( pErrTooBig.next().size(), 4u );
SENF_CHECK_NO_THROW( pErrTooBig.dump( oss));
-
-
+
+
unsigned char dataErrTimeExceeded[] = {
0x03, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-
+
senf::ICMPv6Packet pErrTimeExceeded ( senf::ICMPv6Packet::create(dataErrTimeExceeded) );
BOOST_CHECK_EQUAL( pErrTimeExceeded->type(), 0x03 );
BOOST_CHECK_EQUAL( pErrTimeExceeded->code(), 0x63 );
BOOST_CHECK_EQUAL( pErrTimeExceeded.next().size(), 4u );
SENF_CHECK_NO_THROW( pErrTimeExceeded.dump( oss));
-
-
+
+
unsigned char dataErrParamProblem[] = {
0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-
+
senf::ICMPv6Packet pErrParamProblem ( senf::ICMPv6Packet::create(dataErrParamProblem) );
BOOST_CHECK_EQUAL( pErrParamProblem->type(), 0x04 );
BOOST_CHECK_EQUAL( pErrParamProblem->code(), 0x01 );
BOOST_CHECK_EQUAL( pErrParamProblem.next().size(), 4u );
SENF_CHECK_NO_THROW( pErrParamProblem.dump( oss));
-
+
unsigned char dataRouterSolicitation[] = {
0x85, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
SENF_AUTO_UNIT_TEST(ICMPv6Packet_create)
{
std::ostringstream oss (std::ostringstream::out);
-
+
unsigned char ping[] = { 0x60, 0x00, 0x00, 0x00, 0x00, 0x40, 0x3a, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x80, 0x00, 0xda, 0xe0, 0x9f, 0x7e, 0x00, 0x09,
-
+
0xb7, 0x3c, 0xbb, 0x4a, 0x9d, 0x90, 0x0a, 0x00, //payload
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
senf::ICMPv6Packet icmp (senf::ICMPv6Packet::createAfter(ip));
icmp->code() = 0;
-
+
senf::ICMPv6EchoRequest ereq (senf::ICMPv6EchoRequest::createAfter(icmp));
ereq->identifier() = 0x9f7e;
ereq->seqNr() = 9;
senf::DataPacket::createAfter(ereq, std::make_pair(ping+48, ping+sizeof(ping))));
ip.finalizeAll();
-
+
SENF_CHECK_NO_THROW (ip.dump( oss ));
std::string dump (
prefix_ void senf::ICMPv6ErrDestUnreachableType::dump(packet p, std::ostream & os)
{
- os << "ICMPv6 Error Destination Unreachable (no further fields available here)\n";
+ os << "ICMPv6 Error Destination Unreachable (no further fields available here)\n";
}
prefix_ void senf::ICMPv6ErrTooBigType::dump(packet p, std::ostream & os)
{
os << "ICMPv6 Error Packet Too Big:\n"
- << senf::fieldName("MTU") << unsigned(p->mtu() ) << "\n";
+ << senf::fieldName("MTU") << unsigned(p->mtu() ) << "\n";
}
prefix_ void senf::ICMPv6ErrTimeExceededType::dump(packet p, std::ostream & os)
{
os << "ICMPv6 Error Time Exceeded:\n"
- << senf::fieldName("Unused(32Bit)") << unsigned(p->unused() ) << "\n";
+ << senf::fieldName("Unused(32Bit)") << unsigned(p->unused() ) << "\n";
}
prefix_ void senf::ICMPv6ErrParamProblemType::dump(packet p, std::ostream & os)
{
os << "ICMPv6 Error Parameter Problem:\n"
- << senf::fieldName("Pointer") << unsigned(p->pointer() ) << "\n";
+ << senf::fieldName("Pointer") << unsigned(p->pointer() ) << "\n";
}
prefix_ void senf::MLDv2ListenerQueryType::dump(packet p, std::ostream & os)
senf::MLDv2ListenerQuery::Parser::srcAddresses_t::container c (p->srcAddresses());
senf::MLDv2ListenerQuery::Parser::srcAddresses_t::container::iterator i (c.begin());
for (unsigned int nr =1; i != c.end(); ++i, ++nr)
- os << " " << nr << ".) " << *i << "\n";
- os << "\n";
+ os << " " << nr << ".) " << *i << "\n";
+ os << "\n";
}
prefix_ void senf::MLDv2ListenerReportType::dump(packet p, std::ostream & os)
{
os << "ICMPv6 Multicast Listener Report Message:\n"
- << senf::fieldName("Reserved") << unsigned(p->reserved() )
+ << senf::fieldName("Reserved") << unsigned(p->reserved() )
<<"\n Multicast Address Records:\n";
-
+
senf::MLDv2ListenerReport::Parser::mcastAddrRecords_t::container cAddrR (p->mcastAddrRecords() );
senf::MLDv2ListenerReport::Parser::mcastAddrRecords_t::container::iterator iAddrR (cAddrR.begin() );
for (; iAddrR != cAddrR.end(); ++iAddrR) {
# include SENF_FIXED_PARSER()
SENF_PARSER_FIELD ( identifier, UInt16Parser );
SENF_PARSER_FIELD ( seqNr, UInt16Parser );
-
+
SENF_PARSER_FINALIZE ( ICMPv6EchoRequestParser );
};
-
+
/** \brief ICMPv6 Echo Request
\par Packet type (typedef):
typedef PacketTypeMixin<ICMPv6EchoRequestType> mixin;
typedef ConcretePacket<ICMPv6EchoRequestType> packet;
typedef ICMPv6EchoRequestParser parser;
-
+
using mixin::nextPacketRange;
using mixin::init;
using mixin::initSize;
static void dump(packet p, std::ostream & os);
};
-
+
typedef ConcretePacket<ICMPv6EchoRequestType> ICMPv6EchoRequest;
-
+
//#############################################################
//ICMPv6 Echo Reply
//#############################################################
# include SENF_FIXED_PARSER()
SENF_PARSER_FIELD ( identifier, UInt16Parser );
SENF_PARSER_FIELD ( seqNr, UInt16Parser );
-
+
SENF_PARSER_FINALIZE ( ICMPv6EchoReplyParser );
};
-
+
/** \brief ICMPv6 Echo Reply
\par Packet type (typedef):
typedef PacketTypeMixin<ICMPv6EchoReplyType> mixin;
typedef ConcretePacket<ICMPv6EchoReplyType> packet;
typedef ICMPv6EchoReplyParser parser;
-
+
using mixin::nextPacketRange;
using mixin::init;
using mixin::initSize;
-
+
static void dump(packet p, std::ostream & os);
};
-
+
typedef ConcretePacket<ICMPv6EchoReplyType> ICMPv6EchoReply;
-
+
//#############################################################
//ICMPv6 Error Destination Unreachable Message
//#############################################################
struct ICMPv6ErrDestUnreachableParser : public PacketParserBase
{
# include SENF_FIXED_PARSER()
-
+
//should be set static 0 by sender and ignored by receiver
SENF_PARSER_PRIVATE_FIELD ( unused, UInt32Parser );
-
- SENF_PARSER_INIT() {
- unused() = 0;
+
+ SENF_PARSER_INIT() {
+ unused() = 0;
}
/* Code 0 - No route to destination
1 - Communication with destination
ICMPv6Packet icmpv6 (senf::Packet().rfind<ICMPv6Packet>(senf::nothrow));
icmpv6->code() = code;
}
-
+
SENF_PARSER_FINALIZE ( ICMPv6ErrDestUnreachableParser );
};
-
+
/** \brief ICMPv6 Destination unreachable
\par Packet type (typedef):
\par Fields:
\ref ICMPv6ErrDestUnreachableParser
\image html ICMPv6ErrDestUnreachable.png
-
+
\ingroup protocolbundle_default
*/
struct ICMPv6ErrDestUnreachableType
typedef PacketTypeMixin<ICMPv6ErrDestUnreachableType> mixin;
typedef ConcretePacket<ICMPv6ErrDestUnreachableType> packet;
typedef ICMPv6ErrDestUnreachableParser parser;
-
+
using mixin::nextPacketRange;
using mixin::init;
using mixin::initSize;
-
+
static void dump(packet p, std::ostream & os);
};
-
+
typedef ConcretePacket<ICMPv6ErrDestUnreachableType> ICMPv6ErrDestUnreachable;
-
+
//#############################################################
//ICMPv6 Error Packet Too Big Message
//#############################################################
{
# include SENF_FIXED_PARSER()
SENF_PARSER_FIELD ( mtu, UInt32Parser );
-
+
/* Code static set to 0 */
SENF_PARSER_INIT() {
ICMPv6Packet icmpv6 (packet().rfind<ICMPv6Packet>(senf::nothrow));
icmpv6->code() = 0;
}
-
+
SENF_PARSER_FINALIZE ( ICMPv6ErrTooBigParser );
};
-
+
/** \brief ICMPv6 Packet to big
\par Packet type (typedef):
typedef PacketTypeMixin<ICMPv6ErrTooBigType> mixin;
typedef ConcretePacket<ICMPv6ErrTooBigType> packet;
typedef ICMPv6ErrTooBigParser parser;
-
+
using mixin::nextPacketRange;
using mixin::init;
using mixin::initSize;
-
+
static void dump(packet p, std::ostream & os);
};
typedef ConcretePacket<ICMPv6ErrTooBigType> ICMPv6ErrTooBig;
-
+
//#############################################################
//ICMPv6 Error Time Exceeded Message
//#############################################################
ICMPv6Packet icmpv6 (packet().rfind<ICMPv6Packet>(senf::nothrow));
icmpv6->code() = code;
}
-
+
SENF_PARSER_FINALIZE ( ICMPv6ErrTimeExceededParser );
};
-
+
/** \brief ICMPv6 Time exceeded
\par Packet type (typedef):
typedef PacketTypeMixin<ICMPv6ErrTimeExceededType> mixin;
typedef ConcretePacket<ICMPv6ErrTimeExceededType> packet;
typedef ICMPv6ErrTimeExceededParser parser;
-
+
using mixin::nextPacketRange;
using mixin::init;
using mixin::initSize;
-
+
static void dump(packet p, std::ostream & os);
};
typedef ConcretePacket<ICMPv6ErrTimeExceededType> ICMPv6ErrTimeExceeded;
-
+
//#############################################################
//ICMPv6 Error Parameter Problem Message
//#############################################################
/* Code 0 - Erroneous header field encountered
1 - Unrecognized Next Header type encountered
2 - Unrecognized IPv6 option encountered */
-
+
void setErrCode(int code)
{
ICMPv6Packet icmpv6 (packet().rfind<ICMPv6Packet>(senf::nothrow));
}
SENF_PARSER_FINALIZE ( ICMPv6ErrParamProblemParser );
};
-
+
/** \brief ICMPv6 Parameter problem
\par Packet type (typedef):
typedef PacketTypeMixin<ICMPv6ErrParamProblemType> mixin;
typedef ConcretePacket<ICMPv6ErrParamProblemType> packet;
typedef ICMPv6ErrParamProblemParser parser;
-
+
using mixin::nextPacketRange;
using mixin::init;
using mixin::initSize;
-
+
static void dump(packet p, std::ostream & os);
};
typedef ConcretePacket<ICMPv6ErrParamProblemType> ICMPv6ErrParamProblem;
-
+
//#############################################################
//ICMPv6 MLDv2 (RFC 3810) Multicast Listener Query
//#############################################################
//need a variant here
// a.) maxResponseCode < 32768 =>Interger
// b.) maxResponseCode >=32768 => float (is there a float parser???)
- /*
- float value as followed:
+ /*
+ float value as followed:
0 1 2 3 4 5 6 7 8 9 A B C D E F
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|1| exp | mant |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
-
+
SENF_PARSER_FIELD ( maxResponseCode, UInt16Parser );
SENF_PARSER_FIELD ( reserved, UInt16Parser ); // set to zero by default
SENF_PARSER_FIELD ( mcAddress, INet6AddressParser );
SENF_PARSER_FIELD ( qqic, UInt8Parser );
SENF_PARSER_PRIVATE_FIELD ( nrSources, UInt16Parser );
SENF_PARSER_VECTOR (srcAddresses, nrSources, INet6AddressParser );
-
+
SENF_PARSER_FINALIZE ( MLDv2ListenerQueryParser );
-
- SENF_PARSER_INIT() {
- reserved() = 0;
+
+ SENF_PARSER_INIT() {
+ reserved() = 0;
resv() = 0;
}
};
-
+
/** \brief MLDv2 Listener query
\par Packet type (typedef):
typedef PacketTypeMixin<MLDv2ListenerQueryType> mixin;
typedef ConcretePacket<MLDv2ListenerQueryType> packet;
typedef MLDv2ListenerQueryParser parser;
-
+
using mixin::nextPacketRange;
using mixin::init;
using mixin::initSize;
-
+
static void dump(packet p, std::ostream & os);
};
-
+
typedef ConcretePacket<MLDv2ListenerQueryType> MLDv2ListenerQuery;
-
+
//#############################################################
//ICMPv6 MLDv2 (RFC 3810) Multicast Listener Report Message
//#############################################################
struct MLDv2AddressRecordParser : public PacketParserBase
{
# include SENF_PARSER()
-
+
SENF_PARSER_FIELD ( recordType, UInt8Parser );
SENF_PARSER_PRIVATE_FIELD ( auxDataLen, UInt8Parser );
SENF_PARSER_PRIVATE_FIELD ( nrOfSrcs, UInt16Parser );
SENF_PARSER_FIELD ( mcAddress, INet6AddressParser);
SENF_PARSER_VECTOR ( srcAddresses, nrOfSrcs, INet6AddressParser );
SENF_PARSER_VECTOR ( auxData, auxDataLen, UInt32Parser );
-
+
SENF_PARSER_FINALIZE ( MLDv2AddressRecordParser );
};
-
+
struct MLDv2ListenerReportParser : public PacketParserBase
{
# include SENF_PARSER()
-
+
SENF_PARSER_FIELD ( reserved, UInt16Parser ); //set to zero by default
SENF_PARSER_PRIVATE_FIELD ( nrMcastAddrRecords_, UInt16Parser );
SENF_PARSER_LIST ( mcastAddrRecords, nrMcastAddrRecords_, MLDv2AddressRecordParser );
-
+
SENF_PARSER_FINALIZE ( MLDv2ListenerReportParser );
-
- SENF_PARSER_INIT() {
- reserved() = 0;
+
+ SENF_PARSER_INIT() {
+ reserved() = 0;
}
};
-
+
/** \brief MLDv2 Listener report
\par Packet type (typedef):
typedef PacketTypeMixin<MLDv2ListenerReportType> mixin;
typedef ConcretePacket<MLDv2ListenerReportType> packet;
typedef MLDv2ListenerReportParser parser;
-
+
using mixin::nextPacketRange;
using mixin::init;
using mixin::initSize;
-
+
static void dump(packet p, std::ostream & os);
};
typedef ConcretePacket<MLDv2ListenerReportType> MLDv2ListenerReport;
void value(value_type const & v) { std::copy(v.begin(), v.end(), i()); }
operator value_type() const { return value(); }
byte & operator[](size_type index) const { return *boost::next(i(),index); }
- INet4AddressParser const & operator= (value_type const & other)
+ INet4AddressParser const & operator= (value_type const & other)
{ value(other); return *this; }
};
/** \brief Parse an IPv4 packet
Parser implementing the IPv4 header.
-
+
\image html IPv4Packet.png
-
+
\see IPv4PacketType \n
<a href="http://tools.ietf.org/html/rfc791">RFC 791</a>
}
SENF_PARSER_FINALIZE(IPv4PacketParser);
-
+
boost::uint16_t calcChecksum() const; ///< calculate header checksum
/**< calculate and return the checksum of the header
\see \ref senf::IpChecksum */
bool validateChecksum() const {
return checksum() == calcChecksum();
} ///< validate header checksum
- /**< return \c true if the \ref checksum() "checksum"
- field is equal to the \ref calcChecksum()
+ /**< return \c true if the \ref checksum() "checksum"
+ field is equal to the \ref calcChecksum()
"calculated checksum" */
};
};
/** \brief IPv4 packet
-
+
\par Packet type (typedef):
\ref IPv4Packet
<td>\ref IPv4PacketParser::version() "Version"</td>
<td>\ref IPv4PacketParser::ihl() "IHL"</td>
<td colspan="2">\ref IPv4PacketParser::tos() "TOS"</td>
- <td colspan="8">\ref IPv4PacketParser::length() "Length"</td>
+ <td colspan="8">\ref IPv4PacketParser::length() "Length"</td>
</tr><tr>
<td colspan="4">\ref IPv4PacketParser::identifier() "Identifier"</td>
<td>R</td>
\par Finalize action:
\copydetails finalize()
-
+
\ingroup protocolbundle_default
*/
struct IPv4PacketType
using mixin::initSize;
using mixin::init;
- static key_t nextPacketKey(packet p)
+ static key_t nextPacketKey(packet p)
{ return p->protocol(); }
-
+
/** \brief Dump given IPv4Packet in readable form to given output stream */
- static void dump(packet p, std::ostream & os);
-
+ static void dump(packet p, std::ostream & os);
+
static void finalize(packet p); ///< Finalize packet.
- /**< \li set \ref IPv4PacketParser::length() "length"
+ /**< \li set \ref IPv4PacketParser::length() "length"
from payload size
- \li set \ref IPv4PacketParser::protocol() "protocol"
+ \li set \ref IPv4PacketParser::protocol() "protocol"
from type of next packet if found in \ref IpTypes
- \li calculate and set
+ \li calculate and set
\ref IPv4PacketParser::checksum() "checksum" */
};
SENF_PARSER_BITFIELD ( optionType, 5, unsigned );
SENF_PARSER_FIELD ( length, UInt8Parser );
SENF_PARSER_FINALIZE ( IPv6OptionParser );
-
+
typedef GenericTLVParserRegistry<IPv6OptionParser> Registry;
};
namespace senf {
/** \brief Parse in IPv6 fragment extension header
-
+
Parser implementing the IPv6 fragment extension. The fields implemented are:
\image html IPv6FragmentPacket.png
\par Fields:
\ref IPv6FragmentPacketParser
-
+
\par Associated registries:
\ref IpTypes
-
+
\par Finalize action:
Set \a nextHeader from type of next packet if found in \ref IpTypes
using mixin::initSize;
using mixin::init;
- static key_t nextPacketKey(packet p)
+ static key_t nextPacketKey(packet p)
{ return p->nextHeader(); }
-
+
/** \brief Dump given IPv6FragmentPacket in readable form to given output stream */
- static void dump(packet p, std::ostream & os);
+ static void dump(packet p, std::ostream & os);
static void finalize(packet p);
};
- /** \brief IPv6 fragment extension packet typedef
+ /** \brief IPv6 fragment extension packet typedef
\ingroup protocolbundle_default
*/
typedef ConcretePacket<IPv6FragmentPacketType> IPv6FragmentPacket;
| Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
- + +
+ +
| |
- + Address[1] +
+ + Address[1]
| |
- + +
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. . .
. . .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
- + +
+ +
| |
- + Address[n] +
+ + Address[n]
| |
- + +
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
# include SENF_PARSER()
-
+
SENF_PARSER_FIELD ( nextHeader, UInt8Parser );
SENF_PARSER_FIELD ( headerLength, UInt8Parser );
SENF_PARSER_FIELD ( routingType, UInt8Parser ); //set to Zero for minimal implementation
SENF_PARSER_FIELD_RO ( segmentsLeft, UInt8Parser );
SENF_PARSER_FIELD ( reserved, UInt32Parser ); //set to zero by RFC
SENF_PARSER_VECTOR ( hopAddresses, segmentsLeft, INet6AddressParser );
-
+
SENF_PARSER_FINALIZE ( IPv6RoutingPacketParser );
-
+
//provisionary, since only type 0 is implemented
- SENF_PARSER_INIT() {
+ SENF_PARSER_INIT() {
routingType() = 0u;
- reserved() = 0u;
+ reserved() = 0u;
}
};
-
+
/** \brief IPv6 routing extension
\par Packet type (typedef):
\par Fields:
\ref IPv6RoutingPacketParser
-
+
\par Associated registries:
\ref IpTypes
-
+
\par Finalize action:
Set \a nextHeader from type of next packet if found in \ref IpTypes
typedef ConcretePacket<IPv6RoutingPacketType> packet;
/** \brief typedef to the parser of IPv6 routing extension packet */
typedef IPv6RoutingPacketParser parser;
-
+
using mixin::nextPacketRange;
using mixin::nextPacketType;
using mixin::init;
using mixin::initSize;
-
- static key_t nextPacketKey(packet p)
+
+ static key_t nextPacketKey(packet p)
{ return p->nextHeader(); }
-
+
/** \brief Dump given IPv6RoutingPacket in readable form to given output stream */
- static void dump(packet p, std::ostream & os);
-
+ static void dump(packet p, std::ostream & os);
+
static void finalize(packet p);
};
-
+
/** \brief IPv6 routing extension packet typedef
\ingroup protocolbundle_default
*/
typedef ConcretePacket<IPv6RoutingPacketType> IPv6RoutingPacket;
-
+
// =====================================================================================================
-
+
/** \brief Parse in IPv6 Hop-By-Hop extension header
Parser implementing the IPv6 routing Header extension. The fields implemented are:
\see IPv6ExtensionType_HopByHop \n
<a href="http://tools.ietf.org/html/rfc2460">RFC 2460</a>
*/
- struct IPv6HopByHopOptionsPacketParser : public PacketParserBase
+ struct IPv6HopByHopOptionsPacketParser : public PacketParserBase
{
# include SENF_PARSER()
-
+
SENF_PARSER_FIELD ( nextHeader, UInt8Parser );
SENF_PARSER_FIELD_RO ( headerLength, UInt8Parser );
SENF_PARSER_FINALIZE ( IPv6HopByHopOptionsPacketParser );
};
-
+
/** \brief IPv6 Hop-By-Hop extension
\par Packet type (typedef):
\par Fields:
\ref IPv6HopByHopOptionsPacketParser
-
+
\par Associated registries:
\ref IpTypes
-
+
\par Finalize action:
Set \a nextHeader from type of next packet if found in \ref IpTypes
typedef ConcretePacket<IPv6HopByHopOptionsPacketType> packet;
/** \brief typedef to the parser of IPv6 Hop-By-Hop extension packet */
typedef IPv6HopByHopOptionsPacketParser parser;
-
+
using mixin::nextPacketRange;
using mixin::nextPacketType;
using mixin::init;
using mixin::initSize;
-
+
static key_t nextPacketKey(packet p) {
return p->nextHeader(); }
-
+
/** \brief Dump given IPv6HopByHopOptionsPacket in readable form to given output stream */
- static void dump(packet p, std::ostream & os);
-
+ static void dump(packet p, std::ostream & os);
+
static void finalize(packet p);
};
-
+
/** \brief IPv6 routing Hop-By-Hop packet typedef
\ingroup protocolbundle_default
*/
typedef ConcretePacket<IPv6HopByHopOptionsPacketType> IPv6HopByHopOptionsPacket;
-
+
// =====================================================================================================
-
+
/** \brief Parse in IPv6 Destination Options extension header
- Parser implementing the IPv6 Destination Options Header extension.
+ Parser implementing the IPv6 Destination Options Header extension.
The fields implemented are:
\image html IPv6DestinationOptionsPacket.png
\see IPv6ExtensionType_Destination \n
<a href="http://tools.ietf.org/html/rfc2460">RFC 2460</a>
- */
- struct IPv6DestinationOptionsPacketParser : public PacketParserBase
+ */
+ struct IPv6DestinationOptionsPacketParser : public PacketParserBase
{
# include SENF_PARSER()
SENF_PARSER_FIELD ( nextHeader, UInt8Parser );
SENF_PARSER_FINALIZE ( IPv6DestinationOptionsPacketParser );
};
-
+
/** \brief IPv6 Destination Options extension
\par Packet type (typedef):
\par Fields:
\ref IPv6DestinationOptionsPacketParser
-
+
\par Associated registries:
\ref IpTypes
-
+
\par Finalize action:
Set \a nextHeader from type of next packet if found in \ref IpTypes
typedef ConcretePacket<IPv6DestinationOptionsPacketType> packet;
/** \brief typedef to the parser of IPv6 Destination Options extension packet */
typedef IPv6DestinationOptionsPacketParser parser;
-
+
using mixin::nextPacketRange;
using mixin::nextPacketType;
using mixin::init;
using mixin::initSize;
-
- static key_t nextPacketKey(packet p)
+
+ static key_t nextPacketKey(packet p)
{ return p->nextHeader(); }
/** \brief Dump given IPv6DestinationOptionsPacket in readable form to given output stream */
- static void dump(packet p, std::ostream & os);
-
+ static void dump(packet p, std::ostream & os);
+
static void finalize(packet p);
};
-
+
/** \brief IPv6 routing Destination Options packet typedef
\ingroup protocolbundle_default
*/
typedef ConcretePacket<IPv6DestinationOptionsPacketType> IPv6DestinationOptionsPacket;
-
+
}
///////////////////////////////hh.e////////////////////////////////////////
BOOST_CHECK_EQUAL( pFragment_packet->version(), 6u );
BOOST_CHECK_EQUAL( pFragment_packet->length(), 20u );
BOOST_CHECK_EQUAL( pFragment_packet->nextHeader(), 44u );
- BOOST_CHECK_EQUAL( pFragment_packet->source().value(),
+ BOOST_CHECK_EQUAL( pFragment_packet->source().value(),
senf::INet6Address::from_string("2001::1") );
- BOOST_CHECK_EQUAL( pFragment_packet->destination().value(),
+ BOOST_CHECK_EQUAL( pFragment_packet->destination().value(),
senf::INet6Address::from_string("2001::2") );
std::ostringstream oss (std::ostringstream::out);
{
unsigned char Routing_packetData[] = {
// IP header
- 0x60, 0x30, 0x00, 0x00,
+ 0x60, 0x30, 0x00, 0x00,
0x00, 0x10, // payload Length
0x2b, // next Header (43 = Routing Header)
0xff, // Hop Limit
- 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x01, 0x02, 0xff, 0xfe, 0x00, 0x02, 0x00, // Src Addr
0x35, 0x55, 0x55, 0x55, 0x66, 0x66, 0x66, 0x66,
0x77, 0x77, 0x77, 0x77, 0x88, 0x88, 0x88, 0x88, // Dest. Addr
0xa3, 0xd3, // checksum (incorrect in wireshark capture file, should be 0xa3c4)
0x00, 0x00, 0x00, 0x00
};
-
+
senf::IPv6Packet pRouting_packet (senf::IPv6Packet::create(Routing_packetData));
BOOST_CHECK_EQUAL( pRouting_packet->version(), 6u );
BOOST_CHECK_EQUAL( pRouting_packet->length(), 16u );
BOOST_CHECK_EQUAL( pRouting_packet->nextHeader(), 43u );
- BOOST_CHECK_EQUAL( pRouting_packet->source().value(),
+ BOOST_CHECK_EQUAL( pRouting_packet->source().value(),
senf::INet6Address::from_string("fe80::201:2ff:fe00:200") );
- BOOST_CHECK_EQUAL( pRouting_packet->destination().value(),
+ BOOST_CHECK_EQUAL( pRouting_packet->destination().value(),
senf::INet6Address::from_string("3555:5555:6666:6666:7777:7777:8888:8888"));
-
+
std::ostringstream oss (std::ostringstream::out);
SENF_CHECK_NO_THROW( pRouting_packet.dump( oss));
BOOST_CHECK_EQUAL( pRouting_extension->headerLength(), 0x00 );
BOOST_CHECK_EQUAL( pRouting_extension->routingType(), 0x00 );
BOOST_CHECK_EQUAL( pRouting_extension->segmentsLeft(), 0x00);
-
+
BOOST_CHECK_EQUAL( pRouting_extension->reserved(), 0u);
BOOST_REQUIRE( pRouting_extension.next().is<senf::ICMPv6Packet>() );
0x00, 0x24, // payload length
0x00, // next header: IPv6 hop-by-hop option (0)
0x01, // hop limit (1)
- 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x19, 0xb9, 0xff, 0xfe, 0xeb, 0xb2, 0x26, // IPv6 Source address
- 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, // IPv6 Destination address ff02::16
// HopByHop option
0x3a, // next Header (ICMPv6)
BOOST_CHECK_EQUAL( pHop_packet->version(), 6u );
BOOST_CHECK_EQUAL( pHop_packet->length(), 36u );
BOOST_CHECK_EQUAL( pHop_packet->nextHeader(), 0u );
- BOOST_CHECK_EQUAL( pHop_packet->source().value(),
+ BOOST_CHECK_EQUAL( pHop_packet->source().value(),
senf::INet6Address::from_string("fe80::219:b9ff:feeb:b226") );
BOOST_CHECK_EQUAL( pHop_packet->destination().value(), senf::INet6Address::from_string("ff02::16") );
0x00, 0x24, // payload length
0x00, // next header: IPv6 hop-by-hop option (0)
0x01, // hop limit (1)
- 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IPv6 Source address
+ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IPv6 Source address
0x02, 0x19, 0xb9, 0xff, 0xfe, 0xeb, 0xb2, 0x26, // (fe80::219:b9ff:feeb:b226)
- 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IPv6 Destination address
+ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IPv6 Destination address
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, // (ff02::16)
// HopByHop option
0x3a, // next Header (ICMPv6)
{
senf::IPv6HopByHopOptionsPacket::Parser::options_t::container optC(pext->options() );
{
- senf::IPv6GenericOptionParser opt (
+ senf::IPv6GenericOptionParser opt (
optC.push_back_space().init<senf::IPv6GenericOptionParser>());
opt.altAction() = 0u;
opt.changeFlag() = 0u;
SENF_PARSER_FIELD ( extendedType, senf::UInt8Parser );
SENF_PARSER_FIELD ( checksum, senf::UInt32Parser );
SENF_PARSER_FINALIZE ( IPv6ChecksumOptionParser );
-
+
SENF_PARSER_INIT() {
optionType() = typeId;
length() = 5u;
- extendedType() = extendedTypeId;
+ extendedType() = extendedTypeId;
}
-
+
static const boost::uint8_t typeId = 0x0d;
static const boost::uint8_t extendedTypeId = 0x4d;
};
}
SENF_AUTO_UNIT_TEST(ipv6Extensions_hopByHop_create_SN)
-{
+{
senf::IPv6HopByHopOptionsPacket p ( senf::IPv6HopByHopOptionsPacket::create() );
p->nextHeader() = 0x3a;
{
senf::IPv6HopByHopOptionsPacket::Parser::options_t::container optC (p->options() );
{
- IPv6ChecksumOptionParser opt (
+ IPv6ChecksumOptionParser opt (
optC.push_back_space().init<IPv6ChecksumOptionParser>());
opt.checksum() = 0x01234567u;
}
}
- unsigned char data[] = {
- 0x3a, 0x01, // Hop-By-Hop Header (nextHeader, length)
+ unsigned char data[] = {
+ 0x3a, 0x01, // Hop-By-Hop Header (nextHeader, length)
0x0d, 0x05, // option type, length
// option value: extendedType, checksum
0x4d, 0x01, 0x23, 0x45, 0x67,
0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
};
SENF_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data),
- p.data().begin(), p.data().end() );
+ p.data().begin(), p.data().end() );
}
SENF_AUTO_UNIT_TEST(ipv6Extensions_hopByHop_parse_SN)
{
- unsigned char data[] = {
- 0x3a, 0x01, // Hop-By-Hop Header (nextHeader, length)
+ unsigned char data[] = {
+ 0x3a, 0x01, // Hop-By-Hop Header (nextHeader, length)
0x0d, 0x05, // option type, length
// option value: slfNetType, checksum
0x4d, 0x01, 0x23, 0x45, 0x67,
// padding (PadN option: type, length, 0-padding)
0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
};
-
+
senf::IPv6HopByHopOptionsPacket p ( senf::IPv6HopByHopOptionsPacket::create(data) );
BOOST_CHECK_EQUAL( p->nextHeader(), 0x3a);
-
+
{
typedef senf::IPv6HopByHopOptionsPacket::Parser::options_t::container optContainer_t;
optContainer_t optC (p->options() );
optContainer_t::iterator listIter (optC.begin());
-
+
BOOST_CHECK_EQUAL( listIter->optionType(), 0x0d);
BOOST_CHECK( listIter->is<IPv6ChecksumOptionParser>());
IPv6ChecksumOptionParser opt ( listIter->as<IPv6ChecksumOptionParser>());
boost::io::ios_all_saver ias(os);
os << "Internet protocol Version 6:\n"
<< senf::fieldName("version") << unsigned(p->version()) << "\n"
- << senf::fieldName("traffic class")
+ << senf::fieldName("traffic class")
<< "0x" << std::hex << std::setw(2) << std::setfill('0') << unsigned(p->trafficClass()) << "\n"
- << senf::fieldName("flow label")
+ << senf::fieldName("flow label")
<< "0x" << std::hex << std::setw(5) << std::setfill('0') << unsigned(p->flowLabel()) << "\n"
<< senf::fieldName("payload length") << std::dec << unsigned(p->length()) << "\n"
<< senf::fieldName("next header") << unsigned(p->nextHeader()) << "\n"
namespace senf {
/** \brief Parse an IPv6 address
-
+
\see INet6Address
*/
struct INet6AddressParser : public PacketParserBase
void value(value_type const & v) { std::copy(v.begin(), v.end(), i()); }
operator value_type() const { return value(); }
byte & operator[](size_type index) const { return *boost::next(i(),index); }
- INet6AddressParser const & operator= (value_type const & other)
+ INet6AddressParser const & operator= (value_type const & other)
{ value(other); return *this; }
};
\par Packet type (typedef):
\ref IPv6Packet
-
+
\par Fields:
\ref IPv6PacketParser
\ref IPv6PacketParser::destination() "Destination Address"</td>
</tr>
</table>
-
+
\par Associated registries:
\ref IpTypes
using mixin::initSize;
using mixin::init;
- static key_t nextPacketKey(packet p)
+ static key_t nextPacketKey(packet p)
{ return p->nextHeader(); }
-
+
/** \brief Dump given IPv6Packet in readable form to given output stream */
- static void dump(packet p, std::ostream & os);
-
+ static void dump(packet p, std::ostream & os);
+
static void finalize(packet p); ///< Finalize packet.
- /**< \li set \ref IPv6PacketParser::length() "length"
+ /**< \li set \ref IPv6PacketParser::length() "length"
from payload size
- \li set \ref IPv6PacketParser::nextHeader()
- "nextHeader" from type of next packet if found
+ \li set \ref IPv6PacketParser::nextHeader()
+ "nextHeader" from type of next packet if found
in \ref IpTypes */
};
SENF_AUTO_UNIT_TEST(ipV6Packet_parse)
{
- unsigned char data[] = {
+ unsigned char data[] = {
0x60, 0x12, 0x20, 0x30,
0x00, 0x01, 0x03, 0x04,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
- 0xff
+ 0xff
};
senf::IPv6Packet p (senf::IPv6Packet::create(data));
ip->hopLimit() = 0x04u;
ip->source() = senf::INet6Address::from_string("1011:1213:1415:1617:1819:1a1b:1c1d:1e1f");
ip->destination() = senf::INet6Address::from_string("2021:2223:2425:2627:2829:2a2b:2c2d:2e2f");
-
+
ip.finalizeAll();
-
- unsigned char data[] = {
+
+ unsigned char data[] = {
0x60, 0x12, 0x20, 0x30,
0x00, 0x00, 0x3b, 0x04,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
};
- BOOST_CHECK_EQUAL_COLLECTIONS(
+ BOOST_CHECK_EQUAL_COLLECTIONS(
data, data+sizeof(data), ip.data().begin(), ip.data().end() );
}
prefix_
senf::detail::ListOptionTypeParser_Policy<ElementParser,AuxPolicy>::
ListOptionTypeParser_Policy(Arg const & arg)
- : AuxPolicy(arg)
+ : AuxPolicy(arg)
{}
template <class ElementParser, class AuxPolicy>
prefix_
senf::detail::ListOptionTypeParser_Policy<ElementParser,AuxPolicy>::container_policy::
container_policy(parser_policy const & p)
- : AuxPolicy(p)
+ : AuxPolicy(p)
{}
//destructor
<< senf::fieldName(" dsap") << "0x" << unsigned(p->dsap()) << "\n"
<< senf::fieldName(" ssap") << "0x" << unsigned(p->ssap()) << "\n"
<< senf::fieldName(" control id") << "0x" << unsigned(p->ctrl()) << "\n"
- << " SNAP\n"
+ << " SNAP\n"
<< senf::fieldName(" protocol id") << "0x" << std::setw(6) << unsigned(p->protocolId()) << "\n"
<< senf::fieldName(" type/length") << "0x" << std::setw(4) << unsigned(p->type_length()) << "\n";
}
namespace senf {
/** \brief Parse a LLC/SNAP header
-
+
\image html LlcSnapPacket.png
\todo document me
*/
SENF_PARSER_FIELD( type_length, UInt16Parser );
SENF_PARSER_FINALIZE(LlcSnapPacketParser);
-
+
SENF_PARSER_INIT() {
dsap() = 0xaa;
ssap() = 0xaa;
\ingroup protocolbundle_default
*/
struct LlcSnapPacketType
- : public PacketTypeBase,
+ : public PacketTypeBase,
public PacketTypeMixin<LlcSnapPacketType, EtherTypes>
{
#ifndef DOXYGEN
using mixin::nextPacketRange;
using mixin::initSize;
using mixin::init;
-
+
static factory_t nextPacketType(packet p);
/** \brief Dump given LlcSnapPacket in readable form to given output stream */
- static void dump(packet p, std::ostream & os);
+ static void dump(packet p, std::ostream & os);
static void finalize(packet p);
};
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-/** \file
+/** \file
\brief RTPPacket non-inline non-template implementation */
#include "RTPPacket.hh"
#define prefix_
-namespace
+namespace
{
std::string ptName(int pt)
{
return ptList[n].name;
++n;
}
-
+
return "UNKNOWN";
}
}
<< senf::fieldName("extension") << p->extension() << "\n"
<< senf::fieldName("contributing source cnt") << p->csrcCount() << "\n"
<< senf::fieldName("marker") << p->marker() << "\n"
- << senf::fieldName("payload type") << p->payloadType() << " "
+ << senf::fieldName("payload type") << p->payloadType() << " "
<< ptName(p->payloadType() ) <<"\n"
<< senf::fieldName("sequence number") << p->seqNumber() << "\n"
<< senf::fieldName("timestamp") << p->timeStamp() << "\n"
namespace senf {
-
+
struct RTPPacketParser : public PacketParserBase
{
# include SENF_PARSER()
SENF_PARSER_FIELD ( timeStamp, UInt32Parser ); //signals sampling time of 1st byte of payload; initialised; used to calculate Jitter between segments
SENF_PARSER_FIELD ( synSourceId, UInt32Parser ); //Synchronisation source identifier; identifier of RFTP stream source (random number) in case of conferencing identifier of mixer
SENF_PARSER_VECTOR (csrcOpt, csrcCount, UInt32Parser );
-
+
bool valid() const {return version() == 2;}
SENF_PARSER_FINALIZE(RTPPacketParser);
};
-
- struct RTPPacketType
+
+ struct RTPPacketType
: public PacketTypeBase,
public PacketTypeMixin<RTPPacketType>
{
typedef PacketTypeMixin<RTPPacketType> mixin;
typedef ConcretePacket<RTPPacketType> packet;
typedef RTPPacketParser parser;
-
+
using mixin::nextPacketRange;
using mixin::init;
using mixin::initSize;
-
+
static void dump(packet p, std::ostream &os);
};
-
+
typedef RTPPacketType::packet RTPPacket;
}
"checksum" */
};
- /** \brief TCP packet typedef
+ /** \brief TCP packet typedef
\ingroup protocolbundle_default
*/
typedef ConcretePacket<TCPPacketType> TCPPacket;
0x60, 0xa0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x68, 0x20, 0x01, 0x06, 0x38, 0x04, 0x08, 0x02, 0x01, 0xef,
0xdc, 0x71, 0x52, 0x17, 0x2c, 0x44, 0x3e,
-
+
// 20 Byte TCP-Header without Options
0x00, 0x50, 0xac, 0x3e, 0x82, 0x99, 0x60, 0xa6, 0xa4, 0xfa, 0x32,
0x83, 0x50, 0x18, 0x19, 0x20, 0xd7, 0xcd, 0x00, 0x00,
-
+
// TCP-Payload
0x1a, 0x01, 0x52, 0x0e, 0x26, 0x6f, 0xac, 0xd9, 0x78, 0x0c, 0x3c,
0x69, 0x3c, 0xa6, 0x49, 0xc6, 0x85, 0xc2, 0xa9, 0x72, 0x75, 0x9a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-
+
// TCP-Header + TCP-Payload
0x5b, 0xa0, 0x30, 0x39, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00,
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-/** \file
+/** \file
\brief UDPPacket non-inline non-template implementation */
#include "UDPPacket.hh"
IPv4Packet ipv4 (packet().rfind<IPv4Packet>(nothrow));
if (ipv4) {
// Pseudo header defined in RFC768
- summer.feed( ipv4->source().i(),
+ summer.feed( ipv4->source().i(),
ipv4->source().i() + IPv4Packet::Parser::source_t::fixed_bytes );
///\fixme What about a hop-by-hop routing option? Which destination is used in IPv4 ?
- summer.feed( ipv4->destination().i(),
+ summer.feed( ipv4->destination().i(),
ipv4->destination().i() + IPv4PacketParser::destination_t::fixed_bytes );
summer.feed( 0u );
///\fixme May there be another header between the IPv4 header and UDP? if so, we
/// need to hack the correct protocol number here ...
summer.feed( 17u );
summer.feed( i() + length_offset, i() + length_offset + 2 );
- }
+ }
else {
// Pseudo header defined in RFC2460
IPv6Packet ipv6 (packet().rfind<IPv6Packet>(nothrow));
if (ipv6) {
- summer.feed( ipv6->source().i(),
+ summer.feed( ipv6->source().i(),
ipv6->source().i() + IPv6Packet::Parser::source_t::fixed_bytes );
///\todo Implement routing header support
// The destination used here must be the *final* destination ...
- summer.feed( ipv6->destination().i(),
+ summer.feed( ipv6->destination().i(),
ipv6->destination().i() + IPv6PacketParser::destination_t::fixed_bytes );
// This is a simplification. The value is really 32bit to support UDP Jumbograms
// (RFC2147). However, skipping an even number of 0 bytes does not change the checksum
summer.feed( 17u );
}
}
-
- // since header are 16 / even 32bit aligned we don't have to care for padding. since IpChecksum
+
+ // since header are 16 / even 32bit aligned we don't have to care for padding. since IpChecksum
// cares for padding at the final summing we don't have to care is the payload is 16nbit-aligned, too.
summer.feed( i(), i()+checksum_offset );
summer.feed( i()+checksum_offset+2, data().end() );
Parser implementing the UDP header. The fields implemented are:
\image html UDPPacket.png
-
+
\see UDPPacketType \n
<a href="http://tools.ietf.org/html/rfc768">RFC 768</a>
*/
};
/** \brief UDP packet
-
+
\par Packet type (typedef):
\ref UDPPacket
<td colspan="3">\ref UDPPacketParser::checksum() "Checksum"</td>
</tr>
</table>
-
+
\par Finalize action:
\copydetails finalize()
/** \brief Dump given UDPPacket in readable form to given output stream */
static void dump(packet p, std::ostream & os);
-
+
static void finalize(packet p); ///< Finalize packet.
- /**< \li set \ref UDPPacketParser::length() "length" from
+ /**< \li set \ref UDPPacketParser::length() "length" from
payload size
- \li calculate and set \ref UDPPacketParser::checksum()
+ \li calculate and set \ref UDPPacketParser::checksum()
"checksum" */
};
- /** \brief UDP packet typedef
+ /** \brief UDP packet typedef
\ingroup protocolbundle_default
*/
typedef ConcretePacket<UDPPacketType> UDPPacket;
SENF_AUTO_UNIT_TEST(udpPacket_parse)
{
- unsigned char data[] = {
+ unsigned char data[] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
};
SENF_AUTO_UNIT_TEST(udpPacket_in_ipv4_create)
{
- unsigned char data[] = {
+ unsigned char data[] = {
0x45, 0x00, 0x00, 0x26, 0x00, 0x00, 0x40, 0x00,
0x40, 0x11, 0x3c, 0xc5, 0x7f, 0x00, 0x00, 0x01,
0x7f, 0x00, 0x00, 0x01, 0x5b, 0xa0, 0x30, 0x39,
0x00, 0x12, 0xfa, 0x6e, 0x54, 0x45, 0x53, 0x54,
- 0x2d, 0x57, 0x52, 0x49, 0x54, 0x45
+ 0x2d, 0x57, 0x52, 0x49, 0x54, 0x45
};
senf::IPv4Packet ip (senf::IPv4Packet::create());
BOOST_CHECK( udp->validateChecksum() );
ip.finalizeAll();
- BOOST_CHECK_EQUAL_COLLECTIONS(
+ BOOST_CHECK_EQUAL_COLLECTIONS(
data, data+sizeof(data), ip.data().begin(), ip.data().end() );
BOOST_CHECK( udp->validateChecksum() );
}
SENF_AUTO_UNIT_TEST(udpPacket_in_ipv6_parse)
{
// captured udp packet generated with mgen send over ipv6
- unsigned char data[] = {
+ unsigned char data[] = {
// IPv6 Packet
0x60, 0x00, 0x00, 0x00, 0x00, 0x32, 0x11, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x09, 0x5b, 0x37, 0x13, 0x88, 0x02, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00
+ 0x00, 0x00
};
senf::IPv6Packet ip (senf::IPv6Packet::create(data));
BOOST_CHECK_EQUAL( ip->hopLimit(), 64u );
BOOST_CHECK_EQUAL( ip->source().value(), senf::INet6Address::Loopback );
BOOST_CHECK_EQUAL( ip->destination().value(), senf::INet6Address::Loopback );
-
+
std::ostringstream oss (std::ostringstream::out);
SENF_CHECK_NO_THROW( ip.dump( oss));
-
+
BOOST_REQUIRE( ip.next().is<senf::UDPPacket>() );
senf::UDPPacket udp (ip.next().as<senf::UDPPacket>());
-
+
BOOST_CHECK_EQUAL( udp->source(), 5001u );
BOOST_CHECK_EQUAL( udp->destination(), 5000u );
BOOST_CHECK_EQUAL( udp->length(), 50u );
BOOST_CHECK_EQUAL( udp->checksum(), 0x1123 );
-
+
BOOST_CHECK( udp->validateChecksum() );
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // target mac
0x86, 0xdd, // ethertype
- 0x60, 0x00, 0x00, 0x00, // IP version, class,
+ 0x60, 0x00, 0x00, 0x00, // IP version, class,
// flow label
0x00, 0x00, // payload length
0x3B, // no next header
0x10, // hop limit
0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // source ip
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // target ip
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 };
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace senf {
std::string fieldName(std::string const & s);
-
+
}
///////////////////////////////hh.e////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
template <class Base>
template <class Parser>
prefix_ Parser senf::GenericTLVParserBase<Base>::init()
-{
+{
senf::PacketParserBase::size_type oldSize (bytes() );
senf::PacketParserBase::size_type newParserSize ( senf::init_bytes<Parser>::value );
this->resize( oldSize, newParserSize);
template <class Base>
prefix_ void senf::GenericTLVParserBase<Base>::dump(std::ostream & os)
- const
+ const
{
if (Base::Registry::instance().isRegistered( *this)) {
Base::Registry::instance().dump( *this, os);
}
template <class Base>
-prefix_ senf::PacketInterpreterBase::range senf::GenericTLVParserBase<Base>::value()
- const
+prefix_ senf::PacketInterpreterBase::range senf::GenericTLVParserBase<Base>::value()
+ const
{
senf::PacketData::iterator begin ( boost::next(this->i(), senf::bytes( self())) );
return PacketInterpreterBase::range(begin, boost::next( begin, this->length()) );
throw TLVParserNotRegisteredException();
}
-
+
///////////////////////////////ct.e////////////////////////////////////////
#undef prefix_
prefix_ void senf::GenericTLVParserBase<Base>::value(
ForwardReadableRange const & val,
typename boost::disable_if<senf::is_pair<ForwardReadableRange> >::type *)
-{
- value_( val);
+{
+ value_( val);
}
template <class Base>
prefix_ void senf::GenericTLVParserBase<Base>::value(
std::pair<First, Second> const & val,
typename boost::disable_if<boost::is_convertible<First, typename Base::type_t::value_type> >::type *)
-{
- value_( val);
+{
+ value_( val);
}
template <class Base>
prefix_ void senf::GenericTLVParserBase<Base>::value(
std::pair<Type, ForwardReadableRange> const & val,
typename boost::enable_if<boost::is_convertible<Type, typename Base::type_t::value_type> >::type *)
-{
+{
this->type() = val.first;
- value_( val.second);
+ value_( val.second);
}
#endif
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
-
+
/** \brief Base class for generic TLV parsers
-
+
This abstract base class can be used to define generic TLV parsers. The following
class structure is assumed:
\image html GenericTLV.png
-
+
Your TLVParser base class has to define a \c type and a \c length field:
\code
struct MyTLVParserBase : public senf::PacketParserBase
SENF_PARSER_FINALIZE ( MyTLVParserBase );
};
\endcode
-
+
Your concrete TLV parsers will inherit from this base class and have to define a specific
value field and a \c typeId member:
\code
SENF_PARSER_INHERIT ( MyTLVParserBase );
SENF_PARSER_FIELD ( myValue, senf::UInt32Parser );
SENF_PARSER_FINALIZE ( MyConcreteTLVParser );
-
+
SENF_PARSER_INIT() {
type() = typeId;
length_() = 4;
- }
+ }
static const type_t::value_type typeId = 0x42;
};
\endcode
-
+
With GenericTLVParserBase you can define a generic parser class which provides
members to access the value data and and to cast the parser to a concrete tlv
- parser:
+ parser:
\code
struct MyGenericTLVParser : public senf::GenericTLVParserBase<MyTLVParserBase>
{
typedef senf::GenericTLVParserBase<MyTLVParserBase> base;
MyGenericTLVParser(data_iterator i, state_type s) : base(i,s) {}
-
+
// members for your generic TLV parser...
};
\endcode
-
+
If your generic TLV parser just inherits from GenericTLVParserBase and doesn't
add any additional functionality you can use a simple \c typedef as well:
\code
typedef senf::GenericTLVParserBase<MyTLVParserBase> MyGenericTLVParser;
\endcode
-
+
This generic tlv parser can now be used for example in a list:
\code
class MyTestPacketParser : public senf::PacketParserBase
SENF_PARSER_FINALIZE ( MyTestPacketParser );
};
\endcode
-
+
Now, you can access the TLV parsers in the list in a generic way or you
can cast the parsers to some concrete tlv parser:
\code
typedef MyTestPacket::Parser::tlv_list_t::container container_t;
container_t tlvContainer (p->tlv_list() );
optContainer_t::iterator listIter (tlvContainer.begin());
-
+
// listIter points to a MyGenericTLVParser, so you have generic access:
listIter->type() = 0x42;
listIter->value( someRangeOfValueData);
-
+
// cast to an instance of MyConcreteTLVParser:
if (listIter->is<MyConcreteTLVParser>()) {
MyConcreteTLVParser concreteTLVParser ( listIter->as<MyConcreteTLVParser>());
concreteTLVParser.myValue() = 0xabababab;
}
-
+
// add a MyConcreteTLV to the list:
MyConcreteTLVParser tlv ( tlvContainer.push_back_space().init<MyConcreteTLVParser>());
tlv.myValue() = 0xffff;
- \endcode
+ \endcode
- \see
+ \see
IPv6GenericOptionParser, WLANGenericInfoElementParser, MIHGenericTLVParser \n
GenericTLVParserRegistry
*/
class GenericTLVParserBase : public Base
{
public:
- GenericTLVParserBase(senf::PacketParserBase::data_iterator i, senf::PacketParserBase::state_type s)
+ GenericTLVParserBase(senf::PacketParserBase::data_iterator i, senf::PacketParserBase::state_type s)
: Base(i,s) {}
-
+
senf::PacketParserBase::size_type bytes() const;
void init() const;
template <class Parser>
Parser init();
-
+
template <class Parser>
Parser as() const;
-
+
template <class Parser>
bool is() const;
senf::PacketInterpreterBase::range value() const;
void dump(std::ostream & os) const;
-
+
#ifndef DOXYGEN
template<class ForwardReadableRange>
void value(ForwardReadableRange const & val,
template <class Type, class ForwardReadableRange>
void value(std::pair<Type, ForwardReadableRange> const & val,
- typename boost::enable_if<boost::is_convertible<Type, typename Base::type_t::value_type> >::type * = 0);
+ typename boost::enable_if<boost::is_convertible<Type, typename Base::type_t::value_type> >::type * = 0);
#else
template<class ForwardReadableRange>
void value(ForwardReadableRange const & val);
-
+
template <class ForwardReadableRange>
void value(std::pair<typename Base::type_t::value_type, ForwardReadableRange> const & val);
-#endif
-
+#endif
+
private:
template<class ForwardReadableRange>
void value_(ForwardReadableRange const &range);
-
+
Base & self();
Base const & self() const;
};
-
-
+
+
namespace detail {
template <class BaseParser>
struct GenericTLVParserRegistry_EntryBase {
virtual void dump(GenericTLVParserBase<BaseParser> const & parser, std::ostream & os) const = 0;
virtual PacketParserBase::size_type bytes(GenericTLVParserBase<BaseParser> const & parser) const = 0;
};
-
+
template <class BaseParser, class Parser>
struct GenericTLVParserRegistry_Entry
: GenericTLVParserRegistry_EntryBase<BaseParser>
virtual void dump(GenericTLVParserBase<BaseParser> const & parser, std::ostream & os) const;
virtual PacketParserBase::size_type bytes(GenericTLVParserBase<BaseParser> const & parser) const;
};
-
+
//Helper Functor for STL-compatible predicate (E.g. find_if, for_each ...)
template <class BaseParser, class Parser>
class Predicate
}
};
}
-
+
/** \brief TLV parser registration facility
The %GenericTLVParserRegistry provides a generic facility to globally register concrete
TLV parser by the type value. The concrete TLV parser must therefore provide a \c typeId
member. See GenericTLVParserBase for details about the assumed class structure.
-
- Every registry is identified by the base tlv parser class. Parsers can be registered
- statically only:
+
+ Every registry is identified by the base tlv parser class. Parsers can be registered
+ statically only:
\code
GenericTLVParserRegistry<MyTLVParserBase>::RegistrationProxy<ConcreteTLVParser>
registerConcreteTLVParser;
- \endcode
- This global variable declaration will register ConcreteTLVParser. The variable
- registerConcreteTLVParser is a dummy. It's only function is to force the call of
+ \endcode
+ This global variable declaration will register ConcreteTLVParser. The variable
+ registerConcreteTLVParser is a dummy. It's only function is to force the call of
it's constructor during global construction time. This static registration only
works when the symbol is included into the final binary.
-
+
To simplify the registration the \ref SENF_PACKET_TLV_REGISTRY_REGISTER macro can be used.
The \c ConreteTLVParser must therefore provide a \c Registry typedef pointing to the
%GenericTLVParserRegistry; typically you put this typedef to the TLVBaseParser class.
static const type_t::value_type typeId = 0x42;
void dump(std::ostream & os) const;
};
-
+
// register MyConcreteTLVParser to the MyTLVParserBase-Registry with the type id 0x42:
SENF_PACKET_TLV_REGISTRY_REGISTER( MyConcreteTLVParser );
\endcode
-
+
The registry provides a dump() member to dump an instance of a generic TLV parser.
If the type value of the given TLV parser is registered the generic tlv will be
casted to the registered concrete TLV parser and the dump member from this parser
will be called.
-
+
\see
GenericTLVParserBase for the general TLV class structure \n
IPv6OptionParser::Registry, WLANInfoElementParser::Registry,
- MIHBaseTLVParser::Registry
+ MIHBaseTLVParser::Registry
*/
template <class BaseParser, class Keytype = typename BaseParser::type_t::value_type>
class GenericTLVParserRegistry
: public senf::singleton<GenericTLVParserRegistry<BaseParser,Keytype> >
{
- typedef boost::ptr_map<Keytype,
+ typedef boost::ptr_map<Keytype,
detail::GenericTLVParserRegistry_EntryBase<BaseParser> > Map;
Map map_;
-
+
GenericTLVParserRegistry() {};
public:
using senf::singleton<GenericTLVParserRegistry<BaseParser,Keytype> >::instance;
friend class senf::singleton<GenericTLVParserRegistry<BaseParser,Keytype> >;
-
+
template <class PacketParser>
struct RegistrationProxy {
RegistrationProxy();
template <typename Parser>
void registerParser();
-
+
typedef GenericTLVParserBase<BaseParser> GenericTLVParser;
-
+
bool isRegistered(GenericTLVParserBase<BaseParser> const & parser) const;
bool isRegistered(Keytype const & key) const;
-
+
void dump(GenericTLVParser const & parser, std::ostream & os) const;
void dump(GenericTLVParser const & parser, Keytype const & key, std::ostream & os) const;
-
+
PacketParserBase::size_type bytes(GenericTLVParser const & parser) const;
PacketParserBase::size_type bytes(GenericTLVParser const & parser, Keytype const & key) const;
};
-
+
struct TLVParserNotRegisteredException : public senf::Exception
- {
- TLVParserNotRegisteredException() : senf::Exception("tlv parser not registered") {}
+ {
+ TLVParserNotRegisteredException() : senf::Exception("tlv parser not registered") {}
};
-
+
/** \brief Statically add an entry to a TLV parser registry
- This macro will declare an anonymous global variable in such a way, that constructing
+ This macro will declare an anonymous global variable in such a way, that constructing
this variable will register the given tlv parser.
\hideinitializer
ConreteTLVParser::Registry::RegistrationProxy<ConreteTLVParser> \
BOOST_PP_CAT(tlvparserRegistration_, __LINE__); \
}
-
+
}
///////////////////////////////hh.e////////////////////////////////////////
///////////////////////////////cc.p////////////////////////////////////////
namespace {
- struct MyTLVParserBase
+ struct MyTLVParserBase
: public senf::PacketParserBase
{
# include SENF_PARSER()
SENF_PARSER_FIELD ( type, senf::UInt8Parser );
SENF_PARSER_FIELD_RO ( length, senf::UInt8Parser );
SENF_PARSER_FINALIZE ( MyTLVParserBase );
-
+
typedef senf::GenericTLVParserRegistry<MyTLVParserBase> Registry;
};
-
+
struct MyGenericTLVParser
: public senf::GenericTLVParserBase<MyTLVParserBase>
{
typedef senf::GenericTLVParserBase<MyTLVParserBase> base;
MyGenericTLVParser(data_iterator i, state_type s) : base(i,s) {}
};
-
+
struct MyConcreteTLVParser
: public MyTLVParserBase
{
SENF_PARSER_INHERIT ( MyTLVParserBase );
SENF_PARSER_FIELD ( myValue, senf::UInt32Parser );
SENF_PARSER_FINALIZE ( MyConcreteTLVParser );
-
+
SENF_PARSER_INIT() {
type() = typeId;
length_() = 4;
}
static type_t::value_type const typeId = 0x42;
-
+
void dump(std::ostream & os) const {
boost::io::ios_all_saver ias(os);
os << " MyConcreteTLVParser\n"
<< " value: " << senf::format::dumpint(myValue()) << "\n";
}
};
-
+
struct MyConcrete2TLVParser
: public MyTLVParserBase
{
SENF_PARSER_INHERIT ( MyTLVParserBase );
SENF_PARSER_FIELD ( myValue, senf::UInt32Parser );
SENF_PARSER_FINALIZE ( MyConcrete2TLVParser );
-
+
SENF_PARSER_INIT() {
type() = typeId;
length_() = 4;
}
static type_t::value_type const typeId = 0x47;
-
+
void dump(std::ostream & os) const {
boost::io::ios_all_saver ias(os);
os << " MyConcreteTLVParser\n"
<< " value: " << senf::format::dumpint(myValue()) << "\n";
}
};
-
+
class MyTestPacketParser
: public senf::PacketParserBase
{
SENF_PARSER_LIST ( tlv_list, list_length, MyGenericTLVParser );
SENF_PARSER_FINALIZE ( MyTestPacketParser );
};
-
+
struct MyTestPacketType
: public senf::PacketTypeBase,
public senf::PacketTypeMixin<MyTestPacketType>
SENF_AUTO_UNIT_TEST(GenericTLV_parser)
{
- BOOST_CHECK_EQUAL( senf::init_bytes<MyGenericTLVParser>::value,
+ BOOST_CHECK_EQUAL( senf::init_bytes<MyGenericTLVParser>::value,
senf::init_bytes<MyTLVParserBase>::value) ;
unsigned char data[] = {
SENF_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data),
genericTLVParser.value().begin(), genericTLVParser.value().end() );
- std::vector<unsigned char> value (4, 0xab);
+ std::vector<unsigned char> value (4, 0xab);
genericTLVParser.value( std::make_pair(0x42, value));
-
+
BOOST_CHECK( genericTLVParser.is<MyConcreteTLVParser>());
MyConcreteTLVParser concreteTLVParser ( genericTLVParser.as<MyConcreteTLVParser>());
MyConcreteTLVParser tlv ( tlvContainer.push_back_space().init<MyConcreteTLVParser>());
tlv.myValue() << 0xffff;
p.finalizeThis();
-
+
unsigned char data[] = {
0x01, // tlv list length
// first tlv:
typedef senf::GenericTLVParserRegistry<MyTLVParserBase> MyTLVParserRegistry;
MyTestPacket p ( MyTestPacket::create());
MyTestPacket::Parser::tlv_list_t::container tlvContainer (p->tlv_list() );
- MyConcreteTLVParser conreteTLVParser (
+ MyConcreteTLVParser conreteTLVParser (
tlvContainer.push_back_space().init<MyConcreteTLVParser>());
conreteTLVParser.myValue() << 0xffff;
p.finalizeThis();
-
+
std::stringstream ss;
tlvContainer.begin()->dump( ss);
- BOOST_CHECK_EQUAL( ss.str().substr(0,58),
+ BOOST_CHECK_EQUAL( ss.str().substr(0,58),
" GenericTLVParser<(anonymous namespace)::MyTLVParserBase>" );
BOOST_CHECK( ! MyTLVParserRegistry::instance().isRegistered( tlvContainer.begin()->type()));
-
+
MyTLVParserRegistry::instance().registerParser<MyConcreteTLVParser>();
BOOST_CHECK( MyTLVParserRegistry::instance().isRegistered( tlvContainer.begin()->type()));
- BOOST_CHECK_EQUAL(
+ BOOST_CHECK_EQUAL(
MyTLVParserRegistry::instance().bytes( *tlvContainer.begin()),
senf::bytes( *tlvContainer.begin()) );
-
+
ss.str(""); ss.clear();
-
+
tlvContainer.begin()->dump( ss);
BOOST_CHECK_EQUAL( ss.str().substr(0,21), " MyConcreteTLVParser" );
}
{
MyTestPacket p ( MyTestPacket::create() );
MyTestPacket::Parser::tlv_list_t::container tlvContainer (p->tlv_list() );
- MyConcreteTLVParser conreteTLVParser (
+ MyConcreteTLVParser conreteTLVParser (
tlvContainer.push_back_space().init<MyConcreteTLVParser>());
conreteTLVParser.myValue() << 0xffff;
- MyConcrete2TLVParser conreteTLVParser2 (
+ MyConcrete2TLVParser conreteTLVParser2 (
tlvContainer.push_back_space().init<MyConcrete2TLVParser>());
conreteTLVParser2.myValue() << 0xdddd;
p.finalizeThis();
-
-// typedef senf::IPv6HopByHopOptionsPacket::Parser::options_t::container optContainer_t;
+
+// typedef senf::IPv6HopByHopOptionsPacket::Parser::options_t::container optContainer_t;
// optContainer_t optC (p->tlv_list() );
-
+
MyTestPacket::Parser::tlv_list_t::container testTlvContainer (p->tlv_list() );
MyTestPacket::Parser::tlv_list_t::container::iterator it = std::find_if (
- testTlvContainer.begin(), testTlvContainer.end(),
+ testTlvContainer.begin(), testTlvContainer.end(),
senf::detail::Predicate< senf::GenericTLVParserBase<MyTLVParserBase>, MyConcreteTLVParser>() );
BOOST_CHECK( it->is<MyConcreteTLVParser>()) ;
}
\li <tt>p = v</tt>: Assigns the value to the packet field.
\li <tt>p.value(v)</tt>: same as above.
\li <tt>p.value()</tt>: Returns the fields value as an integer number.
- \li Use of p like an integer in most contexts: <tt>p += v</tt>, <tt>p *= v</tt>, <tt>v = p +
+ \li Use of p like an integer in most contexts: <tt>p += v</tt>, <tt>p *= v</tt>, <tt>v = p
1</tt> and so on. You will only need to use the explicit \c value() member in rare
circumstances when the automatic conversion is ambiguous or in some template contexts.
// $Id$
//
-// Copyright (C) 2010
+// Copyright (C) 2010
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
const
{
return boost::next( container_type::iterator::get(d).i(),
- senf::bytes(ElementParser( container_type::iterator::get(d).i(),
+ senf::bytes(ElementParser( container_type::iterator::get(d).i(),
c.state() )) );
}
};
template <class ElementParser, class AuxPolicy, class Transform>
- struct ListParserPolicy<ElementParser, AuxPolicy,
- senf::detail::auxtag::transform<Transform,
+ struct ListParserPolicy<ElementParser, AuxPolicy,
+ senf::detail::auxtag::transform<Transform,
senf::detail::auxtag::bytes> >
{
typedef ListBParser_Policy< ElementParser,
{
senf::PacketInterpreterBase::ptr pi (senf::PacketInterpreter<VoidPacket>::create(
MyListBParser::init_bytes));
-
+
MyListBParser p (pi->data().begin(),&pi->data());
p.init();
BOOST_CHECK_EQUAL( p.size(), 0u );
{
senf::PacketInterpreterBase::ptr pi (senf::PacketInterpreter<VoidPacket>::create(
MyListBParser::init_bytes));
-
+
{
MyListBParser::container c (MyListBParser(pi->data().begin(),&pi->data()));
-
+
BOOST_CHECK_EQUAL( c.size(), 0u );
BOOST_CHECK_EQUAL( c.bytes(), 2u );
BOOST_CHECK( c.begin() == c.end() );
-
+
c.shift(c.begin());
BOOST_CHECK_EQUAL( c.size(), 1u );
BOOST_CHECK_EQUAL( c.bytes(), 3u );
BOOST_CHECK_EQUAL(c2.size(), 1u);
BOOST_CHECK_EQUAL(c2.bytes(), 7u);
-
+
c.insert(c.end(),c2.back());
BOOST_CHECK_EQUAL( c.size(), 2u );
BOOST_CHECK_EQUAL( c.bytes(), 10u );
c.insert(boost::next(c.begin()), 2u, c2.back());
BOOST_CHECK_EQUAL( c.size(), 4u );
BOOST_CHECK_EQUAL( c.bytes(), 20u );
- BOOST_CHECK_EQUAL( (*boost::next(c.begin())).vec()[0], 0x1357u );
+ BOOST_CHECK_EQUAL( (*boost::next(c.begin())).vec()[0], 0x1357u );
BOOST_CHECK_EQUAL( (*boost::next(c.begin(),2)).vec()[0], 0x1357u );
c2.back().vec()[0] << 0x2468u;
BOOST_CHECK_EQUAL( c.bytes(), 17u );
BOOST_CHECK_EQUAL( c.front().vec()[0],0x1357u );
BOOST_CHECK_EQUAL( c.back().vec()[0], 0x2345u );
-
+
c.erase((boost::next(c.begin(),2)),c.end());
BOOST_CHECK_EQUAL( c.size(), 2u );
BOOST_CHECK_EQUAL( c.bytes(), 12u );
}
namespace {
-
+
struct TestTransform
{
typedef unsigned value_type;
SENF_PARSER_PRIVATE_FIELD ( size2 , senf::UInt8Parser );
SENF_PARSER_FIELD ( dummy , senf::UInt32Parser );
SENF_PARSER_LIST ( list1 , bytes(size1) , VectorParser );
- SENF_PARSER_LIST ( list2 , transform(TestTransform, bytes(size2)) ,
+ SENF_PARSER_LIST ( list2 , transform(TestTransform, bytes(size2)) ,
VectorParser );
SENF_PARSER_FINALIZE(TestListParser);
0x0D, 0x0E, // list2()[1].vec()[1]
0x01, // list2()[2].size()
0x0F, 0x10 }; // list2()[2].vec()[0]
-
+
senf::DataPacket p (senf::DataPacket::create(data));
TestListParser parser (p.data().begin(), &p.data());
-
+
BOOST_CHECK_EQUAL( parser.list1().size(), 2u );
BOOST_CHECK_EQUAL( parser.list2().size(), 3u );
BOOST_CHECK_EQUAL( parser.dummy(), 0x01020304u );
BOOST_CHECK_EQUAL( i->vec().size(), 2u );
BOOST_CHECK_EQUAL( i->vec()[0], 0x0708u );
BOOST_CHECK_EQUAL( i->vec()[1], 0x090Au );
-
+
++i;
BOOST_CHECK( i == list.end() );
}
BOOST_CHECK_EQUAL( i->vec().size(), 2u );
BOOST_CHECK_EQUAL( i->vec()[0], 0x0B0Cu );
BOOST_CHECK_EQUAL( i->vec()[1], 0x0D0Eu );
-
+
++i;
BOOST_CHECK_EQUAL( i->vec().size(), 1u );
BOOST_CHECK_EQUAL( i->vec()[0], 0x0F10u );
-
+
++i;
BOOST_CHECK( i == list.end() );
}
0x0D, 0x0E, // list()[3].vec()[1]
0x01, // list()[4].vec().size()
0x0F, 0x10 }; // list()[4].vec()[0]
-
+
senf::DataPacket p (senf::DataPacket::create(data));
{
size_type bytes (data_iterator i, state_type s) const;
size_type size (data_iterator i, state_type s) const;
void init (data_iterator i, state_type s) const;
-
+
void construct (container_type & c) const;
void destruct (container_type & c) const;
void erase (container_type & c, data_iterator p) const;
};
template <class ElementParser, class AuxPolicy, class Transform>
- struct ListParserPolicy<ElementParser, AuxPolicy,
- senf::detail::auxtag::transform<Transform,
+ struct ListParserPolicy<ElementParser, AuxPolicy,
+ senf::detail::auxtag::transform<Transform,
senf::detail::auxtag::none> >
{
typedef ListNParser_Policy< ElementParser,
SENF_PARSER_PRIVATE_FIELD( size, senf::UInt8Parser );
SENF_PARSER_VECTOR( vec, size, senf::UInt16Parser );
-
+
SENF_PARSER_FINALIZE(MyVec);
};
BOOST_CHECK_EQUAL( p.size(), 2u );
BOOST_CHECK_EQUAL( p.bytes(), 8u );
BOOST_CHECK_EQUAL( p.back().vec().size(), 0u );
-
+
p.back().vec().push_front(0x0123u);
BOOST_CHECK_EQUAL( p.front().vec().size(), 2u );
BOOST_CHECK_EQUAL( p.back().vec().size(), 1u );
p.push_front_space(2u);
BOOST_CHECK_EQUAL( p.size(), 4u );
BOOST_CHECK_EQUAL( p.front().vec().size(), 0u);
-
+
p.resize(3u);
BOOST_CHECK_EQUAL( p.size(), 3u );
BOOST_CHECK_EQUAL( p.back().vec()[0], 0x1234u );
}
namespace {
-
+
struct TestTransform
{
typedef unsigned value_type;
0x0D, 0x0E, // list2()[1].vec()[1]
0x01, // list2()[2].size()
0x0F, 0x10 }; // list2()[2].vec()[0]
-
+
senf::DataPacket p (senf::DataPacket::create(data));
TestListParser parser (p.data().begin(), &p.data());
-
+
BOOST_CHECK_EQUAL( parser.list1().size(), 2u );
BOOST_CHECK_EQUAL( parser.list2().size(), 3u );
BOOST_CHECK_EQUAL( parser.dummy(), 0x01020304u );
BOOST_CHECK_EQUAL( i->vec().size(), 2u );
BOOST_CHECK_EQUAL( i->vec()[0], 0x0708u );
BOOST_CHECK_EQUAL( i->vec()[1], 0x090Au );
-
+
++i;
BOOST_CHECK( i == list.end() );
}
BOOST_CHECK_EQUAL( i->vec().size(), 2u );
BOOST_CHECK_EQUAL( i->vec()[0], 0x0B0Cu );
BOOST_CHECK_EQUAL( i->vec()[1], 0x0D0Eu );
-
+
++i;
BOOST_CHECK_EQUAL( i->vec().size(), 1u );
BOOST_CHECK_EQUAL( i->vec()[0], 0x0F10u );
-
+
++i;
BOOST_CHECK( i == list.end() );
}
API however you will need to instantiate a container wrapper for the list. See \ref
packet_usage_fields_collection.
- \see
+ \see
How to access \ref packet_usage_fields_collection \n
SENF_PARSER_LIST() macro used to define list fields \n
ListParser_Container list container wrapper API \n
// Define the list
SENF_PARSER_LIST ( list, list_size_, EltParser );
\endcode
-
+
Here \c EltParser can be an arbitrary parser and need not have a fixed size.
\warning Realize, that the \a size field is controlled by the list parser. This field
<tr><td>\c transform(\a transform, \c bytes(\a size))</td><td>The \a transform is applied to
the \a size value. The value is then interpreted containing the list size in bytes not
- number of elements</td>
+ number of elements</td>
</table>
The optional \a transform is a class with the following layout
static value_type get(other_type v);
static other_type set(value_type v);
};
- \endcode
+ \endcode
\c other_type is \a size ::\c value_type, the type of the value returned by the \a size
field, whereas the \c value_type typedef is the arbitrary return type of the transform.
\param[in] size name of field giving the list size
\param[in] elt_type list element type
- \see
+ \see
How to use \ref packet_usage_fields_collection \n
senf::ListParser the list parser API for list field access
senf::ListParser_Container the list parser container API for list field access
PacketParserBase::data_iterator raw() const;
PacketParserBase::data_iterator i() const;
-
+
static ListParser_Iterator & get(typename Container::policy::iterator_data & d);
static ListParser_Iterator const & get(typename Container::policy::iterator_data const & d);
private:
friend class boost::iterator_core_access;
template <class P> friend class ListParser_Container;
-
+
value_type dereference() const;
bool equal(ListParser_Iterator const & other) const;
void increment();
<< senf::fieldName("tunnel protocol") << unsigned(p->tunnelProtocol()) << "\n"
<< senf::fieldName("number of BDL ips") << unsigned(p->fbipCount()) << "\n"
<< " feed BDL ips:\n";
-
+
switch (p->ipVersion()) {
case 4 : {
typedef DTCPHelloPacket::Parser::v4fbipList_t FBIPList;
# define DTCP_V6_MCADDRESS "FF02:0:0:0:0:0:1:4"
# define DTCP_UDP_PORT 652
- struct DTCPIPv4AddressListParser : public PacketParserBase
+ struct DTCPIPv4AddressListParser : public PacketParserBase
{
-# include SENF_PARSER()
+# include SENF_PARSER()
SENF_PARSER_PRIVATE_FIELD( fbipCount_, UInt8Parser ); //<pkgdraw: hide
SENF_PARSER_PRIVATE_FIELD( reserved_, UInt8Parser ); //<pkgdraw: hide
SENF_PARSER_FINALIZE(DTCPIPv4AddressListParser);
};
-
- struct DTCPIPv6AddressListParser : public PacketParserBase
+
+ struct DTCPIPv6AddressListParser : public PacketParserBase
{
-# include SENF_PARSER()
+# include SENF_PARSER()
SENF_PARSER_PRIVATE_FIELD( fbipCount_, UInt8Parser ); //<pkgdraw: hide
SENF_PARSER_PRIVATE_FIELD( reserved_, UInt8Parser ); //<pkgdraw: hide
/** \brief Parse a DTCP HELLO packet
Parser implementing the DTCP packet according to RFC 3077
-
+
\see DTCPHelloPacketType
*/
struct DTCPHelloPacketParser : public PacketParserBase
SENF_PARSER_BITFIELD ( receiveCapableFeed, 1, bool );
SENF_PARSER_BITFIELD_RO ( ipVersion, 4, unsigned ); // 4=IPv4, 6=IPv6
- SENF_PARSER_FIELD ( tunnelProtocol, UInt8Parser );
+ SENF_PARSER_FIELD ( tunnelProtocol, UInt8Parser );
SENF_PARSER_FIELD_RO ( fbipCount, UInt8Parser );
//>pkgdraw: name=
- SENF_PARSER_PRIVATE_FIELD ( reserved1_, UInt8Parser ); // must be zero
+ SENF_PARSER_PRIVATE_FIELD ( reserved1_, UInt8Parser ); // must be zero
// Go back to fbipCount so the variant has access to that field
SENF_PARSER_GOTO( fbipCount );
SENF_PARSER_VARIANT ( fbipList_, ipVersion,
( ids(na, has_v4fbipList, init_v4fbipList,
- key(4, DTCPIPv4AddressListParser)) )
+ key(4, DTCPIPv4AddressListParser)) )
( ids(na, has_v6fbipList, init_v6fbipList,
key(6, DTCPIPv6AddressListParser)) ) );
typedef DTCPIPv6AddressListParser::fbips_t v6fbipList_t;
v6fbipList_t v6fbipList() { return fbipList_().get<1>().fbips(); }
-
+
SENF_PARSER_FINALIZE(DTCPHelloPacketParser);
};
-
+
/** \brief DTCP HELLO packet
-
+
\par Packet type (typedef):
\ref DTCPHelloPacket
typedef PacketTypeMixin<DTCPHelloPacketType> mixin;
typedef ConcretePacket<DTCPHelloPacketType> packet;
typedef DTCPHelloPacketParser parser;
-
+
using mixin::nextPacketRange;
using mixin::init;
using mixin::initSize;
-
+
static void dump(packet p, std::ostream & os);
};
-
+
/** \brief DTCP packet typedef */
typedef DTCPHelloPacketType::packet DTCPHelloPacket;
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
SENF_AUTO_UNIT_TEST(dtcpPacket)
{
- unsigned char data[] = {
+ unsigned char data[] = {
0x11, // versionNumber = 1, command = JOIN
5, // interval
0x0A, 0x0B, // sequence number
std::stringstream ss;
hello.dump(ss);
- BOOST_CHECK_EQUAL( ss.str(),
+ BOOST_CHECK_EQUAL( ss.str(),
"DTCP HELLO Packet:\n"
" version : 1\n"
" command : JOIN\n"
/** \brief Parse a GRE packet
Parser implementing the header of a General Routing Encapsulation (GRE, RFC 2784) Packet
-
+
\see GREPacketType
*/
struct GREChecksumParser : public PacketParserBase {
-# include SENF_PARSER()
+# include SENF_PARSER()
SENF_PARSER_FIELD ( checksum1_, UInt16Parser );
SENF_PARSER_PRIVATE_FIELD ( reserved1_, UInt16Parser );
SENF_PARSER_FINALIZE(GREChecksumParser);
SENF_PARSER_FIELD ( protocol_type, UInt16Parser );
SENF_PARSER_PRIVATE_VARIANT ( checksum_, checksum_present,
(VoidPacketParser) (GREChecksumParser) );
-
+
SENF_PARSER_FINALIZE( GREPacketParser );
- private:
+ private:
UInt16Parser checksum() const /// only defined if checksum_present() == \c true
{ return checksum_().get<1>().checksum1_(); }
};
-
+
/** \brief GRE packet
-
+
\par Packet type (typedef):
\ref GREPacket
typedef PacketTypeMixin<GREPacketType, EtherTypes> mixin;
typedef ConcretePacket<GREPacketType> packet;
typedef GREPacketParser parser;
-
+
using mixin::nextPacketRange;
using mixin::nextPacketType;
using mixin::init;
using mixin::initSize;
-
+
static void dump(packet p, std::ostream & os);
static EtherTypes::key_t nextPacketKey(packet p) {
return p->protocol_type();
p->protocol_type() << key(p.next(nothrow));
p->version_number() = 0; // as per RFC2784, 2.3.1
- if (p->checksum_present()) {
+ if (p->checksum_present()) {
// compute checksum
} else {
// ???
}
}
};
-
+
/** \brief GRE packet typedef */
typedef GREPacketType::packet GREPacket;
-
-
+
+
}
/** \brief Dump given MPESection in readable form to given output stream */
static void dump(packet p, std::ostream & os);
-
+
static void finalize(packet p);
-
+
static factory_t nextPacketType(packet p);
-
+
static PacketParserBase::size_type initSize();
static PacketParserBase::size_type initHeadSize();
};
- /** \brief MPESection packet typedef
+ /** \brief MPESection packet typedef
\ingroup protocolbundle_mpegdvb
*/
typedef ConcretePacket<MPESectionType> MPESection;
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x52, 0xdf,
0x6a, 0x1d
};
- SENF_CHECK_EQUAL_COLLECTIONS(
+ SENF_CHECK_EQUAL_COLLECTIONS(
sec_data, sec_data+sizeof(sec_data), sec.data().begin(), sec.data().end() );
}
const
{
return std::for_each(
- data().begin(),
- boost::prior(data().end(), 4),
+ data().begin(),
+ boost::prior(data().end(), 4),
ule_crc32() ).checksum();
}
//prefix_ senf::SNDUPacketType::key_t senf::SNDUPacketType::nextPacketKey(packet p)
//{
-// return p->type();
+// return p->type();
//}
prefix_ void senf::SNDUPacketType::init(packet p)
return e ? e->factory() : no_factory();
}
-prefix_ senf::PacketInterpreterBase::optional_range
-senf::SNDUPacketType::nextPacketRange(packet p)
+prefix_ senf::PacketInterpreterBase::optional_range
+senf::SNDUPacketType::nextPacketRange(packet p)
{
if (p.data().size() < 8)
return no_range();
-
+
size_type sz = 2 + 2; // D-Bit + 15 bits length + 16 bits type field
if (! p->d_bit() )
sz += 6; // + 6 Byte NPA destination address
namespace senf {
/** \brief parse ULE SNDU Packet
-
+
Parser implementing the header and trailer of a ULE SNDU Packet
-
+
\see SNDUPacketType
*/
struct SNDUPacketParser : public PacketParserBase
SENF_PARSER_PRIVATE_BITFIELD ( d_bit_ , 1 , unsigned );
SENF_PARSER_BITFIELD ( length , 15 , unsigned );
SENF_PARSER_FIELD ( type , UInt16Parser );
- SENF_PARSER_PRIVATE_VARIANT ( destination_ , d_bit_ ,
+ SENF_PARSER_PRIVATE_VARIANT ( destination_ , d_bit_ ,
(MACAddressParser) (VoidPacketParser) );
-
+
SENF_PARSER_FINALIZE( SNDUPacketParser );
-
+
MACAddressParser destination() /// Only defined if d_bit() == \c false
{ return destination_().get<0>(); }
void withDestination() /// Clear destination absent bit
{ destination_().init<0>(); }
-
+
void withoutDestination() /// Set destination absent bit
{ destination_().init<1>(); }
- UInt32Parser crc()
+ UInt32Parser crc()
{ return parse<UInt32Parser>( data().size() - 4 ); }
boost::uint32_t calcCrc() const;
};
-
+
struct ULEExtHeaderTypes {
typedef boost::uint16_t key_t;
};
-
+
/** \brief ULE SNDU Packet
-
+
\par Packet type (typedef):
\ref SNDUPacket
// using mixin::nextPacketRange;
// using mixin::nextPacketType;
// using mixin::init;
-
+
// static key_t nextPacketKey(packet p);
-
+
static void init(packet p);
static factory_t nextPacketType(packet p);
-
+
static optional_range nextPacketRange(packet p);
-
+
static void dump(packet p, std::ostream & os);
-
+
static PacketParserBase::size_type initSize();
-
+
static PacketParserBase::size_type initHeadSize();
};
-
+
typedef SNDUPacketType::packet SNDUPacket;
-
+
typedef boost::crc_optimal<32, 0x04C11DB7, 0xFFFFFFFF, 0, false, false> ule_crc32;
/*!
- \def ULE_END_INDICATOR
- ULE End Indicator; indicates to the receiver that there are no
+ \def ULE_END_INDICATOR
+ ULE End Indicator; indicates to the receiver that there are no
further SNDUs present within the current TS packet.
*/
# define ULE_END_INDICATOR 0xffff
prefix_ senf::UInt8Parser senf::TransportPacketParser::pointer_field()
const
{
- return pointer_field_().get<1>();
+ return pointer_field_().get<1>();
}
prefix_ void senf::TransportPacketParser::setPUSI(bool pusi)
if (pusi) pointer_field_().init<1>();
else pointer_field_().init<0>();
}
-
+
prefix_ void senf::TransportPacketType::dump(packet p, std::ostream & os)
{
boost::io::ios_all_saver ias(os);
Parser implementing the header of a MPEG Transport Stream packet.
\image html TransportPacket.png
-
+
\see TransportPacketType
*/
struct TransportPacketParser : public PacketParserBase
SENF_PARSER_PRIVATE_VARIANT ( pointer_field_, pusi,
(senf::VoidPacketParser) (UInt8Parser) );
-
+
SENF_PARSER_FINALIZE( TransportPacketParser );
-
+
UInt8Parser pointer_field() const;
void init_fields() const;
void setPUSI(bool pusi) const;
init_fields();
}
};
-
+
/** \brief Transport Stream packet
-
+
<table class="senf">
<tr style="text-align:center">
<th>Syntax</th><th>No. of bits</th></tr>
<tr>
<td>}</td> <td></td></tr>
</table>
-
+
\par Packet type (typedef):
\ref TransportPacket
#endif
typedef ConcretePacket<TransportPacketType> packet; ///< Transport packet typedef
typedef TransportPacketParser parser; ///< typedef to the parser of Transport packet
-
+
using mixin::nextPacketRange;
using mixin::init;
using mixin::initSize;
-
+
/** \brief Dump given Transport packet in readable form to given output stream */
static void dump(packet p, std::ostream & os);
static const byte SYNC_BYTE = 0x47;
};
-
+
/** \brief Transport packet typedef */
typedef ConcretePacket<TransportPacketType> TransportPacket;
}
\autotoc
-
+
\section packet_intro_arch Introduction
\seechapter \ref packet_arch
The Packet library consists of several components:
-
+
\li The \ref packet_module manages the packet data and provides the framework for handling the
chain of packet headers. The visible interface is provided by the Packet class.
\li \ref packetparser provides the framework for interpreting packet data. It handles
\section packet_intro_usage Tutorial
- \seechapter \ref packet_usage
+ \seechapter \ref packet_usage
+
+ This chapter discusses the usage of the packet library from a high level view.
- This chapter discusses the usage of the packet library from a high level view.
-
\section packet_intro_api The packet API
The packet library API is divided into three areas
\li the packet interpreter chain providing \ref packet_module
\li and \ref packetparser which provides access to protocol specific packet fields.
-
+
\section protocolbundles Supported packet types (protocols)
Each protocol bundle provides a collection of related concrete packet classes for a group of
\li \ref protocolbundle_80221 : 802.21 protocols
There are two ways to link with a bundle
-
+
\li If you only work with known packets which you explicitly reference you may just link with
the corresponding library.
\li If you need to parse unknown packets and want those to be parsed as complete as possible
included whether they are explicitly referenced or not (and they will all automatically be
registered).
-
+
\section packet_intro_new Defining new packet types
\seechapter \ref packet_new
\autotoc
-
+
\section packet_arch_handle The Packet handle
Whenever we are using a Packet, we are talking about a senf::Packet (or a
senf::ConcretePacket). This class is a \e handle referencing an internally managed packet data
structure. So even though we pass senf::Packet instances around by value, they work like
references. The packet library automatically manages all required memory resources using
- reference counting.
+ reference counting.
Different Packet handles may really internally share one Packet data structure if they both
point to the same packet.
-
+
\section packet_arch_data The Packet as a 'bunch of bytes'
From the outside, a packet is just a bunch of bytes just as it is read from (or will be
Packet p = ...;
// Change first byte of packet to 1
- p.data()[0] = 1u;
+ p.data()[0] = 1u;
// Copy packet data into a vector
std::vector<char> data (p.data().size());
\see senf::Packet::data() \n
senf::PacketData
-
+
\section packet_arch_chain The Interpreter Chain
On the next level, the packet is divided into a nested list of sub-packets (or headers) called
interpreters. Each senf::Packet handle internally points to an interpreter or header. This
- allows us to access one and the same packet in different ways.
+ allows us to access one and the same packet in different ways.
Consider an Ethernet Packet with an IP payload holding a UDP packet. We may reference either the
Ethernet packet as a whole or we may reference the IP or UDP interpreters (sub-packets or
udp.prev() == ip // true
udp.prev<EthernetPacket>() // throws InvalidPacketChainException
\endcode
-
+
\see \ref packet_module
senf::EthernetPacket eth (senf::EthernetPacket::create());
senf::IPv4Packet ip (senf::IPv4Packet ::createAfter(eth));
senf::UDPPacket udp (senf::UDPPacket ::createAfter(ip));
- senf::DataPacket payload (senf::DataPacket ::createAfter(udp,
+ senf::DataPacket payload (senf::DataPacket ::createAfter(udp,
std::string("Hello, world!")));
udp->source() = 2000u;
ip->destination() = senf::INet4Address::from_string("192.168.0.2");
eth->source() = senf::MACAddress::from_string("00:11:22:33:44:55");
eth->destination() = senf::MACAddress::from_string("00:11:22:33:44:66");
-
+
eth.finalizeAll();
\endcode
\code
#include "Packets.hh"
\endcode
-
+
explicitly.
\warning Never include any other Packets library header directly, only include \c
Packets.hh or one (or several) protocol headers from the protocol bundles.
Most every use of the packet library starts with some concrete packet typedef. Some fundamental
- packet types are provided by \ref protocolbundle_default.
+ packet types are provided by \ref protocolbundle_default.
\section packet_usage_create Creating a new packet
senf::EthernetPacket eth (senf::EthernetPacket::create());
senf::IPv4Packet ip (senf::IPv4Packet ::createAfter(eth));
senf::UDPPacket udp (senf::UDPPacket ::createAfter(ip));
- senf::DataPacket payload (senf::DataPacket ::createAfter(udp,
+ senf::DataPacket payload (senf::DataPacket ::createAfter(udp,
std::string("Hello, world!")));
\endcode
ip->destination() = senf::INet4Address::from_string("192.168.0.2");
eth->source() = senf::MACAddress::from_string("00:11:22:33:44:55");
eth->destination() = senf::MACAddress::from_string("00:11:22:33:44:66");
-
+
eth.finalizeAll();
\endcode
The chain navigation functions are also used to parse a packet. Let's read an Ethernet packet
from a packet socket handle:
-
+
\code
senf::PacketSocketHandle sock();
sock.bind( senf::LLSocketAddress("eth0"));
\section packet_usage_container The raw data container
-
+
Every packet is based internally on a raw data container holding the packet data. This container
is accessed via senf::Packet::data() member.
-
+
This container is a random access container. It can be used like an ordinary STL container and
supports all the standard container members.
\code
eth.data().insert(eth.data().end(), 5, 0x01);
- assert( eth.data().end() == ip.data().end() + 5
+ assert( eth.data().end() == ip.data().end() + 5
&& ip.data().end() == udp.data().end() );
// Or alternatively: (You could even use eth.data().end() here ... it's the same)
\endcode
Additionally, the parsers have a parser specific API which allows to manipulate or query the
- value.
+ value.
This is a very abstract description of the parser structure. For a more concrete description, we
need to differentiate between the different parser types
\subsection packet_usage_fields_collection Collection parsers
- Besides simple composites, the packet library has support for more complex collections.
+ Besides simple composites, the packet library has support for more complex collections.
\li The senf::ArrayParser allows to repeat an arbitrary parser a fixed number of times.
\li senf::VectorParser and senf::ListParser are two different types of lists with variable
To demonstrate nested collections, we use the \c MLDv2ReportPacket as an example. The relevant
fields of this packet are;
-
+
<table class="fields">
<tr><td>nrOfRecords</td><td>Integer</td><td>Number of multicast address records</td></tr>
<tr><td>records</td><td>List of Records</td><td>List of multicast groups and sources</td></tr>
<tr><td>nrOfSources</td><td>Integer</td><td>Number of sources in this record</td></tr>
<tr><td>sources</td><td>Vector of IPv6 Addresses</td><td>Multicast sources</td></tr>
</table>
-
+
The first example will iterate over the sources in a \c MLDv2QueryPacket:
\code
MLDv2QueryPacket::Parser::sources_t::container sources (mld->sources());
// Iterate over all the addresses in that list
- for (MLDv2QueryPacket::Parser::sources_t::container::iterator i (sources.begin());
+ for (MLDv2QueryPacket::Parser::sources_t::container::iterator i (sources.begin());
i != sources.end(); ++i)
std::cout << *i << std::endl;
\endcode
// Allocate a collection wrapper for the multicast address record
typedef MLDv2ReportPacket::Parser::records_t::value_type::sources_t Sources;
Sources::container sources (i->sources());
-
+
// Iterate over the sources in this record
for (Sources::container::iterator i (sources.begin());
i != sources.end(); ++i)
parser). Any change made to the packet not via the collection wrapper has the potential to
invalidate the wrapper if it changes the packets size.
- \see
+ \see
senf::VectorParser / senf::VectorParser_Container Interface of the vector parser \n
senf::ListParser / senf::ListParser_Container Interface of the list parser
-
+
\subsubsection packet_usage_collection_variant The Variant Parser
fbips.resize(addrs.size());
std::copy(addrs.begin(), addrs.end(), fbips.begin());
\endcode
-
+
\note Here we have documented the default variant interface as it is preferred. It is possible
to define variants in a different way giving other names to the special members (\c has_\e
name or \c init_\e name etc.). This must be documented with the composite or protocol parser
struct Timestamp {
senf::ClockService::clock_t value;
};
-
- std::ostream & operator<<(std::ostream & os, Timestamp const & tstamp) {
- os << tstamp.value; return os;
+
+ std::ostream & operator<<(std::ostream & os, Timestamp const & tstamp) {
+ os << tstamp.value; return os;
}
senf::EthernetPacket packet (senf::EthernetPacket::create(senf::noinit));
In the same way, the annotation can be used later
\code
- if (senf::ClockService::now() - packet.annotation<Timestamp>().value
+ if (senf::ClockService::now() - packet.annotation<Timestamp>().value
> senf::ClockService::seconds(1)) {
// this packet is to old
// ...
}
\endcode
-
+
It is very important to define a specific structure (or class or enum) type for each type of
annotation. \e Never directly store a fundamental type as an annotation: The name of the type is
used to look up the annotation, so you can store only one annotation for each built-in type. \c
typedef does not help since \c typedef does not introduce new type names, it only defines an
alias.
- The annotation type must support the output \c operator<< for description purposes
- (e.g. for the \ref senf::Packet::dump() "Packet::dump()" member).
+ The annotation type must support the output \c operator<< for description purposes
+ (e.g. for the \ref senf::Packet::dump() "Packet::dump()" member).
Of course, the annotation structure can be arbitrary. However, one very important caveat: If the
annotation is not a POD type, it needs to inherit from senf::ComplexAnnotation. A type is POD,
// Or store a reference to the annotation for easier access
ReadInfo & info (packet.annotation<ReadInfo>());
-
+
if (info.interface == "eth0") {
// ...
}
SENF_PARSER_FINALIZE(EthernetPacketParser);
};
\endcode
-
+
There are a lot of other possibilities to define fields. See \ref packetparsermacros for a
detailed description of the macro language which is used to define composite parsers.
- \see
+ \see
\ref packetparsermacros
\section packet_new_type The packet type policy class
in this packet
\li It provides methods to initialize a new packet and get information about the packet size
- All this information is provided via static or typedef members.
+ All this information is provided via static or typedef members.
\code
struct EthernetPacketType
const
{
Packet p (*this);
- while (p && ! p.is<OtherPacket>())
+ while (p && ! p.is<OtherPacket>())
p = p.next(nothrow);
- if (p)
+ if (p)
return p.as<OtherPacket>();
else
return OtherPacket();
const
{
Packet p (*this);
- while (p && ! p.is<OtherPacket>())
+ while (p && ! p.is<OtherPacket>())
p = p.prev(nothrow);
- if (p)
+ if (p)
return p.as<OtherPacket>();
else
return OtherPacket();
template <class PacketType>
prefix_ senf::ConcretePacket<PacketType>
-senf::ConcretePacket<PacketType>::createAfter(Packet const & packet, size_type size,
+senf::ConcretePacket<PacketType>::createAfter(Packet const & packet, size_type size,
senf::NoInit_t)
{
return ConcretePacket(interpreter::createAfter(packet.ptr(), size, senf::noinit));
Packet first() const; ///< Return first packet in chain
- template <class OtherPacket> OtherPacket first() const;
+ template <class OtherPacket> OtherPacket first() const;
///< Return first packet in chain and cast
/**< \throws std::bad_cast if the first() packet is not of
type \a OtherPacket */
typedef unsigned key_t;
};
- struct FooPacketType
+ struct FooPacketType
: public senf::PacketTypeBase,
public senf::PacketTypeMixin<FooPacketType>
{
// mode. Otherwise, mixin::nextPacketRange() would query the parser for it's size to find
// the header size. Since the parser is VoidPacketParser, the header size would therefore be
// 0
- static size_type initHeadSize()
+ static size_type initHeadSize()
{ return initSize(); }
};
typedef senf::ConcretePacket<FooPacketType> FooPacket;
struct BarPacketParser : public senf::PacketParserBase
{
# include SENF_FIXED_PARSER()
-
+
SENF_PARSER_FIELD( type, senf::UInt16Parser );
SENF_PARSER_FIELD( length, senf::Int32Parser );
SENF_PARSER_FIELD( reserved, senf::UInt16Parser );
SENF_PARSER_FINALIZE(BarPacketParser);
};
- struct BarPacketType
+ struct BarPacketType
: public senf::PacketTypeBase,
public senf::PacketTypeMixin<BarPacketType,RegTag>
{
std::ostream & operator<<(std::ostream & os, IntAnnotation const & v)
{ os << v.value; return os; }
-
+
struct LargeAnnotation {
char value[32];
};
SENF_AUTO_UNIT_TEST(packet)
{
- senf::Packet packet (FooPacket::create());
+ senf::Packet packet (FooPacket::create());
BarPacket::createAfter(packet);
BOOST_REQUIRE( packet );
BOOST_CHECK( packet.next().is<BarPacket>() );
BOOST_CHECK( packet.first() == packet );
BOOST_CHECK( packet.last() == packet.next() );
-
+
senf::Packet p2 (packet.next());
BOOST_CHECK( p2 );
packet.parseNextAs<FooPacket>();
BOOST_CHECK( packet.next().is<FooPacket>() );
BOOST_CHECK( ! p2 );
BOOST_CHECK( packet.next().as<FooPacket>() );
-
+
p2 = packet.next().clone();
BOOST_REQUIRE( p2 );
packet.next().append( p2 );
BOOST_CHECK_EQUAL( senf::PacketRegistry<RegTag>::key(packet), 1u );
packet.next().parseNextAs( senf::PacketRegistry<RegTag>::lookup(2u).factory() );
BOOST_CHECK( packet.next().next().is<BarPacket>() );
-
+
std::stringstream s;
packet.dump(s);
- BOOST_CHECK_EQUAL( s.str(),
+ BOOST_CHECK_EQUAL( s.str(),
"Annotations:\n"
" (anonymous namespace)::ComplexAnnotation: no value\n"
" (anonymous namespace)::IntAnnotation: 0\n"
"BarPacket:\n"
" type: 0\n"
" length: 0\n" );
-
+
packet.finalizeAll();
- BOOST_CHECK_EQUAL( packet.last().as<BarPacket>()->type(),
+ BOOST_CHECK_EQUAL( packet.last().as<BarPacket>()->type(),
BarPacket::Parser::type_t::value_type(-1) );
packet.last().append(FooPacket::create());
packet.finalizeThis();
BOOST_CHECK( packet.last().rfind<FooPacket>() == packet.last() );
BOOST_CHECK( packet.next<BarPacket>() == packet.next() );
BOOST_CHECK( packet.last().prev().prev<FooPacket>() == packet );
-
+
senf::DataPacket::createAfter(packet);
BOOST_CHECK_THROW( packet.next().next().next().parseNextAs<BarPacket>(),
senf::InvalidPacketChainException );
// No 'u' suffix here to check, that the disable_if works ...
BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,10).size(), 10u );
BOOST_CHECK_EQUAL( packet.size(), 14u );
-
+
BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,2u,senf::noinit).size(), 2u );
BOOST_CHECK_EQUAL( packet.size(), 6u );
-
+
BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,data).size(), 6u );
BOOST_CHECK_EQUAL( packet.size(), 10u );
-
+
BOOST_CHECK_EQUAL( FooPacket::createBefore(packet).size(), 14u );
BOOST_CHECK_EQUAL( packet.size(), 10u );
bar2->type() << 0x2A2Bu;
bar1.parser() << bar2;
-
+
BOOST_CHECK_EQUAL( bar1->type(), 0x2A2Bu );
}
Whenever the data is manipulated through PacketData, the change is assumed to be within the
data range of that packet: All insertions take place \e inside \c this packet and \e outside
- any following packets in the packet chain.
+ any following packets in the packet chain.
\warning It is not permissible to change data belonging to a following
packet/header/interpreter even though this data is part of \c this sequence. Doing so
will corrupt the packet data.
-
+
\par
\warning When accessing packet data via the PacketData interface you are on your own: The
///@}
///////////////////////////////////////////////////////////////////////////
-
+
///\name Sequence interface to raw data
///@{
iterator begin() const; ///< Return iterator to beginning
/**< Returns an <em>random access iterator</em> referring to the
first byte of the packet data. */
- iterator end() const; ///< Return iterator to end
- /**< Returns an <em>random access iterator</em> referring to the
+ iterator end() const; ///< Return iterator to end
+ /**< Returns an <em>random access iterator</em> referring to the
byte past the end of the packet data. */
size_type size() const; ///< Returns the number of bytes in the packet data.
bool empty() const; ///< Test whether the packet data is empty.
/**< Returns whether the packet data is empty, i.e. whether its size
- is 0. This function does not modify the content of the packet
- data in any way. To clear the content use clear() */
+ is 0. This function does not modify the content of the packet
+ data in any way. To clear the content use clear() */
byte operator[](size_type n) const; ///< Access byte in the packet data
byte & operator[](size_type n); ///< Access byte in the packet data
void erase(iterator pos);
void erase(iterator first, iterator last);
void clear(); ///< All bytes of the packet data dropped, leaving the container with a size of 0. */
-
+
void resize(size_type n, byte v=0);
void reserve(size_type n);
senf::PacketInterpreterBase::ptr pi (senf::PacketInterpreter<VoidPacket>::create());
senf::PacketData & d (pi->data());\
-
+
BOOST_CHECK( d.begin() == d.end() );
BOOST_CHECK_EQUAL( d.size(), 0u );
BOOST_CHECK( d.empty() );
-
+
d.insert(d.begin(), 0xabu);
BOOST_CHECK_EQUAL( d.size(), 1u );
BOOST_CHECK_EQUAL( d[0], 0xabu );
BOOST_CHECK( !d.empty() );
-
+
d.insert(d.begin(), 10, 0xcdu );
BOOST_CHECK_EQUAL( d.size(), 11u );
BOOST_CHECK_EQUAL( d[0], 0xcdu );
BOOST_CHECK_EQUAL( d[9], 0xcdu );
BOOST_CHECK_EQUAL( d[10], 0xabu );
- senf::PacketData::byte data[] =
+ senf::PacketData::byte data[] =
{ 0xf0u, 0xf1u, 0xf2u, 0xf3u, 0xf4u, 0xf5u, 0xf6u, 0xf7u };
d.insert(d.begin()+5, data, data+sizeof(data)/sizeof(data[0]));
BOOST_CHECK_EQUAL( d.size(), 19u );
d.erase(d.begin());
BOOST_CHECK_EQUAL( d.size(), 18u );
BOOST_CHECK_EQUAL( d[4], 0xf0u );
-
+
d.erase(d.begin(), d.begin()+11);
BOOST_CHECK_EQUAL( d.size(), 7u );
BOOST_CHECK_EQUAL( d[0], 0xf7u );
BOOST_CHECK( i == senf::safe_data_iterator(d,d.begin()) );
BOOST_CHECK( senf::PacketData::iterator(i) == d.begin() );
- senf::PacketData::byte data[] =
+ senf::PacketData::byte data[] =
{ 0xf0u, 0xf1u, 0xf2u, 0xf3u, 0xf4u, 0xf5u, 0xf6u, 0xf7u };
d.resize(sizeof(data)/sizeof(data[0]));
BOOST_CHECK( senf::PacketData::iterator(i) == d.begin() );
BOOST_CHECK_EQUAL( d.size(), sizeof(data)/sizeof(data[0]) );
BOOST_CHECK_EQUAL( *(i+sizeof(data)/sizeof(data[0])-1), 0xf7u );
- BOOST_CHECK_EQUAL( std::distance(i,senf::safe_data_iterator(d,d.end())),
+ BOOST_CHECK_EQUAL( std::distance(i,senf::safe_data_iterator(d,d.end())),
senf::PacketData::difference_type(d.size()) );
*(++i) = 0x01u;
BOOST_CHECK_EQUAL( d[1], 0x01u );
prefix_ void senf::detail::AnnotationIndexerBase::dump(PacketImpl * p, std::ostream & os)
{
- for(std::vector<AnnotationIndexerBase*>::const_iterator
+ for(std::vector<AnnotationIndexerBase*>::const_iterator
i (registry().begin()), i_end (registry().end());
i != i_end; ++i)
(*i)->v_dump(p,os);
AnnotationIndexerBase::dump(this, os);
}
-// This function has a problem being inlined. Somehow, often when calling this, the size of the
+// This function has a problem being inlined. Somehow, often when calling this, the size of the
// resulting inlined code would be huge?
prefix_ void senf::detail::PacketImpl::release(refcount_t n)
};
template <class Annotation>
- struct AnnotationIndexer
- : public senf::singleton< AnnotationIndexer<Annotation> >,
+ struct AnnotationIndexer
+ : public senf::singleton< AnnotationIndexer<Annotation> >,
public AnnotationIndexerBase
{
AnnotationIndexer();
# if 0 // The test is difficult since it does not work with user-defined trivial constructors
# ifdef BOOST_HAS_TYPE_TRAITS_INTRINSICS
- BOOST_STATIC_ASSERT(( (boost::has_trivial_constructor<Annotation>::value
+ BOOST_STATIC_ASSERT(( (boost::has_trivial_constructor<Annotation>::value
&& boost::has_trivial_destructor<Annotation>::value)
|| Complex ));
refcount_t refcount_;
raw_container data_;
interpreter_list interpreters_;
-
+
typedef std::vector<AnnotationEntry> Annotations;
Annotations annotations_;
senf::PacketInterpreterBase::ptr pi (senf::PacketInterpreter<VoidPacket>::create());
senf::detail::PacketImpl * p (senf::detail::packet::test::TestDriver::impl(pi));
- senf::detail::PacketImpl::byte data[] =
+ senf::detail::PacketImpl::byte data[] =
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
p->insert(&pi->data(),p->begin(),data, data+sizeof(data));
BOOST_CHECK_EQUAL(p->begin()[0], 0x00u);
BOOST_CHECK_EQUAL(p->begin()[7], 0x07u);
BOOST_CHECK_EQUAL(pi->data().size(), p->size());
-
+
p->insert(&pi->data(),p->begin()+2,0xf0u);
BOOST_CHECK_EQUAL(p->size(),9u);
BOOST_CHECK_EQUAL(p->begin()[8], 0x07u);
BOOST_CHECK_EQUAL(p->size(),16u);
BOOST_CHECK_EQUAL(p->begin()[0], 0x01u);
BOOST_CHECK_EQUAL(pi->data().size(), p->size());
-
+
p->erase(&pi->data(),p->begin()+2, p->begin()+7);
BOOST_CHECK_EQUAL(p->size(),11u);
BOOST_CHECK_EQUAL(p->begin()[2], 0x07u);
BOOST_CHECK( pi1->data().begin() == p->begin() );
BOOST_CHECK( pi2->data().begin() == p->begin() );
BOOST_CHECK( pi3->data().begin() == p->end() );
-
+
p->insert(&pi3->data(),p->end(), 0x00u);
BOOST_CHECK_EQUAL(pi1->data().size(), 11u);
BOOST_CHECK_EQUAL(pi2->data().size(), 11u);
BOOST_CHECK_EQUAL(pi3->data().size(), 1u);
-
+
p->insert(&pi1->data(),p->end(), 2, 0x00u);
BOOST_CHECK_EQUAL(pi1->data().size(), 13u);
BOOST_CHECK_EQUAL(pi2->data().size(), 11u);
{
if (next())
impl().truncateInterpreters(next().get());
-
+
optional_range r (nextPacketRange());
if (!r)
throw InvalidPacketChainException();
-
+
ptr rv (packet->appendClone(&impl(), *r));
rv->data().resize(packet->data().size());
std::copy(packet->data().begin(), packet->data().end(), rv->data().begin());
prefix_ bool senf::PacketInterpreterBase::release()
{
- if (impl_)
+ if (impl_)
// This call will set impl_ to 0 if we just removed the last reference ...
impl_->release();
return intrusive_refcount_t<PacketInterpreterBase>::release() && !impl_;
optional_range r (nextPacketRange());
if (!r)
throw InvalidPacketChainException();
-
+
if (next())
impl().truncateInterpreters(next().get());
- typename PacketInterpreter<Type>::ptr pi
+ typename PacketInterpreter<Type>::ptr pi
(PacketInterpreter<Type>::create(&impl(),r->begin(),r->end(),Append));
return pi;
}
optional_range r (packet->nextPacketRange());
if (!r)
throw InvalidPacketChainException();
-
+
if (packet->next())
packet->impl().truncateInterpreters(packet->next().get());
optional_range r (packet->nextPacketRange());
if (!r)
throw InvalidPacketChainException();
-
+
if (packet->next())
packet->impl().truncateInterpreters(packet->next().get());
}
template <class PacketType>
-const typename senf::PacketInterpreter<PacketType>::FactoryImpl
+const typename senf::PacketInterpreter<PacketType>::FactoryImpl
senf::PacketInterpreter<PacketType>::factory_;
///////////////////////////////ct.e////////////////////////////////////////
template <class PacketType> class PacketInterpreter;
/** \brief Internal: Base packet interpreter class
-
+
\internal
This is the base class for the persistent interpreter. This class encapsulates all the
functionality accessible via the packet handle, most handle operations are just forwarded.
*/
class PacketInterpreterBase
- : protected PacketData,
+ : protected PacketData,
public detail::packet::interpreter_list_base,
public intrusive_refcount_t<PacketInterpreterBase>
{
almost any one of the create / createAfter / createBefore static PacketInterpreter
without static information on the type of packet to create.
*/
- struct Factory {
+ struct Factory {
virtual ~Factory();
// Create completely new packet
virtual ptr create(size_type size, senf::NoInit_t) const = 0;
template <class ForwardReadableRange>
ptr create(ForwardReadableRange const & range) const;
-
+
// Create packet as new packet after a given packet
virtual ptr createAfter(PacketInterpreterBase::ptr packet) const = 0;
virtual ptr createAfter(PacketInterpreterBase::ptr packet, senf::NoInit_t) const = 0;
virtual ptr createAfter(PacketInterpreterBase::ptr packet, size_type size) const = 0;
- virtual ptr createAfter(PacketInterpreterBase::ptr packet, size_type size,
+ virtual ptr createAfter(PacketInterpreterBase::ptr packet, size_type size,
senf::NoInit_t) const = 0;
template <class ForwardReadableRange>
- ptr createAfter(PacketInterpreterBase::ptr packet,
+ ptr createAfter(PacketInterpreterBase::ptr packet,
ForwardReadableRange const & range) const;
-
+
// Create packet as new packet (header) const before a given packet
virtual ptr createBefore(PacketInterpreterBase::ptr packet) const = 0;
virtual ~PacketInterpreterBase();
static factory_t no_factory();
-
+
ptr clone();
-
+
///@}
///////////////////////////////////////////////////////////////////////////
using PacketData::valid;
PacketData & data();
-
+
///@}
///\name Annotations
static ptr createAfter(PacketInterpreterBase::ptr packet, size_type size);
static ptr createAfter(PacketInterpreterBase::ptr packet, size_type size, senf::NoInit_t);
template <class ForwardReadableRange>
- static ptr createAfter(PacketInterpreterBase::ptr packet,
+ static ptr createAfter(PacketInterpreterBase::ptr packet,
ForwardReadableRange const & range);
// Create packet as new packet (header) before a given packet
// virtual interface
virtual optional_range v_nextPacketRange();
- virtual PacketInterpreterBase::ptr v_appendClone(detail::PacketImpl * impl,
+ virtual PacketInterpreterBase::ptr v_appendClone(detail::PacketImpl * impl,
iterator base, iterator new_base);
virtual PacketInterpreterBase::ptr v_appendClone(detail::PacketImpl * impl, range r);
virtual void v_finalize();
// factory
/** \brief Internal: Implementation of abstract factory interface
-
+
\internal
Implements the abstract factory interface for \a PacketType
virtual PacketInterpreterBase::ptr create(senf::NoInit_t) const;
virtual PacketInterpreterBase::ptr create(size_type size) const;
virtual PacketInterpreterBase::ptr create(size_type size,senf::NoInit_t) const;
-
+
// Create packet as new packet after a given packet
- virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet)
+ virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet)
const;
- virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
+ virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
senf::NoInit_t) const;
- virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
+ virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
size_type size) const;
- virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
+ virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
size_type size, senf::NoInit_t) const;
-
+
// Create packet as new packet (header) before a given packet
- virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet)
+ virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet)
const;
virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet,
- senf::NoInit_t)
+ senf::NoInit_t)
const;
- virtual PacketInterpreterBase::ptr createInsertBefore(PacketInterpreterBase::ptr packet)
+ virtual PacketInterpreterBase::ptr createInsertBefore(PacketInterpreterBase::ptr packet)
const;
virtual PacketInterpreterBase::ptr createInsertBefore(PacketInterpreterBase::ptr packet,
senf::NoInit_t)
// Parse next packet in chain
- virtual PacketInterpreterBase::ptr parseNext(PacketInterpreterBase::ptr packet)
+ virtual PacketInterpreterBase::ptr parseNext(PacketInterpreterBase::ptr packet)
const;
};
/** \brief Invalid packet chain operation
This exception signals an invalid operation on the chain like trying to find a non-existent
- chain member and other similar error conditions.
+ chain member and other similar error conditions.
*/
struct InvalidPacketChainException : public senf::Exception
{ InvalidPacketChainException() : senf::Exception("invalid packet chain") {} };
-
+
}
///////////////////////////////hh.e////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
}
prefix_ senf::PacketParserBase::ParserProtector::ParserProtector(PacketParserBase const * p)
- : safe_i_( *p), parser_(p)
+ : safe_i_( *p), parser_(p)
{}
prefix_ senf::PacketParserBase::ParserProtector::ParserProtector(ParserProtector const & other_)
- : safe_i_( *other_.parser_), parser_(other_.parser_)
+ : safe_i_( *other_.parser_), parser_(other_.parser_)
{
other_.parser_ = 0;
}
-prefix_ senf::PacketParserBase::ParserProtector::~ParserProtector()
-{
- if (parser_) const_cast<PacketParserBase *>(parser_)->i_ = safe_i_;
+prefix_ senf::PacketParserBase::ParserProtector::~ParserProtector()
+{
+ if (parser_) const_cast<PacketParserBase *>(parser_)->i_ = safe_i_;
}
// protected members
prefix_ senf::PacketParserBase::ParserProtector senf::PacketParserBase::protect()
const
-{
- return ParserProtector(this);
+{
+ return ParserProtector(this);
}
prefix_ bool senf::PacketParserBase::check(size_type size)
return size <= size_type(std::distance(i(),end()));
}
-prefix_ void senf::PacketParserBase::validate(size_type size)
+prefix_ void senf::PacketParserBase::validate(size_type size)
const
{
if (! check(size))
: i_ (i), data_ (s)
{}
-prefix_ senf::PacketParserBase::PacketParserBase(data_iterator i, state_type s,
+prefix_ senf::PacketParserBase::PacketParserBase(data_iterator i, state_type s,
size_type size)
: i_ (i), data_ (s)
{
#ifndef DOXYGEN
template <class Parser>
-prefix_ typename boost::enable_if<
+prefix_ typename boost::enable_if<
boost::is_base_of<senf::PacketParserBase, Parser>,
Parser >::type senf::operator<<(Parser target, Parser source)
{
#ifndef DOXYGEN
template <class Parser, class Value>
-prefix_ typename boost::enable_if_c <
- boost::is_base_of<senf::PacketParserBase, Parser>::value
+prefix_ typename boost::enable_if_c <
+ boost::is_base_of<senf::PacketParserBase, Parser>::value
&& ! boost::is_base_of<senf::PacketParserBase, Value>::value,
Parser >::type senf::operator<<(Parser target, Value const & value)
{
#ifndef DOXYGEN
template <class Parser, class Value>
-prefix_ typename boost::enable_if_c <
- boost::is_base_of<senf::PacketParserBase, Parser>::value
+prefix_ typename boost::enable_if_c <
+ boost::is_base_of<senf::PacketParserBase, Parser>::value
&& ! boost::is_base_of<senf::PacketParserBase, Value>::value,
Parser >::type senf::operator<<(Parser target, boost::optional<Value> const & value)
{
\brief PacketParser public header */
/** \defgroup packetparser The PacketParser facility
-
+
The PacketParser facility provides a framework to implement very lightweight classes which parse
the raw content of a packet into meaningful values. PacketParsers are always passed around
<em>by value</em>, they can be understood as pointers into the packet data with added type
the field name. Each returns a parser object. Simple parsers can be used like their
corresponding basic type (e.g. a UInt16Parser field can be used like an unsigned integer), more
complex parsers provide type specific access members. Assigning a value to a parser will change
- the underlying representation (the packet data).
+ the underlying representation (the packet data).
Parsers can be grouped into several categories. These categories are not all defined rigorously
but are nevertheless helpful when working with the parsers:
processing fields in some way and so on). You should however be very wary to access data outside
the range assigned to the packet (the range starting at \c i() and with a size of senf::bytes()
bytes).
-
+
Each parser type has specific features
\subsection parserimpl_value Value parsers
\code
// SomeParser must have a 'value_type', The 'value_type' must be default constructible, copy
// constructible and assignable
- SomeParser::value_type v;
+ SomeParser::value_type v;
// An instance of 'SomeParser' must have a 'value' member which returns a value which may be
// assigned to a variable of type 'value_type'
\see parsecollection
\subsection parserimpl_composite Composite parsers
-
+
If possible, composite parsers should be implemented using the \ref packetparsermacros. In
addition to the normal parser requirements, these macros ensure, that for each field,
<em>fieldname</em><tt>_t</tt> is a typedef for the fields parser and
namespace senf {
class Packet;
-
+
/** \brief Parser Base class
Parsers come in two flavors: fixed and dynamically sized parsers. A <em>fixed size
A <em>dynamically sized</em> parser on the other hand infers it's size from the contents of
the data parsed. Any parser containing at least one dynamically sized sub-parser will itself
be dynamically sized.
-
+
Both kinds of parser need to derive from PacketParserBase and implement several required
members. Which members to implement depends on the parsers flavor. There are two ways how to
do this.
// ////////////////////////////////////////////////////////////////////////
- // Add here members returning (sub-)parsers for the fields. The 'parse' member is
+ // Add here members returning (sub-)parsers for the fields. The 'parse' member is
// used to construct the sub-parsers. This member either takes an iterator to the
// data to be parsed or just an offset in bytes.
senf::UInt16Parser size() const { return parse<UInt16Parser>( 2 ); }
};
\endcode
-
+
You should never call the \c bytes() member of a parser directly. Instead you should use the
freestanding senf::bytes() function. This function will return the correct size irrespective
of the parsers flavor. You may access \c fixed_bytes directly, however be aware that this
offset. However, the parser checks, that the iterator is
still within range of the raw data
container. Otherwise a TruncatedPacketException is
- thrown.
-
+ thrown.
+
\throws TruncatedPacketException if the raw data
container does not hold at least \a offset bytes
starting at i(). */
struct ParserProtector {
senf::safe_data_iterator safe_i_;
mutable PacketParserBase const * parser_;
-
+
ParserProtector( PacketParserBase const * parser);
ParserProtector(ParserProtector const & other_);
~ParserProtector();
};
protected:
ParserProtector protect() const;
-
+
PacketParserBase(data_iterator i, state_type s); ///< Standard constructor
/**< This is the constructor used by most parsers. The
parameters are just forwarded from the derived classes
constructor parameters. */
- PacketParserBase(data_iterator i, state_type s, size_type size);
+ PacketParserBase(data_iterator i, state_type s, size_type size);
///< Size checking constructor
/**< In addition to the standard constructor, this
constructor will validate, that there is enough data in
};
/** \brief Return raw size parsed by the given parser object
-
+
This function will either call <tt>p.bytes()</tt> or return <tt>Parser::fixed_bytes</tt>
depending on the type of parser.
*/
template <class Parser>
PacketParserBase::size_type bytes(Parser p);
-
+
namespace detail { template <class Parser> class ParserInitBytes; }
namespace detail { template <class Parser> class ParserIsFixed; }
# ifndef DOXYGEN
template <class Parser>
- typename boost::enable_if<
+ typename boost::enable_if<
boost::is_base_of<PacketParserBase, Parser>,
Parser >::type
operator<<(Parser target, Parser source);
# ifndef DOXYGEN
template <class Parser, class Value>
- typename boost::enable_if_c <
- boost::is_base_of<PacketParserBase, Parser>::value
+ typename boost::enable_if_c <
+ boost::is_base_of<PacketParserBase, Parser>::value
&& ! boost::is_base_of<PacketParserBase, Value>::value,
Parser >::type
operator<<(Parser target, Value const & value);
-# else
+# else
/** \brief Generic parser value assignment
This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
value<tt>)</tt> member. This operator allows to use a common syntax for assigning values or
- parsers to a parser.
+ parsers to a parser.
\ingroup packetparser
*/
# ifndef DOXYGEN
template <class Parser, class Value>
- typename boost::enable_if_c <
- boost::is_base_of<PacketParserBase, Parser>::value
+ typename boost::enable_if_c <
+ boost::is_base_of<PacketParserBase, Parser>::value
&& ! boost::is_base_of<PacketParserBase, Value>::value,
Parser >::type
operator<<(Parser target, boost::optional<Value> const & value);
-# else
+# else
/** \brief Generic parser value assignment
This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
value<tt>)</tt> member. This special version allows to assign optional values: IF the
- optional value is not set, the assignment will be skipped.
+ optional value is not set, the assignment will be skipped.
This operator allows to use a common syntax for assigning values or parsers to a parser.
/** \brief Default parser parsing nothing
*/
- struct VoidPacketParser
+ struct VoidPacketParser
: public PacketParserBase
{
# include SENF_FIXED_PARSER()
// Use SFINAE to check, if Parser has an integer-valued fixed_bytes member. If not,
// 'Parser_TakeNum<Parser::fixed_bytes>' fails and the overload is removed from the overload
- // set.
+ // set.
template <class Parser>
PacketParserBase::size_type packetParserSize(
Parser p, int, senf::mpl::take_uint<Parser::fixed_bytes> * = 0);
// This version of ParserInitBytes_Choose uses 'Parser::init_bytes' to provide 'value' (via
// 'boost::integral_constant')
template <class Parser, unsigned _>
- struct ParserInitBytes_Choose
+ struct ParserInitBytes_Choose
: public boost::integral_constant<PacketParserBase::size_type, Parser::init_bytes> {};
// ^^-- g++ error signaled here:
// error: 'fixed_bytes' is not a member of 'some-class-name'
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
static registration only works when the symbol is included into the final binary. To force
this inclusion, you should not put packet registrations into a library but into an object
file.
-
+
To simplify static registration the SENF_PACKET_REGISTRY_REGISTER macro can be used:
\code
SENF_PACKET_REGISTRY_REGISTER(SomeTag, SomePacket, key_of_somePacket);
BOOST_CHECK_EQUAL( PacketRegistry<BaseTag>::key<FooPacket>(), 1u );
BOOST_CHECK_EQUAL( PacketRegistry<BaseTag>::key<BarPacket>(), 2u );
- BOOST_CHECK_THROW( PacketRegistry<BaseTag>::key<OtherPacket>(),
+ BOOST_CHECK_THROW( PacketRegistry<BaseTag>::key<OtherPacket>(),
PacketTypeNotRegisteredException );
BOOST_CHECK_EQUAL( PacketRegistry<StringTag>::key<FooPacket>(), "foo" );
/// (the function address) Self::initHeadSize is different from PacketTypeBase::initHeadSize
if (sz == PacketTypeBase::size_type(-1)) {
typename Self::size_type headsz (bytes(p.as< ConcretePacket<Self> >().parser()));
- return p.data().size() < headsz ?
- PacketTypeBase::no_range() :
+ return p.data().size() < headsz ?
+ PacketTypeBase::no_range() :
PacketInterpreterBase::optional_range(
PacketTypeBase::range(boost::next(p.data().begin(), headsz),
p.data().end()));
//
// So, the helper only works with fixed-size parsers if the packet has a trailer.
return p.data().size() < Self::initSize() ?
- PacketTypeBase::no_range() :
+ PacketTypeBase::no_range() :
PacketInterpreterBase::optional_range(
PacketTypeBase::range(boost::next(p.data().begin(),sz),
boost::prior(p.data().end(),Self::initSize()-sz)));
{
typedef senf::ConcretePacket<SomePacketType> packet;
typedef SomePacketParser parser;
-
+
static size_type initSize()
{
// This value can in most cases be taken from the parser
struct PacketTypeBase
{
typedef Packet packet;
-
+
typedef senf::detail::packet::iterator iterator;
typedef senf::detail::packet::const_iterator const_iterator;
typedef senf::detail::packet::size_type size_type;
typedef VoidPacketParser parser;
///< Parser to parser packet fields
/**< This typedef has to be set to the parser of the packet
-
+
The default is a VoidPacketParser which does not parse
any field. */
/**< This function gives the index within a newly created,
empty packet where a sub-packet is to be placed.
- The default implementation returns initSize().
-
+ The default implementation returns initSize().
+
\implementation Ok, it does not really return
initSize(), it returns size_type(-1) which is
interpreted to mean initSize(). It can't return
The default implementation does nothing. */
-
+
static optional_range nextPacketRange(packet p);
///< Get next packet placement
/**< nextPacketRange returns the iterator range where the
next packet (header) is placed within the current
packet.
-
+
The default implementation always returns
<tt>no_range()</tt>.
///< Get type of next packet
/**< nextPacketType retrieves the type of the next packet
returning a factory to create that packet.
-
+
The default implementation always returns
<tt>no_factory()</tt>.
/**< finalize() will be called to complete a packet after it
has been modified. This function must calculate any
checksums, set size fields from the interpreter chain
- etc.
-
+ etc.
+
The default implementation does nothing. */
static void dump(packet p, std::ostream & os);
/** \brief Mixin to provide standard implementations for nextPacketRange and nextPacketType
This mixin class simplifies the definition of simple packets:
-
+
\li The packets consist of three sections: The header, the payload and an optional trailer.
\li If the packet has a trailer, both the header and the trailer must have a fixed size.
This mixin provides the nextPacketRange() member as well as initSize() and init(). If you
additionally provide the optional \a Registry argument, PacketTypeMixin provides a simple
- implementation of nextPacketType().
+ implementation of nextPacketType().
When using the PacketTypeMixin, the implementation of a packet is simplified to:
\code
// Here 'SomeRegistryTag' is optional
- struct SimplePacketType
+ struct SimplePacketType
: public senf::PacketTypeBase,
public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
{
typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
typedef senf::ConcretePacket<SimplePacketType> packet;
typedef SomePacketParser parser;
-
+
using mixin::nextPacketRange;
using mixin::nextPacketType; // Only if the optional 'Registry' argument is provided
using mixin::initSize;
static void finalize(packet p)
{
- // Set the type field by querying the type of the next packet. This is an
+ // Set the type field by querying the type of the next packet. This is an
// optional assignment: If the key is not found, the value returned by 'key'
// is an empty optional and the assignment will be skipped.
p->typeField << key(p.next(senf::nothrow));
Most of the members are optional, which reduces the minimal implementation of a packet to:
\code
- struct SimplePacketType
+ struct SimplePacketType
: public senf::PacketTypeBase,
public senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag>
{
typedef senf::PacketTypeMixin<SimplePacketType, SomeRegistryTag> mixin;
typedef senf::ConcretePacket<SimplePacketType> packet;
typedef SomePacketParser parser;
-
+
using mixin::nextPacketRange;
- using mixin::nextPacketType;
+ using mixin::nextPacketType;
using mixin::initSize;
using mixin::init;
next packet from information stored in the current
packets header, the key() member will look up the type
of packet \a p in the registry and return it's
- key.
-
+ key.
+
If either \a p is an in - valid() packet or the packet
type is not found in the registry, the returned
optional value will be empty. */
static PacketInterpreterBase::factory_t nextPacketType (Packet const & p);
static PacketInterpreterBase::size_type initSize ();
static void init (Packet const & p);
-
+
///@}
};
struct smart_pointer {
typedef boost::intrusive_ptr<T> ptr_t;
};
-
+
struct interpreter_list_tag;
typedef boost::intrusive::ilist_base_hook<interpreter_list_tag> interpreter_list_base;
typedef interpreter_list_base::value_traits<PacketInterpreterBase> interpreter_list_type;
typedef std::vector<byte> raw_container;
typedef raw_container::size_type size_type;
typedef raw_container::difference_type difference_type;
-
+
typedef raw_container::iterator iterator;
typedef raw_container::const_iterator const_iterator;
typedef long refcount_t; // This is long since boost uses long for refcounts .. hmm ..
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
SENF_MPL_SLOT_INIT_ZERO(bitfield_size);
SENF_MPL_SLOT_INIT_ZERO(group);
- void init_chain (senf::mpl::rv <0> *) const {}
+ void init_chain (senf::mpl::rv <0> *) const {}
size_type field_offset_ (senf::mpl::rv <0> *) const { return 0; }
// /////////////////////////////////////////////////////////////////////////
void init_chain (senf::mpl::rv<type_index> *) const
{
init_chain (static_cast<senf::mpl::rv<type_index - 1> *>(0));
- }
+ }
public:
size_type type_offset() const
{
return field_offset_(static_cast<senf::mpl::rv<type_index - 1> *>(0)) -
- SENF_MPL_SLOT_GET(bitfield_size);
+ SENF_MPL_SLOT_GET(bitfield_size);
}
static size_type const type_init_bytes =
SENF_MPL_SLOT_GET(init_bytes) - SENF_MPL_SLOT_GET(bitfield_size);
return 1;
}
template <content__chooser_value_type (*KeyFn) ()>
- struct content__key_value_template
+ struct content__key_value_template
: public senf::detail::VariantKey<content__chooser_value_type, KeyFn> {};
template <class T, T (*K)()> friend class senf::detail::VariantKey;
typedef senf::detail::VariantKeyTransform<
// start SENF_PARSER_COLLECTION_I
static bool const content__aux_fixed = (SENF_MPL_SLOT_GET(group) - type_group) == 0;
- typedef senf::detail::ParserAuxPolicySelect <
- type_t,
+ typedef senf::detail::ParserAuxPolicySelect <
+ type_t,
SENF_MPL_SLOT_GET(init_bytes) - type_init_bytes,
- content__aux_fixed
+ content__aux_fixed
>::type content__aux_policy;
typedef content__traits::parser<content__aux_policy, senf::detail::auxtag::none>::type
content__collection_t;
SENF_MPL_SLOT_SET(bit, 0);
SENF_MPL_SLOT_SET(bitfield_size, 0);
- typedef content__collection_t content__t;
+ typedef content__collection_t content__t;
static size_type const content__index = SENF_MPL_SLOT_GET(index) + 1;
SENF_MPL_SLOT_SET(index, content__index);
void init_chain (senf::mpl::rv<content__index> *) const
return content__next_offset();
}
SENF_MPL_SLOT_SET(init_bytes, content__next_init_bytes);
- static size_type const content__group =
+ static size_type const content__group =
SENF_MPL_SLOT_GET(group) + (senf::is_fixed<content__collection_t>::value ? 0 : 1);
SENF_MPL_SLOET_SET(group, content__group);
template < class T >
void init_content() const
{
content_().init<1>();
- }
+ }
bool has_content() const
{
return content_().variant() == 1;
{}
private:
- template <class T>
+ template <class T>
void init(T) const
- {
+ {
defaultInit ();
}
The macros take care of the following:
\li They define the accessor functions returning parsers of the given type.
\li They automatically calculate the offset of the fields from the preceding fields.
- \li The macros provide a definition for \c init()
+ \li The macros provide a definition for \c init()
\li The macros define the \c bytes(), \c fixed_bytes and \c init_bytes members as needed.
You may define either a fixed or a dynamically sized parser. Fixed size parsers are defined by
# include SENF_FIXED_PARSER()
SENF_PARSER_FIELD ( table_id , UInt8Parser );
-
+
SENF_PARSER_BITFIELD ( ssi , 1 , bool );
SENF_PARSER_BITFIELD ( private_indicator , 1 , bool );
SENF_PARSER_SKIP_BITS( 2 );
SENF_PARSER_BITFIELD ( sec_length , 12 , unsigned );
-
+
SENF_PARSER_FIELD ( table_id_extension , UInt16Parser );
-
+
SENF_PARSER_FINALIZE( Parse_DSMCCSection );
};
This code defines two parsers, the second of which is based on the first. Both are fixed size
parsers. The definition of \c Parse_DSMCCSection is straight forward (more on bit fields
- below).
+ below).
The derived parser is a little bit more complex. It starts out the same defining itself as a
fixed size parser. Then the base class is imported. Among other things, this call sets the
the \e name() accessor member is not the parser but the parsers value and therefore it does
not allow assignment to the field.
- \par \c PRIVATE: Fields private to the parser class
+ \par \c PRIVATE: Fields private to the parser class
A private field will not be accessible from the outside (it is made \c private to the parser
class). This is very handy when providing other accessor members to access a field in a
manner more suitable for the specific field, when combining several fields into a single
\subsection parsermacrosbitfields Bit-fields
- \par ""
+ \par ""
\ref SENF_PARSER_BITFIELD(), \ref SENF_PARSER_BITFIELD_RO(), \ref
SENF_PARSER_PRIVATE_BITFIELD()\n
\ref SENF_PARSER_SKIP(), \ref SENF_PARSER_SKIP_BITS(), \ref SENF_PARSER_GOTO(), \ref
SENF_PARSER_GOTO_OFFSET(), \ref SENF_PARSER_LABEL()
- To define more complex parsers, there are some macro commands which change the current offset.
+ To define more complex parsers, there are some macro commands which change the current offset.
\ref SENF_PARSER_SKIP(\e bytes) will skip the given number of bytes. \ref
SENF_PARSER_SKIP_BITS(\e bits) will work within bitfield definition to skip that number of bits.
then later be referenced using \ref SENF_PARSER_GOTO(). This also defines
<em>name</em><tt>_offset</tt> as a constant or member (for fixed respectively dynamically sized
parsers).
-
+
It is very important to recognize, that the size of the parser is defined by the current offset
<em>at the time \ref SENF_PARSER_FINALIZE() is called</em>. This allows to arbitrarily
manipulate the size of the parser by changing the current offset accordingly. For dynamically
///@{
/** \brief Define fixed size parser
-
+
This macro must be called using \c \#include at the beginning of every fixed size parser using
the packet parser helper macros:
#define SENF_FIXED_PARSER() SENF_ABSOLUTE_INCLUDE_PATH(Packets/parse_fixed_setup.hh)
/** \brief Define dynamically sized parser
-
+
This macro must be called using \c \#include at the beginning of every dynamically sized parser
using the packet parser helper macros:
SENF_PARSER_INHERIT(BaseParser)
\endcode
-
+
If you want to define collection fields which reference auxiliary fields in the base parser,
<em>you must define the base parser as a variable parser not a fixed parser</em>.
constructor, parser size, parser initialization). \ref SENF_PARSER_FINALIZE() needs not be the
last macro command within the parser though it will often be the last command since \ref
SENF_PARSER_FINALIZE() does not account for fields defined later.
-
+
\ref SENF_PARSER_FINALIZE() uses the information from \ref SENF_PARSER_INHERIT() to construct
- the parsers base class (which must be a valid parser class).
+ the parsers base class (which must be a valid parser class).
\c defaultInit() is defined to initialize all fields <em>defined before the call to \ref
SENF_PARSER_FINALIZE()</em>. Fields defined later will \e not be initialized. If \ref
\see \ref SENF_PARSER_FIELD_RO(), \ref SENF_PARSER_PRIVATE_FIELD()
\hideinitializer
*/
-#define SENF_PARSER_FIELD(name, type)
+#define SENF_PARSER_FIELD(name, type)
/** \brief Define parser field (read-only)
-
+
Define read-only parser field. Read-only fields may only be defined for \a type's which are
value parsers: The parser \a type must have a \c value_type typedef member and a \c value()
member, which returns the current value of the field.
Defining such a field really defines \e two accessors: A read/write \e private field and a
read-only \e public accessor. The name of the private read/write field is given by adding a
trailing '_' to \a name. The read-only public accessor is called \a name.
-
- \see SENF_PARSER_FIELD()
+
+ \see SENF_PARSER_FIELD()
\hideinitializer
*/
-#define SENF_PARSER_FIELD_RO(name, type)
+#define SENF_PARSER_FIELD_RO(name, type)
/** \brief Define parser field (private)
\see SENF_PARSER_FIELD()
\hideinitializer
*/
-#define SENF_PARSER_PRIVATE_FIELD(name, type)
+#define SENF_PARSER_PRIVATE_FIELD(name, type)
/** \brief Define custom field accessor
return parse<xyz_t>( xyz_offset );
}
\endcode
-
+
The macro defines the same auxiliary symbols defined by \ref SENF_PARSER_FIELD(\a name, \a
type), the accessor method however is provided by the user.
- \a size depends on the type of parser being defined:
+ \a size depends on the type of parser being defined:
\li If defining a fixed parser, \a size is a single value \a bytes which must be a constant
integral expression giving the fixed size of the field.
\param[in] size size of the field, either a single value \a bytes for fixed size parsers or two
separate arguments \a bytes and \a init_bytes for dynamically sized parsers
*/
-#define SENF_PARSER_CUSTOM_FIELD(name, type, size)
+#define SENF_PARSER_CUSTOM_FIELD(name, type, size)
///@}
Bit fields are supported by a special family of parser macros. These macros simplify defining
fields using the senf::IntFieldParser, senf::UIntFieldParser and senf::FlagParser parsers by
- keeping track of the current bit position and automatically creating the correct template
+ keeping track of the current bit position and automatically creating the correct template
parameters.
-
+
The \a type parameter specifies the type of bitfield to define. This value is one of
\li \c signed, for signed bit fields (senf::IntFieldParser)
- \li \c unsigned, for unsigned bit fields (senf::UIntFieldParser) or
- \li \c bool, for single-bit flags (senf::FlagParser).
+ \li \c unsigned, for unsigned bit fields (senf::UIntFieldParser) or
+ \li \c bool, for single-bit flags (senf::FlagParser).
The \a bits parameter specifies the number of bits the field covers. For \c signed or \c
unsigned fields, this value may be any numeric value from 1 to 32, for \c bool fields, this
\see \ref SENF_PARSER_BITFIELD_RO(), \ref SENF_PARSER_PRIVATE_BITFIELD()
\hideinitializer
*/
-#define SENF_PARSER_BITFIELD(name, bits, type)
+#define SENF_PARSER_BITFIELD(name, bits, type)
-/** \brief Define bit-field (read-only)
+/** \brief Define bit-field (read-only)
Define read-only bit field. This is for bit-fields what \ref SENF_PARSER_FIELD_RO is for ordinary fields.
\see \ref SENF_PARSER_BITFIELD() \n \ref SENF_PARSER_FIELD_RO()
\hideinitializer
*/
-#define SENF_PARSER_BITFIELD_RO(name, bits, type)
+#define SENF_PARSER_BITFIELD_RO(name, bits, type)
-/** \brief Define bit-field (private)
+/** \brief Define bit-field (private)
Define a bit field which is marked as \c private and may only be accessed from the parser class
itself.
\see \ref SENF_PARSER_BITFIELD()
\hideinitializer
*/
-#define SENF_PARSER_PRIVATE_BITFIELD(name, bits, type)
+#define SENF_PARSER_PRIVATE_BITFIELD(name, bits, type)
///@}
/** \brief Change current offset to explicit value
\ref SENF_PARSER_GOTO_OFFSET() allows to change the current offset manually to an arbitrary
- value. The \a offset parameter depends on the type of field currently being defined.
-
+ value. The \a offset parameter depends on the type of field currently being defined.
+
\li If defining a <em>fixed size parser</em>, the \a offset argument is a single \a bytes value
which is an integral constant expression to which the offset will be set.
\li If defining a <em>dynamically sized parser</em>, the \a offset argument is given by two
This command defines \a name as a label for the current offset. The member
<em>name</em><tt>_offset</tt> is defined (either as a constant for fixed size parsers or as a
member function for dynamically sized parsers) to return the position at the point of label
- definition.
+ definition.
\ref SENF_PARSER_GOTO() can later be used to jump to a position which has previously been
labeled with \ref SENF_PARSER_LABEL()
#define SENF_PARSER_FIXED_OFFSET(name)
/** \brief Get current fixed offset, if possible
-
+
This macro will return the current fixed offset, a compile-time constant expression. This is
always possible when defining a fixed size parser.
SENF_PARSER_CUSTOM_FIELD ( customField , int, 2 ) {
return parse<senf::UInt16Parser>(customField_offset);
}
-
+
SENF_PARSER_BITFIELD ( signedBitfield , 4, signed );
SENF_PARSER_BITFIELD ( unsignedBitfield , 3, unsigned );
SENF_PARSER_BITFIELD ( boolBitfield , 1, bool );
SENF_PARSER_PRIVATE_FIELD ( privLowbyteOfNormalField , senf::UInt8Parser );
- unsigned lowbyteOfNormalField() {
+ unsigned lowbyteOfNormalField() {
return privLowbyteOfNormalField();
}
# include SENF_FIXED_PARSER()
SENF_PARSER_INHERIT( FixedBaseParser );
-
+
SENF_PARSER_FIELD ( derivedField , senf::UInt16Parser );
SENF_PARSER_LABEL( end );
SENF_PARSER_GOTO( signedBitfield );
SENF_PARSER_FIELD ( anotherOverlay , senf::UInt16Parser );
-
+
SENF_PARSER_GOTO( end );
SENF_PARSER_FINALIZE( FixedDerivedParser )
BOOST_CHECK_EQUAL ( derivedParser.overlayOfRoField() , 0x0304 );
BOOST_CHECK_EQUAL ( derivedParser.overlayOfBitfield() , 0x83u );
BOOST_CHECK_EQUAL ( derivedParser.lowbyteOfNormalField() , 0x02u );
-
+
BOOST_CHECK_EQUAL ( derivedParser.derivedField() , 0x0708u );
BOOST_CHECK_EQUAL ( derivedParser.anotherOverlay() , 0x8384u );
}
SENF_PARSER_CUSTOM_FIELD ( customField , int, 2, 2 ) {
return parse<senf::UInt16Parser>(customField_offset());
}
-
+
SENF_PARSER_BITFIELD ( signedBitfield , 4, signed );
SENF_PARSER_BITFIELD ( unsignedBitfield , 3, unsigned );
SENF_PARSER_BITFIELD ( boolBitfield , 1, bool );
SENF_PARSER_PRIVATE_FIELD ( privLowbyteOfNormalField , senf::UInt8Parser );
- unsigned lowbyteOfNormalField() {
+ unsigned lowbyteOfNormalField() {
return privLowbyteOfNormalField();
}
# include SENF_PARSER()
SENF_PARSER_INHERIT( VariableBaseParser );
-
+
SENF_PARSER_FIELD ( derivedField , senf::UInt16Parser );
SENF_PARSER_LABEL( end );
SENF_PARSER_GOTO( signedBitfield );
SENF_PARSER_FIELD ( anotherOverlay , senf::UInt16Parser );
-
+
SENF_PARSER_GOTO( end );
SENF_PARSER_FINALIZE( VariableDerivedParser );
senf::DataPacket p (senf::DataPacket::create(data));
VariableBaseParser baseParser (p.data().begin(), &p.data());
-
+
BOOST_CHECK_EQUAL ( senf::bytes(baseParser), 8u );
BOOST_CHECK_EQUAL ( baseParser.normalField() , 0x0102u );
BOOST_CHECK_EQUAL ( derivedParser.overlayOfRoField() , 0x0304 );
BOOST_CHECK_EQUAL ( derivedParser.overlayOfBitfield() , 0x83u );
BOOST_CHECK_EQUAL ( derivedParser.lowbyteOfNormalField() , 0x02u );
-
+
BOOST_CHECK_EQUAL ( derivedParser.derivedField() , 0x0708u );
BOOST_CHECK_EQUAL ( derivedParser.anotherOverlay() , 0x8384u );
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
typedef PacketData::size_type size_type;
safe_data_iterator(); ///< Make uninitialized iterator
- explicit safe_data_iterator(PacketData & data);
+ explicit safe_data_iterator(PacketData & data);
///< Construct iterator only setting the data container
safe_data_iterator(PacketData & data, PacketData::iterator i);
///< Initialize iterator to given position
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
template <class LengthParser>
prefix_ senf::StringParser<LengthParser>::StringParser(data_iterator i, state_type s)
- : PacketParserBase(i, s, init_bytes)
+ : PacketParserBase(i, s, init_bytes)
{}
template <class LengthParser>
prefix_ typename senf::StringParser<LengthParser>::size_type senf::StringParser<LengthParser>::bytes()
const
-{
- return length().value() + senf::bytes(length());
+{
+ return length().value() + senf::bytes(length());
}
template <class LengthParser>
prefix_ typename senf::StringParser<LengthParser>::value_type senf::StringParser<LengthParser>::value()
const
-{
- validate(bytes());
- return std::string(i()+senf::bytes(length()), i()+bytes());
+{
+ validate(bytes());
+ return std::string(i()+senf::bytes(length()), i()+bytes());
}
template <class LengthParser>
prefix_ void senf::StringParser<LengthParser>::value(value_type v)
-{
+{
validate(bytes());
- resize(bytes(), v.size()+senf::bytes(length()));
- length() << v.size();
+ resize(bytes(), v.size()+senf::bytes(length()));
+ length() << v.size();
std::copy(v.begin(), v.end(), i()+senf::bytes(length()));
}
prefix_ senf::StringParser<LengthParser>::operator value_type()
const
{
- return value();
+ return value();
}
template <class LengthParser>
prefix_ typename senf::StringParser<LengthParser> const & senf::StringParser<LengthParser>::operator=(value_type other)
-{
- value(other); return *this;
+{
+ value(other); return *this;
}
template <class LengthParser>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
-
+
template <class LengthParser=senf::UInt16Parser>
class StringParser
: public PacketParserBase
# include SENF_PARSER()
SENF_PARSER_PRIVATE_FIELD ( length, LengthParser );
-
+
typedef std::string value_type;
static const size_type init_bytes = senf::init_bytes<LengthParser>::value;
size_type bytes() const;
-
+
value_type value() const;
void value(value_type v);
operator value_type() const;
template <class LengthParser>
std::ostream & operator<<(std::ostream & os, StringParser<LengthParser> const & value);
-
+
}
///////////////////////////////hh.e////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace {
struct VoidPacket : public senf::PacketTypeBase
{};
-
+
typedef senf::StringParser<senf::UInt16Parser> MyStringParser;
}
template <class AuxPolicy, class Parsers>
template <unsigned N>
prefix_ typename boost::mpl::at<
- typename senf::VariantParser<AuxPolicy,Parsers>::parsers,
+ typename senf::VariantParser<AuxPolicy,Parsers>::parsers,
boost::mpl::int_<N> >::type
senf::VariantParser<AuxPolicy,Parsers>::get()
const
defined condition. This is the parser to use, if the type and/or number of fields of a
packet change depending on some condition.
\code
- typedef senf::VariantParser<
- MyAuxPolicy,
+ typedef senf::VariantParser<
+ MyAuxPolicy,
senf::mpl::vector<senf::VoidPacketParser, TypeAParser, TypeBParser> > MyVariantParser;
\endcode
This typedef defines a variant parser choosing one of three sub
When creating a new packet containing a variant parser, the variant parser will always be
initialized to the first sub-parser.
- \see
+ \see
ExampleAuxPolicy on how to implement the \a AuxPolicy \n
\ref SENF_PARSER_VARIANT() on how to integrate the parser into another parser
\ingroup parsecollection
*/
template <class AuxPolicy, class Parsers>
- class VariantParser
+ class VariantParser
: public PacketParserBase, private AuxPolicy
{
typedef Parsers parsers;
size_type bytes() const;
void init();
-
- static const size_type init_bytes = senf::init_bytes<
- typename boost::mpl::at<parsers, boost::mpl::int_<0> >::type>::value
+
+ static const size_type init_bytes = senf::init_bytes<
+ typename boost::mpl::at<parsers, boost::mpl::int_<0> >::type>::value
+ AuxPolicy::aux_bytes;
///\}
\returns Index of currently selected variant. Integer
in the range from 0 to (number-of-sub-parsers - 1)
*/
-
+
template <unsigned N>
typename boost::mpl::at< parsers, boost::mpl::int_<N> >::type get() const;
///< Access sub-parser
struct SomeParser : public PacketParserBase
{
# include SENF_PARSER()
-
+
SENF_PARSER_PRIVATE_FIELD( type, senf::UInt8Parser );
SENF_PARSER_VARIANT( content, type,
(novalue( disable, senf::VoidPacketParser ))
SENF_PARSER_FINALIZE(SomeParser);
};
- \endcode
-
+ \endcode
+
The variant \c content chooses one of the sub parsers depending on the \c type field. If \c
- type is 0, senf::VoidPacketParser is selected, if it is 1, senf::UInt8Parser and so on.
+ type is 0, senf::VoidPacketParser is selected, if it is 1, senf::UInt8Parser and so on.
\warning Realize, that the \a chooser field is controlled by the variant parser. This field
should therefore be declared either read-only or private and must be changed only via
<tr><td><tt>void</tt> <tt>init_</tt><em>name</em>()</td><td>Set the variant to have a value
of this type. If the field is \c novalue, the \c init_ prefix is omitted.</td></tr>
-
+
<tr><td><tt>bool</tt> <tt>has_</tt><em>name</em>()</td><td>Return \c true, if the variant
currently holds this kind of value, \c false otherwise. Only if not \c novalue.</td></tr>
</table>
(senf::UInt24Parser)
(senf::UInt32Parser) );
\endcode
-
+
\param[in] name name of the field
\param[in] chooser name of the field choosing the variant to use
\param[in] types a Boost.Preprocessor style sequence of sub-parser types
- \see
- senf::VariantParser for the VariantParser API\n
+ \see
+ senf::VariantParser for the VariantParser API\n
\ref SENF_PARSER_PRIVATE_VARIANT()
\hideinitializer
\ingroup packetparsermacros
SENF_PARSER_VARIANT_I(public, name, chooser, types)
/** \brief Define private VariantParser field
-
+
\see \ref SENF_PARSER_VARIANT()
\hideinitializer
\ingroup packetparsermacros
template <class Transform, class AuxPolicy, class AuxTag>
struct VariantParserPolicy
- : public VariantParserPolicy< void,
+ : public VariantParserPolicy< void,
TransformAuxParserPolicy<AuxPolicy, Transform>, AuxTag >
{};
template <class AuxPolicy, class Transform>
struct VariantParserPolicy<void,
- AuxPolicy,
- senf::detail::auxtag::transform<Transform,
+ AuxPolicy,
+ senf::detail::auxtag::transform<Transform,
senf::detail::auxtag::none> >
{
typedef TransformAuxParserPolicy<AuxPolicy, Transform> type;
};
};
- template <class T, T (*KeyFn)()>
- struct VariantKey
+ template <class T, T (*KeyFn)()>
+ struct VariantKey
{
static T key() { return (*KeyFn)(); }
};
static Out get(In v);
static In set(Out v);
};
-
+
# define SENF_PARSER_VARIANT_I(access, name, chooser, types) \
SENF_PARSER_REQUIRE_VAR(variant) \
protected: \
# define SENF_PARSER_VARIANT_IFNOTNA(id, x) \
BOOST_PP_EXPR_IIF( BOOST_PP_NOT( SENF_PARSER_VARIANT_NA(id) ), x )
-
+
# define SENF_PARSER_VARIANT_MAKEACCESSOR_VALUE(name, i, elem, id) \
SENF_PARSER_VARIANT_IFNOTNA( id, \
typedef SENF_PARSER_VARIANT_GETTYPE(elem) \
BOOST_PP_CAT(id, _t) id() const \
{ return name().get<i>(); } \
)
-
+
# define SENF_PARSER_VARIANT_MAKEACCESSOR_HAS(name, i, elem, id) \
SENF_PARSER_VARIANT_IFNOTNA( id, \
bool id() const \
typedef senf::ArrayParser<10, senf::UInt8Parser> Array10;
typedef senf::VariantParser< senf::detail::FixedAuxParserPolicy<senf::UInt8Parser, 1>,
boost::mpl::vector<senf::VoidPacketParser, Array10, senf:: UInt32Parser> > Variant;
-
+
unsigned char data[] = { 0x01, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1A, 0x1B };
senf::DataPacket p (senf::DataPacket::create(data));
BOOST_REQUIRE_EQUAL( p.data().size(), 11u );
BOOST_REQUIRE_EQUAL( v.variant(), 0u );
BOOST_CHECK_EQUAL( senf::bytes(v), 0u );
-
+
v.init<2>();
// v invalidated
}
};
}
-// We can't use the unnamed namespace here since there's a bug in gcc-4.2.3 which is
+// We can't use the unnamed namespace here since there's a bug in gcc-4.2.3 which is
// the default version of gcc on ubuntu hardy :-(
// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34213
namespace VariantParser_test_cc_anon_namespace {
-
+
struct SubParser : public senf::PacketParserBase
- {
+ {
# include SENF_FIXED_PARSER()
SENF_PARSER_FIELD( foo, senf::UInt32Parser );
SENF_PARSER_BITFIELD_RO( len, 4, unsigned );
SENF_PARSER_BITFIELD_RO( type, 4, unsigned );
// just here so the second variant is 'var'
- SENF_PARSER_VARIANT( value, len,
+ SENF_PARSER_VARIANT( value, len,
(senf::VoidPacketParser)
(senf::UInt8Parser)
(senf::UInt16Parser)
SENF_PARSER_FINALIZE(TestParser);
};
-
+
}
using namespace VariantParser_test_cc_anon_namespace;
SENF_AUTO_UNIT_TEST(VariantParserMacro)
{
senf::DataPacket p (senf::DataPacket::create(senf::init_bytes<TestParser>::value));
-
+
{
TestParser v (p.data().begin(), & p.data());
v.init();
size_type n,
Value const & t)
{
- for (iterator j (shift(pos,n)); n; --n, ++j)
+ for (iterator j (shift(pos,n)); n; --n, ++j)
*j << t;
}
template <class ElementParser, class AuxPolicy>
prefix_ senf::VectorParser_Container<ElementParser,AuxPolicy>::
VectorParser_Container(parser_type const & vector)
- : AuxPolicy::WrapperPolicy(static_cast<AuxPolicy const &>(vector)), state_ (vector.state()),
+ : AuxPolicy::WrapperPolicy(static_cast<AuxPolicy const &>(vector)), state_ (vector.state()),
i_ (std::distance(data().begin(),vector.i()))
{}
A Vector is a collection of fixed-size elements of which the size of the collection can be
determined directly (that is without traversing the collection). This allows very efficient
random access to the elements of the collection.
-
+
A vector is a model of an STL random-access sequence. The parser only provides a reduced
interface, the container wrapper however completes this interface.
Some basic vector access methods are defined as parser members. To access the complete list
API however you will need to instantiate a container wrapper for the vector. See \ref
packet_usage_fields_collection.
-
+
\see
\ref How to access \ref packet_usage_fields_collection \n
SENF_PARSER_VECTOR() macro used to define vector fields \n
\ingroup parsecollection
*/
template <class ElementParser, class AuxPolicy>
- struct VectorParser
- : public PacketParserBase,
+ struct VectorParser
+ : public PacketParserBase,
private AuxPolicy
{
VectorParser(data_iterator i, state_type s);
value_type back() const;
// Mutators
-
+
// The mutators provided here are those which don't take an iterator argument.
// If you need to pass an iterator it is much simpler and cleaner to use the
// 'container' wrapper
-
+
template <class Value> void push_back (Value const & value, size_type n=1) const;
value_type push_back_space (size_type n=1) const;
template <class Value> void push_front (Value const & value, size_type n=1) const;
the vector in the packet data).
The vector container wrapper provides a complete STL random-access sequence interface.
-
+
\code
SomePacket p (...);
SomePacket::aVectorCollection_t::container c (p->aVectorCollection());
size_type bytes() const;
void init() const;
-
+
///@}
protected:
};
/** \brief Define VectorParser field
-
+
This macro is a special helper to define a senf::VectorParser type field, a vector of
elements of type \a elt_type (a parser) which size is given by the \a size field.
<table class="senf fixedcolumn">
<tr><td>\c bytes(\a size)</td><td>\a size gives the size of the vector in bytes not the
number of contained elements</td></tr>
-
+
<tr><td>\c packetSize()</td><td>Use the size of the packet to get the vector size. The
vector will occupy all space up to the end of the packet.</td></tr>
SENF_PARSER_VECTOR ( vec, transform(MyTransform, vec_size_), senf::UInt32Parser );
SENF_PARSER_VECTOR ( vec, packetSize(), senf::UInt32Parser );
\endcode
-
+
\param[in] name field name
\param[in] size name of field giving the vector size
\param[in] elt_type vector element type
- \see
+ \see
How to use \ref packet_usage_fields_collection \n
senf::VectorParser the vector parser API for vector field access
senf::VectorParser_Container the vector parser container API for vector field access
};
template <class ElementParser, class AuxPolicy, class Transform>
- struct VectorParserPolicy<ElementParser, AuxPolicy,
+ struct VectorParserPolicy<ElementParser, AuxPolicy,
senf::detail::auxtag::transform<Transform,
senf::detail::auxtag::none> >
{
struct VectorParserPolicy<ElementParser, AuxPolicy, senf::detail::auxtag::bytes>
{
typedef senf::detail::TransformAuxParserPolicy<
- AuxPolicy,
+ AuxPolicy,
VectorParserBytesTransform<ElementParser::fixed_bytes> > type;
};
template <class AuxPolicy, class AuxTag>
struct parser {
typedef senf::VectorParser<
- ElementParser,
+ ElementParser,
typename VectorParserPolicy<ElementParser, AuxPolicy, AuxTag>::type > type;
};
};
#endif
}}
-
+
///////////////////////////////ih.e////////////////////////////////////////
#endif
{
UInt16VectorParser v (boost::next(p->data().begin(), 1), &p->data());
-
+
BOOST_CHECK_EQUAL( v[0], 0x1011 );
BOOST_CHECK_EQUAL( v[2], 0x1415 );
BOOST_CHECK_EQUAL( v.size(), 3u );
p->data()[0] = 0x06;
BOOST_CHECK_EQUAL( v.size(), 6u );
BOOST_CHECK_EQUAL( v.bytes(), 12u );
-
+
UInt16VectorParser::iterator b (v.begin());
UInt16VectorParser::iterator e (v.end());
BOOST_CHECK_EQUAL(std::distance(b,e), UInt16VectorParser::difference_type(v.size()));
v.push_back_space() = 37u;
BOOST_CHECK_EQUAL( v.size(), 9u );
BOOST_CHECK_EQUAL( v[8], 37u );
-
+
v.push_front(0xf3f4u);
BOOST_CHECK_EQUAL( v.size(), 10u );
BOOST_CHECK_EQUAL( v[0], 0xf3f4u );
BOOST_CHECK_EQUAL( w.size(), 3u );
p->data()[0] = 0x06;
BOOST_CHECK_EQUAL( w.size(), 6u );
- BOOST_CHECK_EQUAL( std::distance(w.begin(),w.end()),
+ BOOST_CHECK_EQUAL( std::distance(w.begin(),w.end()),
UInt16VectorParser::difference_type(w.size()) );
w.shift(w.begin()+1);
UInt16VectorParser v (senf::UInt8Parser(p->data().begin(), &p->data()),
boost::next(p->data().begin(),1), &p->data());
UInt16VectorParser::container w (v);
-
+
BOOST_CHECK_EQUAL( v.size(), 3u );
BOOST_CHECK_EQUAL( w.size(), 3u );
static unsigned set(unsigned v) { return v+2; }
};
- struct TestVectorParser
+ struct TestVectorParser
: public senf::PacketParserBase
{
# include SENF_PARSER()
SENF_PARSER_FINALIZE( TestVectorParser );
};
-
+
struct TestVectorPacketType
: public senf::PacketTypeBase,
public senf::PacketTypeMixin<TestVectorPacketType>
using mixin::nextPacketRange;
using mixin::init;
- using mixin::initSize;
+ using mixin::initSize;
};
typedef senf::ConcretePacket<TestVectorPacketType> TestVectorPacket;
senf::DataPacket p (senf::DataPacket::create(data));
TestVectorParser parser (p.data().begin(), &p.data());
-
+
BOOST_CHECK_EQUAL( parser.vec1().size(), 3u );
BOOST_CHECK_EQUAL( parser.vec2().size(), 2u );
BOOST_CHECK_EQUAL( parser.dummy(), 0x01020304u );
p->vec2().push_back( 0x0B0Cu);
p->vec2().push_back( 0x0D0Eu);
p.finalizeAll();
-
- unsigned char data[] = {
+
+ unsigned char data[] = {
0x05, // size1
0x04, // size2
0x01, 0x02, 0x03, 0x04, // dummy
0x0B, 0x0C, // vec2[0]
0x0D, 0x0E // vec2[1]
};
- SENF_CHECK_EQUAL_COLLECTIONS(
+ SENF_CHECK_EQUAL_COLLECTIONS(
data, data+sizeof(data), p.data().begin(), p.data().end() );
}
namespace {
-
- struct TestVectorBaseParser
+
+ struct TestVectorBaseParser
: public senf::PacketParserBase
{
# include SENF_PARSER()
senf::DataPacket p (senf::DataPacket::create(data));
TestVectorDerivedParser parser (p.data().begin(), &p.data());
-
+
BOOST_CHECK_EQUAL( parser.vec1().size(), 3u );
BOOST_CHECK_EQUAL( parser.vec2().size(), 2u );
BOOST_CHECK_EQUAL( parser.dummy(), 0x01020304u );
# include SENF_PARSER()
SENF_PARSER_VECTOR ( vec , packetSize() , senf::UInt16Parser );
-
+
SENF_PARSER_FINALIZE( TestPacketSizeVectorParser );
};
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
// This test shall test, if there is now duplicated packet registration in AllBundles.
// The test will fail at the start with an assertion error in this case.
-
+
boost::uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // source mac
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // target mac
0x86, 0xdd, // ethertype
- 0x60, 0x00, 0x00, 0x00, // IP version, class,
+ 0x60, 0x00, 0x00, 0x00, // IP version, class,
// flow label
0x00, 0x00, // payload length
0x3B, // no next header
0x10, // hop limit
0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // source ip
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // target ip
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 };
#define HH_SENF_Scheduler_ClockService_ 1
// Custom includes
-#include <sys/time.h>
+#include <sys/time.h>
#include <boost/utility.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/scoped_ptr.hpp>
// To allow conversion between clock value and absolute time, the ClockService samples the
// absolute current time and the clock value when the conversion is performed. This is done at
// most once per second on a if-needed basis.
-
+
/** \brief Reliable high precision monotonous clock source
The ClockService provides a highly accurate monotonous clock source based on
// Types
/** \brief ClockService timer data type
-
+
Unsigned integer type representing scheduler time. Scheduler time is measured in
nanoseconds relative to some implementation defined reference time.
*/
///////////////////////////////////////////////////////////////////////////
static clock_type now(); ///< Return current clock value
-
+
static abstime_type abstime(clock_type clock); ///< Convert clock to absolute time
/**< This member converts a clock value into an absolute
Boost.DateTime value.
corresponding clock value.
\see abstime */
- static clock_type from_time_t(time_t const & time);
+ static clock_type from_time_t(time_t const & time);
///< Convert legacy time_t to clock value
- /**< This member converts an absolute time value
+ /**< This member converts an absolute time value
represented as a time_t value into a clock value */
- static clock_type from_timeval(timeval const & time);
+ static clock_type from_timeval(timeval const & time);
///< Convert legacy timeval to clock value
/**< This member converts an absolute time value
represented as a timeval value into a clock value */
<tr><td><code>2md</code></td><td>(very unusual) 2 milli-days</td></tr>
</table>
*/
- void parseClockServiceInterval(console::ParseCommandInfo::TokensRange const & tokens,
+ void parseClockServiceInterval(console::ParseCommandInfo::TokensRange const & tokens,
ClockService::clock_type & out);
void formatClockServiceInterval(ClockService::clock_type interval, std::ostream & os);
namespace {
- bool is_close_clock(senf::ClockService::clock_type a, senf::ClockService::clock_type b,
+ bool is_close_clock(senf::ClockService::clock_type a, senf::ClockService::clock_type b,
senf::ClockService::clock_type delta)
{
return (a<b ? b-a : a-b ) < delta;
SENF_AUTO_UNIT_TEST(clockService)
{
BOOST_CHECK( senf::ClockService::abstime(0).is_not_a_date_time());
-
+
char const * enabled (getenv("SENF_TIMING_CRITICAL_TESTS"));
BOOST_WARN_MESSAGE(enabled, "Set SENF_TIMING_CRITICAL_TESTS to not skip timing critical tests");
BOOST_CHECK( true );
senf::ClockService::restart(); // So we know, when the signal will be delivered
-
+
senf::ClockService::clock_type t1 (senf::ClockService::now());
delay(200);
senf::ClockService::clock_type t2 (senf::ClockService::now());
if (enabled)
BOOST_CHECK_PREDICATE( is_close_clock,
- (t1 + senf::ClockService::milliseconds(200))
+ (t1 + senf::ClockService::milliseconds(200))
(t2)
(senf::ClockService::milliseconds(100)) );
if (enabled)
BOOST_CHECK_PREDICATE( is_close_clock,
(t1 + senf::ClockService::milliseconds(200))
- (senf::ClockService::now())
+ (senf::ClockService::now())
(senf::ClockService::milliseconds(100)) );
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
informational)
\param[in] cb Callback to call
\param[in] initiallyEnabled if set \c false, do not
- enable callback automatically.
+ enable callback automatically.
\param[in] priority event priority, defaults to
POST */
~EventHook();
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
void restart();
namespace detail {
-
+
class EventHookDispatcher
: public singleton<EventHookDispatcher>
{
EventHookDispatcher();
~EventHookDispatcher();
- typedef boost::intrusive::ilist<
+ typedef boost::intrusive::ilist<
EventHookListBase::value_traits<EventHook>, false > EventList;
EventList events_;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
FIFORunner::iterator i (FIFORunner::instance().begin());
FIFORunner::iterator const i_end (FIFORunner::instance().end());
for (; i != i_end; ++i)
- os << fmt
+ os << fmt
% i->type()
- % i->name()
+ % i->name()
% reinterpret_cast<unsigned long>(&(*i))
% i->runCount()
% (i->runnable() ? "R" : "W")
if (! i->enabled())
os << fmt
% i->type()
- % i->name()
+ % i->name()
% reinterpret_cast<unsigned long>(&(*i))
% i->runCount()
% "-"
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
-
+
explicit Event(std::string const & name);
virtual ~Event();
public:
using singleton<EventManager>::instance;
using singleton<EventManager>::alive;
-
+
struct IteratorFilter {
bool operator()(Event const & e);
};
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
#include <senf/Utils/senfassert.hh>
#include <senf/Utils/ScopeExit.hh>
#ifdef SENF_DEBUG
- #include <execinfo.h>
+ #include <execinfo.h>
#endif
#include <senf/config.hh>
#include <stdint.h>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// senf::scheduler::detail::FIFORunner::NullTask
prefix_ senf::scheduler::detail::FIFORunner::NullTask::NullTask()
- : senf::scheduler::detail::FIFORunner::TaskInfo ("<null>")
+ : senf::scheduler::detail::FIFORunner::TaskInfo ("<null>")
{}
prefix_ senf::scheduler::detail::FIFORunner::NullTask::~NullTask()
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
//#include "FIFORunner.mpp"
///////////////////////////////hh.p////////////////////////////////////////
-namespace senf {
+namespace senf {
namespace scheduler {
void restart();
typedef boost::intrusive::ilist<TaskListBase::value_traits<TaskInfo>, false> TaskList;
public:
- class TaskInfo
- : public Event,
+ class TaskInfo
+ : public Event,
public TaskListBase
{
public:
protected:
void setRunnable();
-
+
private:
virtual void v_run() = 0;
virtual bool v_enabled() const;
void enqueue(TaskInfo * task);
void dequeue(TaskInfo * task);
-
+
void run();
void taskTimeout(unsigned ms);
TaskList::iterator priorityEnd(TaskInfo::Priority p);
void run(TaskList::iterator f, TaskList::iterator l);
-
+
struct NullTask : public TaskInfo
{
NullTask();
NullTask normalPriorityEnd_;
NullTask highPriorityEnd_;
-
+
timer_t watchdogId_;
bool watchdogRunning_;
unsigned watchdogMs_;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
prefix_ senf::scheduler::FdEvent::FdEvent(std::string const & name, Callback const & cb,
Handle const & handle, int events,
bool initiallyEnabled)
- : detail::FIFORunner::TaskInfo (name), cb_ (cb), fd_ (detail::get_descriptor(handle)),
+ : detail::FIFORunner::TaskInfo (name), cb_ (cb), fd_ (detail::get_descriptor(handle)),
pollable_ (true), events_ (events)
{
if (initiallyEnabled)
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
The callback will be called with one additional argument. This argument is the event mask of
type int. This mask will tell, which of the registered events are signaled. There are some
additional flags which can be set when calling the handler callback:
-
+
\li \c EV_HUP: The other end has closed the connection
\li \c EV_ERR: Transport error
Only a single handler may be registered for any combination of file descriptor and event
otherwise a DuplicateEventRegistrationException is thrown.
-
+
The file descriptor is specified using an arbitrary handle type which supports the \c
retrieve_filehandle() protocol: There must be a global function \c retrieve_filehandle
callable with the handle type. This function must return the file descriptor associated with
public detail::FdSetBase,
public detail::FdManager::Event
{
- public:
+ public:
///////////////////////////////////////////////////////////////////////////
// Types
typedef boost::function<void (int)> Callback;
- enum Events {
+ enum Events {
EV_NONE = 0 ///< No event
, EV_READ = detail::FdManager::EV_READ ///< fd readable (or EOF)
, EV_PRIO = detail::FdManager::EV_PRIO ///< OOB data available for read
, EV_WRITE = detail::FdManager::EV_WRITE ///< fd writable
, EV_HUP = detail::FdManager::EV_HUP ///< remote end closed connection
, EV_ERR = detail::FdManager::EV_ERR ///< transport error
- , EV_ALL = (detail::FdManager::EV_READ
- | detail::FdManager::EV_WRITE
+ , EV_ALL = (detail::FdManager::EV_READ
+ | detail::FdManager::EV_WRITE
| detail::FdManager::EV_PRIO) ///< register all events (read, prio and write)
};
explicitly be set to \c 0 if the value cannot be
initialized. */
~FdEvent();
-
+
///@}
///////////////////////////////////////////////////////////////////////////
FdEvent & addEvents(int events); ///< Add additional events to event mask
FdEvent & removeEvents(int events); ///< Remove events from event mask
int events(); ///< Current event mask
-
+
template <class Handle>
FdEvent & handle(Handle const & handle); ///< Change event file handle
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
bool operator()(int a, FdEvent const & b) const
{ return a < b.fd_; }
};
-
+
class FdDispatcher
: public senf::singleton<FdDispatcher>
{
public:
using senf::singleton<FdDispatcher>::instance;
using senf::singleton<FdDispatcher>::alive;
-
+
bool add(FdEvent & event);
void remove(FdEvent & event);
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
error("connect");
BOOST_FAIL("connect");
}
-
+
{
senf::scheduler::FdEvent sockread ("testHandler", boost::bind(&callback, sock, _1),
sock, senf::scheduler::FdEvent::EV_READ);
BOOST_CHECK_EQUAL( calls, 3 );
SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
BOOST_CHECK_EQUAL( calls, 3 );
-
+
// Ensure, removing an already closed file-descriptor doesn't wreak havoc
close(sock);
}
senf::scheduler::detail::FileDispatcher::instance().timeout(500);
int fd (open("test.empty.file", O_RDWR|O_CREAT|O_TRUNC, 0600));
-
+
senf::ClockService::clock_type t (senf::ClockService::now());
try {
- senf::scheduler::FdEvent fde ("testHandler", &handler,
+ senf::scheduler::FdEvent fde ("testHandler", &handler,
fd, senf::scheduler::FdEvent::EV_READ);
SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
SENF_CHECK_NO_THROW( senf::scheduler::detail::FileDispatcher::instance().prepareRun() );
SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
-
+
BOOST_CHECK( called );
if (enabled)
BOOST_CHECK_PREDICATE( is_close, (t)(senf::ClockService::now()) );
BOOST_CHECK( ! called );
if (enabled)
- BOOST_CHECK_PREDICATE(
+ BOOST_CHECK_PREDICATE(
is_close, (t+senf::ClockService::milliseconds(500))(senf::ClockService::now()) );
unlink("test.empty.file");
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
virtual void signal(int events) = 0; ///< Called when the given event is posted
};
- enum Events {
+ enum Events {
EV_READ = Poller<Event>::EV_READ, EV_PRIO = Poller<Event>::EV_PRIO, EV_WRITE = Poller<Event>::EV_WRITE,
- EV_HUP = Poller<Event>::EV_HUP, EV_ERR = Poller<Event>::EV_ERR
+ EV_HUP = Poller<Event>::EV_HUP, EV_ERR = Poller<Event>::EV_ERR
};
using singleton<FdManager>::instance;
/**< This call waits until at least one event is posted but
no longer than the current timeout(). */
ClockService::clock_type eventTime() const; ///< Time of last event
-
+
protected:
private:
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///\{
-
- IdleEvent(std::string const & name, Callback const & cb,
+
+ IdleEvent(std::string const & name, Callback const & cb,
bool initiallyEnabled = true);
~IdleEvent();
virtual std::string v_info() const;
Callback cb_;
-
+
friend class detail::IdleEventDispatcher;
};
-
+
}}
///////////////////////////////hh.e////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
void restart();
namespace detail {
-
+
class IdleEventDispatcher
: public singleton<IdleEventDispatcher>
{
void add(IdleEvent & event);
void remove(IdleEvent & event);
-
+
void prepareRun();
// Called by PollTimerSource
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
is met (e.g. number of chars read or a specific character sequence is found in the input).
\li senf::WriteHelper writes data to an arbitrary file descriptor until all provided data has
been written.
-
+
\section scheduler_i Implementation
\seechapter \ref scheduler_implementation
\li There is a dispatcher for each event type. This dispatcher manages the event specific
registration and unregistration. The dispatcher is owns the event (and task) objects.
-
+
\li Every registered event is represented by an event specific event class instance.
\li The Dispatcher ultimately registeres with the senf::scheduler::detail::FdManager. Since the
\section scheduler_i_dispatchers Dispatchers
-
+
There is a dispatcher for each event type
\li senf::scheduler::detail::FdDispatcher manages poll-able file descriptors. This does \e not
manage the events. This makes the Scheduler itself be completely devoid of dynamic memory
allocations.
-
+
\section scheduler_i_mainloop The main loop
The application mainloop senf::scheduler::process() is constructed by calling the correct
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
prefix_ bool senf::scheduler::detail::Poller<Value>::set(int fd, int events, Value * data)
{
struct epoll_event ev = { events, { data } };
- if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &ev) != -1)
+ if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &ev) != -1)
return true;
if (errno == EEXIST)
if (epoll_ctl(epollFd_, EPOLL_CTL_MOD, fd, &ev) != -1)
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
public:
///////////////////////////////////////////////////////////////////////////
// Types
-
+
typedef Value value_type;
typedef boost::transform_iterator<GetPollResult, epoll_event*> iterator;
typedef boost::iterator_range<iterator> range;
- enum Events {
+ enum Events {
EV_READ = EPOLLIN, EV_PRIO = EPOLLPRI, EV_WRITE = EPOLLOUT,
- EV_HUP = EPOLLHUP, EV_ERR = EPOLLERR
+ EV_HUP = EPOLLHUP, EV_ERR = EPOLLERR
};
-
+
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
range wait(); ///< Wait for one event
/**< \returns a range of iterators which iterate over the
data values registered with the event */
-
+
void timeout(int t); ///< Set event timeout to \a t milliseconds
int timeout() const; ///< Current event timeout
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
template <class Handle>
prefix_ senf::ReadHelper<Handle>::ReadHelper(Handle handle, std::string::size_type maxSize,
InternalPredicate * predicate, Callback cb)
- : handle_(handle),
+ : handle_(handle),
fde_("senf::ReadHelper", boost::bind(&ReadHelper::dispatchProcess,ptr(this), handle, _1),
handle, senf::scheduler::FdEvent::EV_READ),
maxSize_(maxSize), predicate_(predicate), callback_(cb), errno_(0), complete_(false)
private:
struct InternalPredicate;
- ReadHelper(Handle handle, std::string::size_type maxSize,
+ ReadHelper(Handle handle, std::string::size_type maxSize,
InternalPredicate * predicate, Callback cb);
static void dispatchProcess(ptr helper, Handle handle, int event);
}
namespace {
-
+
// We don't want try { } catch(...) { ... throw; } since that will make debugging more
// difficult: the stack backtrace for an unexpected exception would always end here.
struct SchedulerScopedInit
{
- SchedulerScopedInit()
+ SchedulerScopedInit()
{
senf::scheduler::detail::FIFORunner::instance().startWatchdog();
senf::scheduler::detail::SignalDispatcher::instance().unblockSignals();
fdd->~FdDispatcher();
ffr->~FIFORunner();
fdm->~FdManager();
-
+
new (fdm) detail::FdManager();
new (ffr) detail::FIFORunner();
new (fdd) detail::FdDispatcher();
prefix_ bool senf::scheduler::empty()
{
- return detail::FdDispatcher::instance().empty()
+ return detail::FdDispatcher::instance().empty()
&& detail::TimerDispatcher::instance().empty()
&& detail::FileDispatcher::instance().empty()
&& detail::SignalDispatcher::instance().empty()
public:
SomeServer(SomeSocketHandle handle)
- : handle_ (handle),
+ : handle_ (handle),
event_ ("SomeServer handler", senf::membind(&SomeServer::readData, this),
handle, senf::scheduler::FdEvent::EV_READ)
{}
// Handle callback function
void callback(UDPv4ClientSocketHandle handle, senf::Scheduler::EventId event) {..}
// Pass 'handle' as additional first argument to callback()
- senf::scheduler::FdEvent event ("name", boost::bind(&callback, handle, _1),
+ senf::scheduler::FdEvent event ("name", boost::bind(&callback, handle, _1),
handle, senf::scheduler::FdEvent::EV_READ);
// Timeout function
void timeout( int n) {..}
// e.g. in Foo::Foo() constructor:
Foo::Foo()
: handle_ (...),
- readevent_ ("Foo read", senf::membind(&Foo::callback, this),
+ readevent_ ("Foo read", senf::membind(&Foo::callback, this),
handle_, senf::scheduler::FdEvent::EV_READ)
{ ... }
\endcode
\section sched_exec Executing the Scheduler
To enter the scheduler main-loop, call
-
+
\code
senf::scheduler::process();
\endcode
\code
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/bind.hpp>
-
+
class Foo
{
public:
void add(int fd)
{
fdEvents.insert(
- fd,
- new senf::scheduler::FdEvent("foo", boost::bind(&callback, this, fd, _1), fd,
+ fd,
+ new senf::scheduler::FdEvent("foo", boost::bind(&callback, this, fd, _1), fd,
senf::scheduler::FdEvent::EV_READ) );
}
can produce an informative message and optionally the program can be aborted.
The watchdog is controlled using the watchdogTimeout(), watchdogEvents() and watchdogAbort().
- functions.
+ functions.
The watchdog is implemented using a free running interval timer. The watchdog signal (\c SIGURG)
must \e not be blocked. If signals need to be blocked for some reason, those regions will not be
*/
namespace scheduler {
- /** \brief Event handler main loop
-
+ /** \brief Event handler main loop
+
This member must be called at some time to enter the event handler main loop. Only while
this function is running any events are handled. The call will return if
\li a callback calls terminate()
- \li the run queue becomes empty.
- */
+ \li the run queue becomes empty.
+ */
void process();
/** \brief \c true, if scheduler is running, \c false otherwise */
/** \brief Called by callbacks to terminate the main loop
This member may be called by any callback to tell the main loop to terminate. The main loop
- will return to it's caller after the currently running callback returns.
+ will return to it's caller after the currently running callback returns.
*/
- void terminate();
+ void terminate();
/** \brief Immediately rescheduler
/** \brief Return timestamp of last event
This is the timestamp, the last event has been signaled. This is the real time at which the
- event is delivered \e not the time it should have been delivered (in the case of timers).
+ event is delivered \e not the time it should have been delivered (in the case of timers).
*/
- ClockService::clock_type eventTime();
+ ClockService::clock_type eventTime();
/** \brief Return (approximate) current time
ClockService::clock_type now();
/** \brief Set watchdog timeout to \a ms milliseconds.
-
+
Setting the watchdog timeout to 0 will disable the watchdog.
*/
- void watchdogTimeout(unsigned ms);
+ void watchdogTimeout(unsigned ms);
/** \brief Current watchdog timeout in milliseconds */
- unsigned watchdogTimeout();
+ unsigned watchdogTimeout();
- /** \brief Number of watchdog events
+ /** \brief Number of watchdog events
calling watchtogEvents() will reset the counter to 0
*/
- unsigned watchdogEvents();
+ unsigned watchdogEvents();
/** \brief Enable/disable abort on watchdog event.
-
+
Calling watchdogAbort(\c true) will enable aborting the program execution on a watchdog
event.
*/
bool watchdogAbort();
/** \brief Switch to using hi resolution timers
-
+
By default, timers are implemented directly using epoll. This however restricts the timer
resolution to that of the kernel HZ value.
bool usingHiresTimers();
/** \brief Restart scheduler
-
+
This call will restart all scheduler dispatchers (timers, signals, file descriptors). This
is necessary after a fork().
\warning This call will \e remove all registered events from the scheduler
*/
- void restart();
+ void restart();
/** \brief Return \c true, if no event is registered, \c false otherwise. */
bool empty();
/** \brief Temporarily block all signals
This class is used to temporarily block all signals in a critical section.
-
+
\code
// Begin critical section
{
/**< \param[in] initiallyBlocked set to \c false to not
automatically block signals initially */
~BlockSignals(); ///< Release all signal blocks
-
+
void block(); ///< Block signals if not blocked
void unblock(); ///< Unblock signals if blocked
bool blocked() const; ///< \c true, if signals currently blocked, \c false
{
return (a<b ? b-a : a-b) < senf::ClockService::milliseconds(100);
}
-
+
senf::ClockService::clock_type sigtime (0);
void sigusr(siginfo_t const &)
buffer[size]=0;
BOOST_CHECK_EQUAL( buffer, "OK" );
}
-
+
{
- senf::scheduler::TimerEvent timer1 ("testTimer1", &timeout,
+ senf::scheduler::TimerEvent timer1 ("testTimer1", &timeout,
senf::ClockService::now()+senf::ClockService::milliseconds(200));
senf::scheduler::TimerEvent timer2 ("testTimer2", &timeout,
senf::ClockService::now()+senf::ClockService::milliseconds(400));
-
+
event = senf::scheduler::FdEvent::EV_NONE;
senf::ClockService::clock_type t (senf::ClockService::now());
SENF_CHECK_NO_THROW( senf::scheduler::process() );
senf::ClockService::clock_type t = senf::ClockService::now();
::kill(::getpid(), SIGUSR1);
delay(200);
- SENF_CHECK_NO_THROW( senf::scheduler::process() );
+ SENF_CHECK_NO_THROW( senf::scheduler::process() );
if (enabled) {
BOOST_CHECK_PREDICATE( is_close, (senf::ClockService::now()) (t+senf::ClockService::milliseconds(200)) );
BOOST_CHECK_PREDICATE( is_close, (sigtime) (t+senf::ClockService::milliseconds(200)) );
}
- SENF_CHECK_NO_THROW( senf::scheduler::process() );
- }
+ SENF_CHECK_NO_THROW( senf::scheduler::process() );
+ }
BOOST_CHECK( eventCount >= 8u );
-
+
///////////////////////////////////////////////////////////////////////////
close(sock);
}
namespace {
-
+
void sigme()
{
senf::scheduler::BlockSignals signalBlocker;
senf::scheduler::TimerEvent timer (
"testWatchdog", &timeout, senf::ClockService::now()+senf::ClockService::milliseconds(400));
senf::scheduler::SignalEvent sig (SIGUSR1, &sigusr);
-
+
senf::ClockService::clock_type t = senf::ClockService::now();
- SENF_CHECK_NO_THROW( senf::scheduler::process() );
+ SENF_CHECK_NO_THROW( senf::scheduler::process() );
if (enabled) {
- BOOST_CHECK_PREDICATE( is_close,
- (senf::ClockService::now())
+ BOOST_CHECK_PREDICATE( is_close,
+ (senf::ClockService::now())
(t+senf::ClockService::milliseconds(200)) );
BOOST_CHECK_PREDICATE( is_close, (sigtime) (t+senf::ClockService::milliseconds(200)) );
}
- SENF_CHECK_NO_THROW( senf::scheduler::process() );
+ SENF_CHECK_NO_THROW( senf::scheduler::process() );
}
///////////////////////////////cc.e////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
*/
class SignalEvent
: public detail::FIFORunner::TaskInfo,
- public detail::SignalSetBase
+ public detail::SignalSetBase
{
public:
///////////////////////////////////////////////////////////////////////////
virtual void v_run();
virtual char const * v_type() const;
virtual std::string v_info() const;
-
+
int signal_;
Callback cb_;
siginfo_t siginfo_;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
struct FindNumericSignal {
bool operator()(SignalEvent const & a, int b) const
- { return a.signal_ < b; }
+ { return a.signal_ < b; }
bool operator()(int a, SignalEvent const & b) const
{ return a < b.signal_; }
};
bool empty() const;
struct DuplicateSignalRegistrationException : public Exception
- { DuplicateSignalRegistrationException()
+ { DuplicateSignalRegistrationException()
: Exception("duplicate signal registration") {} };
protected:
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////cc.p////////////////////////////////////////
namespace {
-
+
bool called = false;
void handler(siginfo_t const &)
{
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
cb_ = cb;
}
-prefix_ void senf::scheduler::TimerEvent::timeout(ClockService::clock_type timeout,
+prefix_ void senf::scheduler::TimerEvent::timeout(ClockService::clock_type timeout,
bool initiallyEnabled)
{
disable();
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
: public singleton<TimerDispatcher>
{
SENF_LOG_CLASS_AREA();
-
+
public:
using singleton<TimerDispatcher>::instance;
using singleton<TimerDispatcher>::alive;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
return (a<b ? b-a : a-b) < senf::ClockService::milliseconds(50);
}
-
+
bool called = false;
void handler()
{
senf::ClockService::clock_type t (senf::ClockService::now());
{
- senf::scheduler::TimerEvent timer ("testTimer", &handler,
+ senf::scheduler::TimerEvent timer ("testTimer", &handler,
t + senf::ClockService::milliseconds(500));
SENF_CHECK_NO_THROW( timer.disable() );
SENF_CHECK_NO_THROW( timer.enable() );
"jitterTest::tm2", boost::bind(&jitterCb, boost::ref(tm2)), randomDelay());
senf::scheduler::TimerEvent tm3 (
"jitterTest::tm3", boost::bind(&jitterCb, boost::ref(tm3)), randomDelay());
-
+
// enabled "Idle"-Event will degrade scheduling delay
//senf::scheduler::TimerEvent idle (
// "jitterTest::idle", boost::bind(&idleCb, boost::ref(idle)), senf::scheduler::now());
///////////////////////////////ct.p////////////////////////////////////////
template<typename IdType>
-prefix_ senf::scheduler::TimerEventProxy<IdType>::TimerEventProxy()
+prefix_ senf::scheduler::TimerEventProxy<IdType>::TimerEventProxy()
: entrySetById( entrySet.template get<Id>()),
entrySetByTimeout( entrySet.template get<Timeout> ()),
timer( "TimerEventProxy", membind(&TimerEventProxy<IdType>::timerEvent, this), 0, false)
{ }
template<typename IdType>
-prefix_ senf::scheduler::TimerEventProxy<IdType>::TimerEventProxy(std::string const & name, console::DirectoryNode & node)
+prefix_ senf::scheduler::TimerEventProxy<IdType>::TimerEventProxy(std::string const & name, console::DirectoryNode & node)
: entrySetById( entrySet.template get<Id>()),
entrySetByTimeout( entrySet.template get<Timeout> ()),
timer( "TimerEventProxy", membind(&TimerEventProxy<IdType>::timerEvent, this), 0, false)
host a big count of timers.
*/
template<typename IdType>
- class TimerEventProxy
+ class TimerEventProxy
{
public:
typedef boost::function<void(ClockService::clock_type, IdType const &)> Callback;
TimerEventProxy(std::string const & name, console::DirectoryNode & node);
/**< \brief Instantiate a TimerEventProxy and add the list
command to the give DirectoryNode */
-
+
void add(ClockService::clock_type timeout, IdType const & id, Callback cb);
///< Add new deadline timer
-
+
bool remove(IdType const & id); ///< Remove timer by given \a id.
-
+
std::vector<std::pair<ClockService::clock_type, IdType> > list() const;
///< Returns a vector of all active timers with timeout and id.
-
+
ClockService::clock_type timeout(IdType const & id) const;
///< Returns timeout for given id
- /**< if no timer for this id is registered \a 0 is returned. */
+ /**< if no timer for this id is registered \a 0 is returned. */
private:
#ifndef DOXYGEN
struct Entry {
boost::multi_index::indexed_by<
boost::multi_index::ordered_non_unique<
boost::multi_index::tag<Timeout>,
- boost::multi_index::member<Entry, ClockService::clock_type, &Entry::timeout>
+ boost::multi_index::member<Entry, ClockService::clock_type, &Entry::timeout>
>,
boost::multi_index::ordered_unique<
boost::multi_index::tag<Id>,
- boost::multi_index::member<Entry, IdType, &Entry::id>
+ boost::multi_index::member<Entry, IdType, &Entry::id>
>
>
> EntrySet_t;
EntrySet_t entrySet;
EntrySetById_t & entrySetById;
EntrySetByTimeout_t & entrySetByTimeout;
-
+
scheduler::TimerEvent timer;
void timerEvent(); // callback for the Scheduler timer event
BOOST_CHECK( timers.remove( 4));
BOOST_CHECK(! timers.remove( 4));
timers.add( t + senf::ClockService::milliseconds(700), 2, &handler);
-
+
BOOST_CHECK_EQUAL( timers.timeout(1), t + senf::ClockService::milliseconds(200));
BOOST_CHECK_EQUAL( timers.timeout(2), t + senf::ClockService::milliseconds(700));
BOOST_CHECK_EQUAL( timers.timeout(4), 0);
BOOST_CHECK( mask == 3);
}
-
+
senf::scheduler::TimerEventProxy<int> timers ("test", senf::console::ScopedDirectory<>());
}
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace scheduler {
namespace detail {
- class TimerSource
+ class TimerSource
: boost::noncopyable
{
public:
template <class Handle>
prefix_ senf::WriteHelper<Handle>::WriteHelper(Handle handle, std::string const & data,
Callback callback)
- : handle_(handle),
- fde_("WriteHelper", boost::bind(&WriteHelper::dispatchProcess, ptr(this), _1, _2),
+ : handle_(handle),
+ fde_("WriteHelper", boost::bind(&WriteHelper::dispatchProcess, ptr(this), _1, _2),
handle, scheduler::FdEvent::EV_WRITE),
data_(data), callback_(callback), offset_(data_.begin()), errno_(0)
{}
private:
WriteHelper(Handle handle, std::string const & data, Callback callback);
- static void dispatchProcess(ptr helper, Handle handle,
+ static void dispatchProcess(ptr helper, Handle handle,
senf::scheduler::FdEvent::Events event);
void process(Handle handle, senf::scheduler::FdEvent::Events event);
void done();
// $Id$
//
-// Copyright (C) 2007
+// Copyright (C) 2007
// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
// Stefan Bund <g0dil@berlios.de>
template <class Sequence>
prefix_ void senf::ClientSocketHandle<SPolicy>::read(Sequence & container, unsigned limit)
{
- if (limit == 0)
+ if (limit == 0)
limit = available();
container.resize(limit);
- container.erase(read( std::make_pair(container.begin(), container.end()) ),
+ container.erase(read( std::make_pair(container.begin(), container.end()) ),
container.end());
}
if (limit>0 && nread>limit)
nread = limit;
container.resize(nread);
- container.erase(readfrom( std::make_pair(container.begin(), container.end()), from ),
+ container.erase(readfrom( std::make_pair(container.begin(), container.end()), from ),
container.end());
}
# else
template <class OtherPolicy>
ClientSocketHandle<OtherPolicy> const & operator=(ClientSocketHandle<OtherPolicy> other);
-# endif
+# endif
///@}
///////////////////////////////////////////////////////////////////////////
the other end) and will block, if no data is available now. If you do not want to block,
you \e must make the socket non-blocking (using FileHandle::blocking()).
- \throws senf::SystemException
+ \throws senf::SystemException
This variant will read up to \c limit bytes from the
range. read returns a past-the-end iterator after the
last character read. This iterator will point to
somewhere within the input range.
- \param[in,out] range Range to store data in
+ \param[in,out] range Range to store data in
\returns past-the-end iterator pointer to after the
- last read character
+ last read character
\see \ref read() \n
<a href="http://www.boost.org/libs/range/index.html">Boost.Range</a> */
# endif
work, the container must be a model of 'Sequence' as
defined in the STL documentation
\param[out] container Container to write data to
- \param[in] limit Maximum number of characters to read
+ \param[in] limit Maximum number of characters to read
\see \ref read() */
char * read (char * start, char * end);
///< Read data into memory area
range. read returns a past-the-end iterator after the
last character read. This iterator will point to
somewhere within the input range.
- \param[in,out] range Range to store data in
+ \param[in,out] range Range to store data in
\param[out] from peers address from which the data was
received
\returns past-the-end iterator pointer to after the
- last read character
+ last read character
\see \ref readfrom() \n
<a href="http://www.boost.org/libs/range/index.html">Boost.Range</a> */
template <class ForwardWritableRange>
work, the container must be a model of 'Sequence' as
defined in the STL documentation
\param[out] container Container to write data to
- \param[in] limit Maximum number of characters to read
+ \param[in] limit Maximum number of characters to read
\param[out] from peers address from which the data was
received
\see \ref readfrom() */
range, otherwise a temporary storage area is used.
*/
template <class Handle, class ForwardWritableRange, bool IsContiguous>
- struct ReadRange
+ struct ReadRange
{
static typename boost::range_iterator<ForwardWritableRange>::type
read(Handle & handle, ForwardWritableRange & range);
{
static typename boost::range_const_iterator<ForwardReadableRange>::type
write(Handle & handle, ForwardReadableRange & range);
-
+
static typename boost::range_const_iterator<ForwardReadableRange>::type
writeto(Handle & handle, ForwardReadableRange & range,
typename Handle::Address const & addr);
{
static typename boost::range_const_iterator<ForwardReadableRange>::type
write(Handle & handle, ForwardReadableRange & range);
-
+
static typename boost::range_const_iterator<ForwardReadableRange>::type
writeto(Handle & handle, ForwardReadableRange & range,
typename Handle::Address const & addr);
prefix_ bool senf::FileBody::waitReadable(senf::ClockService::clock_type timeout)
const
{
- return pollCheck(fd(), true,
+ return pollCheck(fd(), true,
(timeout==-1?-1:senf::ClockService::in_milliseconds(timeout)) );
}
prefix_ bool senf::FileBody::waitWriteable(senf::ClockService::clock_type timeout)
const
{
- return pollCheck(fd(), false,
+ return pollCheck(fd(), false,
(timeout==-1?-1:senf::ClockService::in_milliseconds(timeout)) );
}
prefix_ bool senf::FileBody::waitOOBReadable(senf::ClockService::clock_type timeout)
const
{
- return pollCheck(fd(), true,
+ return pollCheck(fd(), true,
(timeout==-1?-1:senf::ClockService::in_milliseconds(timeout)), true);
}
*/
/** \defgroup handle_group The Handle Hierarchy
-
+
\diaimage FhHierarchy.dia
The senf::FileHandle class is the base of a hierarchy of socket handle classes (realized as
bool readable() const; ///< Check, whether a read on the handle would not block
///< (ignoring blocking state)
- bool waitReadable(senf::ClockService::clock_type timeout = -1) const;
+ bool waitReadable(senf::ClockService::clock_type timeout = -1) const;
///< Wait, until read on the handle would not block (ignoring
///< blocking state)
/**< \param[in] timeout max time to wait, default is to wait
- forever.
+ forever.
\returns \c true, if handle became readable or \c false on
timeout. */
bool writeable() const; ///< Check, whether a write on the handle would not block
///< Wait, until a write on the handle would not block
///< (ignoring blocking state)
/**< \param[in] timeout max time to wait, default is to wait
- forever.
+ forever.
\returns \c true, if handle became writable or \c false on
timeout. */
- bool oobReadable() const; ///< Check, whether a read of prioritized data on the handle
+ bool oobReadable() const; ///< Check, whether a read of prioritized data on the handle
///< would not block (ignoring blocking state)
- bool waitOOBReadable(senf::ClockService::clock_type timeout = -1) const;
+ bool waitOOBReadable(senf::ClockService::clock_type timeout = -1) const;
///< Wait, until read of prioritized data on the handle does
///< not block (ignoring blocking state)
/**< \param[in] timeout max time to wait, default is to wait
- forever.
+ forever.
\returns \c true, if handle became readable for
out-of-band data or \c false on timeout. */
\e must also derive from senf::pool_alloc_mixin
*/
class FileBody
- : public senf::intrusive_refcount,
+ : public senf::intrusive_refcount,
public senf::pool_alloc_mixin<FileBody>
{
public:
/** \mainpage The SENF Socket Library
The Socket library provides a high level and object oriented abstraction based on the BSD socket
- API (but not limited to it).
-
+ API (but not limited to it).
+
\autotoc
-
+
\section socket_intro Introduction
\seechapter \ref structure \n
\seechapter \ref usage
-
+
The socket library abstraction is based on several concepts:
\li The basic visible interface is a \link handle_group handle object\endlink
symbol). However, more generic kinds of handles can be defined for more generic functionality.
-
+
\section socket_policy The Policy interface
\seechapter \ref policy_group
provides. This offers highly efficient access to the most important socket functions (like
reading and writing). The policy interface however is a \e static, non-polymorphic interface.
-
+
\section socket_protocol The Protocol interface
\seechapter \ref protocol_group
-
+
The protocol interface provides further protocol dependent and (possibly) polymorphic access to
further socket funcitonality. On the other hand, this type of interface is not as flexible,
\section socket_addr Auxilliary Addressing classes
\seechapter \ref addr_group
-
+
To supplement the socket library, there are a multitude of addressing classes. These come in two
basic groups:
\li Protocol specific addresses (e.g. INet4Address, MACAddress)
Whereas the protocol specific addresses are custom value types which represent their
corresponding low-level address, the socket addresses are based on the corresponding \c sockaddr
- structures.
-
+ structures.
+
\section socket_further Going further
\seechapter \ref extend \n
\seechapter \ref implementation
reducing the policy interface to a minimal sensible subset of the complete API.
\section over_policy The Policy Interface
-
+
The policy of a Socket consists of several parts, called <em>policy axis</em>. Each axis
corresponds to one specific interface aspect of the Socket. The exact meaning of the policy axis
are defined elsewhere (see \ref policy_group). The Protocol will always provide a complete set
defined match those defined in that Socket's protocol. Using such a generic handle decouples the
implementation parts using this handle from the other socket aspects (e.g. you may define a
generic socket handle for TCP based communication leaving the addressingPolicy undefined which
- makes your code independent of the type of addressing, IPv4 or IPv6).
+ makes your code independent of the type of addressing, IPv4 or IPv6).
This can be described as generalized compile-time polymorphism: A base class reference to some
derived class will only give access to a reduced interface (the base class interface) of a
To make your code more flexible, you should not pass around your socket in this form. Most of
your code will be using only a small subset of the ProtocolClientSocketHandle or
ProtocolServerSocketHandle API.
-
+
If instead of using the fully specified handle type you use a more incomplete type, you allow
your code to be used with all sockets which fulfill the minimal requirements of your code. These
types are based on the ClientSocketHandle and ServerSocketHandle templates which implement the
void interfaceName(const std::string &newName);
///< set interface name
/**< Changes the name of the interface.
- Note, that setting the name is a privileged operation.
- It is only allowed when the interface is not up. If
- the interface is up, this call will cause an
+ Note, that setting the name is a privileged operation.
+ It is only allowed when the interface is not up. If
+ the interface is up, this call will cause an
SystemException to be thrown. */
int mtu() const; ///< return the Maximum Transmission Unit
void mtu(int new_mtu); ///< set the Maximum Transmission Unit
/**< Set the MTU (Maximum Transfer Unit) of the device.
Note, that this is a privileged operation.
- Setting the MTU to too small values may cause kernel
+ Setting the MTU to too small values may cause kernel
crashes. */
bool promisc() const; ///< return \c true if interface is in promiscuous mode
int index = ctrl.interfaceIndex();
BOOST_CHECK_EQUAL( index, senf::NetdeviceController(index).interfaceIndex() );
BOOST_CHECK_EQUAL( index, if_nametoindex( ifname.c_str()) );
-
+
BOOST_CHECK_THROW( senf::NetdeviceController("invalid_interfacename"), senf::SystemException );
-
+
int oldMTU (0);
SENF_CHECK_NO_THROW( oldMTU = ctrl.mtu());
-
+
bool promisc (false);
SENF_CHECK_NO_THROW( promisc = ctrl.promisc());
-
+
BOOST_CHECK( ctrl.isUp());
if (getuid() != 0) {
BOOST_CHECK_EQUAL( ctrl.mtu(), oldMTU-16);
SENF_CHECK_NO_THROW( ctrl.mtu(oldMTU));
BOOST_CHECK_EQUAL( ctrl.mtu(), oldMTU);
-
+
SENF_CHECK_NO_THROW( ctrl.promisc( !promisc));
BOOST_CHECK_EQUAL( ctrl.promisc(), !promisc);
SENF_CHECK_NO_THROW( ctrl.promisc( promisc));
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
/** \brief Resolver failure */
struct UnknownHostnameException : public AddressException
- {
- UnknownHostnameException() : AddressException("failed to resolve hostname") {}
+ {
+ UnknownHostnameException() : AddressException("failed to resolve hostname") {}
UnknownHostnameException(const std::string &hostname)
: AddressException("Failed to resolve hostname (\"" + hostname + "\")") {}
};
-}
+}
///////////////////////////////hh.e////////////////////////////////////////
//#include "AddressExceptions.cci"
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace senf {
/** \brief Socket addressing, BSD style
-
+
BSDSocketAddress is the base class of all BSD \c sockaddr based addressing classes. The \c
sockaddr addressing interface is split into several parts
}
}
\endcode
-
+
All these classes provide a generic \c sockaddr API to interface with legacy \c sockaddr
based code (e.g. the BSD socket API). In this base-class, this interface is read-only, the
derived classes however provide a read-write interface.
/** \brief Output generic socket address
This stream operator will output a generic BSDSocketAddress in a family depending format.
-
+
\related BSDSocketAddress
*/
std::ostream & operator<<(std::ostream & os, BSDSocketAddress const & addr);
While BSDSocketAddress provides read-only generic \c sockaddr access,
GenericBSDSocketAddress allows to store (write) arbitrary socket addresses. (It is
- internally based on \c sockaddr_storage).
+ internally based on \c sockaddr_storage).
To access the stored address, use sockaddr_cast to cast the GenericBSDSocketAddress to the
correct family specific address class.
GenericBSDSocketAddress(const GenericBSDSocketAddress& other);
GenericBSDSocketAddress& operator=(const GenericBSDSocketAddress& other);
-
+
///@}
///////////////////////////////////////////////////////////////////////////
///\name Generic sockaddr interface
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
the network (e.g. via ICMP). */
unsigned rcvbuf() const; ///< Check receive buffer size
- /**< \returns size of receive buffer in bytes
+ /**< \returns size of receive buffer in bytes
\internal Linux doubles the buffer size internally when
changing it to cater for additional space needed by
the linux kernel. This call will therefore return
/**< \param[in] size new receive buffer size */
unsigned sndbuf() const; ///< Check send buffer size
- /**< \returns size of send buffer in bytes
+ /**< \returns size of send buffer in bytes
\internal Linux doubles the buffer size internally when
changing it to cater for additional space needed by
the linux kernel. This call will therefore return
only half the value reported by the kernel. */
void sndbuf(unsigned size) const; ///< Change size of send buffer
/**< \param[in] size new send buffer size */
-
+
};
/** \brief Protocol facet providing basic connection oriented BSD socket functions
prefix_ senf::DVBConfigParser::DVBParams::DVBParams()
{
-
- boost::assign::insert(inversion)
+
+ boost::assign::insert(inversion)
( "INVERSION_OFF", INVERSION_OFF )
- ( "INVERSION_ON", INVERSION_ON )
+ ( "INVERSION_ON", INVERSION_ON )
( "INVERSION_AUTO", INVERSION_AUTO );
- boost::assign::insert(bandwidth)
+ boost::assign::insert(bandwidth)
( "BANDWIDTH_6_MHZ", BANDWIDTH_6_MHZ)
( "BANDWIDTH_7_MHZ", BANDWIDTH_7_MHZ)
( "BANDWIDTH_8_MHZ", BANDWIDTH_8_MHZ);
- boost::assign::insert(code_rate)
+ boost::assign::insert(code_rate)
( "FEC_1_2", FEC_1_2)
( "FEC_2_3", FEC_2_3)
( "FEC_3_4", FEC_3_4)
( "FEC_8_9", FEC_8_9)
( "FEC_AUTO", FEC_AUTO)
( "FEC_NONE", FEC_NONE);
- boost::assign::insert(guard_interval)
+ boost::assign::insert(guard_interval)
( "GUARD_INTERVAL_1_16", GUARD_INTERVAL_1_16)
( "GUARD_INTERVAL_1_32", GUARD_INTERVAL_1_32)
( "GUARD_INTERVAL_1_4", GUARD_INTERVAL_1_4)
( "GUARD_INTERVAL_1_8", GUARD_INTERVAL_1_8);
- boost::assign::insert(hierarchy)
+ boost::assign::insert(hierarchy)
( "HIERARCHY_1", HIERARCHY_1)
( "HIERARCHY_2", HIERARCHY_2)
( "HIERARCHY_4", HIERARCHY_4)
( "HIERARCHY_NONE", HIERARCHY_NONE);
- boost::assign::insert(modulation)
+ boost::assign::insert(modulation)
( "QPSK", QPSK)
( "QAM_128", QAM_128)
( "QAM_16", QAM_16)
( "QAM_256", QAM_256)
( "QAM_32", QAM_32)
( "QAM_64", QAM_64);
- boost::assign::insert(transmit_mode)
+ boost::assign::insert(transmit_mode)
( "TRANSMISSION_MODE_2K", TRANSMISSION_MODE_2K)
( "TRANSMISSION_MODE_8K", TRANSMISSION_MODE_8K);
}
-senf::DVBConfigParser::DVBConfigParser(fe_type_t type_, const string & configFilePath_) :
- type(type_),
+senf::DVBConfigParser::DVBConfigParser(fe_type_t type_, const string & configFilePath_) :
+ type(type_),
configFile()
{
initConfigFile(configFilePath_);
string configLine;
size_t pos;
transform(channel.begin(), channel.end(), channel.begin(), ::toupper);
-
+
configFile.open( configFilePath.c_str(), ios_base::in);
if (configFile.bad())
SENF_THROW_SYSTEM_EXCEPTION("Could not read channels file: ") << configFilePath << ".";
-
+
while (configFile.good()) {
getline( configFile, configLine );
SENF_LOG((senf::log::NOTICE) ("configLine: " << configLine ));
transform(configLine.begin(), configLine.end(), configLine.begin(), ::toupper);
pos = configLine.find(channel);
-
- if (pos != string::npos && pos == 0) { // only first matching number should be interpreted as channel number
+
+ if (pos != string::npos && pos == 0) { // only first matching number should be interpreted as channel number
configFile.close();
return configLine; // Line found!
}
int number;
enum { p_Frequency=1, p_Inversion, p_Bandwidth, p_hp_code_rate, p_lp_code_rate, p_Mudualtion, p_Transmission, p_guard, p_hierarchy};
vector<string> words( tokens.begin(), tokens.end() );
-
+
::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters));
-
+
/*if (words.size() < 10)
SENF_THROW_SYSTEM_EXCEPTION("Too few arguments! There must be at least 10, but there are only: ") << words.size();*/
-
+
isst.str(words[p_Frequency]);
isst >> number;
if (isst.fail())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse frequency");
frontend.frequency = number;
-
+
if (params.inversion.find(words[p_Inversion]) == params.inversion.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse inversion");
frontend.inversion = params.inversion.find(words[p_Inversion])->second;
-
+
if (params.bandwidth.find(words[p_Bandwidth]) == params.bandwidth.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse bandwidth");
frontend.u.ofdm.bandwidth = params.bandwidth.find(words[p_Bandwidth])->second;
-
+
if (params.code_rate.find(words[p_hp_code_rate]) == params.code_rate.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse high priority stream code rate");
frontend.u.ofdm.code_rate_HP = params.code_rate.find(words[p_hp_code_rate])->second;
-
+
if (params.code_rate.find(words[p_lp_code_rate]) == params.code_rate.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse low priority stream code rate");
frontend.u.ofdm.code_rate_LP = params.code_rate.find(words[p_lp_code_rate])->second;
-
+
if (params.modulation.find(words[p_Mudualtion]) == params.modulation.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse modulation");
frontend.u.ofdm.constellation = params.modulation.find(words[p_Mudualtion])->second;
-
+
if (params.transmit_mode.find(words[p_Transmission]) == params.transmit_mode.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse transmission mode");
frontend.u.ofdm.transmission_mode = params.transmit_mode.find(words[p_Transmission])->second;
-
+
if (params.guard_interval.find(words[p_guard]) == params.guard_interval.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse guard interval");
- frontend.u.ofdm.guard_interval = params.guard_interval.find(words[p_guard])->second;
-
+ frontend.u.ofdm.guard_interval = params.guard_interval.find(words[p_guard])->second;
+
if (params.hierarchy.find(words[p_hierarchy]) == params.hierarchy.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse hierarchy");
frontend.u.ofdm.hierarchy_information = params.hierarchy.find(words[p_hierarchy])->second;
-
+
return frontend;
}
int number;
enum { p_Frequency=1, p_Inversion, p_Symbole, p_code_rate};
vector<string> words( tokens.begin(), tokens.end() ) ;
-
+
::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters));
-
+
if (words.size() < 5)
SENF_THROW_SYSTEM_EXCEPTION("Too few arguments! There must be at least 5, but there are only: ") << words.size();
-
+
isst.str(words[p_Frequency]);
isst >> number;
if (isst.fail())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse frequency");
frontend.frequency = number;
-
+
if (params.inversion.find(words[p_Inversion]) == params.inversion.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse inversion");
frontend.inversion = params.inversion.find(words[p_Inversion])->second;
-
+
isst.str(words[p_Symbole]);
isst >> number;
if (isst.fail())
if (params.code_rate.find(words[p_code_rate]) == params.code_rate.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse code rate");
frontend.u.qpsk.fec_inner = params.code_rate.find(words[p_code_rate])->second;
-
+
return frontend;
}
istringstream isst;
int number;
enum { p_Frequency=1, p_Inversion, p_Symbole, p_code_rate, p_modulation};
- vector<string> words( ++tokens.begin(), tokens.end() ) ;
-
+ vector<string> words( ++tokens.begin(), tokens.end() ) ;
+
::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters));
-
+
if (words.size() < 6)
SENF_THROW_SYSTEM_EXCEPTION("Too few arguments! There must be at least 6, but there are only: ") << words.size();
-
+
isst.str(words[p_Frequency]);
isst >> number;
if (isst.fail())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse frequency");
frontend.frequency = number;
-
+
if (params.inversion.find(words[p_Inversion]) == params.inversion.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse inversion");
frontend.inversion = params.inversion.find(words[p_Inversion])->second;
-
+
isst.str(words[p_Symbole]);
isst >> number;
if (isst.fail())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse symbole rate");
frontend.u.qam.symbol_rate = number;
-
+
if (params.code_rate.find(words[p_code_rate]) == params.code_rate.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse code rate");
frontend.u.qam.fec_inner = params.code_rate.find(words[p_code_rate])->second;
-
+
if (params.modulation.find(words[p_modulation]) == params.modulation.end())
SENF_THROW_SYSTEM_EXCEPTION("Cant parse modulation");
frontend.u.qam.modulation = params.modulation.find(words[p_modulation])->second;
-
+
return frontend;
}
namespace senf {
- class DVBConfigParser
+ class DVBConfigParser
{
struct DVBParams {
std::map<std::string, fe_spectral_inversion_t> inversion;
std::map<std::string, fe_hierarchy_t> hierarchy;
std::map<std::string, fe_modulation_t> modulation;
std::map<std::string, fe_transmit_mode_t> transmit_mode;
- DVBParams();
+ DVBParams();
};
static const DVBParams params;
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
-
+
public:
DVBConfigParser(fe_type_t type_, const std::string & configFilePath = "");
~DVBConfigParser();
std::string getConfigLine(std::string channel);
-
+
dvb_frontend_parameters getFrontendParam(std::string configLine);
private:
};
}
-#endif
+#endif
sec_filter.filter.mask[0] = mask;
sec_filter.filter.mode[0] = mode;
sec_filter.flags = flags;
-
+
if (::ioctl(fd(), DMX_SET_FILTER, &sec_filter) < 0)
SENF_THROW_SYSTEM_EXCEPTION("Could not set section filter of DVB adapter.");
}
prefix_ void senf::DVBDemuxPESSocketProtocol::setPESFilter(unsigned short int pid, dmx_input_t input, dmx_output_t output, dmx_pes_type_t pesType, unsigned int flags)
const
{
-
+
struct dmx_pes_filter_params pes_filter;
::memset(&pes_filter, 0, sizeof(struct dmx_pes_filter_params));
pes_filter.pid = pid;
pes_filter.output = output;
pes_filter.pes_type = pesType;
pes_filter.flags = flags;
-
+
if (::ioctl(fd(), DMX_SET_PES_FILTER, &pes_filter) < 0)
SENF_THROW_SYSTEM_EXCEPTION("Could not set PES filter of DVB adapter.");
}
NotWriteablePolicy
>::policy DVBDemux_Policy; ///< Socket Policy for xxxx
- /** \brief Baseclass of various DVBProtocolWrappers which are defined in DVBProtocolWrapper.hh
+ /** \brief Baseclass of various DVBProtocolWrappers which are defined in DVBProtocolWrapper.hh
*/
class DVBProtocolWrapper :public boost::enable_shared_from_this<DVBProtocolWrapper> {
public:
DVBProtocolWrapper() {}
virtual ~DVBProtocolWrapper() {}
};
- /** \brief Baseclass for DVBSocketProtocols which want use Wrappers for console.
+ /** \brief Baseclass for DVBSocketProtocols which want use Wrappers for console.
*/
class DVBSocketProtocol : public virtual SocketProtocol {
private:
public:
DVBSocketProtocol() {}
~DVBSocketProtocol() {}
-
- void addWrapper(boost::shared_ptr<DVBProtocolWrapper> wrap)/**< Binds a wrapper to a DVBProtocol,
- so if it is closed the functionality of the wrapper is automatically removed from console.*/
+
+ void addWrapper(boost::shared_ptr<DVBProtocolWrapper> wrap)/**< Binds a wrapper to a DVBProtocol,
+ so if it is closed the functionality of the wrapper is automatically removed from console.*/
{
wrap_ = wrap;
}
}
};
-
-
+
+
class DVBDemuxSectionSocketProtocol
: public ConcreteSocketProtocol<DVBDemux_Policy, DVBDemuxSectionSocketProtocol>,
- public DVBDemuxSocketProtocol,
+ public DVBDemuxSocketProtocol,
public DVBSocketProtocol
{
-
+
public:
///////////////////////////////////////////////////////////////////////////
// internal interface
///@}
///\name Abstract Interface Implementation
///@{
-
+
unsigned available() const;
///@}
-
- void setSectionFilter(unsigned short int pid,
+
+ void setSectionFilter(unsigned short int pid,
unsigned char filter= 0x3e,
- unsigned int flags= DMX_IMMEDIATE_START | DMX_CHECK_CRC,
- unsigned char mask = 0xff,
+ unsigned int flags= DMX_IMMEDIATE_START | DMX_CHECK_CRC,
+ unsigned char mask = 0xff,
unsigned char mode =0x00,
unsigned int timeout =0x00) const;
-
+
};
typedef ProtocolClientSocketHandle<DVBDemuxSectionSocketProtocol> DVBDemuxSectionHandle;
-
+
// ----------------------------------------------------------------
-
+
/** \brief xxx
*/
class DVBDemuxPESSocketProtocol
///@}
///\name Abstract Interface Implementation
///@{
-
+
unsigned available() const;
///@}
-
- void setPESFilter(unsigned short int pid, dmx_input_t input, dmx_output_t output, dmx_pes_type_t pesType, unsigned int flags)const;
+
+ void setPESFilter(unsigned short int pid, dmx_input_t input, dmx_output_t output, dmx_pes_type_t pesType, unsigned int flags)const;
};
typedef ProtocolClientSocketHandle<DVBDemuxPESSocketProtocol> DVBDemuxPESHandle;
-
+
// ----------------------------------------------------------------
-
-
+
+
/** \brief xxx
*/
class DVBDvrSocketProtocol
///@}
///\name Abstract Interface Implementation
///@{
-
+
unsigned available() const;
///@}
typedef ProtocolClientSocketHandle<DVBDvrSocketProtocol> DVBDvrHandle;
///@}
-
+
}
///////////////////////////////hh.e////////////////////////////////////////
#ifndef HH_SENF_Socket_Protocols_DVB_DVBDemuxSocketProtocol_
#define HH_SENF_Socket_Protocols_DVB_DVBDemuxSocketProtocol_ 1
-#include <linux/dvb/dmx.h>
+#include <linux/dvb/dmx.h>
// Custom includes
#include <senf/Socket/SocketProtocol.hh>
: public virtual SocketProtocol
{
public:
- void setBufferSize(unsigned long size) const;
+ void setBufferSize(unsigned long size) const;
///< set the size of the circular buffer used for filtered data.
/**< The default size is two maximum sized sections, i.e. if this
function is not called a buffer size of 2 * 4096 bytes will
\param[in] size Size of circular buffer. */
void startFiltering() const;
void stopFiltering() const;
-
+
///\name Abstract Interface Implementation
///@{
-
+
bool eof() const;
///@}
}
prefix_ void senf::DVBFrontendSocketProtocol::tune(const struct dvb_frontend_parameters & frontend)
- const
+ const
{
// tuning
if (::ioctl(fd(), FE_SET_FRONTEND, &frontend) )
SENF_THROW_SYSTEM_EXCEPTION("") << "ioctl FE_SET_FRONTEND failed. Socket should initialized with r/w permissions.";;
}
-prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_T(unsigned int frequency,
+prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_T(unsigned int frequency,
fe_spectral_inversion_t inversion,
- fe_bandwidth_t bandwidth,
+ fe_bandwidth_t bandwidth,
fe_code_rate_t code_rate_HP, /* high priority stream code rate */
fe_code_rate_t code_rate_LP, /* low priority stream code rate */
fe_modulation_t constellation, /* modulation type */
- fe_transmit_mode_t transmission_mode,
+ fe_transmit_mode_t transmission_mode,
fe_guard_interval_t guard_interval,
fe_hierarchy_t hierarchy_information
)
{
struct dvb_ofdm_parameters ofdm; /* DVB-T Parameters */
struct dvb_frontend_parameters frontend;
-
+
::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters));
::memset(&ofdm, 0, sizeof(struct dvb_ofdm_parameters));
-
+
ofdm.bandwidth = bandwidth;
ofdm.code_rate_HP = code_rate_HP;
ofdm.code_rate_LP = code_rate_LP;
- ofdm.constellation = constellation;
+ ofdm.constellation = constellation;
ofdm.guard_interval = guard_interval;
ofdm.hierarchy_information = hierarchy_information;
-
+
frontend.frequency = frequency;
frontend.inversion = inversion;
frontend.u.ofdm = ofdm;
-
+
tune(frontend);
-
+
}
-prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_S(unsigned int frequency,
- fe_spectral_inversion_t inversion,
+prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_S(unsigned int frequency,
+ fe_spectral_inversion_t inversion,
unsigned int symbole_rate, /* symbol rate in Symbols per second */
fe_code_rate_t fec_inner /* forward error correction (see above) */
)
{
struct dvb_qpsk_parameters qpsk; /* DVB-S Parameters*/
struct dvb_frontend_parameters frontend;
-
+
::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters));
::memset(&qpsk, 0, sizeof(struct dvb_qpsk_parameters));
-
+
qpsk.symbol_rate = symbole_rate;
qpsk.fec_inner = fec_inner;
-
+
frontend.frequency = frequency;
frontend.inversion = inversion;
frontend.u.qpsk = qpsk;
-
+
tune(frontend);
}
-prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_C(unsigned int frequency,
+prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_C(unsigned int frequency,
fe_spectral_inversion_t inversion,
unsigned int symbol_rate,
fe_code_rate_t fec_inner,
{
struct dvb_qam_parameters qam; /* DVB-C Parameters*/
struct dvb_frontend_parameters frontend;
-
+
::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters));
::memset(&qam, 0, sizeof(struct dvb_qam_parameters));
-
+
qam.symbol_rate = symbol_rate;
qam.fec_inner = fec_inner;
qam.modulation = modulation;
-
-
+
+
frontend.frequency = frequency;
frontend.inversion = inversion;
frontend.u.qam = qam;
-
+
tune(frontend);
}
-prefix_ void senf::DVBFrontendSocketProtocol::setNonBlock(bool on)
+prefix_ void senf::DVBFrontendSocketProtocol::setNonBlock(bool on)
const
{
if (on)
{
struct dvb_frontend_info info;
::memset(&info, 0, sizeof(struct dvb_frontend_info));
-
+
if (::ioctl(fd(), FE_GET_INFO, &info)) {
SENF_THROW_SYSTEM_EXCEPTION("") << "Could not read on fildescriptor.";
}
prefix_ dvb_frontend_parameters senf::DVBFrontendSocketProtocol::getFrontendParam() const {
struct dvb_frontend_parameters frontend_;
-
+
::memset(&frontend_, 0, sizeof(struct dvb_frontend_parameters));
-
+
if (::ioctl(fd(), FE_GET_FRONTEND, &frontend_)) {
switch(errno) {
case EBADF:
prefix_ dvb_frontend_event senf::DVBFrontendSocketProtocol::getEvent() const{
struct dvb_frontend_event ev ;
-
+
::memset(&ev, 0, sizeof(struct dvb_frontend_event));
-
+
if (::ioctl(fd(), FE_GET_EVENT, &ev)) {
switch(errno) {
case EBADF:
}
prefix_ int16_t senf::DVBFrontendSocketProtocol::signalNoiseRatio()
- const
+ const
{
int16_t snr;
if (::ioctl(fd(), FE_READ_SNR, &snr) < 0)
NotReadablePolicy,
NotWriteablePolicy
> ::policy DVBFrontend_Policy; ///< Socket Policy for DVBFrontendSocketProtocol
-
+
/** \brief SocketProtocol for the dvb frontend device
The DVB frontend device controls the tuner and DVB demodulator hardware.
ATTENTION!
Some calls are not supported by real life drivers, known issues:
-
+
Cinergy T� getParameter is not supported
Cinergy T� in getEvent fe_status_t will be set but dvb_frontend_parameters will be stay untouched
Cinergy DT XS bitErrorRate is not supported
-
+
This dues to the lack of driver implementation. There could be restrictions also for other DVB devices!
*/
-
+
class DVBFrontendSocketProtocol
: public ConcreteSocketProtocol<DVBFrontend_Policy, DVBFrontendSocketProtocol>
{
- private:
+ private:
void tune(const struct dvb_frontend_parameters & frontend) const;
public:
-
-
+
+
///////////////////////////////////////////////////////////////////////////
// internal interface
///@}
void setNonBlock(bool on = true) const;
-
+
void tuneDVB_S(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, fe_code_rate_t code_rate) const;
///< Tunes a DVB-S device
/**< Tunes a DVB-S device. Needs full configuration */
- void tuneDVB_T(unsigned int frequency,
+ void tuneDVB_T(unsigned int frequency,
fe_spectral_inversion_t inversion,
- fe_bandwidth_t bandwidth,
+ fe_bandwidth_t bandwidth,
fe_code_rate_t code_rate_HP, /* high priority stream code rate */
fe_code_rate_t code_rate_LP, /* low priority stream code rate */
fe_modulation_t constellation, /* modulation type (see above) */
- fe_transmit_mode_t transmission_mode,
+ fe_transmit_mode_t transmission_mode,
fe_guard_interval_t guard_interval,
fe_hierarchy_t hierarchy_information
) const; ///< Tunes a DVB-T device
/**< Tunes a DVB-T device. Needs full configuration */
- void tuneDVB_C(unsigned int frequency,
+ void tuneDVB_C(unsigned int frequency,
fe_spectral_inversion_t inversion,
unsigned int symbol_rate,
fe_code_rate_t fec_inner,
fe_modulation_t modulation
- ) const;
+ ) const;
///< Tunes a DVB-C device
/**< Tunes a DVB-C device. Needs full configuration */
dvb_frontend_info getInfo() const; ///< Returns information struct.
- /**< Returns information struct, which contains information
+ /**< Returns information struct, which contains information
about the device which is associated with the current frontend.*/
struct dvb_frontend_parameters getFrontendParam() const; ///< Returns dvb_frontend_parameters struct.
- /**< Returns dvb_frontend_parameters struct, which contains the actual
+ /**< Returns dvb_frontend_parameters struct, which contains the actual
configuration of the device.*/
///\name Abstract Interface Implementation
///@{
-
+
dvb_frontend_event getEvent() const;
-
+
unsigned available() const; ///< Returns always <tt>0</tt>
/**< Returns always <tt>0</tt>, since the DVB frontend
/**< Returns the bit error rate for the signal currently
received/demodulated by the front-end. For this method,
read-only access to the device is sufficient. */
- uint32_t uncorrectedBlocks() const; ///< Returns the number of uncorrected blocks
- /**< Returns the number of uncorrected blocks
+ uint32_t uncorrectedBlocks() const; ///< Returns the number of uncorrected blocks
+ /**< Returns the number of uncorrected blocks
* detected by the device driver during its lifetime.
- * For meaningful measurements, the increment in block
- * count during a specific time interval should be calculated.
+ * For meaningful measurements, the increment in block
+ * count during a specific time interval should be calculated.
* For this command, read-only access to the device is sufficient.
- * Note that the counter will wrap to zero after its maximum count
+ * Note that the counter will wrap to zero after its maximum count
* has been reached.*/
-
+
fe_status_t status() const; ///< This ioctl call returns status information about the front-end.
- /**< This ioctl call returns status information about the
- * front-end. This call only requires read-only access
+ /**< This ioctl call returns status information about the
+ * front-end. This call only requires read-only access
* to the device.*/
-
+
};
typedef ProtocolClientSocketHandle<DVBFrontendSocketProtocol> DVBFrontendHandle;
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-prefix_ senf::DVBSectionProtocolWrapper::DVBSectionProtocolWrapper(senf::DVBDemuxSectionHandle sh)
+prefix_ senf::DVBSectionProtocolWrapper::DVBSectionProtocolWrapper(senf::DVBDemuxSectionHandle sh)
: protocol(sh.protocol()), dir(this)
{
namespace kw = senf::console::kw;
namespace fty = senf::console::factory;
dir.add("buffersize", fty::Command(&DVBSectionProtocolWrapper::setBufferSize, this)
- .doc("Set the size of the circular buffer used for filtered data.")
- .arg("size", "in byte") );
+ .doc("Set the size of the circular buffer used for filtered data.")
+ .arg("size", "in byte") );
dir.add("start", fty::Command(&DVBSectionProtocolWrapper::startFiltering, this)
- .doc("Starts filtering") );
+ .doc("Starts filtering") );
dir.add("stop", fty::Command(&DVBSectionProtocolWrapper::setBufferSize, this)
- .doc("Stops filtering") );
-
- dir.add("filter",
- fty::Command<void (unsigned short int,
- unsigned,
- senf::console::FlagCollection<Flags>,
- unsigned,
- unsigned,
- unsigned)
- >(&DVBSectionProtocolWrapper::setSectionFilter, this)
- .arg("pid", "pid to filter")
- .arg("filter", "filter",
- kw::default_value = 62,
- kw::default_doc = "0x3e")
- .arg("flags", "or-able: CHECK_CRC, ONESHOT, IMMEDIATE_START, KERNEL_CLIENT",
- kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC,
- kw::default_doc = "(IMMEDIATE_START CHECK_CRC)")
- .arg("mask", "mask",
- kw::default_value = 0xff,
- kw::default_doc = "0xff")
- .arg("mode", "mode",
- kw::default_value = 0,
- kw::default_doc = "0x00")
- .arg("timeout", "timeout",
- kw::default_value = 0,
- kw::default_doc = "0x00")
- .doc("Sets parameters for section filter.") );
+ .doc("Stops filtering") );
+
+ dir.add("filter",
+ fty::Command<void (unsigned short int,
+ unsigned,
+ senf::console::FlagCollection<Flags>,
+ unsigned,
+ unsigned,
+ unsigned)
+ >(&DVBSectionProtocolWrapper::setSectionFilter, this)
+ .arg("pid", "pid to filter")
+ .arg("filter", "filter",
+ kw::default_value = 62,
+ kw::default_doc = "0x3e")
+ .arg("flags", "or-able: CHECK_CRC, ONESHOT, IMMEDIATE_START, KERNEL_CLIENT",
+ kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC,
+ kw::default_doc = "(IMMEDIATE_START CHECK_CRC)")
+ .arg("mask", "mask",
+ kw::default_value = 0xff,
+ kw::default_doc = "0xff")
+ .arg("mode", "mode",
+ kw::default_value = 0,
+ kw::default_doc = "0x00")
+ .arg("timeout", "timeout",
+ kw::default_value = 0,
+ kw::default_doc = "0x00")
+ .doc("Sets parameters for section filter.") );
dir.add("stop", fty::Command(&DVBSectionProtocolWrapper::setBufferSize, this)
- .doc("Stops filtering") );
+ .doc("Stops filtering") );
}
-prefix_ senf::DVBPESProtocolWrapper::DVBPESProtocolWrapper(senf::DVBDemuxPESHandle sh)
- : protocol(sh.protocol()), dir(this)
+prefix_ senf::DVBPESProtocolWrapper::DVBPESProtocolWrapper(senf::DVBDemuxPESHandle sh)
+ : protocol(sh.protocol()), dir(this)
{
namespace kw = senf::console::kw;
namespace fty = senf::console::factory;
- dir.add("filter",
- fty::Command<void (unsigned short int,
- dmx_input_t,
- dmx_output_t,
- dmx_pes_type_t,
- senf::console::FlagCollection<Flags>)
- >(&DVBPESProtocolWrapper::setPESFilter, this)
- .arg("pid", "pid to filter")
- .arg("input", "input-filter: DMX_IN_FRONTEND DMX_IN_DVR ")
- .arg("output", "output-filter: DMX_OUT_DECODER DMX_OUT_TAP DMX_OUT_TS_TAP ")
- .arg("pesType", "PES type: DMX_PES_AUDIO[0-3] DMX_PES_VIDEO[0-3] "
- "DMX_PES_TELETEXT[0-3], DMX_PES_SUBTITLE[0-3], DMX_PES_PCR[0-3], "
- "DMX_PES_OTHER")
- .arg("flags", "or-able: CHECK_CRC, ONESHOT, IMMEDIATE_START, KERNEL_CLIENT",
- kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC,
- kw::default_doc = "(IMMEDIATE_START CHECK_CRC)")
- .doc("Sets parameters for PES filter.") );
-
+ dir.add("filter",
+ fty::Command<void (unsigned short int,
+ dmx_input_t,
+ dmx_output_t,
+ dmx_pes_type_t,
+ senf::console::FlagCollection<Flags>)
+ >(&DVBPESProtocolWrapper::setPESFilter, this)
+ .arg("pid", "pid to filter")
+ .arg("input", "input-filter: DMX_IN_FRONTEND DMX_IN_DVR ")
+ .arg("output", "output-filter: DMX_OUT_DECODER DMX_OUT_TAP DMX_OUT_TS_TAP ")
+ .arg("pesType", "PES type: DMX_PES_AUDIO[0-3] DMX_PES_VIDEO[0-3] "
+ "DMX_PES_TELETEXT[0-3], DMX_PES_SUBTITLE[0-3], DMX_PES_PCR[0-3], "
+ "DMX_PES_OTHER")
+ .arg("flags", "or-able: CHECK_CRC, ONESHOT, IMMEDIATE_START, KERNEL_CLIENT",
+ kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC,
+ kw::default_doc = "(IMMEDIATE_START CHECK_CRC)")
+ .doc("Sets parameters for PES filter.") );
+
dir.add("start", fty::Command(&DVBPESProtocolWrapper::startFiltering, this)
- .doc("Starts filtering") );
+ .doc("Starts filtering") );
dir.add("stop", fty::Command(&DVBPESProtocolWrapper::stopFiltering, this)
- .doc("Stops filtering") );
+ .doc("Stops filtering") );
}
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// comment-column: 40
+// End:
// Custom includes
-#define prefix_ inline
+#define prefix_ inline
///////////////////////////////cci.p////////////////////////////////////////
prefix_ void senf::DVBSectionProtocolWrapper::setSectionFilter(
- unsigned short int pid, u_int8_t filter, unsigned int flags, u_int8_t mask,
- u_int8_t mode, unsigned int timeout)
+ unsigned short int pid, u_int8_t filter, unsigned int flags, u_int8_t mask,
+ u_int8_t mode, unsigned int timeout)
{
protocol.setSectionFilter(pid, timeout, flags, filter, mask, mode);
}
prefix_ void senf::DVBPESProtocolWrapper::setPESFilter(unsigned short int pid, dmx_input_t input,
- dmx_output_t output, dmx_pes_type_t pesType, unsigned int flags)
+ dmx_output_t output, dmx_pes_type_t pesType, unsigned int flags)
{
protocol.setPESFilter(pid, input, output, pesType, flags);
}
/** \brief Helperclass for configuration and controlling DVB protocol handles.
*/
- class DVBSectionProtocolWrapper : public DVBProtocolWrapper
+ class DVBSectionProtocolWrapper : public DVBProtocolWrapper
{
private:
const DVBDemuxSectionSocketProtocol& protocol;
DVBSectionProtocolWrapper(senf::DVBDemuxSectionHandle sh);
~DVBSectionProtocolWrapper() { }
-
+
void setSectionFilter(unsigned short int pid, u_int8_t filter,
unsigned int flags, u_int8_t mask, u_int8_t mode, unsigned int timeout);
- void setBufferSize(unsigned long size);
+ void setBufferSize(unsigned long size);
///< Set the size of the circular buffer used for filtered data.
/**< The default size is two maximum sized sections, i.e. if
this function is not called a buffer size of 2 * 4096 bytes
void startFiltering(); ///< Starts filtering
void stopFiltering(); ///< Stops filtering
};
-
+
SENF_CONSOLE_REGISTER_ENUM_MEMBER(DVBSectionProtocolWrapper, Flags,
(CHECK_CRC)(ONESHOT)(IMMEDIATE_START)(KERNEL_CLIENT));
-
+
class DVBPESProtocolWrapper : public senf::DVBProtocolWrapper
{
private:
const senf::DVBDemuxPESSocketProtocol& protocol;
-
+
public:
enum Flags {CHECK_CRC = DMX_CHECK_CRC,
ONESHOT = DMX_ONESHOT,
void startFiltering(); ///< Starts filtering
void stopFiltering(); ///< Stops filtering
};
-
+
SENF_CONSOLE_REGISTER_ENUM_MEMBER(DVBPESProtocolWrapper, Flags,
(CHECK_CRC)(ONESHOT)(IMMEDIATE_START)(KERNEL_CLIENT));
}
unsigned int senf::DVBSocketController::controllerNr(0);
-senf::DVBSocketController::DVBSocketController(DVBFrontendHandle frontendHandle_, const Callback & cb_)
+senf::DVBSocketController::DVBSocketController(DVBFrontendHandle frontendHandle_,
+ const Callback & cb_)
: dir( this ),
frontendHandle( frontendHandle_ ),
type( frontendHandle.protocol().getInfo().type ),
cb( cb_ ),
sectionNr(1),
pesNr(1),
- event( "senf::DVBSocketController::readEvent", senf::membind(&DVBSocketController::readEvent, this), frontendHandle, senf::scheduler::FdEvent::EV_PRIO, false )
+ event( "senf::DVBSocketController::readEvent",
+ senf::membind(&DVBSocketController::readEvent, this), frontendHandle,
+ senf::scheduler::FdEvent::EV_PRIO, false )
{
initConsole();
}
senf::DVBSocketController::createDVBDemuxSectionHandle(int adapternumber, int demuxnumber,
bool addToConsole)
{
- DVBDemuxSectionHandle sectionHandle(adapternumber, demuxnumber);
+ DVBDemuxSectionHandle sectionHandle(adapternumber, demuxnumber);
if (addToConsole)
this->addToConsole(sectionHandle);
return sectionHandle;
-
+
}
prefix_ senf::DVBDemuxPESHandle
senf::DVBSocketController::createDVBDemuxPESHandle(int adapternumber, int demuxnumber,
bool addToConsole)
{
- DVBDemuxPESHandle pesHandle(adapternumber, demuxnumber);
+ DVBDemuxPESHandle pesHandle(adapternumber, demuxnumber);
if (addToConsole)
this->addToConsole(pesHandle);
return pesHandle;
-
+
}
prefix_ void senf::DVBSocketController::addToConsole(senf::DVBDemuxSectionHandle sh)
if (mode.c_str()[0]=='a') {
switch (type) {
case FE_QPSK:
- tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner);
+ tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate,
+ frontend.u.qpsk.fec_inner);
break;
case FE_QAM:
- tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate, frontend.u.qam.fec_inner, frontend.u.qam.modulation);
+ tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
+ frontend.u.qam.fec_inner, frontend.u.qam.modulation);
break;
case FE_OFDM:
- tuneDVB_T(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth, frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP, frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode, frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information);
+ tuneDVB_T(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
+ frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
+ frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
+ frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information);
break;
default:
SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
else {
switch (type) {
case FE_QPSK:
- tuneDVB_S_sync(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner);
+ tuneDVB_S_sync(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate,
+ frontend.u.qpsk.fec_inner);
break;
case FE_QAM:
- tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate, frontend.u.qam.fec_inner, frontend.u.qam.modulation);
+ tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
+ frontend.u.qam.fec_inner, frontend.u.qam.modulation);
break;
case FE_OFDM:
- tuneDVB_T_sync(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth, frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP, frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode, frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information);
+ tuneDVB_T_sync(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
+ frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
+ frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
+ frontend.u.ofdm.guard_interval,
+ frontend.u.ofdm.hierarchy_information);
break;
default:
SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
frontend = parser.getFrontendParam(configLine);
switch (type) {
case FE_QPSK:
- tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner);
+ tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate,
+ frontend.u.qpsk.fec_inner);
break;
case FE_QAM:
- tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate, frontend.u.qam.fec_inner, frontend.u.qam.modulation);
+ tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
+ frontend.u.qam.fec_inner, frontend.u.qam.modulation);
break;
case FE_OFDM:
- tuneDVB_T(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth, frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP, frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode, frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information);
+ tuneDVB_T(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
+ frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
+ frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
+ frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information);
break;
default:
SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
)
{
if (type != FE_OFDM)
- SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-T Card!";
+ SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
+ << getTypeString() << " for this operation you need a DVB-T Card!";
event.enable();
hierarchy_information);
}
-prefix_ void senf::DVBSocketController::tuneDVB_S(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, fe_code_rate_t code_rate)
+prefix_ void senf::DVBSocketController::tuneDVB_S(unsigned int frequency,
+ fe_spectral_inversion_t inversion,
+ unsigned int symbole_rate,
+ fe_code_rate_t code_rate)
{
if (type != FE_QPSK)
- SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-S Card!";
+ SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
+ << getTypeString() << " for this operation you need a DVB-S Card!";
event.enable();
)
{
if (type != FE_QAM)
- SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-C Card!";
+ SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
+ << getTypeString() << " for this operation you need a DVB-C Card!";
event.enable();
frontend = parser.getFrontendParam(configLine);
switch (type) {
case FE_QPSK:
- ev = tuneDVB_S_sync(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner);
+ ev = tuneDVB_S_sync(frontend.frequency, frontend.inversion,
+ frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner);
break;
case FE_QAM:
- ev = tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate, frontend.u.qam.fec_inner, frontend.u.qam.modulation);
+ ev = tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
+ frontend.u.qam.fec_inner, frontend.u.qam.modulation);
break;
case FE_OFDM:
- ev = tuneDVB_T_sync(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth, frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP, frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode, frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information);
+ ev = tuneDVB_T_sync(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
+ frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
+ frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
+ frontend.u.ofdm.guard_interval,
+ frontend.u.ofdm.hierarchy_information);
break;
default:
SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
)
{
if (type != FE_OFDM)
- SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-T Card!";
+ SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
+ << getTypeString() << " for this operation you need a DVB-T Card!";
event.disable();
unsigned int symbole_rate, fe_code_rate_t code_rate)
{
if (type != FE_QPSK)
- SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-S Card!";
+ SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
+ << getTypeString() << " for this operation you need a DVB-S Card!";
event.disable();
)
{
if (type != FE_QAM)
- SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-C Card!";
+ SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
+ << getTypeString() << " for this operation you need a DVB-C Card!";
event.disable();
++controllerNr;
dir.add("type", fty::Command(&DVBSocketController::getTypeString, this)
- .doc("Shows actual type of card DVB-{T, S, C}") );
+ .doc("Shows actual type of card DVB-{T, S, C}") );
dir.add("info", fty::Command(&DVBSocketController::getTuneInfo, this)
- .doc("Returns a string which shows actual tuning status.\n"
- "'S' prints signal strength (in hex)\n"
- "'s' prints singal to noise ration (in hex)\n"
- "'b' prints bit error rate (in hex)\n"
- "'u' prints uncorrected blocks (in hex)\n"
- "'f' prints readable overal status e.g. 'Has Lock'\n\n"
- "These characters can be used to form the output. Be aware, some\n"
- "features may not be supported be your current driver implementation\n"
- "and could end in throwing an exception!")
- .arg("conf", "Ssbuf", kw::default_value = "Ssbuf") );
+ .doc("Returns a string which shows actual tuning status.\n"
+ "'S' prints signal strength (in hex)\n"
+ "'s' prints singal to noise ration (in hex)\n"
+ "'b' prints bit error rate (in hex)\n"
+ "'u' prints uncorrected blocks (in hex)\n"
+ "'f' prints readable overal status e.g. 'Has Lock'\n\n"
+ "These characters can be used to form the output. Be aware, some\n"
+ "features may not be supported be your current driver implementation\n"
+ "and could end in throwing an exception!")
+ .arg("conf", "Ssbuf", kw::default_value = "Ssbuf") );
dir.add("tune", fty::Command(&DVBSocketController::tuneToCMD, this)
- .doc("tunes to channel listet in the configfile.")
- .arg("channel", "channel to tune")
- .arg("mode", "mode 'sync' or 'async'", kw::default_value = "async") );
+ .doc("tunes to channel listet in the configfile.")
+ .arg("channel", "channel to tune")
+ .arg("mode", "mode 'sync' or 'async'", kw::default_value = "async") );
}
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// comment-column: 40
+// End:
You have to find out which parts of these functionality are implemented by your preferred
device driver by your own.
*/
-
-
-
+
+
+
class DVBSocketController : boost::noncopyable
{
public:
DVBSocketController(DVBFrontendHandle frontendHandle_ = DVBFrontendHandle(0,0), const Callback & cb = NULL);
~DVBSocketController();
-
+
senf::DVBDemuxSectionHandle createDVBDemuxSectionHandle( int adapternumber=0, int demuxnumber=0, bool addToConsole=false );
senf::DVBDemuxPESHandle createDVBDemuxPESHandle( int adapternumber=0, int demuxnumber=0, bool addToConsole=false );
void addToConsole(senf::DVBDemuxSectionHandle sh);
- ///< Adds an DVBDemuxSectionHandle to the console
- /**< Allocates the functionality of DVBDemuxSectionProtocol
- into the folder of the DVBSocketController. If the
- protocol is closed, or all handles are discarded the
+ ///< Adds an DVBDemuxSectionHandle to the console
+ /**< Allocates the functionality of DVBDemuxSectionProtocol
+ into the folder of the DVBSocketController. If the
+ protocol is closed, or all handles are discarded the
console support will automatically removed.
\param[in] sh handle of a protocol*/
-
+
void addToConsole(senf::DVBDemuxPESHandle sh);
- ///< Adds an DVBDemuxPESHandle to the console
+ ///< Adds an DVBDemuxPESHandle to the console
/**< Allocates the functionality of DVBDemuxPESProtocol into
the folder of the DVBSocketController. If the protocol
- is closed, or all handles are discarded the console
+ is closed, or all handles are discarded the console
support will automatically removed.
\param[in] sh handle of a protocol*/
-
+
void tuneToCMD( const std::string & input, const std::string & mode = "async");
///< Tunes a DVB device given by the type of the DVBFrontendHandle
/**< Tunes a DVB device by a channel name or complete
on the socket.
\returns timestamp when last packet was received */
};
-
+
///\}
}
const
{
init_client(protocol);
- if (address.boolean_test()) {
+ if (address.boolean_test()) {
//only connect if socket is not [::]:0, this results in an irreversible binding to the lo interface (linux 2.6.15)
clientHandle().connect(address);
}
\par Address Type:
INet4SocketAddress
- ConnectedRawV4SocketProtocol provides an Internet protocol raw socket based on IPv4 addressing.
- This socket will put data written to it onto the IPv4 layer: if you call writeto don't include
- the header!
- On the other hand `read` will return the packet data including the IP header.
- This behaviour is strange and differs from the behaviour of IPv6 RAW sockets and should be
- changed in the future.
+ ConnectedRawV4SocketProtocol provides an Internet protocol raw socket based on IPv4
+ addressing. This socket will put data written to it onto the IPv4 layer: if you call
+ writeto don't include the header!
+
+ On the other hand `read` will return the packet data including the IP header.
+ This behaviour is strange and differs from the behaviour of IPv6 RAW sockets and should be
+ changed in the future.
This class is utilized as the protocol class of the ProtocolClientSocketHandle
via the Socket Handle typedefs above.
- \attention
- If socket handle with ConnectedRawV4SocketProtocol is connected via INet4SocketAddress, the port number
- is interpreted as protocol number for IPv4 layer. Please refer manpage: "man 7 raw".
+ \attention If socket handle with ConnectedRawV4SocketProtocol is connected via
+ INet4SocketAddress, the port number is interpreted as protocol number for IPv4
+ layer. Please refer manpage: "man 7 raw".
\see ConnectedRawV6SocketProtocol
\see RawV4SocketProtocol
/**< \note This member is implicitly called from the
ProtocolClientSocketHandle::ProtocolClientSocketHandle()
constructor */
- void init_client(int const & protocol) const; ///< Create unconnected client socket for protocol
-
+ void init_client(int const & protocol) const;
+ ///< Create unconnected client socket for protocol
+
void init_client(int const & protocol, INet4SocketAddress const & address) const;
///< Create client socket and connect
- /**< Creates a new client socket for the given protocol and connects to the given
- address.
- \param[in] protocol Layer 4 protocol to filter for / to send
+ /**< Creates a new client socket for the given protocol and
+ connects to the given address.
+ \param[in] protocol Layer 4 protocol to filter for / to
+ send
\param[in] address local address to connect to */
///@}
};
- typedef ProtocolClientSocketHandle<ConnectedRawV4SocketProtocol> ConnectedRawV4ClientSocketHandle;
+ typedef ProtocolClientSocketHandle<ConnectedRawV4SocketProtocol>
+ ConnectedRawV4ClientSocketHandle;
-//////////////////////////////////////////////////////////////////// Raw IPv6 Socket //////////////////////////////////////
+//////////////////////////////////////////////// Raw IPv6 Socket ////////////////////////////
typedef MakeSocketPolicy<
INet6AddressingPolicy,
DatagramFramingPolicy,
\par Socket Handle typedefs:
\ref ConnectedRawV6ClientSocketHandle (ProtocolClientSocketHandle)
- \par Policy Interface:
+ \par Policy Interface:
ClientSocketHandle::read(), ClientSocketHandle::write(), ClientSocketHandle::bind(),
ClientSocketHandle::local(), ClientSocketHandle::connect(), ClientSocketHandle::peer()
-
+
\par Address Type:
INet6Address
- ConnectedRawV6SocketProtocol provides an internet protocol raw socket based on IPv6 addressing which is connected to certain peer.
- This socket will put data written to it onto the IPv6 layer: if you call writeto don't inlude the header!
- On the other hand `read` will return the packet data on top of the IPv6 layer, excluding the IP header.
- Note: This behaviour is differs from the behaviour of IPv4 RAW sockets.
+ ConnectedRawV6SocketProtocol provides an internet protocol raw socket based on IPv6
+ addressing which is connected to certain peer. This socket will put data written to it onto
+ the IPv6 layer: if you call writeto don't inlude the header! On the other hand `read` will
+ return the packet data on top of the IPv6 layer, excluding the IP header. Note: This
+ behaviour is differs from the behaviour of IPv4 RAW sockets.
This class is utilized as the protocol class of the ProtocolClientSocketHandle
via the Socket Handle typedefs above.
- \attention
- If socket handle with ConnectedRawV6SocketProtocol is connected via INet6SocketAddress, the port number
- is interpreted as protocol number for IPv6 layer. Please refer manpage: "man 7 ipv6".
+ \attention If socket handle with ConnectedRawV6SocketProtocol is connected via
+ INet6SocketAddress, the port number is interpreted as protocol number for IPv6
+ layer. Please refer manpage: "man 7 ipv6".
\see ConnectedRawV4SocketProtocol
\see RawV4SocketProtocol
ProtocolClientSocketHandle::ProtocolClientSocketHandle()
constructor */
- void init_client(int const & protocol) const; ///< Create unconnected client socket for protocol
+ void init_client(int const & protocol) const;
+ ///< Create unconnected client socket for protocol
void init_client(int const & protocol, INet6SocketAddress const & address) const;
///< Create client socket and connect
- /**< Creates a new client socket for the given protocol and connects to the given
- address.
- \param[in] protocol Layer 4 protocol to filter for / to send
- \param[in] address local address to connect to */
- /**< \note This member is implicitly called from the
+ /**< Creates a new client socket for the given protocol and
+ connects to the given address.
+ \param[in] protocol Layer 4 protocol to filter for / to
+ send
+ \param[in] address local address to connect to
+ \note This member is implicitly called from the //
ProtocolClientSocketHandle::ProtocolClientSocketHandle()
constructor (??) */
///@}
};
- typedef ProtocolClientSocketHandle<ConnectedRawV6SocketProtocol> ConnectedRawV6ClientSocketHandle;
+ typedef ProtocolClientSocketHandle<ConnectedRawV6SocketProtocol>
+ ConnectedRawV6ClientSocketHandle;
/// @}
}
#endif /*CONNECTEDHH_SENF_Socket_Protocols_INet_RawINetSocketHandle_*/
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// comment-column: 40
+// End:
\par Address Type:
INet4SocketAddress
-
+
ConnectedUDPv4SocketProtocol provides an internet protocol stream socket based on the UDP
protocol and IPv4 addressing.
\par Policy Interface:
ClientSocketHandle::read(), ClientSocketHandle::write(), ClientSocketHandle::bind(),
ClientSocketHandle::local(), ClientSocketHandle::connect(), ClientSocketHandle::peer()
-
+
\par Address Type:
INet6Address
prefix_ void senf::detail::apply_mask(unsigned bits, ForwardIterator b, ForwardIterator e,
Function fn)
{
- for(; bits>8 && b != e; bits -= 8, ++b)
+ for(; bits>8 && b != e; bits -= 8, ++b)
fn(*b, boost::lambda::make_const(0xFFu));
if (bits > 0 && b != e)
fn( *(b++), boost::lambda::make_const(~ low_bits_mask(8-bits)));
template <class ForwardIterator1, class ForwardIterator2, class Function>
prefix_ ForwardIterator1 senf::detail::find_if_mask(unsigned bits, ForwardIterator1 b1,
- ForwardIterator1 e1, ForwardIterator2 b2,
+ ForwardIterator1 e1, ForwardIterator2 b2,
Function fn)
{
- for(; bits>8 && b1 != e1; bits -= 8, ++b1, ++b2)
+ for(; bits>8 && b1 != e1; bits -= 8, ++b1, ++b2)
if (fn(*b1, *b2, boost::lambda::make_const(0xFFu)))
return b1;
if (bits > 0 && b1 != e1)
prefix_ bool senf::detail::CheckINet6Network_impl5<a,0,restbits>::match(boost::uint8_t v0,
boost::uint8_t v1)
{
- return v0 & ~boost::low_bits_mask_t<8-restbits>::sig_bits
+ return v0 & ~boost::low_bits_mask_t<8-restbits>::sig_bits
== boost::uint8_t(a>>8) & ~boost::low_bits_mask_t<8-restbits>::sig_bits;
}
boost::uint8_t v1)
{
return v0 == boost::uint8_t(a>>8) &&
- v1 & ~boost::low_bits_mask_t<8-restbits>::sig_bits
+ v1 & ~boost::low_bits_mask_t<8-restbits>::sig_bits
== boost::uint8_t(a) & ~boost::low_bits_mask_t<8-restbits>::sig_bits;
}
-template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
+template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
unsigned a6, unsigned a7, unsigned restbits>
prefix_ bool senf::detail::CheckINet6Network_impl3<a0,a1,a2,a3,a4,a5,a6,a7,0,restbits>::
match(INet6Address const & addr)
return CheckINet6Network_impl4<a0,restbits>::match(addr[0],addr[1]);
}
-template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
+template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
unsigned a6, unsigned a7, unsigned restbits>
prefix_ bool senf::detail::CheckINet6Network_impl3<a0,a1,a2,a3,a4,a5,a6,a7,1,restbits>::
match(INet6Address const & addr)
{
- return
+ return
addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) &&
CheckINet6Network_impl4<a1,restbits>::match(addr[2],addr[3]);
}
-template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
+template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
unsigned a6, unsigned a7, unsigned restbits>
prefix_ bool senf::detail::CheckINet6Network_impl3<a0,a1,a2,a3,a4,a5,a6,a7,2,restbits>::
match(INet6Address const & addr)
{
- return
+ return
addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) &&
addr[2] == boost::uint8_t(a1>>8) && addr[3] == boost::uint8_t(a1) &&
CheckINet6Network_impl4<a1,restbits>::match(addr[4],addr[5]);
}
-template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
+template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
unsigned a6, unsigned a7, unsigned restbits>
prefix_ bool senf::detail::CheckINet6Network_impl3<a0,a1,a2,a3,a4,a5,a6,a7,3,restbits>::
match(INet6Address const & addr)
{
- return
+ return
addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) &&
addr[2] == boost::uint8_t(a1>>8) && addr[3] == boost::uint8_t(a1) &&
addr[4] == boost::uint8_t(a2>>8) && addr[5] == boost::uint8_t(a2) &&
CheckINet6Network_impl4<a3,restbits>::match(addr[6],addr[7]);
}
-template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
+template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
unsigned a6, unsigned a7, unsigned restbits>
prefix_ bool senf::detail::CheckINet6Network_impl3<a0,a1,a2,a3,a4,a5,a6,a7,4,restbits>::
match(INet6Address const & addr)
{
- return
+ return
addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) &&
addr[2] == boost::uint8_t(a1>>8) && addr[3] == boost::uint8_t(a1) &&
addr[4] == boost::uint8_t(a2>>8) && addr[5] == boost::uint8_t(a2) &&
CheckINet6Network_impl4<a4,restbits>::match(addr[8],addr[9]);
}
-template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
+template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
unsigned a6, unsigned a7, unsigned restbits>
prefix_ bool senf::detail::CheckINet6Network_impl3<a0,a1,a2,a3,a4,a5,a6,a7,5,restbits>::
match(INet6Address const & addr)
{
- return
+ return
addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) &&
addr[2] == boost::uint8_t(a1>>8) && addr[3] == boost::uint8_t(a1) &&
addr[4] == boost::uint8_t(a2>>8) && addr[5] == boost::uint8_t(a2) &&
CheckINet6Network_impl4<a5,restbits>::match(addr[10],addr[11]);
}
-template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
+template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
unsigned a6, unsigned a7, unsigned restbits>
prefix_ bool senf::detail::CheckINet6Network_impl3<a0,a1,a2,a3,a4,a5,a6,a7,6,restbits>::
match(INet6Address const & addr)
{
- return
+ return
addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) &&
addr[2] == boost::uint8_t(a1>>8) && addr[3] == boost::uint8_t(a1) &&
addr[4] == boost::uint8_t(a2>>8) && addr[5] == boost::uint8_t(a2) &&
CheckINet6Network_impl4<a6,restbits>::match(addr[12],addr[13]);
}
-template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
+template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4, unsigned a5,
unsigned a6, unsigned a7, unsigned restbits>
prefix_ bool senf::detail::CheckINet6Network_impl3<a0,a1,a2,a3,a4,a5,a6,a7,7,restbits>::
match(INet6Address const & addr)
{
- return
+ return
addr[0] == boost::uint8_t(a0>>8) && addr[1] == boost::uint8_t(a0) &&
addr[2] == boost::uint8_t(a1>>8) && addr[3] == boost::uint8_t(a1) &&
addr[4] == boost::uint8_t(a2>>8) && addr[5] == boost::uint8_t(a2) &&
///< Construct link-local INet6 address
/**< This will construct a link local address of the form
<tt>fe80::xxxx:xxxx:xxxx:xxxx</tt>. */
-
+
in6_addr toin6_addr() const; ///< get the linux in6_addr struct (convinience only)
///@}
struct CheckINet6Network_impl4
: public CheckINet6Network_impl5<a,bits/8,bits%8>
{};
-
+
template <unsigned a0, unsigned a1, unsigned a2, unsigned a3, unsigned a4,
unsigned a5, unsigned a6, unsigned a7, unsigned words, unsigned restbits>
struct CheckINet6Network_impl3
void apply_mask(unsigned bits, ForwardIterator b, ForwardIterator e, Function fn);
template <class ForwardIterator1, class ForwardIterator2, class Function>
- ForwardIterator1 find_if_mask(unsigned bits,
+ ForwardIterator1 find_if_mask(unsigned bits,
ForwardIterator1 b1, ForwardIterator1 e1, ForwardIterator2 b2,
Function fn);
BOOST_CHECK( ! net.match(net2) );
BOOST_CHECK( net2.match(INet6Network("2001:db8:1234::/48")) );
BOOST_CHECK( ! net2.match(INet6Network("2001:db8:1234::/32")) );
-
+
BOOST_CHECK( ! INet6Network("ff14:1234::1/128").match(INet6Network("ff14:1234::2/128")) );
BOOST_CHECK_EQUAL( senf::str(net2), "2001:db8:1230::/44" );
///\addtogroup protocol_facets_group
///\{
-
+
/** \brief Generic addressing type independent multicast protocol facet
\todo implement complete new multicast API from RFC3678 (as far as supported by linux)
\bug mcLeaveSSMSource fails with EADDRNOTAVAIL
*/
- class MulticastSocketProtocol
+ class MulticastSocketProtocol
: public virtual SocketProtocol
{
public:
unsigned mcTTL() const; ///< Return current multicast TTL
void mcTTL(unsigned value) const; ///< Set multicast TTL
- bool mcLoop() const; ///< Return current multicast loopback state.
+ bool mcLoop() const; ///< Return current multicast loopback state.
void mcLoop(bool value) const; ///< Set multicast loopback state
/**< If set to false via \c mcLoop(value) multicast messages
will not be looped back to local sockets. Default value
void mcIface(std::string const & iface = std::string()) const;
///< Set multicast send interface of the socket
/**< \param[in] iface name of interface to send multicast
- data from
+ data from
Under current linux versions this option is broken at
best. Don't use. */
/**< This member will add \a mcAddr to the list of multicast
groups received. The group is joined on the interface
with the given local address.
- \deprecated Use \link mcAddMembership(INet4Address const & mcAddr, std::string const & iface) const mcAddMembership( \a mcAddr , \a iface )\endlink
+ \deprecated Use \link mcAddMembership(INet4Address const & mcAddr, std::string const & iface) const mcAddMembership( \a mcAddr , \a iface )\endlink
for compatibility with the IPv6 API.
\param[in] mcAddr address of group to join
\param[in] localAddr address of interface to join on */
multicast groups received. The group is left from the
default interface.
\param[in] mcAddr address of group to leave */
- void mcDropMembership(INet4Address const & mcAddr, INet4Address const & localAddr)
+ void mcDropMembership(INet4Address const & mcAddr, INet4Address const & localAddr)
const;
///< leave multicast group on a specific interface
/**< This member will remove \a mcAddr from the list of
multicast groups received. The group is left from the
interface with the given local address.
- \deprecated Use \link mcDropMembership(INet4Address const & mcAddr, std::string const & iface) const mcDropMembership( \a mcAddr , \a iface )\endlink
+ \deprecated Use \link mcDropMembership(INet4Address const & mcAddr, std::string const & iface) const mcDropMembership( \a mcAddr , \a iface )\endlink
for compatibility with the IPv6 API.
\param[in] mcAddr address of group to leave
\param[in] localAddr address of interface to leave
from */
- void mcDropMembership(INet4Address const & mcAddr, std::string const & iface)
+ void mcDropMembership(INet4Address const & mcAddr, std::string const & iface)
const;
///< leave multicast group on a specific interface
/**< This member will remove \a mcAddr from the list of
\param[in] mcAddr address of group to leave
\param[in] iface interface name */
- void mcJoinSSMSource(INet4Address const & group, INet4Address const & source,
+ void mcJoinSSMSource(INet4Address const & group, INet4Address const & source,
std::string const & iface) const;
///< join SSM multicast group
/**< This call will join the multicast group \a group for
\param[in] mcAddr address of group to leave
\param[in] iface interface name */
- void mcJoinSSMSource(INet6Address const & group, INet6Address const & source,
+ void mcJoinSSMSource(INet6Address const & group, INet6Address const & source,
std::string const & iface) const;
///< join SSM multicast group
/**< This call will join the multicast group \a group for
group on
\param[in] iface interface to join the group on. If set
to the empty string, use the default interface. */
- void mcJoinSSMSource(INet6Address const & group, INet6Address const & source,
+ void mcJoinSSMSource(INet6Address const & group, INet6Address const & source,
int ifacei = 0) const;
///< join SSM multicast group
/**< This call will join the multicast group \a group for
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
RawV4SocketProtocol provides an internet protocol raw socket based on IPv4 addressing.
This socket will put data written to it onto the IPv4 layer: if you call writeto don't inlude the header!
- On the other hand `read` will return the packet data including the IP header.
- This behaviour is strange and differs from the behaviour of IPv6 RAW sockets and should be changed in the future.
+ On the other hand `read` will return the packet data including the IP header.
+ This behaviour is strange and differs from the behaviour of IPv6 RAW sockets and should be changed in the future.
This class is utilized as the protocol class of the ProtocolClientSocketHandle
via the Socket Handle typedefs above.
ProtocolClientSocketHandle::ProtocolClientSocketHandle()
constructor */
void init_client(int const & protocol) const; ///< Create unconnected client socket for protocol
-
+
void init_client(int const & protocol, INet4SocketAddress const & address) const;
///< Create client socket and bind
/**< Creates a new client socket for the given protocol and binds to the given
address.
- \param[in] protocol Layer 4 protocol to filter for / to send
+ \param[in] protocol Layer 4 protocol to filter for / to send
\param[in] address local address to bind to */
///@}
\par Socket Handle typedefs:
\ref RawV6ClientSocketHandle (ProtocolClientSocketHandle)
- \par Policy Interface:
+ \par Policy Interface:
ClientSocketHandle::read(), ClientSocketHandle::readfrom(),
ClientSocketHandle::writeto(), ClientSocketHandle::bind(), ClientSocketHandle::local()
RawV6SocketProtocol provides an internet protocol raw socket based on IPv6 addressing.
This socket will put data written to it onto the IPv6 layer: if you call writeto don't inlude the header!
- On the other hand `read` will return the packet data on top of the IPv6 layer, excluding the IP header.
- Note: This behaviour is differs from the behaviour of IPv4 RAW sockets.
+ On the other hand `read` will return the packet data on top of the IPv6 layer, excluding the IP header.
+ Note: This behaviour is differs from the behaviour of IPv4 RAW sockets.
This class is utilized as the protocol class of the ProtocolClientSocketHandle
via the Socket Handle typedefs above.
///< Create client socket and bind
/**< Creates a new client socket for the given protocol and binds to the given
address.
- \param[in] protocol Layer 4 protocol to filter for / to send
+ \param[in] protocol Layer 4 protocol to filter for / to send
\param[in] address local address to bind to */
/**< \note This member is implicitly called from the
ProtocolClientSocketHandle::ProtocolClientSocketHandle()
sin.sin_family = AF_INET;
sin.sin_port = htons(0);
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
+
int sockrec = socket(PF_INET,SOCK_RAW,47);
if (sockrec<0) fail("server_v4","socket(rec)");
int socksend = socket(PF_INET,SOCK_RAW,48);
if (socksend<0) fail("server_v4","socket(send)");
-
+
char buffer[1024];
while (1) {
int n = read(sockrec,buffer,1024);
::memset(&sin,0,sizeof(sin));
sin.sin6_family = AF_INET6;
sin.sin6_port = htons(0);
- inet_pton(AF_INET6, "::1", &sin.sin6_addr);
+ inet_pton(AF_INET6, "::1", &sin.sin6_addr);
int sockrec6 = socket(PF_INET6,SOCK_RAW,47);
if (sockrec6<0) fail("server_v6","socket(rec)");
int socksend6 = socket(PF_INET6,SOCK_RAW,48);
SENF_CHECK_NO_THROW( sock.writeto(senf::INet4SocketAddress("127.0.0.1:0"), test) );
senf::RawV4ClientSocketHandle sockrec(48); //IPPROTO_GRE+1
std::string in = sockrec.read();
- BOOST_CHECK_EQUAL(in.substr(20), test);
+ BOOST_CHECK_EQUAL(in.substr(20), test);
SENF_CHECK_NO_THROW( sock.writeto(senf::INet4SocketAddress("127.0.0.1:0"),"QUIT"));
//sock.close();
//sockrec.close();
SENF_CHECK_NO_THROW( sock.writeto(senf::INet6SocketAddress("[::1]:0"), test) );
senf::RawV6ClientSocketHandle sockrec(48); //IPPROTO_GRE+1
std::string in = sockrec.read();
- BOOST_CHECK_EQUAL(in, test);
+ BOOST_CHECK_EQUAL(in, test);
SENF_CHECK_NO_THROW( sock.writeto(senf::INet6SocketAddress("[::1]:0"),"QUIT"));
alarm(0);
} catch (...) {
/// \addtogroup protocol_facets_group
/// @{
- /** \brief Protocol facat to support RAW operations upon IPv4/6
+ /** \brief Protocol facat to support RAW operations upon IPv4/6
This protocol facet provides all those protocol functions,
which are available on a PF_INET[6]/RAW socket.
-
+
*/
class RawINetSocketProtocol
: public virtual INetSocketProtocol
\par Socket Handle typedefs:
\ref TCPv4ClientSocketHandle (ProtocolClientSocketHandle), \ref TCPv4ServerSocketHandle
(ProtocolServerSocketHandle)
-
+
\par Policy Interface:
ClientSocketHandle::read(), ClientSocketHandle::write(), ClientSocketHandle::bind(),
ClientSocketHandle::local(), ClientSocketHandle::connect(), ClientSocketHandle::peer()
{
senf::TCPv4ClientSocketHandle sock;
- BOOST_CHECK_THROW( sock.connect(senf::INet4SocketAddress(localhost4str(0))),
+ BOOST_CHECK_THROW( sock.connect(senf::INet4SocketAddress(localhost4str(0))),
senf::SystemException );
}
{
senf::TCPv6ClientSocketHandle sock;
- BOOST_CHECK_THROW( sock.connect(senf::INet6SocketAddress(localhost6str(0))),
+ BOOST_CHECK_THROW( sock.connect(senf::INet6SocketAddress(localhost6str(0))),
senf::SystemException );
}
\par Socket Handle typedefs:
\ref UDPv6ClientSocketHandle (ProtocolClientSocketHandle)
- \par Policy Interface:
+ \par Policy Interface:
ClientSocketHandle::read(), ClientSocketHandle::readfrom(),
ClientSocketHandle::writeto(), ClientSocketHandle::bind(), ClientSocketHandle::local()
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
class MACAddress;
/** \brief EUI-64 data type
-
+
An EUI-64 is a 64 bit (8 octet) id. The id is represented as an 8 byte sequence in network
byte order. An EUI64 can be converted from/to several other representations
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
BOOST_CHECK_EQUAL( eui, senf::EUI64::from_data(data) );
BOOST_CHECK_EQUAL( eui, senf::EUI64::from_string("10:20:30:ff-FE:40:50:60") );
- BOOST_CHECK_THROW( senf::EUI64::from_string("123:20:30:40:50:60:70:80"),
+ BOOST_CHECK_THROW( senf::EUI64::from_string("123:20:30:40:50:60:70:80"),
senf::AddressSyntaxException );
- BOOST_CHECK_THROW( senf::EUI64::from_string("12:20:30:40:50:60:70"),
+ BOOST_CHECK_THROW( senf::EUI64::from_string("12:20:30:40:50:60:70"),
senf::AddressSyntaxException );
- BOOST_CHECK_THROW( senf::EUI64::from_string("12:20:30:40:50:60:70:8g"),
+ BOOST_CHECK_THROW( senf::EUI64::from_string("12:20:30:40:50:60:70:8g"),
senf::AddressSyntaxException );
- BOOST_CHECK_THROW( senf::EUI64::from_string("12:20:30:40:50:60:70:80:90"),
+ BOOST_CHECK_THROW( senf::EUI64::from_string("12:20:30:40:50:60:70:80:90"),
senf::AddressSyntaxException );
-
+
BOOST_CHECK_EQUAL( senf::EUI64::None, senf::EUI64(0) );
BOOST_CHECK(! senf::EUI64::None );
-
+
{
std::stringstream ss;
ss << std::uppercase << eui;
BOOST_CHECK( !eui );
ss >> eui;
BOOST_CHECK_EQUAL( eui, senf::EUI64(0x102030fffe405060ull) );
-
+
BOOST_CHECK( (ss >> eui).fail() );
}
prefix_ void senf::LLSocketAddress::interface(std::string const & iface)
{
- if (iface.empty())
+ if (iface.empty())
addr_.sll_ifindex = 0;
else {
addr_.sll_ifindex = if_nametoindex(iface.c_str());
prefix_ std::ostream & senf::operator<<(std::ostream & os, LLSocketAddress const & llAddr)
{
os << "[" << llAddr.address()
- << '%' << llAddr.interface()
+ << '%' << llAddr.interface()
<< ' ' << llAddr.protocol()
<< ' ' << llAddr.arptype()
<< ( llAddr.pkttype() == senf::LLSocketAddress::Host ? " Host" :
/** \brief Valid pkttype() values
- These are the possible values returned by pkttype()
+ These are the possible values returned by pkttype()
*/
enum PktType { Undefined = 0
, Host = PACKET_HOST /**< Packet destined for this host */
, OtherHost = PACKET_OTHERHOST /**< Packet sent to another host (promisc) */
, Outgoing = PACKET_OUTGOING /**< Packet sent out from this host */
};
-
+
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
SENF_AUTO_UNIT_TEST(llAddress)
{
using senf::LLSocketAddress;
-
+
{
LLSocketAddress addr;
BOOST_CHECK_EQUAL( addr.pkttype(), LLSocketAddress::Undefined );
BOOST_CHECK( ! addr.address() );
}
-
+
{
BOOST_CHECK_THROW( LLSocketAddress addr("SENF_TEST_INVALID_INTERFACENAME"),
senf::AddressSyntaxException );
-
+
LLSocketAddress addr ("lo");
-
+
BOOST_CHECK_EQUAL( addr.protocol(), 0u );
BOOST_CHECK_EQUAL( addr.interface(), "lo" );
BOOST_CHECK_EQUAL( addr.arptype(), 0u );
BOOST_CHECK_EQUAL( addr.pkttype(), LLSocketAddress::Undefined );
BOOST_CHECK( ! addr.address() );
-
+
BOOST_CHECK_EQUAL( LLSocketAddress("").interface(), "" );
}
}
}
namespace {
-
+
void do_mc(int fd, std::string const & interface, senf::MACAddress address, bool add)
{
struct packet_mreq mreq;
///< Disable reception of a multicast group
/**< \see \ref mcAdd() */
- void promisc(std::string const & interface, bool mode) const;
+ void promisc(std::string const & interface, bool mode) const;
///< enable/disable promiscuous mode
///@}
SENF_CHECK_NO_THROW( sock.protocol().promisc( "eth0", true) );
SENF_CHECK_NO_THROW( sock.protocol().promisc( "eth0", false));
-
+
SENF_CHECK_NO_THROW( sock.protocol().available() );
BOOST_CHECK( ! sock.eof() );
}
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
/**< Opens the tun/tap socket and create a new tap interface
Use \ref ifaceName() to get the actual name of the newly
created interface.
-
- The new interface is down and has to be set up separately.
+
+ The new interface is down and has to be set up separately.
After closing the socket, the tap interface and all
corresponding routes will be deleted automatically. */
/**< \note This member is implicitly called from the
with the given name. Note that the created interface can
have a different name as specified. Use \ref ifaceName()
to get the actual name.
-
- The new interface is down and has to be set up separately.
+
+ The new interface is down and has to be set up separately.
After closing the socket, the tap interface and all
- corresponding routes will be deleted automatically.
+ corresponding routes will be deleted automatically.
\param[in] interface_name name of the new tap interface.
- \param[in] NO_PI if set to \c false each packet has a
+ \param[in] NO_PI if set to \c false each packet has a
additional 4 bytes header (flags, proto) */
/**< \note This member is implicitly called from the
ProtocolClientSocketHandle::ProtocolClientSocketHandle()
unsigned available() const;
bool eof() const; ///< returns always false.
unsigned int ifaceIndex() const;///< returns the index of the correspondent tap interface
- std::string ifaceName() const; ///< returns the actual name of the correspondent tap interface
+ std::string ifaceName() const; ///< returns the actual name of the correspondent tap interface
private:
mutable unsigned int ifaceIndex_;
fd(sock);
}
-prefix_ void senf::ConnectedUNDatagramSocketProtocol::init_client(UNSocketAddress const & address) const
+prefix_ void senf::ConnectedUNDatagramSocketProtocol::init_client(UNSocketAddress const & address) const
{
init_client();
clientHandle().connect(address);
class ConnectedUNDatagramSocketProtocol
: public ConcreteSocketProtocol<ConnectedUNDatagramSocket_Policy,
ConnectedUNDatagramSocketProtocol>,
- public UNSocketProtocol,
+ public UNSocketProtocol,
public BSDSocketProtocol,
public AddressableBSDSocketProtocol
{
/**< \note This member is implicitly called from the
ProtocolClientSocketHandle::ProtocolClientSocketHandle()
constructor */
- void init_client(UNSocketAddress const & address) const;
+ void init_client(UNSocketAddress const & address) const;
///< Create client socket and connect
/**< Creates a new client socket and connects to the given
address.
/**< \note This member is implicitly called from the
ProtocolClientSocketHandle::ProtocolClientSocketHandle()
constructor */
-
+
///@}
};
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
/** \brief Unix domain socket address
UNSocketAddress wraps the standard sockaddr_un datatype. It provides simple accessor methods
- to access the path.
-
+ to access the path.
+
\implementation This implementation is based on sockaddr_un.
\ingroup addr_group
{
public:
static short const addressFamily = AF_UNIX;
-
- UNSocketAddress();
+
+ UNSocketAddress();
explicit UNSocketAddress(std::string const & path);
///< Construct an address constant from given path
{
senf::UNSocketAddress addr;
BOOST_CHECK( ! addr);
-
+
std::string path ("/tmp/SENF_TEST");
addr.path( path);
-
+
BOOST_CHECK( addr);
BOOST_CHECK_EQUAL( addr.path(), path);
BOOST_CHECK_EQUAL( addr, senf::UNSocketAddress(path));
BOOST_CHECK_EQUAL( addr, senf::UNSocketAddress(addr));
-
+
std::stringstream str;
str << addr;
BOOST_CHECK_EQUAL( str.str(), path );
-
+
// UNSocketAddress path too long
BOOST_CHECK_THROW( senf::UNSocketAddress(std::string(1024, 'x')), senf::AddressSyntaxException );
}
fd(sock);
}
-prefix_ void senf::UNDatagramSocketProtocol::init_client(UNSocketAddress const & address) const
+prefix_ void senf::UNDatagramSocketProtocol::init_client(UNSocketAddress const & address) const
{
init_client();
clientHandle().bind(address);
class UNDatagramSocketProtocol
: public ConcreteSocketProtocol<UNDatagramSocket_Policy,
UNDatagramSocketProtocol>,
- public UNSocketProtocol,
+ public UNSocketProtocol,
public BSDSocketProtocol,
public AddressableBSDSocketProtocol
{
/**< \note This member is implicitly called from the
ProtocolClientSocketHandle::ProtocolClientSocketHandle()
constructor */
- void init_client(UNSocketAddress const & address) const;
+ void init_client(UNSocketAddress const & address) const;
///< Create client socket and bind
/**< Creates a new client socket and bind to the given
address.
/**< \note This member is implicitly called from the
ProtocolClientSocketHandle::ProtocolClientSocketHandle()
constructor */
-
+
///@}
};
BOOST_CHECKPOINT( 5 );
BOOST_CHECK_EQUAL( inputSocket.read(), testString);
-
-
+
+
BOOST_CHECKPOINT( 6 );
outputSocket.close();
return false;
}
-prefix_ void senf::UNSocketProtocol::close()
+prefix_ void senf::UNSocketProtocol::close()
{
check_and_unlink();
-
+
SocketProtocol::close();
}
-prefix_ void senf::UNSocketProtocol::terminate()
+prefix_ void senf::UNSocketProtocol::terminate()
const
{
check_and_unlink();
-
+
SocketProtocol::terminate();
}
SENF_LOG(("UNSocketProtocol::check_and_unlink() failed; [" << e.errorString() << "]."));
}
}
-
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
//#include "UNSocketProtocol.mpp"
/** \brief Protocol facet providing Unix Domain Addressing related API
- This protocol facet introduces all the socket api protocol members which are related to Unix
+ This protocol facet introduces all the socket api protocol members which are related to Unix
Domain addressing.
*/
class UNSocketProtocol
virtual void close(); ///< Close socket
/**< This override will automatically \c shutdown() the
socket whenever it is closed.
- \throws senf::SystemException */ //
+ \throws senf::SystemException */ //
virtual void terminate() const; ///< Forcibly close socket
/**< This override will automatically \c shutdown() the
socket whenever it is called. Additionally it will
unsigned available() const;
bool eof() const;
-
+
private:
- void check_and_unlink() const;
-
+ void check_and_unlink() const;
+
std::string path_;
};
SPolicy,ConnectedCommunicationPolicy>::type * = 0);
# else
template <class SPolicy>
- static unsigned write(ClientSocketHandle<SPolicy> handle, char const * buffer,
+ static unsigned write(ClientSocketHandle<SPolicy> handle, char const * buffer,
unsigned size);
///< write data to socket
/**< This member is only enabled if the socket uses
\param lod level of %detail requested. The
interpretation of this value is protocol specific
-
+
\implementation This member will be re-implemented in
every derived class. See the state()
documentation. */
///< Value assigment
/**< This operator will assign the string from any
arbitrary type. It will use boost::lexical_cast to
- convert the argument to its string representation.
+ convert the argument to its string representation.
If the string is non-empty, an additional separating
comma is added to the string. */
};
template <class SProtocol>
- class ProtocolSocketBody
- : public SocketBody,
+ class ProtocolSocketBody
+ : public SocketBody,
private SProtocol,
public senf::pool_alloc_mixin< ProtocolSocketBody<SProtocol> >
{
/**< \param isServer \c true, if this socket is a server
socket, false otherwise
\param fd socket file descriptor */
-
+
private:
virtual SocketProtocol const & v_protocol() const;
virtual std::string v_protocolName() const;
SENF_CHECK_NO_THROW( myh.facet<senf::test::SomeSocketProtocol>() );
}
-
+
// Ensure, the destructor is called and calls the correct close() implementation
BOOST_CHECK( senf::test::SomeSocketProtocol::closeCount() >= 1u );
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
template < BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateArgs, , SENF_SOCKET_POLICIES ) >
struct SocketPolicy
: public SocketPolicyBase,
- public senf::pool_alloc_mixin<
+ public senf::pool_alloc_mixin<
SocketPolicy< BOOST_PP_SEQ_FOR_EACH_I( SP_TemplateParms, , SENF_SOCKET_POLICIES ) > >
{
# define SP_DeclarePolicyMember(x1,x2,SomePolicy) \
} // namespace impl
- template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SENF_SOCKET_POLICIES_N,
- class T,
+ template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SENF_SOCKET_POLICIES_N,
+ class T,
mpl::nil ) >
class MakeSocketPolicy
: public boost::mpl::if_< boost::is_convertible< T0*, SocketPolicyBase* >,
- impl::MakeSocketPolicy_impl<
- T0,
- boost::mpl::vector<
- BOOST_PP_ENUM_SHIFTED_PARAMS(
+ impl::MakeSocketPolicy_impl<
+ T0,
+ boost::mpl::vector<
+ BOOST_PP_ENUM_SHIFTED_PARAMS(
SENF_SOCKET_POLICIES_N, T ) > >,
- impl::MakeSocketPolicy_impl<
+ impl::MakeSocketPolicy_impl<
SocketPolicy<>,
- boost::mpl::vector<
- BOOST_PP_ENUM_PARAMS(
+ boost::mpl::vector<
+ BOOST_PP_ENUM_PARAMS(
SENF_SOCKET_POLICIES_N, T ) > > >::type
{};
template <class BasePolicy, class DerivedPolicy>
struct SocketPolicyIsBaseOf
- : public boost::mpl::if_<
+ : public boost::mpl::if_<
boost::mpl::and_< boost::is_convertible< BasePolicy*, SocketPolicyBase* >,
boost::is_convertible< DerivedPolicy*, SocketPolicyBase* > >,
impl::SocketPolicy_compatibility<BasePolicy,DerivedPolicy>,
- boost::false_type
+ boost::false_type
>::type
{};
// The following should fail at compile time
// p1 = p3;
}
-
+
{
Policy1 p1;
Policy3 p3;
\attention SocketProtocol must \e always be inherited using public \e virtual inheritance.
*/
- class SocketProtocol
+ class SocketProtocol
: boost::noncopyable
{
public:
in a single (non-blocking) read operation. If the
socket does not support reading (viz. NotReadablePolicy
is set), this member should always return \c 0.
-
+
Depending on the protocol, it may not be possible to
return a good value. In this case, an upper bound may
be returned (e.g.: When reading from a socket which
virtual void close(); ///< Close socket
/**< This override will automatically \c shutdown() the
socket whenever it is closed.
- \throws senf::SystemException
+ \throws senf::SystemException
\fixme Move into (at least) BSDSOcketProtocol */
-
+
virtual void terminate() const; ///< Forcibly close socket
/**< This override will automatically \c shutdown() the
socket whenever it is called. Additionally it will
disable SO_LINGER to ensure, that v_terminate will not
block. Like the overriden method, this member will ignore
failures and will never throw. It is therefore safe to be
- called from a destructor.
+ called from a destructor.
\fixme Move into (at least) BSDSocketProtocol */
virtual void state(SocketStateMap & map, unsigned lod) const;
\a lod value with a default value of 0. The
interpretation of the \a lod value is completely
implementation defined.
-
+
Every class derived from SocketProtocol should
reimplement state(). The reimplemented method should
call (all) baseclass-implementations of this
keys are interpreted as hierarchical strings with '.'
as a separator (like hostnames or struct or class
members). They are automatically sorted correctly.
-
+
The values are std:string with one additional feature:
they allow assignment or conversion from *any* type as
long as that type is streamable. This simplifies
assigning non-string values to the map:
-
+
\code
map["socket.protocol.ip.address"] << peer();
map["socket.protocol.tcp.backlog"] << backlog();
\endcode
-
+
This will work even if peer() returns an ip-address
object or backlog() returns an integer. The values are
automatically converted to their string representation.
-
+
Additionally, if the slot the date is written to is not
empty, the <tt>\<\<</tt> operator will add add a comma
as separator. */
friend class SocketBody;
};
-
+
template <class SPolicy> class ClientSocketHandle;
template <class SPolicy> class ServerSocketHandle;
protocols themselves, they are combined to build concrete protocols. This structure will
remove a lot of code duplication. It is important to ensure, that the protocol facets do not
overlap, since otherwise there will be problems resolving overlapping members.
-
+
\doc init_client init_server
*/
template <class SocketPolicy, class Self>
///////////////////////////////////////////////////////////////////////////
Policy const & policy() const;
-
+
protected:
- ClientSocketHandle<Policy> clientHandle() const;
+ ClientSocketHandle<Policy> clientHandle() const;
///< Get client handle for associated socket
/**< Returns a client handle for the socket associated with
this protocol instance */
// BOOST_CHECK( protocol.body() == 0 );
protocol.policy();
-
+
BOOST_CHECK( true );
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// Custom includes
#ifdef SENF_DEBUG
- #include <execinfo.h>
+ #include <execinfo.h>
#endif
#include <cxxabi.h>
#include <boost/regex.hpp>
#ifdef SENF_DEBUG
char ** symbols (::backtrace_symbols(backtrace, numEntries));
- static boost::regex const backtraceRx
+ static boost::regex const backtraceRx
("(.*)\\((.*)\\+(0x[0-9a-f]+)\\) \\[(0x[0-9a-f]+)\\]");
enum { File = 1,
Symbol = 2,
symbol = std::string(demangled);
free(demangled);
}
- os << " " << symbol << " + " << match[Offset]
+ os << " " << symbol << " + " << match[Offset]
<< "\n in " << match[File] << " [" << match[Address] << "]\n";
}
else if (sym == "[0xffffe410]")
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
prefix_ bool senf::console::detail::RestrictedExecutor::complete()
const
{
- return parsedNodes_.size() == 1
- && ! parsedNodes_[0].expired()
+ return parsedNodes_.size() == 1
+ && ! parsedNodes_[0].expired()
&& *parsedNodes_[0].lock() == executor_.chroot();
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
This bundle may also be passed to other code which may use restricted parsing to parse
partial information from all configuration sources.
-
+
\ingroup console_access
*/
class ConfigBundle
template <class Source>
Source & add(boost::intrusive_ptr<Source> source);
///< Add configuration source
-
+
void parse(); ///< Parse config bundle
/**< All nodes already parsed are skipped */
void parse(DirectoryNode & restrict); ///< Parse config bundle under \a restrict
protected:
template <class Source>
Source & add(boost::intrusive_ptr<Source> source);
-
+
private:
ConfigBundle bundle_;
};
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace detail {
/** \brief Internal: Executor wrapper implementing restricted execution
-
+
A RestrictedExecutor will only process commands which a re children of a given node. It does
\e not follow any links.
*/
void execute(std::ostream & output, ParseCommandInfo const & command);
///< Execute command
- /**< Output will be written to \a output.
+ /**< Output will be written to \a output.
Same as operator()(). */
void operator()(std::ostream & output, ParseCommandInfo const & command);
///< Execute command
- /**< Output will be written to \a output.
+ /**< Output will be written to \a output.
Same as execute(). */
GenericNode & getNode(ParseCommandInfo const & command);
};
/** \brief Internal: Set restricted node of a RestrictedExecutor
-
+
A RestrictGuard will set the node to which to restrict. It will automatically reset the node
in it's destructor.
*/
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
public:
TempFile(std::string const & name) : name_ (name), file_ (name_.c_str()) {}
~TempFile() { file_.close(); boost::filesystem::remove(name_); }
-
+
template <class T> TempFile & operator<<(T const & v) { file_ << v; return *this; }
enum Closer { close }; void operator<<(Closer) { file_.close(); }
std::string const & name() { return name_; }
std::string name_;
std::ofstream file_;
};
-
+
}
SENF_AUTO_UNIT_TEST(configBundle_empty)
{
TempFile cfg ("test.cfg");
cfg << TempFile::close;
-
+
senf::console::ScopedDirectory<> root;
root.add("fun2", senf::console::factory::Command(&fun2));
-
+
senf::console::ConfigBundle bundle(root);
bundle.add( senf::console::FileConfig(cfg.name()));
-
+
SENF_CHECK_NO_THROW( bundle.parse() );
}
SENF_CHECK_NO_THROW( bundle.parse() );
BOOST_CHECK_EQUAL( val1, "bar" );
BOOST_CHECK_EQUAL( val2, true );
-
+
bundle.chroot( chroot);
SENF_CHECK_NO_THROW( bundle.parse() );
BOOST_CHECK_EQUAL( val1, "bar" );
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
throw;
}
}
-#endif
+#endif
///////////////////////////////////////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
prefix_ senf::console::detail::ConfigFileSource::ConfigFileSource(std::string const & filename)
: filename_ (filename), ignoreMissing_ (false)
{}
-#endif
+#endif
///////////////////////////////////////////////////////////////////////////
// senf::console::ConfigFile
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// Parse only statements under the directory of some object. The object 'ob'
// must have been registered somewhere in the node tree
cf.parse(ob.dir);
-
+
// Parse rest of the config file
cf.parse();
\endcode
\ingroup console_access
*/
- class ConfigFile
+ class ConfigFile
: public detail::BundleMixin
{
public:
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
int var1 (0);
bool var2 (false);
-
+
void fun1(int v) { var1 = v; }
void fun2() { var2 = true; }
public:
TempFile(std::string const & name) : name_ (name), file_ (name_.c_str()) {}
~TempFile() { file_.close(); boost::filesystem::remove(name_); }
-
+
template <class T> TempFile & operator<<(T const & v) { file_ << v; return *this; }
enum Closer { close }; void operator<<(Closer) { file_.close(); }
std::string const & name() { return name_; }
std::string name_;
std::ofstream file_;
};
-
+
}
#define SENF_CHECK_THROW_SYSTEMEXCEPTION( expr, errorNumber, msg) \
BOOST_CHECK( ex.anyOf( errorNumber)); \
BOOST_CHECK( ex.message().find(msg) != std::string::npos); \
} \
-
+
SENF_AUTO_UNIT_TEST(configFile)
{
namespace fty = senf::console::factory;
TempFile cfgf ("test.cfg");
- cfgf << "dir1/fun1 10;\n"
+ cfgf << "dir1/fun1 10;\n"
<< TempFile::close;
-
+
senf::console::ScopedDirectory<> dir1;
senf::console::root().add("dir1", dir1);
dir1.add("fun1",fty::Command(&fun1));
cfgf << "dir1/fun1 10;\n"
<< "dir2/fun2;\n"
<< TempFile::close;
-
+
senf::console::ScopedDirectory<> dir1;
senf::console::root().add("dir1", dir1);
dir1.add("fun1",fty::Command(&fun1));
-
+
{
var1 = 0;
var2 = false;
cfgf << "dir1/fun1 10;\n"
<< "dir2 { dir3 { fun2; } fun1 5; }"
<< TempFile::close;
-
+
senf::console::ScopedDirectory<> dir1;
senf::console::root().add("dir1", dir1);
dir1.add("fun1",fty::Command(&fun1));
-
+
senf::console::ScopedDirectory<> dir2;
senf::console::root().add("dir2", dir2);
-
+
dir2.add("dir3",fty::Directory()).add("fun2", fty::Command(&fun2));
dir2.add("fun1", fty::Command(&fun1));
cfgf << "dir1/fun1 10;\n"
<< "link1 { dir3 { fun2; } fun1 5; }"
<< TempFile::close;
-
+
senf::console::ScopedDirectory<> dir1;
senf::console::root().add("dir1", dir1);
dir1.add("fun1",fty::Command(&fun1));
-
+
senf::console::ScopedDirectory<> dir2;
dir1.add("dir2", dir2);
-
+
dir2.add("dir3",fty::Directory()).add("fun2", fty::Command(&fun2));
dir2.add("fun1", fty::Command(&fun1));
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
built-in command at the console.
The next callback accesses the client instance directly to manipulate the logging:
-
+
\until }
The senf::console::Client instance can be accessed using the senf::console::Client::get() helper
messages to the console instance.
We now define \c main() which initializes the node tree and starts the console server
-
+
\until route
-
+
Here we just setup more verbose logging and set \c SIGPIPE signals to be ignored. \c SIGPIPE's
are a pain and really should be disabled.
-
+
\until settings
This shows, how to set the top-level documentation and create a new subdirectory.
directly. All the add commands return such a node reference of the correct type (this is a lie,
but it works like this anyways and it's an implementation detail that must not concern you
here).
-
+
Instead of creating a new directory directly and later sotring a reference, it is better to use
\c senf::console::ScopedDirectory<> like this:
\until functions
-
+
This will automatically remove the node from the tree when the \c senf::console::ScopedDirectory
instance is destroyed. It also protects against the problem of dangling references: When using a
plain reference, removing the directory from the tree will destroy the node. The reference
however will still reference the (now nonexistent) directory and any access via the reference
- will crash the program.
+ will crash the program.
The next statements add commands to the various directories declared so far
-
+
\until Example
We now continue by creating an instance of our test class \c TestObject
-
+
\until Example
We add that objects directory to the \c test dir. We now have created a directory structure like
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
return token.value();
}
};
-
+
}
///////////////////////////////////////////////////////////////////////////
try {
switch(command.builtin()) {
- case ParseCommandInfo::NoBuiltin :
+ case ParseCommandInfo::NoBuiltin :
if (skipping())
return;
exec(output, command);
"'cd' cannot be skipped (don't use 'cd' in conf-files)");
}
break;
-
+
case ParseCommandInfo::BuiltinLS :
if (skipping())
break;
else
exec(output, command);
break;
-
+
case ParseCommandInfo::BuiltinPOPD :
// The parser ensures, we have no arguments
popd();
break;
-
+
case ParseCommandInfo::BuiltinEXIT :
if (skipping())
break;
typedef std::map<senf::console::DirectoryNode*,std::string> NodesMap;
- void dolr(std::ostream & output, unsigned width, NodesMap & nodes, std::string const & base,
+ void dolr(std::ostream & output, unsigned width, NodesMap & nodes, std::string const & base,
unsigned level, senf::console::DirectoryNode & node)
{
boost::format fmt ("%s%s%s %|" BOOST_PP_STRINGIZE(HELP_COLUMN) "t|%s\n");
NodesMap::iterator j (nodes.find(&subnode));
if (j == nodes.end()) {
output << fmt
- % pad % i->first
+ % pad % i->first
% ( i->second->isDirectory() ? "/" : i->second->isLink() ? "@" : "" )
% i->second->shorthelp().substr(0,width);
std::string subbase (base);
nodes.insert(std::make_pair(&subnode, subbase));
dolr(output, width, nodes, subbase, level+1, subnode);
} else
- output << pad << i->first
+ output << pad << i->first
<< ( i->second->isDirectory() ? "/" : i->second->isLink() ? "@" : "" )
<< " -> " << j->second << "\n";
} else {
output << fmt
- % pad % i->first
+ % pad % i->first
% ( i->second->isDirectory() ? "/" : i->second->isLink() ? "@" : "" )
% i->second->shorthelp().substr(0,width);
}
traverseDirectory(path, dir);
DirectoryNode & node (*dir.back().lock());
NodesMap nodes;
- dolr(output, senf::console::Client::getWidth(output, 80u, 60u)-(HELP_COLUMN+1),
+ dolr(output, senf::console::Client::getWidth(output, 80u, 60u)-(HELP_COLUMN+1),
nodes, "", 0, node);
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// Types
/// Thrown by built-in 'exit' command
- struct ExitException {};
+ struct ExitException {};
/// Executor policy function
typedef boost::function<void (DirectoryNode &,std::string const &)> SecurityPolicy;
///////////////////////////////////////////////////////////////////////////
//\/name Structors and default members
///\{
-
+
Executor();
///\}
void execute(std::ostream & output, ParseCommandInfo const & command);
///< Execute command
- /**< Output will be written to \a output.
+ /**< Output will be written to \a output.
Same as operator()(). */
void operator()(std::ostream & output, ParseCommandInfo const & command);
///< Execute command
- /**< Output will be written to \a output.
+ /**< Output will be written to \a output.
Same as execute(). */
GenericNode & getNode(ParseCommandInfo const & command);
DirectoryNode & cwd() const; ///< Current working directory
DirectoryNode & chroot() const; ///< Get root node
/**< The root node defaults to senf::console::root(). If
changed, all path references are relative to this node
- and objects outside that tree cannot be accessed. */
+ and objects outside that tree cannot be accessed. */
Executor & chroot(DirectoryNode & node); ///< chroot into given directory
/**< After this call, all path's are interpreted relative to
std::string path;
InvalidPathException() : path() {}
InvalidPathException(std::string path_) : path(path_) {}
-
+
};
struct InvalidDirectoryException {
std::string path;
InvalidDirectoryException(std::string path_) : path(path_) {}
};
struct InvalidCommandException {};
-
+
DirectoryNode::ptr root_;
SecurityPolicy policy_;
mutable Path cwd_;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
senf::console::CommandParser parser;
BOOST_CHECK( &executor.cwd() == &senf::console::root() );
-
+
{
std::stringstream os;
parser.parse("cd dir1", &setCommand);
parser.parse("ll", &setCommand);
executor(os, commands.back());
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinLL );
- BOOST_CHECK_EQUAL( os.str(),
+ BOOST_CHECK_EQUAL( os.str(),
"dir1/ \n"
"dir2/ Helptext\n"
"sys/ \n" );
BOOST_CHECK_EQUAL( commands.back().builtin(), senf::console::ParseCommandInfo::BuiltinLS );
BOOST_CHECK_EQUAL( os.str(), "" );
}
-
+
{
std::stringstream os;
parser.parse("lr", &setCommand);
}
namespace {
-
+
void testPolicy(senf::console::DirectoryNode & dir, std::string const & entry)
{
if (dir == senf::console::root() && entry == "dir2")
BOOST_CHECK_EQUAL( executor.cwdPath(), "/dir2" );
BOOST_CHECK_EQUAL( os.str(), "" );
}
-
+
{
std::stringstream os;
parser.parse("t", &setCommand);
executor(os, commands.back());
BOOST_CHECK_EQUAL( os.str(), "testCommand\n" );
}
-
+
commands.clear();
senf::console::root().remove("tdir1");
senf::console::root().remove("dir2");
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
senf::membind(&LineEditorClientReader::deleteCharOrExit, this));
editor_.defineKey(senf::term::KeyParser::Tab,
boost::bind(&term::bindings::complete,
- _1,
+ _1,
senf::membind(&LineEditorClientReader::completePath, this)));
editor_.defineKey(senf::term::KeyParser::Return, &senf::term::bindings::acceptWithRepeat);
}
std::string const & t (editor.text());
// Search backward from e finding the longest valid path. This does *not* accept all valid
// path's, only those without embedded white-space. However, this is only for completion so
- // it's ok.
+ // it's ok.
if (b<e) {
unsigned bb (e-1);
for (;;) {
catch (CommandParser::ParserErrorException & ex) {
return;
}
-
+
ParseCommandInfo::TokensRange path (cmd.commandPath());
if (path.empty()) {
DirectoryNode::ChildrenRange cs (client().cwd().children());
completions.push_back(i->first + (i->second->followLink().isDirectory() ? "/" : " "));
return;
}
-
+
ParseCommandInfo::TokensRange::const_iterator i (path.begin());
ParseCommandInfo::TokensRange::const_iterator const i_end (boost::prior(path.end()));
DirectoryNode * dir (& client().cwd());
if (parent) dir = parent;
prefix += "../";
}
- else if (*i == WordToken("."))
+ else if (*i == WordToken("."))
prefix += "./";
else {
if (dir->hasChild(i->value())) {
return;
}
prefix += i->value() + "/";
- }
+ }
else {
DirectoryNode::ChildrenRange cs (dir->completions(i->value()));
if (has_one_elt(cs)) {
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace detail {
/** \brief Internal: Client reader switching between LineEditorClientReader or DumbClientReader
-
+
This ClientReader implementation will try to initialize a LineEditorClientReader. If the
setup fails, a DumbClientReader is initialized instead. LineEditor support may fail to be
initialized if
-
+
\li The telnet client does not support necessary functionality
\li or the terminal type of the client is missing some functionality.
*/
/** \brief Internal: ClientReader using senf::term::LineEditor for interactive input
- This ClientReader implementation uses a senf::term::LineEditor for interactive input.
+ This ClientReader implementation uses a senf::term::LineEditor for interactive input.
*/
class LineEditorClientReader
: public ClientReader, public term::TelnetTerminal
{
public:
explicit LineEditorClientReader(Client & client, LineEditorSwitcher & switcher);
-
+
private:
// TelnetTerminal API implementation
virtual void v_setupFailed();
// Editor callbacks
void executeLine(std::string const & text);
void deleteCharOrExit(term::LineEditor & editor);
- void completePath(term::LineEditor & editor, unsigned & b, unsigned & e,
+ void completePath(term::LineEditor & editor, unsigned & b, unsigned & e,
std::string & prefix, std::vector<std::string> & completions);
term::LineEditor editor_;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
nodes.
\li There exist several interfaces to \link console_access access\endlink entries in the node
tree: interactive console, reading configuration files etc.
-
+
The node tree works like a directory structure. Commands are entered into this directory
structure and can be called passing arbitrary arguments. Configuration parameters are just
commands which set their respective parameter, however the library allows commands to do much
</pre>
the console can be accessed easily via telnet:
-
+
<pre>
$ telnet localhost 23232
Trying 127.0.0.1...
and auxiliary commands. Parameters are just commands which set a parameter value so everything
is either a directory entry (senf::console::DirectoryNode) or a command
(senf::console::CommandNode).
-
+
\section intro_commands Implementing console/config commands
\seechapter \ref console_commands
To get more flexible, instantiate a senf::console::ConfigFile instance at use that to parse the
file
-
+
\code
senf::console::ConfigFile cf ("some.conf");
// The following line is optional: Call to ignore mussing files
commands.
\code
/server/port 1234;
-
+
/logger/targets/console {
accept senf::log::Debug IMPORTANT;
accept server::ServerLog CRITICAL;
\endcode
This registeres two short options and accumulates all non-option arguments in \c args.
-
+
If the application supports other configuration sources besides the command line options (like
configuration files) see \ref console_access_multiple and add a senf::console::OptionsConfig()
source to a senf::console::ConfigBundle.
Everything after the first '=' character is parsed into argument tokens using the normal
config/console parser. If the option has no '=' character, the list of argument tokens will be
empty.
-
+
<table style="font-size:80%" class="senf">
<tr><th>Command</th><th>File syntax</th><th>Option syntax</th></tr>
<td><tt>/path/to/doo john.doe@everywhere.org;</tt></td>
<td><tt>--path-to-doo="john.doe@everywhere.org"</tt></td>
</tr>
-
+
<tr>
<td><tt>void doo(std::string const &)</tt></td>
<td><tt>/path/to/doo "some test";</tt></td>
</pre>
which is the same as
-
+
<pre>
$ program --mycommand="2 3" --mycommand="4 5"
</pre>
- (Beware, that the second argument to \c alias() is \e not shell quoted).
+ (Beware, that the second argument to \c alias() is \e not shell quoted).
\subsection console_access_root Changing the root node
When used in it's default state, parsing will always interpret all commands relative to the
senf::console::root() node and will parse a file completely.
- The first possibility to control this is to change the root node. This is done by
+ The first possibility to control this is to change the root node. This is done by
\li passing that root node to the helper class or to the parse helper as an additional argument
(see the respective documentation).
\li passing it to the senf::console::ConfigBundle constructor when parsing multiple sources.
-
+
for example:
\code
// Open configuration file
senf::console::ConfigFile cf ("/etc/myserver.conf");
-
+
// Parse only commands in the configuration file which are in the foo.dir directory
cf.parse(foo.dir);
senf::console::ConfigBundle conf (senf::console::root()["config"]);
conf.add( senf::console::FileConfig("/etc/myserver.conf") );
conf.add( senf::console::FileConfig(".myserver.conf")->ignoreMissing() );
- conf.add( senf::console::OptionsConfig(senf::Daemon::instance().argc(),
+ conf.add( senf::console::OptionsConfig(senf::Daemon::instance().argc(),
senf::Daemon::instance().argv()) )
.nonOptions(args)
.alias('c', "--mycommand",true)
// Parse the logger subsystem commands in '/logger'
conf.parse(senf::console::root()['logger']);
-
+
...
// Parse all other configuration commands. All necessary commands and links in '/config' must by
- // now have been created.
+ // now have been created.
conf.parse();
\endcode
// You need to enter the scheduler main-loop for the server to work
senf::scheduler::process();
-
+
// Alternatively enter the main-loop via the PPI
// senf::ppi::run();
}
int main(int, char**)
{
senf::console::Server & server ( senf::console::start( ... ) );
-
+
// Do something ...
server.stop()
void someCallback(std::ostream & os, ... )
{
senf::console::Client & client (senf::console::Client::get(os));
-
+
// Use the client's log target
client.route<senf::log::Debug, senf::Log::IMPORTANT>();
}
\endcode
- \see
+ \see
senf::console::Server for the Server API \n
<a href="classsenf_1_1console_1_1Client-members.html">senf::console::Client / List of all
members</a> for the Client API
non-interactive mode. In this mode, no prompt is displayed. In this mode, commands are \e not
terminated automatically by end-of-line (CR). This allows, to easily cat an arbitrary
configuration file into the network console using netcat:
-
+
<pre>
$ nc -q1 localhost 23232 < some.conf
</pre>
</pre>
Commands are executed as soon as the terminating character (';', '{' or '}') is received or when
- the sending end of the connection is closed.
+ the sending end of the connection is closed.
\section console_udp Non-interactive UDP console
The UDP console allows to script the console tree via UDP packets. Every UDP packet must be a
complete command (or sequence of commands). The combined reply of all these commands will be
- returned in a single UDP packet. This reply can be disabled or directed to a different address.
+ returned in a single UDP packet. This reply can be disabled or directed to a different address.
To start a UDP server, just create an instance of the senf::console::UDPServer class
\code
os << value << std::endl;
}
\endcode
-
+
Registering this callback is done by simply adding it. To provide online help, pass it to
'doc()':
\code
href="http://www.boost.org/doc/libs/1_33_1/libs/range/doc/utility_class.html#iter_range">
boost::iterator_range</a> instances. These behave much like containers: They have \c begin() and
\c end() and some other useful members.
-
+
The parser will have divided the argument tokens into arguments already. This simplifies further
parsing. If however you want to access the list of argument tokens as a single list, you can do
so using senf::console::ParseCommandInfo::tokens().
-
+
Parsing arguments is quite simple but can get very tedious. To simplify this task, the parsing
can be delegated to the Console/config library. See the next section.
\section console_autoparse Automatic argument parsing
-
- To greatly simplify parsing complex commands, we turn to automatic argument parsing.
+
+ To greatly simplify parsing complex commands, we turn to automatic argument parsing.
\subsection console_autoadd Adding
.add("over", SENF_FNP(void, over, (int)));
senf::console::root()
.add("over", SENF_FNP(void, over, (int,int));
-
+
class SomeModule {
senf::console::ScopedDirectory<SomeModule> dir;
-
+
unsigned int overlodedMethod() const {....};
void overlodedMethod(unsigned int) {....};
-
+
void addConsoleCommands() {
- dir.node().add("overlodedMethod",
+ dir.node().add("overlodedMethod",
SENF_MEMBINDFNP(unsigned int, SomeModule, overlodedMethod, () const));
- dir.node().add("overlodedMethod",
+ dir.node().add("overlodedMethod",
SENF_MEMBINDFNP(unsigned int, SomeModule, overlodedMethod, (unsigned int));
}
}
\subsection console_attributes Attributes
As have seen so far, some documentation is automatically provided. We can add more info, by
- setting additional attributes.
+ setting additional attributes.
\code
senf::console::root()
.add("test5", &fun3)
Variant 1:
Repeat {arg12} for {arg11} lines
-
+
Variant 2:
Echo the {arg21} argument
senf:/$
Variant 1:
Repeat {text} for {n} lines
-
+
Variant 2:
Echo the {text} argument
senf:/$
.overloadDoc("Echo the <text> argument")
.arg("text");
\endcode
-
+
Keyword arguments should always be used if additional attributes are set. You can however mix
positional and keyword arguments.
-
+
\subsection console_defaults Default values
-
+
Another information which can not be automatically gathered from the type system is default
values. These have to be declared explicitly:
\code
flexible, it is not mandatory, for default values to be specified only for the trailing
arguments. For the exact definition, how parsed argument values are assigned to overload
arguments in the presence of default values, see \ref senf::console::kw::default_value.
-
+
\htmlonly
<pre>
server:/$ test7 echo
server:/$ help test7
Usage:
test4 [n:unsigned] text:string
-
+
With:
n Number of repetitions
default: 1
\code
senf::console::root()
- .add("test8",
+ .add("test8",
boost::function<void (std::ostream &, std::string const &)>(
boost::bind(&fun3, _1, 4u, _2)));
\endcode
This works with any callable object where argument types cannot be deduced automatically:
Boost.Bind expressions, Boost.Lambda expressions, functors and so on.
-
+
\htmlonly
<pre>
server:/$ test8 ok
<tr><td style="width:14em">\link senf::console::ParsedArgumentAttributorBase::doc() .doc\endlink
( \e doc )</td><td>Set documentation for all overloads</td></tr>
-
+
<tr><td>\link senf::console::ParsedArgumentAttributorBase::overloadDoc()
.overloadDoc\endlink ( \e doc )</td><td>Set documentation for a specific overload</td></tr>
</table>
The most important argument attributes (all defined in the senf::console::kw namespace) are:
-
+
<table class="senf fixed width">
<tr><td style="width:14em">\link senf::console::kw::name kw::name\endlink</td><td>Parameter
/ List of all members</a> for the complete attribute interface \n
\ref senf::console::kw for a list of all argument attribute keywords
-
+
\section console_memberfn Member functions
-
+
Non-static member functions are supported like non-member functions (static member functions are
identical to non-members). They must however be added through a senf::console::ScopedDirectory
instance to bind them to their instance.
public:
senf::console::ScopedDirectory<Test1> dir;
- Test1(std::string label) : dir(this), label_ (label)
+ Test1(std::string label) : dir(this), label_ (label)
{ dir.add("test", &Test::test1);
dir.add("test", &Test::test2); }
-
+
std::string test1(std::string const & text)
{ return label_ + ": " + text; }
- void test2(std::ostream & os, unsigned n, std::string const & text)
+ void test2(std::ostream & os, unsigned n, std::string const & text)
{ while (n-- > 0) os << label << ": " << text << std::endl; }
private:
\section console_variables Variables
-
+
\subsection console_varadd Adding
The console/config library supports the direct registration of variables as commands. A
variable command consists of two overloads, one to query the current value and one to change the
- value.
+ value.
\code
class Test2
{
\subsection console_varro Read-only variables
-
+
The library also supports read-only variables. To make a variable read-only, just wrap it in \c
boost::cref() (where \c cref stands for \c const reference)
\code
server:/$ help var1
Usage:
var1
- server:/$
+ server:/$
</pre>
\endhtmlonly
<tr><td style="width:14em">\link senf::console::VariableAttributor::doc() .doc\endlink
( \e doc )</td><td>Set variable documentation</td></tr>
-
+
<tr><td>\link senf::console::VariableAttributor::onChange() .onChange\endlink
( \e handler )</td><td>Set change handler</td></tr>
-
+
</table>
\see senf::console::VariableAttributor for the complete attribute interface
senf::console::root().add("var2",var)
.onChange(&varChanged);
\endcode
-
+
After this setup, \c varChanged will be called, whenever the value has changed.
\section console_args Console library supported types
- By default, types which can be read and written using \c iostreams are automatically supported.
+ By default, types which can be read and written using \c iostreams are automatically supported.
This includes all the C++ built-in types as well as user defined streamable types.
An exception is made for all \c char types: These types are by default parsed as \e numeric
<pre>
()
</pre>
-
+
Collection's with only one element may skip the parenthesis <em>if and only if</em> the element
type does not need additional parenthesis
A \c vector, \c list or \c set of integer with one element may be written with or without
parenthesis:
<pre>
- (1)
+ (1)
1
</pre>
<pre>
(foo=1 bar=2 "foo bar"=3)
</pre>
-
+
\subsection console_args_bool Boolean arguments and return values
The console library by default formats boolean values using the strings \c true and \c false for
their representation. When parsing a boolean value, most sensible representations will be
accepted:
-
+
<table class="senf">
<tr><td>\c true</td> <td>\c false</td> <td>\ref senf::console::formatTrueFalse</td></tr>
<tr><td>\c on</td> <td>\c off</td> <td>\ref senf::console::formatOnOff</td></tr>
The last column lists explicit formatters which can be set to customize the return value
formatting of a registered overload accordingly.
-
+
\subsection console_args_enum Registering enum types
Enum types are a special case, since it is not possible, to find a string representation for the
{
public:
enum Color { Red, Green, Blue };
-
+
senf::console::ScopedDirectory<Test3> dir;
Test3();
Test3::Test3() : dir(this)
{ dir.add("test", &Test3::mem3); }
-
+
Test3 test3ob;
senf::console::root().add("test3ob", test3ob.dir);
\endcode
{
return value;
}
-
+
senf::console::root()
.add("test8", boost::function<bool (bool)>(&fun4));
\endcode
-
+
Here, the type signature specified via \c boost::function is different from the real type
signature but is compatible. \c boost::function automatically handles the conversion
process. Since the console library now sees the argument and return value of type \c bool,
the values will be parsed and formatted as boolean values.
-
+
\subsection console_args_special Special Console types
The %console library defines some special types to be used as arguments and/or return values.
{
os << '(' << value.x << ' ' << value.y << ')';
}
- \endcode
+ \endcode
The parser will accept an argument with two tokens which are each forwarded to the integer
parser. The senf::console::CheckedArgumentIteratorWrapper ensures two things: That all input
\code
Coordinate fun5(Coordinate const & p) { return Coordinate(2*p.x, 2*p.y) }
-
+
namespace kw = senf::console::kw;
senf::console::root()
server:/$
</pre>
\endhtmlonly
-
+
If you want to customize the formatting of default values differently from the formating of
return-values or if you want to change the displayed name of a type, you will need to specialize
the senf::console::ArgumentTraits class instead of implementing
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
output << "/\n";
dodump(output, level+1,static_cast<senf::console::DirectoryNode&>(*i->second));
}
- else if (i->second->isLink())
+ else if (i->second->isLink())
output << "@ -> " << i->second->followLink().path() << '\n';
else
output << '\n';
senf::console::DirectoryNode::remove(std::string const & name)
{
ChildMap::iterator i (children_.find(name));
- if (i == children_.end())
+ if (i == children_.end())
throw UnknownNodeNameException() << ": '" << name << "'";
GenericNode::ptr node (i->second);
children_.erase(i);
++suffix;
newName = node->name() + "-" + boost::lexical_cast<std::string>(suffix);
} while (children_.find(newName) != children_.end());
- SENF_LOG((senf::log::MESSAGE)("Uniquifying node '" << node->name() << "' to '"
+ SENF_LOG((senf::log::MESSAGE)("Uniquifying node '" << node->name() << "' to '"
<< newName << "'"));
node->name(newName);
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
Recursively dumps the console directory structure starting at \a dir. By default, dumps the
complete tree beginning at the root node.
-
+
In contrast to the console 'lr' command, links are dumped by showing the \e absolute path
to the target node.
*/
\param[in] command command arguments. This is a
range of ranges of Token instances. */
- void execute(boost::any & rv, std::ostream & output, ParseCommandInfo const & command)
+ void execute(boost::any & rv, std::ostream & output, ParseCommandInfo const & command)
const;
///< Execute the command
/**< \param[out] rv command return value
#ifndef DOXYGEN
namespace factory {
-
+
class SimpleCommand
: public detail::NodeFactory
{
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
public:
NodeTraverser(DirectoryNode & root, DirectoryNode & dir, bool autocomplete);
-
+
void operator()(std::string const & name);
-
+
GenericNode & node();
-
+
private:
DirectoryNode & root_;
DirectoryNode::ptr dir_;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
std::stringstream ss;
node.help(ss);
BOOST_CHECK_EQUAL( ss.str(), "help info\n" );
-
+
{
senf::console::GenericNode::ptr p (senf::console::root()["dir1"].unlink());
BOOST_CHECK( ! node.active() );
BOOST_CHECK_THROW( senf::console::root()("fn2"), senf::console::UnknownNodeNameException );
BOOST_CHECK_THROW( senf::console::root()["fn"], std::bad_cast );
BOOST_CHECK( &senf::console::root().get("dir1") == p.get() );
-
+
senf::console::root()
.add("dir2", fty::Directory())
.add("dir3", fty::Directory());
char const * const children[] = { "dir1", "dir2", "fn", "sys" };
- BOOST_CHECK_EQUAL_COLLECTIONS(
- boost::make_transform_iterator(senf::console::root().children().begin(),
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ boost::make_transform_iterator(senf::console::root().children().begin(),
select1st<std::string const &>()),
boost::make_transform_iterator(senf::console::root().children().end(),
select1st<std::string const &>()),
- children,
+ children,
children+sizeof(children)/sizeof(children[0]) );
char const * const completions[] = { "dir1", "dir2" };
BOOST_CHECK_EQUAL_COLLECTIONS(
- boost::make_transform_iterator(senf::console::root().completions("dir").begin(),
+ boost::make_transform_iterator(senf::console::root().completions("dir").begin(),
select1st<std::string const &>()),
boost::make_transform_iterator(senf::console::root().completions("dir").end(),
select1st<std::string const &>()),
- completions,
+ completions,
completions+sizeof(completions)/sizeof(completions[0]) );
p->doc("test doc\nline 2");
senf::console::root().add("fn1", fty::SimpleCommand(&callback));
senf::console::root().add("fn2", fty::SimpleCommand(Functor()));
-
+
senf::console::ParseCommandInfo info;
{
senf::console::root()("fn2")(ss, info);
BOOST_CHECK_EQUAL( ss.str(), "functor" );
}
-
+
senf::console::root().remove("fn1");
senf::console::root().remove("fn2");
}
senf::console::root()("fn")(ss, info);
BOOST_CHECK_EQUAL( ss.str(), "callback" );
}
-
+
{
std::stringstream ss;
senf::console::root().get("fn").help(ss);
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// default: 1.23
// arg3 - arg3-doc
//
-// Generic documentation foo blalsdljfl laj flkajslkjs fdlkj oiwlksdj ;llkaj
+// Generic documentation foo blalsdljfl laj flkajslkjs fdlkj oiwlksdj ;llkaj
// sdflkja sldkfjslkdfj sdlkfj lskjdf lskjdf lksj dflkj lsdkfj lskdjf lskjkd
-// Generic documentation foo blalsdljfl laj flkajslkjs fdlkj oiwlksdj ;llkaj
+// Generic documentation foo blalsdljfl laj flkajslkjs fdlkj oiwlksdj ;llkaj
// sdflkja sldkfjslkdfj sdlkfj lskjdf lskjdf lksj dflkj lsdkfj lskdjf lskjkd
-// Generic documentation foo blalsdljfl laj flkajslkjs fdlkj oiwlksdj ;llkaj
+// Generic documentation foo blalsdljfl laj flkajslkjs fdlkj oiwlksdj ;llkaj
// sdflkja sldkfjslkdfj sdlkfj lskjdf lskjdf lksj dflkj lsdkfj lskdjf lskjkd
//
-// Variant 1:
+// Variant 1:
// Variant 1 doc la;ksjf lkj sdlkfj lkjekj sdflkj ekljsdlkfj wlej
// slkj dkj sldkfj lwekljsdf skldjf lskjdf l jsd
//
//
// Variatn 3:
// Variant 3 doc slkjflw ekj lskdfj lskdjf laksdj flksj elkj aldskjf lwkejlksdj
-// ldkfaj wlekj slkdfj lskdjf lwkejlkasdjf
+// ldkfaj wlekj slkdfj lskdjf lwkejlkasdjf
prefix_ void senf::console::OverloadedCommandNode::v_help(std::ostream & os)
const
ArgumentDocs::const_iterator const i_end (argumentDocs.end());
for (; i != i_end; ++i) {
if (! i->doc.empty() || ! i->defaultValue.empty()) {
- os << " "
- << i->name
+ os << " "
+ << i->name
<< std::string(i->name.length()<8 ? 8-i->name.length() : 0, ' ')
<< " "
<< i->doc
}
}
}
-
+
if (! doc_.empty())
os << "\n" << doc_ << "\n";
-
+
{
Overloads::const_iterator i (overloads_.begin());
Overloads::const_iterator const i_end (overloads_.end());
Overloads::const_iterator const i_end (overloads_.end());
for (; i != i_end; ++i) {
std::string overloadDoc ((*i)->doc());
- if (! overloadDoc.empty())
+ if (! overloadDoc.empty())
return overloadDoc.substr(0,overloadDoc.find('\n'));
}
return "";
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
prefix_ unsigned
senf::console::OverloadedCommandNode::overloadIndex(CommandOverload const & overload)
{
- return find(overloads_.begin(), overloads_.end(), CommandOverload::cptr(&overload))
+ return find(overloads_.begin(), overloads_.end(), CommandOverload::cptr(&overload))
- overloads_.begin() + 1;
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
void execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command);
///< Call the overload
/**< If the \a arguments are not acceptable for this
- overload, a SyntaxErrorException must be thrown.
+ overload, a SyntaxErrorException must be thrown.
Same as operator()() */
void operator()(boost::any & rv, std::ostream & os, ParseCommandInfo const & command);
///< Call the overload
/**< If the \a arguments are not acceptable for this
- overload, a SyntaxErrorException must be thrown.
+ overload, a SyntaxErrorException must be thrown.
Same as execute() */
-
+
unsigned numArguments() const; ///< Number of arguments this overload takes
void argumentDoc(unsigned index, ArgumentDoc & doc) const;
///< Get information on argument \a index
\param[out] doc Argument documentation */
std::string doc() const; ///< Get overload documentation
-
+
OverloadedCommandNode & node() const; ///< Access owning node
/**< \pre The command \e must have been added to an
OverloadedCommandNode. */
'SyntaxErrorException' exception is thrown.
This works by first adding an OverloadedCommandNode to the directory in question and then
- adding commands to that node. Commands are derived from CommandOverload.
+ adding commands to that node. Commands are derived from CommandOverload.
\code
senf::console::DirectoryNode & dir (...);
senf::console::OverloadedCommandNode & cmd (
///@}
///////////////////////////////////////////////////////////////////////////
-
+
template <class Command>
Command & add(boost::intrusive_ptr<Command> overload); ///< Add an additional overload
/** \brief Basic command overload
This is an implementation of CommandOverload which allows to call an arbitrary callback with
- the correct signature
+ the correct signature
(<tt>void (std::ostream &, senf::console::ParseCommandInfo const &)</tt>)
*/
class SimpleCommandOverload
SimpleOverloadAttributor const & overloadDoc(std::string const & doc) const;
OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
-
+
private:
SimpleCommandOverload::ptr overload_;
mutable boost::optional<std::string> doc_;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
std::stringstream ss;
BOOST_CHECK_THROW( senf::console::root()("overload")(ss, info),
senf::console::SyntaxErrorException );
-
+
cmd.add(senf::console::SimpleCommandOverload::create(&fn3)).doc("fn3");
SENF_CHECK_NO_THROW( senf::console::root()("overload")(ss, info) );
BOOST_CHECK_EQUAL( ss.str(), "fn3\n" );
}
-
+
{
std::stringstream ss;
cmd.help(ss);
- BOOST_CHECK_EQUAL( ss.str(),
- "Usage:\n"
+ BOOST_CHECK_EQUAL( ss.str(),
+ "Usage:\n"
" 1- overload ...\n"
" 2- overload ...\n"
" 3- overload ...\n"
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
void popDirectory()
{ info_->clear();
info_->builtin(ParseCommandInfo::BuiltinPOPD); }
-
+
void builtin_exit()
{ info_->clear();
info_->builtin(ParseCommandInfo::BuiltinEXIT); }
"Word" };
// The real table is:
// static const int bitPosition[32] = {
- // 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
+ // 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
// 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 };
// However, we have replaced all values >= sizeof(tokenTypeName) with 0
// and have added 1 to all the remaining values
static const int bitPosition[32] = {
- 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 5, 9,
+ 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 5, 9,
0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 7, 0, 6, 0, 10 };
// We need to check token.type() against 0 explicitly since 0 and 1 will both be mapped to 0
- os << tokenTypeName[ token.type()
+ os << tokenTypeName[ token.type()
? bitPosition[(((token.type() & -token.type()) * 0x077CB531UL) >> 27) & 31]
: 0 ]
<< "('"
char const * builtins[] = { 0, "cd", "ls", "lr", "pushd", "popd", "exit", "help" };
stream << "builtin-" << builtins[info.builtin()];
}
-
+
ParseCommandInfo::ArgumentsRange args (info.arguments());
for (ParseCommandInfo::argument_iterator i (args.begin()); i != args.end(); ++i) {
ParseCommandInfo::token_iterator j (i->begin());
#endif
namespace {
-
+
template <class Error>
- void throwParserError(Error const & err)
+ void throwParserError(Error const & err)
{
static char const * msg [] = { "end of statement expected",
"path expected",
}
-namespace boost {
+namespace boost {
namespace spirit {
template <>
// we would need to expose the Impl member to the public, which we don't want to do.
template <class Iterator>
-prefix_ Iterator senf::console::CommandParser::parseLoop(Iterator npb, Iterator npe,
+prefix_ Iterator senf::console::CommandParser::parseLoop(Iterator npb, Iterator npe,
std::string const & source, Callback cb)
{
typedef boost::spirit::position_iterator<
result = boost::spirit::parse(
b, e, * impl().grammar.use_parser<Impl::Grammar::SkipParser>());
b = result.stop;
- if (b == e)
+ if (b == e)
return e.base();
info.clear();
try {
}
// Otherwise the error handling in the parser is broken
SENF_ASSERT( result.hit );
- if (! info.empty())
+ if (! info.empty())
try {
cb(info);
}
prefix_ void senf::console::CommandParser::parseFile(std::string const & filename, Callback cb)
{
- // file_iterator sets errno to EINVAL and returns error when file size is 0
- // so we check the file size before
- struct stat statBuf;
+ // file_iterator sets errno to EINVAL and returns error when file size is 0
+ // so we check the file size before
+ struct stat statBuf;
if (stat( filename.c_str(), &statBuf) != 0)
throw SystemException(filename, errno SENF_EXC_DEBUGINFO);
if (statBuf.st_size == 0) return;
if (!i) {
if (errno == 0)
// hmm.. errno==0 but the file_iterator is false; something is wrong but we
- // do not know what exactly, so we throw a SystemeException with EINVAL
+ // do not know what exactly, so we throw a SystemeException with EINVAL
throw SystemException(filename, EINVAL SENF_EXC_DEBUGINFO);
else
throw SystemException(filename, errno SENF_EXC_DEBUGINFO);
detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info);
boost::spirit::parse_info<PositionIterator> result;
try {
- result = boost::spirit::parse( b, e,
+ result = boost::spirit::parse( b, e,
impl().grammar.use_parser<Impl::Grammar::ArgumentsParser>(),
impl().grammar.use_parser<Impl::Grammar::SkipParser>() );
}
detail::ParseDispatcher::BindInfo bind (impl().dispatcher, info);
boost::spirit::parse_info<PositionIterator> result;
try {
- result = boost::spirit::parse( b, e,
+ result = boost::spirit::parse( b, e,
impl().grammar.use_parser<Impl::Grammar::PathParser>(),
impl().grammar.use_parser<Impl::Grammar::SkipParser>() );
}
senf::console::CommandParser::parseIncremental(std::string const & commands, Callback cb)
{
SetIncremental si (*this);
- return std::distance( commands.begin(),
+ return std::distance( commands.begin(),
parseLoop(commands.begin(), commands.end(), "<unknown>", cb) );
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
const
{
if (b_ == e_) setRange();
- return b_->is(Token::ArgumentGroupOpen)
+ return b_->is(Token::ArgumentGroupOpen)
? boost::make_iterator_range(boost::next(b_), boost::prior(e_))
: boost::make_iterator_range(b_, e_);
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
configuration file
\code
# My someserver configuration file
-
+
/server/port 1234;
-
+
/logger/targets {
console {
accept senf::log::Debug IMPORTANT;
These are characters, which have a special meaning. Some are used internally, others are just
returned as punctuation tokens
-
+
<table class="senf">
<tr><td>#</td><td>Comments are marked with '#' and continue to the end of the line</td></tr>
<tr><td>/</td><td>path component separator</td></tr>
"\"foo\nbar\""
"\x04test"
</pre>
-
+
A <b>hex-string literal</b> is used to represent binary data. It looks like a string which has
only hexadecimal bytes or whitespace as contents (comments and newlines are Ok when not read
from the interactive console)
</pre>
\subsection console_statements Statements
-
+
There are several types of statements:
\li The bulk of all statements are \e path statements
\li There are some \e built-in statements which are mostly useful at the interactive console
is completely up to the command.
A <b>built-in</b> statement is one of
-
+
<table class="senf">
<tr><td>\c cd \e path</td><td>Change current directory</td></tr>
<tr><td>\c ls [ \e path ]</td><td>List contents of \e path or current directory</td></tr>
/** \brief Single argument token
All command arguments are split into tokens by the parser. Each token is returned as an
- Token instance.
+ Token instance.
\ingroup console_parser
*/
class Token
{
public:
- enum TokenType {
+ enum TokenType {
None = 0,
PathSeparator = 0x0001, // '/'
ArgumentGroupOpen = 0x0002, // '('
};
enum TokenGroup {
- ArgumentGrouper = ArgumentGroupOpen
+ ArgumentGrouper = ArgumentGroupOpen
| ArgumentGroupClose,
- DirectoryGrouper = DirectoryGroupOpen
+ DirectoryGrouper = DirectoryGroupOpen
| DirectoryGroupClose,
- Punctuation = DirectoryGroupOpen
- | DirectoryGroupClose
- | PathSeparator
- | CommandTerminator
+ Punctuation = DirectoryGroupOpen
+ | DirectoryGroupClose
+ | PathSeparator
+ | CommandTerminator
| OtherPunctuation,
- String = BasicString
+ String = BasicString
| HexString,
- SimpleArgument = Word
- | BasicString
+ SimpleArgument = Word
+ | BasicString
| HexString
};
-
+
Token(); ///< Create empty token
- Token(TokenType type, std::string token);
+ Token(TokenType type, std::string token);
///< Create token with given type and value
- Token(TokenType type, std::string token, detail::FilePositionWithIndex const & pos);
+ Token(TokenType type, std::string token, detail::FilePositionWithIndex const & pos);
///< Create token with given type and value
Every command parsed is returned in a ParseCommandInfo instance. This information is purely
taken from the parser, no semantic information is attached at this point, the config/console
node tree is not involved in any way. ParseCommandInfo consist of
-
+
\li the type of command: built-in or normal command represented by a possibly relative path
into the command tree.
\li the command
typedef std::vector<std::string> CommandPath;
public:
- class ArgumentIterator;
+ class ArgumentIterator;
typedef CommandPath::const_iterator path_iterator;
typedef Tokens::const_iterator token_iterator;
typedef boost::iterator_range<argument_iterator> ArgumentsRange;
typedef boost::iterator_range<token_iterator> TokensRange;
- enum BuiltinCommand { NoBuiltin,
- BuiltinCD,
- BuiltinLS,
+ enum BuiltinCommand { NoBuiltin,
+ BuiltinCD,
+ BuiltinLS,
BuiltinLL,
BuiltinLR,
- BuiltinPUSHD,
+ BuiltinPUSHD,
BuiltinPOPD,
BuiltinEXIT,
BuiltinHELP };
void clear(); ///< Clear all data members
bool empty(); ///< \c true, if the data is empty
- void builtin(BuiltinCommand builtin); ///< Assign builtin command
+ void builtin(BuiltinCommand builtin); ///< Assign builtin command
void command(std::vector<Token> & commandPath); ///< Assign non-builtin command
void addToken(Token const & token); ///< Add argument token
This iterator is a bidirectional iterator \e not a random access iterator.
*/
class ParseCommandInfo::ArgumentIterator
- : public boost::iterator_facade< ParseCommandInfo::ArgumentIterator,
+ : public boost::iterator_facade< ParseCommandInfo::ArgumentIterator,
ParseCommandInfo::TokensRange,
boost::bidirectional_traversal_tag,
ParseCommandInfo::TokensRange >
of SyntaxErrorException. This is important, so command overloading works.
*/
struct SyntaxErrorException : public senf::Exception
- { explicit SyntaxErrorException(std::string const & msg = "syntax error")
+ { explicit SyntaxErrorException(std::string const & msg = "syntax error")
: senf::Exception(msg) {} };
/** \brief Wrapper checking argument iterator access for validity
-
+
CheckedArgumentIteratorWrapper is a wrapper around a range of arguments parsed using the
ParseCommandInfo::ArgumentIterator. It is used to parse arguments either in a command
(registered with manual argument parsing) or when defining a custom parser.
{
std:;string arg1;
unsigned arg2 (0);
-
+
{
senf::console::CheckedArgumentIteratorWrapper arg (command.arguments());
senf::console::parse( *(arg++), arg1 );
\li You increment the iterator \e past all arguments you parse. The iterator must point to
the end of the range when parsing is complete.
\li The iterator wrapper is destroyed after parsing but before executing the command itself
- begins.
+ begins.
Accessing a non-existent argument or failing to parse all arguments will raise a
senf::console::SyntaxErrorException.
std::string const & msg = "invalid number of arguments");
///< Make wrapper from ArgumentsRange
/**< This constructs a wrapper from a
- ParseCommandInfo::ArgumentsRange.
+ ParseCommandInfo::ArgumentsRange.
\param[in] range Range of arguments to parse
\param[in] msg Error message */
explicit CheckedArgumentIteratorWrapper(
SyntaxErrorException, if not all arguments are parsed
and when no other exception is in progress. */
- operator ParseCommandInfo::ArgumentIterator();
+ operator ParseCommandInfo::ArgumentIterator();
///< Use wrapper as ParseCommandInfo::ArgumentIterator
bool boolean_test() const; ///< \c true, if more arguments are available
///< Compare wrapper against ArgumentIterator
bool operator!=(ParseCommandInfo::ArgumentIterator const & other) const;
///< Compare wrapper against ArgumentIterator
-
+
using IteratorFacade::operator++;
ParseCommandInfo::ArgumentIterator operator++(int);
/**< An incremental parse will parse all complete statements
in \a commands. parseIncremental() will return the
number of characters successfully parsed from \a
- commands.
-
+ commands.
+
\note The incremental parser \e requires all statements
to be terminated explicitly. This means, that the
last ';' is \e not optional in this case. */
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
#ifndef DOXYGEN
- struct FilePositionWithIndex
+ struct FilePositionWithIndex
: public boost::spirit::file_position
{
int index;
-
+
FilePositionWithIndex(std::string const & file_ = std::string(),
int line_ = 1, int column_ = 1, int index_ = 0)
: boost::spirit::file_position (file_, line_, column_), index (index_)
bool operator==(const FilePositionWithIndex & fp) const
{
- return boost::spirit::file_position::operator==(fp) && index == fp.index;
+ return boost::spirit::file_position::operator==(fp) && index == fp.index;
}
};
//////////////////////////////////////////////////////////////////////////
// charachter sets
-
+
static boost::spirit::chset<> special_p;
static boost::spirit::chset<> punctuation_p;
static boost::spirit::chset<> space_p;
///////////////////////////////////////////////////////////////////////////
- CommandGrammar(ParseDispatcher & d, Context & c)
+ CommandGrammar(ParseDispatcher & d, Context & c)
: context(c), incremental(false), dispatcher(d) {}
template <class Scanner>
- struct definition
- : public boost::spirit::grammar_def< boost::spirit::rule<Scanner>,
+ struct definition
+ : public boost::spirit::grammar_def< boost::spirit::rule<Scanner>,
boost::spirit::rule<Scanner>,
boost::spirit::rule<Scanner>,
boost::spirit::rule<Scanner> >
{
boost::spirit::rule<Scanner> command, path, argument, word, string, hexstring, token,
- punctuation, hexbyte, balanced_tokens, simple_argument, complex_argument, builtin,
- skip, statement, relpath, abspath, arguments, group_start, group_close,
+ punctuation, hexbyte, balanced_tokens, simple_argument, complex_argument, builtin,
+ skip, statement, relpath, abspath, arguments, group_start, group_close,
statement_end, opt_path;
definition(CommandGrammar const & self)
// Beside this, we use some special parsers (ch_p, eps_p, confix_p, lex_escape_ch_p,
// keyword_p, comment_p) and directives (lexeme_d), however, the parser should be
// quite readable.
- //
+ //
// ch_p match character
// eps_p always matches nothing (to attach unconditional actions)
// confix_p(a,b,c) match b, preceded by a and terminated by c. Used to parse
//
// More info is in the Boost.Spirit documentation
- command
+ command
= builtin >> end_of_statement_expected(statement_end)
| group_close
| ch_p(';') // Ignore empty commands
statement
= path_expected(path) [ bind(&PD::beginCommand)(d_, path_) ]
>> arguments
- >> end_of_statement_expected(
+ >> end_of_statement_expected(
( group_start | statement_end )
[ bind(&PD::endCommand)(d_) ]
)
;
builtin
- = self.keyword_p("cd")
+ = self.keyword_p("cd")
>> path_expected(path)
>> eps_p [ bind(&PD::builtin_cd)(d_, path_) ]
| self.keyword_p("ls")
= simple_argument [ bind(&PD::pushToken)(d_, token_) ]
| balanced_tokens
;
-
+
simple_argument // All these return their value in context.token
= string
| hexstring
| word
;
-
+
string // Returns value in context.token
= eps_p [ pos_ = positionOf(arg1) ][ clear(str_) ]
>> lexeme_d
[
ch_p('"')
- >> * ( ( lex_escape_ch_p[ ch_ = arg1 ]
- - '"'
+ >> * ( ( lex_escape_ch_p[ ch_ = arg1 ]
+ - '"'
) [ str_ += ch_ ]
)
>> quote_expected(ch_p('"'))
- [ token_ = construct_<Token>(Token::BasicString,
+ [ token_ = construct_<Token>(Token::BasicString,
str_,
pos_) ]
]
str_,
pos_) ]
;
-
+
opt_path
= ! path [ bind(&PD::beginCommand)(d_, path_) ]
[ bind(&PD::endCommand)(d_) ]
| eps_p [ push_back(path_, construct_<Token>()) ] )
;
- balanced_tokens
+ balanced_tokens
= eps_p [ pos_ = positionOf(arg1) ]
>> ch_p('(') [ token_ = construct_<Token>(
Token::ArgumentGroupOpen,
(+ self.word_p) [ str_ = construct_<std::string>(arg1, arg2) ]
]
>> eps_p [ token_ = construct_<Token>(
- Token::Word,
+ Token::Word,
str_,
pos_) ]
;
ch_p(';')
]
.else_p [
- ch_p(';')
+ ch_p(';')
| end_p
]
;
",=");
template <class PD> boost::spirit::chset<> CommandGrammar<PD>::space_p (
" \t\n\r");
- template <class PD> boost::spirit::chset<> CommandGrammar<PD>::invalid_p (
+ template <class PD> boost::spirit::chset<> CommandGrammar<PD>::invalid_p (
(boost::spirit::chset<>('\0') | boost::spirit::chset<>("\x01-\x20")) - space_p );
template <class PD> boost::spirit::chset<> CommandGrammar<PD>::word_p (
boost::spirit::anychar_p - special_p - punctuation_p - space_p - invalid_p);
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-namespace
+namespace
{
- struct TestParseDispatcher
+ struct TestParseDispatcher
{
TestParseDispatcher(std::ostream & os) : os_ (os) {}
void popDirectory()
{ os_ << "popDirectory()\n"; }
- void beginCommand(std::vector<senf::console::Token> const & command)
+ void beginCommand(std::vector<senf::console::Token> const & command)
{ os_ << "beginCommand( " << senf::stringJoin(command, "/") << " )\n"; }
- void endCommand()
+ void endCommand()
{ os_ << "endCommand()\n"; }
-
+
void pushToken(senf::console::Token token)
{ os_ << "pushToken( " << token << " )\n"; }
senf::console::detail::CommandGrammar<TestParseDispatcher>::Context context;
std::stringstream ss;
TestParseDispatcher dispatcher (ss);
-
+
typedef senf::console::detail::CommandGrammar<TestParseDispatcher> Grammar;
Grammar grammar (dispatcher, context);
{
- static char text[] =
+ static char text[] =
"# Comment\n"
"doo / bii / // doo arg"
" flab::blub"
" x\"01 02 # Inner comment\n"
" 0304\";";
- BOOST_CHECK( boost::spirit::parse(
- text,
- grammar.use_parser<Grammar::CommandParser>(),
+ BOOST_CHECK( boost::spirit::parse(
+ text,
+ grammar.use_parser<Grammar::CommandParser>(),
grammar.use_parser<Grammar::SkipParser>() ) . full );
- BOOST_CHECK_EQUAL( ss.str(),
+ BOOST_CHECK_EQUAL( ss.str(),
"beginCommand( Word('doo')/Word('bii')/Word('doo') )\n"
"pushToken( Word('arg') )\n"
"pushToken( Word('flab::blub') )\n"
{
ss.str("");
- BOOST_CHECK( boost::spirit::parse(
- "ls //foo/bar;",
- grammar.use_parser<Grammar::CommandParser>(),
+ BOOST_CHECK( boost::spirit::parse(
+ "ls //foo/bar;",
+ grammar.use_parser<Grammar::CommandParser>(),
grammar.use_parser<Grammar::SkipParser>() ) . full );
BOOST_CHECK_EQUAL( ss.str(), "builtin_ls( None('')/Word('foo')/Word('bar') )\n" );
}
{
ss.str("");
- BOOST_CHECK( boost::spirit::parse(
- "lr /foo/bar;",
- grammar.use_parser<Grammar::CommandParser>(),
+ BOOST_CHECK( boost::spirit::parse(
+ "lr /foo/bar;",
+ grammar.use_parser<Grammar::CommandParser>(),
grammar.use_parser<Grammar::SkipParser>() ) . full );
BOOST_CHECK_EQUAL( ss.str(), "builtin_lr( None('')/Word('foo')/Word('bar') )\n" );
}
{
ss.str("");
- BOOST_CHECK( boost::spirit::parse(
- "cd /foo/bar;",
- grammar.use_parser<Grammar::CommandParser>(),
+ BOOST_CHECK( boost::spirit::parse(
+ "cd /foo/bar;",
+ grammar.use_parser<Grammar::CommandParser>(),
grammar.use_parser<Grammar::SkipParser>() ) . full );
BOOST_CHECK_EQUAL( ss.str(), "builtin_cd( None('')/Word('foo')/Word('bar') )\n" );
}
{
ss.str("");
- BOOST_CHECK( boost::spirit::parse(
- "exit;",
- grammar.use_parser<Grammar::CommandParser>(),
+ BOOST_CHECK( boost::spirit::parse(
+ "exit;",
+ grammar.use_parser<Grammar::CommandParser>(),
grammar.use_parser<Grammar::SkipParser>() ) . full );
BOOST_CHECK_EQUAL( ss.str(), "builtin_exit()\n" );
}
{
ss.str("");
- BOOST_CHECK( boost::spirit::parse(
- "foo/bar// {",
- grammar.use_parser<Grammar::CommandParser>(),
+ BOOST_CHECK( boost::spirit::parse(
+ "foo/bar// {",
+ grammar.use_parser<Grammar::CommandParser>(),
grammar.use_parser<Grammar::SkipParser>() ) . full );
- BOOST_CHECK_EQUAL( ss.str(),
+ BOOST_CHECK_EQUAL( ss.str(),
"beginCommand( Word('foo')/Word('bar')/None('') )\n"
"pushDirectory()\n"
"endCommand()\n" );
{
ss.str("");
- BOOST_CHECK( boost::spirit::parse(
- "}",
- grammar.use_parser<Grammar::CommandParser>(),
+ BOOST_CHECK( boost::spirit::parse(
+ "}",
+ grammar.use_parser<Grammar::CommandParser>(),
grammar.use_parser<Grammar::SkipParser>() ) . full );
BOOST_CHECK_EQUAL( ss.str(), "popDirectory()\n" );
}
{
ss.str("");
- BOOST_CHECK( boost::spirit::parse(
- "help /foo/bar",
- grammar.use_parser<Grammar::CommandParser>(),
+ BOOST_CHECK( boost::spirit::parse(
+ "help /foo/bar",
+ grammar.use_parser<Grammar::CommandParser>(),
grammar.use_parser<Grammar::SkipParser>() ) . full );
BOOST_CHECK_EQUAL( ss.str(), "builtin_help( None('')/Word('foo')/Word('bar') )\n" );
}
{
senf::console::CommandParser parser;
- char const text[] =
+ char const text[] =
"# Comment\n"
"doo / bii / doo arg"
" flab::blub"
{
senf::console::ParseCommandInfo const & info (commands.front());
- senf::console::Token path[] = {
- senf::console::Token(senf::console::Token::Word, "doo"),
+ senf::console::Token path[] = {
+ senf::console::Token(senf::console::Token::Word, "doo"),
senf::console::Token(senf::console::Token::Word, "bii"),
senf::console::Token(senf::console::Token::Word, "doo")
};
path, path + sizeof(path)/sizeof(path[0]) );
BOOST_CHECK_EQUAL( boost::next(info.commandPath().begin())->index(), 16u );
BOOST_CHECK_EQUAL( unsigned(info.tokens().size()), 15u );
-
- char const * tokens[] = { "arg",
- "flab::blub",
- "123.434>a",
+
+ char const * tokens[] = { "arg",
+ "flab::blub",
+ "123.434>a",
"(", "a", ",", "b", ",", "c", "(", "huhu", ")", ")",
"foo\"bar",
"\x01\x02\x03\x04" };
BOOST_REQUIRE( args != info.arguments().end() );
BOOST_REQUIRE_EQUAL( unsigned(args->size()), 1u );
BOOST_CHECK_EQUAL( args->begin()->value(), tokens[0] );
-
+
++ args;
BOOST_REQUIRE( args != info.arguments().end() );
BOOST_REQUIRE_EQUAL( args->size(), 1u );
BOOST_CHECK_EQUAL( args->begin()->value(), tokens[1] );
-
+
++ args;
BOOST_REQUIRE( args != info.arguments().end() );
BOOST_REQUIRE_EQUAL( args->size(), 1u );
BOOST_CHECK_EQUAL( args->begin()->value(), tokens[2] );
-
+
++ args;
BOOST_REQUIRE( args != info.arguments().end() );
BOOST_REQUIRE_EQUAL( args->size(), 8u );
BOOST_CHECK_EQUAL( info.tokens().begin()[3].index(), 96u );
BOOST_CHECK_EQUAL( info.tokens().begin()[5].index(), 98u );
BOOST_CHECK_EQUAL( info.tokens().begin()[12].index(), 109u );
-
+
++ args;
BOOST_REQUIRE( args != info.arguments().end() );
BOOST_REQUIRE_EQUAL( args->size(), 1u );
BOOST_CHECK_EQUAL( args->begin()->value(), tokens[13] );
BOOST_CHECK_EQUAL( args->begin()->index(), 126u );
-
+
++ args;
BOOST_REQUIRE( args != info.arguments().end() );
BOOST_REQUIRE_EQUAL( args->size(), 1u );
BOOST_CHECK_EQUAL( args->begin()->value(), tokens[14] );
-
+
++ args;
BOOST_CHECK( args == info.arguments().end() );
}
senf::console::CommandParser parser;
SENF_CHECK_NO_THROW( parser.parse("foo a", &setInfo) );
- BOOST_CHECK_THROW( parseArgs(commands.back().arguments()),
+ BOOST_CHECK_THROW( parseArgs(commands.back().arguments()),
senf::console::SyntaxErrorException );
SENF_CHECK_NO_THROW( parser.parse("foo a b", &setInfo) );
SENF_CHECK_NO_THROW( parseArgs(commands.back().arguments()) );
SENF_CHECK_NO_THROW( parser.parse("foo a b c", &setInfo) );
- BOOST_CHECK_THROW( parseArgs(commands.back().arguments()),
+ BOOST_CHECK_THROW( parseArgs(commands.back().arguments()),
senf::console::SyntaxErrorException );
-
+
senf::console::CheckedArgumentIteratorWrapper arg (commands.back().arguments());
BOOST_CHECK( arg == commands.back().arguments().begin() );
BOOST_CHECK( arg != commands.back().arguments().end() );
try { parser.parse(c, &setInfo); } \
catch (std::exception & ex) { msg = parseErrorMessage(ex.what()); } \
BOOST_CHECK_EQUAL( msg, e )
-
+
CheckParseEx( "/foo/bar;\n ()", "path expected\nat <unknown>:2:3" );
CheckParseEx( "cd /foo/bar foo/bar", "end of statement expected\nat <unknown>:1:13" );
CheckParseEx( "/foo/bar foo /", "end of statement expected\nat <unknown>:1:14" );
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
BOOST_ASSERT( index < parameters_.size() );
detail::ArgumentInfoBase & arg (*parameters_[index]);
- doc.name = arg.name.empty()
+ doc.name = arg.name.empty()
? (boost::format("arg%d%d") % overloadIndex() % (index+1)).str()
: arg.name;
doc.type = arg.type;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
template <class ParameterType>
prefix_ senf::console::detail::ArgumentInfo<ParameterType>::ArgumentInfo()
- : ArgumentInfoBase ( ArgumentTraits<ParameterType>::description(),
+ : ArgumentInfoBase ( ArgumentTraits<ParameterType>::description(),
ArgumentTraits<ParameterType>::singleToken ),
defaultValue ()
{}
prefix_
senf::console::ParsedArgumentAttributor<Overload, index, false>::
ParsedArgumentAttributor(typename Overload::ptr overload)
- : ParsedArgumentAttributorBase<
+ : ParsedArgumentAttributorBase<
Overload, ParsedArgumentAttributor<Overload, index, false> > (overload, index)
{}
///////////////////////////////////////////////////////////////////////////
template <class Signature>
-prefix_ senf::console::SimpleOverloadAttributor
+prefix_ senf::console::SimpleOverloadAttributor
senf::console::factory::
Command(boost::function<Signature> fn,
typename boost::enable_if_c<detail::ParsedCommandTraits<Signature>::is_simple>::type *)
}
template <class Function>
-prefix_ senf::console::SimpleOverloadAttributor
+prefix_ senf::console::SimpleOverloadAttributor
senf::console::factory::
Command(Function fn,
typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_simple>::type *)
}
template <class Owner, class Member>
-prefix_ senf::console::SimpleOverloadAttributor
+prefix_ senf::console::SimpleOverloadAttributor
senf::console::factory::
Command(Member memfn, Owner * owner,
typename boost::enable_if<boost::is_member_function_pointer<Member> >::type *,
}
template <class Owner, class Member>
-prefix_ senf::console::SimpleOverloadAttributor
+prefix_ senf::console::SimpleOverloadAttributor
senf::console::factory::
Command(Member memfn, Owner const * owner,
typename boost::enable_if<boost::is_member_function_pointer<Member> >::type *,
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
should do so to make the unwieldy casts unnecessary.
\section overload_parse Custom parameter parsers
-
+
By default, parameters are parsed using \c boost::lexical_cast and therefore using \c
iostreams. This means, that any type which can be read from a stream can automatically be
used as argument type.
Attributes for parsed commands are not set directly on the node. They are set via a special
attributor temporary returned when adding a parsed command to the tree.
-
+
This class is the base class for those attributors. It provides members which do not depend
in any way on the exact type of command added.
void argDoc(std::string const & doc);
void typeName(std::string const & doc);
void defaultDoc(std::string const & doc);
-
+
ParsedCommandOverloadBase & overload() const;
void overloadDoc(std::string const & doc);
void nodeDoc(std::string const & doc);
void shortDoc(std::string const & doc);
-
+
private:
ParsedCommandOverloadBase::ptr overload_;
unsigned index_;
boost::optional<std::string> shortdoc_;
};
- /** \brief Non argument dependent ParsedCommandBase attributes
-
+ /** \brief Non argument dependent ParsedCommandBase attributes
+
Attributes for parsed commands are not set directly on the node. They are set via a special
attributor temporary returned when adding a parsed command to the tree.
// Either qualify them with their complete namespace
dir.add(...)
.arg( senf::console::kw::name = "name" );
-
+
// Or use a namespace alias
namespace kw = senf::console::kw;
dir.add(...)
<pre>
Usage:
command [name:type_name]
-
+
With:
name description
default: default_doc
token list returned by the console/config parser into
the appropriate value. If not set explicitly, this
conversion is supplied by the ArgumentTraits
- class.
+ class.
Setting the \a parser attribute allows to use a custom
parser. The parser is an arbitrary callable object with
Attributes for parsed commands are not set directly on the node. They are set via a special
attributor temporary returned when adding a parsed command to the tree.
-
+
This class adds all those members, which do not depend on any specific argument but which
need to return the correct attributor type.
Self doc(std::string const & doc); ///< Set documentation for all overloads
Self shortdoc(std::string const & doc); ///< Set short documentation for all overloads
Self overloadDoc(std::string const & doc); ///< Set overload specific documentation
- Self formatter(typename Overload::Formatter formatter);
+ Self formatter(typename Overload::Formatter formatter);
///< Set return value formatter
/**< This member is only available, if the \a ReturnType of
the installed callback is not \c void.
};
#endif
-
+
/** \brief Argument dependent ParsedCommandBase attributes
Attributes for parsed commands are not set directly on the node. They are set via a special
attributor temporary returned when adding a parsed command to the tree.
-
+
This class adds all those members, which depend on a specific argument. Each call to \c arg
will advance to the next argument.
*/
template <class Overload, unsigned index, bool flag>
class ParsedArgumentAttributor
- : public ParsedArgumentAttributorBase< Overload,
+ : public ParsedArgumentAttributorBase< Overload,
ParsedArgumentAttributor<Overload, index, flag> >
{
typedef boost::parameter::parameters<
kw::type::parser> arg_params;
public:
- typedef typename senf::function_traits_arg_type<
+ typedef typename senf::function_traits_arg_type<
typename Overload::traits, int(index) >::type arg_type;
typedef typename senf::remove_cvref< arg_type >::type value_type;
typedef ParsedArgumentAttributor<Overload, index+1> next_type;
argument. The attributes are passed to arg() as keyword
arguments using the <a
href="http://www.boost.org/doc/libs/1_33_1/libs/parameter/doc/html/index.html">Boost.Parameter</a>
- library.
+ library.
\code
...
- .arg( kw::name = "name",
+ .arg( kw::name = "name",
kw::default_value = 1 )
...
\endcode
The valid keywords are defined in the senf::console::kw
namespace.
-
+
Each call to arg() will increment the argument index
and advance to the next argument. This member is only
present, if there is an argument at the current
void argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_);
template <class ArgumentPack>
- void argInfo(boost::parameter::keyword<kw::type::name> const &,
+ void argInfo(boost::parameter::keyword<kw::type::name> const &,
ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
- void argInfo(boost::parameter::keyword<kw::type::description> const &,
+ void argInfo(boost::parameter::keyword<kw::type::description> const &,
ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
- void argInfo(boost::parameter::keyword<kw::type::default_value> const &,
+ void argInfo(boost::parameter::keyword<kw::type::default_value> const &,
ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
- void argInfo(boost::parameter::keyword<kw::type::type_name> const &,
+ void argInfo(boost::parameter::keyword<kw::type::type_name> const &,
ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
- void argInfo(boost::parameter::keyword<kw::type::default_doc> const &,
+ void argInfo(boost::parameter::keyword<kw::type::default_doc> const &,
ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
- void argInfo(boost::parameter::keyword<kw::type::parser> const &,
+ void argInfo(boost::parameter::keyword<kw::type::parser> const &,
ArgumentPack const & args, boost::mpl::true_);
next_type next() const;
template <class Overload, unsigned index>
class ParsedArgumentAttributor<Overload, index, false>
- : public ParsedArgumentAttributorBase< Overload,
+ : public ParsedArgumentAttributorBase< Overload,
ParsedArgumentAttributor<Overload, index, false> >
{
public:
namespace factory {
template <class Signature>
- SimpleOverloadAttributor
+ SimpleOverloadAttributor
Command(boost::function<Signature> fn,
typename boost::enable_if_c<detail::ParsedCommandTraits<Signature>::is_simple>::type * = 0);
template <class Function>
- SimpleOverloadAttributor
+ SimpleOverloadAttributor
Command(Function fn,
typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_simple>::type * = 0);
Command(Function fn,
typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0,
typename boost::disable_if<boost::is_member_function_pointer<Function> >::type * = 0);
-
+
template <class Signature>
typename senf::console::detail::ParsedCommandTraits<Signature>::Attributor
Command(boost::function<Signature> fn);
typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
Command(Member memfn, Owner const * owner,
typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
-
+
template <class CastTo, class Owner, class Member>
typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
Command(Member memfn, Owner * owner,
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace senf {
namespace console {
- template < class FunctionTraits,
- class ReturnType=typename FunctionTraits::result_type,
+ template < class FunctionTraits,
+ class ReturnType=typename FunctionTraits::result_type,
unsigned arity=FunctionTraits::arity >
class ParsedCommandOverload;
- template < class Overload,
- unsigned index=0,
+ template < class Overload,
+ unsigned index=0,
bool flag=(index < unsigned(Overload::traits::arity)) >
class ParsedArgumentAttributor;
namespace detail {
/** \brief Internal: Argument information structure
-
- This class is used to hold argument information for automatically parsed commands.
+
+ This class is used to hold argument information for automatically parsed commands.
\see ParsedCommandOverloadBase
*/
: public intrusive_refcount
{
typedef boost::intrusive_ptr<ArgumentInfoBase> ptr;
-
+
std::string type;
std::string name;
std::string defaultDoc;
bool hasDefault;
std::string doc;
bool singleToken;
-
+
explicit ArgumentInfoBase(std::string const & type, bool singleToken=false);
virtual ~ArgumentInfoBase();
virtual std::string defaultValueStr() const = 0;
};
-
+
/** \brief Internal: Argument information structure
-
- This class is used to hold argument information for automatically parsed commands.
+
+ This class is used to hold argument information for automatically parsed commands.
\see ParsedCommandOverloadBase
*/
template <class ParameterType>
- struct ArgumentInfo
+ struct ArgumentInfo
: public ArgumentInfoBase
{
typedef boost::intrusive_ptr<ArgumentInfo> ptr;
- typedef boost::function<void (ParseCommandInfo::TokensRange const &,
+ typedef boost::function<void (ParseCommandInfo::TokensRange const &,
ParameterType &)> Parser;
static ptr create();
virtual std::string defaultValueStr() const;
};
-
+
#ifndef DOXYGEN
// FirstArgType returns void, if the function has no arguments, otherwise it returns arg1_type
static const bool has_ostream_arg = boost::is_same<first_arg_type, std::ostream &>::value;
typedef typename boost::mpl::if_c<
- has_ostream_arg,
- typename function_traits_remove_arg<base_traits>::type,
+ has_ostream_arg,
+ typename function_traits_remove_arg<base_traits>::type,
base_traits>
::type traits;
static const bool is_callable = true;
static const bool is_member = boost::is_member_pointer<base_type>::value;
static const bool is_simple = false;
-
+
typedef typename senf::member_class<base_type>::type class_type;
typedef ParsedCommandOverload<traits> Overload;
template <class FunctionP>
struct ParsedCommandTraits
- : public ParsedCommandTraits_i< FunctionP,
+ : public ParsedCommandTraits_i< FunctionP,
typename senf::remove_any_pointer<FunctionP>::type >
{};
//
// If however, it does NOT take an std::ostream first argument, 'ignoreOneArg' will be true and
// the create member will use boost::bind to DROP the first argument.
-
- template <class Traits,
- bool ignoreOneArg=! Traits::has_ostream_arg,
+
+ template <class Traits,
+ bool ignoreOneArg=! Traits::has_ostream_arg,
unsigned arity=Traits::traits::arity>
struct CreateParsedCommandOverload
{};
struct CreateParsedCommandOverload<Traits, false, arity>
{
typedef typename Traits::traits traits;
-
+
template <class Function>
- static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn)
+ static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn)
{ return senf::console::ParsedCommandOverload<traits>::create(fn); };
};
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
private:
ParsedCommandOverload(Function fn);
- virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
+ virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
const;
Function function_;
private:
ParsedCommandOverload(Function fn);
- virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
+ virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
const;
Function function_;
senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
arg() const
{
- return static_cast< detail::ArgumentInfo<
+ return static_cast< detail::ArgumentInfo<
typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
}
prefix_
senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::
ParsedCommandOverload(Function fn)
- : function_ (fn)
+ : function_ (fn)
{
# define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
arg() const
{
- return static_cast< detail::ArgumentInfo<
+ return static_cast< detail::ArgumentInfo<
typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
}
prefix_
senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
ParsedCommandOverload(Function fn)
- : function_ (fn)
+ : function_ (fn)
{
# define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) ); \
}
# define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
- BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
+ BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
# undef mpp_l
# undef mpp_l_
ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) ); \
}
# define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
- BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
+ BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
# undef mpp_l
# undef mpp_l_
// Create keyword arg forwarding functions
-template <BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), class A ) >
+template <BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), class A ) >
next_type arg ( BOOST_PP_ENUM_BINARY_PARAMS( BOOST_PP_ITERATION(), A, const & a ),
typename arg_params::match< BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), A ) >::type
kw = arg_params()) {
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
std::string cb4(std::ostream & os) { os << "text\n"; return "value"; }
void cb5(std::ostream & os, std::string const & v) { os << "Value: " << v << "\n"; }
- struct TestParser
+ struct TestParser
{
void operator()(senf::console::ParseCommandInfo::TokensRange const &,
std::string & out) const
{
std::stringstream ss;
dir.add("cb1", fty::Command(&cb1));
- parser.parse("test/cb1 2 3.2",
+ parser.parse("test/cb1 2 3.2",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
BOOST_CHECK_EQUAL( ss.str(), "5\n" );
}
{
std::stringstream ss;
- BOOST_CHECK_THROW(
- parser.parse("test/cb1 2 3.2 foo",
+ BOOST_CHECK_THROW(
+ parser.parse("test/cb1 2 3.2 foo",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )),
senf::console::SyntaxErrorException );
BOOST_CHECK_THROW(
- parser.parse("test/cb1 2",
+ parser.parse("test/cb1 2",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )),
senf::console::SyntaxErrorException );
BOOST_CHECK_THROW(
- parser.parse("test/cb1 2 foo",
+ parser.parse("test/cb1 2 foo",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )),
senf::console::SyntaxErrorException );
}
std::stringstream ss;
// Just for the fun of it, use a functor and not a function pointer as parser ...
- dir.add("cb6",
+ dir.add("cb6",
fty::Command(&cb5)
.arg( kw::parser = TestParser() )
);
{
std::stringstream ss;
- // This tests adding boost::function objects and at the same time validates, that
+ // This tests adding boost::function objects and at the same time validates, that
// compatible types also work
- dir.add("cb7",
+ dir.add("cb7",
fty::Command(boost::function<float()>(&cb2))
.formatter( &testFormatter )
);
.arg( description = "Bar didelfrump di desgorb. Nu widsoflar brimeldrgf." )
- .arg( name = "checkup",
+ .arg( name = "checkup",
type_name = "number",
description = "Florgel, dargel and durgel",
default_value = 2.1,
.overloadDoc(
"Uus Primordia fundo falsidicus corium, diurnitas humo pro leto. Sui Ueraciter\n"
"hio eruca lenis qua Agalmate ut fors penitentia. Iugum obdormio anxio nuncupo\n"
- "iam, in vos nam Custodi." )
+ "iam, in vos nam Custodi." )
.arg( "text", default_value = "" ) )
);
{
std::stringstream ss;
senf::console::root()["test"]("cb").help(ss);
- BOOST_CHECK_EQUAL(
- ss.str(),
+ BOOST_CHECK_EQUAL(
+ ss.str(),
"Usage:\n"
" 1- cb arg11:int [checkup:number]\n"
" 2- cb [text:string]\n"
}
namespace {
- struct Test
+ struct Test
{
senf::console::ScopedDirectory<Test> dir;
std::string name_;
senf::console::CommandParser parser;
senf::console::ScopedDirectory<> dir;
senf::console::root().add("test", dir);
-
+
{
Test obj ("bar");
dir.add("obj", obj.dir);
-
+
std::stringstream ss;
parser.parse("test/obj/name \": foo\"",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
namespace {
- senf::console::DirectoryNode::ptr dircb()
+ senf::console::DirectoryNode::ptr dircb()
{
namespace fty = senf::console::factory;
SENF_CHECK_NO_THROW(
parser.parse("test/test { ll; }",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
- BOOST_CHECK_EQUAL( ss.str(),
+ BOOST_CHECK_EQUAL( ss.str(),
"<Directory at '/test/dircb'>\n"
"cb1 \n" );
}
-
+
}
#ifdef COMPILE_CHECK
}
#endif
-
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
--n;
}
}
- else
+ else
param = arg.substr(i+1);
i = arg.size();
}
ParseCommandInfo cmd;
Path path;
-
+
DirectoryNode::ptr cwd (executor.root().thisptr());
std::string::size_type b (0);
while (b < name.size()) {
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// Parse only options under the directory of some object. The object 'ob'
// must have been registered somewhere in the node tree
cf.parse(ob.dir);
-
+
// Parse rest of the config file
cf.parse();
\endcode
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
-
+
ProgramOptions(int argc, char const ** argv, DirectoryNode & root = root());
///< Create ProgramOptions parser for given options
/**< The given argc/argv values are those passed to main by
///@}
///////////////////////////////////////////////////////////////////////////
-
+
template <class Container>
ProgramOptions & nonOptions(Container & container);
///< Set container to add non-option arguments to
line. This argument will be appended (with an
additional '=') to \a longOpt. If \a withArg is \c
false (the default), \a longOpt may optional contain an
- argument.
+ argument.
\param[in] letter option letter
\param[in] longOpt long option alias
\param[in] withArg \c true, if the option should take
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace senf {
namespace console {
namespace detail {
-
+
#ifndef DOXYGEN
class ProgramOptionsSource : public ConfigSource
template <class Container>
ProgramOptionsSource & nonOptions(Container & container);
ProgramOptionsSource & alias(char letter, std::string const & longOpt, bool withArg=false);
-
+
private:
ProgramOptionsSource(int argc, char const ** argv);
-
+
virtual void v_parse(RestrictedExecutor & executor);
void parseLongOption(std::string const & arg, RestrictedExecutor & executor);
};
typedef std::map<char, ShortOption> ShortOptions;
-
+
int argc_;
char const ** argv_;
CommandParser parser_;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
BOOST_CHECK_EQUAL( val1, "" );
BOOST_CHECK_EQUAL( val2, true );
}
-
+
{
char const * argv[] = { "", "-ab" };
senf::console::ProgramOptions opts(sizeof(argv)/sizeof(argv[0]), argv, root);
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
prefix_ std::string
senf::console::detail::CollectionArgumentTraitsBase<Collection>::description()
{
- return senf::prettyBaseName(typeid(Collection)) + "<"
+ return senf::prettyBaseName(typeid(Collection)) + "<"
+ ArgumentTraits<typename Collection::value_type>::description() + ">";
}
if (i != i_end)
for (;;) {
os << senf::console::str(*i);
- if (++i == i_end)
+ if (++i == i_end)
break;
else
os << " ";
template <class Collection>
prefix_ std::string senf::console::detail::MapArgumentTraits<Collection>::description()
{
- return senf::prettyBaseName(typeid(Collection)) + "<"
+ return senf::prettyBaseName(typeid(Collection)) + "<"
+ ArgumentTraits<typename Collection::key_type>::description() + ","
+ ArgumentTraits<typename Collection::mapped_type>::description() + ">";
}
os << senf::console::str(i->first)
<< "="
<< senf::console::str(i->second);
- if (++i == i_end)
+ if (++i == i_end)
break;
else
os << " ";
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
template <class T, class Alloc>
struct ArgumentTraits< std::vector<T,Alloc> >
- : public detail::CollectionArgumentTraits< std::vector<T,Alloc>,
+ : public detail::CollectionArgumentTraits< std::vector<T,Alloc>,
detail::PushBackFunctor >
{};
template <class T, class Alloc>
struct ArgumentTraits< std::list<T,Alloc> >
- : public detail::CollectionArgumentTraits< std::list<T,Alloc>,
+ : public detail::CollectionArgumentTraits< std::list<T,Alloc>,
detail::PushBackFunctor >
{};
template <class Key, class Compare, class Alloc>
struct ArgumentTraits< std::set<Key,Compare,Alloc> >
- : public detail::CollectionArgumentTraits< std::set<Key,Compare,Alloc>,
+ : public detail::CollectionArgumentTraits< std::set<Key,Compare,Alloc>,
detail::InsertFunctor >
{};
template <class Key, class Compare, class Alloc>
struct ArgumentTraits< std::multiset<Key,Compare,Alloc> >
- : public detail::CollectionArgumentTraits< std::multiset<Key,Compare,Alloc>,
+ : public detail::CollectionArgumentTraits< std::multiset<Key,Compare,Alloc>,
detail::InsertFunctor >
{};
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
struct MapReturnValueTraits
{
typedef Collection type;
-
+
static void format(Collection const & value, std::ostream & os);
};
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
}
return std::make_pair(keys,sum);
}
-
+
}
SENF_AUTO_UNIT_TEST(vectorSupport)
BOOST_CHECK_EQUAL( ss.str(), "9\n" "0\n" "5\n" "13\n" "17\n" );
ss.str("");
- SENF_CHECK_NO_THROW(
+ SENF_CHECK_NO_THROW(
parser.parse("help test/test",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
BOOST_CHECK_EQUAL(
- ss.str(),
+ ss.str(),
"Usage:\n"
" test [data:vector<int>]\n"
"\n"
BOOST_CHECK_EQUAL( ss.str(), "9\n" "0\n" "5\n" "13\n" "17\n" );
ss.str("");
- SENF_CHECK_NO_THROW(
+ SENF_CHECK_NO_THROW(
parser.parse("help test/test",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
BOOST_CHECK_EQUAL(
- ss.str(),
+ ss.str(),
"Usage:\n"
" test [data:list<int>]\n"
"\n"
BOOST_CHECK_EQUAL( ss.str(), "9\n" "0\n" "5\n" "13\n" "17\n" );
ss.str("");
- SENF_CHECK_NO_THROW(
+ SENF_CHECK_NO_THROW(
parser.parse("help test/test",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
BOOST_CHECK_EQUAL(
- ss.str(),
+ ss.str(),
"Usage:\n"
" test [data:set<int>]\n"
"\n"
parser.parse("test/test; test/test (); "
"test/test (vier=4 fuenf = 5 acht=8 )",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
- BOOST_CHECK_EQUAL( ss.str(), "(\"barfoo bar\" 9)\n" "(\"\" 0)\n" "(achtfuenfvier 17)\n" ); //
+ BOOST_CHECK_EQUAL( ss.str(), "(\"barfoo bar\" 9)\n" "(\"\" 0)\n" "(achtfuenfvier 17)\n" ); //
ss.str("");
- SENF_CHECK_NO_THROW(
+ SENF_CHECK_NO_THROW(
parser.parse("help test/test",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
BOOST_CHECK_EQUAL(
- ss.str(),
+ ss.str(),
"Usage:\n"
" test [data:map<string,int>]\n"
"\n"
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
return node().doc(doc);
}
-prefix_ std::string const & senf::console::ScopedDirectoryBase::name()
+prefix_ std::string const & senf::console::ScopedDirectoryBase::name()
const
{
return node().name();
return node().path(root);
}
-prefix_ boost::shared_ptr<senf::console::DirectoryNode>
-senf::console::ScopedDirectoryBase::parent()
+prefix_ boost::shared_ptr<senf::console::DirectoryNode>
+senf::console::ScopedDirectoryBase::parent()
const
{
return node().parent();
node().help( output);
}
-prefix_ std::string senf::console::ScopedDirectoryBase::shorthelp()
+prefix_ std::string senf::console::ScopedDirectoryBase::shorthelp()
const
{
return node().shorthelp();
}
-
+
prefix_ senf::console::ScopedDirectoryBase::ScopedDirectoryBase()
: node_ (DirectoryNode::create())
{}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
public:
ScopedDirectory<MyClass> configDir;
- MyClass() : configDir(this)
+ MyClass() : configDir(this)
{
configDIr.add(...);
}
public:
///////////////////////////////////////////////////////////////////////////
// Types
-
+
typedef Owner owner;
///////////////////////////////////////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
BOOST_CHECK( &dir["foo"] == &dir.get("foo") );
BOOST_CHECK( &dir("cb") == &dir.get("cb") );
BOOST_CHECK_EQUAL(dir.name(), "dir");
-
+
char const * const children[] = { "cb", "foo" };
- BOOST_CHECK_EQUAL_COLLECTIONS(
+ BOOST_CHECK_EQUAL_COLLECTIONS(
boost::make_transform_iterator(dir.children().begin(),
select1st<std::string const &>()),
boost::make_transform_iterator(dir.children().end(),
select1st<std::string const &>()),
- children,
+ children,
children+sizeof(children)/sizeof(children[0]) );
-
+
dir.doc("dir");
std::stringstream ss;
dir.node().help(ss);
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
senf::TCPv4ServerSocketHandle handle (address);
Server & server (senf::console::Server::start(handle));
- SENF_LOG((Server::SENFLogArea)(log::NOTICE)(
+ SENF_LOG((Server::SENFLogArea)(log::NOTICE)(
"Console server started at " << address ));
return server;
}
{
senf::TCPv6ServerSocketHandle handle (address);
Server & server (senf::console::Server::start(handle));
- SENF_LOG((Server::SENFLogArea)(log::NOTICE)(
+ SENF_LOG((Server::SENFLogArea)(log::NOTICE)(
"Console server started at " << address ));
return server;
}
}
prefix_ senf::console::Server::Server(ServerHandle handle)
- : handle_ (handle),
+ : handle_ (handle),
event_ ("senf::console::Server", senf::membind(&Server::newClient, this),
handle_, scheduler::FdEvent::EV_READ),
root_ (senf::console::root().thisptr()), mode_ (Automatic),
stopClient();
return;
}
-
+
promptLen_ = 0;
promptActive_ = false;
prefix_
senf::console::detail::NoninteractiveClientReader::NoninteractiveClientReader(Client & client)
- : ClientReader (client),
- readevent_ ("senf::console::detail::NoninteractiveClientReader",
+ : ClientReader (client),
+ readevent_ ("senf::console::detail::NoninteractiveClientReader",
senf::membind(&NoninteractiveClientReader::newData, this),
handle(), senf::scheduler::FdEvent::EV_READ)
{}
// senf::console::Client
prefix_ senf::console::Client::Client(Server & server, ClientHandle handle)
- : out_t(boost::ref(*this)),
- senf::log::IOStreamTarget("client-" + senf::str(handle.peer()), out_t::member),
- server_ (server), handle_ (handle),
- readevent_ ("senf::console::Client::interactive_check",
- boost::bind(&Client::setNoninteractive,this),
+ : out_t(boost::ref(*this)),
+ senf::log::IOStreamTarget("client-" + senf::str(handle.peer()), out_t::member),
+ server_ (server), handle_ (handle),
+ readevent_ ("senf::console::Client::interactive_check",
+ boost::bind(&Client::setNoninteractive,this),
handle, scheduler::FdEvent::EV_READ, false),
- timer_ ("senf::console::Client::interactive_timer",
+ timer_ ("senf::console::Client::interactive_timer",
boost::bind(&Client::setInteractive, this),
scheduler::eventTime() + ClockService::milliseconds(INTERACTIVE_TIMEOUT),
false),
if (i != std::string::npos) {
backtrace_ = msg.substr(0,i);
msg = msg.substr(i+4);
- } else
+ } else
backtrace_.clear();
stream() << msg << std::endl;
}
unsigned minWidth)
{
unsigned rv (defaultWidth);
- try {
- rv = get(os).width();
+ try {
+ rv = get(os).width();
}
catch (std::bad_cast &) {}
return rv < minWidth ? defaultWidth : rv;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
public:
///////////////////////////////////////////////////////////////////////////
// Types
-
+
typedef detail::ServerHandle ServerHandle;
enum Mode { Automatic, Interactive, Noninteractive };
Mode mode() const; ///< Get mode
/**< \see \ref mode(Mode) */
-
+
Server & mode(Mode mode); ///< Set mode
- /**< There are two Server types:
+ /**< There are two Server types:
\li An interactive server displays a command prompt and
optionally supports command-line editing.
\li A non-interactive server does not display any
opened. */
void stop(); ///< Stop the server
- /**< All clients will be closed
+ /**< All clients will be closed
\warning The Server instance itself will be deleted */
protected:
void newClient(int event);
void removeClient(Client & client);
-
+
ServerHandle handle_;
scheduler::FdEvent event_;
DirectoryNode::ptr root_;
Mode mode_;
-
+
typedef std::set< boost::intrusive_ptr<Client> > Clients;
Clients clients_;
std::string name_;
-
+
friend class Client;
};
-
+
/** \brief Server client instance
Whenever a new client connects, a new instance of this class is created. This class shows a
\ingroup console_access
*/
class Client
- : public senf::intrusive_refcount,
+ : public senf::intrusive_refcount,
private boost::base_from_member< detail::NonblockingSocketOStream >,
public senf::log::IOStreamTarget
{
ClientHandle handle() const; ///< Get the client's network socket handle
std::ostream & stream(); ///< Get client's output stream
/**< Data sent to this stream is sent out over the network
- via the client's socket handle. Write operation is
+ via the client's socket handle. Write operation is
non-blocking and data may be dropped. Data is written
using Client::write(). */
std::string promptString() const; ///< Get the prompt string
will return the associated Client instance reference.
\throws std::bad_cast if \a os is not associated with a
Client instance. */
- static unsigned getWidth(std::ostream & os, unsigned defaultWidth = 0,
+ static unsigned getWidth(std::ostream & os, unsigned defaultWidth = 0,
unsigned minWidth = 0);
///< Get width of client console if possible
/**< If possible, the width of the client console attached
to the stream \a os is returned. If this is not
possible, the \a defaultValue will be used.
-
+
If the width obtained this way is smaller than \a
minWidth, \a defaultValue will be returned instead. */
protected:
-
+
private:
Client(Server & server, ClientHandle handle);
void setNoninteractive();
size_t handleInput(std::string input, bool incremental = false);
- virtual void v_write(senf::log::time_type timestamp, std::string const & stream,
- std::string const & area, unsigned level,
+ virtual void v_write(senf::log::time_type timestamp, std::string const & stream,
+ std::string const & area, unsigned level,
std::string const & message);
-
+
Server & server_;
ClientHandle handle_;
scheduler::FdEvent readevent_;
friend class detail::ClientReader;
friend class detail::NonblockingSocketSink;
- class SysBacktrace
+ class SysBacktrace
{
SysBacktrace();
static void backtrace(std::ostream & os);
static SysBacktrace instance_;
};
-
+
};
-
+
/** \brief Output Console Client instance as it's string representation
\related Client
*/
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
\fixme Don't throw exceptions ... set stream error indicator (if at all)
*/
- class NonblockingSocketSink
+ class NonblockingSocketSink
: public boost::iostreams::sink
{
public:
std::streamsize write(const char * s, std::streamsize n);
Client & client() const;
-
+
private:
Client & client_;
};
typedef boost::iostreams::stream<NonblockingSocketSink> NonblockingSocketOStream;
typedef senf::ServerSocketHandle<
- senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy,
+ senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy,
senf::BSDAddressingPolicy>::policy > ServerHandle;
/** \brief Internal: Generic client interface
};
/** \brief Internal: Primitive ClientReader implementation
-
+
This implementation uses the cooked telnet mode to read lines from the console. It does not
support explicit line editing or any other advanced features.
*/
};
/** \brief Internal: Primitive ClientReader implementation
-
+
This implementation uses the cooked telnet mode to read lines from the console. It does not
support explicit line editing or any other advanced features.
*/
scheduler::FdEvent readevent_;
std::string buffer_;
};
-
+
}}}
///////////////////////////////ih.e////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
public:
using singleton<SysdirManager>::instance;
using singleton<SysdirManager>::alive;
-
+
ScopedDirectory<> & sysdir();
-
+
private:
SysdirManager();
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
if (rv[i] == '"' || rv[i] == '\\')
rv.insert(i++,"\\");
else if (rv[i] < ' ' || rv[i] > 126) {
- rv.insert(i+1, (boost::format("x%02x")
+ rv.insert(i+1, (boost::format("x%02x")
% unsigned(static_cast<unsigned char>(rv[i]))).str().c_str());
rv[i] = '\\';
i += 3;
}
-
+
rv.insert(0,"\"");
rv.push_back('"');
return rv;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace console {
/** \brief Customize argument parsing
-
+
ArgumentTraits provides argument parsing, Additionally, this class provides a way to get a
string-description of a type and to convert a value back into it's string representation
used to display default values.
-
- The default implementation provided here
+
+ The default implementation provided here
\li will use senf_console_parse_argument() to parse a value. This functions default
implementation uses \c boost::lexical_cast and thereby \c iostreams to convert an
argument consisting of a single input token into the required type.
\li will name types by returning the last component of the fully scoped name (e.g. \c
- "string" for \c std::string).
+ "string" for \c std::string).
\li Will format values (for default value display) by forwarding the value to the
ReturnValueTraits of that type.
{
typedef Type type;
- static bool const singleToken =
+ static bool const singleToken =
boost::is_same< typeof(senf_console_parse_argument(
*static_cast<ParseCommandInfo::TokensRange const *>(0),
*static_cast<Type*>(0))),
/** \brief Register enum type for argument parsing
- Enum types need to be registered explicitly to support parsing.
+ Enum types need to be registered explicitly to support parsing.
\code
enum Foo { Foo1, Foo2 };
SENF_CONSOLE_REGISTER_ENUM( Foo, (Foo1)(Foo2) );
/** \brief Register enum type for argument parsing
- Enum types need to be registered explicitly to support parsing.
+ Enum types need to be registered explicitly to support parsing.
\code
class SomeClass
{
/** \brief Format boolean value as \c enabled / \c disabled */
void formatEnabledDisabled(bool value, std::ostream & os);
-
+
/** \brief Format boolean value as \c on / \c off */
void formatOnOff(bool value, std::ostream & os);
template <> struct ArgumentTraits<signed char> : public detail::CharArgumentTraits<signed char> {};
template <> struct ReturnValueTraits<signed char> : public detail::CharReturnValueTraits<signed char> {};
template <> struct ArgumentTraits<unsigned char> : public detail::CharArgumentTraits<unsigned char> {};
- template <> struct ReturnValueTraits<unsigned char> : public detail::CharReturnValueTraits<unsigned char> {};
+ template <> struct ReturnValueTraits<unsigned char> : public detail::CharReturnValueTraits<unsigned char> {};
#endif
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
template <class _> struct ReturnValueTraits;
namespace detail {
-
+
template <class CharT>
struct MatchingShortType
: public boost::mpl::if_c<std::numeric_limits<CharT>::is_signed,short,unsigned short>
struct StringILess
{
bool operator()(std::string const & left, std::string const & right) const
- { return boost::algorithm::to_lower_copy(left)
+ { return boost::algorithm::to_lower_copy(left)
< boost::algorithm::to_lower_copy(right); }
};
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
SENF_AUTO_UNIT_TEST(stringTraits)
{
- BOOST_CHECK_EQUAL(
+ BOOST_CHECK_EQUAL(
senf::console::ArgumentTraits<std::string>::str("Test\nOf\nA \"String\"\x01\x7f\xa0\xff"),
"\"Test\\x0aOf\\x0aA \\\"String\\\"\\x01\\x7f\\xa0\\xff\"" );
}
senf::console::root().add("test", dir);
dir.add("test",fty::Command(&test));
-
+
std::stringstream ss;
SENF_CHECK_NO_THROW(
parser.parse("test/test Foo",
{
BOOST_CHECK( senf::console::ArgumentTraits<std::string>::singleToken );
BOOST_CHECK( senf::console::ArgumentTraits<int>::singleToken );
- BOOST_CHECK( ! senf::console::ArgumentTraits<
+ BOOST_CHECK( ! senf::console::ArgumentTraits<
senf::console::FlagCollection<TestEnum> >::singleToken );
}
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////cc.p////////////////////////////////////////
prefix_ senf::console::UDPServer::UDPServer(senf::INet4SocketAddress const & address)
- : replies_ (true), emptyReplies_ (true), target_ (),
- handle_ (senf::UDPv4ClientSocketHandle(address)),
- readevent_ ("senf::console::UDPServer::readevent",
- senf::membind(&UDPServer::handleInput, this),
- handle_,
+ : replies_ (true), emptyReplies_ (true), target_ (),
+ handle_ (senf::UDPv4ClientSocketHandle(address)),
+ readevent_ ("senf::console::UDPServer::readevent",
+ senf::membind(&UDPServer::handleInput, this),
+ handle_,
senf::scheduler::FdEvent::EV_READ),
parser_ (), executor_ ()
{
}
prefix_ senf::console::UDPServer::UDPServer(senf::INet6SocketAddress const & address)
- : replies_ (true), target_ (), handle_ (senf::UDPv6ClientSocketHandle(address)),
- readevent_ ("senf::console::UDPServer::readevent",
- senf::membind(&UDPServer::handleInput, this),
- handle_,
+ : replies_ (true), target_ (), handle_ (senf::UDPv6ClientSocketHandle(address)),
+ readevent_ ("senf::console::UDPServer::readevent",
+ senf::membind(&UDPServer::handleInput, this),
+ handle_,
senf::scheduler::FdEvent::EV_READ),
parser_ (), executor_ ()
{
senf::console::UDPServer::replies(senf::INet4SocketAddress const & address)
{
SENF_ASSERT( handle_.local().family() == senf::INet4SocketAddress::addressFamily );
- target_ = address;
+ target_ = address;
return *this;
}
stream << '\0';
handle_.writeto(address, stream.str());
}
-
+
}
///////////////////////////////cc.e////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
does support multicast operation.
Every UDP packet will be executed in a clean context: No directory groups are open/closed,
- and the current directory is always the root directory.
+ and the current directory is always the root directory.
By default, the server will send command replies via UDP to the sender of the corresponding
incoming command. Replies may however either be completely disabled or be sent to a fixed
///< Open UDP server on \a address
explicit UDPServer(senf::INet6SocketAddress const & address);
///< Open UDP server on \a address
-
+
///@}
///////////////////////////////////////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
unsigned nread (0);
unsigned flags (0);
std::string data;
-
+
void read(senf::ConnectedUDPv4ClientSocketHandle socket, int ev)
{
flags |= ev;
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
argument/return type \a CharT to CharAsString<CharT>:
\code
char foo(char v) { return v; }
-
+
senf::console::root().add(
"foo", boost::function< CharAsString<char> (CharAsString<char>) >(&foo));
\endcode
CharAsString(CharT value_);
operator CharT () const;
CharT value;
- };
+ };
#ifndef DOXYGEN
{
typedef CharAsString<CharT> type;
static bool const singleToken = true;
-
+
static void parse(ParseCommandInfo::TokensRange const & tokens, CharAsString<CharT> & out);
static std::string description();
static std::string str(CharAsString<CharT> value);
struct ReturnValueTraits< CharAsString<CharT> >
{
typedef CharAsString<CharT> type;
-
+
static void format(CharAsString<CharT> value, std::ostream & os);
};
#endif
/** \brief Value range
-
+
A value range may be represented in the console either by a single value (setting both \a
low and \a high to the same value) or as a lower and upper bound seperated by a colon.
/** \brief Bit-mask flag argument type
senf::console::FlagCollection supplies a special argument type for use in registering
- console commands. This argument type is used to represent a bit-mask of single flags.
+ console commands. This argument type is used to represent a bit-mask of single flags.
\code
// Function taking a flags argument
Baz = 4,
Doo = 8 };
SENF_CONSOLE_REGISTER_ENUM(MyFlags, (Foo)(Bar)(Baz)(Boo));
-
+
// Register the function with a FlagCollection argument type
consoleDir.add("func", boost::function<void (FlagCollection<MyFlags>)>(&func));
\endcode
The nice thing is, that \c boot::function supports compatible argument types and does
automatic type conversion. Since a FlagCollection is convertible to and from unsigned long,
- this conversion will work.
+ this conversion will work.
After registering this function, you can call it with a collection of flags as argument
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
senf::console::root().add("test", dir);
std::stringstream ss;
- dir.add("test",
+ dir.add("test",
fty::Command<senf::console::CharAsString<char> (senf::console::CharAsString<char>)>(
&charTest));
std::stringstream ss;
dir.add("test",fty::Command(&collectionTest));
-
+
ss.str("");
SENF_CHECK_NO_THROW(
parser.parse("test/test foo",
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
prefix_ typename senf::console::factory::VariableFactory<Variable>
senf::console::factory::VariableFactory<Variable>::onChange(OnChangeHandler handler)
{
- setOverload_->function(
+ setOverload_->function(
boost::bind(detail::SetVariable<Variable>(var_, handler),_2));
return *this;
}
template <class Variable>
prefix_ senf::console::factory::VariableFactory<Variable>::VariableFactory(Variable & var)
- : ConstVariableFactory<Variable> (var),
+ : ConstVariableFactory<Variable> (var),
setOverload_ (detail::SetVariable<Variable>::create(var)),
var_ (var)
{}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace factory {
/** \brief Variable command attributes (const)
-
+
\see VariableFactory
*/
template <class Variable>
ConstVariableFactory formatter(Formatter formatter);
OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
-
+
explicit ConstVariableFactory(Variable const & var);
private:
boost::optional<std::string> doc_;
boost::optional<std::string> shortdoc_;
};
-
+
/** \brief Variable command attributes
Variable commands allow to register any arbitrary variable as a command node. The variable
Since a variable command is added as a combination of two ordinary overloads, it is possible
to register additional overloads with the same name before or after registering the
- variable.
+ variable.
It is also possible, to register a variable read-only. To achieve this, just wrap it with \c
boost::cref(). Such a variable cannot be changed only queried. Therefore, it does not have
\code
void parser(senf::console::ParseCommandInfo::TokensRange const & tokens, value_type & out);
\endcode
-
+
where \c value_type is the type of the overload
parameter. The parser must read and parse the complete
\a tokens range and return the parsed value in \a
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
typedef detail::CreateParsedCommandOverload<Traits> CreateOverload;
typedef boost::function<void (Variable const &)> OnChangeHandler;
typedef void result_type;
-
+
SetVariable(Variable & var, OnChangeHandler handler = OnChangeHandler());
static typename Traits::Overload::ptr create(Variable & var);
-
+
void operator()(Variable const & value) const;
Variable & var_;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
ss.str("");
dir("var").help(ss);
- BOOST_CHECK_EQUAL(ss.str(),
+ BOOST_CHECK_EQUAL(ss.str(),
"Usage:\n"
" 1- var\n"
" 2- var new_value:number\n"
}
namespace {
-
+
class Test2
{
public:
senf::console::ScopedDirectory<Test2> dir;
-
+
Test2() : dir(this), var_(0)
{ dir.add("var", senf::console::factory::Variable(boost::ref(var_))); }
-
+
private:
int var_;
};
-
+
}
SENF_AUTO_UNIT_TEST(memberVariables)
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
senf::console::ScopedDirectory<TestObject> dir;
- TestObject()
- : dir(this)
+ TestObject()
+ : dir(this)
{
dir.add("vat", fty::Command(&TestObject::vat, this)
.arg("vat", "VAT in %", kw::default_value = 19)
.doc("Returns the amount of {vat}-% VAT included in {amount}") );
}
- double vat (int vat, double amount)
+ double vat (int vat, double amount)
{
return amount * vat/(100.0+vat);
}
return daemonize_;
}
-prefix_ int senf::Daemon::argc()
+prefix_ int senf::Daemon::argc()
{
return argc_;
}
-prefix_ char const ** senf::Daemon::argv()
+prefix_ char const ** senf::Daemon::argv()
{
return argv_;
}
stderr_ = ::dup(fd);
if (stderr_ < 0)
SENF_THROW_SYSTEM_EXCEPTION("::dup()");
- }
+ }
else {
fd = ::open(stdoutLog_.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
if (fd < 0)
{
if (! stdoutLog_.empty()) {
int fd (::open(stdoutLog_.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666));
- if (fd < 0)
+ if (fd < 0)
goto error;
- if (::dup2(fd, 1) < 0)
+ if (::dup2(fd, 1) < 0)
goto error;
if (stderrLog_ == stdoutLog_) {
- if (::dup2(fd, 2) < 0)
+ if (::dup2(fd, 2) < 0)
goto error;
return;
}
}
if (! stderrLog_.empty()) {
int fd (::open(stderrLog_.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666));
- if (fd < 0)
+ if (fd < 0)
goto error;
- if (::dup2(fd, 2) < 0)
+ if (::dup2(fd, 2) < 0)
goto error;
}
return;
prefix_ void senf::Daemon::detach()
{
if (daemonize_ && ! detached_) {
- // Wow .. ouch ..
+ // Wow .. ouch ..
// To ensure all data is written to the console log file in the correct order, we suspend
// execution here until the parent process tells us to continue via SIGUSR1: We block
// SIGUSR1 and install our own signal handler saving the old handler and signal mask. Then
if (pidfileCreate())
pidfileCreated_ = true;
else {
- std::cerr << "PID file '" << pidfile_
+ std::cerr << "PID file '" << pidfile_
<< "' creation failed. Daemon running ?" << std::endl;
return 1;
}
LIBC_CALL( ::sigprocmask, (SIG_BLOCK, &cldsig, &oldsig) );
if (! senf::scheduler::empty() ) {
- std::cerr <<
+ std::cerr <<
"\n"
"*** WARNING ***\n"
"Scheduler not empty before fork(). THIS MUST NOT HAPPEN.\n"
"\n*** WARNING ***\n"
"\n";
}
-
+
LIBC_CALL_RV( pid, ::fork, () );
if (pid == 0) {
// Ouch ... ensure, the daemon watcher does not remove the pidfile ...
pidfile_ = "";
-
+
LIBC_CALL( ::close, (coutpipe[1]) );
LIBC_CALL( ::close, (cerrpipe[1]) );
}
if (::link(tempname.c_str(), pidfile_.c_str()) < 0) {
- if (errno != EEXIST)
+ if (errno != EEXIST)
SENF_THROW_SYSTEM_EXCEPTION("") << linkErrorFormat % pidfile_ % tempname;
}
else {
int old_pid (-1);
std::ifstream pidf (pidfile_.c_str());
if ( ! (pidf >> old_pid)
- || old_pid < 0
- || ::kill(old_pid, 0) >= 0
+ || old_pid < 0
+ || ::kill(old_pid, 0) >= 0
|| errno == EPERM ) {
LIBC_CALL( ::unlink, (tempname.c_str()) );
return false;
return false;
}
}
-
+
{
std::ofstream pidf (tempname.c_str());
pidf << ::getpid() << std::endl;
::sigaction(SIGFPE, &sa, NULL);
::sigaction(SIGBUS, &sa, NULL);
::sigaction(SIGSEGV, &sa, NULL);
-#ifdef SIGSTKFLT //SIGSTKFLT is used for stack faults on coprocessors. That condition doesn't exist on MIPS
+#ifdef SIGSTKFLT //SIGSTKFLT is used for stack faults on coprocessors. That condition doesn't exist on MIPS
::sigaction(SIGSTKFLT, &sa, NULL);
#endif
::sigaction(SIGSYS, &sa, NULL);
stderr_(stderr), sigChld_(false),
cldSignal_ (SIGCHLD, senf::membind(&DaemonWatcher::sigChld, this)),
timer_ ("senf::detail::DaemonWatcher::childOk", senf::membind(&DaemonWatcher::childOk, this)),
- coutForwarder_(coutpipe_, boost::bind(&DaemonWatcher::pipeClosed, this, 1)),
- cerrForwarder_(cerrpipe_, boost::bind(&DaemonWatcher::pipeClosed, this, 2))
+ coutForwarder_(coutpipe_, boost::bind(&DaemonWatcher::pipeClosed, this, 1)),
+ cerrForwarder_(cerrpipe_, boost::bind(&DaemonWatcher::pipeClosed, this, 2))
{
coutForwarder_.addTarget(1);
if (stdout_ >= 0)
// senf::detail::DaemonWatcher::Forwarder
prefix_ senf::detail::DaemonWatcher::Forwarder::Forwarder(int src, Callback cb)
- : src_(src), cb_(cb),
+ : src_(src), cb_(cb),
readevent_("senf::detail::DaemonWatcher::Forwarder::readevent", senf::membind(&Forwarder::readData, this),
src_, scheduler::FdEvent::EV_READ)
{}
while (1) {
n = ::read(src_,buf,1024);
if (n<0) {
- if (errno != EINTR)
+ if (errno != EINTR)
SENF_THROW_SYSTEM_EXCEPTION("::read()");
- }
- else
+ }
+ else
break;
}
if (n == 0) {
if (buffer_.empty())
- cb_();
+ cb_();
src_ = -1;
readevent_.disable();
return;
}
prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(int event, Target * target)
-{
+{
if (event != scheduler::FdEvent::EV_WRITE) {
// Broken pipe while writing data ? Not much, we can do here, we just drop the data
targets_.erase_and_destroy(Targets::current(*target),DestroyDelete());
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
\li <i>Optional foreground execution.</i> The daemon may be started in the foreground for
debugging purposes. In this case, the console log file(s) is/are automatically
suppressed.
-
+
Starting the daemon process proceeds along the following steps:
\li The daemon is started by calling the daemon class instances start() member. This
normally happens from the \c main() function generated by \ref SENF_DAEMON_MAIN().
created. The parent (foreground) process keeps running overseeing the daemon process.
\li main() is called. This virtual member may optionally be overridden in the derived
class. Here we assume, main() is not overridden so the default implementation is used.
- \li main() calls init().
+ \li main() calls init().
\li after init() returns, main() calls detach().
\li detach() signals successful startup to the parent process. The parent process terminates
leaving the daemon process running in the background.
arguments. It just checks, if any of above arguments are present and precesses them. Other
arguments are completely ignored. The command line parameters should be completely processed
within init().
-
+
*/
class Daemon : boost::noncopyable
{
///////////////////////////////////////////////////////////////////////////
// Types
-
+
/// Select standard stream to redirect
- enum StdStream {
+ enum StdStream {
StdOut /** Standard output stream */
, StdErr /** Standard error stream */
, Both /** Both, standard output and error stream */
- };
+ };
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
void daemonize(bool); ///< Configure whether to run in fore- or background
bool daemon(); ///< \c true, if running as daemon
- void consoleLog(std::string const &, StdStream which = Both);
+ void consoleLog(std::string const &, StdStream which = Both);
///< Configure console log file
/**< May be called multiple times to set the log file
for stdout and stderr seperately. Any standard stream
not assigned to a log file will be redirected to
- <tt>/dev/null</tt>.
+ <tt>/dev/null</tt>.
When running in the foreground, the log files will be
ignored. */
SIGHUP calls logReopen. */
///\}
-
+
int start(int argc, char const ** argv); ///< Called from main() to launch daemon.
/**< Normally not called directly but from the
\ref SENF_DAEMON_MAIN macro. */
private:
- class Forwarder
+ class Forwarder
{
public:
typedef boost::function<void ()> Callback;
Callback cb_;
scheduler::FdEvent readevent_;
};
-
+
void pipeClosed(int id);
void sigChld(siginfo_t const &);
void childDied();
class MyDaemon : public senf::Daemon
{
- void configure() {
- std::cout << "Running configure()" << std::endl;
+ void configure() {
+ std::cout << "Running configure()" << std::endl;
pidFile("invalid.pid");
consoleLog("invalid.log");
senf::Daemon::configure();
}
- void init() {
- std::cout << "Running init()" << std::endl;
+ void init() {
+ std::cout << "Running init()" << std::endl;
std::cerr << "(stderr)" << std::endl;
}
void run() {
- std::cout << "Running run()" << std::endl;
+ std::cout << "Running run()" << std::endl;
delay(2000);
}
};
}
signal(SIGCHLD, SIG_DFL);
int status;
- if (::waitpid(pid, &status, 0) < 0)
+ if (::waitpid(pid, &status, 0) < 0)
throw senf::SystemException("::waitpid()");
if (WIFSIGNALED(status))
- std::cerr << "Terminated with signal "
+ std::cerr << "Terminated with signal "
<< senf::signalName(WTERMSIG(status)) << "(" << WTERMSIG(status) << ")\n";
else if (WIFEXITED(status))
std::cerr << "Exited normally with exit status " << WEXITSTATUS(status) << "\n";
SENF_AUTO_UNIT_TEST(testDaemon)
{
- char const * args[] = { "run",
- "--console-log=testDaemon.log",
+ char const * args[] = { "run",
+ "--console-log=testDaemon.log",
"--pid-file=testDaemon.pid" };
SENF_CHECK_NO_THROW( BOOST_CHECK_EQUAL( run(sizeof(args)/sizeof(*args), args), 0 ) );
BOOST_CHECK( ! boost::filesystem::exists("invalid.pid") );
BOOST_CHECK( boost::filesystem::exists("testDaemon.pid") );
BOOST_REQUIRE( boost::filesystem::exists("testDaemon.log") );
-
+
boost::filesystem::rename("testDaemon.log", "testDaemon.log.1");
{
std::ifstream pidFile ("testDaemon.pid");
BOOST_CHECK( ! boost::filesystem::exists("testDaemon.pid") );
BOOST_CHECK( boost::filesystem::exists("testDaemon.log") );
BOOST_CHECK( boost::filesystem::exists("testDaemon.log.1") );
-
+
std::ifstream log ("testDaemon.log.1");
std::stringstream data;
data << log.rdbuf();
member functions.
\code
#include <senf/Utils/Daemon.hh>
-
+
class MyDaemon : public senf::Daemon
{
void configure() {
// here after setting default parameters
senf::Daemon::configure();
}
-
+
void init() {
// Initialize application. Setup all necessary objects. After init()
// has completed, the startup should not fail
Since there are times, where separating init() and run() into two separate functions is
difficult, instead of defining init() and run(), the member main() may be defined. This member
must call detach() as soon as initialization is completed to detach from the foreground
- terminal.
+ terminal.
\code
#include <senf/Utils/Daemon.hh>
-
+
class MyDaemon : public senf::Daemon
{
// 'configure()' like above. Don't implement 'init()' or 'run()' if you implement 'main()'.
SENF_DAEMON_MAIN(MyDaemon);
\endcode
- \see
+ \see
\ref senf::Daemon class \n
\ref SENF_DAEMON_MAIN() main() implementation macro
*/
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
}
#endif
-///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
// senf::Exception
prefix_ senf::Exception::~Exception()
init("", code _SENF_EXC_DEBUG_ARGS_P);
}
-prefix_ senf::SystemException::SystemException(std::string const & descr, int code
+prefix_ senf::SystemException::SystemException(std::string const & descr, int code
_SENF_EXC_DEBUG_ARGS_ND)
{
init(descr, code _SENF_EXC_DEBUG_ARGS_P);
int c6, int c7, int c8, int c9)
const
{
- return
+ return
(c0 && code_ == c0) ||
(c1 && code_ == c1) ||
(c2 && code_ == c2) ||
use <a href="http://www.boost.org/libs/format/doc/format.html">Boost.Format</a>:
\code
- try {
+ try {
// ...
}
catch (senf::ExceptionMixin & e) {
SENF_WRAP_EXC(std::bad_cast)
SENF_WRAP_EXC(somelib::FooException)
}
- \endcode
+ \endcode
The re-thrown exception can then be caught as <tt>std::bad_cast</tt> or as senf::ExceptionMixin
as needed. It is safe, to wrap an exception twice (the macro will detect this case).
\code
/**< Adds \a text to the description text. */
protected:
- explicit ExceptionMixin(std::string const & description = "");
+ explicit ExceptionMixin(std::string const & description = "");
///< Initialize exception with string
/**< \a description is the initial error description
string. This should probably be a string constant
virtual char const * what() const throw();
///< get exception description and backtrace if available
/**< get description of the exception (message()) and backtrace
- information if SENF is compiled with \c SENF_DEBUG */
+ information if SENF is compiled with \c SENF_DEBUG */
protected:
explicit Exception(std::string const & description = "");
};
-
+
/** \brief Wrapper for standard non-senf exceptions
This class wraps an exception of type \a BaseException and adds functionality from
exception description string. This operator allows to
use Exception instances like streams. The conversion is
performed using <code>boost::lexical_cast</code> and is
- therefor identical to a streaming operation.
+ therefor identical to a streaming operation.
\see \ref exception */
\code
// Standard usage: Take \c errno from environment
- throw senf::SystemException("::open()")
+ throw senf::SystemException("::open()")
<< " while opening configuration file: " << filename;
// You may however explicitly specify the errno value
int errorNumber() const; ///< Error code (\c errno number)
char const * errorString() const; ///< Error string (\c strerror() value)
- bool anyOf(int c0, int c1=0, int c2=0, int c3=0, int c4=0, int c5=0,
+ bool anyOf(int c0, int c1=0, int c2=0, int c3=0, int c4=0, int c5=0,
int c6=0, int c7=0, int c8=0, int c9=0) const;
///< \c true, if errorNumber() is one of \a c0 ... \a c9
private:
void init(std::string const & descr, int code _SENF_EXC_DEBUG_ARGS_ND);
-
+
int code_;
};
// compile-command: "scons -u test"
// comment-column: 40
// End:
-
+
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace {
- char const SIPrefix[] = { 'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm',
- ' ',
+ char const SIPrefix[] = { 'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm',
+ ' ',
'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
unsigned const SIScales = 8;
os.fill(v_.fill_);
unsigned prec (os.precision());
- if (prec < 4)
+ if (prec < 4)
prec = 4;
unsigned w (os.width());
char fill (os.fill());
std::ios_base::fmtflags align (flags & std::ios_base::adjustfield);
if (! std::isnan(v_.d_))
minw += prec+3;
-
+
float ref (std::fabs(v_.v_));
float v (v_.v_);
float d (0.0);
if (w > 0) {
if ((align == 0 || align == std::ios_base::right || align == std::ios_base::internal))
os << std::setw(prec+2+(w>minw ? w-minw : 0));
- else
+ else
os << std::right << std::setfill(' ') << std::setw(prec+2);
}
else
os << SIPrefix[scale/3+SIScales];
}
else if ((flags & std::ios_base::showpoint) || scale != 0)
- os << ((flags & std::ios_base::uppercase)?'E':'e')
+ os << ((flags & std::ios_base::uppercase)?'E':'e')
<< std::showpos << std::internal << std::setw(3) << scale;
else if (w > 0)
os << " ";
int bytes ((bits+7)/8);
int digs (int(2.4*bytes)+1);
std::stringstream ss;
- ss << (sign ? (sign<0 ? "-" : " ") : "")
- << "0x" << std::setw(2*bytes) << std::setfill('0') << std::hex
+ ss << (sign ? (sign<0 ? "-" : " ") : "")
+ << "0x" << std::setw(2*bytes) << std::setfill('0') << std::hex
<< 1u*v
<< " (" << std::setw(digs+(sign ? 1 : 0)) << std::setfill(' ') << std::dec;
if (sign)
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// senf::format::IndentHelper
prefix_ senf::format::IndentHelper::IndentHelper()
- : instance_level(1)
+ : instance_level(1)
{
- ++static_level;
+ ++static_level;
}
prefix_ senf::format::IndentHelper::~IndentHelper()
{
- static_level -= instance_level;
+ static_level -= instance_level;
}
prefix_ void senf::format::IndentHelper::increase()
{
- ++static_level;
- ++instance_level;
+ ++static_level;
+ ++instance_level;
}
-prefix_ unsigned int senf::format::IndentHelper::level()
+prefix_ unsigned int senf::format::IndentHelper::level()
const
-{
- return static_level;
+{
+ return static_level;
}
prefix_ std::ostream & senf::format::operator<<(std::ostream & os, senf::format::IndentHelper const & indent)
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////cti.p///////////////////////////////////////
template <class T>
-prefix_ std::string
+prefix_ std::string
senf::format::dumpint(T const & v, typename boost::enable_if<boost::is_signed<T> >::type *)
-{
+{
return detail::dumpintSigned(v, std::numeric_limits<T>::digits);
}
prefix_ std::string
senf::format::dumpint(T const & v, typename boost::enable_if<boost::is_unsigned<T> >::type *)
{
- return detail::dumpintUnsigned(v, std::numeric_limits<T>::digits);
+ return detail::dumpintUnsigned(v, std::numeric_limits<T>::digits);
}
template <class T>
-prefix_ std::string
+prefix_ std::string
senf::format::dumpint(T const & v, typename boost::enable_if<boost::is_signed<typename T::value_type> >::type *)
-{
+{
return detail::dumpintSigned(v.value(), std::numeric_limits<typename T::value_type>::digits);
}
prefix_ std::string
senf::format::dumpint(T const & v, typename boost::enable_if<boost::is_unsigned<typename T::value_type> >::type *)
{
- return detail::dumpintUnsigned(v.value(), std::numeric_limits<typename T::value_type>::digits);
+ return detail::dumpintUnsigned(v.value(), std::numeric_limits<typename T::value_type>::digits);
}
///////////////////////////////cti.e///////////////////////////////////////
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
\par \c std::\c showpoint, \c std::\c noshowpoint
If the \c showpoint flag is set, the exponent will be output even if it is 0. Otherwise,
if \c width is set, the exponent will be replaced with 4 blanks.
-
+
\par \c std::\c uppercase, \c std::\c nouppercase
If the \c uppercase flag is set, the exponent letter will be an uppercase 'E' instead of
'e'. SI prefixes are \e not uppercased, since some SI prefixes differ only in case.
os << std::setw(1) << senf::format::eng(1.23);
-> " 1.230 "
- os << std::setw(25) << std::setprecision(5) << std::showpos << std::uppercase
+ os << std::setw(25) << std::setprecision(5) << std::showpos << std::uppercase
<< std::internal << senf::format::eng(12345,67);
-> "+ 12.35+-000.07E+03"
senf::str(senf::format::eng(12.345,67).setw().setprecision(5).showpoint().uppercase())
-> " 12.35+-67.00E+00"
\endcode
-
+
\param[in] v value
\param[in] d optional delta
private:
float v_;
float d_;
-
+
mutable bool haveWidth_;
mutable unsigned width_;
mutable bool havePrecision_;
template <class T>
streamable_type dumpint(T const & v);
-#else
+#else
- template <class T>
- std::string dumpint(T const & v,
+ template <class T>
+ std::string dumpint(T const & v,
typename boost::enable_if<boost::is_signed<T> >::type * = 0);
- template <class T>
- std::string dumpint(T const & v,
+ template <class T>
+ std::string dumpint(T const & v,
typename boost::enable_if<boost::is_unsigned<T> >::type * = 0);
-
- template <class T>
- std::string dumpint(T const & v,
+
+ template <class T>
+ std::string dumpint(T const & v,
typename boost::enable_if<boost::is_signed<typename T::value_type> >::type * = 0);
- template <class T>
- std::string dumpint(T const & v,
+ template <class T>
+ std::string dumpint(T const & v,
typename boost::enable_if<boost::is_unsigned<typename T::value_type> >::type * = 0);
#endif
-
+
/** \brief Helper class to easily achieve indent levels
-
- This class helps to achieve indent levels across function calls. Every instance
+
+ This class helps to achieve indent levels across function calls. Every instance
increases the static indent level. On destruction the level is decreased to the level
before the instance.
The following example illustrates the use of this class:
std::cout << indent << "f2 end\n";
}
f2()
- \endcode
+ \endcode
Output:
<pre>
f2 begin
f1
f2 end
</pre>
- Here <tt>f1()</tt> and <tt>f2()</tt> don't need to know to current indent level,
+ Here <tt>f1()</tt> and <tt>f2()</tt> don't need to know to current indent level,
they just increase the level by instantiating IndentHelper.
-
+
\ingroup senf_utils_format
*/
class IndentHelper
static unsigned int static_level;
unsigned int instance_level;
public:
-
+
IndentHelper(); ///< Construct new IndentHelper instance
/**< The static indent level is increased by one. */
~IndentHelper(); ///< Destruct IndentHelper instance
/**< The indent level of the instance is increases by one. */
unsigned int level() const; ///< return the current indent level
};
-
+
/** \brief Output indent to given ostream
\related IndentHelper
*/
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
CheckFormat( (1.345e-3, 3.456), "0.0+-3.5" );
# undef CheckFormat
-
+
// From documentation
-
+
{
std::stringstream ss;
ss << senf::format::eng(1.23);
{
std::stringstream ss;
- ss << std::setw(25) << std::setprecision(5) << std::showpos << std::uppercase
+ ss << std::setw(25) << std::setprecision(5) << std::showpos << std::uppercase
<< std::internal << senf::format::eng(12345,67);
BOOST_CHECK_EQUAL( ss.str(), "+ 12.35+-000.07E+03" );
}
SENF_AUTO_UNIT_TEST(dumpint)
{
std::stringstream ss;
-
+
# define CheckFormat(v,s) \
{ \
ss.str(""); \
{
std::stringstream ss;
f2(ss);
- BOOST_CHECK_EQUAL( ss.str(),
+ BOOST_CHECK_EQUAL( ss.str(),
" f2_1\n"
" f1\n"
" f2_2\n"
// $Id$
//
-// Copyright (C) 2010
+// Copyright (C) 2010
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2010
+// Copyright (C) 2010
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
-
+
/** \brief Calculate TCP/IP 16bit checksum value
This class allows calculation of the 16bit checksum value as defined in the TCP/IP v4
///< Feed range of bytes
boost::uint16_t sum() const; ///< Calculate checksum
-
+
protected:
private:
bool odd_;
};
-
+
}
///////////////////////////////hh.e////////////////////////////////////////
}
template<class Iterator>
- void do(Iterator i, boost::true_type)
+ void do(Iterator i, boost::true_type)
{
typename Iterator::pointer p (senf::storage_iterator(i));
// Manipulate the container by manipulating the data pointed at via 'p'
Thie \ref senf::storage_iterator helper function will convert an iterator to a pointer to
the same element the iterator is referencing.
-
+
This trait will return \c true for pointers. Additonally it should be configured to return
true for all standard containers which obey above implementation restrictions. This
typically includes \c std::vector and \c std::basic_string.
{};
/** \brief Convert contiguous storage iterator to pointer
-
+
storage_iterator will convert a contiguous storage iterator into a pointer to the same
element in the container. This allows to directly access the containers storage.
*/
template <class Iterator>
typename std::iterator_traits<Iterator>::pointer storage_iterator(Iterator i);
-
+
}
///////////////////////////////hh.e////////////////////////////////////////
{};
template <class CharT, class Traits, class Alloc>
- struct contiguous_storage_iterator<
+ struct contiguous_storage_iterator<
::__gnu_cxx::__normal_iterator<CharT*, std::basic_string<CharT, Traits, Alloc> > >
: public boost::true_type
{};
if (i->limit < l)
l = i->limit;
}
- if (i == i_end)
+ if (i == i_end)
routingCache_[stream.index].routes.push_back(RouteEntry(limit, &target));
else
for (; i != i_end; ++i)
prefix_ unsigned senf::log::detail::AreaBase::limit(StreamBase const & stream)
const
{
- return stream.index >= routingCache_.size() ?
+ return stream.index >= routingCache_.size() ?
DISABLED::value : routingCache_[stream.index].limit;
}
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
-namespace log {
+namespace log {
namespace detail { struct AreaBase; }
- /** \brief Area registry
-
- The area registry keeps track of all areas defined.
+ /** \brief Area registry
+
+ The area registry keeps track of all areas defined.
The area registry exposes a forward sequence interface which allows to query the list of all
registered areas.
{
typedef std::map<std::string, detail::AreaBase const *> Registry;
- struct SelectName
+ struct SelectName
{
typedef std::string result_type;
std::string const & operator()(Registry::value_type const & v) const;
friend class senf::singleton<AreaRegistry>;
friend class detail::AreaBase;
friend class Target;
- };
-
+ };
+
}}
///////////////////////////////hh.e////////////////////////////////////////
{
AreaBase();
virtual ~AreaBase();
-
+
std::string fullName() const;
virtual std::string v_name() const;
bool alive() const;
unsigned limit(StreamBase const & stream) const;
- void updateRoutingCache(Target & target, StreamBase const & stream, unsigned limit) const;
- void removeRoutingCache(Target & target, StreamBase const & stream) const;
+ void updateRoutingCache(Target & target, StreamBase const & stream, unsigned limit) const;
+ void removeRoutingCache(Target & target, StreamBase const & stream) const;
void write(time_type timestamp, StreamBase const & stream, unsigned level,
std::string const & msg) const;
{
BOOST_CHECK( true );
#if 0
- // Need to rewrite this test ...
+ // Need to rewrite this test ...
char const * areas[] = { "GlobalTestArea",
- "senf::log::DefaultArea",
- "senf::log::test::Foo",
+ "senf::log::DefaultArea",
+ "senf::log::test::Foo",
"senf::log::test::myArea" };
BOOST_CHECK_EQUAL_COLLECTIONS( senf::log::AreaRegistry::instance().begin(),
</pre>
All the entries specified via \c SENF_LOG_CONF are applied in a fixed order:
-
+
\li First the entries which have both a stream and an area specified are checked
\li next all entries with area but no stream given are checked
\li followed by all entries with a given stream but no area
consoleLog.route<foo::Transactions, senf::log::IMPORTANT>();
fileLog.route<foo::Transactions>();
- \endcode
+ \endcode
Here we see an already relatively complex setup: All debug messages (that is, those, which are
not disabled at compile time) are routed to the console. We also route important transactions to
the console \e except transactions from the \c foo::SomeClass area. The \c fileLog simply
enabled \e explicitly by setting \c SENF_LOG_CONF so they can be routed.
\section config_fallback Fallback routing
-
+
There are two cases, where this setup may lead to inadvertently lost log messages:
\li When using a library which does internally use the Logger but not initializing the logger in
your application.
\li When log messages are created during initialization of static objects.
Since no route is set up in these cases, the messages will be dropped.
-
+
To counter this problem, the logger is initially in <em>fallback routing</em> state. If any log
message arrives in this state, the message will be logged to the console if it is above the
default runtime limit of it's stream. The first routing statement on any target will take the
<tr><td>name</td> <td>::= arbitrary C++ identifier</td></tr>
</table>
- \ref SENF_LOG_CONF is a Boost.Preprocessor style sequence of 3-tuples.
+ \ref SENF_LOG_CONF is a Boost.Preprocessor style sequence of 3-tuples.
The first tuple element \e optional_stream specifies the stream to match. If this is
<tt>(_)</tt>, the entry will match any stream.
# endif
/** \brief Check, if logging is enabled for stream/area/level tuple
-
+
This is a template meta-function which will check, whether logging to the given combination
of parameters \a Stream, \a Area and \a Level is compile-time enabled. The logging might
still be disabled at runtime.
\code
- if (senf::log::Enabled<senf::log::Debug,
- senf::log::DefaultArea,
+ if (senf::log::Enabled<senf::log::Debug,
+ senf::log::DefaultArea,
senf::log::VERBOSE>::value) {
// ...
}
SENF_AUTO_UNIT_TEST(logConfig)
{
- BOOST_CHECK(( senf::log::Enabled< senf::log::Debug,
- senf::log::DefaultArea,
+ BOOST_CHECK(( senf::log::Enabled< senf::log::Debug,
+ senf::log::DefaultArea,
senf::log::NOTICE >::value ));
- BOOST_CHECK(( ! senf::log::Enabled< senf::log::Debug,
- senf::log::DefaultArea,
+ BOOST_CHECK(( ! senf::log::Enabled< senf::log::Debug,
+ senf::log::DefaultArea,
senf::log::VERBOSE >::value ));
- BOOST_CHECK(( ! senf::log::Enabled< senf::log::test::myStream,
- senf::log::DefaultArea,
+ BOOST_CHECK(( ! senf::log::Enabled< senf::log::test::myStream,
+ senf::log::DefaultArea,
senf::log::VERBOSE >::value ));
- BOOST_CHECK(( senf::log::Enabled< senf::log::test::myStream,
- senf::log::test::Foo,
+ BOOST_CHECK(( senf::log::Enabled< senf::log::test::myStream,
+ senf::log::test::Foo,
senf::log::VERBOSE >::value ));
}
//#include "ConsoleTarget.mpp"
///////////////////////////////hh.p////////////////////////////////////////
-namespace senf {
+namespace senf {
namespace log {
/** \brief Write %log messages to std::cout
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
-
+
static ConsoleTarget & instance();
///@}
///////////////////////////////cc.p////////////////////////////////////////
namespace {
-
+
std::string getNodename(std::string const & filename, std::string const & nodename)
{
if (! nodename.empty())
prefix_ senf::log::FileTarget::FileTarget(std::string const & filename,
std::string const & nodename)
- : ofstream_t (filename.c_str(), std::ofstream::app),
- IOStreamTarget (getNodename(filename, nodename), ofstream_t::member),
+ : ofstream_t (filename.c_str(), std::ofstream::app),
+ IOStreamTarget (getNodename(filename, nodename), ofstream_t::member),
file_ (filename)
{
namespace fty = senf::console::factory;
fty::Command(SENF_MEMBINDFNP(void, FileTarget, reopen, ()))
.doc("Reopen logfile") );
consoleDir()
- .add("reopen",
+ .add("reopen",
fty::Command(SENF_MEMBINDFNP(void, FileTarget, reopen, (std::string const &)))
.arg("filename","new filename")
.overloadDoc("Reopen logfile under new name") );
}
prefix_ boost::shared_ptr<senf::console::DirectoryNode>
-senf::log::FileTarget::RegisterConsole::create(std::string const & filename,
+senf::log::FileTarget::RegisterConsole::create(std::string const & filename,
std::string const & nodename)
{
std::auto_ptr<Target> tp (new FileTarget(filename, nodename));
\code
senf::log::FileTarget target ("file.name");
-
+
// Route all messages to this file.
target.route();
\endcode
\ingroup targets
*/
- class FileTarget
+ class FileTarget
: private boost::base_from_member<std::ofstream>,
public IOStreamTarget
{
///\name Structors and default members
///@{
- explicit FileTarget(std::string const & filename, std::string const & nodename = "");
+ explicit FileTarget(std::string const & filename, std::string const & nodename = "");
///< Construct FileTarget writing to \a file
///@}
BOOST_CHECK_EQUAL( std::string(buffer), message);
SENF_CHECK_NO_THROW( boost::filesystem::remove(filename) );
-
+
target.reopen();
BOOST_REQUIRE( boost::filesystem::exists(filename));
SENF_CHECK_NO_THROW( boost::filesystem::remove(filename) );
-
+
filename = std::string("/tmp/senf_fileTarget_test2.log");
target.reopen( filename);
BOOST_REQUIRE( boost::filesystem::exists(filename));
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
\verbatim <date> [<level>][<area>] <message> \endverbatim
The \e area will be omitted if it is \c senf::log::DefaultArea.
-
+
\warning The class keeps a reference to the passed stream.
-
+
\ingroup targets
*/
class IOStreamTarget
using detail::LogFormat::showArea;
using detail::LogFormat::timeFormat;
using detail::LogFormat::tag;
-
+
protected:
- void v_write(time_type timestamp, std::string const & stream,
- std::string const & area, unsigned level,
+ void v_write(time_type timestamp, std::string const & stream,
+ std::string const & area, unsigned level,
std::string const & message);
private:
namespace log {
/** \defgroup loglevels Log levels
-
+
These are the valid %log levels with some additional special values:
<dl><dt>VERBOSE</dt><dd>Really verbose %log messages. Messages at this level are used for
<dt>CRITICAL</dt><dd>Error condition which does not terminate the program completely but has
non-reversible adverse effects</dd>
-
+
<dt>FATAL</dt><dd>Error condition which does terminate program execution or enforces a
restart or some kind of re-initialization with loss of state and context.</dd></dl>
There are also some special values which <em>must not be used as a %log level</em>:
-
- <dl><dt>DISABLED</dt><dd>Disable all %log messages.</dd>
+
+ <dl><dt>DISABLED</dt><dd>Disable all %log messages.</dd>
<dt>NONE</dt><dd>Special value which signifies inheritance of the default %log
level.</dd></dl>
*/
///\{
-
+
/** \brief Log level %VERBOSE
\see loglevels */
struct VERBOSE : public detail::LevelBase { static unsigned const value = 1; };
struct NONE : public detail::LevelBase { static unsigned const value = 0; };
///\}
-
+
static char const * const LEVELNAMES[8] = {
"NONE", "VERBOSE", "NOTICE", "MESSAGE", "IMPORTANT", "CRITICAL", "FATAL", "DISABLED" };
namespace senf {
namespace log {
namespace detail {
-
+
/// Internal: Log level base class
struct LevelBase {};
SENF_LOG( (senf::log::Debug)(senf::log::NOTICE)(FroblizerArea)("The log message") );
\endcode
- The argument is comprised of a sequence of parameters and the %log message itself.
+ The argument is comprised of a sequence of parameters and the %log message itself.
The parameters are
- the <em>%log stream</em>,
- the <em>%log area</em>,
- the <em>%log level</em>.
-
+
These parameters are optional and may be specified <i>in arbitrary order</i> (with the %log
message always being the last sequence element) and even multiple times in the parameter
sequence. If some argument type occurs multiple times, the last occurrence wins. If any one of
The %log level senf::log::NONE is special. If the %log level is set to this value, the %log level
will be set from the stream provided default value.
-
+
All these parameters must be <em>compile time constants</em> (they are all types, so it's
difficult for them to be something else).
SENFLogParameters::area, \
SENFLogParameters::level >(log.str()); \
} \
- } while(0)
+ } while(0)
#define SENF_LOG_BLOCK_TPL_(parameters, block) \
do { \
typename SENFLogParameters::area, \
typename SENFLogParameters::level>(log.str()); \
} \
- } while(0)
+ } while(0)
///////////////////////////////ih.e////////////////////////////////////////
#endif
target.route<senf::log::Debug>();
// We cannot easily check the exact log string since that includes the current date/time
-
+
SENF_LOG_DEFAULT_STREAM(senf::log::Debug);
SENF_LOG_DEFAULT_AREA(senf::log::DefaultArea);
SENF_LOG_DEFAULT_LEVEL(senf::log::VERBOSE);
SENF_LOG((senf::log::VERBOSE)("Log message 2"));
BOOST_CHECK( target.str().empty() );
target.clear();
-
+
SENF_LOG((senf::log::IMPORTANT)("Important message"));
std::cerr << target.str();
BOOST_CHECK( ! target.str().empty() );
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
<< std::setfill('0') << std::setw(9)
<< (delta % 1000000000ll);
}
- else
+ else
datestream_ << senf::ClockService::abstime(timestamp);
datestream_ << ' ';
}
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
void tag(std::string const & tag); ///< Set tag (log line prefix)
protected:
- std::string prefix(time_type timestamp, std::string const & stream,
+ std::string prefix(time_type timestamp, std::string const & stream,
std::string const & area, unsigned level);
bool isPlainFormat() const;
void consoleFormat(std::ostream & os);
<em>disabled</em> at compile time. senf::log::VERBOSE message will therefore only appear,
if you explictly enable the messages for the area in question using (here for the area
<code>some::Area</code>)
- <pre>
- g++ ... -DSENF_LOG_CONF="(( (senf)(log)(Debug), (some)(Area), VERBOSE ))"
+ <pre>
+ g++ ... -DSENF_LOG_CONF="(( (senf)(log)(Debug), (some)(Area), VERBOSE ))"
</pre>
in addition to routing the messages at runtime. For more, see \ref config.
any number of \e targets. A \e target receives messages and using it's routing information
decides, wether the message is output or not. A message may be routed to multiple targets
simultaneously or may not be output by any target at all. (see: \ref targets)
-
+
\section logging_tutorial Tutorial introduction
Using the logging library mostly concerns using \ref SENF_LOG statements in your code. There are
\code
namespace foo {
- // Define a new log stream with default level, runtime limit and compile time limit
+ // Define a new log stream with default level, runtime limit and compile time limit
// set to senf::log::MESSAGE
SENF_LOG_DEFINE_STREAM( UserLog, senf::log::MESSAGE, senf::log::MESSAGE, senf::log::MESSAGE );
design goals
\li Flexible configuration at compile and runtime
\li Concise usage and simple interface
- \li Zero overhead for compile-time disabled log messages
+ \li Zero overhead for compile-time disabled log messages
I did not find any non-mcaro implementation which was not either completely convoluted,
unusable or slow. So I turned to a macro based implementation which can provide all the
namespace senf {
namespace log {
-
+
class DefaultArea;
class Debug;
class NONE;
senf::mpl::rv<5> Parameters_select_(AliasBase *);
template <class Base, class Param>
- struct Parameters_<Base,Param,5>
+ struct Parameters_<Base,Param,5>
: public Param::template apply<Base>::type
{};
// this name is created by SENF_LOG_CLASS_AREA()
template <class T>
senf::mpl::rv<6> Parameters_select_(
- T *,
+ T *,
typename boost::disable_if< boost::is_convertible<T*,StreamBase*> >::type * = 0,
typename boost::disable_if< boost::is_convertible<T*,AreaBase*> >::type * = 0,
typename boost::disable_if< boost::is_convertible<T*,LevelBase*> >::type * = 0,
template <class Base>
struct Parameters : public Base
{
- typedef typename boost::mpl::if_c< Base::level::value == NONE::value,
- typename Base::stream::defaultLevel,
+ typedef typename boost::mpl::if_c< Base::level::value == NONE::value,
+ typename Base::stream::defaultLevel,
typename Base::level >::type level;
static bool const compileEnabled = senf::log::Enabled<
- typename Base::stream,
- typename Base::area_base,
+ typename Base::stream,
+ typename Base::area_base,
level>::value;
- static bool enabled() {
+ static bool enabled() {
return compileEnabled
&& ( senf::log::detail::TargetRegistry::instance().fallbackRouting() ||
Base::area::instance().limit(Base::stream::instance()) <= level::value );
template <class Base, class Param>
struct apply {
typedef Parameters_<
- Base,
- Param,
+ Base,
+ Param,
SENF_MPL_RV(Parameters_select_(static_cast<Param*>(0)))> type;
};
};
prefix_ senf::log::StreamRegistry::iterator senf::log::StreamRegistry::begin()
{
- return boost::make_transform_iterator(registry_.begin(),
+ return boost::make_transform_iterator(registry_.begin(),
::__gnu_cxx::select1st<Registry::value_type>());
}
namespace detail { struct StreamBase; }
- /** \brief Stream registry
-
+ /** \brief Stream registry
+
The stream registry keeps track of all streams defined. stream classes are defined as
singletons and will automatically register with this registry.
The stream registry exposes a forward sequence interface which is a sequence of the names of
all registered streams.
*/
- class StreamRegistry
+ class StreamRegistry
: public senf::singleton<StreamRegistry>
{
typedef std::map<std::string, detail::StreamBase const *> Registry;
public:
- typedef boost::transform_iterator< ::__gnu_cxx::select1st<Registry::value_type>,
+ typedef boost::transform_iterator< ::__gnu_cxx::select1st<Registry::value_type>,
Registry::const_iterator > iterator;
# ifdef DOXYGEN
namespace detail {
/// Internal: Log stream base class
- struct StreamBase
+ struct StreamBase
{
StreamBase();
virtual ~StreamBase();
-
+
std::string fullName() const;
virtual std::string v_name() const;
virtual unsigned defaultRuntimeLimit() const = 0;
SENF_AUTO_UNIT_TEST(streamRegistry)
{
- char const * streams[] =
+ char const * streams[] =
{ "senf::SenfLog", "senf::log::Debug", "senf::log::test::myStream" };
BOOST_CHECK_EQUAL_COLLECTIONS( senf::log::StreamRegistry::instance().begin(),
namespace senf {
namespace log {
-
+
/** \brief Store %log messages in a string buffer
- This target is mostly useful for debug purposes.
+ This target is mostly useful for debug purposes.
\ingroup targets
*/
- class StringTarget
+ class StringTarget
: private boost::base_from_member<std::stringstream>,
public IOStreamTarget
{
};
-}}
+}}
///////////////////////////////hh.e////////////////////////////////////////
//#include "StringTarget.cci"
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace console { class DirectoryNode; }
namespace log {
-
+
/** \brief Log target writing to the syslog
The SyslogTarget will send all log messages to the syslog at the given facility.
\endcode
Valid facility values (taken from <tt>man 3 syslog</tt>):
- \par ""
+ \par ""
<tt>LOG_AUTHPRIV</tt>, <tt>LOG_CRON</tt>, <tt>LOG_DAEMON</tt>, <tt>LOG_FTP</tt>,
<tt>LOG_KERN</tt>, <tt>LOG_LOCAL0</tt>, <tt>LOG_LOCAL1</tt>, <tt>LOG_LOCAL2</tt>,
<tt>LOG_LOCAL3</tt>, <tt>LOG_LOCAL4</tt>, <tt>LOG_LOCAL5</tt>, <tt>LOG_LOCAL6</tt>,
\ingroup targets
*/
- class SyslogTarget
+ class SyslogTarget
: public Target
{
public:
///////////////////////////////////////////////////////////////////////////
private:
- void v_write(time_type timestamp, std::string const & stream,
- std::string const & area, unsigned level,
+ void v_write(time_type timestamp, std::string const & stream,
+ std::string const & area, unsigned level,
std::string const & message);
int facility_;
public:
static int const LEVELMAP[8];
-
- enum LogFacility {
+
+ enum LogFacility {
AUTHPRIV = LOG_AUTHPRIV,
CRON = LOG_CRON,
DAEMON = LOG_DAEMON,
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
SENF_AUTO_UNIT_TEST(syslogTarget)
{
senf::log::SyslogTarget syslog;
-
+
syslog.route();
BOOST_WARN_MESSAGE( false, "Check the system log for the test message" );
SENF_LOG(("SENF syslog test message"));
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
std::string line;
unsigned sz (896-prf.size());
- for (; i != i_end; ++i)
+ for (; i != i_end; ++i)
for (unsigned j (0); j < i->size(); j += sz) {
line = prf;
line += std::string(*i, j, sz);
namespace fty = senf::console::factory;
detail::TargetRegistry::instance().consoleDir()
- .add("udp-target",
- fty::Command<senf::console::DirectoryNode::ptr (*)(INet4SocketAddress const &,
+ .add("udp-target",
+ fty::Command<senf::console::DirectoryNode::ptr (*)(INet4SocketAddress const &,
LogFacility)
>(&RegisterConsole::create)
.arg("address", "target address to send log messages to")
" syslog false; # no syslog format, just plain udp\n"
" }\n") );
detail::TargetRegistry::instance().consoleDir()
- .add("udp-target",
- fty::Command<senf::console::DirectoryNode::ptr (*)(INet4Address const &,
+ .add("udp-target",
+ fty::Command<senf::console::DirectoryNode::ptr (*)(INet4Address const &,
LogFacility)
>(&RegisterConsole::create)
.arg("address")
.arg("facility", kw::default_value = USER) );
detail::TargetRegistry::instance().consoleDir()
- .add("udp-target",
- fty::Command<senf::console::DirectoryNode::ptr (*)(INet6SocketAddress const &,
+ .add("udp-target",
+ fty::Command<senf::console::DirectoryNode::ptr (*)(INet6SocketAddress const &,
LogFacility)
>(&RegisterConsole::create)
.arg("address")
.arg("facility", kw::default_value = USER) );
detail::TargetRegistry::instance().consoleDir()
- .add("udp-target",
- fty::Command<senf::console::DirectoryNode::ptr (*)(INet6Address const &,
+ .add("udp-target",
+ fty::Command<senf::console::DirectoryNode::ptr (*)(INet6Address const &,
LogFacility)
>(&RegisterConsole::create)
.arg("address")
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
/** \brief Log target writing UDP syslog packets
- The SyslogUDPTarget will send all %log messages directly via UDP to a target host. This
+ The SyslogUDPTarget will send all %log messages directly via UDP to a target host. This
host should have a syslog daemon or relay running. The protocol is defined in <a
href="http://tools.ietf.org/html/rfc3164">RFC-3164</a>.
Valid facility values are from <tt>man 3 syslog</tt>:
- \par ""
+ \par ""
<tt>LOG_AUTHPRIV</tt>, <tt>LOG_CRON</tt>, <tt>LOG_DAEMON</tt>, <tt>LOG_FTP</tt>,
<tt>LOG_KERN</tt>, <tt>LOG_LOCAL0</tt>, <tt>LOG_LOCAL1</tt>, <tt>LOG_LOCAL2</tt>,
<tt>LOG_LOCAL3</tt>, <tt>LOG_LOCAL4</tt>, <tt>LOG_LOCAL5</tt>, <tt>LOG_LOCAL6</tt>,
void syslog(bool enabled=true); ///< Set syslog format
private:
- void init();
- void v_write(time_type timestamp, std::string const & stream,
- std::string const & area, unsigned level,
+ void init();
+ void v_write(time_type timestamp, std::string const & stream,
+ std::string const & area, unsigned level,
std::string const & message);
void consoleFormat(std::ostream & os);
bool syslogFormat_;
public:
- enum LogFacility {
+ enum LogFacility {
AUTHPRIV = LOG_AUTHPRIV,
CRON = LOG_CRON,
DAEMON = LOG_DAEMON,
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace detail {
- SENF_CONSOLE_REGISTER_ENUM_MEMBER( TargetRegistry, Level,
+ SENF_CONSOLE_REGISTER_ENUM_MEMBER( TargetRegistry, Level,
(VERBOSE)(NOTICE)(MESSAGE)(IMPORTANT)(CRITICAL)(FATAL) );
}}}
prefix_ void senf::log::Target::consoleList(std::ostream & os)
{
- static char const * levels[] = {
+ static char const * levels[] = {
"verbose", "verbose", "notice", "message", "important", "critical", "fatal", "disabled" };
boost::format fmt ("%2d %-29s %-29s %-9s %-6s\n");
os << fmt % "#" % "STREAM" % "AREA" % "LEVEL" % "ACTION";
unsigned n (0);
for (iterator i (begin()); i != end(); ++i, ++n)
- os << fmt
- % n
+ os << fmt
+ % n
% formatLabel(i->stream())
% formatLabel(i->area())
% levels[i->level()]
senf::log::detail::TargetRegistry::consoleSelf(std::ostream & os)
{
return senf::console::Client::get(os).consoleDir().node().thisptr();
-}
+}
///////////////////////////////////////////////////////////////////////////
// senf::log::detail::LogParameters
namespace {
- char const * levelNames[] = {
+ char const * levelNames[] = {
"NONE", "VERBOSE", "NOTICE", "MESSAGE", "IMPORTANT", "CRITICAL", "FATAL", "DISABLED" };
void parseParamToken(std::string const & value, senf::log::detail::LogParameters & out)
out.area = a;
return;
}
-
+
char const ** i (
std::find(levelNames+1, levelNames+sizeof(levelNames)/sizeof(levelNames[0])-1, value));
if (i == levelNames+sizeof(levelNames)/sizeof(levelNames[0])-1)
LogParameters & out)
{
out.clear();
-
+
for (console::ParseCommandInfo::TokensRange::iterator i (tokens.begin());
i != tokens.end(); ++i)
parseParamToken(i->value(), out);
prefix_ senf::log::Target::RoutingEntry::RoutingEntry(detail::StreamBase const * stream,
detail::AreaBase const * area,
unsigned level, action_t action)
- : stream_(stream), area_(area), level_(level), action_(action)
+ : stream_(stream), area_(area), level_(level), action_(action)
{}
prefix_ senf::log::Target::RoutingEntry::RoutingEntry()
- : stream_(0), area_(0), level_(0), action_(ACCEPT)
+ : stream_(0), area_(0), level_(0), action_(ACCEPT)
{}
prefix_ bool senf::log::Target::RoutingEntry::operator==(RoutingEntry const & other)
const
-{
- return
- stream_ == other.stream_ &&
- area_ == other.area_ &&
+{
+ return
+ stream_ == other.stream_ &&
+ area_ == other.area_ &&
level_ == other.level_ &&
- action_ == other.action_;
+ action_ == other.action_;
}
prefix_ std::string senf::log::Target::RoutingEntry::stream()
prefix_ void senf::log::Target::route(action_t action, int index)
{
typedef detail::RouteParameters<A1,A2,A3> Params;
- route( detail::InstanceP<typename Params::Stream, detail::StreamBase>::value(),
- detail::InstanceP<typename Params::Area, detail::AreaBase>::value(),
- Params::Level::value,
+ route( detail::InstanceP<typename Params::Stream, detail::StreamBase>::value(),
+ detail::InstanceP<typename Params::Area, detail::AreaBase>::value(),
+ Params::Level::value,
action, index);
}
prefix_ void senf::log::Target::unroute(action_t action)
{
typedef detail::RouteParameters<A1,A2,A3> Params;
- unroute( detail::InstanceP<typename Params::Stream, detail::StreamBase>::value(),
- detail::InstanceP<typename Params::Area, detail::AreaBase>::value(),
- Params::Level::value,
+ unroute( detail::InstanceP<typename Params::Stream, detail::StreamBase>::value(),
+ detail::InstanceP<typename Params::Area, detail::AreaBase>::value(),
+ Params::Level::value,
action);
}
-#endif
+#endif
///////////////////////////////////////////////////////////////////////////
// namespace senf::log::detail members
The routing table is processed from first route to last route, the first matching entry
determines the fate of a log messages. Therefore, the ordering of routing entries is
important.
-
+
If no position is explicitly specified, new routing entries are added to the end of the
routing table. All routing statements however take an index as optional argument to
explicitly specify the position of the new routing entry.
std::ostream & operator<<(std::ostream & os, LogParameters const & pm);
- void senf_console_parse_argument(console::ParseCommandInfo::TokensRange const & tokens,
+ void senf_console_parse_argument(console::ParseCommandInfo::TokensRange const & tokens,
LogParameters & out);
/** \brief Internal: Target registry */
: public senf::singleton<TargetRegistry>
{
public:
- enum Level {
- VERBOSE = senf::log::VERBOSE::value,
- NOTICE = senf::log::NOTICE::value,
- MESSAGE = senf::log::MESSAGE::value,
- IMPORTANT = senf::log::IMPORTANT::value,
- CRITICAL = senf::log::CRITICAL::value,
+ enum Level {
+ VERBOSE = senf::log::VERBOSE::value,
+ NOTICE = senf::log::NOTICE::value,
+ MESSAGE = senf::log::MESSAGE::value,
+ IMPORTANT = senf::log::IMPORTANT::value,
+ CRITICAL = senf::log::CRITICAL::value,
FATAL = senf::log::FATAL::value
};
using senf::singleton<TargetRegistry>::instance;
- void write(StreamBase const & stream, AreaBase const & area, unsigned level,
+ void write(StreamBase const & stream, AreaBase const & area, unsigned level,
std::string const & msg);
void routed();
private:
TargetRegistry();
~TargetRegistry();
-
+
void registerTarget(Target * target, std::string const & name);
void unregisterTarget(Target * target);
console::LazyDirectory consoleDir_;
Targets dynamicTargets_;
-
+
friend class senf::log::Target;
friend class senf::singleton<TargetRegistry>;
};
#ifndef DOXYGEN
- // This code takes the routing target template arguments in any order and sorts them
+ // This code takes the routing target template arguments in any order and sorts them
// by type (Stream, Area and Level).
senf::mpl::rv<0u> RouteParameterCheck_(...);
///////////////////////////////cc.p////////////////////////////////////////
namespace {
-
+
struct RouteCheck
{
typedef std::string result_type;
std::string operator()(senf::log::Target::RoutingEntry const & entry) const
{
- static char const * levels[] = {
+ static char const * levels[] = {
"NONE", "VERBOSE", "NOTICE", "MESSAGE", "IMPORTANT", "CRITICAL", "FATAL", "DISABLED" };
static char const * actions[] = { "ACCEPT", "REJECT" };
std::stringstream s;
- s << entry.stream() << "-" << entry.area() << "-" << levels[entry.level()] << "-"
+ s << entry.stream() << "-" << entry.area() << "-" << levels[entry.level()] << "-"
<< actions[entry.action()];
return s.str();
}
{
senf::log::StringTarget target;
- BOOST_CHECK_THROW( target.route("senf::log::test::myStream", "invalid_area"),
+ BOOST_CHECK_THROW( target.route("senf::log::test::myStream", "invalid_area"),
senf::log::Target::InvalidAreaException );
BOOST_CHECK_THROW( target.route("invalid_stream", ""),
senf::log::Target::InvalidStreamException );
- BOOST_CHECK_THROW( target.unroute("senf::log::test::myStream", "invalid_area"),
+ BOOST_CHECK_THROW( target.unroute("senf::log::test::myStream", "invalid_area"),
senf::log::Target::InvalidAreaException );
BOOST_CHECK_THROW( target.unroute("invalid_stream", ""),
senf::log::Target::InvalidStreamException );
target.route<senf::log::test::myStream, senf::log::VERBOSE>(senf::log::Target::ACCEPT, 0);
target.route<senf::log::test::myStream, senf::log::test::Foo, senf::log::VERBOSE>(
senf::log::Target::ACCEPT, 2);
- target.route("senf::log::test::myStream", "", senf::log::IMPORTANT::value,
+ target.route("senf::log::test::myStream", "", senf::log::IMPORTANT::value,
senf::log::Target::REJECT, 4);
target.route("senf::log::Debug", "senf::log::test::Foo", senf::log::VERBOSE::value,
senf::log::Target::REJECT, -5);
- target.route("senf::log::Debug", "", senf::log::MESSAGE::value,
+ target.route("senf::log::Debug", "", senf::log::MESSAGE::value,
senf::log::Target::ACCEPT, -7);
typedef boost::transform_iterator<RouteCheck, senf::log::Target::iterator> iterator;
iterator i (boost::make_transform_iterator(target.begin(), RouteCheck()));
iterator const i_end (boost::make_transform_iterator(target.end(), RouteCheck()));
- char const * data[] = {
+ char const * data[] = {
"senf::log::Debug--MESSAGE-ACCEPT",
"senf::log::test::myStream--VERBOSE-ACCEPT",
"senf::log::Debug-senf::log::test::Foo-VERBOSE-REJECT",
target.unroute<senf::log::Debug>();
target.unroute<senf::log::test::myStream, senf::log::VERBOSE>();
target.unroute<senf::log::test::myStream, senf::log::DefaultArea>(senf::log::Target::REJECT);
- target.unroute("senf::log::test::myStream", "", senf::log::IMPORTANT::value,
+ target.unroute("senf::log::test::myStream", "", senf::log::IMPORTANT::value,
senf::log::Target::REJECT);
target.unroute(1);
target.flush();
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
This time source is installed by default and uses gettimeofday() (via the Boost.DateTime
library) to get the current universal time.
-
+
\ingroup config
*/
struct SystemTimeSource : public TimeSource
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
time_type now();
void timeSource(std::auto_ptr<TimeSource> source);
-
+
private:
TimeSourceManager();
-
+
boost::scoped_ptr<TimeSource> timeSource_;
friend class senf::singleton<TimeSourceManager>;
namespace senf {
namespace log {
namespace test {
-
+
struct Foo
{
SENF_LOG_CLASS_AREA();
\section basic_mixins Mixin classes
-
+
<table class="listing">
<tr><td>\ref intrusive_refcount</td><td>mixin to simplify writing classes for use with <a
href="http://www.boost.org/libs/smart_ptr/intrusive_ptr.html">boost::intrusive_ptr</a></td></tr>
<tr><td>\ref safe_bool</td><td>a mixin class to provide a really safe replacement for
<tt>operator bool</tt>
-
+
<tr><td>\ref singleton</td><td>mixin to make a class a singleton</td></tr>
</table>
-
+
\section memory_management Memory Management
buffers</td></tr>
<tr><td>\ref pool_alloc_mixin</td><td>mixin to provide pool allocation to a class</td></tr>
-
+
<tr><td>\ref contiguous_storage_iterator</td><td>traits class to check iterator type for raw
pointer accessibility</td></tr>
</table>
<tr><td>\ref TypeIdValue</td><td>class wrapping a typeid in a way that it can be used like any
other value type, e.g. as the key in a map.</td></tr>
</table>
-
+
\section miscstuff Miscellaneous
<tr><td>\ref exception</td><td>standard exception for system errors (errno)</td></tr>
<tr><td>\ref senf_statistics</td><td>statistics functionality</td></tr>
-
+
<tr><td>\ref hexdump</td><td>a simple but usefull function to write binary data in in
hexadecimal format.</td></tr>
<tr><td>stringJoin()</td><td>Utility to join a string range into
a single string (with separator)</td></tr>
-
+
<tr><td>make_transform_range()</td><td>\c boost::make_transform_iterator() with support for
ranges</td></tr>
// $Id$
//
-// Copyright (C) 2010
+// Copyright (C) 2010
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
-
+
template <class T, class B = boost::detail::empty_base<T> >
struct strict_totally_ordered1
: boost::totally_ordered1< T, boost::equivalent1< T, B > >
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace senf {
namespace phoenix {
-
+
/** \brief \c push_back phoenix functor
<tt>push_back(c, x) := c.push_back(x)</tt>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
struct clear {
template <class A1>
struct result { typedef void type; };
-
+
template <class A1>
void operator()(A1 & a1) const
{ a1.clear(); }
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////cti.p///////////////////////////////////////
template <class Range, class Fn>
-prefix_ boost::iterator_range<
+prefix_ boost::iterator_range<
boost::transform_iterator< Fn,
typename boost::range_const_iterator<Range>::type > >
senf::make_transform_range(Range const & range, Fn const & fn)
}
template <class Range, class Fn>
-prefix_ boost::iterator_range<
+prefix_ boost::iterator_range<
boost::transform_iterator< Fn,
typename boost::range_iterator<Range>::type > >
senf::make_transform_range(Range & range, Fn const & fn)
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
-
+
/** \brief Make a \c boost::iterator_range from \c boost::trasform_iterator
This helper is like \c boost::make_transform_iterator, however for ranges instead of
- iterators.
+ iterators.
*/
template <class Range, class Fn>
- boost::iterator_range<
+ boost::iterator_range<
boost::transform_iterator< Fn,
typename boost::range_const_iterator<Range>::type > >
make_transform_range(Range const & range, Fn const & fn);
template <class Range, class Fn>
- boost::iterator_range<
+ boost::iterator_range<
boost::transform_iterator< Fn,
typename boost::range_iterator<Range>::type > >
make_transform_range(Range & range, Fn const & fn);
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
namespace fmt = senf::format;
- os << boost::format("%s%-5d%|15t| %12.5g %19.5g %12.5g\n")
- % std::string(2*level,' ') % rank()
+ os << boost::format("%s%-5d%|15t| %12.5g %19.5g %12.5g\n")
+ % std::string(2*level,' ') % rank()
% fmt::eng(min()).setw() % fmt::eng(avg(),dev()).setw() % fmt::eng(max()).setw();
{
OutputMap::const_iterator i (outputs_.begin());
OutputMap::const_iterator i_end (outputs_.end());
for (; i != i_end; ++i)
os << boost::format(" %3d %12.5g %19.5g %12.5g\n")
- % i->second.n
- % fmt::eng(i->second.min).setw()
- % fmt::eng(i->second.avg, i->second.dev).setw()
+ % i->second.n
+ % fmt::eng(i->second.min).setw()
+ % fmt::eng(i->second.avg, i->second.dev).setw()
% fmt::eng(i->second.max).setw();
}
{
for (; i != i_end; ++i)
stats = & (stats->collect(*i));
-
+
}
prefix_ boost::shared_ptr<senf::console::DirectoryNode>
StatisticsBase * stats (this);
std::vector<unsigned>::const_iterator i (ranks.begin());
std::vector<unsigned>::const_iterator const i_end (ranks.end());
-
+
try {
for (; i != i_end; ++i)
stats = &(*stats)[*i];
for (; i != i_end; ++i)
stats = & (stats->collect(*i));
-
+
return stats->output(window).dir().node().thisptr();
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
template <class Owner>
prefix_ senf::StatisticsBase::OutputProxy<Owner>::OutputProxy(Owner * owner, OutputEntry * entry)
- : owner_ (owner), entry_ (entry)
+ : owner_ (owner), entry_ (entry)
{}
template <class Owner>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
/** \defgroup senf_statistics Statistics
The statistics functionality has two parts:
-
+
\li the senf::Statistics class
\li statistics sources
class Collector;
class Statistics;
-
+
/** \brief Internal: Generic Statistics collection */
class StatisticsBase
- {
+ {
typedef std::map<unsigned, Collector> Children;
struct Transform {
// Function object
struct Collector
{
- void operator()(float min, float avg, float max, float dev)
+ void operator()(float min, float avg, float max, float dev)
{ ... }
};
\endcode
template <class Target> Owner & connect(Target & target,
std::string label="") const;
///< Connect externally managed target
- template <class PTarget> Owner & connect(std::auto_ptr<PTarget> target,
+ template <class PTarget> Owner & connect(std::auto_ptr<PTarget> target,
std::string label="") const;
///< Connect internally managed target
Owner & noconnect() const; ///< Don't connect the output
private:
#endif
OutputProxy(Owner * owner, OutputEntry * entry);
- template <class OtherOwner>
+ template <class OtherOwner>
OutputProxy(Owner * owner, OutputProxy<OtherOwner> const & other);
private:
template <class OtherOwner> friend class OutputProxy;
};
-
+
///////////////////////////////////////////////////////////////////////////
///\name Accessing the current value
///\{
/**< This member will return a reference to the collector
collecting \a rank values.
\param[in] rank Number of values the requested
- collector collects into each combined value.
+ collector collects into each combined value.
\throws InvalidRankException if \a rank is not a valid
registered rank value. */
CollectorRange collectors(); ///< List all child collectors
Statistics & base(); ///< Get base statistics object
/**< Returns the base statistics object. If this is
a child collector, this will return the outermost
- statistics object, otherwise it will return
+ statistics object, otherwise it will return
\c *this. */
std::string path() const; ///< Get the path to this collector
float max_;
float dev_;
Children children_;
-
+
struct QueueEntry {
float min;
float avg;
struct Target : public TargetBase
{
boost::scoped_ptr<PTarget> target_;
- Target(std::auto_ptr<PTarget> target, std::string const & label)
+ Target(std::auto_ptr<PTarget> target, std::string const & label)
: TargetBase (label), target_ (target.release()) {}
explicit Target(std::string const & label)
: TargetBase (label), target_ (0) {}
.collect(10u) // seconds
.collect(60u) // minutes
.collect(60u); // hours
-
+
packetStats[10u].collect(100u); // 100 seconds
rateAnalyzer.startStatistics(senf::ClockService::milliseconds(100u));
\see senf::StatisticsBase::OutputProxy for the output proxy (connect) interface
\ingroup senf_statistics
*/
- class Statistics
+ class Statistics
: public StatisticsBase, boost::noncopyable
{
public:
\param[in] max maximal data values since last call
\param[in] dev standard deviation of avg value */
- void operator()(float value, float dev=0.0f);
+ void operator()(float value, float dev=0.0f);
///< Same as enter() with \a min == \a avg == \a max
/**< Provided so a Statistics instance can be directly used
as a signal target. */
class Collector : public StatisticsBase
{
public:
- virtual unsigned rank() const;
+ virtual unsigned rank() const;
StatisticsBase::OutputProxy<Collector> output(unsigned n = 1u);
-
+
private:
Collector(StatisticsBase * owner, unsigned rank);
void enter(float min, float avg, float max, float dev);
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////cc.p////////////////////////////////////////
namespace {
-
+
struct GetRange
{
typedef senf::Collector const & first_argument_type;
typedef boost::tokenizer<Separator> Tokenizer;
struct Pred {
bool operator()(std::string const & s) const
- { try { boost::lexical_cast<double>(s); return true; }
+ { try { boost::lexical_cast<double>(s); return true; }
catch (std::bad_cast &) { return false; } }
};
typedef boost::filter_iterator<Pred,Tokenizer::iterator> FilterIterator;
typedef TransformIterator iterator;
typedef TransformIterator const_iterator;
-
+
splitFloats(std::string const & s) : s_ (s), sep_ (" \n"), tok_ (s_, sep_) {}
- TransformIterator begin() const
+ TransformIterator begin() const
{ return TransformIterator(FilterIterator(tok_.begin(), tok_.end())); }
- TransformIterator end() const
+ TransformIterator end() const
{ return TransformIterator(FilterIterator(tok_.end(), tok_.end())); }
std::string s_;
senf::StatisticsLogger("level3"));
unsigned children1[] = { 4u };
- BOOST_CHECK_EQUAL_COLLECTIONS(
+ BOOST_CHECK_EQUAL_COLLECTIONS(
boost::make_transform_iterator(stats.collectors().begin(), GetRange()),
boost::make_transform_iterator(stats.collectors().end(), GetRange()),
children1, children1 + sizeof(children1)/sizeof(children1[0]) );
unsigned children2[] = { 3u };
- BOOST_CHECK_EQUAL_COLLECTIONS(
+ BOOST_CHECK_EQUAL_COLLECTIONS(
boost::make_transform_iterator(stats[4].collectors().begin(), GetRange()),
boost::make_transform_iterator(stats[4].collectors().end(), GetRange()),
children2, children2 + sizeof(children2)/sizeof(children2[0]) );
unsigned children3[] = { 2u };
- BOOST_CHECK_EQUAL_COLLECTIONS(
+ BOOST_CHECK_EQUAL_COLLECTIONS(
boost::make_transform_iterator(stats[4][3].collectors().begin(), GetRange()),
boost::make_transform_iterator(stats[4][3].collectors().end(), GetRange()),
children3, children3 + sizeof(children3)/sizeof(children3[0]) );
- float values[][3] = {
+ float values[][3] = {
{ -1.0f, 2.3f, 2.5f }, { 0.3f, 2.4f, 3.8f }, { -1.1f, -0.3f, 0.0f },
{ -0.3f, 3.2f, 3.3f }, { 1.0f, 1.1f, 1.1f }, { 0.5f, 0.5f, 0.5f },
{ 0.0f, 0.0f, 0.0f }, { -2.0f, -1.8f, -1.0f }, { 0.0f, 2.3f, 2.4f },
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
RegisterStatisticsLogger();
- static void adder(senf::StatisticsBase & stats,
+ static void adder(senf::StatisticsBase & stats,
unsigned rank,
senf::console::DirectoryNode & dir);
- static void consoleCreate(senf::StatisticsBase & stats,
+ static void consoleCreate(senf::StatisticsBase & stats,
unsigned rank,
std::string const & prefix);
};
{
namespace kw = senf::console::kw;
namespace fty = senf::console::factory;
-
+
dir.add("logger", fty::Command<void (std::string const &)>(
boost::bind(&consoleCreate, boost::ref(stats), rank, _1))
.arg("prefix","Optional prefix string to add to each log message",
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
*/
typedef unspecified StatisticsStream;
#else
- SENF_LOG_DEFINE_STREAM(StatisticsStream,
+ SENF_LOG_DEFINE_STREAM(StatisticsStream,
senf::log::MESSAGE, senf::log::MESSAGE, senf::log::MESSAGE);
#endif
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
: public senf::singleton<StatisticsLoggerRegistry>
{
public:
- typedef void (*AddFn)(senf::StatisticsBase &, unsigned,
+ typedef void (*AddFn)(senf::StatisticsBase &, unsigned,
senf::console::DirectoryNode &);
using senf::singleton<StatisticsLoggerRegistry>::instance;
{
StatisticsLogger(std::string const & label_);
void operator()(float min, float avg, float max, float dev);
-
+
std::string label;
};
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
typename boost::range_const_iterator<ForwardReadableRange>::type i (boost::begin(range));
typename boost::range_const_iterator<ForwardReadableRange>::type const i_end (boost::end(range));
std::stringstream ss;
-
+
if (i != i_end) {
for (;;) {
ss << *i;
(*interpreter_) << mod;
return *this;
}
-
+
private:
boost::shared_ptr< senf::detail::lexical_stream<Target> > interpreter_;
};
{
senf::detail::lexical_stream<Target> interpreter;
Target result;
-
+
if (!(interpreter << arg && interpreter >> result))
boost::throw_exception(boost::bad_lexical_cast(typeid(Source), typeid(Target)));
return result;
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
-
+
/** \brief Join string range with separator into single string
This utility will build string by joining all elements of \a range into a single string
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
SENF_AUTO_UNIT_TEST(lexicalCast)
{
- SENF_CHECK_NO_THROW(
- BOOST_CHECK_EQUAL(
- senf::lexical_cast<unsigned>()[std::setbase(0)](std::string("0x1a2b")),
+ SENF_CHECK_NO_THROW(
+ BOOST_CHECK_EQUAL(
+ senf::lexical_cast<unsigned>()[std::setbase(0)](std::string("0x1a2b")),
6699u ) );
- SENF_CHECK_NO_THROW(
- BOOST_CHECK_EQUAL(
- senf::lexical_cast<std::string>()[std::hex][std::uppercase][std::showbase](6699u),
+ SENF_CHECK_NO_THROW(
+ BOOST_CHECK_EQUAL(
+ senf::lexical_cast<std::string>()[std::hex][std::uppercase][std::showbase](6699u),
"0X1A2B" ) );
SENF_CHECK_NO_THROW(
BOOST_CHECK_EQUAL(
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
This abstract interface base class provides an abstract interface to a terminal. There are
two parts to this interface:
-
+
\li The interface which allows the terminal user to get information about the terminal
\li The interface which allows the terminal to send messages to the terminal user
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
prefix_ senf::term::BaseEditor::BaseEditor(AbstractTerminal & terminal)
: terminal_ (&terminal),
keyTimeout_ (senf::ClockService::milliseconds(DEFAULT_KEY_TIMEOUT_MS)),
- timer_ ("senf::term::BaseEditor::keySequenceTimeout",
+ timer_ ("senf::term::BaseEditor::keySequenceTimeout",
senf::membind(&BaseEditor::keySequenceTimeout, this)),
column_ (0u), displayHeight_ (1u), line_ (0u)
{
///////////////////////////////////////////////////////////////////////////
prefix_ senf::term::LineEditor::LineEditor(AbstractTerminal & terminal, AcceptCallback cb)
- : BaseEditor(terminal), enabled_ (false), prompt_ ("$"), promptWidth_ (1u), editWidth_ (0u),
+ : BaseEditor(terminal), enabled_ (false), prompt_ ("$"), promptWidth_ (1u), editWidth_ (0u),
text_ (""), point_ (0u), displayPos_ (0u), lastKey_ (0u), callback_ (cb), historyPoint_ (0u)
{
defineKey(KeyParser::Return, &bindings::accept);
completer(editor, b, e, prefix, completions);
if (completions.empty())
return;
- if (e > text.size())
+ if (e > text.size())
e = text.size();
if (b > e)
b = e;
-
+
// Find common start string of all completions
unsigned commonStart (completions[0].size());
unsigned maxLen (commonStart);
std::string line;
for (unsigned column (0); column < nColumns && i != completions.end(); ++column, ++i) {
std::string entry (colWidth, ' ');
- std::copy(i->begin(),
- i->size() > colWidth-2 ? i->begin()+colWidth-2 : i->end(),
+ std::copy(i->begin(),
+ i->size() > colWidth-2 ? i->begin()+colWidth-2 : i->end(),
entry.begin());
line += entry;
}
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
void write(char ch);
void write(std::string const & s);
-
+
AbstractTerminal * terminal_;
Terminfo tifo_;
KeyParser keyParser_;
unsigned displayHeight_;
unsigned line_;
};
-
+
/** \brief Single line interactive text editor
LineEditor implements a single-line input widget on an arbitrary AbstractTerminal.
\li The LineEditor supports an arbitrary auxiliary display area below the input line
\li The LineEditor has hide() / show() support to allow editing to be temporarily
interrupted.
-
+
The LineEditor will query the user for an input line. When the user accepts a line,
LineEditor will call a user callback function. After the callback has been called, the
editor is disabled. To accept a new input line, call show().
See the senf::term::bindings namespace for a list of all default provided key binding
functions.
-
+
\section editor_complete Completion suppoprt
bindings::complete():
\code
- void myCompleter(senf::term::LineEditor & editor, unsigned & b, unsigned & e,
+ void myCompleter(senf::term::LineEditor & editor, unsigned & b, unsigned & e,
std::string & prefix, std::vector<std::string> & completions)
{
// Get text to complete
}
senf::term::LineEditor editor (...);
- editor.defineKey(senf::term::KeyParser::TAB,
+ editor.defineKey(senf::term::KeyParser::TAB,
boost::bind(&senf::term::bindings::complete, _1, &myCompleter));
\endcode
The completion protocol is as follows: When completion is desired, the completer function is
called. \a b and \a e are set to 0 and <tt>editor.point()</tt> respectively. \a prefix and
\a completions are empty.
-
+
\li the completer may restrict the to-be-completed string to any subrange by changing \a b
and \a e accordingly.
\li If there is an initial substring which applies to \e all completions but should not be
listed in the list of completions, assign this value to \a prefix.
- \li Add all possible completions to the \a completions vector not including the \a prefix.
+ \li Add all possible completions to the \a completions vector not including the \a prefix.
\li The completion result is taken from the size of the \a completions vector \e only: If
this vector is empty, completion failed (even if \a prefix is set), a single entry in \a
completions (even if it is the empty string) signals a unique completion.
-
+
\section editor_auxarea The aux display area
/**< \param[in] terminal abstract terminal interface
\param[in] cb callback to call for complete input
line */
-
+
///////////////////////////////////////////////////////////////////////////
///\name Overall edit control
void unsetKey(keycode_t key); ///< Remove all bindings for \a key
///\}
-
+
private:
virtual bool cb_init();
virtual void cb_windowSizeChanged();
void nextHistory (LineEditor & editor); ///< Move to next history entry
void clearScreen (LineEditor & editor); ///< Clear screen and redisplay editor
- typedef boost::function<void (LineEditor &, unsigned & b, unsigned & e,
+ typedef boost::function<void (LineEditor &, unsigned & b, unsigned & e,
std::string & prefix, std::vector<std::string> &)> Completer;
void complete (LineEditor & editor, Completer completer);
///< Complete text at cursor
/**< This function calls \a completer to find the list of
possible completions for the text between \a b and \a e
(as passed to the completer). The completer must add
- all possible completions to the \a completions vector.
+ all possible completions to the \a completions vector.
\see \ref editor_complete */
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
prefix_ senf::term::BaseTelnetProtocol::BaseTelnetProtocol(Handle handle)
: handle_ (handle), charState_ (NORMAL), command_ (CMD_NONE), option_ (0),
inputEvent_ ("senf::term::BaseTelnetProtocol::input",
- senf::membind(&BaseTelnetProtocol::readHandler, this), handle,
+ senf::membind(&BaseTelnetProtocol::readHandler, this), handle,
senf::scheduler::FdEvent::EV_READ),
outputEvent_ ("senf::term::BaseTelnetProtocol::output",
senf::membind(&BaseTelnetProtocol::writeHandler, this), handle,
handleChar(c);
break;
}
-}
+}
prefix_ void senf::term::BaseTelnetProtocol::handleOption(char c)
{
}
prefix_ void senf::term::BaseTelnetProtocol::writeHandler(int state)
-{
+{
if (state != senf::scheduler::FdEvent::EV_WRITE) {
outputEvent_.disable();
inputEvent_.disable();
v_eof();
return;
}
- sendQueue_.erase(sendQueue_.begin(),
+ sendQueue_.erase(sendQueue_.begin(),
handle_.write(boost::make_iterator_range(
sendQueue_.begin(), sendQueue_.end())));
if (sendQueue_.empty())
}
else if (enabled != info.enabled) {
// Request to change the current state
- if (!enabled ||
+ if (!enabled ||
(enabled && (info.wantState == OptInfo::WANTED || info.wantState == OptInfo::ACCEPTED))) {
// accept the request
info.optionState = OptInfo::ACKNOWLEDGED;
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
\c v_handleOptionParameters() member is called.
\code
- class MyTelnetHandler
+ class MyTelnetHandler
: public senf::term::BaseTelnetProtocol::TelnetHandler
{
public:
protected:
MyTelnetHandler() { registerHandler(this); }
-
+
private:
virtual void v_init()
{
sendOptionParameters(OPTION_CODE, "my special subnegotiation");
incrementRequestCounter();
}
-
+
virtual void v_handleOptionParameters(std::string const & data)
{
if (data == "another special subnegotiation")
static unsigned const DEFAULT_REQUEST_TIMEOUT_MS = 500u;
typedef ClientSocketHandle<senf::MakeSocketPolicy<
- ConnectedCommunicationPolicy,
- StreamFramingPolicy,
+ ConnectedCommunicationPolicy,
+ StreamFramingPolicy,
ReadablePolicy,
WriteablePolicy>::policy> Handle; ///< Type of socket handle required
void sendEC(); ///< Send EraseCharacter to peer
void sendEL(); ///< Send EraseLine to peer
void sendGA(); ///< Send GoAhead to peer
-
+
void sendOptionParameters(option_type option, std::string const & data);
///< Send extended option parameter to peer
/**< This will send \a data as extended option parameter of
bool localOption(option_type option); ///< \c true, if \a option locally enabled
bool peerOption(option_type option); ///< \c true, if \a option enabled in peer
-
+
protected:
explicit BaseTelnetProtocol(Handle handle); ///< Construct telnet protocol handler
BaseTelnetProtocol(); ///< Provided for TelnetHandler mixins only
virtual void v_handleEC(); ///< Called, when the peer sends an EraseCharacter
virtual void v_handleEL(); ///< Called, when the peer sends an EraseLine
virtual void v_handleGA(); ///< Called, when the peer sends a GoAhead
-
+
private:
void handleChar(char c);
void handleNormalChar(char c);
void writeHandler(int state);
void timeout();
- enum Command {
+ enum Command {
CMD_NONE = 0,
CMD_SE = 240,
CMD_NOP = 241,
WantState wantState;
OptionState optionState;
bool enabled;
-
+
};
OptInfo & getOption(bool local, option_type option);
typedef std::vector<char> SendQueue;
SendQueue sendQueue_;
- enum CharState { NORMAL, IAC_SEEN, EXPECT_OPTION, CR_SEEN,
+ enum CharState { NORMAL, IAC_SEEN, EXPECT_OPTION, CR_SEEN,
SB_OPTION, SB_DATA, SB_IAC_SEEN };
CharState charState_;
};
/** \brief Telnet handler base class
-
+
\see BaseTelnetProtocol
*/
struct BaseTelnetProtocol::TelnetHandler
See http://www.iana.org/assignments/telnet-options for a list of options
- \ingroup telnet_group
+ \ingroup telnet_group
*/
namespace telnetopt { BaseTelnetProtocol::option_type const ECHO = 1u; }
namespace telnetopt { BaseTelnetProtocol::option_type const TRANSMIT_BINARY = 0u; }
void nextTerminalType(); ///< Request another terminal type
std::string const & terminalType() const; ///< Return current terminal type
-
+
protected:
TerminalType();
};
/** \brief Implement NAWS (Negotiation About Window Size) option
-
+
This telnet handler implements the NAWS option. The client terminals window size will be
requested during initialization. The current window size may always be accessed using the
- width() and height() members.
-
+ width() and height() members.
+
Whenever the window size is changed, the v_windowSizeChanged() function is called. This
function must be implemented in a derived class.
\see BaseTelnetProtocol for how to integrate this handler \n
<a href="http://tools.ietf.org/html/rfc1073">RFC 1073</a> Telnet Window Size Option
*/
- class NAWS
+ class NAWS
: public BaseTelnetProtocol::TelnetHandler
{
public:
protected:
NAWS();
-
+
# ifndef DOXYGEN
private:
# endif
unsigned width_;
unsigned height_;
};
-
+
}
}}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
if (setupFailed_)
v_setupFailed();
- else if (! (width() > 0
+ else if (! (width() > 0
&& ! terminalType().empty()
&& localOption(telnetopt::SUPPRESS_GO_AHEAD)
&& peerOption(telnetopt::SUPPRESS_GO_AHEAD)
if (! init)
log << " terminal initialization (cb_init) failed\n";
}));
-
+
setupFailed_ = true;
requestPeerOption(telnetopt::SUPPRESS_GO_AHEAD, false);
requestLocalOption(telnetopt::SUPPRESS_GO_AHEAD, false);
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
/** \brief AbstractTerminal interface implementation based on telnet
This class provides a telnet server implementation implementing the AbstractTerminal
- interface.
+ interface.
TelnetTerminal provides one additional callback which needs to be implemented in a derived
class: v_setupFailed(). This member will be called, when not all required telnet options are
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
std::vector<senf::term::Terminfo::number_t> stack;
- void push(senf::term::Terminfo::number_t v)
+ void push(senf::term::Terminfo::number_t v)
{
stack.push_back(v);
}
- senf::term::Terminfo::number_t pop()
- {
+ senf::term::Terminfo::number_t pop()
+ {
if (stack.empty())
return 0;
else {
case '~': stack.push(~stack.pop()); break;
case 't': bCondValue = stack.pop();
case 'e': if ((bCondValue = !bCondValue)) // this also supports elsif
- --(i = prgstr.begin() + std::min (prgstr.find ("%e", i-prgstr.begin()),
+ --(i = prgstr.begin() + std::min (prgstr.find ("%e", i-prgstr.begin()),
prgstr.find ("%;", i-prgstr.begin())));
case '?':
case ';': break;
- case 'p':
+ case 'p':
switch (*++i) {
case '1': stack.push(arg1); break;
case '2': stack.push(arg2); break;
NumberVec::const_iterator i (numbers_.begin());
NumberVec::const_iterator const i_end (numbers_.end());
for (; i != i_end; ++i, ++n)
- if (*i != NoValue
+ if (*i != NoValue
&& n < sizeof(properties::NumericNames)/sizeof(properties::NumericNames[0]))
os << " " << properties::NumericNames[n] << " = " << *i << "\n";
}
}
if (booleans_.size() & 1)
is.ignore(1u);
-
+
numbers_.resize(h.nNumbers);
for (NumberVec::iterator i (numbers_.begin()); i != numbers_.end(); ++i) {
number_t v;
if (!is) throw InvalidTerminfoException();
*i = v;
}
-
+
stringPool_.resize(h.stringPoolSz);
is.read(&(stringPool_[0]), stringPool_.size());
if (!is) throw InvalidTerminfoException();
if (key.empty())
return std::make_pair(KeyCode(0), 0);
- // There are several cases:
+ // There are several cases:
// a) 'key' is an incomplete key sequence. In this case, 'key' will precede all completions in
// the key table. The first possible completion is found by 'upper_bound'
// b) 'key' is a complete key sequence. This is the key sequence *preceding* the 'upper_bound'
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
*/
/** \brief Terminfo database entry
-
+
This class reads a single terminfo database entry and allows to access the terminfo
- properties.
-
- \ingroup terminfo_group
+ properties.
+
+ \ingroup terminfo_group
*/
class Terminfo
{
CpiChangesRes, LpiChangesRes, BackspacesWithBs, CrtNoScrolling,
NoCorrectlyWorkingCr, GnuHasMetaKey, LinefeedIsNewline, HasHardwareTabs,
ReturnDoesClrEol };
-
+
/** \brief Boolean property names
\hideinitializer */
static char const * const BooleanNames[];
-
+
/** \brief Numeric terminfo properties */
enum Numeric {
Columns, InitTabs, Lines, LinesOfMemory, MagicCookieGlitch, PaddingBaudRate,
typedef char const* string_t; ///< String terminfo property type
///////////////////////////////////////////////////////////////////////////
-
+
Terminfo();
explicit Terminfo(std::string const & term); ///< Load terminfo entry \a term
void load(std::string const & term); ///< Load terminfo entry \a term
-
+
bool getFlag(properties::Boolean p) const; ///< Get boolean property value
number_t getNumber(properties::Numeric p) const; ///< Get numeric property value
string_t getString(properties::String p) const; ///< Get string property value
bool hasProperty(properties::String p ) const; ///< \c true, if string property \a p exists
std::string formatString(properties::String p,
- number_t arg1=NoValue, number_t arg2=NoValue,
+ number_t arg1=NoValue, number_t arg2=NoValue,
number_t arg3=NoValue, number_t arg4=NoValue,
number_t arg5=NoValue, number_t arg6=NoValue,
number_t arg7=NoValue, number_t arg8=NoValue,
All keys are returned as keyboard code's. Values 0 to 255 represent ordinary ASCII
characters, larger values are special keys taken from the KeyCode \c enum
-
- \ingroup terminfo_group
+
+ \ingroup terminfo_group
*/
class KeyParser
{
Keytable table_;
};
-
+
}}
///////////////////////////////hh.e////////////////////////////////////////
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
//ifo.dump(std::cout);
//kp.dump(std::cout);
- BOOST_CHECK_EQUAL( kp.lookup("\e[5\x7e"),
+ BOOST_CHECK_EQUAL( kp.lookup("\e[5\x7e"),
Pair(senf::term::KeyParser::PageUp, 4u) );
BOOST_CHECK_EQUAL( kp.lookup("\e"),
Pair(senf::term::KeyParser::Incomplete, 1u) );
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
///////////////////////////////cc.p////////////////////////////////////////
namespace {
-
- class MyTelnet
+
+ class MyTelnet
: public senf::term::TelnetTerminal
{
public:
- explicit MyTelnet(Handle handle)
- : senf::term::BaseTelnetProtocol (handle),
- editor_ (*this, senf::membind(&MyTelnet::executeLine, this))
+ explicit MyTelnet(Handle handle)
+ : senf::term::BaseTelnetProtocol (handle),
+ editor_ (*this, senf::membind(&MyTelnet::executeLine, this))
{
editor_.prompt("myTelnet-with-an-endlesssly-long-prompt$");
- editor_.defineKey(senf::term::KeyParser::Ctrl('D'),
+ editor_.defineKey(senf::term::KeyParser::Ctrl('D'),
senf::membind(&MyTelnet::deleteCharOrExit, this));
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
std::type_info const * p_;
};
- /**
+ /**
\related TypeIdValue
*/
TypeIdValue const typeIdValue();
- /**
+ /**
\related TypeIdValue
*/
template <class Type>
TypeIdValue const typeIdValue();
- /**
+ /**
\related TypeIdValue
*/
template <class Type>
TypeIdValue const typeIdValue(Type const & ob);
- /**
+ /**
\related TypeIdValue
*/
std::ostream & operator<<(std::ostream & os, TypeIdValue const & v);
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
/** \brief Check for compile failure
- \c COMPILE_FAIL() is used to check, that a certain piece of code will produce a compile
+ \c COMPILE_FAIL() is used to check, that a certain piece of code will produce a compile
time failure.
\code
// fails to compile ....
int x = "foo";
}
-
+
COMPILE_FAIL(bar)
{ ... }
\endcode
This check is performed by the extended unit-test builder in \c senfscons.
-
+
\ingroup unittest
*/
#define COMPILE_FAIL(n) void n()
#ifdef DOXYGEN
/** \brief Check for non-equality
-
+
\c SENF_CHECK_NOT_EQUAL() is the opposite of \c BOOST_CHECK_EQUAL.
\hideinitializer
\ingroup unittest
// $Id$
//
-// Copyright (C) 2009
+// Copyright (C) 2009
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
namespace detail {
template <class Type, class Iterator>
- struct ConvertingIterator
+ struct ConvertingIterator
: public boost::iterator_adaptor<
ConvertingIterator<Type, Iterator>, Iterator, Type, boost::use_default, Type>
{
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
#include "hexdump.ih"
// Custom includes
-#include <iomanip>
+#include <iomanip>
//#include "hexdump.mpp"
#define prefix_
}
}
-#endif
+#endif
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
//#include "hexdump.mpp"
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
: os_ (os), ias_ (os_), block_size_ (block_size), offset_ (0)
{}
-#endif
+#endif
///////////////////////////////cci.e///////////////////////////////////////
#undef prefix_
#undef prefix_
//#include "hexdump.mpp"
-
+
// Local Variables:
// mode: c++
// fill-column: 100
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
private:
refcount_t refcount_;
-
+
template <class S> void intrusive_ptr_add_ref();
template <class S> void intrusive_ptr_release();
-
+
template <class S>
friend void senf::intrusive_ptr_add_ref(intrusive_refcount_t<S> const * p);
template <class S>
publicly from intrusive_refcount_t.
\code
- class SomeClass
+ class SomeClass
: public intrusive_refcount_t<SomeClass>
{
// ...
{
// Call intrusive_base::release() to decrement the
// refcount. This call will return 'true' when the refcount reaches 0.
-
+
// Return 'true', if the instance shall be deleted
}
friend class intrusive_base;
};
\endcode
-
+
Two additional benefits of using intrusive_refcount are
\li The object can access it's own refcount
\li It is valid and safe to convert a plain object pointer to an intrusive_ptr at any time
BOOST_CHECK_EQUAL(p->refcount(),1u);
BOOST_CHECK_EQUAL(p->is_shared(),false);
BOOST_CHECK_EQUAL(TesterCustom::refs,1u);
-
+
{
TesterCustom::ptr pp (p);
Foo()
{
// Get bound member function for second overload
- SENF_MEMBINDFNP(int, Foo, foo, () const)
+ SENF_MEMBINDFNP(int, Foo, foo, () const)
}
-
+
};
\endcode
/** \brief Marker class for empty default values etc.
This is like Boosts \c boost::mpl::na just an empty class used as template default argument
- to mark missing arguments
-
+ to mark missing arguments
+
\note Don't use this as an empty base class. We may add some informative members to this.
\ingroup senfmpl
*/
\ingroup senfmpl
*/
template <unsigned n>
- struct rv {
- char _[SENF_MPL_RV_ALIGNMENT][n+1];
+ struct rv {
+ char _[SENF_MPL_RV_ALIGNMENT][n+1];
};
/** \brief Get return value of overload selector
-
+
Used together with senf::mpl::rv to implement overload selection.
-
+
\see \ref senf::mpl::rv
\ingroup senfmpl
\hideinitializer
# define SENF_MPL_RV(expr) (sizeof(expr)/SENF_MPL_RV_ALIGNMENT-1)
/** \brief Take an arbitrary unsigned integer template argument
-
+
Used together with <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>: The expression
<tt>take_uint<</tt> \a expr <tt>></tt> is only valid if \a expr is valid and returns a value
convertible to an unsigned integer.
template <unsigned long _> struct take_uint {};
/** \brief Take an arbitrary integer template argument
-
+
Used together with <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>: The expression
<tt>take_int<</tt> \a expr <tt>></tt> is only valid if \a expr is valid and returns a value
convertible to an integer.
template <long _> struct take_int {};
/** \brief Take an arbitrary type template argument
-
+
Used together with <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>: The expression
<tt>take_class<</tt> \a expr <tt>></tt> is only valid if \a expr is valid and is a type.
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
\brief parameter public header */
/** \defgroup boost_parameter Boost.Parameter utilities
-
+
Here we define some utilities for the <a
href="http://www.boost.org/doc/libs/1_33_1/libs/parameter/doc/html/index.html">Boost.Parameter</a>
library.
///\{
/** \brief Test \a ArgumentPack, whether the \a TagType argument was supplied
-
+
This check will test, whether the argument identified by the \a TagType keyword tag type was
specified in the \a ArgumentPack. This inherits from \c boost::mpl::true_ or \c
boost::mpl::false_ accordingly.
*/
template <class ArgumentPack, class TagType>
struct has_parameter
- : public boost::mpl::not_<
+ : public boost::mpl::not_<
boost::is_same< typename boost::parameter::binding< ArgumentPack, TagType, void>::type,
void > >::type
{};
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
the simple typedef is replaced with a nested struct.
*/
template <class T=void>
- struct pool
+ struct pool
: public boost::singleton_pool< pool_alloc_mixin_tag, sizeof(Self) >
{
typedef boost::singleton_pool< pool_alloc_mixin_tag, sizeof(Self) > type;
///\{
///\ingroup senfpp
-/** \brief Return last element of a sequence
- \hideinitializer
+/** \brief Return last element of a sequence
+ \hideinitializer
*/
#define SENF_PP_SEQ_BACK(seq) BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(seq)),seq)
...
}
\endcode
-
+
If the class to be made using senf::safe_bool is itself comparable via it's own \c
operator==, you must use comparable_safe_bool instead of safe_bool to not loose this
capability.
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
prefix_ std::string const & senf::signalName(int signal)
{
static std::string const names[] = {
- "<unknown>",
- "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", "SIGABRT", "SIGBUS", "SIGFPE",
- "SIGKILL", "SIGUSR1", "SIGSEGV", "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM",
- "SIGSTKFLT", "SIGCHLD", "SIGCONT", "SIGSTOP", "SIGTSTP", "SIGTTIN", "SIGTTOU",
- "SIGURG", "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO",
+ "<unknown>",
+ "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGTRAP", "SIGABRT", "SIGBUS", "SIGFPE",
+ "SIGKILL", "SIGUSR1", "SIGSEGV", "SIGUSR2", "SIGPIPE", "SIGALRM", "SIGTERM",
+ "SIGSTKFLT", "SIGCHLD", "SIGCONT", "SIGSTOP", "SIGTSTP", "SIGTTIN", "SIGTTOU",
+ "SIGURG", "SIGXCPU", "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO",
"SIGPWR", "SIGSYS" };
return names[
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
~AliveTest2();
};
- AliveTest1::AliveTest1()
+ AliveTest1::AliveTest1()
{
test2Alive = AliveTest2::alive();
}
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
If the function described in \a Traits does not take any arguments, it is returned
unchanged.
-
+
\code
typedef boost::function_traits<void (int, double)> traits
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::function_traits_remove_arg< traits >::type,
- boost::function_traits<void (double)>
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::function_traits_remove_arg< traits >::type,
+ boost::function_traits<void (double)>
>::value ));
\endcode
struct function_traits_remove_arg {};
/** \brief Get argument type from function traits
-
+
function_traits_arg<Traits, index> will return the type of the \a index-th argument from \a
Traits. If the function has no argument at that index, \c void is returned
typedef boost::function_traits<void (int, double)> traits;
BOOST_STATIC_ASSERT(( boost:is_same<
senf::function_traits_arg_type< traits, 0 >::type,
- int
+ int
>::value ));
BOOST_STATIC_ASSERT(( boost::is_same<
senf::function_traits_arg_type< traits, 2 >::type,
void
>::value ));
\endcode
-
+
\tparam Traits \c boost::function_traits instantiation
\tparam index 0 based argument index
*/
- template < class Traits, int index, bool flag = (index < Traits::arity) >
+ template < class Traits, int index, bool flag = (index < Traits::arity) >
struct function_traits_arg_type {};
#ifndef DOXYGEN
will be returned unchanged.
\code
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_member_pointer< int (Class::*) >::type,
- int
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_member_pointer< int (Class::*) >::type,
+ int
>::value ));
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_member_pointer< void (Class::*)(int) >::type,
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_member_pointer< void (Class::*)(int) >::type,
void (int)
>::value ));
\endcode
{
typedef void type;
};
-
+
#ifndef DOXYGEN
template < class C, class T > struct member_class <T (C::*) >
This meta function will remove a plain or member pointer from the given type. If \a T is
neither a member pointer nor an ordinary pointer, \a T will be returned unchanged.
-
+
\code
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_any_pointer< int (Class::*) >::type,
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_any_pointer< int (Class::*) >::type,
int
>::value ));
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_any_pointer< void (Class::*)(int) >::type,
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_any_pointer< void (Class::*)(int) >::type,
void (int) > );
BOOST_STATIC_ASSERT(( boost::is_same<
senf::remove_any_pointer < int (*)() >::type,
{};
/** \brief Test object if it is a function or member-function (pointer)
-
+
is_any_function will inherit from \c boost::true_type, when \a T is a function type,
function pointer type or a member function pointer type. Otherwise, it will inherit from \c
boost::false_type.
{};
/** \brief Remove reference and CV qualification from type
-
+
remove_cvref will remove all the 'ornaments' from a type as typically used to pass
arguments: references and any CV spec. It will thus convert a typical argument type into
it's basic type.
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
typedef typename Traits::mpp_CurArg() type;
};
-template <class C, class T mpp_TrailTplArgs() >
+template <class C, class T mpp_TrailTplArgs() >
struct remove_member_pointer <T (C::*)( mpp_Args() ) const>
{
typedef T type (mpp_Args());
};
-template <class C, class T mpp_TrailTplArgs() >
+template <class C, class T mpp_TrailTplArgs() >
struct remove_member_pointer <T (C::* const)( mpp_Args() ) const>
{
typedef T type (mpp_Args());
(save-excursion (re-search-backward "^// Undefine local Macros")
(forward-line 1) (delete-region (point) (progn (search-forward
"// ////") (forward-line -1) (point))) (insert "\n") (let ((b (point))
- (e (progn (insert (save-excursion (re-search-backward
+ (e (progn (insert (save-excursion (re-search-backward
"^// Local Macros") (search-forward "#define") (beginning-of-line)
(buffer-substring (point) (progn (search-forward "// ////")
(search-backward "#define") (forward-line 1) (point))))) (point))))
// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
{
typedef boost::function_traits<void (int, double)> traits;
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::function_traits_remove_arg< traits >::type,
- boost::function_traits<void (double)>
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::function_traits_remove_arg< traits >::type,
+ boost::function_traits<void (double)>
>::value ));
BOOST_STATIC_ASSERT(( boost::is_same<
void
>::value ));
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_member_pointer< Class (Class::*) >::type,
- Class
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_member_pointer< Class (Class::*) >::type,
+ Class
>::value ));
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_member_pointer< Class const (Class::*) >::type,
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_member_pointer< Class const (Class::*) >::type,
Class const
>::value ));
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_member_pointer< Class (Class::*)(int) >::type,
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_member_pointer< Class (Class::*)(int) >::type,
Class (int)
>::value ));
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_member_pointer< Class const (Class::*)(int) >::type,
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_member_pointer< Class const (Class::*)(int) >::type,
Class const (int)
>::value ));
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_member_pointer< void (Class::*)(int) const>::type,
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_member_pointer< void (Class::*)(int) const>::type,
void (int)
>::value ));
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_member_pointer< Class const (Class::*)(int) const>::type,
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_member_pointer< Class const (Class::*)(int) const>::type,
Class const (int)
>::value ));
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_member_pointer< void (Class::* const)(int)>::type,
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_member_pointer< void (Class::* const)(int)>::type,
void (int)
>::value ));
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_member_pointer< void (Class::* const)(int) const>::type,
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_member_pointer< void (Class::* const)(int) const>::type,
void (int)
>::value ));
void
>::value ));
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_any_pointer< int (Class::*) >::type,
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_any_pointer< int (Class::*) >::type,
int
>::value ));
- BOOST_STATIC_ASSERT(( boost::is_same<
- senf::remove_any_pointer< void (Class::*)(int) >::type,
+ BOOST_STATIC_ASSERT(( boost::is_same<
+ senf::remove_any_pointer< void (Class::*)(int) >::type,
void (int)
>::value ));
BOOST_STATIC_ASSERT(( boost::is_same<
BOOST_STATIC_ASSERT(( senf::is_pair< std::pair<int,void*> >::value ));
BOOST_STATIC_ASSERT(( ! senf::is_pair< void () >::value ));
-
+
BOOST_CHECK( true );
}
// 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 config public header */
-
+
#ifndef HH_config_
#define HH_config_ 1
-
+
// Custom includes
#include <boost/cstdint.hpp>
#include <limits.h>
-
+
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
#
# // Add other compilers here ...
#
-# // dynamic arrays are part of C99. Which is NOT part of C++
+# // dynamic arrays are part of C99. Which is NOT part of C++
# // but lets try nonetheless ...
# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
# define SENF_BUFFER_USE_LOCALS 1
# define SENF_DEBUG_BACKTRACE_NUMCALLERS 64
# endif
#
-# ifndef SENF_CONSOLE_MAX_COMMAND_ARITY
+# ifndef SENF_CONSOLE_MAX_COMMAND_ARITY
# define SENF_CONSOLE_MAX_COMMAND_ARITY 6
# endif
-#
+#
# ifndef PHOENIX_LIMIT
# define PHOENIX_LIMIT 6
# endif
# if __GLIBC__>=2 && __GLIBC_MINOR__>=8
# define HAVE_TIMERFD 1
# endif
-
+
///////////////////////////////hh.e////////////////////////////////////////
#endif
-
+
\f
// Local Variables:
// mode: c++
// ispell-local-dictionary: "american"
// compile-command: "scons -u all_tests"
// End:
-
+
find . \
-name .svn -prune -o \
-name .git -prune -o \
+ -name .sconf_temp -prune -o \
-name doc -prune -o \
-name debian -prune -o \
-name dist -prune -o \