#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();
}
static SocketAddress broadcast(const std::string& service)
{
- return SocketAddress(service, "255.255.255.255", SOCK_DGRAM);
+ 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);
}
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
service.length() > 0 ? service.c_str() : 0, &hints, &list);
if (status == 0)
{
- struct addrinfo* addr = list;
- while (addr != 0)
+ for (struct addrinfo* addr = list;
+ addr != 0; addr = addr->ai_next)
{
resolved.push_back(SocketAddress(addr, name));
- addr = addr->ai_next;
}
freeaddrinfo(list);
else
{
Mf::logWarning(gai_strerror(status));
+ return -1;
}
return 0;
{
#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)
+ {
+#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)
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, const std::string& value)
{
return setsockopt(mFd, SOL_SOCKET, option,
- value.c_str(), value.length());
+ value.data(), value.length());
}
int get(int option, int& value)
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;
+ }
+
+ ssize_t read(Packet& packet)
+ {
+ char buffer[65536];
+ ssize_t result = read(buffer, sizeof(buffer));
+ if (result != -1) packet = Packet(buffer, result);
+ return result;
+ }
- address = SocketAddress(&addr.sa, length, mAddress.type());
- return Packet(buffer, size);
+ 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;
};