#include <msp/io/handle_private.h>
#include <msp/strings/format.h>
#include "datagramsocket.h"
+#include "sockaddr_private.h"
#include "socket_private.h"
namespace Msp {
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<sockaddr *>(&sa), size);
+ int err = ::connect(priv->handle, reinterpret_cast<sockaddr *>(&sa.addr), sa.size);
if(err==-1)
{
#ifdef WIN32
peer_addr = addr.copy();
delete local_addr;
- size = sizeof(sockaddr_storage);
- getsockname(priv->handle, reinterpret_cast<sockaddr *>(&sa), &size);
- local_addr = SockAddr::create(sa);
+ SockAddr::SysAddr lsa;
+ getsockname(priv->handle, reinterpret_cast<sockaddr *>(&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<sockaddr *>(&addr), addr_len);
+ int ret = ::sendto(priv->handle, buf, size, 0, reinterpret_cast<sockaddr *>(&sa.addr), sa.size);
if(ret<0)
{
if(errno==EAGAIN)
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<sockaddr *>(&addr), &addr_len);
+ SockAddr::SysAddr sa;
+ int ret = ::recvfrom(priv->handle, buf, size, 0, reinterpret_cast<sockaddr *>(&sa.addr), &sa.size);
if(ret<0)
{
if(errno==EAGAIN)
}
}
- addr_ = SockAddr::create(addr);
+ from_addr = SockAddr::from_sys(sa);
return ret;
}
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#endif
#include <msp/strings/format.h>
#include "inet.h"
+#include "sockaddr_private.h"
using namespace std;
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<const unsigned char *>(&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<const sockaddr_in &>(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<sockaddr_in &>(sa);
+ SysAddr sa;
+ sa.size = sizeof(sockaddr_in);
+ sockaddr_in &sai = reinterpret_cast<sockaddr_in &>(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
#ifndef MSP_NET_INET_H_
#define MSP_NET_INET_H_
-#ifdef WIN32
-#include <winsock2.h>
-#else
-#include <netinet/in.h>
-#endif
#include "sockaddr.h"
namespace Msp {
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
+#ifdef WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netinet/in.h>
+#endif
#include <msp/strings/format.h>
#include "inet6.h"
+#include "sockaddr_private.h"
using namespace std;
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<const sockaddr_in6 &>(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<sockaddr_in6 &>(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
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<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
#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 {
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
#endif
#include <msp/core/systemerror.h>
#include <msp/strings/format.h>
+#include "sockaddr_private.h"
#include "socket.h"
#include "resolve.h"
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<const char *>(res->ai_addr);
+ char *dptr = reinterpret_cast<char *>(&sa.addr);
+ copy(sptr, sptr+res->ai_addrlen, dptr);
+ SockAddr *addr = SockAddr::from_sys(sa);
freeaddrinfo(res);
return addr;
}
#include <stdexcept>
#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<const sockaddr_in &>(sa));
+ return new InetAddr(sa);
case AF_INET6:
- return new Inet6Addr(reinterpret_cast<const sockaddr_in6 &>(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<sockaddr &>(sa));
+ addr.ss_family = AF_UNSPEC;
}
} // namespace Net
#define MSP_NET_SOCKADDR_H_
#include <string>
-#ifndef WIN32
-#include <sys/socket.h>
-#endif
#include "constants.h"
namespace Msp {
class SockAddr
{
+public:
+ struct SysAddr;
+
protected:
SockAddr() { }
public:
virtual ~SockAddr() { }
- static SockAddr *create(const sockaddr &sa) { return create(reinterpret_cast<const sockaddr_storage &>(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
--- /dev/null
+#ifndef MSP_NET_SOCKADDR_PRIVATE_H_
+#define MSP_NET_SOCKADDR_PRIVATE_H_
+
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <sys/socket.h>
+#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
#include <msp/strings/format.h>
#include <msp/time/rawtime_private.h>
#include <msp/time/units.h>
+#include "sockaddr_private.h"
#include "socket.h"
#include "socket_private.h"
{
priv->handle = p.handle;
- sockaddr_storage sa;
- socklen_t size = sizeof(sockaddr_storage);
- getsockname(priv->handle, reinterpret_cast<sockaddr *>(&sa), &size);
- local_addr = SockAddr::create(sa);
+ SockAddr::SysAddr sa;
+ getsockname(priv->handle, reinterpret_cast<sockaddr *>(&sa.addr), &sa.size);
+ local_addr = SockAddr::from_sys(sa);
#ifdef WIN32
*priv->event = CreateEvent(0, false, false, 0);
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<sockaddr *>(&sa), size);
+ int err = ::bind(priv->handle, reinterpret_cast<sockaddr *>(&sa.addr), sa.size);
if(err==-1)
throw system_error("bind");
#include <msp/core/systemerror.h>
#include <msp/io/handle_private.h>
#include <msp/strings/format.h>
+#include "sockaddr_private.h"
#include "socket_private.h"
#include "streamlistensocket.h"
#include "streamsocket.h"
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<sockaddr *>(&sa), &size);
+ new_p.handle = ::accept(priv->handle, reinterpret_cast<sockaddr *>(&sa.addr), &sa.size);
- RefPtr<SockAddr> paddr = SockAddr::create(sa);
+ RefPtr<SockAddr> paddr = SockAddr::from_sys(sa);
return new StreamSocket(new_p, *paddr);
}
#include <msp/io/handle_private.h>
#include <msp/io/poll.h>
#include <msp/strings/format.h>
+#include "sockaddr_private.h"
#include "socket_private.h"
#include "streamsocket.h"
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<sockaddr *>(&sa), size, 0, 0, 0, 0);
+ int err = WSAConnect(priv->handle, reinterpret_cast<sockaddr *>(&sa.addr), sa.size, 0, 0, 0, 0);
if(err==SOCKET_ERROR)
{
int err_code = WSAGetLastError();
throw system_error("connect", err_code);
}
#else
- int err = ::connect(priv->handle, reinterpret_cast<sockaddr *>(&sa), size);
+ int err = ::connect(priv->handle, reinterpret_cast<sockaddr *>(&sa.addr), sa.size);
if(err==-1)
{
if(errno==EINPROGRESS)
peer_addr = addr.copy();
delete local_addr;
- size = sizeof(sockaddr_storage);
- getsockname(priv->handle, reinterpret_cast<sockaddr *>(&sa), &size);
- local_addr = SockAddr::create(sa);
+ SockAddr::SysAddr lsa;
+ getsockname(priv->handle, reinterpret_cast<sockaddr *>(&lsa.addr), &lsa.size);
+ local_addr = SockAddr::from_sys(lsa);
if(err==0)
{