From cf6ffc4c853abb36b30c93f500cc1c04a501ee71 Mon Sep 17 00:00:00 2001 From: sbund <sbund@wiback.org> Date: Fri, 1 Sep 2006 15:44:01 +0000 Subject: [PATCH] implemented further protocol methods --- Socket/BSDSocketProtocol.cc | 84 +++++++++++++++++++++++++++ Socket/BSDSocketProtocol.hh | 60 +++++++++++++++++++ Socket/INetProtocol.cc | 112 ++++++++++++++++++++++++++++++++++++ Socket/INetProtocol.hh | 31 +++++++++- Socket/SocketProtocol.cci | 6 +- Socket/SocketProtocol.hh | 28 +++++---- Socket/TCPProtocol.cc | 84 +++++++++++++++++++++++++++ Socket/TCPProtocol.hh | 11 +++- Socket/TCPSocketHandle.cc | 37 +----------- Socket/TCPSocketHandle.hh | 10 +--- 10 files changed, 404 insertions(+), 59 deletions(-) create mode 100644 Socket/BSDSocketProtocol.cc create mode 100644 Socket/BSDSocketProtocol.hh create mode 100644 Socket/TCPProtocol.cc diff --git a/Socket/BSDSocketProtocol.cc b/Socket/BSDSocketProtocol.cc new file mode 100644 index 000000000..b171fb33d --- /dev/null +++ b/Socket/BSDSocketProtocol.cc @@ -0,0 +1,84 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline non-template functions + +#include "BSDSocketProtocol.hh" +//#include "BSDSocketProtocol.ih" + +// Custom includes +#include <sys/types.h> +#include <sys/socket.h> +#include "SocketHandle.hh" + +//#include "BSDSocketProtocol.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ bool satcom::lib::BSDSocketProtocol::reuseaddr() + const +{ + int value; + socklen_t len (sizeof(value)); + if (::getsockopt(body().fd(),SOL_SOCKET,SO_REUSEADDR,&value,&len) < 0) + throw SystemException(errno); + return value; +} + +prefix_ void satcom::lib::BSDSocketProtocol::reuseaddr(bool value) + const +{ + // FIXME: This is only relevant for addressable sockets (not for e.g. socketpair) + int ivalue (value); + if (::setsockopt(body().fd(),SOL_SOCKET,SO_REUSEADDR,&ivalue,sizeof(ivalue)) < 0) + throw SystemException(errno); +} + +prefix_ std::pair<bool,unsigned> satcom::lib::BSDSocketProtocol::linger() +{ + // FIXME: This is really only relevant for stream sockets ... + // TODO: Can the linger timeout be 0 or -1 and what does that mean? + struct linger ling; + socklen_t len = sizeof(ling); + if (::getsockopt(body().fd(),SOL_SOCKET,SO_LINGER,&ling,&len) < 0) + throw SystemException(errno); + return std::make_pair(ling.l_onoff,ling.l_linger); +} + +prefix_ void satcom::lib::BSDSocketProtocol::linger(bool enable, unsigned timeout) +{ + struct linger ling; + ling.l_onoff = enable; + ling.l_linger = timeout; + if (::setsockopt(body().fd(),SOL_SOCKET,SO_LINGER,&ling,sizeof(ling)) < 0) + throw SystemException(errno); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "BSDSocketProtocol.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/BSDSocketProtocol.hh b/Socket/BSDSocketProtocol.hh new file mode 100644 index 000000000..f8d5c0041 --- /dev/null +++ b/Socket/BSDSocketProtocol.hh @@ -0,0 +1,60 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HH_BSDSocketProtocol_ +#define HH_BSDSocketProtocol_ 1 + +// Custom includes +#include "SocketProtocol.hh" + +//#include "BSDSocketProtocol.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + class BSDSocketProtocol + : public virtual SocketProtocolHelper + { + public: + bool reuseaddr() const; + void reuseaddr(bool value) const; + + std::pair<bool,unsigned> linger(); + void linger(bool enable, unsigned timeout); + }; + +}} + + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "BSDSocketProtocol.cci" +//#include "BSDSocketProtocol.ct" +//#include "BSDSocketProtocol.cti" +//#include "BSDSocketProtocol.mpp" +#endif + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/INetProtocol.cc b/Socket/INetProtocol.cc index efdf8a75a..d1ebe9ec6 100644 --- a/Socket/INetProtocol.cc +++ b/Socket/INetProtocol.cc @@ -27,12 +27,17 @@ // Custom includes #include <sys/socket.h> +#include <netinet/in.h> +#include <net/if.h> // for if_nametoindex #include "Utils/Exception.hh" //#include "INetProtocol.mpp" #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::INet4AddressingPolicy + prefix_ void satcom::lib::INet4AddressingPolicy::local(FileHandle handle, Address & addr) { addr.clear(); @@ -58,10 +63,117 @@ prefix_ void satcom::lib::INet4AddressingPolicy::do_peer(FileHandle handle, Addr prefix_ void satcom::lib::INet4AddressingPolicy::do_connect(FileHandle handle, Address const & addr) { + // FIXME: a non-blocking socket will return with EINPROGRESS + // This necessitates reading the SO_ERROR value and poll-ing for + // completion !! (see man connect) if (::connect(handle.fd(),addr.sockaddr_p(),addr.sockaddr_len()) < 0) throw SystemException(errno); } +/////////////////////////////////////////////////////////////////////////// +// satcom::lib::INet4Protocol + +prefix_ void satcom::lib::IPv4Protocol::connect(INet4Address const & address) + const +{ + if (::connect(body().fd(),address.sockaddr_p(), address.sockaddr_len()) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::IPv4Protocol::bind(INet4Address const & address) + const +{ + if (::bind(body().fd(),address.sockaddr_p(), address.sockaddr_len()) < 0) + throw SystemException(errno); +} + +prefix_ bool satcom::lib::IPv4Protocol::mcLoop() +{ + int value; + socklen_t len (sizeof(value)); + if (::getsockopt(body().fd(),SOL_IP,IP_MULTICAST_LOOP,&value,&len) < 0) + throw SystemException(errno); + return value; +} + +prefix_ void satcom::lib::IPv4Protocol::mcLoop(bool value) +{ + int ivalue (value); + if (::setsockopt(body().fd(),SOL_IP,IP_MULTICAST_LOOP,&ivalue,sizeof(ivalue)) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::IPv4Protocol::mcAddMembership(INet4Address const & mcAddr) +{ + struct ip_mreqn mreqn; + mreqn.imr_multiaddr = reinterpret_cast<struct sockaddr_in const *>(mcAddr.sockaddr_p())->sin_addr; + mreqn.imr_address.s_addr = htons(INADDR_ANY); + mreqn.imr_ifindex = 0; + if (::setsockopt(body().fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::IPv4Protocol::mcAddMembership(INet4Address const & mcAddr, + INet4Address const & localAddr) +{ + struct ip_mreqn mreqn; + mreqn.imr_multiaddr = reinterpret_cast<struct sockaddr_in const *>(mcAddr.sockaddr_p())->sin_addr; + mreqn.imr_address = reinterpret_cast<struct sockaddr_in const *>(localAddr.sockaddr_p())->sin_addr; + mreqn.imr_ifindex = 0; + if (::setsockopt(body().fd(),SOL_IP,IP_ADD_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::IPv4Protocol::mcDropMembership(INet4Address const & mcAddr) +{ + struct ip_mreqn mreqn; + mreqn.imr_multiaddr = reinterpret_cast<struct sockaddr_in const *>(mcAddr.sockaddr_p())->sin_addr; + mreqn.imr_address.s_addr = htons(INADDR_ANY); + mreqn.imr_ifindex = 0; + if (::setsockopt(body().fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::IPv4Protocol::mcDropMembership(INet4Address const & mcAddr, + INet4Address const & localAddr) +{ + struct ip_mreqn mreqn; + mreqn.imr_multiaddr = reinterpret_cast<struct sockaddr_in const *>(mcAddr.sockaddr_p())->sin_addr; + mreqn.imr_address = reinterpret_cast<struct sockaddr_in const *>(localAddr.sockaddr_p())->sin_addr; + mreqn.imr_ifindex = 0; + if (::setsockopt(body().fd(),SOL_IP,IP_DROP_MEMBERSHIP,&mreqn,sizeof(mreqn)) < 0) + throw SystemException(errno); +} + +prefix_ void satcom::lib::IPv4Protocol::mcIface(std::string iface) +{ + struct ip_mreqn mreqn; + ::memset(&mreqn,sizeof(mreqn),0); + if (!iface.empty()) { + mreqn.imr_ifindex = if_nametoindex(iface.c_str()); + if (mreqn.imr_ifindex == 0) + throw SystemException(EINVAL); + } + if (::setsockopt(body().fd(),SOL_IP,IP_MULTICAST_IF,&mreqn,sizeof(mreqn)) < 0) + throw SystemException(errno); +} + +prefix_ unsigned satcom::lib::IPv4Protocol::mcTTL() +{ + int value; + socklen_t len (sizeof(value)); + if (::getsockopt(body().fd(),SOL_IP,IP_MULTICAST_TTL,&value,&len) < 0) + throw SystemException(errno); + return value; +} + +prefix_ void satcom::lib::IPv4Protocol::mcTTL(unsigned value) +{ + if (::setsockopt(body().fd(),SOL_IP,IP_MULTICAST_TTL,&value,sizeof(value)) < 0) + throw SystemException(errno); +} + + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "INetProtocol.mpp" diff --git a/Socket/INetProtocol.hh b/Socket/INetProtocol.hh index 24e520469..ecfb189c2 100644 --- a/Socket/INetProtocol.hh +++ b/Socket/INetProtocol.hh @@ -20,10 +20,13 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// TODO: what about OOB data? das OOB Data block receipt of normal data ? + #ifndef HH_INetProtocol_ #define HH_INetProtocol_ 1 // Custom includes +#include "SocketProtocol.hh" #include "SocketPolicy.hh" #include "INetAddress.hh" #include "ClientSocketHandle.hh" @@ -62,9 +65,35 @@ namespace lib { }; class IPv4Protocol - {}; + : public virtual SocketProtocolHelper + { + public: + void connect(INet4Address const & address) const; + void bind(INet4Address const & address) const; + + unsigned mcTTL(); + void mcTTL(unsigned value); + + bool mcLoop(); + void mcLoop(bool value); + + // TODO: Implement real INet4Address datatype and + // rename this one to INet4SockAddress ... + // TODO: Is it safe, not to allow setting the interface + // index on add/drop? what does it do (especially if + // the local addres is given ?) + + void mcAddMembership(INet4Address const & mcAddr); + void mcAddMembership(INet4Address const & mcAddr, INet4Address const & localAddr); + + void mcDropMembership(INet4Address const & mcAddr); + void mcDropMembership(INet4Address const & mcAddr, INet4Address const & localAddr); + + void mcIface(std::string iface = std::string()); + }; class IPv6Protocol + : public virtual SocketProtocolHelper {}; }} diff --git a/Socket/SocketProtocol.cci b/Socket/SocketProtocol.cci index 82611e179..ae71b1404 100644 --- a/Socket/SocketProtocol.cci +++ b/Socket/SocketProtocol.cci @@ -30,14 +30,14 @@ #define prefix_ inline ///////////////////////////////cci.p/////////////////////////////////////// -prefix_ satcom::lib::SocketProtocol::SocketProtocol() +prefix_ satcom::lib::SocketProtocolHelper::SocketProtocolHelper() : body_() {} -prefix_ satcom::lib::SocketProtocol::~SocketProtocol() +prefix_ satcom::lib::SocketProtocolHelper::~SocketProtocolHelper() {} -prefix_ satcom::lib::SocketBody & satcom::lib::SocketProtocol::body() +prefix_ satcom::lib::SocketBody & satcom::lib::SocketProtocolHelper::body() const { BOOST_ASSERT( body_ ); diff --git a/Socket/SocketProtocol.hh b/Socket/SocketProtocol.hh index 4f9c24f84..306d7f8fa 100644 --- a/Socket/SocketProtocol.hh +++ b/Socket/SocketProtocol.hh @@ -36,11 +36,24 @@ namespace lib { class FileHandle; class SocketPolicyBase; - /** \brief - */ - class SocketProtocol + class SocketProtocolHelper : boost::noncopyable { + public: + SocketProtocolHelper(); + virtual ~SocketProtocolHelper() = 0; + + SocketBody & body() const; + + private: + SocketBody * body_; + + friend class SocketBody; + }; + + class SocketProtocol + : public virtual SocketProtocolHelper + { public: /////////////////////////////////////////////////////////////////////////// // Types @@ -49,17 +62,13 @@ namespace lib { ///\name Structors and default members ///@{ - SocketProtocol(); - virtual ~SocketProtocol() = 0; - - // no default constructor + // default default constructor // no copy // no conversion constructors ///@} /////////////////////////////////////////////////////////////////////////// - SocketBody & body() const; virtual SocketPolicyBase const & policy() const = 0; /////////////////////////////////////////////////////////////////////////// @@ -74,9 +83,6 @@ namespace lib { private: // That SocketBody instance owns us and controls our lifetime // Do we need this ?? - SocketBody * body_; - - friend class SocketBody; }; /** \brief diff --git a/Socket/TCPProtocol.cc b/Socket/TCPProtocol.cc new file mode 100644 index 000000000..835504471 --- /dev/null +++ b/Socket/TCPProtocol.cc @@ -0,0 +1,84 @@ +// $Id$ +// +// Copyright (C) 2006 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund <stefan.bund@fokus.fraunhofer.de> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +// Definition of non-inline non-template functions + +#include "TCPProtocol.hh" +//#include "TCPProtocol.ih" + +// Custom includes +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <sys/ioctl.h> +#include <linux/sockios.h> // for SIOCINQ / SIOCOUTQ +#include "SocketHandle.hh" + +//#include "TCPProtocol.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ bool satcom::lib::TCPProtocol::nodelay() + const +{ + int value; + socklen_t len (sizeof(value)); + if (::getsockopt(body().fd(),SOL_TCP,TCP_NODELAY,&value,&len) < 0) + throw SystemException(errno); + return value; +} + +prefix_ void satcom::lib::TCPProtocol::nodelay(bool value) + const +{ + int ivalue (value); + if (::setsockopt(body().fd(),SOL_TCP,TCP_NODELAY,&ivalue,sizeof(ivalue)) < 0) + throw SystemException(errno); +} + +prefix_ unsigned satcom::lib::TCPProtocol::siocinq() + const +{ + int n; + if (::ioctl(body().fd(),SIOCINQ,&n) < 0) + throw SystemException(errno); + return n; +} + +prefix_ unsigned satcom::lib::TCPProtocol::siocoutq() + const +{ + int n; + if (::ioctl(body().fd(),SIOCOUTQ,&n) < 0) + throw SystemException(errno); + return n; +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "TCPProtocol.mpp" + + +// Local Variables: +// mode: c++ +// c-file-style: "satcom" +// End: diff --git a/Socket/TCPProtocol.hh b/Socket/TCPProtocol.hh index 849da76df..fc3a80e48 100644 --- a/Socket/TCPProtocol.hh +++ b/Socket/TCPProtocol.hh @@ -24,6 +24,7 @@ #define HH_TCPProtocol_ 1 // Custom includes +#include "SocketProtocol.hh" //#include "TCPProtocol.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -32,7 +33,15 @@ namespace satcom { namespace lib { class TCPProtocol - {}; + : public virtual SocketProtocolHelper + { + public: + bool nodelay() const; + void nodelay(bool value) const; + + unsigned siocinq() const; + unsigned siocoutq() const; + }; }} diff --git a/Socket/TCPSocketHandle.cc b/Socket/TCPSocketHandle.cc index af9fa9c82..6b6835a76 100644 --- a/Socket/TCPSocketHandle.cc +++ b/Socket/TCPSocketHandle.cc @@ -36,24 +36,6 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -prefix_ bool satcom::lib::TCPv4SocketProtocol::reuseraddr() - const -{ - int value; - socklen_t len (sizeof(value)); - if (::getsockopt(body().fd(),SOL_SOCKET,SO_REUSEADDR,&value,&len) < 0) - throw SystemException(errno); - return value; -} - -prefix_ void satcom::lib::TCPv4SocketProtocol::reuseaddr(bool value) - const -{ - int ivalue (value); - if (::setsockopt(body().fd(),SOL_SOCKET,SO_REUSEADDR,&ivalue,sizeof(ivalue)) < 0) - throw SystemException(errno); -} - prefix_ void satcom::lib::TCPv4SocketProtocol::init_client() const { @@ -91,20 +73,6 @@ satcom::lib::TCPv4SocketProtocol::init_server(INet4Address const & address) throw SystemException(errno); } -prefix_ void satcom::lib::TCPv4SocketProtocol::connect(INet4Address const & address) - const -{ - if (::connect(body().fd(),address.sockaddr_p(), address.sockaddr_len()) < 0) - throw SystemException(errno); -} - -prefix_ void satcom::lib::TCPv4SocketProtocol::bind(INet4Address const & address) - const -{ - if (::bind(body().fd(),address.sockaddr_p(), address.sockaddr_len()) < 0) - throw SystemException(errno); -} - prefix_ std::auto_ptr<satcom::lib::SocketProtocol> satcom::lib::TCPv4SocketProtocol::clone() const { @@ -114,10 +82,7 @@ prefix_ std::auto_ptr<satcom::lib::SocketProtocol> satcom::lib::TCPv4SocketProto prefix_ unsigned satcom::lib::TCPv4SocketProtocol::available() const { - int n; - if (::ioctl(body().fd(),FIONREAD,&n) < 0) - throw SystemException(errno); - return n; + return siocinq(); } prefix_ bool satcom::lib::TCPv4SocketProtocol::eof() diff --git a/Socket/TCPSocketHandle.hh b/Socket/TCPSocketHandle.hh index e540315a5..d7d85454c 100644 --- a/Socket/TCPSocketHandle.hh +++ b/Socket/TCPSocketHandle.hh @@ -26,6 +26,7 @@ // Custom includes #include "INetProtocol.hh" #include "TCPProtocol.hh" +#include "BSDSocketProtocol.hh" #include "StreamFramingPolicy.hh" #include "CommunicationPolicy.hh" #include "ReadWritePolicy.hh" @@ -51,12 +52,10 @@ namespace lib { class TCPv4SocketProtocol : public ConcreteSocketProtocol<TCPv4Socket_Policy>, public IPv4Protocol, - public TCPProtocol + public TCPProtocol, + public BSDSocketProtocol { public: - bool reuseraddr() const; - void reuseaddr(bool value) const; - /////////////////////////////////////////////////////////////////////////// // internal interface @@ -65,9 +64,6 @@ namespace lib { void init_server() const; void init_server(INet4Address const & address) const; - void connect(INet4Address const & address) const; - void bind(INet4Address const & address) const; - std::auto_ptr<SocketProtocol> clone() const; unsigned available() const; bool eof() const; -- GitLab