#ifndef WIN32
-#include <errno.h>
+#include <cerrno>
#include <fcntl.h>
#include <sys/socket.h>
#endif
#include <msp/time/rawtime_private.h>
#include <msp/time/units.h>
#include "socket.h"
+#include "socket_private.h"
namespace {
namespace Msp {
namespace Net {
-Socket::Socket(SocketHandle h, const SockAddr &paddr):
- handle(h),
+Socket::Socket(const Private &p, const SockAddr &paddr):
+ priv(new Private),
connected(true),
local_addr(0),
peer_addr(paddr.copy())
{
+ priv->handle = p.handle;
+
sockaddr_storage sa;
socklen_t size = sizeof(sockaddr_storage);
- getsockname(handle, reinterpret_cast<sockaddr *>(&sa), &size);
+ getsockname(priv->handle, reinterpret_cast<sockaddr *>(&sa), &size);
local_addr = SockAddr::create(sa);
#ifdef WIN32
- event = CreateEvent(0, false, false, 0);
+ *priv->event = CreateEvent(0, false, false, 0);
#else
- *event = handle;
+ *priv->event = priv->handle;
#endif
}
Socket::Socket(Family af, int type, int proto):
+ priv(new Private),
connected(false),
local_addr(0),
peer_addr(0)
{
- handle = socket(af, type, proto);
+ priv->handle = socket(af, type, proto);
#ifdef WIN32
- event = CreateEvent(0, false, false, 0);
+ *priv->event = CreateEvent(0, false, false, 0);
#else
- *event = handle;
+ *priv->event = priv->handle;
#endif
}
Socket::~Socket()
{
- close();
+ signal_flush_required.emit();
+#ifdef WIN32
+ closesocket(priv->handle);
+ CloseHandle(*priv->event);
+#else
+ ::close(priv->handle);
+#endif
+
+ delete local_addr;
+ delete peer_addr;
+ delete priv;
}
void Socket::set_block(bool b)
#ifdef WIN32
u_long flag = !b;
- ioctlsocket(handle, FIONBIO, &flag);
+ ioctlsocket(priv->handle, FIONBIO, &flag);
#else
- int flags = fcntl(handle, F_GETFL);
- fcntl(handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
+ int flags = fcntl(priv->handle, F_GETFL);
+ fcntl(priv->handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
#endif
}
const IO::Handle &Socket::get_event_handle()
{
- return event;
+ return priv->event;
}
void Socket::bind(const SockAddr &addr)
{
- check_state(false);
-
sockaddr_storage sa;
unsigned size = addr.fill_sockaddr(sa);
- int err = ::bind(handle, reinterpret_cast<sockaddr *>(&sa), size);
+ int err = ::bind(priv->handle, reinterpret_cast<sockaddr *>(&sa), size);
if(err==-1)
throw system_error("bind");
local_addr = addr.copy();
}
-void Socket::close()
-{
- if(handle==MSP_NET_INVALID_SOCKET_HANDLE)
- return;
-
- set_events(IO::P_NONE);
-
- signal_flush_required.emit();
-#ifdef WIN32
- closesocket(handle);
- CloseHandle(event);
-#else
- ::close(handle);
-#endif
- handle = MSP_NET_INVALID_SOCKET_HANDLE;
- connected = false;
- signal_closed.emit();
-
- delete local_addr;
- local_addr = 0;
- delete peer_addr;
- peer_addr = 0;
-}
-
void Socket::set_timeout(const Time::TimeDelta &timeout)
{
#ifndef WIN32
return *peer_addr;
}
-void Socket::check_state(bool conn) const
-{
- if(handle==MSP_NET_INVALID_SOCKET_HANDLE)
- throw bad_socket_state("socket is closed");
- if(conn && !connected)
- throw bad_socket_state("not connected");
-}
-
int Socket::set_option(int level, int optname, const void *optval, socklen_t optlen)
{
#ifdef WIN32
- return setsockopt(handle, level, optname, reinterpret_cast<const char *>(optval), optlen);
+ return setsockopt(priv->handle, level, optname, reinterpret_cast<const char *>(optval), optlen);
#else
- return setsockopt(handle, level, optname, optval, optlen);
+ return setsockopt(priv->handle, level, optname, optval, optlen);
#endif
}
int Socket::get_option(int level, int optname, void *optval, socklen_t *optlen) const
{
#ifdef WIN32
- return getsockopt(handle, level, optname, reinterpret_cast<char *>(optval), optlen);
+ return getsockopt(priv->handle, level, optname, reinterpret_cast<char *>(optval), optlen);
#else
- return getsockopt(handle, level, optname, optval, optlen);
+ return getsockopt(priv->handle, level, optname, optval, optlen);
#endif
}
unsigned Socket::do_write(const char *buf, unsigned size)
{
- check_state(true);
+ if(!connected)
+ throw bad_socket_state("not connected");
if(size==0)
return 0;
- int ret = ::send(handle, buf, size, 0);
+ int ret = ::send(priv->handle, buf, size, 0);
if(ret<0)
{
if(errno==EAGAIN)
unsigned Socket::do_read(char *buf, unsigned size)
{
- check_state(true);
+ if(!connected)
+ throw bad_socket_state("not connected");
+
if(size==0)
return 0;
- int ret = ::recv(handle, buf, size, 0);
+ int ret = ::recv(priv->handle, buf, size, 0);
if(ret<0)
{
if(errno==EAGAIN)