summaryrefslogtreecommitdiff
path: root/libcult/cult/os/net/ipv4
diff options
context:
space:
mode:
authorJörg Frings-Fürst <jff@merkur>2014-05-18 16:08:14 +0200
committerJörg Frings-Fürst <jff@merkur>2014-05-18 16:08:14 +0200
commita15cf65c44d5c224169c32ef5495b68c758134b7 (patch)
tree3419f58fc8e1b315ba8171910ee044c5d467c162 /libcult/cult/os/net/ipv4
Imported Upstream version 3.3.0.2upstream/3.3.0.2
Diffstat (limited to 'libcult/cult/os/net/ipv4')
-rw-r--r--libcult/cult/os/net/ipv4/address.cxx37
-rw-r--r--libcult/cult/os/net/ipv4/address.hxx143
-rw-r--r--libcult/cult/os/net/ipv4/datagram-socket.cxx20
-rw-r--r--libcult/cult/os/net/ipv4/datagram-socket.hxx282
-rw-r--r--libcult/cult/os/net/ipv4/multicast-socket.cxx19
-rw-r--r--libcult/cult/os/net/ipv4/multicast-socket.hxx133
6 files changed, 634 insertions, 0 deletions
diff --git a/libcult/cult/os/net/ipv4/address.cxx b/libcult/cult/os/net/ipv4/address.cxx
new file mode 100644
index 0000000..2507ed6
--- /dev/null
+++ b/libcult/cult/os/net/ipv4/address.cxx
@@ -0,0 +1,37 @@
+// file : cult/os/net/ipv4/address.cxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/os/net/ipv4/address.hxx>
+
+#include <ostream>
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ namespace IPv4
+ {
+ std::ostream&
+ operator<< (std::ostream& os, Address const& addr)
+ {
+ char str[INET_ADDRSTRLEN];
+
+ if (inet_ntop (AF_INET,
+ &addr.addr_.sin_addr,
+ str,
+ INET_ADDRSTRLEN) == 0)
+ {
+ throw Address::Invalid ();
+ }
+
+ return os << str << ":" << addr.port ();
+ }
+ }
+ }
+ }
+}
+
diff --git a/libcult/cult/os/net/ipv4/address.hxx b/libcult/cult/os/net/ipv4/address.hxx
new file mode 100644
index 0000000..9168507
--- /dev/null
+++ b/libcult/cult/os/net/ipv4/address.hxx
@@ -0,0 +1,143 @@
+// file : cult/os/net/ipv4/address.hxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_OS_NET_IPV4_ADDRESS_HXX
+#define CULT_OS_NET_IPV4_ADDRESS_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/os/net/address.hxx>
+
+#include <netinet/in.h> // IPv4 types (sockaddr_in, etc)
+#include <arpa/inet.h> // hto{n,h}{s,l}, iNet_pton
+
+#include <iosfwd>
+#include <cstring> // memset
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ namespace IPv4
+ {
+ class Address: public Net::Address
+ {
+ public:
+ Address ()
+ {
+ std::memset (&addr_, 0, sizeof (addr_));
+ }
+
+ Address (sockaddr_in const& addr)
+ {
+ if (addr.sin_family != AF_INET)
+ throw Invalid ();
+
+ std::memset (&addr_, 0, sizeof (addr_));
+
+ addr_.sin_family = AF_INET;
+ addr_.sin_addr.s_addr = addr.sin_addr.s_addr;
+ addr_.sin_port = addr.sin_port;
+ }
+
+ Address (in_addr_t host_addr, in_port_t host_port)
+ {
+ std::memset (&addr_, 0, sizeof (addr_));
+
+ addr_.sin_family = AF_INET;
+ addr_.sin_addr.s_addr = htonl (host_addr);
+ addr_.sin_port = htons (host_port);
+ }
+
+ Address (String const& host_addr, in_port_t host_port)
+ {
+ std::memset (&addr_, 0, sizeof (addr_));
+
+ addr_.sin_family = AF_INET;
+ addr_.sin_port = htons (host_port);
+
+ if (inet_pton (AF_INET, host_addr.c_str (), &addr_.sin_addr) <= 0)
+ throw Invalid ();
+ }
+
+ public:
+ virtual sa_family_t
+ familiy () const
+ {
+ return AF_INET;
+ }
+
+ virtual sockaddr const*
+ raw_addr () const
+ {
+ return reinterpret_cast<sockaddr const*> (&addr_);
+ }
+
+ virtual Size
+ raw_size () const
+ {
+ return sizeof (addr_);
+ }
+
+ public:
+ sockaddr_in const&
+ addr () const
+ {
+ return addr_;
+ }
+
+ in_addr_t
+ ip () const
+ {
+ return ntohl (addr_.sin_addr.s_addr);
+ }
+
+ in_port_t
+ port () const
+ {
+ return ntohs (addr_.sin_port);
+ }
+
+ public:
+ friend
+ Boolean
+ operator< (Address const& x, Address const& y)
+ {
+ return (x.addr_.sin_addr.s_addr < y.addr_.sin_addr.s_addr) ||
+ ((x.addr_.sin_addr.s_addr == y.addr_.sin_addr.s_addr) &&
+ (x.addr_.sin_port < y.addr_.sin_port));
+ }
+
+ friend
+ Boolean
+ operator== (Address const& x, Address const& y)
+ {
+ return (x.addr_.sin_addr.s_addr == y.addr_.sin_addr.s_addr) &&
+ (x.addr_.sin_port == y.addr_.sin_port);
+ }
+
+ friend
+ Boolean
+ operator!= (Address const& x, Address const& y)
+ {
+ return !(x == y);
+ }
+
+ friend
+ std::ostream&
+ operator<< (std::ostream&, Address const&);
+
+ private:
+ sockaddr_in addr_;
+ };
+ }
+ }
+ }
+}
+
+
+#endif // CULT_OS_NET_IPV4_ADDRESS_HXX
diff --git a/libcult/cult/os/net/ipv4/datagram-socket.cxx b/libcult/cult/os/net/ipv4/datagram-socket.cxx
new file mode 100644
index 0000000..ce470cc
--- /dev/null
+++ b/libcult/cult/os/net/ipv4/datagram-socket.cxx
@@ -0,0 +1,20 @@
+// file : cult/os/net/ipv4/datagram-socket.cxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/os/net/ipv4/datagram-socket.hxx>
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ namespace IPv4
+ {
+ }
+ }
+ }
+}
+
diff --git a/libcult/cult/os/net/ipv4/datagram-socket.hxx b/libcult/cult/os/net/ipv4/datagram-socket.hxx
new file mode 100644
index 0000000..2aad43f
--- /dev/null
+++ b/libcult/cult/os/net/ipv4/datagram-socket.hxx
@@ -0,0 +1,282 @@
+// file : cult/os/net/ipv4/datagram-socket.hxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_OS_NET_IPV4_DATAGRAM_SOCKET_HXX
+#define CULT_OS_NET_IPV4_DATAGRAM_SOCKET_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/os/net/address.hxx>
+#include <cult/os/net/datagram-socket.hxx>
+#include <cult/os/net/ipv4/address.hxx>
+
+#include <unistd.h> // close
+#include <sys/socket.h> // socket, bind, sendto, revcfrom
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ namespace IPv4
+ {
+ class DatagramSocket: public virtual Net::DatagramSocket
+ {
+ public:
+ virtual
+ ~DatagramSocket ()
+ {
+ ::close (sock_);
+ }
+
+ DatagramSocket ()
+ {
+ sock_ = ::socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+ if (sock_ == -1)
+ throw Exception (); //@@
+ }
+
+ DatagramSocket (Address const& addr)
+ {
+ sock_ = ::socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+ if (sock_ == -1)
+ throw Exception (); //@@
+
+ if (::bind (sock_, addr.raw_addr (), addr.raw_size ()) == -1)
+ throw Exception (); //@@
+ }
+
+ public:
+ virtual sa_family_t
+ familiy () const
+ {
+ return AF_INET;
+ }
+
+ virtual Int
+ protocol () const
+ {
+ return IPPROTO_UDP;
+ }
+
+ // Options.
+ //
+ public:
+ Size
+ recv_buffer_size () const
+ {
+ Int r;
+ socklen_t s (sizeof (r));
+
+ if (::getsockopt (sock_,
+ SOL_SOCKET,
+ SO_RCVBUF,
+ &r,
+ &s) == -1)
+ {
+ throw Exception (); //@@
+ }
+
+ return static_cast<Size> (r);
+ }
+
+ Void
+ recv_buffer_size (Size size)
+ {
+ Int r (static_cast<Int> (size));
+
+ if (::setsockopt (sock_,
+ SOL_SOCKET,
+ SO_RCVBUF,
+ &r,
+ sizeof (r)) == -1)
+ {
+ throw Exception ();
+ }
+ }
+
+ Size
+ send_buffer_size () const
+ {
+ Int r;
+ socklen_t s (sizeof (r));
+
+ if (::getsockopt (sock_,
+ SOL_SOCKET,
+ SO_SNDBUF,
+ &r,
+ &s) == -1)
+ {
+ throw Exception ();
+ }
+
+ return static_cast<Size> (r);
+ }
+
+ void
+ send_buffer_size (Size size)
+ {
+ Int r (static_cast<Int> (size));
+
+ if (::setsockopt (sock_,
+ SOL_SOCKET,
+ SO_SNDBUF,
+ &r,
+ sizeof (r)) == -1)
+ {
+ throw Exception ();
+ }
+ }
+
+ public:
+ Void
+ connect (Address const& addr)
+ {
+ if (::connect (sock_, addr.raw_addr (), addr.raw_size ()) == -1)
+ throw Exception ();
+ }
+
+ Address
+ address () const
+ {
+ sockaddr_in raw_addr;
+ socklen_t raw_size (sizeof (raw_addr));
+
+ if (::getsockname (sock_,
+ reinterpret_cast<sockaddr*> (&raw_addr),
+ &raw_size) == -1)
+ {
+ throw Exception ();
+ }
+
+ return Address (raw_addr);
+ }
+
+
+ public:
+ virtual Size
+ send (Void const* buf, Size size, Net::Address const& addr)
+ {
+ if (addr.familiy () != familiy ())
+ throw InvalidAddress ();
+
+ return send (buf, size, dynamic_cast<Address const&> (addr));
+ }
+
+ virtual Size
+ send (Void const* buf, Size size, Address const& addr)
+ {
+ ssize_t n (::sendto (sock_,
+ buf,
+ size,
+ 0,
+ addr.raw_addr (),
+ addr.raw_size ()));
+
+ if (n == -1)
+ throw Exception ();
+
+ return static_cast<Size> (n);
+ }
+
+ virtual Size
+ recv (Void* buf, Size size)
+ {
+ ssize_t n (::recvfrom (sock_, buf, size, 0, 0, 0));
+
+ if (n == -1)
+ throw Exception ();
+
+ return static_cast<Size> (n);
+ }
+
+ virtual Size
+ recv (Void* buf, Size size, Address& addr)
+ {
+ sockaddr_in raw_addr;
+ socklen_t raw_size (sizeof (raw_addr));
+
+ ssize_t n (::recvfrom (sock_,
+ buf,
+ size,
+ 0,
+ reinterpret_cast<sockaddr*> (&raw_addr),
+ &raw_size));
+
+ if (n == -1)
+ throw Exception ();
+
+ addr = Address (raw_addr);
+
+ return static_cast<Size> (n);
+ }
+
+ virtual Size
+ peek (Void* buf, Size size, Address& addr)
+ {
+ sockaddr_in raw_addr;
+ socklen_t raw_size (sizeof (raw_addr));
+
+ ssize_t n (::recvfrom (sock_,
+ buf,
+ size,
+ MSG_PEEK,
+ reinterpret_cast<sockaddr*> (&raw_addr),
+ &raw_size));
+
+ if (n == -1)
+ throw Exception ();
+
+ addr = Address (raw_addr);
+
+ return static_cast<Size> (n);
+ }
+
+ /*
+ virtual Boolean
+ recv (Void* buf,
+ Size size,
+ Size& received,
+ OS::Time const& timeout)
+ {
+ fd_set r,e;
+
+ FD_ZERO (&r);
+ FD_ZERO (&e);
+
+ FD_SET (sock_, &r);
+ FD_SET (sock_, &e);
+
+ int n = ::pselect (sock_ + 1, &r, 0, &e, &timeout.timespec (), 0);
+
+ if (n > 0)
+ {
+ recv_size = recv (buf, buf_size);
+ return true;
+ }
+ else if (n == 0) // timeout
+ {
+ return false;
+ }
+ else
+ {
+ throw Failure ("pselect");
+ }
+ }
+ */
+
+ protected:
+ Int sock_;
+ };
+ }
+ }
+ }
+}
+
+
+#endif // CULT_OS_NET_IPV4_DATAGRAM_SOCKET_HXX
diff --git a/libcult/cult/os/net/ipv4/multicast-socket.cxx b/libcult/cult/os/net/ipv4/multicast-socket.cxx
new file mode 100644
index 0000000..1431adc
--- /dev/null
+++ b/libcult/cult/os/net/ipv4/multicast-socket.cxx
@@ -0,0 +1,19 @@
+// file : cult/os/net/ipv4/multicast-socket.cxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cult/os/net/ipv4/multicast-socket.hxx>
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ namespace IPv4
+ {
+ }
+ }
+ }
+}
diff --git a/libcult/cult/os/net/ipv4/multicast-socket.hxx b/libcult/cult/os/net/ipv4/multicast-socket.hxx
new file mode 100644
index 0000000..70207a3
--- /dev/null
+++ b/libcult/cult/os/net/ipv4/multicast-socket.hxx
@@ -0,0 +1,133 @@
+// file : cult/os/net/ipv4/multicast-socket.hxx
+// author : Boris Kolpackov <boris@kolpackov.Net>
+// copyright : Copyright (c) 2005-2010 Boris Kolpackov
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#ifndef CULT_OS_NET_IPV4_MULTICAST_SOCKET_HXX
+#define CULT_OS_NET_IPV4_MULTICAST_SOCKET_HXX
+
+#include <cult/types.hxx>
+
+#include <cult/os/net/address.hxx>
+#include <cult/os/net/multicast-socket.hxx>
+#include <cult/os/net/ipv4/address.hxx>
+#include <cult/os/net/ipv4/datagram-socket.hxx>
+
+#include <cstring> // memcpy
+#include <sys/socket.h> // bind, setsockopt
+#include <arpa/inet.h> // htonl
+
+namespace Cult
+{
+ namespace OS
+ {
+ namespace Net
+ {
+ namespace IPv4
+ {
+ //@@ Add MulticastAddress (with proper checks)?
+ //
+
+ class MulticastSocket : public virtual Net::MulticastSocket,
+ public virtual DatagramSocket
+ {
+ public:
+ virtual
+ ~MulticastSocket ()
+ {
+ }
+
+ public:
+ MulticastSocket (Boolean loop = true, UnsignedShort ttl = 1)
+ {
+ unsigned char ttl_ (static_cast<unsigned char> (ttl));
+
+ {
+ Int flag (1);
+
+ if (::setsockopt (sock_,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ &flag,
+ sizeof (flag)) == -1)
+ {
+ throw Exception ();
+ }
+ }
+
+ if (ttl != 1)
+ {
+ if (::setsockopt (sock_,
+ IPPROTO_IP,
+ IP_MULTICAST_TTL,
+ &ttl_,
+ sizeof (ttl_)) == -1)
+ {
+ throw Exception ();
+ }
+ }
+
+ if (!loop)
+ {
+ unsigned char flag (0);
+
+ if (::setsockopt (sock_,
+ IPPROTO_IP,
+ IP_MULTICAST_LOOP,
+ &flag,
+ sizeof (flag)) == -1)
+ {
+ throw Exception ();
+ }
+ }
+
+ }
+
+ public:
+ virtual Void
+ join (Net::Address const& addr)
+ {
+ if (addr.familiy () != familiy ())
+ throw InvalidAddress ();
+
+ join (dynamic_cast<Address const&> (addr));
+ }
+
+ virtual Void
+ join (Address const& addr)
+ {
+ ip_mreq mreq;
+
+ std::memcpy (&mreq.imr_multiaddr,
+ &addr.addr ().sin_addr,
+ sizeof (in_addr));
+
+ mreq.imr_interface.s_addr = htonl (INADDR_ANY);
+
+ if (::setsockopt (sock_,
+ IPPROTO_IP,
+ IP_ADD_MEMBERSHIP,
+ &mreq,
+ sizeof (mreq)) == -1)
+ {
+ throw Exception ();
+ }
+
+ if (::bind (sock_, addr.raw_addr (), addr.raw_size ()) == -1)
+ throw Exception ();
+ }
+
+ virtual Void
+ leave ()
+ {
+ //@@ TODO
+ abort ();
+ }
+ };
+ }
+ }
+ }
+}
+
+
+#endif // CULT_OS_NET_IPV4_MULTICAST_SOCKET_HXX