From: Mikko Rasa Date: Mon, 15 Oct 2012 09:07:22 +0000 (+0300) Subject: Add support for AF_UNIX X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=b5f2e718a2fd3d2e7422476e70ca7b1de5e32175;p=libs%2Fnet.git Add support for AF_UNIX --- diff --git a/source/net/sockaddr.cpp b/source/net/sockaddr.cpp index 9b41f81..e9b1433 100644 --- a/source/net/sockaddr.cpp +++ b/source/net/sockaddr.cpp @@ -2,6 +2,7 @@ #include "inet.h" #include "inet6.h" #include "sockaddr_private.h" +#include "unix.h" using namespace std; @@ -16,6 +17,8 @@ SockAddr *SockAddr::new_from_sys(const SysAddr &sa) return new InetAddr(sa); case AF_INET6: return new Inet6Addr(sa); + case AF_UNIX: + return new UnixAddr(sa); default: throw invalid_argument("SockAddr::create"); } diff --git a/source/net/unix.cpp b/source/net/unix.cpp new file mode 100644 index 0000000..373b65a --- /dev/null +++ b/source/net/unix.cpp @@ -0,0 +1,82 @@ +#include +#ifndef WIN32 +#include +#endif +#include "sockaddr_private.h" +#include "unix.h" + +using namespace std; + +namespace Msp { +namespace Net { + +UnixAddr::UnixAddr(): + abstract(false) +{ +#ifdef WIN32 + throw logic_error("no unix sockets on windows"); +#endif +} + +UnixAddr::UnixAddr(const SysAddr &sa): + abstract(false) +{ +#ifdef WIN32 + (void)sa; + throw logic_error("no unix sockets on windows"); +#else + const sockaddr_un &sau = reinterpret_cast(sa.addr); + if(sa.size>sizeof(sa_family_t)) + { + abstract = (sau.sun_path[0]==0); + path.assign(sau.sun_path+abstract, sa.size-sizeof(sa_family_t)-abstract); + } +#endif +} + +UnixAddr::UnixAddr(const string &p, bool a): + path(p), + abstract(a) +{ +#ifdef WIN32 + throw logic_error("no unix sockets on windows"); +#else + if(sizeof(sa_family_t)+path.size()+1>sizeof(sockaddr_storage)) + throw invalid_argument("UnixAddr"); +#endif +} + +SockAddr::SysAddr UnixAddr::to_sys() const +{ + SysAddr sa; +#ifndef WIN32 + sa.size = sizeof(sa_family_t); + if(!path.empty()) + sa.size += path.size()+1; + + sockaddr_un &sau = reinterpret_cast(sa.addr); + sau.sun_family = AF_UNIX; + if(!path.empty()) + { + if(abstract) + sau.sun_path[0] = 0; + std::copy(path.begin(), path.end(), sau.sun_path+abstract); + if(!abstract) + sau.sun_path[path.size()] = 0; + } +#endif + + return sa; +} + +string UnixAddr::str() const +{ + string result = "unix:"; + if(abstract) + result += '@'; + result += path; + return result; +} + +} // namespace Net +} // namespace Msp diff --git a/source/net/unix.h b/source/net/unix.h new file mode 100644 index 0000000..821e915 --- /dev/null +++ b/source/net/unix.h @@ -0,0 +1,31 @@ +#ifndef MSP_NET_UNIX_H_ +#define MSP_NET_UNIX_H_ + +#include "sockaddr.h" + +namespace Msp { +namespace Net { + +class UnixAddr: public SockAddr +{ +private: + std::string path; + bool abstract; + +public: + UnixAddr(); + UnixAddr(const SysAddr &); + UnixAddr(const std::string &, bool = false); + + virtual UnixAddr *copy() const { return new UnixAddr(*this); } + + virtual SysAddr to_sys() const; + + virtual Family get_family() const { return UNIX; } + virtual std::string str() const; +}; + +} // namespace Net +} // namespace Msp + +#endif