# Passenger::EventedClient Class Reference

A utility class for making I/O handling in non-blocking libev evented servers much easier. More...

`#include <EventedClient.h>`

Inherited by Passenger::EventedMessageClient.

List of all members.

## Public Types
enum | { DISCONNECT_FULL, DISCONNECT_WRITE }
| Controls what to do when a write error is encountered. More...
## Public Member Functions
| EventedClient (struct ev_loop *loop, const FileDescriptor &_fd)
| Creates a new EventedClient with the given libev loop and file descriptor.
void | ref ()
| Increase reference count.
void | unref ()
| Decrease reference count.
bool | ioAllowed () const
| Returns whether it is allowed to perform some kind of I/O with this client, either reading or writing.
bool | writeAllowed () const
| Returns whether it is allowed to write data to the client.
bool | readWatcherActive () const
| Used by unit tests.
size_t | pendingWrites () const
| Returns the number of bytes that are scheduled to be sent to the client at a later time.
void | notifyReads (bool enable)
| Sets whether you're interested in read events.
void | setOutboxLimit (unsigned int size)
| Sets a limit on the client outbox.
void | write (const StaticString data[], unsigned int count)
| Sends data to this client.
void | closeWrite ()
| Close only the writer side of the client connection.
void | disconnect (bool force=false)
| Disconnects the client.
FileDescriptor | detach ()
| Detaches the client file descriptor so that this EventedClient no longer has any control over it.
## Public Attributes
FileDescriptor | fd
| The client's file descriptor.
enum Passenger::EventedClient:: { ... } | writeErrorAction
| Controls what to do when a write error is encountered.
Callback | onReadable
| Called when the file descriptor becomes readable and read notifications are enabled (see `notifyRead()`).
Callback | onDisconnect
| Called when the client is disconnected.
Callback | onDetach
| Called when `detach()` is called for the first time.
Callback | onPendingDataFlushed
| Called after all pending outgoing data have been written out.
SystemErrorCallback | onSystemError
| System call errors are reported with this callback.
void * | userData
| EventedClient doesn't do anything with this.

## Detailed Description

A utility class for making I/O handling in non-blocking libev evented servers much easier.

- An EventedClient is associated with a reference counted file descriptor.
- It contains connection state information (i.e. whether the connection is established or closed). Callbacks are provided for watching connection state changes (e.g. `onDisconnect`).
- It provides reference counting features for simpler memory management (`ref()` and `unref()`).
- It installs input and output readiness watchers that are unregistered when the EventedClient is destroyed. One can hook into input readiness watcher with the `onReadable` callback.
- Makes zero-copy writes easy. The `write()` method accepts an array of buffers. Whenever possible, all of these buffers are written out in the given order, using a single system call, without copying them into a single temporary buffer.
- Makes non-blocking writes easy. Normally a write() system call on a non-blocking socket can fail with EAGAIN if the socket send buffer is full. EventedClient schedules the data to be sent later when the socket is writable again. It automatically integrates into the main loop in order to do this. This allows one to have write operations occur concurrently with read operations. In case too many scheduled writes are being piled up, EventedClient is smart enough to temporarily disable read notifications and wait until everything is written out before enabling read notifications again. The definition of "too many" is customizable (`setOutboxLimit()`).
- EventedClient's `disconnect` method respects pending writes. It will disconnect after all pending outgoing data have been written out.

## Basic usage

Construct an EventedClient with a libev loop and a file descriptor:

     EventedClient *client = new EventedClient(loop, fd);

You are probably interested in read readiness notifications on `fd`. However these notifications are disabled by default. You need to set the `onReadable` callback (which is called every time the fd is readable) and enable read notifications.

     void onReadable(EventedClient *client) {
         // do whatever you want
     }

     ...
     client->onReadable = onReadable;
     client->notifyReads(true);

## Error handling

EventedClient never raises exceptions, except when your callbacks do. It reports errors with the `onSystemError` callback. That said, EventedClient is exception-aware and will ensure that its internal state stays consistent even when your callbacks throw exceptions.

## Member Enumeration Documentation

anonymous enum

Controls what to do when a write error is encountered.

Enumerator:

  DISCONNECT_FULL | Forcefully disconnect the client.
  DISCONNECT_WRITE | Close the writer side of the connection, but continue allowing reading.

## Constructor & Destructor Documentation

Passenger::EventedClient::EventedClient | ( | struct ev_loop * | loop,
|  | const FileDescriptor & | _fd |
| ) |  |  | `[inline]`

Creates a new EventedClient with the given libev loop and file descriptor.

The initial reference count is 1.

## Member Function Documentation

void Passenger::EventedClient::closeWrite | ( |  | ) | `[inline]`

Close only the writer side of the client connection.

After calling this method, subsequent write() calls won't do anything anymore. Any pending outgoing data will be sent out whenever the opportunity arises.

This function does nothing if the client is being disconnected, already disconnected or if only the writer side is closed.

FileDescriptor Passenger::EventedClient::detach | ( |  | ) | `[inline]`

Detaches the client file descriptor so that this EventedClient no longer has any control over it.

Any EventedClient I/O watchers on the client file descriptor will be stopped and further I/O on the file descriptor via EventedClient will become impossible. Any pending outgoing data will be discarded. The original client file descriptor is returned and `onDetach` is called. Subsequent calls to this function will return -1 and will no longer call `onDetach`.

Postcondition:
  !ioAllowed()
  fd == -1

void Passenger::EventedClient::disconnect | ( | bool | force = `false` | ) | `[inline]`

Disconnects the client.

This actually closes the underlying file descriptor, even if the FileDescriptor object still has references.

If force is true then the client will be disconnected immediately, and any pending outgoing data will be discarded. Otherwise the client will be disconnected after all pending outgoing data have been sent; in the mean time no new data can be received from or sent to the client.

After the client has actually been disconnected (which may be either immediately or after a short period of time), a disconnect event will be emitted.

If the client connection has already been closed then this method does nothing. If the client connection is being closed (because there's pending outgoing data) then the behavior depends on the `force` argument: if true then the connection is closed immediately and the pending data is discarded, otherwise this method does nothing.

The `onDisconnect` callback will be called after the file descriptor is closed, which is either immediately or after all pending data has been sent out.

bool Passenger::EventedClient::ioAllowed | ( |  | ) | const`[inline]`

Returns whether it is allowed to perform some kind of I/O with this client, either reading or writing.

Usually true, and false when the client is either being disconnected or has been disconnected. A return value of false indicates that `fd` might be -1, but even when it isn't -1 you shouldn't access `fd` anymore. When the connection is half-closed (e.g. after closeWrite() has been called) the return value is still be true. Only when I/O of any kind is disallowed will this function return false.

void Passenger::EventedClient::notifyReads | ( | bool | enable | ) | `[inline]`

Sets whether you're interested in read events.

This will start or stop the input readiness watcher appropriately according to the current state.

If the client connection is already being closed or has already been closed then this method does nothing.

size_t Passenger::EventedClient::pendingWrites | ( |  | ) | const`[inline]`

Returns the number of bytes that are scheduled to be sent to the client at a later time.

See also:
  write()

bool Passenger::EventedClient::readWatcherActive | ( |  | ) | const`[inline]`

Used by unit tests.

void Passenger::EventedClient::setOutboxLimit | ( | unsigned int | size | ) | `[inline]`

Sets a limit on the client outbox.

The outbox is where data is stored that could not be immediately sent to the client, e.g. because of network congestion. Whenver the outbox's size grows past this limit, EventedClient will enter a state in which it will stop listening for read events and instead concentrate on sending out all pending data.

Setting this to 0 means that the outbox has an unlimited size. Please note however that this also means that the outbox's memory could grow unbounded if the client is too slow at receiving data.

The default value is some non-zero value.

If the client connection is already being closed or has already been closed then this method does nothing.

void Passenger::EventedClient::unref | ( |  | ) | `[inline]`

Decrease reference count.

Upon reaching 0, this EventedClient object will be destroyed.

void Passenger::EventedClient::write | ( | const StaticString | data[],
|  | unsigned int | count |
| ) |  |  | `[inline]`

Sends data to this client.

This method will try to send the data immediately (in which no intermediate copies of the data will be made), but if the client is not yet ready to receive data (e.g. because of network congestion) then the data will be buffered and scheduled for sending later.

If an I/O error was encountered then the action taken depends on the value of writeActionError. By default it is DISCONNECT_FULL, meaning the client connection will be closed by calling `disconnect(true)`. This means this method could potentially call the `onDisconnect` callback.

If the client connection is already being closed, has already been closed or if the writer side is closed, then this method does nothing.

The `onPendingDataFlushed` callback will be called after this data and whatever existing pending data have been written out. That may either be immediately or after a short period of of time.

bool Passenger::EventedClient::writeAllowed | ( |  | ) | const`[inline]`

Returns whether it is allowed to write data to the client.

Usually true, and false when the client is either being disconnected or has been disconnected or when the writer side of the client connection has been closed. write() will do nothing if this function returns false.

## Member Data Documentation

FileDescriptor Passenger::EventedClient::fd

The client's file descriptor.

Could be -1: see `ioAllowed()`.

Callback Passenger::EventedClient::onDisconnect

Called when the client is disconnected.

This happens either immediately when `disconnect()` is called, or a short amount of time later. See the documentation for that function for details.

Please note that destroying an EventedClient object does *not* cause this callback to be called.

Callback Passenger::EventedClient::onPendingDataFlushed

Called after all pending outgoing data have been written out.

If `write()` can be completed immediately without scheduling data for later, then `write()` will call this callback immediately after writing.

Callback Passenger::EventedClient::onReadable

Called when the file descriptor becomes readable and read notifications are enabled (see `notifyRead()`).

When there's too much pending outgoing data, readability notifications are temporarily disabled; see `write()` for details.

void* Passenger::EventedClient::userData

EventedClient doesn't do anything with this.

Set it to whatever you want.

enum { ... } Passenger::EventedClient::writeErrorAction

Controls what to do when a write error is encountered.

The documentation for this class was generated from the following file:

- EventedClient.h