/** * @brief std::system_error plus the name of what was being * attempted. * */ classtagged_error : public std::system_error { private: std::string attempt_and_error; //!< what was attempted, and what happened
public: /** * @brief Construct from a category, an attempt, and an error code. * * @param[in] category is the category of error * @param[in] attempt is what was supposed to happen * @param[in] error_code is the resulting error */ tagged_error(conststd::error_category &category, conststd::string &attempt, constint error_code) : std::system_error{error_code, category}, attempt_and_error{attempt + ": " + std::system_error::what()} {}
/** * @brief Returns a C string describing the error * */ constchar *what()const noexcept override { return attempt_and_error.c_str(); } };
/** * @brief A tagged_error for syscalls * */ classunix_error : public tagged_error { public: /** * @brief Construct from a syscall name and the resulting errno * * @param[in] attempt is the name of the syscall attempted * @param[in] error is the [errno(3)](\ref man3::errno) that resulted */ explicit unix_error(conststd::string &attempt, constint error = errno) : tagged_error{std::system_category(), attempt, error} {} };
/** * @brief Error-checking wrapper for most syscalls * */ intSystemCall(constchar *attempt, constint return_value, constint errno_mask = 0);
/** * @brief Version of SystemCall that takes a C++ std::string * */ intSystemCall(conststd::string &attempt, constint return_value, constint errno_mask = 0);
// miniSMTPServer/util/socket.hpp classFileDescriptor { /** * @brief A handle on a kernel file descriptor. * * @details FileDescriptor objects contain a std::shared_ptr to a FDWrapper. */ classFDWrapper { public: int fd; //!< The file descriptor number returned by the kernel bool eof = false; //!< Flag indicating whether FDWrapper::_fd is at EOF bool closed = false; //!< Flag indicating whether FDWrapper::_fd has been closed
/** * @brief Construct from a file descriptor number returned by the kernel * */ explicitFDWrapper(constint fd); /** * @brief Closes the file descriptor upon destruction * */ ~FDWrapper(); /** * @brief Calls [close(2)](\ref man2::close) on FDWrapper::fd * */ voidclose();
//! A reference-counted handle to a shared FDWrapper std::shared_ptr<FDWrapper> internal_fd;
// private constructor used to duplicate the FileDescriptor (increase the reference count) explicitFileDescriptor(std::shared_ptr<FDWrapper> other_shared_ptr);
public: //! Construct from a file descriptor number returned by the kernel explicitFileDescriptor(constint fd);
//! Free the std::shared_ptr; the FDWrapper destructor calls close() when the refcount goes to zero. ~FileDescriptor() = default;
//! Read up to `limit` bytes std::string read(constsize_t limit = std::numeric_limits<size_t>::max());
//! Read up to `limit` bytes into `str` (caller can allocate storage) voidread(std::string &str, constsize_t limit = std::numeric_limits<size_t>::max());
//! Write a string, possibly blocking until all is written size_twrite(constchar *str);
//! Write a string, possibly blocking until all is written size_twrite(const std::string &str);
//! Close the underlying file descriptor voidclose(){ internal_fd->close(); }
//! Copy a FileDescriptor explicitly, increasing the FDWrapper refcount FileDescriptor duplicate()const;
while (true) { s.read(result); if (result.size() == 0) { std::cout << "S: Connection lost\n"; s.close(); break; } s.write("Hello, this is the server\n"); } }