/* $Header: /pjproject-0.3/pjlib/include/pj/ioqueue.h 10 10/29/05 11:29a Bennylp $ */ | |
#ifndef __PJ_IOQUEUE_H__ | |
#define __PJ_IOQUEUE_H__ | |
/** | |
* @file ioqueue.h | |
* @brief I/O Dispatching Mechanism | |
*/ | |
#include <pj/types.h> | |
PJ_BEGIN_DECL | |
/** | |
* @defgroup PJ_IO Network I/O | |
* @brief Network I/O | |
* @ingroup PJ_OS | |
* | |
* This section contains API building blocks to perform network I/O and | |
* communications. If provides: | |
* - @ref PJ_SOCK | |
*\n | |
* A highly portable socket abstraction, runs on all kind of | |
* network APIs such as standard BSD socket, Windows socket, Linux | |
* \b kernel socket, PalmOS networking API, etc. | |
* | |
* - @ref pj_addr_resolve | |
*\n | |
* Portable address resolution, which implements #pj_gethostbyname(). | |
* | |
* - @ref PJ_SOCK_SELECT | |
*\n | |
* A portable \a select() like API (#pj_sock_select()) which can be | |
* implemented with various back-ends. | |
* | |
* - @ref PJ_IOQUEUE | |
*\n | |
* Framework for dispatching network events. | |
* | |
* For more information see the modules below. | |
*/ | |
/** | |
* @defgroup PJ_IOQUEUE I/O Event Dispatching Queue | |
* @ingroup PJ_IO | |
* @{ | |
* | |
* This file provides abstraction for various event dispatching mechanisms. | |
* The interfaces for event dispatching vary alot, even in a single | |
* operating system. The abstraction here hopefully is suitable for most of | |
* the event dispatching available. | |
* | |
* Currently, the I/O Queue supports: | |
* - select(), as the common denominator, but the least efficient. | |
* - I/O Completion ports in Windows NT/2000/XP, which is the most efficient | |
* way to dispatch events in Windows NT based OSes, and most importantly, | |
* it doesn't have the limit on how many handles to monitor. And it works | |
* with files (not only sockets) as well. | |
* | |
* \section pj_ioqeuue_examples_sec Examples | |
* | |
* For some examples on how to use the I/O Queue, please see: | |
* | |
* - \ref page_pjlib_ioqueue_tcp_test | |
* - \ref page_pjlib_ioqueue_udp_test | |
* - \ref page_pjlib_ioqueue_perf_test | |
*/ | |
/** | |
* This structure describes the callbacks to be called when I/O operation | |
* completes. | |
*/ | |
typedef struct pj_ioqueue_callback | |
{ | |
/** | |
* This callback is called when #pj_ioqueue_read or #pj_ioqueue_recvfrom | |
* completes. | |
* | |
* @param key The key. | |
* @param bytes_read The size of data that has just been read. | |
*/ | |
void (*on_read_complete)(pj_ioqueue_key_t *key, pj_ssize_t bytes_read); | |
/** | |
* This callback is called when #pj_ioqueue_write or #pj_ioqueue_sendto | |
* completes. | |
* | |
* @param key The key. | |
* @param bytes_read The size of data that has just been read. | |
*/ | |
void (*on_write_complete)(pj_ioqueue_key_t *key, pj_ssize_t bytes_sent); | |
/** | |
* This callback is called when #pj_ioqueue_accept completes. | |
* | |
* @param key The key. | |
* @param sock Newly connected socket. | |
* @param status Zero if the operation completes successfully. | |
*/ | |
void (*on_accept_complete)(pj_ioqueue_key_t *key, pj_sock_t sock, | |
int status); | |
/** | |
* This callback is called when #pj_ioqueue_connect completes. | |
* | |
* @param key The key. | |
* @param status Zero if the operation completes successfully. | |
*/ | |
void (*on_connect_complete)(pj_ioqueue_key_t *key, int status); | |
} pj_ioqueue_callback; | |
/** | |
* Types of I/O Queue operation. | |
*/ | |
typedef enum pj_ioqueue_operation_e | |
{ | |
PJ_IOQUEUE_OP_NONE = 0, /**< No operation. */ | |
PJ_IOQUEUE_OP_READ = 1, /**< read() operation. */ | |
PJ_IOQUEUE_OP_RECV = 2, /**< recv() operation. */ | |
PJ_IOQUEUE_OP_RECV_FROM = 4, /**< recvfrom() operation. */ | |
PJ_IOQUEUE_OP_WRITE = 8, /**< write() operation. */ | |
PJ_IOQUEUE_OP_SEND = 16, /**< send() operation. */ | |
PJ_IOQUEUE_OP_SEND_TO = 32, /**< sendto() operation. */ | |
#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0 | |
PJ_IOQUEUE_OP_ACCEPT = 64, /**< accept() operation. */ | |
PJ_IOQUEUE_OP_CONNECT = 128, /**< connect() operation. */ | |
#endif /* PJ_HAS_TCP */ | |
} pj_ioqueue_operation_e; | |
/** | |
* Indicates that the I/O Queue should be created to handle reasonable | |
* number of threads. | |
*/ | |
#define PJ_IOQUEUE_DEFAULT_THREADS 0 | |
/** | |
* Create a new I/O Queue framework. | |
* | |
* @param pool The pool to allocate the I/O queue structure. | |
* @param max_fd The maximum number of handles to be supported, which | |
* should not exceed PJ_IOQUEUE_MAX_HANDLES. | |
* @param max_threads The maximum number of threads that are allowed to | |
* operate on a single descriptor simultaneously. If | |
* the value is zero, the framework will set it | |
* to a reasonable value. | |
* @param ioqueue Pointer to hold the newly created I/O Queue. | |
* | |
* @return PJ_SUCCESS on success. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_create( pj_pool_t *pool, | |
pj_size_t max_fd, | |
int max_threads, | |
pj_ioqueue_t **ioqueue); | |
/** | |
* Destroy the I/O queue. | |
* | |
* @param ioque The I/O Queue to be destroyed. | |
* | |
* @return PJ_SUCCESS if success. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_destroy( pj_ioqueue_t *ioque ); | |
/** | |
* Set the lock object to be used by the I/O Queue. This function can only | |
* be called right after the I/O queue is created, before any handle is | |
* registered to the I/O queue. | |
* | |
* Initially the I/O queue is created with non-recursive mutex protection. | |
* Applications can supply alternative lock to be used by calling this | |
* function. | |
* | |
* @param ioque The ioqueue instance. | |
* @param lock The lock to be used by the ioqueue. | |
* @param auto_delete In non-zero, the lock will be deleted by the ioqueue. | |
* | |
* @return PJ_SUCCESS or the appropriate error code. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_set_lock( pj_ioqueue_t *ioque, | |
pj_lock_t *lock, | |
pj_bool_t auto_delete ); | |
/** | |
* Register a socket to the I/O queue framework. | |
* When a socket is registered to the IOQueue, it may be modified to use | |
* non-blocking IO. If it is modified, there is no guarantee that this | |
* modification will be restored after the socket is unregistered. | |
* | |
* @param pool To allocate the resource for the specified handle, | |
* which must be valid until the handle/key is unregistered | |
* from I/O Queue. | |
* @param ioque The I/O Queue. | |
* @param sock The socket. | |
* @param user_data User data to be associated with the key, which can be | |
* retrieved later. | |
* @param cb Callback to be called when I/O operation completes. | |
* @param key Pointer to receive the returned key. | |
* | |
* @return PJ_SUCCESS on success, or the error code. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, | |
pj_ioqueue_t *ioque, | |
pj_sock_t sock, | |
void *user_data, | |
const pj_ioqueue_callback *cb, | |
pj_ioqueue_key_t **key); | |
/** | |
* Unregister a handle from the I/O Queue framework. | |
* | |
* @param ioque The I/O Queue. | |
* @param key The key that uniquely identifies the handle, which is | |
* returned from the function #pj_ioqueue_register_sock() | |
* or other registration functions. | |
* | |
* @return PJ_SUCCESS on success or the error code. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_t *ioque, | |
pj_ioqueue_key_t *key ); | |
/** | |
* Get user data associated with the I/O Queue key. | |
* | |
* @param key The key previously associated with the socket/handle with | |
* #pj_ioqueue_register_sock() (or other registration | |
* functions). | |
* | |
* @return The user data associated with the key, or NULL on error | |
* of if no data is associated with the key during | |
* registration. | |
*/ | |
PJ_DECL(void*) pj_ioqueue_get_user_data( pj_ioqueue_key_t *key ); | |
#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0 | |
/** | |
* Instruct I/O Queue to wait for incoming connections on the specified | |
* listening socket. This function will return | |
* immediately (i.e. non-blocking) regardless whether some data has been | |
* transfered. If the function can't complete immediately, and the caller will | |
* be notified about the completion when it calls pj_ioqueue_poll(). | |
* | |
* @param ioqueue The I/O Queue | |
* @param key The key which registered to the server socket. | |
* @param sock Argument which contain pointer to receive | |
* the socket for the incoming connection. | |
* @param local Optional argument which contain pointer to variable to | |
* receive local address. | |
* @param remote Optional argument which contain pointer to variable to | |
* receive the remote address. | |
* @param addrlen On input, contains the length of the buffer for the | |
* address, and on output, contains the actual length of the | |
* address. This argument is optional. | |
* @return | |
* - PJ_SUCCESS If there's a connection available immediately, which | |
* in this case the callback should have been called before | |
* the function returns. | |
* - PJ_EPENDING If accept is queued, or | |
* - non-zero which indicates the appropriate error code. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_accept( pj_ioqueue_t *ioqueue, | |
pj_ioqueue_key_t *key, | |
pj_sock_t *sock, | |
pj_sockaddr_t *local, | |
pj_sockaddr_t *remote, | |
int *addrlen ); | |
/** | |
* Initiate non-blocking socket connect. If the socket can NOT be connected | |
* immediately, the result will be reported during poll. | |
* | |
* @param ioqueue The ioqueue | |
* @param key The key associated with TCP socket | |
* @param addr The remote address. | |
* @param addrlen The remote address length. | |
* | |
* @return | |
* - PJ_SUCCESS If socket is connected immediately, which in this case | |
* the callback should have been called. | |
* - PJ_EPENDING If operation is queued, or | |
* - non-zero Indicates the error code. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_connect( pj_ioqueue_t *ioqueue, | |
pj_ioqueue_key_t *key, | |
const pj_sockaddr_t *addr, | |
int addrlen ); | |
#endif /* PJ_HAS_TCP */ | |
/** | |
* Poll the I/O Queue for completed events. | |
* | |
* @param ioque the I/O Queue. | |
* @param timeout polling timeout, or NULL if the thread wishes to wait | |
* indefinetely for the event. | |
* | |
* @return | |
* - zero if timed out (no event). | |
* - (<0) if error occured during polling. Callback will NOT be called. | |
* - (>1) to indicate numbers of events. Callbacks have been called. | |
*/ | |
PJ_DECL(int) pj_ioqueue_poll( pj_ioqueue_t *ioque, | |
const pj_time_val *timeout); | |
/** | |
* Instruct the I/O Queue to read from the specified handle. This function | |
* returns immediately (i.e. non-blocking) regardless whether some data has | |
* been transfered. If the operation can't complete immediately, caller will | |
* be notified about the completion when it calls pj_ioqueue_poll(). | |
* | |
* @param ioque The I/O Queue. | |
* @param key The key that uniquely identifies the handle. | |
* @param buffer The buffer to hold the read data. The caller MUST make sure | |
* that this buffer remain valid until the framework completes | |
* reading the handle. | |
* @param buflen The maximum size to be read. | |
* | |
* @return | |
* - PJ_SUCCESS If immediate data has been received. In this case, the | |
* callback must have been called before this function | |
* returns, and no pending operation is scheduled. | |
* - PJ_EPENDING If the operation has been queued. | |
* - non-zero The return value indicates the error code. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_read( pj_ioqueue_t *ioque, | |
pj_ioqueue_key_t *key, | |
void *buffer, | |
pj_size_t buflen); | |
/** | |
* This function behaves similarly as #pj_ioqueue_read(), except that it is | |
* normally called for socket. | |
* | |
* @param ioque The I/O Queue. | |
* @param key The key that uniquely identifies the handle. | |
* @param buffer The buffer to hold the read data. The caller MUST make sure | |
* that this buffer remain valid until the framework completes | |
* reading the handle. | |
* @param buflen The maximum size to be read. | |
* @param flags Recv flag. | |
* | |
* @return | |
* - PJ_SUCCESS If immediate data has been received. In this case, the | |
* callback must have been called before this function | |
* returns, and no pending operation is scheduled. | |
* - PJ_EPENDING If the operation has been queued. | |
* - non-zero The return value indicates the error code. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_recv( pj_ioqueue_t *ioque, | |
pj_ioqueue_key_t *key, | |
void *buffer, | |
pj_size_t buflen, | |
unsigned flags ); | |
/** | |
* This function behaves similarly as #pj_ioqueue_read(), except that it is | |
* normally called for socket, and the remote address will also be returned | |
* along with the data. Caller MUST make sure that both buffer and addr | |
* remain valid until the framework completes reading the data. | |
* | |
* @param ioque The I/O Queue. | |
* @param key The key that uniquely identifies the handle. | |
* @param buffer The buffer to hold the read data. The caller MUST make sure | |
* that this buffer remain valid until the framework completes | |
* reading the handle. | |
* @param buflen The maximum size to be read. | |
* @param flags Recv flag. | |
* @param addr Pointer to buffer to receive the address, or NULL. | |
* @param addrlen On input, specifies the length of the address buffer. | |
* On output, it will be filled with the actual length of | |
* the address. | |
* | |
* @return | |
* - PJ_SUCCESS If immediate data has been received. In this case, the | |
* callback must have been called before this function | |
* returns, and no pending operation is scheduled. | |
* - PJ_EPENDING If the operation has been queued. | |
* - non-zero The return value indicates the error code. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_t *ioque, | |
pj_ioqueue_key_t *key, | |
void *buffer, | |
pj_size_t buflen, | |
unsigned flags, | |
pj_sockaddr_t *addr, | |
int *addrlen); | |
/** | |
* Instruct the I/O Queue to write to the handle. This function will return | |
* immediately (i.e. non-blocking) regardless whether some data has been | |
* transfered. If the function can't complete immediately, and the caller will | |
* be notified about the completion when it calls pj_ioqueue_poll(). | |
* | |
* @param ioque the I/O Queue. | |
* @param key the key that identifies the handle. | |
* @param data the data to send. Caller MUST make sure that this buffer | |
* remains valid until the write operation completes. | |
* @param datalen the length of the data. | |
* | |
* @return | |
* - PJ_SUCCESS If data was immediately written. | |
* - PJ_EPENDING If the operation has been queued. | |
* - non-zero The return value indicates the error code. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_write( pj_ioqueue_t *ioque, | |
pj_ioqueue_key_t *key, | |
const void *data, | |
pj_size_t datalen); | |
/** | |
* This function behaves similarly as #pj_ioqueue_write(), except that | |
* pj_sock_send() (or equivalent) will be called to send the data. | |
* | |
* @param ioque the I/O Queue. | |
* @param key the key that identifies the handle. | |
* @param data the data to send. Caller MUST make sure that this buffer | |
* remains valid until the write operation completes. | |
* @param datalen the length of the data. | |
* @param flags send flags. | |
* | |
* @return | |
* - PJ_SUCCESS If data was immediately written. | |
* - PJ_EPENDING If the operation has been queued. | |
* - non-zero The return value indicates the error code. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_send( pj_ioqueue_t *ioque, | |
pj_ioqueue_key_t *key, | |
const void *data, | |
pj_size_t datalen, | |
unsigned flags ); | |
/** | |
* This function behaves similarly as #pj_ioqueue_write(), except that | |
* pj_sock_sendto() (or equivalent) will be called to send the data. | |
* | |
* @param ioque the I/O Queue. | |
* @param key the key that identifies the handle. | |
* @param data the data to send. Caller MUST make sure that this buffer | |
* remains valid until the write operation completes. | |
* @param datalen the length of the data. | |
* @param flags send flags. | |
* @param addr remote address. | |
* @param addrlen remote address length. | |
* | |
* @return | |
* - PJ_SUCCESS If data was immediately written. | |
* - PJ_EPENDING If the operation has been queued. | |
* - non-zero The return value indicates the error code. | |
*/ | |
PJ_DECL(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_t *ioque, | |
pj_ioqueue_key_t *key, | |
const void *data, | |
pj_size_t datalen, | |
unsigned flags, | |
const pj_sockaddr_t *addr, | |
int addrlen); | |
/** | |
* !} | |
*/ | |
PJ_END_DECL | |
#endif /* __PJ_IOQUEUE_H__ */ | |