X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FSocket.hh;fp=src%2FMoof%2FSocket.hh;h=0000000000000000000000000000000000000000;hp=60fd8e054531aa080f7cc1740d6075664f3ffb18;hb=831f04d4bc19a390415ac0bbac4331c7a65509bc;hpb=299af4f2047e767e5d79501c26444473bda64c64 diff --git a/src/Moof/Socket.hh b/src/Moof/Socket.hh deleted file mode 100644 index 60fd8e0..0000000 --- a/src/Moof/Socket.hh +++ /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 -#include -#include -#include -#include -#include - -#if HAVE_FCNTL_H -#include -#else -#error No alternative to fcntl implemented yet. -#endif - -#if defined(_WIN32) -#include -#include -#include -#define SHUT_RD SD_RECEIVE -#define SHUT_WR SD_SEND -#define SHUT_RDWR SD_BOTH -#else -#include -#include -#include -#include -#endif - -#include -#include -#include - - -#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& 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& 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& 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 - int set(int option, const T& value, int level = SOL_SOCKET) - { -#if defined(_WIN32) - return setsockopt(mImpl.fd, - level, - option, - reinterpret_cast(&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 - 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(&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(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(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(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(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 Function; - - explicit SocketMultiplexer(Socket sock) : - mSocket(sock) {} - - - void setSocket(Socket sock) - { - Mutex::ScopedLock lock(mMutex); - mSocket = sock; - } - - Socket& socket() - { - return mSocket; - } - - - std::vector& 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::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 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& 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 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_ -