// // 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 BOOST_ASIO_ERROR_HPP #define BOOST_ASIO_ERROR_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include #include #include #include #include #include #include #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) # include #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) #include #include #include namespace boost { namespace asio { #if defined(GENERATING_DOCUMENTATION) /// INTERNAL ONLY. # define BOOST_ASIO_SOCKET_ERROR(e) implementation_defined /// INTERNAL ONLY. # define BOOST_ASIO_NETDB_ERROR(e) implementation_defined /// INTERNAL ONLY. # define BOOST_ASIO_GETADDRINFO_ERROR(e) implementation_defined /// INTERNAL ONLY. # define BOOST_ASIO_OS_ERROR(e_win, e_posix) implementation_defined #elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) # define BOOST_ASIO_SOCKET_ERROR(e) WSA ## e # define BOOST_ASIO_NETDB_ERROR(e) WSA ## e # define BOOST_ASIO_GETADDRINFO_ERROR(e) e # define BOOST_ASIO_OS_ERROR(e_win, e_posix) e_win #else # define BOOST_ASIO_SOCKET_ERROR(e) e # define BOOST_ASIO_NETDB_ERROR(e) 16384 + e # define BOOST_ASIO_GETADDRINFO_ERROR(e) 32768 + e # define BOOST_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 = BOOST_ASIO_SOCKET_ERROR(EACCES), /// Address family not supported by protocol. address_family_not_supported = BOOST_ASIO_SOCKET_ERROR(EAFNOSUPPORT), /// Address already in use. address_in_use = BOOST_ASIO_SOCKET_ERROR(EADDRINUSE), /// Transport endpoint is already connected. already_connected = BOOST_ASIO_SOCKET_ERROR(EISCONN), /// Operation already in progress. already_started = BOOST_ASIO_SOCKET_ERROR(EALREADY), /// A connection has been aborted. connection_aborted = BOOST_ASIO_SOCKET_ERROR(ECONNABORTED), /// Connection refused. connection_refused = BOOST_ASIO_SOCKET_ERROR(ECONNREFUSED), /// Connection reset by peer. connection_reset = BOOST_ASIO_SOCKET_ERROR(ECONNRESET), /// Bad file descriptor. bad_descriptor = BOOST_ASIO_SOCKET_ERROR(EBADF), /// End of file or stream. eof = BOOST_ASIO_OS_ERROR(ERROR_HANDLE_EOF, -1), /// Bad address. fault = BOOST_ASIO_SOCKET_ERROR(EFAULT), /// Host not found (authoritative). host_not_found = BOOST_ASIO_NETDB_ERROR(HOST_NOT_FOUND), /// Host not found (non-authoritative). host_not_found_try_again = BOOST_ASIO_NETDB_ERROR(TRY_AGAIN), /// No route to host. host_unreachable = BOOST_ASIO_SOCKET_ERROR(EHOSTUNREACH), /// Operation now in progress. in_progress = BOOST_ASIO_SOCKET_ERROR(EINPROGRESS), /// Interrupted system call. interrupted = BOOST_ASIO_SOCKET_ERROR(EINTR), /// Invalid argument. invalid_argument = BOOST_ASIO_SOCKET_ERROR(EINVAL), /// Message too long. message_size = BOOST_ASIO_SOCKET_ERROR(EMSGSIZE), /// Network is down. network_down = BOOST_ASIO_SOCKET_ERROR(ENETDOWN), /// Network dropped connection on reset. network_reset = BOOST_ASIO_SOCKET_ERROR(ENETRESET), /// Network is unreachable. network_unreachable = BOOST_ASIO_SOCKET_ERROR(ENETUNREACH), /// Too many open files. no_descriptors = BOOST_ASIO_SOCKET_ERROR(EMFILE), /// No buffer space available. no_buffer_space = BOOST_ASIO_SOCKET_ERROR(ENOBUFS), /// The query is valid but does not have associated address data. no_data = BOOST_ASIO_NETDB_ERROR(NO_DATA), /// Cannot allocate memory. no_memory = BOOST_ASIO_OS_ERROR(ERROR_OUTOFMEMORY, ENOMEM), /// Operation not permitted. no_permission = BOOST_ASIO_OS_ERROR(ERROR_ACCESS_DENIED, EPERM), /// Protocol not available. no_protocol_option = BOOST_ASIO_SOCKET_ERROR(ENOPROTOOPT), /// A non-recoverable error occurred. no_recovery = BOOST_ASIO_NETDB_ERROR(NO_RECOVERY), /// Transport endpoint is not connected. not_connected = BOOST_ASIO_SOCKET_ERROR(ENOTCONN), /// Socket operation on non-socket. not_socket = BOOST_ASIO_SOCKET_ERROR(ENOTSOCK), /// Operation not supported. not_supported = BOOST_ASIO_SOCKET_ERROR(EOPNOTSUPP), /// Operation cancelled. operation_aborted = BOOST_ASIO_OS_ERROR(ERROR_OPERATION_ABORTED, ECANCELED), /// The service is not supported for the given socket type. service_not_found = BOOST_ASIO_OS_ERROR( WSATYPE_NOT_FOUND, BOOST_ASIO_GETADDRINFO_ERROR(EAI_SERVICE)), /// The socket type is not supported. socket_type_not_supported = BOOST_ASIO_OS_ERROR( WSAESOCKTNOSUPPORT, BOOST_ASIO_GETADDRINFO_ERROR(EAI_SOCKTYPE)), /// Cannot send after transport endpoint shutdown. shut_down = BOOST_ASIO_SOCKET_ERROR(ESHUTDOWN), /// Success. success = 0, /// Connection timed out. timed_out = BOOST_ASIO_SOCKET_ERROR(ETIMEDOUT), /// Resource temporarily unavailable. try_again = BOOST_ASIO_OS_ERROR(ERROR_RETRY, EAGAIN), /// The socket is marked non-blocking and the requested operation would /// block. would_block = BOOST_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__) 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(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 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 boost::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 Ostream& operator<<(Ostream& os, const error& e) { os << e.what(); return os; } #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) } // namespace asio } // namespace boost #undef BOOST_ASIO_SOCKET_ERROR #undef BOOST_ASIO_NETDB_ERROR #undef BOOST_ASIO_GETADDRINFO_ERROR #undef BOOST_ASIO_OS_ERROR #include #endif // BOOST_ASIO_ERROR_HPP