win32 port of new sockets, with fixes
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Fri, 7 May 2010 04:46:09 +0000 (22:46 -0600)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Fri, 7 May 2010 04:46:09 +0000 (22:46 -0600)
configure.ac
src/Main.cc
src/Moof/Packet.cc
src/Moof/Packet.hh
src/Moof/Socket.hh

index 45ccfc4752bee029923710bb3bbfb73270251df0..6820114ece89abb0a0564a145aa61693ac5e5a28 100644 (file)
@@ -294,6 +294,12 @@ then
                                           AC_MSG_WARN([Missing QT4 ($website)])])
 fi
 
+if test x$WIN32 = xyes
+then
+       # On Windows, sockets are in the ws2_32 library.
+       LIBS="$LIBS -lws2_32"
+fi
+
 if test x$missing = xyes
 then
        AC_MSG_ERROR([You are missing some required libraries.])
@@ -306,7 +312,7 @@ AC_MSG_NOTICE([Checks for header files.])
 
 AC_HEADER_STDBOOL
 AC_HEADER_STDC
-AC_CHECK_HEADERS([byteswap.h stddef.h stdint.h stdlib.h string.h unistd.h])
+AC_CHECK_HEADERS([arpa/inet.h byteswap.h fcntl.h stddef.h stdint.h stdlib.h string.h unistd.h])
 
 BOOST_SMART_PTR
 BOOST_STRING_ALGO
@@ -339,7 +345,7 @@ AC_MSG_NOTICE([Checks for library functions.])
 
 AC_FUNC_ERROR_AT_LINE
 AC_FUNC_STRTOD
-AC_CHECK_FUNCS([nanosleep strchr strcspn strrchr strstr])
+AC_CHECK_FUNCS([fcntl ioctl nanosleep strchr strcspn strrchr strstr])
 
 if test x$clock_gettime = xyes
 then
index 277cc3dde45eaa7642c79cc1d61b3a4aa196f252..c6df957010d16fc2cd65dfc6a43fdc1e4ca68752 100644 (file)
@@ -280,7 +280,7 @@ void goodbye()
 
 int main(int argc, char* argv[])
 {
-       Mf::ResolverTask task("compy", "4950", SOCK_DGRAM);
+       Mf::ResolverTask task("4950", "255.255.255.255", SOCK_DGRAM);
        task.run();
 
        int i = task.wait();
@@ -295,21 +295,27 @@ int main(int argc, char* argv[])
                                        << " (" << addr.type() << ")" << std::endl;
        }
 
-       Mf::SocketAddress addr("www.apple.com", "80", SOCK_DGRAM);
-       
-       Mf::logInfo << "address: " << addr.name() << ":" << addr.port() 
-                               << " (" << addr.type() << ")" << std::endl;
 
        Mf::Packet packet(1000000);
-       packet << (uint16_t)45;
+
+       packet << 5.1234f;
+       Mf::logInfo << "packet size: " << packet.size() << std::endl;
+
+       float meh3;
+       packet >> meh3;
+       Mf::logInfo << "float: " << meh3 << std::endl;
+       Mf::logInfo << "packet size: " << packet.size() << std::endl;
+
+
+       packet << uint16_t(45);
        Mf::logInfo << "packet size: " << packet.size() << std::endl;
-       packet << (int64_t)-1234567890123456789;
+       packet << uint64_t(1234567812345679ULL);
        Mf::logInfo << "packet size: " << packet.size() << std::endl;
 
        packet << true << false << false << true << false << true << true;
        Mf::logInfo << "packet size: " << packet.size() << std::endl;
 
-       std::vector<char> hi;
+       std::vector<short> hi;
        hi.push_back(34);
        hi.push_back(-12345);
        hi.push_back(7734);
@@ -329,10 +335,25 @@ int main(int argc, char* argv[])
        Mf::logInfo << "packet size: " << packet.size() << std::endl;
 
 
+       Mf::SocketAddress addr("634", "lappy");
+       Mf::logInfo << "local addr: " << addr.name() << std::endl;
+
        for (it = task.addresses().begin(); it != task.addresses().end(); ++it)
        {
+               int bcast = 0;
+
                Mf::SocketAddress addr = *it;
                Mf::Socket sock(addr);
+
+               sock.get(SO_BROADCAST, bcast);
+               Mf::logInfo << "bcast: " << bcast << std::endl;
+
+               sock.set(SO_REUSEADDR, 1);
+               sock.set(SO_BROADCAST, 1);
+
+               sock.get(SO_BROADCAST, bcast);
+               Mf::logInfo << "bcast: " << bcast << std::endl;
+
                sock.write(packet);
        }
 
index 4f3b7fd64f00def5b04ce2f9d7f74287f63e2b2c..62da00b17f98141d307573232c2d23ca07444fa8 100644 (file)
 #include <byteswap.h>
 #endif
 
+#if HAVE_ARPA_INET_H
 #include <arpa/inet.h>
+#endif
 
 #include <SDL/SDL.h>
 
 #include "Packet.hh"
 
 
+#ifndef bswap_16
+#define bswap_16(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
+#endif
+
+#ifndef bswap_32
+#define bswap_32(x) ((((x) & 0xff000000) >> 24) | \
+                                       (((x)  & 0x00ff0000) >>  8) | \
+                                       (((x)  & 0x0000ff00) <<  8) | \
+                                       (((x)  & 0x000000ff) << 24))
+#endif
+
 #ifndef bswap_64
-#define bswap_64(x)    (((uint64_t)(x) << 56) | \
-                                       (((uint64_t)(x) << 40) & 0xff000000000000ULL) | \
-                                       (((uint64_t)(x) << 24) & 0xff0000000000ULL) | \
-                                       (((uint64_t)(x) << 8)  & 0xff00000000ULL) | \
-                                       (((uint64_t)(x) >> 8)  & 0xff000000ULL) | \
-                                       (((uint64_t)(x) >> 24) & 0xff0000ULL) | \
-                                       (((uint64_t)(x) >> 40) & 0xff00ULL) | \
-                                       ((uint64_t)(x)  >> 56))
+#define bswap_64(x)    (((x) << 56) | \
+                                       (((x) << 40) & 0xff000000000000ULL) | \
+                                       (((x) << 24) & 0xff0000000000ULL) | \
+                                       (((x) << 8)  & 0xff00000000ULL) | \
+                                       (((x) >> 8)  & 0xff000000ULL) | \
+                                       (((x) >> 24) & 0xff0000ULL) | \
+                                       (((x) >> 40) & 0xff00ULL) | \
+                                       ((x)  >> 56))
 #endif
 
-static uint64_t htonll(uint64_t x)
+
+#if !HAVE_ARPA_INET_H
+static uint16_t htons(uint16_t x)
 {
 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
-       return bswap_64(x);
+       return bswap_16(x);
+#else
+       return x;
 #endif
 }
+static uint16_t ntohs(uint16_t x)
+{
+       return htons(x);
+}
 
-static uint64_t ntohll(uint64_t x)
+static uint32_t htonl(uint32_t x)
+{
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+       return bswap_32(x);
+#else
+       return x;
+#endif
+}
+static uint32_t ntohl(uint32_t x)
+{
+       return htonl(x);
+}
+#endif
+
+
+static uint64_t htonll(uint64_t x)
 {
 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
        return bswap_64(x);
+#else
+       return x;
 #endif
 }
+static uint64_t ntohll(uint64_t x)
+{
+       return htonll(x);
+}
 
 
 namespace Mf {
@@ -144,18 +186,23 @@ Packet& Packet::operator<<(uint64_t value)
        return *this;
 }
 
-//Packet& Packet::operator<<(float value)
-//{
-//}
-
-//Packet& Packet::operator<<(double value)
-//{
-//}
-
-//Packet& Packet::operator<<(long double value)
-//{
-//}
+Packet& Packet::operator<<(float value)
+{
+       // XXX: assumes the ieee-754
+       uint32_t* integer = reinterpret_cast<uint32_t*>(&value);
+       *integer = htonl(*integer);
+       write(integer, sizeof(value));
+       return *this;
+}
 
+Packet& Packet::operator<<(double value)
+{
+       // XXX: assumes the ieee-754
+       uint64_t* integer = reinterpret_cast<uint64_t*>(&value);
+       *integer = htonll(*integer);
+       write(integer, sizeof(value));
+       return *this;
+}
 
 size_t Packet::write(const void* bytes, size_t size)
 {
@@ -230,6 +277,23 @@ Packet& Packet::operator>>(uint64_t& value)
        return *this;
 }
 
+Packet& Packet::operator>>(float& value)
+{
+       // XXX: assumes the ieee-754
+       uint32_t* integer = reinterpret_cast<uint32_t*>(&value);
+       read(integer, sizeof(value));
+       *integer = htonl(*integer);
+       return *this;
+}
+
+Packet& Packet::operator>>(double& value)
+{
+       // XXX: assumes the ieee-754
+       uint64_t* integer = reinterpret_cast<uint64_t*>(&value);
+       read(integer, sizeof(value));
+       *integer = htonll(*integer);
+       return *this;
+}
 
 size_t Packet::read(void* bytes, size_t size)
 {
index 198212c352646984e3a3352a6705a73e0de9c600..208b22e9bc75fa51af739546708e7023206b6bdc 100644 (file)
@@ -38,9 +38,8 @@ public:
        Packet& operator<<(uint16_t value);
        Packet& operator<<(uint32_t value);
        Packet& operator<<(uint64_t value);
-       //Packet& operator<<(float value);
-       //Packet& operator<<(double value);
-       //Packet& operator<<(long double value);
+       Packet& operator<<(float value);
+       Packet& operator<<(double value);
 
        size_t write(const void* bytes, size_t size);
 
@@ -53,6 +52,8 @@ public:
        Packet& operator>>(uint16_t& value);
        Packet& operator>>(uint32_t& value);
        Packet& operator>>(uint64_t& value);
+       Packet& operator>>(float& value);
+       Packet& operator>>(double& value);
 
        size_t read(void* bytes, size_t size);
 
@@ -85,7 +86,7 @@ private:
 
 inline Packet& operator<<(Packet& packet, const char* value)
 {
-       uint8_t length = strnlen(value, 255);
+       uint16_t length = strlen(value);
        packet << length;
        packet.write(value, length);
        return packet;
@@ -93,7 +94,7 @@ inline Packet& operator<<(Packet& packet, const char* value)
 
 inline Packet& operator<<(Packet& packet, const std::string& value)
 {
-       packet << (uint8_t)value.length();
+       packet << (uint16_t)value.length();
        packet.write(value.c_str(), value.length());
        return packet;
 }
index 4b67887416429835f0ebff9b0cee6afae17faf96..f1604663b038c37ff408061ca50db4d914ccd38a 100644 (file)
 #include <string>
 #include <vector>
 
+#if defined(_WIN32)
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <wspiapi.h>
+#else
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#endif
 
 #include <Moof/Log.hh>
 #include <Moof/Packet.hh>
 #include <Moof/Thread.hh>
 
 
+#ifndef SO_NONBLOCK
+#define SO_NONBLOCK 1024
+#endif
+
+
 namespace Mf {
 
 
@@ -34,47 +50,27 @@ class SocketAddress
 {
 public:
 
-       SocketAddress(int type = SOCK_STREAM)
+       SocketAddress() :
+               mSize(0),
+               mType(0)
        {
-               mType = type;
-               memset(&mAddress.in4, 0, sizeof(mAddress.in4));
-               mAddress.in4.sin_family = AF_INET;
-               mAddress.in4.sin_port = 0;
-               mAddress.in4.sin_addr.s_addr = INADDR_ANY;
-               mName = "[any]";
-               mSize = sizeof(mAddress.in4);
+               mAddress.sa.sa_family = AF_UNSPEC;
+               mAddress.v4.sin_port = 0;
        }
 
-       SocketAddress(const std::string& name, const std::string& service,
-                       int type = SOCK_STREAM, int family = AF_INET)
+       SocketAddress(const std::string& service, const std::string& name,
+                       int type = SOCK_STREAM, int family = AF_UNSPEC)
        {
-               ASSERT(type == SOCK_STREAM || type == SOCK_DGRAM);
-               ASSERT(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
-
-               struct addrinfo hints;
-               memset(&hints, 0, sizeof(hints));
-               hints.ai_family = family;
-               hints.ai_socktype = type;
-               hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
-
-               struct addrinfo* addr;
-               int status = getaddrinfo(name.length() > 0 ? name.c_str() : 0,
-                               service.length() > 0 ? service.c_str() : 0, &hints, &addr);
-               if (status != 0)
-               {
-                       Mf::logError("uh oh, that didn't work!");
-                       return;
-               }
-
-               mType = addr->ai_socktype;
-               memcpy(&mAddress.sa, addr->ai_addr, addr->ai_addrlen);
-               mName = addr->ai_canonname;
-               mSize = addr->ai_addrlen;
+               init(service, name, type, family);
+       }
 
-               freeaddrinfo(addr);
+       SocketAddress(const std::string& service,
+                       int type = SOCK_STREAM, int family = AF_UNSPEC)
+       {
+               init(service, type, family);
        }
 
-       SocketAddress(const std::string& name, const struct addrinfo* addr)
+       SocketAddress(const struct addrinfo* addr, const std::string& name)
        {
                mType = addr->ai_socktype;
                memcpy(&mAddress.sa, addr->ai_addr, addr->ai_addrlen);
@@ -88,11 +84,56 @@ public:
                mType = type;
                memcpy(&mAddress.sa, addr, size);
                mSize = size;
+               setNameFromAddress();
+       }
 
-               char name[128] = {'\0'};
-               inet_ntop(addr->sa_family, (struct sockaddr_in*)addr,
-                               name, sizeof(name));
-               mName = name;
+
+       static SocketAddress broadcast(const std::string& service)
+       {
+               return SocketAddress(service, "255.255.255.255", SOCK_DGRAM);
+       }
+
+
+       void init(const std::string& service, const std::string& name = "",
+                       int type = SOCK_STREAM, int family = AF_UNSPEC)
+       {
+               ASSERT(type == SOCK_STREAM || type == SOCK_DGRAM);
+               ASSERT(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
+
+               struct addrinfo hints;
+               memset(&hints, 0, sizeof(hints));
+               hints.ai_family = family;
+               hints.ai_socktype = type;
+               hints.ai_flags = AI_PASSIVE;
+
+               struct addrinfo* addr;
+               int status = getaddrinfo(name.length() > 0 ? name.c_str() : 0,
+                               service.c_str(), &hints, &addr);
+               if (status == 0)
+               {
+                       mType = addr->ai_socktype;
+                       memcpy(&mAddress.sa, addr->ai_addr, addr->ai_addrlen);
+                       mSize = addr->ai_addrlen;
+
+                       if (name != "") mName = name;
+                       else            setNameFromAddress();
+
+                       freeaddrinfo(addr);
+               }
+               else
+               {
+                       Mf::logWarning(gai_strerror(status));
+                       mType = 0;
+                       mSize = 0;
+                       mAddress.sa.sa_family = AF_UNSPEC;
+                       mAddress.v4.sin_port = 0;
+               }
+       }
+
+       void init(const std::string& service,
+                       int type = SOCK_STREAM, int family = AF_UNSPEC)
+       {
+               init(service, "", type, family);
        }
 
 
@@ -101,9 +142,14 @@ public:
                return mName;
        }
 
+       void setName(const std::string& name)
+       {
+               mName = name;
+       }
+
        unsigned short port() const
        {
-               return ntohs(mAddress.in4.sin_port);
+               return ntohs(mAddress.v4.sin_port);
        }
 
        int type() const
@@ -119,7 +165,7 @@ public:
 
        const struct sockaddr* address() const
        {
-               return &mAddress.sa;
+               return mSize != 0 ? &mAddress.sa : 0;
        }
 
        size_t size() const
@@ -128,45 +174,64 @@ public:
        }
 
 
-       static int resolve(const std::string& name, const std::string& service,
+       static int resolve(const std::string& service, const std::string& name,
                        int type, int family, std::vector<SocketAddress>& resolved)
        {
                ASSERT(type == SOCK_STREAM || type == SOCK_DGRAM);
                ASSERT(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
 
+               resolved.clear();
+
                struct addrinfo hints;
                memset(&hints, 0, sizeof(hints));
                hints.ai_family = family;
                hints.ai_socktype = type;
-               hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
+               hints.ai_flags = AI_PASSIVE;
 
                struct addrinfo* list;
                int status = getaddrinfo(name.length() > 0 ? name.c_str() : 0,
                                service.length() > 0 ? service.c_str() : 0, &hints, &list);
-               if (status != 0) return -1;
-
-               resolved.clear();
-
-               const char* canonicalName = list->ai_canonname;
-               struct addrinfo* addr = list;
-               while (addr != 0)
+               if (status == 0)
+               {
+                       struct addrinfo* addr = list;
+                       while (addr != 0)
+                       {
+                               resolved.push_back(SocketAddress(addr, name));
+                               addr = addr->ai_next;
+                       }
+
+                       freeaddrinfo(list);
+               }
+               else
                {
-                       resolved.push_back(SocketAddress(canonicalName, addr));
-                       addr = addr->ai_next;
+                       Mf::logWarning(gai_strerror(status));
                }
 
-               freeaddrinfo(list);
                return 0;
        }
 
 
 private:
 
+       void setNameFromAddress()
+       {
+#if defined(_WIN32)
+               // inet_ntop was introduced in Vista
+               mName = inet_ntoa(mAddress.v4.sin_addr);
+#else
+               char name[INET6_ADDRSTRLEN] = {'\0'};
+               inet_ntop(mAddress.sa.sa_family, &mAddress.sa, name, sizeof(name));
+               mName = name;
+#endif
+       }
+
+
        union
        {
-               sockaddr                sa;
-               sockaddr_in             in4;
-               sockaddr_in6    in6;
+               sockaddr                        sa;
+               sockaddr_in                     v4;
+               sockaddr_in6            v6;
+               sockaddr_storage        storage;
        }                       mAddress;
        size_t          mSize;
        std::string     mName;
@@ -179,6 +244,7 @@ class Socket
 public:
 
        Socket(const SocketAddress& address) :
+               mFd(-1),
                mAddress(address)
        {
                mFd = socket(address.family(), address.type(), 0);
@@ -186,13 +252,17 @@ public:
 
        ~Socket()
        {
-               close(mFd);
+#if defined(_WIN32)
+               if (mFd != -1) closesocket(mFd);
+#else
+               if (mFd != -1) close(mFd);
+#endif
        }
 
 
        bool isConnected() const
        {
-               return false;
+               return mFd != -1;
        }
 
        const SocketAddress& address() const
@@ -201,6 +271,71 @@ public:
        }
 
 
+       int connect()
+       {
+               return ::connect(mFd, mAddress.address(), mAddress.size());
+       }
+
+       int bind()
+       {
+               return ::bind(mFd, mAddress.address(), mAddress.size());
+       }
+
+       int listen(int backlog = SOMAXCONN)
+       {
+               return ::listen(mFd, backlog > 0 ? backlog : SOMAXCONN);
+       }
+
+       Socket accept()
+       {
+               return Socket(mFd);
+       }
+
+
+       int set(int option, int value = 0)
+       {
+               if (option == SO_NONBLOCK)
+               {
+#ifdef HAVE_FCNTL
+                       int flags = fcntl(mFd, F_GETFL);
+                       return fcntl(mFd, F_SETFL, (value ? O_NONBLOCK : 0) | flags);
+#else
+                       return ioctl(mFd, FIONBIO, value);
+#endif
+               }
+               return setsockopt(mFd, SOL_SOCKET, option, &value, sizeof(value));
+       }
+
+       int set(int option, const std::string& value)
+       {
+               return setsockopt(mFd, SOL_SOCKET, option,
+                               value.c_str(), value.length());
+       }
+
+       int get(int option, int& value)
+       {
+               if (option == SO_NONBLOCK)
+               {
+#ifdef HAVE_FCNTL
+                       int flags = fcntl(mFd, F_GETFL);
+                       return flags & O_NONBLOCK;
+#else
+                       return ioctl(mFd, FIONBIO, &value);
+#endif
+               }
+               socklen_t optlen = sizeof(value);
+               return getsockopt(mFd, SOL_SOCKET, option, &value, &optlen);
+       }
+
+       int get(int option, std::string& value)
+       {
+               char str[64] = {'\0'};
+               socklen_t optlen = sizeof(str);
+               int result = getsockopt(mFd, SOL_SOCKET, option, &str, &optlen);
+               value = str;
+               return result;
+       }
+
        void write(const Packet& packet)
        {
                write(mAddress, packet);
@@ -233,13 +368,28 @@ public:
                int size = recvfrom(mFd, buffer, sizeof(buffer), 0,
                                &addr.sa, &length);
 
-               address = SocketAddress(&addr.sa, length, SOCK_DGRAM);
+               address = SocketAddress(&addr.sa, length, mAddress.type());
                return Packet(buffer, size);
        }
 
 
 private:
 
+       Socket(int fd)
+       {
+               // for accepting a socket from fd
+               union
+               {
+                       sockaddr                        sa;
+                       sockaddr_storage        storage;
+               } addr;
+               socklen_t length = sizeof(addr);
+
+               mFd = ::accept(fd, &addr.sa, &length);
+               mAddress = SocketAddress(&addr.sa, length);
+       }
+
+
        int                             mFd;
        SocketAddress   mAddress;
 };
@@ -249,12 +399,12 @@ class ResolverTask : public ThreadedTask
 {
 public:
 
-       ResolverTask(const std::string& name, const std::string& service,
+       ResolverTask(const std::string& service, const std::string& name,
                        int type = SOCK_STREAM, int family = AF_UNSPEC) :
                mIsDone(false)
        {
                mFunction = boost::bind(&ResolverTask::resolve,
-                               this, name, service, type, family);
+                               this, service, name, type, family);
        }
 
 
@@ -277,10 +427,10 @@ public:
 
 private:
 
-       int resolve(const std::string& name, const std::string& service,
+       int resolve(const std::string& service, const std::string& name,
                        int type, int family)
        {
-               int status = SocketAddress::resolve(name, service,
+               int status = SocketAddress::resolve(service, name,
                                type, family, mAddressList);
                mIsDone = true;
                return status;
This page took 0.039297 seconds and 4 git commands to generate.