deluge/include/libtorrent/asio/error.hpp

388 lines
10 KiB
C++
Raw Normal View History

2007-01-07 22:50:11 +00:00
//
// error.hpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_ERROR_HPP
#define ASIO_ERROR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include <boost/scoped_ptr.hpp>
#include <cerrno>
#include <cstring>
#include <exception>
#include <string>
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
# include <iostream>
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
#include "asio/detail/pop_options.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/win_local_free_on_block_exit.hpp"
namespace asio {
#if defined(GENERATING_DOCUMENTATION)
/// INTERNAL ONLY.
# define ASIO_SOCKET_ERROR(e) implementation_defined
/// INTERNAL ONLY.
# define ASIO_NETDB_ERROR(e) implementation_defined
/// INTERNAL ONLY.
# define ASIO_GETADDRINFO_ERROR(e) implementation_defined
/// INTERNAL ONLY.
# define ASIO_OS_ERROR(e_win, e_posix) implementation_defined
#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
# define ASIO_SOCKET_ERROR(e) WSA ## e
# define ASIO_NETDB_ERROR(e) WSA ## e
# define ASIO_GETADDRINFO_ERROR(e) e
# define ASIO_OS_ERROR(e_win, e_posix) e_win
#else
# define ASIO_SOCKET_ERROR(e) e
# define ASIO_NETDB_ERROR(e) 16384 + e
# define ASIO_GETADDRINFO_ERROR(e) 32768 + e
# define ASIO_OS_ERROR(e_win, e_posix) e_posix
#endif
/// The error class is used to encapsulate system error codes.
class error
: public std::exception
{
public:
/// Error codes.
enum code_type
{
/// Permission denied.
access_denied = ASIO_SOCKET_ERROR(EACCES),
/// Address family not supported by protocol.
address_family_not_supported = ASIO_SOCKET_ERROR(EAFNOSUPPORT),
/// Address already in use.
address_in_use = ASIO_SOCKET_ERROR(EADDRINUSE),
/// Transport endpoint is already connected.
already_connected = ASIO_SOCKET_ERROR(EISCONN),
/// Operation already in progress.
already_started = ASIO_SOCKET_ERROR(EALREADY),
/// A connection has been aborted.
connection_aborted = ASIO_SOCKET_ERROR(ECONNABORTED),
/// Connection refused.
connection_refused = ASIO_SOCKET_ERROR(ECONNREFUSED),
/// Connection reset by peer.
connection_reset = ASIO_SOCKET_ERROR(ECONNRESET),
/// Bad file descriptor.
bad_descriptor = ASIO_SOCKET_ERROR(EBADF),
/// End of file or stream.
eof = ASIO_OS_ERROR(ERROR_HANDLE_EOF, -1),
/// Bad address.
fault = ASIO_SOCKET_ERROR(EFAULT),
/// Host not found (authoritative).
host_not_found = ASIO_NETDB_ERROR(HOST_NOT_FOUND),
/// Host not found (non-authoritative).
host_not_found_try_again = ASIO_NETDB_ERROR(TRY_AGAIN),
/// No route to host.
host_unreachable = ASIO_SOCKET_ERROR(EHOSTUNREACH),
/// Operation now in progress.
in_progress = ASIO_SOCKET_ERROR(EINPROGRESS),
/// Interrupted system call.
interrupted = ASIO_SOCKET_ERROR(EINTR),
/// Invalid argument.
invalid_argument = ASIO_SOCKET_ERROR(EINVAL),
/// Message too long.
message_size = ASIO_SOCKET_ERROR(EMSGSIZE),
/// Network is down.
network_down = ASIO_SOCKET_ERROR(ENETDOWN),
/// Network dropped connection on reset.
network_reset = ASIO_SOCKET_ERROR(ENETRESET),
/// Network is unreachable.
network_unreachable = ASIO_SOCKET_ERROR(ENETUNREACH),
/// Too many open files.
no_descriptors = ASIO_SOCKET_ERROR(EMFILE),
/// No buffer space available.
no_buffer_space = ASIO_SOCKET_ERROR(ENOBUFS),
/// The query is valid but does not have associated address data.
no_data = ASIO_NETDB_ERROR(NO_DATA),
/// Cannot allocate memory.
no_memory = ASIO_OS_ERROR(ERROR_OUTOFMEMORY, ENOMEM),
/// Operation not permitted.
no_permission = ASIO_OS_ERROR(ERROR_ACCESS_DENIED, EPERM),
/// Protocol not available.
no_protocol_option = ASIO_SOCKET_ERROR(ENOPROTOOPT),
/// A non-recoverable error occurred.
no_recovery = ASIO_NETDB_ERROR(NO_RECOVERY),
/// Transport endpoint is not connected.
not_connected = ASIO_SOCKET_ERROR(ENOTCONN),
/// Socket operation on non-socket.
not_socket = ASIO_SOCKET_ERROR(ENOTSOCK),
/// Operation not supported.
not_supported = ASIO_SOCKET_ERROR(EOPNOTSUPP),
/// Operation cancelled.
operation_aborted = ASIO_OS_ERROR(ERROR_OPERATION_ABORTED, ECANCELED),
/// The service is not supported for the given socket type.
service_not_found = ASIO_OS_ERROR(
WSATYPE_NOT_FOUND,
ASIO_GETADDRINFO_ERROR(EAI_SERVICE)),
/// The socket type is not supported.
socket_type_not_supported = ASIO_OS_ERROR(
WSAESOCKTNOSUPPORT,
ASIO_GETADDRINFO_ERROR(EAI_SOCKTYPE)),
/// Cannot send after transport endpoint shutdown.
shut_down = ASIO_SOCKET_ERROR(ESHUTDOWN),
/// Success.
success = 0,
/// Connection timed out.
timed_out = ASIO_SOCKET_ERROR(ETIMEDOUT),
/// Resource temporarily unavailable.
try_again = ASIO_OS_ERROR(ERROR_RETRY, EAGAIN),
/// The socket is marked non-blocking and the requested operation would
/// block.
would_block = ASIO_SOCKET_ERROR(EWOULDBLOCK)
};
/// Default constructor.
error()
: code_(success)
{
}
/// Construct with a specific error code.
error(int code)
: code_(code)
{
}
/// Copy constructor.
error(const error& e)
: std::exception(e),
code_(e.code_)
{
}
/// Destructor.
virtual ~error() throw ()
{
}
/// Assignment operator.
error& operator=(const error& e)
{
code_ = e.code_;
what_.reset();
return *this;
}
/// Get a string representation of the exception.
virtual const char* what() const throw ()
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
try
{
if (!what_)
{
char* msg = 0;
DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS, 0, code_,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0);
detail::win_local_free_on_block_exit local_free_obj(msg);
if (length && msg[length - 1] == '\n')
msg[--length] = '\0';
if (length && msg[length - 1] == '\r')
msg[--length] = '\0';
if (length)
what_.reset(new std::string(msg));
else
return "asio error";
}
return what_->c_str();
}
catch (std::exception&)
{
return "asio error";
}
#else // defined(BOOST_WINDOWS)
switch (code_)
{
case error::eof:
return "End of file.";
case error::host_not_found:
return "Host not found (authoritative).";
case error::host_not_found_try_again:
return "Host not found (non-authoritative), try again later.";
case error::no_recovery:
return "A non-recoverable error occurred during database lookup.";
case error::no_data:
return "The query is valid, but it does not have associated data.";
#if !defined(__sun)
case error::operation_aborted:
return "Operation aborted.";
#endif // !defined(__sun)
case error::service_not_found:
return "Service not found.";
case error::socket_type_not_supported:
return "Socket type not supported.";
default:
#if defined(__sun) || defined(__QNX__)
return strerror(code_);
#elif defined(__MACH__) && defined(__APPLE__) \
|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
try
{
char buf[256] = "";
strerror_r(code_, buf, sizeof(buf));
what_.reset(new std::string(buf));
return what_->c_str();
}
catch (std::exception&)
{
return "asio error";
}
#else
try
{
char buf[256] = "";
what_.reset(new std::string(strerror_r(code_, buf, sizeof(buf))));
return what_->c_str();
}
catch (std::exception&)
{
return "asio error";
}
#endif
}
#endif // defined(BOOST_WINDOWS)
}
/// Get the code associated with the error.
int code() const
{
return code_;
}
struct unspecified_bool_type_t
{
};
typedef unspecified_bool_type_t* unspecified_bool_type;
/// Operator returns non-null if there is a non-success error code.
operator unspecified_bool_type() const
{
if (code_ == success)
return 0;
else
return reinterpret_cast<unspecified_bool_type>(1);
}
/// Operator to test if the error represents success.
bool operator!() const
{
return code_ == success;
}
/// Equality operator to compare two error objects.
friend bool operator==(const error& e1, const error& e2)
{
return e1.code_ == e2.code_;
}
/// Inequality operator to compare two error objects.
friend bool operator!=(const error& e1, const error& e2)
{
return e1.code_ != e2.code_;
}
private:
// The code associated with the error.
int code_;
// The string representation of the error.
mutable boost::scoped_ptr<std::string> what_;
};
/// Output the string associated with an error.
/**
* Used to output a human-readable string that is associated with an error.
*
* @param os The output stream to which the string will be written.
*
* @param e The error to be written.
*
* @return The output stream.
*
* @relates asio::error
*/
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
std::ostream& operator<<(std::ostream& os, const error& e)
{
os << e.what();
return os;
}
#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
template <typename Ostream>
Ostream& operator<<(Ostream& os, const error& e)
{
os << e.what();
return os;
}
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
} // namespace asio
#undef ASIO_SOCKET_ERROR
#undef ASIO_NETDB_ERROR
#undef ASIO_GETADDRINFO_ERROR
#undef ASIO_OS_ERROR
#include "asio/detail/pop_options.hpp"
#endif // ASIO_ERROR_HPP