]> git.tdb.fi Git - libs/net.git/commitdiff
Add support for AF_UNIX
authorMikko Rasa <tdb@tdb.fi>
Mon, 15 Oct 2012 09:07:22 +0000 (12:07 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 15 Oct 2012 09:07:22 +0000 (12:07 +0300)
source/net/sockaddr.cpp
source/net/unix.cpp [new file with mode: 0644]
source/net/unix.h [new file with mode: 0644]

index 9b41f81b948492dc077920dbe83ea06a80ea8a67..e9b14333b51586c69727b038a384bb4bec5e1fd3 100644 (file)
@@ -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 (file)
index 0000000..373b65a
--- /dev/null
@@ -0,0 +1,82 @@
+#include <stdexcept>
+#ifndef WIN32
+#include <sys/un.h>
+#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<const sockaddr_un &>(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<sockaddr_un &>(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 (file)
index 0000000..821e915
--- /dev/null
@@ -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