// Copyright (c) 2002 David Muse
// See the COPYING file for more information.
#ifndef RUDIMENTS_FILEDESCRIPTOR_H
#define RUDIMENTS_FILEDESCRIPTOR_H
#include <rudiments/private/filedescriptorincludes.h>
// The filedescriptor class is a base class for other classes that utilize
// file descriptors.
#ifdef RUDIMENTS_NAMESPACE
namespace rudiments {
#endif
class listener;
class filedescriptorprivate;
class filedescriptor {
public:
filedescriptor();
// Creates an uninitialized filedescriptor.
filedescriptor(const filedescriptor &f);
filedescriptor &operator=(const filedescriptor &f);
virtual ~filedescriptor();
// Calls close() if it hasn't already been
// called.
virtual bool close();
// Closes the file descriptor.
// Returns true on success and false on failure.
int getFileDescriptor() const;
// Returns the file descriptor.
void setFileDescriptor(int filedesc);
// Sets the file descriptor associated with
// the class to "filedesc".
int duplicate() const;
// Duplicates the file descriptor and returns
// the handle of the duplicate descriptor. The
// old and new descriptors may be used
// interchangeably, they share locks, position
// pointers, flags (except the close-on-exec
// flag), etc.
//
// Returns the lowest-numbered unused descriptor
// on success or -1 on failure.
bool duplicate(int newfd) const;
// Sets file descriptor handle "newfd" to be a
// duplicate of this file descriptor. If
// "newfd" is already open, it will be closed
// first.
//
// Returns true on success and false on failure.
#ifdef RUDIMENTS_HAS_SSL
void setSSLContext(SSL_CTX *ctx);
// Associates SSL context "ctx" with the
// filedescriptor. Passing in a NULL for "ctx"
// has the additional side effect of calling
// deInitializeSSL() below.
SSL_CTX *getSSLContext();
// Returns the SSL context currently associated
// with the filedescriptor or NULL if none
// is currently associated.
bool initializeSSL();
// Should be called after calling
// setSSLContext() and one of open(),
// create() or connect() (from socket child
// classes). Causes the appropriate SSL
// function to be called instead of or in
// concert with read(), write(), connect(),
// accept() and close() methods.
//
// Returns true on success and false on failure
SSL *getSSL() const;
// Returns a pointer to the currently
// initialized SSL handle or NULL if
// initializeSSL() has not been called or
// failed.
void deInitializeSSL();
// Causes read(), write(), connect(), accept()
// and close() methods to be performed
// without the accompanying SSL-specific
// functions.
int getSSLResult() const;
// Returns the result code of the previously
// executed SSL command. If a method fails
// but errno is 0 then an SSL-related error
// occurred. You may call SSL_get_error()
// on the result of this method to determine
// the exact error.
#endif
virtual bool useNonBlockingMode() const;
// Puts the file descriptor in non-blocking
// mode. Returns true on success and false on
// failure.
virtual bool useBlockingMode() const;
// Puts the file descriptor in blocking mode.
// Returns true on success and false on
// failure.
bool isUsingNonBlockingMode() const;
// Returns true if the file descriptor is in
// non-blocking mode and false otherwise.
// Write methods - write data to the file descriptor.
// These methods return the number of bytes that were
// successfully written or RESULT_ERROR if an error occurred.
ssize_t write(uint16_t number) const;
// Write "number" to the file descriptor.
ssize_t write(uint32_t number) const;
// Write "number" to the file descriptor.
ssize_t write(uint64_t number) const;
// Write "number" to the file descriptor.
ssize_t write(int16_t number) const;
// Write "number" to the file descriptor.
ssize_t write(int32_t number) const;
// Write "number" to the file descriptor.
ssize_t write(int64_t number) const;
// Write "number" to the file descriptor.
ssize_t write(float number) const;
// Write "number" to the file descriptor.
ssize_t write(double number) const;
// Write "number" to the file descriptor.
ssize_t write(unsigned char character) const;
// Write "character" to the file descriptor.
ssize_t write(char character) const;
// Write "character" to the file descriptor.
ssize_t write(bool value) const;
// Write "value" to the file descriptor.
ssize_t write(const unsigned char *string) const;
// Write "string" to the file descriptor. Note
// that "string" must be NULL-terminated.
ssize_t write(const char *string) const;
// Write "string" to the file descriptor. Note
// that "string" must be NULL-terminated.
ssize_t write(const unsigned char *string, size_t size) const;
// Write "size" bytes from "string" to the file
// descriptor. Note that it is possible to
// write beyond the string's NULL terminator
// using this method.
ssize_t write(const char *string, size_t size) const;
// Write "size" bytes from "string" to the file
// descriptor. Note that it is possible to
// write beyond the string's NULL terminator
// using this method.
ssize_t write(const void *buffer, size_t size) const;
// Write "size" bytes from "buffer" to the file
// descriptor.
// Write methods - write data to the file descriptor with a
// timeout of "sec" seconds and "usec" microseconds.
// These methods return the number of bytes that were
// successfully written, RESULT_ERROR if an error occurred or
// RESULT_TIMEOUT if a timeout occurred.
ssize_t write(uint16_t number, long sec, long usec) const;
// Write "number" to the file descriptor.
ssize_t write(uint32_t number, long sec, long usec) const;
// Write "number" to the file descriptor.
ssize_t write(uint64_t number, long sec, long usec) const;
// Write "number" to the file descriptor.
ssize_t write(int16_t number, long sec, long usec) const;
// Write "number" to the file descriptor.
ssize_t write(int32_t number, long sec, long usec) const;
// Write "number" to the file descriptor.
ssize_t write(int64_t number, long sec, long usec) const;
// Write "number" to the file descriptor.
ssize_t write(float number, long sec, long usec) const;
// Write "number" to the file descriptor.
ssize_t write(double number, long sec, long usec) const;
// Write "number" to the file descriptor.
ssize_t write(unsigned char character,
long sec, long usec) const;
// Write "character" to the file descriptor.
ssize_t write(char character, long sec, long usec) const;
// Write "character" to the file descriptor.
ssize_t write(bool value, long sec, long usec) const;
// Write "value" to the file descriptor.
ssize_t write(const unsigned char *string,
long sec, long usec) const;
// Write "string" to the file descriptor. Note
// that "string" must be NULL-terminated.
ssize_t write(const char *string,
long sec, long usec) const;
// Write "string" to the file descriptor. Note
// that "string" must be NULL-terminated.
ssize_t write(const unsigned char *string, size_t size,
long sec, long usec) const;
// Write "size" bytes from "string" to the file
// descriptor. Note that it is possible to
// write beyond the string's NULL terminator
// using this method.
ssize_t write(const char *string, size_t size,
long sec, long usec) const;
// Write "size" bytes from "string" to the file
// descriptor. Note that it is possible to
// write beyond the string's NULL terminator
// using this method.
ssize_t write(const void *buffer, size_t size,
long sec, long usec) const;
// Write "size" bytes from "buffer" to the file
// descriptor.
// Read methods - read data from the file descriptor.
// These methods return the number of bytes that were
// successfully read or RESULT_ERROR if an error occurred.
ssize_t read(uint16_t *buffer) const;
// Reads sizeof(uint16_t) bytes
// from the file descriptor into "buffer".
ssize_t read(uint32_t *buffer) const;
// Reads sizeof(uint32_t) bytes
// from the file descriptor into "buffer".
ssize_t read(uint64_t *buffer) const;
// Reads sizeof(uint64_t) bytes
// from the file descriptor into "buffer".
ssize_t read(int16_t *buffer) const;
// Reads sizeof(int16_t) bytes
// from the file descriptor into "buffer".
ssize_t read(int32_t *buffer) const;
// Reads sizeof(int32_t) bytes
// from the file descriptor into "buffer".
ssize_t read(int64_t *buffer) const;
// Reads sizeof(int64_t) bytes
// from the file descriptor into "buffer".
ssize_t read(float *buffer) const;
// Reads sizeof(float) bytes from the file
// descriptor into "buffer".
ssize_t read(double *buffer) const;
// Reads sizeof(double) bytes from the file
// descriptor into "buffer".
ssize_t read(unsigned char *buffer) const;
// Reads sizeof(unsigned char) bytes
// from the file descriptor into "buffer".
ssize_t read(char *buffer) const;
// Reads sizeof(char) bytes from the file
// descriptor into "buffer".
ssize_t read(bool *buffer) const;
// Reads sizeof(bool) bytes from the file
// descriptor into "buffer".
ssize_t read(unsigned char *buffer, size_t size) const;
// Reads "size" bytes from the file descriptor
// into "buffer".
ssize_t read(char *buffer, size_t size) const;
// Reads "size" bytes from the file descriptor
// into "buffer".
ssize_t read(void *buf, size_t size) const;
// Reads "size" bytes from the file descriptor
// into "buffer".
ssize_t read(char **buffer, char *terminator) const;
// Reads from the file desciptor into "buffer"
// until "terminator" is encountered. Note
// that "buffer" is allocated internally and
// must be freed by the calling program.
// Read methods - read data from the file descriptor with a
// timeout of "sec" seconds and "usec" microseconds.
// These methods return the number of bytes that were
// successfully read, RESULT_ERROR if an error occurred or
// RESULT_TIMEOUT if a timeout occurred.
ssize_t read(uint16_t *buffer, long sec, long usec) const;
// Reads sizeof(uint16_t) bytes
// from the file descriptor into "buffer".
ssize_t read(uint32_t *buffer, long sec, long usec) const;
// Reads sizeof(uint32_t) bytes
// from the file descriptor into "buffer".
ssize_t read(uint64_t *buffer, long sec, long usec) const;
// Reads sizeof(uint64_t) bytes
// from the file descriptor into "buffer".
ssize_t read(int16_t *buffer, long sec, long usec) const;
// Reads sizeof(int16_t) bytes
// from the file descriptor into "buffer".
ssize_t read(int32_t *buffer, long sec, long usec) const;
// Reads sizeof(int32_t) bytes
// from the file descriptor into "buffer".
ssize_t read(int64_t *buffer, long sec, long usec) const;
// Reads sizeof(int64_t) bytes
// from the file descriptor into "buffer".
ssize_t read(float *buffer, long sec, long usec) const;
// Reads sizeof(float) bytes from the file
// descriptor into "buffer".
ssize_t read(double *buffer, long sec, long usec) const;
// Reads sizeof(double) bytes from the file
// descriptor into "buffer".
ssize_t read(unsigned char *buffer,
long sec, long usec) const;
// Reads sizeof(unsigned char) bytes
// from the file descriptor into "buffer".
ssize_t read(char *buffer, long sec, long usec) const;
// Reads sizeof(char) bytes from the file
// descriptor into "buffer".
ssize_t read(bool *buffer, long sec, long usec) const;
// Reads sizeof(bool) bytes from the
// file descriptor into "buffer".
ssize_t read(unsigned char *buffer, size_t size,
long sec, long usec) const;
// Reads "size" bytes from the file descriptor
// into "buffer".
ssize_t read(char *buffer, size_t size,
long sec, long usec) const;
// Reads "size" bytes from the file descriptor
// into "buffer".
ssize_t read(void *buf, size_t size,
long sec, long usec) const;
// Reads "size" bytes from the file descriptor
// into "buffer".
ssize_t read(char **buffer, char *terminator,
long sec, long usec) const;
// Reads from the file desciptor into "buffer"
// until "terminator" is encountered. Note
// that "buffer" is allocated internally and
// must be freed by the calling program.
// Wait methods.
int waitForNonBlockingRead(long sec, long usec) const;
// Causes the application to wait until a read()
// will proceed without blocking or until "sec"
// seconds and "usec" microseconds have elapsed.
//
// Entering -1 for either parameter causes the
// method to wait indefinitely.
//
// Entering 0 for both parameters causes the
// method to fall through immediately unless a
// data is immediately available.
//
// Returns RESULT_ERROR on error, RESULT_TIMEOUT
// on timeout and otherwise returns the number
// of file descriptors that are ready to be
// read from.
//
// This will usually be 1, indicating that the
// file descriptor represented by the class is
// ready to be read from. However, if
// useListener() has been called, it may be
// greater than 1, indicating that a set of
// file descriptors that the listener is
// listening on are all ready to be read from.
int waitForNonBlockingWrite(long sec, long usec) const;
// Causes the application to wait until a
// write() will proceed without blocking or
// until "sec" seconds and "usec" microseconds
// have elapsed.
//
// Entering -1 for either parameter causes the
// method to wait indefinitely.
//
// Entering 0 for both parameters causes the
// method to fall through immediately unless a
// data is immediately available.
//
// Returns RESULT_ERROR on error, RESULT_TIMEOUT
// on timeout and otherwise returns the number
// of file descriptors that are ready to be
// written to.
//
// This will usually be 1, indicating that the
// file descriptor represented by the class is
// ready to be written to. However, if
// useListener() has been called, it may be
// greater than 1, indicating that a set of
// file descriptors that the listener is
// listening on are all ready to be written to.
// By default, if a read or write is occurring and a signal
// interrupts it, the read or write returns with errno set to
// EINTR and must be retried. These methods override that
// behavior.
void retryInterruptedReads();
// Causes reads to automatically retry if interrupted
// by a signal.
void dontRetryInterruptedReads();
// Causes reads not to automatically retry if
// interrupted by a signal.
void retryInterruptedWrites();
// Causes writes to automatically retry if
// interrupted by a signal. This is the default.
void dontRetryInterruptedWrites();
// Causes writes not to automatically retry if
// interrupted by a signal.
void retryInterruptedWaits();
// Causes waits to automatically retry if
// interrupted by a signal. This is the default.
void dontRetryInterruptedWaits();
// Causes waits not to automatically retry if
// interrupted by a signal.
void retryInterruptedFcntl();
// Causes fcntl() to automatically retry if
// interrupted by a signal. This is the default.
void dontRetryInterruptedFcntl();
// Causes fcntl() not to automatically retry if
// interrupted by a signal.
void retryInterruptedIoctl();
// Causes ioctl() to automatically retry if
// interrupted by a signal. This is the default.
void dontRetryInterruptedIoctl();
// Causes ioctl() not to automatically retry if
// interrupted by a signal.
// By default, read() will attempt to read the specified number
// of bytes from the file descriptor, in several passes if
// necessary. No single pass will try to read more than
// SSIZE_MAX bytes. These methods override that behavior.
void allowShortReads();
// Causes a read to return the number of bytes that
// were read in a single pass from the file descriptor.
// Note that reads longer than SSIZE_MAX will always
// return SSIZE_MAX or fewer bytes. This is useful,
// for example, when reading from devices which block
// rather than returning 0 for EOF.
void dontAllowShortReads();
// Causes a read to attempt to read the specified
// number of bytes from the file descriptor, in several
// passes if necessary.
// By default, write() will attempt to write the specified
// number of bytes from the file descriptor, in several passes
// if necessary. No single pass will try to read more than
// SSIZE_MAX bytes. These methods override that behavior.
void allowShortWrites();
// Causes a write to return the number of bytes that
// were written in a single pass from the file
// descriptor. Note that writes longer than SSIZE_MAX
// will always return SSIZE_MAX or fewer bytes. This
// is useful, for example, when writing to devices
// which block rather than returning 0 for EOF.
void dontAllowShortWrites();
// Causes a write to attempt to write the specified
// number of bytes from the file descriptor, in several
// passes if necessary.
// By default, calls to waitForNonBlockingRead() and
// waitForNonBlockingWrite() will wait using the select()
// system call. These methods override that behavior.
void useListener(listener *lstnr);
// Causes calls to waitForNonBlockingRead() and
// waitForNonBlockingWrite() to in turn call
// lstnr->waitForNonBlockingRead() or
// lstnr->waitForNonBlockingWrite().
void dontUseListener();
// Causes calls to waitForNonBlockingRead() and
// waitForNonBlockingWrite() to use select().
// This is the default.
listener *getListener();
// Returns the listener set previously by useListener()
// or NULL if none has been set.
void useListenerInsideReads();
void dontUseListenerInsideReads();
// FIXME: document this
void useListenerInsideWrites();
void dontUseListenerInsideWrites();
// FIXME: document this
virtual bool passFileDescriptor(int descriptor) const;
virtual bool receiveFileDescriptor(int *descriptor) const;
void translateByteOrder();
void dontTranslateByteOrder();
int fcntl(int command, long arg) const;
int ioctl(int command, void *arg) const;
// Interfaces for performing varions miscellaneous
// operations on the file descriptor.
bool useNaglesAlgorithm();
// Causes small write()'s to be collected up and
// sent together when the buffer is full or when
// a maximum of 0.2 seconds has gone by. This is
// the default. (enables Nagle's algorithm)
//
// Returns true on success and false on failure.
bool dontUseNaglesAlgorithm();
// Causes all write()'s to be sent immediately.
// (disables Nagle's algorithm)
//
// Returns true on success and false on failure.
bool getTcpWriteBufferSize(int *size);
bool setTcpWriteBufferSize(int size);
bool getTcpReadBufferSize(int *size);
bool setTcpReadBufferSize(int size);
const char *getType() const;
char *getPeerAddress() const;
// Returns the IP address of the client at
// the other end of the connection if
// the filedescriptor is an inet socket or
// NULL otherwise.
//
// Note that the buffer for the address is
// allocated internally and must be freed by
// the calling program.
// If an application does many small writes, the overhead of
// all of those ::write() system calls can slow the application
// down substantially. To address that issue, the
// filedescriptor class can buffer data passed in to any of it's
// write() methods and only make ::write() system calls when
// the buffer is full or when it's flushed manually. Note that
// when using buffered writes, the data is not actually written
// to the file descriptor until the buffer is full or until
// it's flushed manually.
bool setWriteBufferSize(ssize_t size) const;
// Discards the current write buffer and sets
// the size of the write buffer to "size". A
// size of 0 means don't buffer writes at all.
// A size less than 0 will return false.
bool flushWriteBuffer(long sec, long usec) const;
// Causes the contents of the write buffer to
// be written to the filedescriptor immediately.
bool setReadBufferSize(ssize_t size) const;
// These methods manipulate or return the close-on-exec status
// of the file descriptor. If close-on-exec is false (the
// default), then the file descriptor will remain open across
// an execve() call, otherwise it will be closed.
bool closeOnExec();
// sets the close-on-exec status to true
bool dontCloseOnExec();
// sets the close-on-exec status to false
bool getCloseOnExec();
// Returns true if the close-on-exec status
// is set true and false otherwise.
#include <rudiments/private/filedescriptor.h>
};
#ifdef RUDIMENTS_NAMESPACE
}
#endif
#endif