]> git.tdb.fi Git - libs/net.git/commitdiff
Add IPv6 support
authorMikko Rasa <tdb@tdb.fi>
Sat, 15 Jan 2011 18:09:48 +0000 (18:09 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sat, 15 Jan 2011 18:09:48 +0000 (18:09 +0000)
source/datagramsocket.cpp
source/inet.cpp
source/inet.h
source/inet6.cpp [new file with mode: 0644]
source/inet6.h [new file with mode: 0644]
source/resolve.cpp
source/sockaddr.cpp
source/sockaddr.h
source/socket.cpp
source/streamlistensocket.cpp
source/streamsocket.cpp

index 7944532aa673a4e09ae0ae619bc98e719e381e62..a1b1c9ec7c8cd49ea3bc167c84093a4d8aff5c40 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspnet
-Copyright © 2008  Mikkosoft Productions, Mikko Rasa
+Copyright © 2008, 2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the LGPL
 */
 
@@ -25,10 +25,10 @@ int DatagramSocket::connect(const SockAddr &addr)
 {
        check_state(false);
 
-       sockaddr sa;
+       sockaddr_storage sa;
        socklen_t size=addr.fill_sockaddr(sa);
 
-       int err=::connect(handle, &sa, size);
+       int err=::connect(handle, reinterpret_cast<sockaddr *>(&sa), size);
        if(err==-1)
                throw SystemError("Unable to connect", errno);
 
@@ -36,8 +36,8 @@ int DatagramSocket::connect(const SockAddr &addr)
        peer_addr=addr.copy();
 
        delete local_addr;
-       size=sizeof(sockaddr);
-       getsockname(handle, &sa, &size);
+       size=sizeof(sockaddr_storage);
+       getsockname(handle, reinterpret_cast<sockaddr *>(&sa), &size);
        local_addr=SockAddr::create(sa);
 
        connected=true;
@@ -52,10 +52,10 @@ unsigned DatagramSocket::sendto(const char *buf, unsigned size, const SockAddr &
        if(size==0)
                return 0;
 
-       sockaddr addr;
+       sockaddr_storage addr;
        socklen_t addr_len=addr_.fill_sockaddr(addr);
 
-       int ret=::sendto(handle, buf, size, 0, &addr, addr_len);
+       int ret=::sendto(handle, buf, size, 0, reinterpret_cast<sockaddr *>(&addr), addr_len);
        if(ret<0)
        {
                if(errno==EAGAIN)
@@ -74,10 +74,10 @@ unsigned DatagramSocket::recvfrom(char *buf, unsigned size, SockAddr *&addr_)
        if(size==0)
                return 0;
 
-       sockaddr addr;
-       socklen_t addr_len=sizeof(sockaddr);
+       sockaddr_storage addr;
+       socklen_t addr_len=sizeof(sockaddr_storage);
 
-       int ret=::recvfrom(handle, buf, size, 0, &addr, &addr_len);
+       int ret=::recvfrom(handle, buf, size, 0, reinterpret_cast<sockaddr *>(&addr), &addr_len);
        if(ret<0)
        {
                if(errno==EAGAIN)
index 181c73403cfa3606731d384abb90a056953f07b4..57d8085cd299f0fb2bb72e5a932652adf69e214f 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspnet
-Copyright © 2008  Mikkosoft Productions, Mikko Rasa
+Copyright © 2008, 2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the LGPL
 */
 
@@ -18,7 +18,7 @@ InetAddr::InetAddr():
        port(0)
 { }
 
-InetAddr::InetAddr(sockaddr_in &sa):
+InetAddr::InetAddr(const sockaddr_in &sa):
        addr(sa.sin_addr.s_addr),
        port(sa.sin_port)
 { }
@@ -31,7 +31,10 @@ InetAddr::InetAddr(in_addr_t a, in_port_t p):
 string InetAddr::str() const
 {
        const unsigned char *ptr=reinterpret_cast<const unsigned char *>(&addr);
-       return format("%d.%d.%d.%d:%d", static_cast<int>(ptr[0]), static_cast<int>(ptr[1]), static_cast<int>(ptr[2]), static_cast<int>(ptr[3]), ntohs(port));
+       string result = format("%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);
+       if(port)
+               result += format(":%d", ntohs(port));
+       return result;
 }
 
 unsigned InetAddr::fill_sockaddr(sockaddr &sa) const
index 56b9f4d06a91092baf6d2b26d3d849a2e051a2a3..be67dee56bd71db14c8fef146d6b487fa77c352c 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspnet
-Copyright © 2008  Mikkosoft Productions, Mikko Rasa
+Copyright © 2008, 2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the LGPL
 */
 
@@ -13,29 +13,28 @@ Distributed under the LGPL
 #else
 #include <netinet/in.h>
 #endif
-#include <string>
 #include "sockaddr.h"
 
 namespace Msp {
 namespace Net {
 
-#ifdef WIN32
-typedef u_long in_addr_t;
-typedef u_short in_port_t;
-#endif
-
 /**
 Address class for IPv4 sockets.
 */
 class InetAddr: public SockAddr
 {
 private:
+#ifdef WIN32
+       typedef u_long in_addr_t;
+       typedef u_short in_port_t;
+#endif
+
        in_addr_t   addr;
        in_port_t   port;
 
 public:
        InetAddr();
-       InetAddr(sockaddr_in &);
+       InetAddr(const sockaddr_in &);
        InetAddr(in_addr_t, in_port_t);
 
        Family      get_family() const { return INET; }
diff --git a/source/inet6.cpp b/source/inet6.cpp
new file mode 100644 (file)
index 0000000..dbbf2db
--- /dev/null
@@ -0,0 +1,68 @@
+/* $Id$
+
+This file is part of libmspnet
+Copyright © 2011  Mikkosoft Productions, Mikko Rasa
+Distributed under the LGPL
+*/
+
+#include <msp/core/except.h>
+#include <msp/strings/formatter.h>
+#include "inet6.h"
+
+using namespace std;
+
+namespace Msp {
+namespace Net {
+
+Inet6Addr::Inet6Addr():
+       addr(in6addr_any),
+       port(0)
+{ }
+
+Inet6Addr::Inet6Addr(const sockaddr_in6 &sai6):
+       addr(sai6.sin6_addr),
+       port(sai6.sin6_port)
+{ }
+
+Inet6Addr::Inet6Addr(unsigned char a[16], in_port_t p):
+       port(p)
+{
+       std::copy(a, a+16, addr.s6_addr);
+}
+
+string Inet6Addr::str() const
+{
+       string result = "[";
+       for(unsigned i=0; i<16; i+=2)
+       {
+               unsigned short part = (addr.s6_addr[i]<<8) | addr.s6_addr[i+1];
+               if(i>0)
+                       result += ':';
+               result += format("%x", part);
+       }
+       result += ']';
+       if(port)
+               result += format(":%d", ntohs(port));
+
+       return result;
+}
+
+unsigned Inet6Addr::fill_sockaddr(sockaddr &) const
+{
+       throw Exception("Inet6Addr doesn't fit in struct sockaddr");
+}
+
+unsigned Inet6Addr::fill_sockaddr(sockaddr_storage &sa) const
+{
+       sockaddr_in6 &sai6 = reinterpret_cast<sockaddr_in6 &>(sa);
+       sai6.sin6_family = AF_INET6;
+       sai6.sin6_port = port;
+       sai6.sin6_addr = addr;
+       sai6.sin6_flowinfo = 0;
+       sai6.sin6_scope_id = 0;
+
+       return sizeof(sockaddr_in6);
+}
+
+} // namespace Net
+} // namespace Msp
diff --git a/source/inet6.h b/source/inet6.h
new file mode 100644 (file)
index 0000000..02ec450
--- /dev/null
@@ -0,0 +1,49 @@
+/* $Id$
+
+This file is part of libmspnet
+Copyright © 2011  Mikkosoft Productions, Mikko Rasa
+Distributed under the LGPL
+*/
+
+#ifndef MSP_NET_INET6_H_
+#define NSP_NET_INET6_H_
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif
+#include "sockaddr.h"
+
+namespace Msp {
+namespace Net {
+
+class Inet6Addr: public SockAddr
+{
+private:
+#ifdef WIN32
+       typedef u_short in_port_t;
+#endif
+
+       in6_addr addr;
+       in_port_t port;
+
+public:
+       Inet6Addr();
+       Inet6Addr(const sockaddr_in6 &);
+       Inet6Addr(unsigned char [16], in_port_t);
+
+       virtual Family get_family() const { return INET6; }
+       virtual std::string str() const;
+
+       virtual unsigned fill_sockaddr(sockaddr &) const;
+       virtual unsigned fill_sockaddr(sockaddr_storage &) const;
+
+       virtual Inet6Addr *copy() const { return new Inet6Addr(*this); }
+};
+
+} // namespace Net
+} // namespace Msp
+
+#endif
index 121b152b154c12d5e47867352ceae68d78e9ea63..bfe7eaaa5cada587f0eef0e8585965670df526fd 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspnet
-Copyright © 2008  Mikkosoft Productions, Mikko Rasa
+Copyright © 2008, 2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the LGPL
 */
 
@@ -23,14 +23,25 @@ namespace Net {
 SockAddr *resolve(const string &s, Family family)
 {
        string host, serv;
-       unsigned colon=s.find(':');
-       if(colon!=string::npos)
+       if(s[0]=='[')
        {
-               host=s.substr(0, colon);
-               serv=s.substr(colon+1);
+               unsigned bracket = s.find(']');
+               host = s.substr(1, bracket-1);
+               unsigned colon = s.find(':', bracket);
+               if(colon!=string::npos)
+                       serv = s.substr(colon+1);
        }
        else
-               host=s;
+       {
+               unsigned colon = s.find(':');
+               if(colon!=string::npos)
+               {
+                       host = s.substr(0, colon);
+                       serv = s.substr(colon+1);
+               }
+               else
+                       host = s;
+       }
 
        addrinfo hints={0, family, 0, 0, 0, 0, 0, 0};
        addrinfo *res;
index c3ae2db3091d06730b183a6ad51f886808b1fad9..26c77b643df8b4ae9b8180ddd1c38145f71dcc65 100644 (file)
@@ -1,22 +1,30 @@
 /* $Id$
 
 This file is part of libmspnet
-Copyright © 2008  Mikkosoft Productions, Mikko Rasa
+Copyright © 2008, 2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the LGPL
 */
 
 #include <msp/core/except.h>
 #include "inet.h"
+#include "inet6.h"
 
 namespace Msp {
 namespace Net {
 
-SockAddr *SockAddr::create(sockaddr &sa)
+unsigned SockAddr::fill_sockaddr(sockaddr_storage &sa) const
 {
-       switch(sa.sa_family)
+       return fill_sockaddr(reinterpret_cast<sockaddr &>(sa));
+}
+
+SockAddr *SockAddr::create(const sockaddr_storage &sa)
+{
+       switch(sa.ss_family)
        {
        case AF_INET:
-               return new InetAddr(reinterpret_cast<sockaddr_in &>(sa));
+               return new InetAddr(reinterpret_cast<const sockaddr_in &>(sa));
+       case AF_INET6:
+               return new Inet6Addr(reinterpret_cast<const sockaddr_in6 &>(sa));
        default:
                throw InvalidParameterValue("Unknown address family");
        }
index 63f2ab48db1462b9f201737208477d95a7a42763..0f7a7468170b816edda4f13580019fccee232e1b 100644 (file)
@@ -1,13 +1,14 @@
 /* $Id$
 
 This file is part of libmspnet
-Copyright © 2008  Mikkosoft Productions, Mikko Rasa
+Copyright © 2008, 2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the LGPL
 */
 
 #ifndef MSP_NET_SOCKADDR_H_
 #define MSP_NET_SOCKADDR_H_
 
+#include <string>
 #ifndef WIN32
 #include <sys/socket.h>
 #endif
@@ -28,12 +29,14 @@ public:
        @return  Number of bytes used
        */
        virtual unsigned fill_sockaddr(sockaddr &) const =0;
+       virtual unsigned fill_sockaddr(sockaddr_storage &) const;
 
        virtual SockAddr *copy() const =0;
 
        virtual ~SockAddr() { }
 
-       static SockAddr *create(sockaddr &);
+       static SockAddr *create(const sockaddr &sa) { return create(reinterpret_cast<const sockaddr_storage &>(sa)); }
+       static SockAddr *create(const sockaddr_storage &);
 protected:
        SockAddr() { }
 };
index 49614df0c807bdf89f3d5772b3afb996b1bf0039..150d8367948c7d0ed64a3c1547d2ae485ab089dc 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspnet
-Copyright © 2008  Mikkosoft Productions, Mikko Rasa
+Copyright © 2008, 2010-2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the LGPL
 */
 
@@ -49,9 +49,9 @@ Socket::Socket(SocketHandle h, const SockAddr &paddr):
        local_addr(0),
        peer_addr(paddr.copy())
 {
-       sockaddr sa;
-       socklen_t size=sizeof(sockaddr);
-       getsockname(handle, &sa, &size);
+       sockaddr_storage sa;
+       socklen_t size=sizeof(sockaddr_storage);
+       getsockname(handle, reinterpret_cast<sockaddr *>(&sa), &size);
        local_addr=SockAddr::create(sa);
 
 #ifdef WIN32
@@ -105,10 +105,10 @@ void Socket::bind(const SockAddr &addr)
 {
        check_state(false);
 
-       sockaddr sa;
+       sockaddr_storage sa;
        unsigned size=addr.fill_sockaddr(sa);
 
-       int err=::bind(handle, &sa, size);
+       int err=::bind(handle, reinterpret_cast<sockaddr *>(&sa), size);
        if(err==-1)
                throw SystemError("Unable to bind", errno);
 
index 2a8bc3d216e89c85a4a69e1dd17017601c7e4ee7..12e98b1f6a2d3b9d40fca5f689f74e2af07a7630 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspnet
-Copyright © 2008  Mikkosoft Productions, Mikko Rasa
+Copyright © 2008, 2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the LGPL
 */
 
@@ -45,9 +45,9 @@ StreamSocket *StreamListenSocket::accept()
        if(!listening)
                throw InvalidState("Socket is not listening");
 
-       sockaddr sa;
-       socklen_t size=sizeof(sockaddr);
-       SocketHandle new_h=::accept(handle, &sa, &size);
+       sockaddr_storage sa;
+       socklen_t size=sizeof(sockaddr_storage);
+       SocketHandle new_h=::accept(handle, reinterpret_cast<sockaddr *>(&sa), &size);
 
        RefPtr<SockAddr> paddr=SockAddr::create(sa);
        return new StreamSocket(new_h, *paddr);
index 56df99335fb6c0b19f84264e73aa10f94a0ba248..0322f12f1c286b63977435e7bb64b151daf0af68 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspnet
-Copyright © 2008-2009  Mikkosoft Productions, Mikko Rasa
+Copyright © 2008-2009, 2011  Mikkosoft Productions, Mikko Rasa
 Distributed under the LGPL
 */
 
@@ -102,11 +102,11 @@ int StreamSocket::connect(const SockAddr &addr)
        if(connected)
                throw InvalidState("Socket is already connected");
 
-       sockaddr sa;
+       sockaddr_storage sa;
        socklen_t size=addr.fill_sockaddr(sa);
 
 #ifdef WIN32
-       int err=WSAConnect(handle, &sa, size, 0, 0, 0, 0);
+       int err=WSAConnect(handle, reinterpret_cast<sockaddr *>(&sa), size, 0, 0, 0, 0);
        if(err==SOCKET_ERROR)
        {
                int err_code=WSAGetLastError();
@@ -120,7 +120,7 @@ int StreamSocket::connect(const SockAddr &addr)
                        throw Exception(format("Unable to connect: %d", err_code));
        }
 #else
-       int err=::connect(handle, &sa, size);
+       int err=::connect(handle, reinterpret_cast<sockaddr *>(&sa), size);
        if(err==-1)
        {
                if(errno==EINPROGRESS)
@@ -137,8 +137,8 @@ int StreamSocket::connect(const SockAddr &addr)
        peer_addr=addr.copy();
 
        delete local_addr;
-       size=sizeof(sockaddr);
-       getsockname(handle, &sa, &size);
+       size=sizeof(sockaddr_storage);
+       getsockname(handle, reinterpret_cast<sockaddr *>(&sa), &size);
        local_addr=SockAddr::create(sa);
 
        if(err==0)