\section class_diagram Class Diagram
\image html classes.png
-
- \fixme Implement Spliters: PassiveSplitter, PrioritySplitter, CloneSplitter
- \fixme Implement DiscardSink, CloneSource
- \fixme Implement ThrottleBarrier
*/
\f
\li \ref sourcesink_modules generate or absorb packets internally
\li \ref routing_modules forward packets within the network
\li \ref adapter_modules are used to connect incompatible connectors to each other
+
+ \todo Implement Spliters: PassiveSplitter, PrioritySplitter, CloneSplitter
*/
/** \defgroup io_modules Input/Output Modules
}
prefix_ int senf::ConnectedCommunicationPolicy::do_accept(FileHandle handle,
- struct sockaddr * addr,
- unsigned len)
+ struct sockaddr * addr,
+ unsigned len)
{
int rv = -1;
do {
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief CommunicationPolicy inline non-template implementation */
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+prefix_ int senf::ConnectedCommunicationPolicy::accept(FileHandle handle)
+{
+ return do_accept(handle, 0, 0);
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
\returns file descriptor of new client socket */
# endif
+ static int accept(FileHandle handle);
+ ///< accept a new connection on the socket.
+ /**< The accept() member will return a new client file
+ descriptor. This file descriptor will be used by the
+ ServerSocketHandle implementation to build a new
+ ClientSocketHandle for the new connection.
+
+ \param[in] handle socket handle to accept connection on
+ \returns file descriptor of new client socket */
+
private:
static void do_listen(FileHandle handle, unsigned backlog);
static int do_accept(FileHandle handle, struct sockaddr * addr, unsigned len);
///////////////////////////////hh.e////////////////////////////////////////
-//#include "CommunicationPolicy.cci"
+#include "CommunicationPolicy.cci"
//#include "CommunicationPolicy.ct"
#include "CommunicationPolicy.cti"
#endif
struct in_addr ina;
if (::inet_pton(AF_INET,s.c_str(),&ina) > 0)
return senf::INet4Address::from_inaddr(ina.s_addr);
+
+ if (s.empty())
+ throw SyntaxException();
+
int herr (0);
// If available, we use the reentrant GNU variant. This has the additional advantage, that we
# endif // __GLIBC__
if (!ent)
- ///\fixme Need to give better exception here
- throw SyntaxException();
+ throw UnknownHostnameException();
if (ent->h_addrtype != AF_INET)
- throw SyntaxException();
+ throw UnknownHostnameException();
// We are only interested in the first address ...
return senf::INet4Address::from_inaddr(
#include <iostream>
#include <string>
#include <boost/cstdint.hpp>
-#include <boost/function.hpp>
#include <boost/array.hpp>
#include <boost/operators.hpp>
#include "Utils/SafeBool.hh"
therefore not be distinguished from initialization with a string literal. Therefore we
need to disambiguate using the named constructors.
- \todo Add additional classes for CIDR addresses and networks and network math.
\ingroup addr_group
*/
class INet4Address
typedef uint32_t address_type; ///< Address representation as number in host byte order
typedef uint32_t inaddr_type; ///< Legacy address representation in network byte order
- typedef boost::function<void (INet4Address const &)> Callback;
- ///< Callback for asynchronous from_string call
static INet4Address const None; ///< The empty (0) address
static INet4Address const Loopback; ///< The loopback (127.0.0.1) address
converted for some reason
\param[in] s Address literal or hostname */
- static void from_string(std::string const & s, Callback const & cb);
- ///< Convert string to address (async/non-blocking)
- /**< This member works like
- from_string(std::string const &). However unlike
- from_string(std::string const &), this call will not
- block. Instead it will call \a cb passing the
- INet4Address instance as soon as the address has been
- resolved (which may be immediate if the address
- represents an IP literal). \par
- On error, the address passed to \a cb will be empty.
- \param[in] s Address literal or hostname
- \param[in] cb Callback to pass the address to
- \fixme Implement */
-
template <class InputIterator>
static INet4Address from_data(InputIterator i);
///< Construct address from 4 bytes of raw data
////@}
- struct SyntaxException : public std::exception
- { virtual char const * what() const throw() { return "invalid INet4 address syntax"; } };
+ /** \brief Base-class for INet4Address exceptions */
+ struct AddressException : public std::exception {};
+
+ /** \brief Invalid INet4 address syntax */
+ struct SyntaxException : public AddressException
+ { virtual char const * what() const throw()
+ { return "invalid INet4 address syntax"; } };
+ /** \brief Resolver failure */
+ struct UnknownHostnameException : public AddressException
+ { virtual char const * what() const throw()
+ { return "failed to resolve INet4 hostname"; } };
+
private:
enum InAddr_t { IsInAddr };
INet4Address(inaddr_type addr, InAddr_t);
struct in6_addr ina;
if (::inet_pton(AF_INET6,s.c_str(),&ina) > 0)
return senf::INet6Address::from_data(&ina.s6_addr[0]);
+
+ if (s.empty())
+ throw SyntaxException();
+
int herr (0);
// If available, we use the reentrant GNU variant. This has the additional advantage, that we
return senf::INet6Address::from_data(
&reinterpret_cast<in6_addr*>(*(ent->h_addr_list))->s6_addr[0]);
- ///\todo Throw better exceptions here ?
-
if (resolve == ResolveINet4)
try {
return from_inet4address(INet4Address::from_string(s));
} catch (INet4Address::SyntaxException const & ex) {
throw SyntaxException();
+ } catch (INet4Address::UnknownHostnameException const & ex) {
+ throw UnknownHostnameException();
}
else
- throw SyntaxException();
+ throw UnknownHostnameException();
}
prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Address const & addr)
#include <iostream>
#include <string>
#include <boost/cstdint.hpp>
-#include <boost/function.hpp>
#include <boost/array.hpp>
#include <boost/operators.hpp>
#include "Utils/SafeBool.hh"
///////////////////////////////////////////////////////////////////////////
// Types
- typedef boost::function<void (INet6Address const &)> Callback;
- ///< Callback for asynchronous from_string call
-
static INet6Address const None; ///< The empty (::0) address
static INet6Address const Loopback; ///< The loopback (::1) address
static INet6Address const AllNodes; ///< The 'all nodes' link-local multicast address
found. The address will be returned as mapped IpV6
address. */
- static void from_string(std::string const & s, Callback const & cb,
- Resolve_t resolve = ResolveINet6);
- ///< Convert string to address (async/non-blocking)
- /**< This member works like
- from_string(std::string const &). However unlike
- from_string(std::string const &), this call will not
- block. Instead it will call \a cb passing the
- INet6Address instance as soon as the address has been
- resolved (which may be immediate if the address
- represents an IP literal). \par
- On error, the address passed to \a cb will be empty.
- \param[in] s Address literal or hostname
- \param[in] cb Callback to pass the address to
- \param[in] resolve If this is set to \c ResolveINet4,
- the call will additionally try to interpret \a s as
- an IpV4 address if no valid IpV6 address is
- found. The address will be returned as mapped IpV6
- address.
- \fixme Implement */
-
template <class InputIterator>
static INet6Address from_data(InputIterator i);
///< Construct address from 16 bytes of raw data
///@}
- /** \brief Invalid IpV6 address syntax */
- struct SyntaxException : public std::exception
- { virtual char const * what() const throw() { return "Invalid IpV6 address syntax"; } };
+ /** \brief Base-class for INet6Address exceptions */
+ struct AddressException : public std::exception {};
+
+ /** \brief Invalid INet4 address syntax */
+ struct SyntaxException : public AddressException
+ { virtual char const * what() const throw()
+ { return "invalid INet6 address syntax"; } };
+
+ /** \brief Resolver failure */
+ struct UnknownHostnameException : public AddressException
+ { virtual char const * what() const throw()
+ { return "failed to resolve INet6 hostname"; } };
};
/** \brief Output INet6Address instance as it's string representation
BOOST_CHECK_EQUAL( INet6Address::from_inet4address(INet4Address(0x01020304)),
INet6Address::from_string("::ffff:1.2.3.4") );
- BOOST_CHECK_THROW( INet6Address::from_string("1.2.3.4"), INet6Address::SyntaxException );
+ BOOST_CHECK_THROW( INet6Address::from_string("1.2.3.4"), INet6Address::UnknownHostnameException );
BOOST_CHECK_EQUAL( INet6Address::from_string("1.2.3.4", INet6Address::ResolveINet4),
INet6Address::from_string("::ffff:1.2.3.4") );
}
unsigned i = addr.find(':');
if (i == std::string::npos)
throw SyntaxException();
- address(INet4Address::from_string(std::string(addr,0,i)));
try {
port(boost::lexical_cast< ::u_int16_t >(std::string(addr,i+1)));
}
catch (boost::bad_lexical_cast const &) {
throw SyntaxException();
}
+ try {
+ address(INet4Address::from_string(std::string(addr,0,i)));
+ }
+ catch (INet4Address::SyntaxException const &) {
+ throw SyntaxException();
+ }
}
prefix_ senf::INet4SocketAddress::INet4SocketAddress(INet4Address const & addr, unsigned p)
if (! regex_match(addr, match, addressRx))
throw SyntaxException();
- INet6Address a (INet6Address::from_string(
- match[NumericAddr].matched ? match[NumericAddr] : match[Hostname],
- resolve));
- std::copy(a.begin(), a.end(), &sockaddr_.sin6_addr.s6_addr[0]);
-
if (match[ZoneId].matched)
assignIface(match[ZoneId]);
sockaddr_.sin6_port = htons(boost::lexical_cast<boost::uint16_t>(match[Port]));
+
+ try {
+ INet6Address a (INet6Address::from_string(
+ match[NumericAddr].matched ? match[NumericAddr] : match[Hostname],
+ resolve));
+ std::copy(a.begin(), a.end(), &sockaddr_.sin6_addr.s6_addr[0]);
+ } catch (INet6Address::SyntaxException const &) {
+ throw SyntaxException();
+ }
}
prefix_ bool senf::INet6SocketAddress::operator==(INet6SocketAddress const & other)
{
public:
INet4SocketAddress();
- explicit INet4SocketAddress(std::string const & address); ///< Set address and port
+ explicit INet4SocketAddress(std::string const & addr); ///< Set address and port
/**< This constructor expects a string of the form
'host:port'. The constructor will use this value to
initialize the host and port members. Since it uses the
INet4Address::from_string constructor, this call may
block while waiting for the resolver.
- \throws SyntaxException if the 'host:port' syntax is
- not obeyed.
- \throws INet4Address::SyntaxException if the host part
- cannot be converted to an IP address. */
+ \throws SyntaxException if the address syntax is
+ invalid
+ \throws INet4Address::UnknownHostnameException if the
+ address cannot be resolved. */
INet4SocketAddress(INet4Address const & addr, unsigned port);
///< Set address and port explicitly
explicit INet6SocketAddress(std::string const & addr,
INet6Address::Resolve_t resolve = INet6Address::ResolveINet6);
///< Initialize/convert from string representation
- /**< \param[in] addr Address to parse
+ /**< \throws SyntaxException if the address syntax is
+ invalid
+ \throws INet6Address::UnknownHostnameException if the
+ address cannot be resolved.
+ \param[in] addr Address to parse
\param[in] resolve If this is
- INet6Address::ResolveINet4, support also IpV4
+ INet6Address::ResolveINet4, support IpV4
addresses. See INet6Address. */
INet6SocketAddress(INet6Address const & addr, unsigned port);
///< Initialize from address and port
INet4SocketAddress(INet4Address::Loopback,12345) );
BOOST_CHECK_THROW( INet4SocketAddress("127.0.0.1"), INet4SocketAddress::SyntaxException );
- BOOST_CHECK_THROW( INet4SocketAddress("foo@bar:12345"), INet4Address::SyntaxException );
+ BOOST_CHECK_THROW( INet4SocketAddress("foo:bar"), INet4SocketAddress::SyntaxException );
+ BOOST_CHECK_THROW( INet4SocketAddress(":12345"), INet4SocketAddress::SyntaxException );
BOOST_CHECK_THROW( INet4SocketAddress("127.0.0.1:1234a"), INet4SocketAddress::SyntaxException );
BOOST_CHECK_EQUAL( INet4SocketAddress("127.0.0.1:12345").address(), INet4Address::Loopback );
prefix_ typename senf::ServerSocketHandle<Policy>::ClientSocketHandle
senf::ServerSocketHandle<Policy>::accept()
{
- Address address;
- return acceptfrom(address);
+ return ClientSocketHandle(this->protocol().clone(),
+ Policy::CommunicationPolicy::accept(*this));
}
template <class Policy>
{
Address address;
- ClientSocketHandle handle = accept(address);
+ ClientSocketHandle handle = acceptfrom(address);
return std::make_pair(handle,address);
}
This variant ...
\returns handle of new client connection
-
- \fixme Make this accept()-variant work with unspecified addressing policy
*/
ClientSocketHandle
accept ();
<table class="senf">
<tr><td>method</td> <td><tt>void listen(FileHandle, unsigned backlog)</tt></td> <td>Switch socket into listening state</td></tr>
<tr><td>method</td> <td><tt>int accept(FileHandle, Address &)</tt></td> <td>Accept a new connection</td></tr>
+ <tr><td>method</td> <td><tt>int accept(FileHandle)</tt></td> <td>Accept a new connection</td></tr>
</table>
The \c listen member is straight forward. The \c accept() member must return a new file
descriptor (which will be used to create a new SocketHandle of the correct
- type). Additionally, accept() should only be defined, if the Addressing policy is not \c
- NoAddressingPolicy (which together with ConnectedCommunicationPolicy would identify a
- point-to-point link with fixed communication partners).
+ type).
\note This Policy only has two meaningful states: ConnectedCommunicationPolicy and
UnconnectedCommunicationPolicy. It is probably not sensible to define a new
{
static int accept(FileHandle handle, unsigned & addr)
{ addr = 3; return -1; }
+ static int accept(FileHandle handle)
+ { return -1; }
};
struct SomeReadPolicy : public senf::ReadPolicyBase
if (/^(#?[0-9]| )/) {
push @l,$_ if /^#/;
$l[$#l] .= $_ if @l && /^ /;
+ } elsif (/^Current language: auto;/) {
+ ;
} else {
$mode=0;
if (/: fatal error in /) {