From dbfb303f336037cf7ca4fca3d8bfe504c624b501 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 6 Aug 2011 19:23:26 +0300 Subject: [PATCH] Hide platform specific parts of socket addresses --- source/datagramsocket.cpp | 29 ++++++++---------- source/inet.cpp | 54 +++++++++++++++++++-------------- source/inet.h | 22 +++----------- source/inet6.cpp | 57 ++++++++++++++++++----------------- source/inet6.h | 22 +++----------- source/resolve.cpp | 8 ++++- source/sockaddr.cpp | 14 +++++---- source/sockaddr.h | 17 ++++------- source/sockaddr_private.h | 29 ++++++++++++++++++ source/socket.cpp | 13 ++++---- source/streamlistensocket.cpp | 8 ++--- source/streamsocket.cpp | 14 ++++----- 12 files changed, 150 insertions(+), 137 deletions(-) create mode 100644 source/sockaddr_private.h diff --git a/source/datagramsocket.cpp b/source/datagramsocket.cpp index 7aee3f8..3f20ba5 100644 --- a/source/datagramsocket.cpp +++ b/source/datagramsocket.cpp @@ -3,6 +3,7 @@ #include #include #include "datagramsocket.h" +#include "sockaddr_private.h" #include "socket_private.h" namespace Msp { @@ -19,10 +20,9 @@ DatagramSocket::DatagramSocket(Family f, int p): int DatagramSocket::connect(const SockAddr &addr) { - sockaddr_storage sa; - socklen_t size = addr.fill_sockaddr(sa); + SockAddr::SysAddr sa = addr.to_sys(); - int err = ::connect(priv->handle, reinterpret_cast(&sa), size); + int err = ::connect(priv->handle, reinterpret_cast(&sa.addr), sa.size); if(err==-1) { #ifdef WIN32 @@ -36,24 +36,23 @@ int DatagramSocket::connect(const SockAddr &addr) peer_addr = addr.copy(); delete local_addr; - size = sizeof(sockaddr_storage); - getsockname(priv->handle, reinterpret_cast(&sa), &size); - local_addr = SockAddr::create(sa); + SockAddr::SysAddr lsa; + getsockname(priv->handle, reinterpret_cast(&lsa.addr), &lsa.size); + local_addr = SockAddr::from_sys(lsa); connected = true; return (err==0)?0:1; } -unsigned DatagramSocket::sendto(const char *buf, unsigned size, const SockAddr &addr_) +unsigned DatagramSocket::sendto(const char *buf, unsigned size, const SockAddr &addr) { if(size==0) return 0; - sockaddr_storage addr; - socklen_t addr_len = addr_.fill_sockaddr(addr); + SockAddr::SysAddr sa = addr.to_sys(); - int ret = ::sendto(priv->handle, buf, size, 0, reinterpret_cast(&addr), addr_len); + int ret = ::sendto(priv->handle, buf, size, 0, reinterpret_cast(&sa.addr), sa.size); if(ret<0) { if(errno==EAGAIN) @@ -71,15 +70,13 @@ unsigned DatagramSocket::sendto(const char *buf, unsigned size, const SockAddr & return ret; } -unsigned DatagramSocket::recvfrom(char *buf, unsigned size, SockAddr *&addr_) +unsigned DatagramSocket::recvfrom(char *buf, unsigned size, SockAddr *&from_addr) { if(size==0) return 0; - sockaddr_storage addr; - socklen_t addr_len = sizeof(sockaddr_storage); - - int ret = ::recvfrom(priv->handle, buf, size, 0, reinterpret_cast(&addr), &addr_len); + SockAddr::SysAddr sa; + int ret = ::recvfrom(priv->handle, buf, size, 0, reinterpret_cast(&sa.addr), &sa.size); if(ret<0) { if(errno==EAGAIN) @@ -94,7 +91,7 @@ unsigned DatagramSocket::recvfrom(char *buf, unsigned size, SockAddr *&addr_) } } - addr_ = SockAddr::create(addr); + from_addr = SockAddr::from_sys(sa); return ret; } diff --git a/source/inet.cpp b/source/inet.cpp index 41b5ae7..29e24aa 100644 --- a/source/inet.cpp +++ b/source/inet.cpp @@ -1,5 +1,11 @@ +#ifdef WIN32 +#include +#else +#include +#endif #include #include "inet.h" +#include "sockaddr_private.h" using namespace std; @@ -7,37 +13,39 @@ namespace Msp { namespace Net { InetAddr::InetAddr(): - addr(0), port(0) -{ } - -InetAddr::InetAddr(const sockaddr_in &sa): - addr(sa.sin_addr.s_addr), - port(sa.sin_port) -{ } - -InetAddr::InetAddr(in_addr_t a, in_port_t p): - addr(htonl(a)), - port(htons(p)) -{ } +{ + fill(addr, addr+4, 0); +} -string InetAddr::str() const +InetAddr::InetAddr(const SysAddr &sa) { - const unsigned char *ptr = reinterpret_cast(&addr); - string result = format("%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]); - if(port) - result += format(":%d", ntohs(port)); - return result; + const sockaddr_in &sai = reinterpret_cast(sa.addr); + addr[0] = sai.sin_addr.s_addr>>24; + addr[1] = sai.sin_addr.s_addr>>16; + addr[2] = sai.sin_addr.s_addr>>8; + addr[3] = sai.sin_addr.s_addr; + port = ntohs(sai.sin_port); } -unsigned InetAddr::fill_sockaddr(sockaddr &sa) const +SockAddr::SysAddr InetAddr::to_sys() const { - sockaddr_in &sai = reinterpret_cast(sa); + SysAddr sa; + sa.size = sizeof(sockaddr_in); + sockaddr_in &sai = reinterpret_cast(sa.addr); sai.sin_family = AF_INET; - sai.sin_addr.s_addr = addr; - sai.sin_port = port; + sai.sin_addr.s_addr = (addr[0]<<24) | (addr[1]<<16) | (addr[2]<<8) | (addr[3]); + sai.sin_port = htons(port); - return sizeof(sockaddr_in); + return sa; +} + +string InetAddr::str() const +{ + string result = format("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); + if(port) + result += format(":%d", port); + return result; } } // namespace Net diff --git a/source/inet.h b/source/inet.h index 75735a7..94436f9 100644 --- a/source/inet.h +++ b/source/inet.h @@ -1,11 +1,6 @@ #ifndef MSP_NET_INET_H_ #define MSP_NET_INET_H_ -#ifdef WIN32 -#include -#else -#include -#endif #include "sockaddr.h" namespace Msp { @@ -17,26 +12,19 @@ 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; + unsigned char addr[4]; + unsigned port; public: InetAddr(); - InetAddr(const sockaddr_in &); - InetAddr(in_addr_t, in_port_t); + InetAddr(const SysAddr &); virtual InetAddr *copy() const { return new InetAddr(*this); } + virtual SysAddr to_sys() const; + Family get_family() const { return INET; } - in_addr_t get_addr() const { return ntohl(addr); } - in_port_t get_port() const { return ntohs(port); } std::string str() const; - virtual unsigned fill_sockaddr(sockaddr &) const; }; } // namespace Net diff --git a/source/inet6.cpp b/source/inet6.cpp index 6903a77..79da1d2 100644 --- a/source/inet6.cpp +++ b/source/inet6.cpp @@ -1,5 +1,12 @@ +#ifdef WIN32 +#include +#include +#else +#include +#endif #include #include "inet6.h" +#include "sockaddr_private.h" using namespace std; @@ -7,19 +14,30 @@ namespace Msp { namespace Net { Inet6Addr::Inet6Addr(): - addr(in6addr_any), port(0) -{ } +{ + fill(addr, addr+16, 0); +} -Inet6Addr::Inet6Addr(const sockaddr_in6 &sai6): - addr(sai6.sin6_addr), - port(sai6.sin6_port) -{ } +Inet6Addr::Inet6Addr(const SysAddr &sa) +{ + const sockaddr_in6 &sai6 = reinterpret_cast(sa.addr); + std::copy(sai6.sin6_addr.s6_addr, sai6.sin6_addr.s6_addr+16, addr); + port = htons(sai6.sin6_port); +} -Inet6Addr::Inet6Addr(unsigned char a[16], in_port_t p): - port(p) +SockAddr::SysAddr Inet6Addr::to_sys() const { - std::copy(a, a+16, addr.s6_addr); + SysAddr sa; + sa.size = sizeof(sockaddr_in6); + sockaddr_in6 &sai6 = reinterpret_cast(sa.addr); + sai6.sin6_family = AF_INET6; + std::copy(addr, addr+16, sai6.sin6_addr.s6_addr); + sai6.sin6_port = htons(port); + sai6.sin6_flowinfo = 0; + sai6.sin6_scope_id = 0; + + return sa; } string Inet6Addr::str() const @@ -27,34 +45,17 @@ 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]; + unsigned short part = (addr[i]<<8) | addr[i+1]; if(i>0) result += ':'; result += format("%x", part); } result += ']'; if(port) - result += format(":%d", ntohs(port)); + result += format(":%d", port); return result; } -unsigned Inet6Addr::fill_sockaddr(sockaddr &) const -{ - throw logic_error("sizeof(sockaddr_in6)>sizeof(sockaddr)"); -} - -unsigned Inet6Addr::fill_sockaddr(sockaddr_storage &sa) const -{ - sockaddr_in6 &sai6 = reinterpret_cast(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 index f5a7079..97197c7 100644 --- a/source/inet6.h +++ b/source/inet6.h @@ -1,12 +1,6 @@ #ifndef MSP_NET_INET6_H_ #define NSP_NET_INET6_H_ -#ifdef WIN32 -#include -#include -#else -#include -#endif #include "sockaddr.h" namespace Msp { @@ -15,25 +9,19 @@ namespace Net { class Inet6Addr: public SockAddr { private: -#ifdef WIN32 - typedef u_short in_port_t; -#endif - - in6_addr addr; - in_port_t port; + unsigned char addr[16]; + unsigned port; public: Inet6Addr(); - Inet6Addr(const sockaddr_in6 &); - Inet6Addr(unsigned char [16], in_port_t); + Inet6Addr(const SysAddr &); virtual Inet6Addr *copy() const { return new Inet6Addr(*this); } + virtual SysAddr to_sys() const; + 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; }; } // namespace Net diff --git a/source/resolve.cpp b/source/resolve.cpp index 3896db7..076fea0 100644 --- a/source/resolve.cpp +++ b/source/resolve.cpp @@ -6,6 +6,7 @@ #endif #include #include +#include "sockaddr_private.h" #include "socket.h" #include "resolve.h" @@ -44,7 +45,12 @@ SockAddr *resolve(const string &s, Family family) int err = getaddrinfo(chost, cserv, &hints, &res); if(err==0) { - SockAddr *addr = SockAddr::create(*res->ai_addr); + SockAddr::SysAddr sa; + sa.size = res->ai_addrlen; + const char *sptr = reinterpret_cast(res->ai_addr); + char *dptr = reinterpret_cast(&sa.addr); + copy(sptr, sptr+res->ai_addrlen, dptr); + SockAddr *addr = SockAddr::from_sys(sa); freeaddrinfo(res); return addr; } diff --git a/source/sockaddr.cpp b/source/sockaddr.cpp index f6123ca..0d14dfd 100644 --- a/source/sockaddr.cpp +++ b/source/sockaddr.cpp @@ -1,28 +1,30 @@ #include #include "inet.h" #include "inet6.h" +#include "sockaddr_private.h" using namespace std; namespace Msp { namespace Net { -SockAddr *SockAddr::create(const sockaddr_storage &sa) +SockAddr *SockAddr::from_sys(const SysAddr &sa) { - switch(sa.ss_family) + switch(sa.addr.ss_family) { case AF_INET: - return new InetAddr(reinterpret_cast(sa)); + return new InetAddr(sa); case AF_INET6: - return new Inet6Addr(reinterpret_cast(sa)); + return new Inet6Addr(sa); default: throw invalid_argument("SockAddr::create"); } } -unsigned SockAddr::fill_sockaddr(sockaddr_storage &sa) const +SockAddr::SysAddr::SysAddr(): + size(sizeof(sockaddr_storage)) { - return fill_sockaddr(reinterpret_cast(sa)); + addr.ss_family = AF_UNSPEC; } } // namespace Net diff --git a/source/sockaddr.h b/source/sockaddr.h index ff2f88a..bf75477 100644 --- a/source/sockaddr.h +++ b/source/sockaddr.h @@ -2,9 +2,6 @@ #define MSP_NET_SOCKADDR_H_ #include -#ifndef WIN32 -#include -#endif #include "constants.h" namespace Msp { @@ -12,23 +9,21 @@ namespace Net { class SockAddr { +public: + struct SysAddr; + protected: SockAddr() { } public: virtual ~SockAddr() { } - static SockAddr *create(const sockaddr &sa) { return create(reinterpret_cast(sa)); } - static SockAddr *create(const sockaddr_storage &); - virtual SockAddr *copy() const = 0; + static SockAddr *from_sys(const SysAddr &); + virtual SysAddr to_sys() const = 0; + virtual Family get_family() const = 0; virtual std::string str() const = 0; - - /** Fills a struct sockaddr with information from this SockAddr. Returns - the number of bytes used. */ - virtual unsigned fill_sockaddr(sockaddr &) const = 0; - virtual unsigned fill_sockaddr(sockaddr_storage &) const; }; } // namespace Net diff --git a/source/sockaddr_private.h b/source/sockaddr_private.h new file mode 100644 index 0000000..16af063 --- /dev/null +++ b/source/sockaddr_private.h @@ -0,0 +1,29 @@ +#ifndef MSP_NET_SOCKADDR_PRIVATE_H_ +#define MSP_NET_SOCKADDR_PRIVATE_H_ + +#ifdef WIN32 +#include +#else +#include +#endif +#include "sockaddr.h" + +namespace Msp { +namespace Net { + +struct SockAddr::SysAddr +{ + struct sockaddr_storage addr; +#ifdef WIN32 + int size; +#else + socklen_t size; +#endif + + SysAddr(); +}; + +} // namespace Net +} // namespace Msp + +#endif diff --git a/source/socket.cpp b/source/socket.cpp index 8fa910c..0e29509 100644 --- a/source/socket.cpp +++ b/source/socket.cpp @@ -9,6 +9,7 @@ #include #include #include +#include "sockaddr_private.h" #include "socket.h" #include "socket_private.h" @@ -48,10 +49,9 @@ Socket::Socket(const Private &p, const SockAddr &paddr): { priv->handle = p.handle; - sockaddr_storage sa; - socklen_t size = sizeof(sockaddr_storage); - getsockname(priv->handle, reinterpret_cast(&sa), &size); - local_addr = SockAddr::create(sa); + SockAddr::SysAddr sa; + getsockname(priv->handle, reinterpret_cast(&sa.addr), &sa.size); + local_addr = SockAddr::from_sys(sa); #ifdef WIN32 *priv->event = CreateEvent(0, false, false, 0); @@ -113,10 +113,9 @@ const IO::Handle &Socket::get_event_handle() void Socket::bind(const SockAddr &addr) { - sockaddr_storage sa; - unsigned size = addr.fill_sockaddr(sa); + SockAddr::SysAddr sa = addr.to_sys(); - int err = ::bind(priv->handle, reinterpret_cast(&sa), size); + int err = ::bind(priv->handle, reinterpret_cast(&sa.addr), sa.size); if(err==-1) throw system_error("bind"); diff --git a/source/streamlistensocket.cpp b/source/streamlistensocket.cpp index 3b375bc..681aded 100644 --- a/source/streamlistensocket.cpp +++ b/source/streamlistensocket.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "sockaddr_private.h" #include "socket_private.h" #include "streamlistensocket.h" #include "streamsocket.h" @@ -44,12 +45,11 @@ StreamSocket *StreamListenSocket::accept() if(!listening) throw bad_socket_state("not listening"); - sockaddr_storage sa; - socklen_t size = sizeof(sockaddr_storage); + SockAddr::SysAddr sa; Private new_p; - new_p.handle = ::accept(priv->handle, reinterpret_cast(&sa), &size); + new_p.handle = ::accept(priv->handle, reinterpret_cast(&sa.addr), &sa.size); - RefPtr paddr = SockAddr::create(sa); + RefPtr paddr = SockAddr::from_sys(sa); return new StreamSocket(new_p, *paddr); } diff --git a/source/streamsocket.cpp b/source/streamsocket.cpp index c6cd214..5794ecd 100644 --- a/source/streamsocket.cpp +++ b/source/streamsocket.cpp @@ -6,6 +6,7 @@ #include #include #include +#include "sockaddr_private.h" #include "socket_private.h" #include "streamsocket.h" @@ -75,11 +76,10 @@ int StreamSocket::connect(const SockAddr &addr) if(connected) throw bad_socket_state("already connected"); - sockaddr_storage sa; - socklen_t size = addr.fill_sockaddr(sa); + SockAddr::SysAddr sa = addr.to_sys(); #ifdef WIN32 - int err = WSAConnect(priv->handle, reinterpret_cast(&sa), size, 0, 0, 0, 0); + int err = WSAConnect(priv->handle, reinterpret_cast(&sa.addr), sa.size, 0, 0, 0, 0); if(err==SOCKET_ERROR) { int err_code = WSAGetLastError(); @@ -93,7 +93,7 @@ int StreamSocket::connect(const SockAddr &addr) throw system_error("connect", err_code); } #else - int err = ::connect(priv->handle, reinterpret_cast(&sa), size); + int err = ::connect(priv->handle, reinterpret_cast(&sa.addr), sa.size); if(err==-1) { if(errno==EINPROGRESS) @@ -110,9 +110,9 @@ int StreamSocket::connect(const SockAddr &addr) peer_addr = addr.copy(); delete local_addr; - size = sizeof(sockaddr_storage); - getsockname(priv->handle, reinterpret_cast(&sa), &size); - local_addr = SockAddr::create(sa); + SockAddr::SysAddr lsa; + getsockname(priv->handle, reinterpret_cast(&lsa.addr), &lsa.size); + local_addr = SockAddr::from_sys(lsa); if(err==0) { -- 2.43.0