]> Dogcows Code - chaz/yoink/blobdiff - src/Moof/Socket.hh
packet copy bugfix
[chaz/yoink] / src / Moof / Socket.hh
index a0f2a7cae65bf2da03ee8b57af64f6b754e06c19..fcf1a3edbfc0464395941929c222d699d53a1e91 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _MOOF_SOCKET_HH_
 #define _MOOF_SOCKET_HH_
 
+#include <algorithm>
 #include <cstring>
 #include <sstream>
 #include <string>
@@ -54,8 +55,8 @@ public:
                mSize(0),
                mType(0)
        {
-               mAddress.sa.sa_family = AF_UNSPEC;
-               mAddress.v4.sin_port = 0;
+               mAddr.sa.sa_family = AF_UNSPEC;
+               mAddr.in.sin_port = 0;
        }
 
        SocketAddress(const std::string& service, const std::string& name,
@@ -73,7 +74,7 @@ public:
        SocketAddress(const struct addrinfo* addr, const std::string& name)
        {
                mType = addr->ai_socktype;
-               memcpy(&mAddress.sa, addr->ai_addr, addr->ai_addrlen);
+               memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
                mName = name;
                mSize = addr->ai_addrlen;
        }
@@ -82,7 +83,7 @@ public:
                        int type = SOCK_STREAM)
        {
                mType = type;
-               memcpy(&mAddress.sa, addr, size);
+               memcpy(&mAddr.sa, addr, size);
                mSize = size;
                setNameFromAddress();
        }
@@ -121,7 +122,7 @@ public:
                if (status == 0)
                {
                        mType = addr->ai_socktype;
-                       memcpy(&mAddress.sa, addr->ai_addr, addr->ai_addrlen);
+                       memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
                        mSize = addr->ai_addrlen;
 
                        if (name != "") mName = name;
@@ -134,8 +135,8 @@ public:
                        Mf::logWarning(gai_strerror(status));
                        mType = 0;
                        mSize = 0;
-                       mAddress.sa.sa_family = AF_UNSPEC;
-                       mAddress.v4.sin_port = 0;
+                       mAddr.sa.sa_family = AF_UNSPEC;
+                       mAddr.in.sin_port = 0;
                }
        }
 
@@ -158,7 +159,7 @@ public:
 
        unsigned short port() const
        {
-               return ntohs(mAddress.v4.sin_port);
+               return ntohs(mAddr.in.sin_port);
        }
 
        int type() const
@@ -168,13 +169,13 @@ public:
 
        int family() const
        {
-               return mAddress.sa.sa_family;
+               return mAddr.sa.sa_family;
        }
 
 
        const struct sockaddr* address() const
        {
-               return mSize != 0 ? &mAddress.sa : 0;
+               return mSize != 0 ? &mAddr.sa : 0;
        }
 
        size_t size() const
@@ -213,6 +214,7 @@ public:
                else
                {
                        Mf::logWarning(gai_strerror(status));
+                       return -1;
                }
 
                return 0;
@@ -225,10 +227,10 @@ private:
        {
 #if defined(_WIN32)
                // inet_ntop was introduced in Vista
-               mName = inet_ntoa(mAddress.v4.sin_addr);
+               mName = inet_ntoa(mAddr.in.sin_addr);
 #else
                char name[INET6_ADDRSTRLEN] = {'\0'};
-               inet_ntop(mAddress.sa.sa_family, &mAddress.sa, name, sizeof(name));
+               inet_ntop(mAddr.sa.sa_family, &mAddr.sa, name, sizeof(name));
                mName = name;
 #endif
        }
@@ -237,10 +239,9 @@ private:
        union
        {
                sockaddr                        sa;
-               sockaddr_in                     v4;
-               sockaddr_in6            v6;
+               sockaddr_in                     in;
                sockaddr_storage        storage;
-       }                       mAddress;
+       }                       mAddr;
        size_t          mSize;
        std::string     mName;
        int                     mType;
@@ -249,15 +250,92 @@ private:
 
 class Socket
 {
+       struct Impl
+       {
+               int                             fd;
+               bool                    isConnected;
+               SocketAddress   address;
+       };
+
+
 public:
 
+       Socket() :
+               mFd(-1),
+               mIsConnected(false) {}
+
        Socket(const SocketAddress& address) :
                mFd(-1),
-               mAddress(address)
+               mIsConnected(false),
+               mAddress(address) {}
+
+       Socket(const std::string& service, const std::string& name,
+                       int type = SOCK_STREAM, int family = AF_UNSPEC) :
+               mFd(-1),
+               mIsConnected(false),
+               mAddress(SocketAddress(service, name, type, family)) {}
+
+       Socket(const std::string& service,
+                       int type = SOCK_STREAM, int family = AF_UNSPEC) :
+               mFd(-1),
+               mIsConnected(false),
+               mAddress(SocketAddress(service, type, family)) {}
+
+
+       Socket(Socket& move) :
+               mFd(move.mFd),
+               mIsConnected(move.mIsConnected),
+               mAddress(move.mAddress)
+       {
+               move.mFd = -1;
+               move.mIsConnected = false;
+       }
+
+       Socket(Impl move) :
+               mFd(move.fd),
+               mIsConnected(move.isConnected),
+               mAddress(move.address) {}
+
+       Socket& operator=(Socket& move)
        {
-               mFd = socket(address.family(), address.type(), 0);
+#if defined(_WIN32)
+               if (mFd != -1) closesocket(mFd);
+#else
+               if (mFd != -1) close(mFd);
+#endif
+               mFd = move.mFd;
+               mIsConnected = move.mIsConnected;
+               mAddress = move.mAddress;
+               move.mFd = -1;
+               move.mIsConnected = false;
+               return *this;
        }
 
+       Socket& operator=(Impl move)
+       {
+#if defined(_WIN32)
+               if (mFd != -1) closesocket(mFd);
+#else
+               if (mFd != -1) close(mFd);
+#endif
+               mFd = move.fd;
+               mIsConnected = move.isConnected;
+               mAddress = move.address;
+               return *this;
+       }
+
+       operator Impl()
+       {
+               Impl impl;
+               impl.fd = mFd;
+               impl.isConnected = mIsConnected;
+               impl.address = mAddress;
+               mFd = -1;
+               mIsConnected = false;
+               return impl;
+       }
+
+
        ~Socket()
        {
 #if defined(_WIN32)
@@ -270,7 +348,7 @@ public:
 
        bool isConnected() const
        {
-               return mFd != -1;
+               return mIsConnected;
        }
 
        const SocketAddress& address() const
@@ -281,11 +359,15 @@ public:
 
        int connect()
        {
-               return ::connect(mFd, mAddress.address(), mAddress.size());
+               if (mFd == -1) mFd = socket(mAddress.family(), mAddress.type(), 0);
+               int result = ::connect(mFd, mAddress.address(), mAddress.size());
+               mIsConnected = result != -1;
+               return result;
        }
 
        int bind()
        {
+               if (mFd == -1) mFd = socket(mAddress.family(), mAddress.type(), 0);
                return ::bind(mFd, mAddress.address(), mAddress.size());
        }
 
@@ -294,14 +376,21 @@ public:
                return ::listen(mFd, backlog > 0 ? backlog : SOMAXCONN);
        }
 
-       Socket accept()
+       int accept(Socket& socket)
        {
-               return Socket(mFd);
+               Socket temp = Socket(mFd);
+               if (temp.mFd != -1)
+               {
+                       socket = temp;
+                       return socket.mFd;
+               }
+               return -1;
        }
 
 
        int set(int option, int value = 0)
        {
+               if (mFd == -1) mFd = socket(mAddress.family(), mAddress.type(), 0);
                if (option == SO_NONBLOCK)
                {
 #ifdef HAVE_FCNTL
@@ -316,12 +405,14 @@ public:
 
        int set(int option, const std::string& value)
        {
+               if (mFd == -1) mFd = socket(mAddress.family(), mAddress.type(), 0);
                return setsockopt(mFd, SOL_SOCKET, option,
-                               value.c_str(), value.length());
+                               value.data(), value.length());
        }
 
        int get(int option, int& value)
        {
+               if (mFd == -1) mFd = socket(mAddress.family(), mAddress.type(), 0);
                if (option == SO_NONBLOCK)
                {
 #ifdef HAVE_FCNTL
@@ -337,6 +428,7 @@ public:
 
        int get(int option, std::string& value)
        {
+               if (mFd == -1) mFd = socket(mAddress.family(), mAddress.type(), 0);
                char str[64] = {'\0'};
                socklen_t optlen = sizeof(str);
                int result = getsockopt(mFd, SOL_SOCKET, option, &str, &optlen);
@@ -344,26 +436,35 @@ public:
                return result;
        }
 
-       void write(const Packet& packet)
+
+       ssize_t write(const void* bytes, size_t size)
        {
-               write(mAddress, packet);
+               return send(mFd, bytes, size, 0);
+       }
+       ssize_t write(const void* bytes, size_t size,
+               const SocketAddress& address)
+       {
+               return sendto(mFd, bytes, size, 0,
+                       address.address(), address.size());
        }
 
-       void write(const SocketAddress& address, const Packet& packet)
+       ssize_t write(const Packet& packet)
        {
-               sendto(mFd, packet.bytes(), packet.size(), 0,
-                               address.address(), address.size());
+               return write(packet.bytes(), packet.size());
        }
 
-       Packet read()
+       ssize_t write(const Packet& packet, const SocketAddress& address)
        {
-               char buffer[1024];
-               int size = recv(mFd, buffer, sizeof(buffer), 0);
+               return write(packet.bytes(), packet.size(), address);
+       }
+
 
-               return Packet(buffer, size);
+       ssize_t read(void* bytes, size_t size)
+       {
+               return recv(mFd, bytes, size, 0);
        }
 
-       Packet read(SocketAddress& address)
+       ssize_t read(void* bytes, size_t size, SocketAddress& address)
        {
                union
                {
@@ -372,12 +473,28 @@ public:
                } addr;
                socklen_t length = sizeof(addr);
 
-               char buffer[1024];
-               int size = recvfrom(mFd, buffer, sizeof(buffer), 0,
-                               &addr.sa, &length);
+               ssize_t result = recvfrom(mFd, bytes, size, 0, &addr.sa, &length);
+               if (result != -1)
+               {
+                       address = SocketAddress(&addr.sa, length, mAddress.type());
+               }
+               return result;
+       }
 
-               address = SocketAddress(&addr.sa, length, mAddress.type());
-               return Packet(buffer, size);
+       ssize_t read(Packet& packet)
+       {
+               char buffer[65536];
+               ssize_t result = read(buffer, sizeof(buffer));
+               if (result != -1) packet = Packet(buffer, result);
+               return result;
+       }
+
+       ssize_t read(Packet& packet, SocketAddress& address)
+       {
+               char buffer[65536];
+               ssize_t result = read(buffer, sizeof(buffer), address);
+               if (result != -1) packet = Packet(buffer, result);
+               return result;
        }
 
 
@@ -394,11 +511,16 @@ private:
                socklen_t length = sizeof(addr);
 
                mFd = ::accept(fd, &addr.sa, &length);
-               mAddress = SocketAddress(&addr.sa, length);
+               if (mFd != -1)
+               {
+                       mIsConnected = true;
+                       mAddress = SocketAddress(&addr.sa, length);
+               }
        }
 
 
        int                             mFd;
+       bool                    mIsConnected;
        SocketAddress   mAddress;
 };
 
This page took 0.026079 seconds and 4 git commands to generate.