A utility class for making I/O handling in non-blocking libev evented servers much easier. More...
#include <EventedClient.h>
Inherited by Passenger::EventedMessageClient.
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. |
A utility class for making I/O handling in non-blocking libev evented servers much easier.
onDisconnect
).ref()
and unref()
).onReadable
callback.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.setOutboxLimit()
).disconnect
method respects pending writes. It will disconnect after all pending outgoing data have been written out.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);
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.
anonymous enum |
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.
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
.
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.
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.
The client's file descriptor.
Could be -1: see ioAllowed()
.
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.
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.
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.