-/* $Id$
-
-This file is part of libmspnet
-Copyright © 2008 Mikkosoft Productions, Mikko Rasa
-Distributed under the LGPL
-*/
-
#ifndef WIN32
#include <errno.h>
#include <fcntl.h>
namespace Msp {
namespace Net {
+Socket::Socket(SocketHandle h, const SockAddr &paddr):
+ handle(h),
+ connected(true),
+ local_addr(0),
+ peer_addr(paddr.copy())
+{
+ sockaddr_storage sa;
+ socklen_t size=sizeof(sockaddr_storage);
+ getsockname(handle, reinterpret_cast<sockaddr *>(&sa), &size);
+ local_addr=SockAddr::create(sa);
+
+#ifdef WIN32
+ event=CreateEvent(0, false, false, 0);
+#endif
+}
+
+Socket::Socket(Family af, int type, int proto):
+ connected(false),
+ local_addr(0),
+ peer_addr(0)
+{
+ handle=socket(af, type, proto);
+
+#ifdef WIN32
+ event=CreateEvent(0, false, false, 0);
+#endif
+}
+
+Socket::~Socket()
+{
+ close();
+}
+
void Socket::set_block(bool b)
{
mode=(mode&~IO::M_NONBLOCK);
{
check_state(false);
- sockaddr sa;
+ sockaddr_storage sa;
unsigned size=addr.fill_sockaddr(sa);
- int err=::bind(handle, &sa, size);
+ int err=::bind(handle, reinterpret_cast<sockaddr *>(&sa), size);
if(err==-1)
- throw Exception(format("Unable to bind: %s", strerror(errno)));
+ throw SystemError("Unable to bind", errno);
delete local_addr;
local_addr=addr.copy();
}
/**
-Closes the socket. Most operations on the socket will return an error after
+Closes the socket. Most operations on the socket will throw an exception after
this.
*/
void Socket::close()
::close(handle);
#endif
handle=MSP_NET_INVALID_SOCKET_HANDLE;
+ connected=false;
signal_closed.emit();
delete local_addr;
peer_addr=0;
}
+void Socket::set_timeout(const Time::TimeDelta &timeout)
+{
+#ifndef WIN32
+ timeval tv;
+ timeout.fill_timeval(tv);
+ set_option(SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(timeval));
+ set_option(SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(timeval));
+#else
+ DWORD msecs = static_cast<DWORD>(timeout/Time::msec);
+ set_option(SOL_SOCKET, SO_RCVTIMEO, &msecs, sizeof(DWORD));
+ set_option(SOL_SOCKET, SO_SNDTIMEO, &msecs, sizeof(DWORD));
+#endif
+}
+
const SockAddr &Socket::get_local_address() const
{
if(local_addr==0)
return *peer_addr;
}
-Socket::~Socket()
-{
- close();
-}
-
-Socket::Socket(SocketHandle h, const SockAddr &paddr):
- handle(h),
- connected(true),
- local_addr(0),
- peer_addr(paddr.copy())
-{
- sockaddr sa;
- socklen_t size=sizeof(sockaddr);
- getsockname(handle, &sa, &size);
- local_addr=SockAddr::create(sa);
-
-#ifdef WIN32
- event=CreateEvent(0, false, false, 0);
-#endif
-}
-
-Socket::Socket(Family af, int type, int proto):
- connected(false),
- local_addr(0),
- peer_addr(0)
-{
- handle=socket(af, type, proto);
-
-#ifdef WIN32
- event=CreateEvent(0, false, false, 0);
-#endif
-}
-
void Socket::check_state(bool conn) const
{
if(handle==MSP_NET_INVALID_SOCKET_HANDLE)
throw Exception("Socket is not connected");
}
-int Socket::get_option(int level, int optname, void *optval, socklen_t *optlen)
+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);
+#else
+ return setsockopt(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);
if(errno==EAGAIN)
return 0;
else
- throw Exception(format("Writing to socket failed: %s", strerror(errno)));
+ throw SystemError("Writing to socket failed", errno);
}
return ret;
if(errno==EAGAIN)
return 0;
else
- throw Exception(format("Reading from socket failed: %s", strerror(errno)));
+ throw SystemError("Reading from socket failed", errno);
}
else if(ret==0 && !eof_flag)
{