]> Dogcows Code - chaz/yoink/blobdiff - src/Moof/Socket.hh
the massive refactoring effort
[chaz/yoink] / src / Moof / Socket.hh
diff --git a/src/Moof/Socket.hh b/src/Moof/Socket.hh
deleted file mode 100644 (file)
index 60fd8e0..0000000
+++ /dev/null
@@ -1,1132 +0,0 @@
-
-/*]  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.
-*
-**************************************************************************/
-
-/**
- * \file Socket.hh
- * Network-related classes, including a reinterpreted sockets API.
- */
-
-#ifndef _MOOF_SOCKET_HH_
-#define _MOOF_SOCKET_HH_
-
-#include <algorithm>
-#include <cstring>
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#if HAVE_FCNTL_H
-#include <fcntl.h>
-#else
-#error No alternative to fcntl implemented yet.
-#endif
-
-#if defined(_WIN32)
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <wspiapi.h>
-#define SHUT_RD   SD_RECEIVE
-#define SHUT_WR   SD_SEND
-#define SHUT_RDWR SD_BOTH
-#else
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#endif
-
-#include <Moof/Log.hh>
-#include <Moof/Packet.hh>
-#include <Moof/Thread.hh>
-
-
-#ifndef AI_ADDRCONFIG
-#define AI_ADDRCONFIG 0
-#endif
-
-#ifndef AI_V4MAPPED
-#define AI_V4MAPPED 0
-#endif
-
-
-namespace Mf {
-
-
-/**
- * A class to represent the address of a remote host, including the type of
- * service and socket communication.
- */
-class SocketAddress
-{
-public:
-
-       /**
-        * Construct an unspecified address.
-        */
-       SocketAddress() :
-               mSize(0),
-               mType(0)
-       {
-               mAddr.sa.sa_family = AF_UNSPEC;
-               mAddr.in.sin_port = 0;
-       }
-
-       /**
-        * Construct an address with a specified host.  The address can be used
-        * to connect to a host.
-        * \param service The service name or port number.
-        * \param name The numeric IP address of the host.
-        * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
-        * \param family The family; can be AF_INET or AF_INET6.
-        */
-       SocketAddress(const std::string& service,
-                                 const std::string& name,
-                                 int type = SOCK_STREAM,
-                                 int family = AF_UNSPEC)
-       {
-               init(service, name, type, family);
-       }
-
-       /**
-        * Construct an address without a specified host.  The address can be
-        * used to accept on a local port.
-        * \param service The service name or port number.
-        * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
-        * \param family The family; can be AF_INET or AF_INET6.
-        */
-       explicit SocketAddress(const std::string& service,
-                                                  int type = SOCK_STREAM,
-                                                  int family = AF_UNSPEC)
-       {
-               init(service, type, family);
-       }
-
-       /**
-        * Construct an address from the information in an addrinfo structure.
-        * \param addr The addrinfo structure.
-        */
-       SocketAddress(const struct addrinfo* addr) :
-               mSize(addr->ai_addrlen),
-               mType(addr->ai_socktype)
-       {
-               memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
-               getNameAndService(mName, mService);
-       }
-
-       /**
-        * Construct an address from a sockaddr structure.
-        * \param addr The sockaddr structure.
-        * \param size The size of the sockaddr structure.
-        * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
-        */
-       SocketAddress(const struct sockaddr* addr,
-                                 size_t size,
-                                 int type = SOCK_STREAM) :
-               mSize(size),
-               mType(type)
-       {
-               memcpy(&mAddr.sa, addr, size);
-               getNameAndService(mName, mService);
-       }
-
-
-       /**
-        * Get an IPv4 broadcast address.
-        * \param service The service name or port number.
-        * \return The socket address.
-        */
-       static SocketAddress broadcast(const std::string& service)
-       {
-               std::istringstream stream(service);
-               unsigned short port;
-               stream >> port;
-
-               struct sockaddr_in addr;
-               addr.sin_family = AF_INET;
-               addr.sin_port = htons(port);
-               addr.sin_addr.s_addr = INADDR_BROADCAST;
-               memset(&addr.sin_zero, 0, sizeof(addr.sin_zero));
-               return SocketAddress((sockaddr*)&addr, sizeof(addr), SOCK_DGRAM);
-       }
-
-
-       /**
-        * Initialize the address with a specified host.  The address can be
-        * used to connect to a host.
-        * \param service The service name or port number.
-        * \param name The numeric IP address of the host.
-        * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
-        * \param family The family; can be AF_INET or AF_INET6.
-        */
-       void init(const std::string& service,
-                         const std::string& name,
-                         int type = SOCK_STREAM,
-                         int family = AF_UNSPEC)
-       {
-               struct addrinfo* addr = resolve(service.c_str(), name.c_str(),
-                                                                               type, family,
-                                                                               AI_ADDRCONFIG | AI_NUMERICHOST | AI_V4MAPPED);
-               if (addr)
-               {
-                       mSize = addr->ai_addrlen;
-                       mType = addr->ai_socktype;
-                       memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
-
-                       mService = service;
-                       mName = name;
-
-                       freeaddrinfo(addr);
-               }
-               else
-               {
-                       mType = 0;
-                       mSize = 0;
-                       mAddr.sa.sa_family = AF_UNSPEC;
-                       mAddr.in.sin_port = 0;
-               }
-       }
-
-       /**
-        * Initialize the address without a specified host.  The address can be
-        * used to accept on a local port.
-        * \param service The service name or port number.
-        * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
-        * \param family The family; can be AF_INET or AF_INET6.
-        */
-       void init(const std::string& service,
-                         int type = SOCK_STREAM,
-                         int family = AF_UNSPEC)
-       {
-               struct addrinfo* addr = resolve(service.c_str(), 0,
-                                                                               type, family,
-                                                                               AI_PASSIVE);
-               if (addr)
-               {
-                       mSize = addr->ai_addrlen;
-                       mType = addr->ai_socktype;
-                       memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
-
-                       mService = service;
-                       getName(mName);
-
-                       freeaddrinfo(addr);
-               }
-               else
-               {
-                       mType = 0;
-                       mSize = 0;
-                       mAddr.sa.sa_family = AF_UNSPEC;
-                       mAddr.in.sin_port = 0;
-               }
-       }
-
-
-       /**
-        * Get the name of the service.  This could also be a port number if
-        * there is no service name associated with the number.
-        * \return The service.
-        */
-       const std::string& service() const
-       {
-               return mService;
-       }
-
-       /**
-        * Get the name of the host.  This may be the host used to construct
-        * the address, or a resolved numeric host if none was used.
-        * \return The host.
-        */
-       const std::string& name() const
-       {
-               return mName;
-       }
-
-       /**
-        * Get the port number of the address service.
-        * \return Port number.
-        */
-       unsigned short port() const
-       {
-               return ntohs(mAddr.in.sin_port);
-       }
-
-       /**
-        * Get the type of socket associated with the service of this address.
-        * \return Socket type; either SOCK_STREAM or SOCK_DGRAM.
-        */
-       int type() const
-       {
-               return mType;
-       }
-
-       /**
-        * Get the family of the protocol associated with the address.
-        * \return Protocol family; either AF_INET, AF_INET6, or AF_UNSPEC.
-        */
-       int family() const
-       {
-               return mAddr.sa.sa_family;
-       }
-
-
-       /**
-        * Get the sockaddr structure of the address.
-        * \return The sockaddr structure.
-        */
-       const struct sockaddr* address() const
-       {
-               return mSize != 0 ? &mAddr.sa : 0;
-       }
-
-       /**
-        * Get the size of the sockaddr structure of the address.
-        * \return The size of the sockaddr structure.
-        */
-       size_t size() const
-       {
-               return mSize;
-       }
-
-
-       /**
-        * Get a list of addresses resolved to by the given search criteria.
-        * This can be used to perform lookups for name resolution, so this
-        * method may take some time to return.  Use the ResolveTask class to
-        * resolve addresses asynchronously.
-        * \param service The service name or port number.
-        * \param name The name of the local or remote host.
-        * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
-        * \param family The family; can be AF_INET or AF_INET6.
-        * \param resolved The list to be filled with addresses.
-        * \return 0 on success, -1 on error.
-        */
-       static int resolve(const std::string& service,
-                                          const std::string& name,
-                                          int type,
-                                          int family,
-                                          std::vector<SocketAddress>& resolved)
-       {
-               struct addrinfo* list = resolve(service.c_str(), name.c_str(),
-                                                                               type, family,
-                                                                               AI_ADDRCONFIG | AI_V4MAPPED);
-               int result = collectAddresses(list, resolved);
-               freeaddrinfo(list);
-               return result;
-       }
-
-       /**
-        * Get a list of addresses resolved to by the given search criteria.
-        * The addresses will be suitable for accepting on a local port.
-        * \param service The service name or port number.
-        * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
-        * \param family The family; can be AF_INET or AF_INET6.
-        * \param resolved The list to be filled with addresses.
-        * \return 0 on success, -1 on error.
-        */
-       static int resolve(const std::string& service,
-                                          int type,
-                                          int family,
-                                          std::vector<SocketAddress>& resolved)
-       {
-               struct addrinfo* list = resolve(service.c_str(), 0,
-                                                                               type, family,
-                                                                               AI_PASSIVE);
-               int result = collectAddresses(list, resolved);
-               freeaddrinfo(list);
-               return result;
-       }
-
-
-       /**
-        * Resolve the hostname of the address.  The default behavior is to
-        * avoid a reverse lookup by giving the numeric address.  You can
-        * change that behavior with the getnameinfo flags.
-        * \param name The place to store the hostname or IP address.
-        * \param flags The getnameinfo flags.
-        */
-       void getName(std::string& name, int flags = NI_NUMERICHOST)
-       {
-               char node[256] = {'\0'};
-               int result = getnameinfo(&mAddr.sa, mSize,
-                                                                node, sizeof(node),
-                                                                0, 0,
-                                                                flags);
-               if (result == 0) name.assign(node);
-       }
-
-       /**
-        * Resolve the service name of the address.
-        * \param service The place to store the service name or port number.
-        * \param flags The getnameinfo flags.
-        */
-       void getService(std::string& service, int flags)
-       {
-               flags |= mType == SOCK_DGRAM ? NI_DGRAM : 0;
-
-               char serv[64] = {'\0'};
-               int result = getnameinfo(&mAddr.sa, mSize,
-                                                                0, 0,
-                                                                serv, sizeof(serv),
-                                                                flags);
-               if (result == 0) service.assign(serv);
-       }
-
-       /**
-        * Resolve the service and hostname of the address.  The default
-        * behavior is to avoid a reverse lookup by giving the numeric address.
-        * You can change that behavior with the getnameinfo flags.
-        * \param name The place to store the hostname or IP address.
-        * \param service The place to store the service name or port number.
-        * \param flags The getnameinfo flags.
-        */
-       void getNameAndService(std::string& name,
-                                                  std::string& service,
-                                                  int flags = NI_NUMERICHOST)
-       {
-               flags |= mType == SOCK_DGRAM ? NI_DGRAM : 0;
-
-               char serv[64] = {'\0'};
-               char node[256] = {'\0'};
-               int result = getnameinfo(&mAddr.sa, mSize,
-                                                                node, sizeof(node),
-                                                                serv, sizeof(serv),
-                                                                flags);
-               if (result == 0)
-               {
-                       service.assign(serv);
-                       name.assign(node);
-               }
-       }
-
-
-private:
-
-       static struct addrinfo* resolve(const char* service,
-                                                                       const char* node,
-                                                                       int type,
-                                                                       int family,
-                                                                       int flags)
-       {
-               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 = flags;
-
-               struct addrinfo* addr;
-               int status = getaddrinfo(node, service, &hints, &addr);
-
-               if (status == 0)
-               {
-                       return addr;
-               }
-               else
-               {
-                       Mf::logWarning(gai_strerror(status));
-                       return 0;
-               }
-       }
-
-       static int collectAddresses(struct addrinfo* addresses,
-                                                               std::vector<SocketAddress>& resolved)
-       {
-               if (addresses)
-               {
-                       resolved.clear();
-
-                       for (struct addrinfo* addr = addresses;
-                                addr != 0;
-                                addr = addr->ai_next)
-                       {
-                               resolved.push_back(SocketAddress(addr));
-                       }
-
-                       return 0;
-               }
-               else return -1;
-       }
-
-
-       union
-       {
-               sockaddr                        sa;
-               sockaddr_in                     in;
-               sockaddr_storage        storage;
-       }                       mAddr;
-       size_t          mSize;
-       int                     mType;
-
-       std::string     mName;
-       std::string mService;
-};
-
-
-/**
- * The socket class represents a connection or between this node and a
- * remote node.
- */
-class Socket
-{
-       struct Impl
-       {
-               SocketAddress   address;
-               int                             fd;
-               bool                    isConnected;
-
-               Impl() :
-                       fd(-1),
-                       isConnected(false) {}
-
-               Impl(const SocketAddress& address, int flags = 0) :
-                       address(address),
-                       fd(::socket(address.family(), address.type(), flags)),
-                       isConnected(false) {}
-       } mImpl;
-
-
-public:
-
-       /**
-        * Construct a socket with no associated peer.
-        */
-       Socket() {}
-
-       /**
-        * Construct a socket with an address.
-        * \param address The address.
-        * \param flags The socket options.
-        */
-       Socket(const SocketAddress& address, int flags = 0) :
-               mImpl(address, flags) {}
-
-       /**
-        * Construct a socket with a specified host.  The socket can be used to
-        * connect to a host.
-        * \param service The service name or port number.
-        * \param name The numeric IP address of the host.
-        * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
-        * \param family The family; can be AF_INET or AF_INET6.
-        * \param flags The socket options.
-        */
-       Socket(const std::string& service,
-                  const std::string& name,
-                  int type = SOCK_STREAM,
-                  int family = AF_UNSPEC,
-                  int flags = 0) :
-               mImpl(SocketAddress(service, name, type, family), flags) {}
-
-       /**
-        * Construct a socket without a specified host.  The socket can be used
-        * to accept sockets on a local port.
-        * \param service The service name or port number.
-        * \param type The type of socket; either SOCK_STREAM or SOCK_DGRAM.
-        * \param family The family; can be AF_INET or AF_INET6.
-        * \param flags The socket options.
-        */
-       explicit Socket(const std::string& service,
-                                       int type = SOCK_STREAM,
-                                       int family = AF_UNSPEC,
-                                       int flags = 0) :
-               mImpl(SocketAddress(service, type, family), flags) {}
-
-
-       /**
-        * Deconstruct the socket, closing it.
-        */
-       ~Socket()
-       {
-               close();
-       }
-
-
-       /**
-        * Get whether or not the socket is connected.
-        * \return True if the socket is connected, false otherwise.
-        */
-       bool isConnected() const
-       {
-               return mImpl.isConnected;
-       }
-
-       /**
-        * Get the address associated with the socket.
-        */
-       const SocketAddress& address() const
-       {
-               return mImpl.address;
-       }
-
-
-       /**
-        * Connect the socket to its peer.
-        * \return 0 on success, -1 on failure.
-        */
-       int connect()
-       {
-               int result = ::connect(mImpl.fd,
-                                                          mImpl.address.address(),
-                                                          mImpl.address.size());
-               mImpl.isConnected = result != -1;
-               return result;
-       }
-
-       /**
-        * Disconnect a connected socket from its peer.
-        * \param flags Specify the socket directions to close.
-        * \return 0 on success, -1 on failure.
-        */
-       int disconnect(int flags = SHUT_RDWR)
-       {
-               return shutdown(mImpl.fd, flags);
-       }
-
-
-       /**
-        * Bind the socket to interface and port number specified in the
-        * address.
-        * \return 0 on success, -1 on failure.
-        */
-       int bind()
-       {
-               return ::bind(mImpl.fd,
-                                         mImpl.address.address(),
-                                         mImpl.address.size());
-       }
-
-       /**
-        * Listen on the socket for incoming connections.  This is only useful
-        * for sockets of type SOCK_STREAM.
-        * \param backlog The number of unaccepted connections to queue.
-        * \return 0 on success, -1 on failure.
-        */
-       int listen(int backlog = SOMAXCONN)
-       {
-               return ::listen(mImpl.fd, backlog > 0 ? backlog : SOMAXCONN);
-       }
-
-       /**
-        * Accept a new connection on the socket.  This is only useful for
-        * sockets of type SOCK_STREAM.
-        * \param socket Set to the new socket on return.
-        * \return 0 on success, -1 on failure.
-        */
-       int accept(Socket& socket)
-       {
-               Socket temp = Socket(mImpl.fd);
-               if (temp.mImpl.fd != -1)
-               {
-                       socket = temp;
-                       return socket.mImpl.fd;
-               }
-               return -1;
-       }
-
-
-       /**
-        * Set an integer socket option.
-        * \param option The option to set.
-        * \param value The new value.
-        * \param level The layer to handle the option.
-        * \return 0 on success, -1 on failure.
-        */
-       template <class T>
-       int set(int option, const T& value, int level = SOL_SOCKET)
-       {
-#if defined(_WIN32)
-               return setsockopt(mImpl.fd,
-                                                 level,
-                                                 option,
-                                                 reinterpret_cast<const char*>(&value),
-                                                 sizeof(value));
-#else
-               return setsockopt(mImpl.fd, level, option, &value, sizeof(value));
-#endif
-       }
-
-       /**
-        * Set a string socket option.
-        * \param option The option to set.
-        * \param value The new value.
-        * \param level The layer to handle the option.
-        * \return 0 on success, -1 on failure.
-        */
-       int set(int option, const std::string& value, int level = SOL_SOCKET)
-       {
-               return setsockopt(mImpl.fd, level, option,
-                                                 value.data(), value.length());
-       }
-
-       /**
-        * Get an integer socket option.
-        * \param option The option to set.
-        * \param value The new value.
-        * \param level The layer to handle the option.
-        * \return 0 on success, -1 on failure.
-        */
-       template <class T>
-       int get(int option, T& value, int level = SOL_SOCKET) const
-       {
-               int size = sizeof(value);
-               return getsockopt(mImpl.fd, level, option, &value, &size);
-       }
-
-       /**
-        * Get a string socket option.
-        * \param option The option to set.
-        * \param value The new value.
-        * \param level The layer to handle the option.
-        * \return 0 on success, -1 on failure.
-        */
-       int get(int option, std::string& value, int level = SOL_SOCKET) const
-       {
-               char            str[256] = {'\0'};
-               socklen_t       size = sizeof(str);
-
-#if defined(_WIN32)
-               int result = getsockopt(mImpl.fd,
-                                                               level,
-                                                               option,
-                                                               reinterpret_cast<char*>(&str),
-                                                               &size);
-#else
-               int result = getsockopt(mImpl.fd, level, option, &str, &size);
-#endif
-               value.assign(str, size);
-               return result;
-       }
-
-
-       /**
-        * Set the socket IO mode to either blocking or non-blocking.
-        * \param isBlocking True if the socket blocks, false otherwise.
-        */
-       void setBlocking(bool isBlocking)
-       {
-#ifdef HAVE_FCNTL
-               int flags = fcntl(mImpl.fd, F_GETFL);
-               flags = isBlocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
-               fcntl(mImpl.fd, F_SETFL, flags);
-#elif defined(_WIN32)
-               u_long value = isBlocking;
-               ioctlsocket(mImpl.fd, FIONBIO, &value);
-#endif
-       }
-
-       /**
-        * Get whether or not the socket is blocking or non-blocking.  If the
-        * IO mode can't be determined, this method will assume the socket is
-        * a blocking socket.
-        * \return True if the socket blocks, false otherwise.
-        */
-       bool isBlocking() const
-       {
-#ifdef HAVE_FCNTL
-               int flags = fcntl(mImpl.fd, F_GETFL);
-               return !(flags & O_NONBLOCK);
-#endif
-               return true;
-       }
-
-
-       /**
-        * Write some bytes to the socket.  Use this for connected sockets.
-        * \param bytes The bytes.
-        * \param size The number of bytes.
-        * \param flags The send options.
-        * \return The number of bytes written.
-        */
-       ssize_t write(const void* bytes, size_t size, int flags = 0)
-       {
-#if defined(_WIN32)
-               return send(mImpl.fd,
-                                       reinterpret_cast<const char *>(bytes), size,
-                                       flags);
-#else
-               return send(mImpl.fd, bytes, size, flags);
-#endif
-       }
-
-       /**
-        * Write some bytes to the socket using the given address.  Use this
-        * for unconnected sockets.
-        * \param bytes The bytes.
-        * \param size The number of bytes.
-        * \param address The address to send to.
-        * \param flags The send options.
-        * \return The number of bytes written.
-        */
-       ssize_t write(const void* bytes,
-                                 size_t size,
-                                 const SocketAddress& address,
-                                 int flags = 0)
-       {
-#if defined(_WIN32)
-               return sendto(mImpl.fd,
-                                         reinterpret_cast<const char*>(bytes), size,
-                                         flags,
-                                         address.address(), address.size());
-#else
-               return sendto(mImpl.fd, bytes, size, flags,
-                                         address.address(), address.size());
-#endif
-       }
-
-       /**
-        * Write a packet to the socket.  Use this for connected sockets.
-        * \param packet The packet.
-        * \param flags The send options.
-        * \return The number of bytes written.
-        */
-       ssize_t write(const Packet& packet, int flags = 0)
-       {
-               return write(packet.bytes(), packet.size(), flags);
-       }
-
-       /**
-        * Write a packet to the socket using the given address.  Use this for
-        * unconnected sockets.
-        * \param packet The packet.
-        * \param address The address to send to.
-        * \param flags The send options.
-        * \return The number of bytes written.
-        */
-       ssize_t write(const Packet& packet,
-                                 const SocketAddress& address,
-                                 int flags = 0)
-       {
-               return write(packet.bytes(), packet.size(), address, flags);
-       }
-
-
-       /**
-        * Read some bytes from the socket.  Use this for connected sockets.
-        * \param bytes The buffer to store the bytes.
-        * \param size The size of the buffer.
-        * \param flags The recv options.
-        * \return The number of bytes read.
-        */
-       ssize_t read(void* bytes, size_t size, int flags = 0)
-       {
-#if defined(_WIN32)
-               ssize_t result = recv(mImpl.fd,
-                                                         reinterpret_cast<char*>(bytes), size,
-                                                         flags);
-#else
-               ssize_t result = recv(mImpl.fd, bytes, size, flags);
-#endif
-               if (result == 0) mImpl.isConnected = false;
-               return result;
-       }
-
-       /**
-        * Read some bytes from the socket using the given address.  Use this
-        * for unconnected sockets.
-        * \param bytes The buffer to store the bytes.
-        * \param size The size of the buffer.
-        * \param address The address to read from.
-        * \param flags The recv options.
-        * \return The number of bytes read.
-        */
-       ssize_t read(void* bytes,
-                                size_t size,
-                                SocketAddress& address,
-                                int flags = 0)
-       {
-               union
-               {
-                       sockaddr                        sa;
-                       sockaddr_storage        storage;
-               } addr;
-               socklen_t length = sizeof(addr);
-
-#if defined(_WIN32)
-               ssize_t result = recvfrom(mImpl.fd,
-                                                                 reinterpret_cast<char*>(bytes), size,
-                                                                 flags,
-                                                                 &addr.sa, &length);
-#else
-               ssize_t result = recvfrom(mImpl.fd, bytes, size, flags,
-                                                                 &addr.sa, &length);
-#endif
-               if (result != -1)
-               {
-                       address = SocketAddress(&addr.sa, length, mImpl.address.type());
-               }
-               else if (result == 0)
-               {
-                       mImpl.isConnected = false;
-               }
-               return result;
-       }
-
-       /**
-        * Read a packet from the socket.  Use this for connected sockets.
-        * \param packet Set to the packet read on return.
-        * \param flags The recv options.
-        * \return The number of bytes read.
-        */
-       ssize_t read(Packet& packet, int flags = 0)
-       {
-               char buffer[65536];
-               ssize_t result = read(buffer, sizeof(buffer), flags);
-               if (result != -1) packet = Packet(buffer, result);
-               return result;
-       }
-
-       /**
-        * Read a packet from the socket using the given address.  Use this for
-        * unconnected sockets.
-        * \param packet Set to the packet read on return.
-        * \param address The address to read from.
-        * \param flags The recv options.
-        * \return The number of bytes read.
-        */
-       ssize_t read(Packet& packet, SocketAddress& address, int flags = 0)
-       {
-               char buffer[65536];
-               ssize_t result = read(buffer, sizeof(buffer), address, flags);
-               if (result != -1) packet = Packet(buffer, result);
-               return result;
-       }
-
-
-       // The rest of this junk is used to implement the "move" semantics
-       // correctly, since it makes no sense for socket objects to be copied.
-
-       Socket(Socket& move) :
-               mImpl(move.mImpl)
-       {
-               move.mImpl.fd = -1;
-               move.mImpl.isConnected = false;
-       }
-
-       Socket(Impl move) :
-               mImpl(move) {}
-
-       Socket& operator=(Socket& move)
-       {
-               close();
-               mImpl = move.mImpl;
-               move.mImpl.fd = -1;
-               move.mImpl.isConnected = false;
-               return *this;
-       }
-
-       Socket& operator=(Impl move)
-       {
-               close();
-               mImpl = move;
-               return *this;
-       }
-
-       operator Impl()
-       {
-               Impl impl(mImpl);
-               mImpl.fd = -1;
-               mImpl.isConnected = false;
-               return impl;
-       }
-
-
-private:
-
-       Socket(int fd)
-       {
-               // for accepting a socket from fd
-               union
-               {
-                       sockaddr                        sa;
-                       sockaddr_storage        storage;
-               } addr;
-               socklen_t length = sizeof(addr);
-
-               mImpl.fd = ::accept(fd, &addr.sa, &length);
-               if (mImpl.fd != -1)
-               {
-                       mImpl.isConnected = true;
-                       mImpl.address = SocketAddress(&addr.sa, length);
-               }
-       }
-
-       void close()
-       {
-#if defined(_WIN32)
-               if (mImpl.fd != -1) closesocket(mImpl.fd);
-#else
-               if (mImpl.fd != -1) ::close(mImpl.fd);
-#endif
-       }
-};
-
-
-class SocketMultiplexer
-{
-public:
-
-       typedef boost::function<int(SocketMultiplexer&,
-                                                               Packet&,
-                                                               const SocketAddress&)> Function;
-
-       explicit SocketMultiplexer(Socket sock) :
-               mSocket(sock) {}
-
-
-       void setSocket(Socket sock)
-       {
-               Mutex::ScopedLock lock(mMutex);
-               mSocket = sock;
-       }
-
-       Socket& socket()
-       {
-               return mSocket;
-       }
-
-
-       std::vector<Function>& protocols()
-       {
-               return mProtocols;
-       }
-
-
-       void update(Scalar t, Scalar dt)
-       {
-               SocketAddress   address;
-               Packet                  packet;
-               ssize_t                 bytes = mSocket.read(packet, address);
-
-               if (bytes > 0)
-               {
-                       std::vector<Function>::iterator it;
-                       for (it = mProtocols.begin(); it < mProtocols.end(); ++it)
-                       {
-                               packet.reset();
-                               if ((*it)(*this, packet, address)) break;
-                       }
-               }
-       }
-
-
-       int background()
-       {
-               return 0;
-       }
-
-
-private:
-
-       Socket                                  mSocket;
-       std::vector<Function>   mProtocols;
-       Mutex                                   mMutex;
-};
-
-
-/**
- * An asynchronous task to resolve addresses.
- */
-class ResolverTask : public ThreadedTask
-{
-public:
-
-       /**
-        * Construct a resolver task from a service and hostname.
-        * \param service Server name or port number.
-        * \param name The hostname or numeric address.
-        * \param type The type of communication.
-        * \param family The requested protocol family.
-        */
-       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, service, name, type, family);
-       }
-
-
-       /**
-        * Get whether or not the task is done.
-        * \return True if the task has finished, false otherwise.
-        */
-       bool isDone() const
-       {
-               return mIsDone;
-       }
-
-       /**
-        * Start the task.  This does nothing if the task was already run or is
-        * currently running.
-        */
-       void run()
-       {
-               if (!isDone() && !mThread.isValid())
-               {
-                       mThread = Thread::detach(mFunction);
-               }
-       }
-
-
-       /**
-        * Get the addresses resolved.  This is filled and safe to access after
-        * the task finishes.
-        * \return List of addresses.
-        * \see isDone()
-        */
-       const std::vector<SocketAddress>& addresses() const
-       {
-               return mAddressList;
-       }
-
-
-private:
-
-       int resolve(const std::string& service,
-                               const std::string& name,
-                               int type,
-                               int family)
-       {
-               int status = SocketAddress::resolve(service, name,
-                                                                                       type, family,
-                                                                                       mAddressList);
-               mIsDone = true;
-               return status;
-       }
-
-
-       std::vector<SocketAddress>      mAddressList;
-       bool                                            mIsDone;
-       Thread::Function                        mFunction;
-};
-
-
-std::ostream& operator<<(std::ostream& stream, const SocketAddress& addr)
-{
-       stream << addr.name() << ":" << addr.service();
-       return stream;
-}
-
-std::ostream& operator<<(std::ostream& stream, const Socket& sock)
-{
-       stream << sock.address();
-       return stream;
-}
-
-
-} // namespace Mf
-
-#endif // _MOOF_SOCKET_HH_
-
This page took 0.036357 seconds and 4 git commands to generate.