#ifndef _MOOF_SOCKET_HH_
#define _MOOF_SOCKET_HH_
+#include <algorithm>
#include <cstring>
#include <sstream>
#include <string>
mSize(0),
mType(0)
{
- mAddress.sa.sa_family = AF_UNSPEC;
- mAddress.v4.sin_port = 0;
+ mAddr.sa.sa_family = AF_UNSPEC;
+ mAddr.in.sin_port = 0;
}
SocketAddress(const std::string& service, const std::string& name,
SocketAddress(const struct addrinfo* addr, const std::string& name)
{
mType = addr->ai_socktype;
- memcpy(&mAddress.sa, addr->ai_addr, addr->ai_addrlen);
+ memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
mName = name;
mSize = addr->ai_addrlen;
}
int type = SOCK_STREAM)
{
mType = type;
- memcpy(&mAddress.sa, addr, size);
+ memcpy(&mAddr.sa, addr, size);
mSize = size;
setNameFromAddress();
}
if (status == 0)
{
mType = addr->ai_socktype;
- memcpy(&mAddress.sa, addr->ai_addr, addr->ai_addrlen);
+ memcpy(&mAddr.sa, addr->ai_addr, addr->ai_addrlen);
mSize = addr->ai_addrlen;
if (name != "") mName = name;
Mf::logWarning(gai_strerror(status));
mType = 0;
mSize = 0;
- mAddress.sa.sa_family = AF_UNSPEC;
- mAddress.v4.sin_port = 0;
+ mAddr.sa.sa_family = AF_UNSPEC;
+ mAddr.in.sin_port = 0;
}
}
unsigned short port() const
{
- return ntohs(mAddress.v4.sin_port);
+ return ntohs(mAddr.in.sin_port);
}
int type() const
int family() const
{
- return mAddress.sa.sa_family;
+ return mAddr.sa.sa_family;
}
const struct sockaddr* address() const
{
- return mSize != 0 ? &mAddress.sa : 0;
+ return mSize != 0 ? &mAddr.sa : 0;
}
size_t size() const
{
#if defined(_WIN32)
// inet_ntop was introduced in Vista
- mName = inet_ntoa(mAddress.v4.sin_addr);
+ mName = inet_ntoa(mAddr.in.sin_addr);
#else
char name[INET6_ADDRSTRLEN] = {'\0'};
- inet_ntop(mAddress.sa.sa_family, &mAddress.sa, name, sizeof(name));
+ inet_ntop(mAddr.sa.sa_family, &mAddr.sa, name, sizeof(name));
mName = name;
#endif
}
union
{
sockaddr sa;
- sockaddr_in v4;
- sockaddr_in6 v6;
+ sockaddr_in in;
sockaddr_storage storage;
- } mAddress;
+ } mAddr;
size_t mSize;
std::string mName;
int mType;
class Socket
{
+ struct Impl
+ {
+ int fd;
+ bool isConnected;
+ SocketAddress address;
+ };
+
+
public:
+ Socket() :
+ mFd(-1),
+ mIsConnected(false) {}
+
Socket(const SocketAddress& address) :
mFd(-1),
mIsConnected(false),
- mAddress(address)
+ mAddress(address) {}
+
+ Socket(const std::string& service, const std::string& name,
+ int type = SOCK_STREAM, int family = AF_UNSPEC) :
+ mFd(-1),
+ mIsConnected(false),
+ mAddress(SocketAddress(service, name, type, family)) {}
+
+ Socket(const std::string& service,
+ int type = SOCK_STREAM, int family = AF_UNSPEC) :
+ mFd(-1),
+ mIsConnected(false),
+ mAddress(SocketAddress(service, type, family)) {}
+
+
+ Socket(Socket& move) :
+ mFd(move.mFd),
+ mIsConnected(move.mIsConnected),
+ mAddress(move.mAddress)
+ {
+ move.mFd = -1;
+ move.mIsConnected = false;
+ }
+
+ Socket(Impl move) :
+ mFd(move.fd),
+ mIsConnected(move.isConnected),
+ mAddress(move.address) {}
+
+ Socket& operator=(Socket& move)
+ {
+#if defined(_WIN32)
+ if (mFd != -1) closesocket(mFd);
+#else
+ if (mFd != -1) close(mFd);
+#endif
+ mFd = move.mFd;
+ mIsConnected = move.mIsConnected;
+ mAddress = move.mAddress;
+ move.mFd = -1;
+ move.mIsConnected = false;
+ return *this;
+ }
+
+ Socket& operator=(Impl move)
+ {
+#if defined(_WIN32)
+ if (mFd != -1) closesocket(mFd);
+#else
+ if (mFd != -1) close(mFd);
+#endif
+ mFd = move.fd;
+ mIsConnected = move.isConnected;
+ mAddress = move.address;
+ return *this;
+ }
+
+ operator Impl()
{
- mFd = socket(address.family(), address.type(), 0);
+ Impl impl;
+ impl.fd = mFd;
+ impl.isConnected = mIsConnected;
+ impl.address = mAddress;
+ mFd = -1;
+ mIsConnected = false;
+ return impl;
}
+
~Socket()
{
#if defined(_WIN32)
int connect()
{
+ if (mFd == -1) mFd = socket(mAddress.family(), mAddress.type(), 0);
int result = ::connect(mFd, mAddress.address(), mAddress.size());
mIsConnected = result != -1;
return result;
int bind()
{
+ if (mFd == -1) mFd = socket(mAddress.family(), mAddress.type(), 0);
return ::bind(mFd, mAddress.address(), mAddress.size());
}
return ::listen(mFd, backlog > 0 ? backlog : SOMAXCONN);
}
- Socket accept()
+ int accept(Socket& socket)
{
- return Socket(mFd);
+ Socket temp = Socket(mFd);
+ if (temp.mFd != -1)
+ {
+ socket = temp;
+ return socket.mFd;
+ }
+ return -1;
}
socklen_t length = sizeof(addr);
mFd = ::accept(fd, &addr.sa, &length);
- mAddress = SocketAddress(&addr.sa, length);
+ if (mFd != -1)
+ {
+ mIsConnected = true;
+ mAddress = SocketAddress(&addr.sa, length);
+ }
}