#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),
- mAddress(address)
+ mIsConnected(false),
+ 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)
{
- mFd = socket(address.family(), address.type(), 0);
+#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()
+ {
+ Impl impl;
+ impl.fd = mFd;
+ impl.isConnected = mIsConnected;
+ impl.address = mAddress;
+ mFd = -1;
+ mIsConnected = false;
+ return impl;
+ }
+
+
~Socket()
{
#if defined(_WIN32)
bool isConnected() const
{
- return mFd != -1;
+ return mIsConnected;
}
const SocketAddress& address() const
int connect()
{
- return ::connect(mFd, mAddress.address(), mAddress.size());
+ 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;
}
int set(int option, int value = 0)
{
+ if (mFd == -1) mFd = socket(mAddress.family(), mAddress.type(), 0);
if (option == SO_NONBLOCK)
{
#ifdef HAVE_FCNTL
int set(int option, const std::string& value)
{
+ if (mFd == -1) mFd = socket(mAddress.family(), mAddress.type(), 0);
return setsockopt(mFd, SOL_SOCKET, option,
- value.c_str(), value.length());
+ value.data(), value.length());
}
int get(int option, int& value)
{
+ if (mFd == -1) mFd = socket(mAddress.family(), mAddress.type(), 0);
if (option == SO_NONBLOCK)
{
#ifdef HAVE_FCNTL
int get(int option, std::string& value)
{
+ if (mFd == -1) mFd = socket(mAddress.family(), mAddress.type(), 0);
char str[64] = {'\0'};
socklen_t optlen = sizeof(str);
int result = getsockopt(mFd, SOL_SOCKET, option, &str, &optlen);
return result;
}
- void write(const Packet& packet)
+
+ ssize_t write(const void* bytes, size_t size)
{
- write(mAddress, packet);
+ return send(mFd, bytes, size, 0);
+ }
+ ssize_t write(const void* bytes, size_t size,
+ const SocketAddress& address)
+ {
+ return sendto(mFd, bytes, size, 0,
+ address.address(), address.size());
}
- void write(const SocketAddress& address, const Packet& packet)
+ ssize_t write(const Packet& packet)
{
- sendto(mFd, packet.bytes(), packet.size(), 0,
- address.address(), address.size());
+ return write(packet.bytes(), packet.size());
}
- Packet read()
+ ssize_t write(const Packet& packet, const SocketAddress& address)
{
- char buffer[1024];
- int size = recv(mFd, buffer, sizeof(buffer), 0);
+ return write(packet.bytes(), packet.size(), address);
+ }
+
- return Packet(buffer, size);
+ ssize_t read(void* bytes, size_t size)
+ {
+ return recv(mFd, bytes, size, 0);
}
- Packet read(SocketAddress& address)
+ ssize_t read(void* bytes, size_t size, SocketAddress& address)
{
union
{
} addr;
socklen_t length = sizeof(addr);
- char buffer[1024];
- int size = recvfrom(mFd, buffer, sizeof(buffer), 0,
- &addr.sa, &length);
+ ssize_t result = recvfrom(mFd, bytes, size, 0, &addr.sa, &length);
+ if (result != -1)
+ {
+ address = SocketAddress(&addr.sa, length, mAddress.type());
+ }
+ return result;
+ }
- address = SocketAddress(&addr.sa, length, mAddress.type());
- return Packet(buffer, size);
+ ssize_t read(Packet& packet)
+ {
+ char buffer[65536];
+ ssize_t result = read(buffer, sizeof(buffer));
+ if (result != -1) packet = Packet(buffer, result);
+ return result;
+ }
+
+ ssize_t read(Packet& packet, SocketAddress& address)
+ {
+ char buffer[65536];
+ ssize_t result = read(buffer, sizeof(buffer), address);
+ if (result != -1) packet = Packet(buffer, result);
+ return result;
}
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);
+ }
}
int mFd;
+ bool mIsConnected;
SocketAddress mAddress;
};