| /* $Id$ |
| */ |
| |
| #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 Input/Output |
| * @brief Input/Output |
| * @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 |
| * @{ |
| * |
| * I/O Queue provides API for performing asynchronous I/O operations. It |
| * conforms to proactor pattern, which allows application to submit an |
| * asynchronous operation and to be notified later when the operation has |
| * completed. |
| * |
| * The I/O Queue can work on both socket and file descriptors. For |
| * asynchronous file operations however, one must make sure that the correct |
| * file I/O back-end is used, because not all file I/O back-end can be |
| * used with the ioqueue. Please see \ref PJ_FILE_IO for more details. |
| * |
| * The framework works natively in platforms where asynchronous operation API |
| * exists, such as in Windows NT with IoCompletionPort/IOCP. In other |
| * platforms, the I/O queue abstracts the operating system's event poll API |
| * to provide semantics similar to IoCompletionPort with minimal penalties |
| * (i.e. per ioqueue and per handle mutex protection). |
| * |
| * The I/O queue provides more than just unified abstraction. It also: |
| * - makes sure that the operation uses the most effective way to utilize |
| * the underlying mechanism, to achieve the maximum theoritical |
| * throughput possible on a given platform. |
| * - choose the most efficient mechanism for event polling on a given |
| * platform. |
| * |
| * Currently, the I/O Queue is implemented using: |
| * - <tt><b>select()</b></tt>, as the common denominator, but the least |
| * efficient. Also the number of descriptor is limited to |
| * \c PJ_IOQUEUE_MAX_HANDLES (which by default is 64). |
| * - <tt><b>/dev/epoll</b></tt> on Linux (user mode and kernel mode), |
| * a much faster replacement for select() on Linux (and more importantly |
| * doesn't have limitation on number of descriptors). |
| * - <b>I/O Completion ports</b> on 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_ioqueue_concurrency_sec Concurrency Rules |
| * |
| * The items below describe rules that must be obeyed when using the I/O |
| * queue, with regard to concurrency: |
| * - simultaneous operations (by different threads) to different key is safe. |
| * - simultaneous operations to the same key is also safe, except |
| * <b>unregistration</b>, which is described below. |
| * - <b>care must be taken when unregistering a key</b> from the |
| * ioqueue. Application must take care that when one thread is issuing |
| * an unregistration, other thread is not simultaneously invoking an |
| * operation <b>to the same key</b>. |
| *\n |
| * This happens because the ioqueue functions are working with a pointer |
| * to the key, and there is a possible race condition where the pointer |
| * has been rendered invalid by other threads before the ioqueue has a |
| * chance to acquire mutex on it. |
| * |
| * \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 operation specific key to be submitted to |
| * I/O Queue when performing the asynchronous operation. This key will |
| * be returned to the application when completion callback is called. |
| * |
| * Application normally wants to attach it's specific data in the |
| * \c user_data field so that it can keep track of which operation has |
| * completed when the callback is called. Alternatively, application can |
| * also extend this struct to include its data, because the pointer that |
| * is returned in the completion callback will be exactly the same as |
| * the pointer supplied when the asynchronous function is called. |
| */ |
| typedef struct pj_ioqueue_op_key_t |
| { |
| void *internal__[32]; /**< Internal I/O Queue data. */ |
| void *user_data; /**< Application data. */ |
| } pj_ioqueue_op_key_t; |
| |
| /** |
| * 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_recv or #pj_ioqueue_recvfrom |
| * completes. |
| * |
| * @param key The key. |
| * @param op_key Operation key. |
| * @param bytes_read >= 0 to indicate the amount of data read, |
| * otherwise negative value containing the error |
| * code. To obtain the pj_status_t error code, use |
| * (pj_status_t code = -bytes_read). |
| */ |
| void (*on_read_complete)(pj_ioqueue_key_t *key, |
| pj_ioqueue_op_key_t *op_key, |
| pj_ssize_t bytes_read); |
| |
| /** |
| * This callback is called when #pj_ioqueue_write or #pj_ioqueue_sendto |
| * completes. |
| * |
| * @param key The key. |
| * @param op_key Operation key. |
| * @param bytes_sent >= 0 to indicate the amount of data written, |
| * otherwise negative value containing the error |
| * code. To obtain the pj_status_t error code, use |
| * (pj_status_t code = -bytes_sent). |
| */ |
| void (*on_write_complete)(pj_ioqueue_key_t *key, |
| pj_ioqueue_op_key_t *op_key, |
| pj_ssize_t bytes_sent); |
| |
| /** |
| * This callback is called when #pj_ioqueue_accept completes. |
| * |
| * @param key The key. |
| * @param op_key Operation key. |
| * @param sock Newly connected socket. |
| * @param status Zero if the operation completes successfully. |
| */ |
| void (*on_accept_complete)(pj_ioqueue_key_t *key, |
| pj_ioqueue_op_key_t *op_key, |
| pj_sock_t sock, |
| pj_status_t status); |
| |
| /** |
| * This callback is called when #pj_ioqueue_connect completes. |
| * |
| * @param key The key. |
| * @param status PJ_SUCCESS if the operation completes successfully. |
| */ |
| void (*on_connect_complete)(pj_ioqueue_key_t *key, |
| pj_status_t status); |
| } pj_ioqueue_callback; |
| |
| |
| /** |
| * Types of pending I/O Queue operation. This enumeration is only used |
| * internally within the ioqueue. |
| */ |
| 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; |
| |
| |
| /** |
| * This macro specifies the maximum number of events that can be |
| * processed by the ioqueue on a single poll cycle, on implementation |
| * that supports it. The value is only meaningfull when specified |
| * during PJLIB build. |
| */ |
| #ifndef PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL |
| # define PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL (16) |
| #endif |
| |
| /** |
| * Return the name of the ioqueue implementation. |
| * |
| * @return Implementation name. |
| */ |
| PJ_DECL(const char*) pj_ioqueue_name(void); |
| |
| |
| /** |
| * 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 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, |
| 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 key to be associated with this |
| * socket. Subsequent I/O queue operation will need this |
| * 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 from the I/O Queue framework. Caller must make sure that |
| * the key doesn't have any pending operations before calling this function, |
| * by calling #pj_ioqueue_is_pending() for all previously submitted
|
| * operations except asynchronous connect, and if necessary call
|
| * #pj_ioqueue_post_completion() to cancel the pending operations.
|
| *
|
| * Note that asynchronous connect operation will automatically be
|
| * cancelled during the unregistration. |
| * |
| * @param key The key that was previously obtained from registration. |
| * |
| * @return PJ_SUCCESS on success or the error code.
|
| *
|
| * @see pj_ioqueue_is_pending |
| */ |
| PJ_DECL(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key ); |
| |
| |
| /** |
| * Get user data associated with an ioqueue key. |
| * |
| * @param key The key that was previously obtained from registration. |
| * |
| * @return The user data associated with the descriptor, or NULL |
| * on error or if no data is associated with the key during |
| * registration. |
| */ |
| PJ_DECL(void*) pj_ioqueue_get_user_data( pj_ioqueue_key_t *key ); |
| |
| /** |
| * Set or change the user data to be associated with the file descriptor or |
| * handle or socket descriptor. |
| * |
| * @param key The key that was previously obtained from registration. |
| * @param user_data User data to be associated with the descriptor. |
| * @param old_data Optional parameter to retrieve the old user data. |
| * |
| * @return PJ_SUCCESS on success or the error code. |
| */ |
| PJ_DECL(pj_status_t) pj_ioqueue_set_user_data( pj_ioqueue_key_t *key, |
| void *user_data, |
| void **old_data); |
| |
|
|
| /**
|
| * Check if operation is pending on the specified operation key.
|
| * The \c op_key must have been submitted as pending operation before,
|
| * or otherwise the result is undefined.
|
| *
|
| * @param key The key.
|
| * @param op_key The operation key, previously submitted to any of
|
| * the I/O functions and has returned PJ_EPENDING.
|
| *
|
| * @return Non-zero if operation is still pending.
|
| */
|
| PJ_DECL(pj_bool_t) pj_ioqueue_is_pending( pj_ioqueue_key_t *key,
|
| pj_ioqueue_op_key_t *op_key );
|
|
|
|
|
| /**
|
| * Post completion status to the specified operation key and call the
|
| * appropriate callback. When the callback is called, the number of bytes
|
| * received in read/write callback or the status in accept/connect callback
|
| * will be set from the \c bytes_status parameter.
|
| *
|
| * @param key The key.
|
| * @param op_key Pending operation key.
|
| * @param bytes_status Number of bytes or status to be set. A good value
|
| * to put here is -PJ_ECANCELLED.
|
| *
|
| * @return PJ_SUCCESS if completion status has been successfully
|
| * sent.
|
| */
|
| PJ_DECL(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key,
|
| pj_ioqueue_op_key_t *op_key,
|
| pj_ssize_t bytes_status );
|
|
|
|
|
| |
| #if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0 |
| /** |
| * Instruct I/O Queue to accept incoming connection on the specified |
| * listening socket. This function will return immediately (i.e. non-blocking) |
| * regardless whether a connection is immediately available. If the function |
| * can't complete immediately, the caller will be notified about the incoming |
| * connection when it calls pj_ioqueue_poll(). If a new connection is |
| * immediately available, the function returns PJ_SUCCESS with the new |
| * connection; in this case, the callback WILL NOT be called. |
| * |
| * @param key The key which registered to the server socket. |
| * @param op_key An operation specific key to be associated with the |
| * pending operation, so that application can keep track of |
| * which operation has been completed when the callback is |
| * called. |
| * @param new_sock Argument which contain pointer to receive the new 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 When connection is available immediately, and the |
| * parameters will be updated to contain information about |
| * the new connection. In this case, a completion callback |
| * WILL NOT be called. |
| * - PJ_EPENDING If no connection is available immediately. When a new |
| * connection arrives, the callback will be called. |
| * - non-zero which indicates the appropriate error code. |
| */ |
| PJ_DECL(pj_status_t) pj_ioqueue_accept( pj_ioqueue_key_t *key, |
| pj_ioqueue_op_key_t *op_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, asynchronous connect() will be scheduled and caller will be |
| * notified via completion callback when it calls pj_ioqueue_poll(). If |
| * socket is connected immediately, the function returns PJ_SUCCESS and |
| * completion callback WILL NOT be called. |
| * |
| * @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. In this case, the |
| * completion callback WILL NOT be called. |
| * - PJ_EPENDING If operation is queued, or |
| * - non-zero Indicates the error code. |
| */ |
| PJ_DECL(pj_status_t) pj_ioqueue_connect( 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(). If data |
| * is immediately available, the function will return PJ_SUCCESS and the |
| * callback WILL NOT be called. |
| * |
| * @param key The key that uniquely identifies the handle. |
| * @param op_key An operation specific key to be associated with the |
| * pending operation, so that application can keep track of |
| * which operation has been completed when the callback is |
| * called. Caller must make sure that this key remains |
| * valid until the function completes. |
| * @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 length On input, it specifies the size of the buffer. If data is |
| * available to be read immediately, the function returns |
| * PJ_SUCCESS and this argument will be filled with the |
| * amount of data read. If the function is pending, caller |
| * will be notified about the amount of data read in the |
| * callback. This parameter can point to local variable in |
| * caller's stack and doesn't have to remain valid for the |
| * duration of pending operation. |
| * @param flags Recv flag. |
| * |
| * @return |
| * - PJ_SUCCESS If immediate data has been received in the buffer. In this |
| * case, the callback WILL NOT be called. |
| * - PJ_EPENDING If the operation has been queued, and the callback will be |
| * called when data has been received. |
| * - non-zero The return value indicates the error code. |
| */ |
| PJ_DECL(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key, |
| pj_ioqueue_op_key_t *op_key, |
| void *buffer, |
| pj_ssize_t *length, |
| unsigned flags ); |
| |
| /** |
| * This function behaves similarly as #pj_ioqueue_recv(), 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 key The key that uniquely identifies the handle. |
| * @param op_key An operation specific key to be associated with the |
| * pending operation, so that application can keep track of |
| * which operation has been completed when the callback is |
| * called. |
| * @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 length On input, it specifies the size of the buffer. If data is |
| * available to be read immediately, the function returns |
| * PJ_SUCCESS and this argument will be filled with the |
| * amount of data read. If the function is pending, caller |
| * will be notified about the amount of data read in the |
| * callback. This parameter can point to local variable in |
| * caller's stack and doesn't have to remain valid for the |
| * duration of pending operation. |
| * @param flags Recv flag. |
| * @param addr Optional Pointer to buffer to receive the address. |
| * @param addrlen On input, specifies the length of the address buffer. |
| * On output, it will be filled with the actual length of |
| * the address. This argument can be NULL if \c addr is not |
| * specified. |
| * |
| * @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_key_t *key, |
| pj_ioqueue_op_key_t *op_key, |
| void *buffer, |
| pj_ssize_t *length, |
| 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, the caller will |
| * be notified about the completion when it calls pj_ioqueue_poll(). If |
| * operation completes immediately and data has been transfered, the function |
| * returns PJ_SUCCESS and the callback will NOT be called. |
| * |
| * @param key The key that identifies the handle. |
| * @param op_key An operation specific key to be associated with the |
| * pending operation, so that application can keep track of |
| * which operation has been completed when the callback is |
| * called. |
| * @param data The data to send. Caller MUST make sure that this buffer |
| * remains valid until the write operation completes. |
| * @param length On input, it specifies the length of data to send. When |
| * data was sent immediately, this function returns PJ_SUCCESS |
| * and this parameter contains the length of data sent. If |
| * data can not be sent immediately, an asynchronous operation |
| * is scheduled and caller will be notified via callback the |
| * number of bytes sent. This parameter can point to local |
| * variable on caller's stack and doesn't have to remain |
| * valid until the operation has completed. |
| * @param flags Send flags. |
| * |
| * @return |
| * - PJ_SUCCESS If data was immediately transfered. In this case, no |
| * pending operation has been scheduled and the callback |
| * WILL NOT be called. |
| * - PJ_EPENDING If the operation has been queued. Once data base been |
| * transfered, the callback will be called. |
| * - non-zero The return value indicates the error code. |
| */ |
| PJ_DECL(pj_status_t) pj_ioqueue_send( pj_ioqueue_key_t *key, |
| pj_ioqueue_op_key_t *op_key, |
| const void *data, |
| pj_ssize_t *length, |
| unsigned flags ); |
| |
| |
| /** |
| * 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, the caller will |
| * be notified about the completion when it calls pj_ioqueue_poll(). If |
| * operation completes immediately and data has been transfered, the function |
| * returns PJ_SUCCESS and the callback will NOT be called. |
| * |
| * @param key the key that identifies the handle. |
| * @param op_key An operation specific key to be associated with the |
| * pending operation, so that application can keep track of |
| * which operation has been completed when the callback is |
| * called. |
| * @param data the data to send. Caller MUST make sure that this buffer |
| * remains valid until the write operation completes. |
| * @param length On input, it specifies the length of data to send. When |
| * data was sent immediately, this function returns PJ_SUCCESS |
| * and this parameter contains the length of data sent. If |
| * data can not be sent immediately, an asynchronous operation |
| * is scheduled and caller will be notified via callback the |
| * number of bytes sent. This parameter can point to local |
| * variable on caller's stack and doesn't have to remain |
| * valid until the operation has completed. |
| * @param flags send flags. |
| * @param addr Optional remote address. |
| * @param addrlen Remote address length, \c addr is specified. |
| * |
| * @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_key_t *key, |
| pj_ioqueue_op_key_t *op_key, |
| const void *data, |
| pj_ssize_t *length, |
| unsigned flags, |
| const pj_sockaddr_t *addr, |
| int addrlen); |
| |
| |
| /** |
| * !} |
| */ |
| |
| PJ_END_DECL |
| |
| #endif /* __PJ_IOQUEUE_H__ */ |
| |