]> Dogcows Code - chaz/yoink/blobdiff - src/Moof/Socket.hh
initial network stuff
[chaz/yoink] / src / Moof / Socket.hh
diff --git a/src/Moof/Socket.hh b/src/Moof/Socket.hh
new file mode 100644 (file)
index 0000000..4b67887
--- /dev/null
@@ -0,0 +1,299 @@
+
+/*]  Copyright (c) 2009-2010, Charles McGarvey  [**************************
+**]  All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_SOCKET_HH_
+#define _MOOF_SOCKET_HH_
+
+#include <cstring>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <Moof/Log.hh>
+#include <Moof/Packet.hh>
+#include <Moof/Thread.hh>
+
+
+namespace Mf {
+
+
+class SocketAddress
+{
+public:
+
+       SocketAddress(int type = SOCK_STREAM)
+       {
+               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);
+       }
+
+       SocketAddress(const std::string& name, const std::string& service,
+                       int type = SOCK_STREAM, int family = AF_INET)
+       {
+               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;
+
+               freeaddrinfo(addr);
+       }
+
+       SocketAddress(const std::string& name, const struct addrinfo* addr)
+       {
+               mType = addr->ai_socktype;
+               memcpy(&mAddress.sa, addr->ai_addr, addr->ai_addrlen);
+               mName = name;
+               mSize = addr->ai_addrlen;
+       }
+
+       SocketAddress(const struct sockaddr* addr, size_t size,
+                       int type = SOCK_STREAM)
+       {
+               mType = type;
+               memcpy(&mAddress.sa, addr, size);
+               mSize = size;
+
+               char name[128] = {'\0'};
+               inet_ntop(addr->sa_family, (struct sockaddr_in*)addr,
+                               name, sizeof(name));
+               mName = name;
+       }
+
+
+       const std::string& name() const
+       {
+               return mName;
+       }
+
+       unsigned short port() const
+       {
+               return ntohs(mAddress.in4.sin_port);
+       }
+
+       int type() const
+       {
+               return mType;
+       }
+
+       int family() const
+       {
+               return mAddress.sa.sa_family;
+       }
+
+
+       const struct sockaddr* address() const
+       {
+               return &mAddress.sa;
+       }
+
+       size_t size() const
+       {
+               return mSize;
+       }
+
+
+       static int resolve(const std::string& name, const std::string& service,
+                       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);
+
+               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* 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)
+               {
+                       resolved.push_back(SocketAddress(canonicalName, addr));
+                       addr = addr->ai_next;
+               }
+
+               freeaddrinfo(list);
+               return 0;
+       }
+
+
+private:
+
+       union
+       {
+               sockaddr                sa;
+               sockaddr_in             in4;
+               sockaddr_in6    in6;
+       }                       mAddress;
+       size_t          mSize;
+       std::string     mName;
+       int                     mType;
+};
+
+
+class Socket
+{
+public:
+
+       Socket(const SocketAddress& address) :
+               mAddress(address)
+       {
+               mFd = socket(address.family(), address.type(), 0);
+       }
+
+       ~Socket()
+       {
+               close(mFd);
+       }
+
+
+       bool isConnected() const
+       {
+               return false;
+       }
+
+       const SocketAddress& address() const
+       {
+               return mAddress;
+       }
+
+
+       void write(const Packet& packet)
+       {
+               write(mAddress, packet);
+       }
+
+       void write(const SocketAddress& address, const Packet& packet)
+       {
+               sendto(mFd, packet.bytes(), packet.size(), 0,
+                               address.address(), address.size());
+       }
+
+       Packet read()
+       {
+               char buffer[1024];
+               int size = recv(mFd, buffer, sizeof(buffer), 0);
+
+               return Packet(buffer, size);
+       }
+
+       Packet read(SocketAddress& address)
+       {
+               union
+               {
+                       sockaddr                        sa;
+                       sockaddr_storage        storage;
+               } addr;
+               socklen_t length = sizeof(addr);
+
+               char buffer[1024];
+               int size = recvfrom(mFd, buffer, sizeof(buffer), 0,
+                               &addr.sa, &length);
+
+               address = SocketAddress(&addr.sa, length, SOCK_DGRAM);
+               return Packet(buffer, size);
+       }
+
+
+private:
+
+       int                             mFd;
+       SocketAddress   mAddress;
+};
+
+
+class ResolverTask : public ThreadedTask
+{
+public:
+
+       ResolverTask(const std::string& name, const std::string& service,
+                       int type = SOCK_STREAM, int family = AF_UNSPEC) :
+               mIsDone(false)
+       {
+               mFunction = boost::bind(&ResolverTask::resolve,
+                               this, name, service, type, family);
+       }
+
+
+       bool isDone() const
+       {
+               return mIsDone;
+       }
+
+       void run()
+       {
+               if (!mThread) mThread = Mf::detachFunction(mFunction);
+       }
+
+
+       const std::vector<SocketAddress>& addresses() const
+       {
+               return mAddressList;
+       }
+
+
+private:
+
+       int resolve(const std::string& name, const std::string& service,
+                       int type, int family)
+       {
+               int status = SocketAddress::resolve(name, service,
+                               type, family, mAddressList);
+               mIsDone = true;
+               return status;
+       }
+
+
+       std::vector<SocketAddress>      mAddressList;
+       bool                                            mIsDone;
+       Function                                        mFunction;
+};
+
+
+} // namespace Mf
+
+#endif // _MOOF_SOCKET_HH_
+
This page took 0.024026 seconds and 4 git commands to generate.