changeset 317:890729b8cb60

Reimplement SocketError and add a new Timeout code
author David Demelier <markand@malikania.fr>
date Wed, 04 Mar 2015 13:45:56 +0100
parents 4c0af1143fc4
children 68ae6d7dea1f
files C++/Socket.cpp C++/Socket.h C++/SocketAddress.cpp C++/SocketListener.cpp C++/SocketTcp.cpp C++/SocketUdp.cpp
diffstat 6 files changed, 125 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/C++/Socket.cpp	Tue Mar 03 18:48:54 2015 +0100
+++ b/C++/Socket.cpp	Wed Mar 04 13:45:56 2015 +0100
@@ -69,6 +69,31 @@
 }
 
 /* --------------------------------------------------------
+ * SocketError class
+ * -------------------------------------------------------- */
+
+SocketError::SocketError(Code code, std::string function)
+	: m_code(code)
+	, m_function(std::move(function))
+	, m_error(Socket::syserror())
+{
+}
+
+SocketError::SocketError(Code code, std::string function, int error)
+	: m_code(code)
+	, m_function(std::move(function))
+	, m_error(Socket::syserror(error))
+{
+}
+
+SocketError::SocketError(Code code, std::string function, std::string error)
+	: m_code(code)
+	, m_function(std::move(function))
+	, m_error(std::move(error))
+{
+}
+
+/* --------------------------------------------------------
  * Socket class
  * -------------------------------------------------------- */
 
@@ -82,7 +107,7 @@
 	m_handle = ::socket(domain, type, protocol);
 
 	if (m_handle == Invalid)
-		throw SocketError();
+		throw SocketError(SocketError::System, "socket");
 }
 
 void Socket::bind(const SocketAddress &address)
@@ -91,7 +116,7 @@
 	const auto addrlen = address.length();
 
 	if (::bind(m_handle, reinterpret_cast<const sockaddr *>(&sa), addrlen) == Error)
-		throw SocketError("bind", Socket::syserror(), errno);
+		throw SocketError(SocketError::System, "bind");
 
 	m_state = SocketState::Bound;
 }
@@ -121,12 +146,12 @@
 		flags |= O_NONBLOCK;
 
 	if (fcntl(m_handle, F_SETFL, flags) == Error)
-		throw SocketError("setBlockMode", Socket::syserror(), errno);
+		throw SocketError(SocketError::System, "setBlockMode");
 #else
 	unsigned long flags = (block) ? 0 : 1;
 
 	if (ioctlsocket(m_handle, FIONBIO, &flags) == Error)
-		throw SocketError("setBlockMode", Socket::syserror(), WSAGetLastError());
+		throw SocketError(SocketError::System, "setBlockMode");
 #endif
 }
 
--- a/C++/Socket.h	Tue Mar 03 18:48:54 2015 +0100
+++ b/C++/Socket.h	Wed Mar 04 13:45:56 2015 +0100
@@ -69,6 +69,10 @@
 
 class SocketAddress;
 
+/**
+ * @class SocketError
+ * @brief Base class for sockets error
+ */
 class SocketError : public std::exception {
 public:
 	enum Code {
@@ -80,12 +84,38 @@
 	};
 
 	Code m_code;
+	std::string m_function;
 	std::string m_error;
 
-	template <typename... Args>
-	inline SocketError(const Args&... args)
+	/**
+	 * Constructor that use the last system error.
+	 *
+	 * @param code which kind of error
+	 * @param function the function name
+	 */
+	SocketError(Code code, std::string function);
+
+	/**
+	 * Constructor that use the system error set by the user.
+	 *
+	 * @param code which kind of error
+	 * @param function the function name
+	 * @param error the error
+	 */
+	SocketError(Code code, std::string function, int error);
+
+	/**
+	 * Constructor that set the error specified by the user.
+	 *
+	 * @param code which kind of error
+	 * @param function the function name
+	 * @param error the error
+	 */
+	SocketError(Code code, std::string function, std::string error);
+
+	inline const std::string &function() const noexcept
 	{
-
+		return m_function;
 	}
 
 	inline Code code() const noexcept
@@ -93,17 +123,23 @@
 		return m_code;
 	}
 
-	const char *what() const noexcept {
+	const char *what() const noexcept
+	{
 		return "Error failure";
 	}
 };
 
+/**
+ * @enum SocketState
+ * @brief Category of error
+ */
 enum class SocketState {
 	Opened,				///!< Socket is opened
 	Closed,				///!< Socket has been closed
 	Bound,				///!< Socket is bound to address
 	Connected,			///!< Socket is connected to an end point
-	Disconnected			///!< Socket is disconnected
+	Disconnected,			///!< Socket is disconnected
+	Timeout				///!< Timeout has occured in a waiting operation
 };
 
 /**
@@ -254,7 +290,7 @@
 #else
 		if (setsockopt(m_handle, level, name, (Socket::ConstArg)&arg, sizeof (arg)) < 0)
 #endif
-			throw SocketError("set", syserror(), errno);
+			throw SocketError(SocketError::System, "set");
 	}
 
 	/**
@@ -275,7 +311,7 @@
 #else
 		if (getsockopt(m_handle, level, name, (Socket::Arg)&desired, &size) < 0)
 #endif
-			throw SocketError("get", syserror(), errno);
+			throw SocketError(SocketError::System, "get");
 
 		std::memcpy(&result, &desired, size);
 
--- a/C++/SocketAddress.cpp	Tue Mar 03 18:48:54 2015 +0100
+++ b/C++/SocketAddress.cpp	Wed Mar 04 13:45:56 2015 +0100
@@ -56,7 +56,7 @@
 
 		auto error = getaddrinfo(host.c_str(), std::to_string(port).c_str(), &hints, &res);
 		if (error != 0)
-			throw SocketError("getaddrinfo", gai_strerror(error), error);
+			throw SocketError(SocketError::System, "getaddrinfo", gai_strerror(error));
 
 		std::memcpy(&m_addr, res->ai_addr, res->ai_addrlen);
 		m_addrlen = res->ai_addrlen;
--- a/C++/SocketListener.cpp	Tue Mar 03 18:48:54 2015 +0100
+++ b/C++/SocketListener.cpp	Wed Mar 04 13:45:56 2015 +0100
@@ -78,7 +78,7 @@
 		auto result = selectMultiple(ms);
 
 		if (result.size() == 0) {
-			throw SocketError("select", "No socket found", 0);
+			throw SocketError(SocketError::System, "select", "No socket found");
 		}
 
 		return result[0];
@@ -116,15 +116,10 @@
 
 		auto error = ::select(max + 1, &readset, &writeset, nullptr, towait);
 		if (error == Socket::Error) {
-#if defined(_WIN32)
-			throw SocketError("select", Socket::syserror(), WSAGetLastError());
-#else
-			throw SocketError("select", Socket::syserror(), errno);
-#endif
+			throw SocketError(SocketError::System, "select");
 		}
-
 		if (error == 0) {
-			throw SocketError("select");
+			throw SocketError(SocketError::Timeout, "select", "Timeout while listening");
 		}
 
 		std::vector<SocketStatus> sockets;
@@ -246,13 +241,9 @@
 	{
 		auto result = poll(m_fds.data(), m_fds.size(), ms);
 		if (result == 0)
-			throw SocketError("select");
+			throw SocketError(SocketError::Timeout, "select", "Timeout while listening");
 		if (result < 0)
-#if defined(_WIN32)
-			throw SocketError("poll", Socket::syserror(), WSAGetLastError());
-#else
-			throw SocketError("poll", Socket::syserror(), errno);
-#endif
+			throw SocketError(SocketError::System, "poll");
 
 		for (auto &fd : m_fds) {
 			if (fd.revents != 0) {
@@ -260,21 +251,17 @@
 			}
 		}
 
-		throw SocketError("select", "No socket found", 0);
+		throw SocketError(SocketError::System, "select", "No socket found");
 	}
 
 	std::vector<SocketStatus> selectMultiple(int ms) override
 	{
 		auto result = poll(m_fds.data(), m_fds.size(), ms);
 		if (result == 0) {
-			throw SocketError("select");
+			throw SocketError(SocketError::Timeout, "select", "Timeout while listening");
 		}
 		if (result < 0) {
-#if defined(_WIN32)
-			throw SocketError("poll", Socket::syserror(), WSAGetLastError());
-#else
-			throw SocketError("poll", Socket::syserror(), errno);
-#endif
+			throw SocketError(SocketError::System, "poll");
 		}
 
 		std::vector<SocketStatus> sockets;
--- a/C++/SocketTcp.cpp	Tue Mar 03 18:48:54 2015 +0100
+++ b/C++/SocketTcp.cpp	Wed Mar 04 13:45:56 2015 +0100
@@ -27,7 +27,7 @@
 void SocketAbstractTcp::listen(int max)
 {
 	if (::listen(m_handle, max) == Error)
-		throw SocketError("listen", Socket::syserror(), errno);
+		throw SocketError(SocketError::System, "listen");
 }
 
 /* --------------------------------------------------------
@@ -54,15 +54,17 @@
 
 	if (handle == Invalid) {
 #if defined(_WIN32)
-		if (WSAGetLastError() == WSAEWOULDBLOCK)
-			throw SocketError("accept", Socket::syserror(WSAEWOULDBLOCK), WSAEWOULDBLOCK /* TODO: Read */);
+		int error = WSAGetLastError();
 
-		throw SocketError("accept", Socket::syserror(), WSAGetLastError());
+		if (error == WSAEWOULDBLOCK)
+			throw SocketError(SocketError::WouldBlockRead, "accept", error);
+
+		throw SocketError(SocketError::System, "accept", error);
 #else
 		if (errno == EAGAIN || errno == EWOULDBLOCK)
-			throw SocketError("accept", Socket::syserror(EWOULDBLOCK), EWOULDBLOCK /* TODO: Read */);
+			throw SocketError(SocketError::WouldBlockRead, "accept");
 
-		throw SocketError("accept", Socket::syserror(), errno);
+		throw SocketError(SocketError::System, "accept");
 #endif
 	}
 
@@ -86,15 +88,17 @@
 		 * accomplished yet.
 		 */
 #if defined(_WIN32)
-		if (WSAGetLastError() == WSAEWOULDBLOCK)
-			throw SocketError("connect", Socket::syserror(WSAEWOULDBLOCK), WSAEWOULDBLOCK /*, Write */);
+		int error = WSAGetLastError();
 
-		throw SocketError("connect", Socket::syserror(WSAEWOULDBLOCK), WSAGetLastError());
+		if (error == WSAEWOULDBLOCK)
+			throw SocketError(SocketError::WouldBlockWrite, "connect", error);
+
+		throw SocketError(SocketError::System, "connect", error);
 #else
 		if (errno == EINPROGRESS)
-			throw SocketError("connect", Socket::syserror(EINPROGRESS), EINPROGRESS /*, Write */);
+			throw SocketError(SocketError::WouldBlockWrite, "connect");
 
-		throw SocketError("connect", Socket::syserror(), errno);
+		throw SocketError(SocketError::System, "connect");
 #endif
 	}
 
@@ -120,7 +124,7 @@
 		int error = get<int>(SOL_SOCKET, SO_ERROR);
 
 		if (error) {
-			throw SocketError("connect", Socket::syserror(error), error);
+			throw SocketError(SocketError::System, "connect", error);
 		}
 	}
 
@@ -150,15 +154,17 @@
 	nbread = ::recv(m_handle, (Socket::Arg)data, dataLen, 0);
 	if (nbread == Error) {
 #if defined(_WIN32)
-		if (WSAGetLastError() == WSAEWOULDBLOCK)
-			throw SocketError("recv", Socket::syserror(), WSAEWOULDBLOCK /* TODO: Read */);
+		int error = WSAGetLastError();
 
-		throw SocketError("recv", Socket::syserror(), WSAGetLastError());
+		if (error == WSAEWOULDBLOCK)
+			throw SocketError(SocketError::WouldBlockRead, "recv", error)
+
+		throw SocketError(SocketError::System, "recv", error);
 #else
 		if (errno == EAGAIN || errno == EWOULDBLOCK)
-			throw SocketError("recv", Socket::syserror(), errno /* TODO: Read */);
+			throw SocketError(SocketError::WouldBlockRead, "recv");
 
-		throw SocketError("recv", Socket::syserror(), errno);
+		throw SocketError(SocketError::System, "recv");
 #endif
 	} else if (nbread == 0)
 		m_state = SocketState::Closed;
@@ -182,15 +188,17 @@
 	nbsent = ::send(m_handle, (Socket::ConstArg)data, length, 0);
 	if (nbsent == Error) {
 #if defined(_WIN32)
-		if (WSAGetLastError() == WSAEWOULDBLOCK)
-			throw SocketError("send", Socket::syserror(), WSAEWOULDBLOCK /* Write */);
+		int error = WSAGetLastError();
 
-		throw SocketError("send", Socket::syserror(), WSAGetLastError());
+		if (error == WSAEWOULDBLOCK)
+			throw SocketError(SocketError::WouldBlockWrite, "send", error);
+
+		throw SocketError(SocketError::System, "send", error);
 #else
 		if (errno == EAGAIN || errno == EWOULDBLOCK)
-			throw SocketError("send", Socket::syserror(), errno /*, Write */);
+			throw SocketError(SocketError::WouldBlockWrite, "send");
 
-		throw SocketError("send", Socket::syserror(), errno);
+		throw SocketError(SocketError::System, "send");
 #endif
 	}
 
--- a/C++/SocketUdp.cpp	Tue Mar 03 18:48:54 2015 +0100
+++ b/C++/SocketUdp.cpp	Wed Mar 04 13:45:56 2015 +0100
@@ -39,15 +39,17 @@
 
 	if (nbread == Error) {
 #if defined(_WIN32)
-		if (WSAGetLastError() == WSAEWOULDBLOCK)
-			throw SocketError("recvfrom", Socket::syserror(), WSAEWOULDBLOCK /*, Read */);
+		int error = WSAGetLastError();
 
-		throw SocketError("recvfrom", Socket::syserror(), WSAGetLastError());
+		if (error == WSAEWOULDBLOCK)
+			throw SocketError(SocketError::WouldBlockRead, "recvfrom", error);
+
+		throw SocketError(SocketError::System, "recvfrom", error);
 #else
 		if (errno == EAGAIN || errno == EWOULDBLOCK)
-			throw SocketError("recvfrom", Socket::syserror(), errno /* , Read */);
+			throw SocketError(SocketError::WouldBlockRead, "recvfrom");
 
-		throw SocketError("recvfrom", Socket::syserror(), errno);
+		throw SocketError(SocketError::System, "recvfrom");
 #endif
 	}
 
@@ -61,15 +63,17 @@
 	nbsent = ::sendto(m_handle, (Socket::ConstArg)data, length, 0, (const sockaddr *)&info.address(), info.length());
 	if (nbsent == Error) {
 #if defined(_WIN32)
-		if (WSAGetLastError() == WSAEWOULDBLOCK)
-			throw SocketError("sendto", Socket::syserror(), WSAEWOULDBLOCK /*, Write */);
+		int error = WSAGetLastError();
 
-		throw SocketError("sendto", Socket::syserror(), errno);
+		if (error == WSAEWOULDBLOCK)
+			throw SocketError(SocketError::WouldBlockWrite, "sendto", error);
+
+		throw SocketError(SocketError::System, "sendto", error);
 #else
 		if (errno == EAGAIN || errno == EWOULDBLOCK)
-			throw SocketError("sendto", Socket::syserror(), errno /*, Write */);
+			throw SocketError(SocketError::WouldBlockWrite, "sendto");
 
-		throw SocketError("sendto", Socket::syserror(), errno);
+		throw SocketError(SocketError::System, "sendto");
 #endif
 	}