ext/common/Utils/IOUtils.h in passenger-3.0.0 vs ext/common/Utils/IOUtils.h in passenger-3.0.1

- old
+ new

@@ -28,11 +28,12 @@ #include <sys/types.h> #include <sys/uio.h> #include <unistd.h> #include <string> #include <vector> -#include "../StaticString.h" +#include <StaticString.h> +#include <FileDescriptor.h> namespace Passenger { using namespace std; @@ -91,10 +92,16 @@ * @ingroup Support */ void setNonBlocking(int fd); /** + * Try to call the Linux accept4() system call. If the system call is + * not available, then -1 is returned and errno is set to ENOSYS. + */ +int callAccept4(int sock, struct sockaddr *addr, socklen_t *addr_len, int options); + +/** * Resolves the given host name and returns a list of IP addresses. * <em>hostname</em> may also be an IP address, in which case it is * returned. You may explicitly specify a <em>port</em> as a hint to * the DNS resolver; set to 0 if you don't care or can't provide a * port number. @@ -192,10 +199,111 @@ * @ingroup Support */ int connectToTcpServer(const StaticString &hostname, unsigned int port); /** + * Creates a Unix domain socket pair. + * + * @throws SystemException + * @throws boost::thread_interrupted + */ +SocketPair createUnixSocketPair(); + +/** + * Creates a pipe. + * + * @throws SystemException + * @throws boost::thread_interrupted + */ +Pipe createPipe(); + +/** + * Waits at most <tt>*timeout</tt> microseconds for the file descriptor to become readable. + * Returns true if it become readable within the timeout, false if the timeout expired. + * + * <tt>*timeout</tt> may be 0, in which case this method will check whether the file + * descriptor is readable, and immediately returns without waiting. + * + * If no exception is thrown, this method deducts the number of microseconds that has + * passed from <tt>*timeout</tt>. + * + * @throws SystemException + * @throws boost::thread_interrupted + */ +bool waitUntilReadable(int fd, unsigned long long *timeout); + +/** + * Waits at most <tt>*timeout</tt> microseconds for the file descriptor to become writable. + * Returns true if it become writable within the timeout, false if the timeout expired. + * + * <tt>*timeout</tt> may be 0, in which case this method will check whether the file + * descriptor is writable, and immediately returns without waiting. + * + * If no exception is thrown, this method deducts the number of microseconds that has + * passed from <tt>*timeout</tt>. + * + * @throws SystemException + * @throws boost::thread_interrupted + */ +bool waitUntilWritable(int fd, unsigned long long *timeout); + +/** + * Attempts to read exactly <tt>size</tt> bytes of data from the given file + * descriptor, and put the result in <tt>buf</tt>. On non-blocking sockets + * this function will block by poll()ing the socket. + * + * @param buf The buffer to place the read data in. This buffer must be at least + * <tt>size</tt> bytes long. + * @param size The number of bytes to read. + * @param timeout A pointer to an integer, which specifies the maximum number of + * microseconds that may be spent on reading the <tt>size</tt> bytes + * of data. If the timeout expired then TimeoutException will be + * thrown. + * If this function returns without throwing an exception, then the + * total number of microseconds spent on reading will be deducted + * from <tt>timeout</tt>. + * Pass NULL if you do not want to enforce a timeout. + * @return The number of bytes read. This is exactly equal to <em>size</em>, + * except when EOF is encountered prematurely. + * @pre buf != NULL + * @throws SystemException + * @throws TimeoutException Unable to read <tt>size</tt> bytes of data within + * <tt>timeout</tt> microseconds. + * @throws boost::thread_interrupted + */ +unsigned int readExact(int fd, void *buf, unsigned int size, unsigned long long *timeout = NULL); + +/** + * Writes a block of data to the given file descriptor and blocks until everything + * is written, even for non-blocking sockets. If not everything can be written (e.g. + * because the peer closed the connection before accepting everything) then an + * exception will be thrown. + * + * @note Security guarantee: this method will not copy the data in memory, + * so it's safe to use this method to write passwords to the underlying + * file descriptor. + * + * @param data The data to send. + * @param size The number of bytes in <tt>data</tt>. + * @param timeout A pointer to an integer, which specifies the maximum number of + * microseconds that may be spent on writing the <tt>size</tt> bytes + * of data. If the timeout expired then TimeoutException will be + * thrown. + * If this function returns without throwing an exception, then the + * total number of microseconds spent on writing will be deducted + * from <tt>timeout</tt>. + * Pass NULL if you do not want to enforce a timeout. + * @pre data != NULL + * @throws SystemException + * @throws TimeoutException Unable to write <tt>size</tt> bytes of data within + * <tt>timeout</tt> microseconds. + * @throws boost::thread_interrupted + */ +void writeExact(int fd, const void *data, unsigned int size, unsigned long long *timeout = NULL); +void writeExact(int fd, const StaticString &data, unsigned long long *timeout = NULL); + +/** * Writes a bunch of data to the given file descriptor using a gathering I/O interface. * Instead of accepting a single buffer, this function accepts multiple buffers plus * a special 'rest' buffer. The rest buffer is written out first, and the data buffers * are then written out in the order as they appear. This all is done with a single * writev() system call without concatenating all data into a single buffer. @@ -245,9 +353,18 @@ /** * Sets a writev-emulating function that gatheredWrite() should call instead of the real writev(). * Useful for unit tests. Pass NULL to restore back to the real writev(). */ void setWritevFunction(WritevFunction func); + +/** + * Closes the given file descriptor and throws an exception if anything goes wrong. + * This function also works around certain close() bugs on certain operating systems. + * + * @throws SystemException + * @throws boost::thread_interrupted + */ +void safelyClose(int fd); } // namespace Passenger #endif /* _PASSENGER_IO_UTILS_H_ */