aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2005-08-24 20:47:13 +0000
committerVincent Richard <[email protected]>2005-08-24 20:47:13 +0000
commit658fcc26b54eabcdb4bd1dea57a8f7191cdffe2e (patch)
tree8d3856b9813f12025f8134a0568fe6b4d4aa8635
parentRenamed 'vmime::messaging' to 'vmime::net'. (diff)
downloadvmime-658fcc26b54eabcdb4bd1dea57a8f7191cdffe2e.tar.gz
vmime-658fcc26b54eabcdb4bd1dea57a8f7191cdffe2e.zip
Error handling in posixSocket::send().
-rw-r--r--src/exception.cpp16
-rw-r--r--src/platforms/posix/posixSocket.cpp71
-rw-r--r--vmime/exception.hpp18
-rw-r--r--vmime/platforms/posix/posixSocket.hpp4
4 files changed, 100 insertions, 9 deletions
diff --git a/src/exception.cpp b/src/exception.cpp
index 5090e4fe..a8479b82 100644
--- a/src/exception.cpp
+++ b/src/exception.cpp
@@ -329,12 +329,26 @@ const char* net_exception::name() const throw() { return "net_exception"; }
//
+// socket_exception
+//
+
+socket_exception::~socket_exception() throw() {}
+socket_exception::socket_exception(const string& what, const exception& other)
+ : net_exception(what.empty()
+ ? "Socket error."
+ : "Socket error: '" + what + "'.", other) {}
+
+exception* socket_exception::clone() const { return new socket_exception(*this); }
+const char* socket_exception::name() const throw() { return "socket_exception"; }
+
+
+//
// connection_error
//
connection_error::~connection_error() throw() {}
connection_error::connection_error(const string& what, const exception& other)
- : net_exception(what.empty()
+ : socket_exception(what.empty()
? "Connection error."
: "Connection error: '" + what + "'.", other) {}
diff --git a/src/platforms/posix/posixSocket.cpp b/src/platforms/posix/posixSocket.cpp
index 8a042950..32b657fd 100644
--- a/src/platforms/posix/posixSocket.cpp
+++ b/src/platforms/posix/posixSocket.cpp
@@ -26,6 +26,8 @@
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
#include "vmime/exception.hpp"
@@ -90,16 +92,34 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port
m_desc = ::socket(AF_INET, SOCK_STREAM, 0);
if (m_desc == -1)
- throw vmime::exceptions::connection_error("Error while creating socket.");
+ {
+ try
+ {
+ throwSocketError(errno);
+ }
+ catch (exceptions::socket_exception& e)
+ {
+ throw vmime::exceptions::connection_error
+ ("Error while creating socket.", e);
+ }
+ }
// Start connection
if (::connect(m_desc, reinterpret_cast <sockaddr*>(&addr), sizeof(addr)) == -1)
{
- ::close(m_desc);
- m_desc = -1;
+ try
+ {
+ throwSocketError(errno);
+ }
+ catch (exceptions::socket_exception& e)
+ {
+ ::close(m_desc);
+ m_desc = -1;
- // Error
- throw vmime::exceptions::connection_error("Error while connecting socket.");
+ // Error
+ throw vmime::exceptions::connection_error
+ ("Error while connecting socket.", e);
+ }
}
}
@@ -156,16 +176,53 @@ const int posixSocket::receiveRaw(char* buffer, const int count)
void posixSocket::send(const vmime::string& buffer)
{
- ::send(m_desc, buffer.data(), buffer.length(), 0);
+ if (::send(m_desc, buffer.data(), buffer.length(), 0) == -1)
+ throwSocketError(errno);
}
void posixSocket::sendRaw(const char* buffer, const int count)
{
- ::send(m_desc, buffer, count, 0);
+ if (::send(m_desc, buffer, count, 0) == -1)
+ throwSocketError(errno);
}
+void posixSocket::throwSocketError(const int err)
+{
+ string msg;
+
+ switch (err)
+ {
+ case EACCES: msg = "EACCES: permission denied"; break;
+ case EAFNOSUPPORT: msg = "EAFNOSUPPORT: address family not supported"; break;
+ case EMFILE: msg = "EMFILE: process file table overflow"; break;
+ case ENFILE: msg = "ENFILE: system limit reached"; break;
+ case EPROTONOSUPPORT: msg = "EPROTONOSUPPORT: protocol not supported"; break;
+ case EAGAIN: msg = "EGAIN: blocking operation"; break;
+ case EBADF: msg = "EBADF: invalid descriptor"; break;
+ case ECONNRESET: msg = "ECONNRESET: connection reset by peer"; break;
+ case EFAULT: msg = "EFAULT: bad user space address"; break;
+ case EINTR: msg = "EINTR: signal occured before transmission"; break;
+ case EINVAL: msg = "EINVAL: invalid argument"; break;
+ case EMSGSIZE: msg = "EMSGSIZE: message cannot be sent atomically"; break;
+ case ENOBUFS: msg = "ENOBUFS: output queue is full"; break;
+ case ENOMEM: msg = "ENOMEM: out of memory"; break;
+ case EPIPE:
+ case ENOTCONN: msg = "ENOTCONN: not connected"; break;
+ case ECONNREFUSED: msg = "ECONNREFUSED: connection refused"; break;
+ default:
+
+ std::ostringstream oss;
+ oss << ::strerror(err);
+
+ msg = oss.str();
+ break;
+ }
+
+ throw exceptions::socket_exception(msg);
+}
+
//
diff --git a/vmime/exception.hpp b/vmime/exception.hpp
index c09e8919..55d4c480 100644
--- a/vmime/exception.hpp
+++ b/vmime/exception.hpp
@@ -359,11 +359,27 @@ public:
typedef net_exception messaging_exception;
+/** Socket error.
+ */
+
+class socket_exception : public net_exception
+{
+public:
+
+ socket_exception(const string& what = "", const exception& other = NO_EXCEPTION);
+ ~socket_exception() throw();
+
+ exception* clone() const;
+ const char* name() const throw();
+
+};
+
+
/** Error while connecting to the server: this may be a DNS resolution error
* or a connection error (for example, time-out while connecting).
*/
-class connection_error : public net_exception
+class connection_error : public socket_exception
{
public:
diff --git a/vmime/platforms/posix/posixSocket.hpp b/vmime/platforms/posix/posixSocket.hpp
index 93315cf9..fea46abd 100644
--- a/vmime/platforms/posix/posixSocket.hpp
+++ b/vmime/platforms/posix/posixSocket.hpp
@@ -49,6 +49,10 @@ public:
void send(const vmime::string& buffer);
void sendRaw(const char* buffer, const int count);
+protected:
+
+ static void throwSocketError(const int err);
+
private:
char m_buffer[65536];