| /* $Id$ */ |
| /* |
| * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) |
| * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| #ifndef __PJ_ASYNCSOCK_H__ |
| #define __PJ_ASYNCSOCK_H__ |
| |
| /** |
| * @file activesock.h |
| * @brief Active socket |
| */ |
| |
| #include <pj/ioqueue.h> |
| #include <pj/sock.h> |
| |
| |
| PJ_BEGIN_DECL |
| |
| /** |
| * @defgroup PJ_ACTIVESOCK Active socket I/O |
| * @brief Active socket performs active operations on socket. |
| * @ingroup PJ_IO |
| * @{ |
| * |
| * Active socket is a higher level abstraction to the ioqueue. It provides |
| * automation to socket operations which otherwise would have to be done |
| * manually by the applications. For example with socket recv(), recvfrom(), |
| * and accept() operations, application only needs to invoke these |
| * operation once, and it will be notified whenever data or incoming TCP |
| * connection (in the case of accept()) arrives. |
| */ |
| |
| /** |
| * This opaque structure describes the active socket. |
| */ |
| typedef struct pj_activesock_t pj_activesock_t; |
| |
| /** |
| * This structure contains the callbacks to be called by the active socket. |
| */ |
| typedef struct pj_activesock_cb |
| { |
| /** |
| * This callback is called when a data arrives as the result of |
| * pj_activesock_start_read(). |
| * |
| * @param asock The active socket. |
| * @param data The buffer containing the new data, if any. If |
| * the status argument is non-PJ_SUCCESS, this |
| * argument may be NULL. |
| * @param size The length of data in the buffer. |
| * @param status The status of the read operation. This may contain |
| * non-PJ_SUCCESS for example when the TCP connection |
| * has been closed. In this case, the buffer may |
| * contain left over data from previous callback which |
| * the application may want to process. |
| * @param remainder If application wishes to leave some data in the |
| * buffer (common for TCP applications), it should |
| * move the remainder data to the front part of the |
| * buffer and set the remainder length here. The value |
| * of this parameter will be ignored for datagram |
| * sockets. |
| * |
| * @return PJ_TRUE if further read is desired, and PJ_FALSE |
| * when application no longer wants to receive data. |
| * Application may destroy the active socket in the |
| * callback and return PJ_FALSE here. |
| */ |
| pj_bool_t (*on_data_read)(pj_activesock_t *asock, |
| void *data, |
| pj_size_t size, |
| pj_status_t status, |
| pj_size_t *remainder); |
| /** |
| * This callback is called when a packet arrives as the result of |
| * pj_activesock_start_recvfrom(). |
| * |
| * @param asock The active socket. |
| * @param data The buffer containing the packet, if any. If |
| * the status argument is non-PJ_SUCCESS, this |
| * argument will be set to NULL. |
| * @param size The length of packet in the buffer. If |
| * the status argument is non-PJ_SUCCESS, this |
| * argument will be set to zero. |
| * @param src_addr Source address of the packet. |
| * @param addr_len Length of the source address. |
| * @param status This contains |
| * |
| * @return PJ_TRUE if further read is desired, and PJ_FALSE |
| * when application no longer wants to receive data. |
| * Application may destroy the active socket in the |
| * callback and return PJ_FALSE here. |
| */ |
| pj_bool_t (*on_data_recvfrom)(pj_activesock_t *asock, |
| void *data, |
| pj_size_t size, |
| const pj_sockaddr_t *src_addr, |
| int addr_len, |
| pj_status_t status); |
| |
| /** |
| * This callback is called when data has been sent. |
| * |
| * @param asock The active socket. |
| * @param send_key Key associated with the send operation. |
| * @param sent If value is positive non-zero it indicates the |
| * number of data sent. When the value is negative, |
| * it contains the error code which can be retrieved |
| * by negating the value (i.e. status=-sent). |
| * |
| * @return Application may destroy the active socket in the |
| * callback and return PJ_FALSE here. |
| */ |
| pj_bool_t (*on_data_sent)(pj_activesock_t *asock, |
| pj_ioqueue_op_key_t *send_key, |
| pj_ssize_t sent); |
| |
| /** |
| * This callback is called when new connection arrives as the result |
| * of pj_activesock_start_accept(). If the status of accept operation is |
| * needed use on_accept_complete2 instead of this callback. |
| * |
| * @param asock The active socket. |
| * @param newsock The new incoming socket. |
| * @param src_addr The source address of the connection. |
| * @param addr_len Length of the source address. |
| * |
| * @return PJ_TRUE if further accept() is desired, and PJ_FALSE |
| * when application no longer wants to accept incoming |
| * connection. Application may destroy the active socket |
| * in the callback and return PJ_FALSE here. |
| */ |
| pj_bool_t (*on_accept_complete)(pj_activesock_t *asock, |
| pj_sock_t newsock, |
| const pj_sockaddr_t *src_addr, |
| int src_addr_len); |
| |
| /** |
| * This callback is called when new connection arrives as the result |
| * of pj_activesock_start_accept(). |
| * |
| * @param asock The active socket. |
| * @param newsock The new incoming socket. |
| * @param src_addr The source address of the connection. |
| * @param addr_len Length of the source address. |
| * @param status The status of the accept operation. This may contain |
| * non-PJ_SUCCESS for example when the TCP listener is in |
| * bad state for example on iOS platform after the |
| * application waking up from background. |
| * |
| * @return PJ_TRUE if further accept() is desired, and PJ_FALSE |
| * when application no longer wants to accept incoming |
| * connection. Application may destroy the active socket |
| * in the callback and return PJ_FALSE here. |
| */ |
| pj_bool_t (*on_accept_complete2)(pj_activesock_t *asock, |
| pj_sock_t newsock, |
| const pj_sockaddr_t *src_addr, |
| int src_addr_len, |
| pj_status_t status); |
| |
| /** |
| * This callback is called when pending connect operation has been |
| * completed. |
| * |
| * @param asock The active socket. |
| * @param status The connection result. If connection has been |
| * successfully established, the status will contain |
| * PJ_SUCCESS. |
| * |
| * @return Application may destroy the active socket in the |
| * callback and return PJ_FALSE here. |
| */ |
| pj_bool_t (*on_connect_complete)(pj_activesock_t *asock, |
| pj_status_t status); |
| |
| } pj_activesock_cb; |
| |
| |
| /** |
| * Settings that can be given during active socket creation. Application |
| * must initialize this structure with #pj_activesock_cfg_default(). |
| */ |
| typedef struct pj_activesock_cfg |
| { |
| /** |
| * Optional group lock to be assigned to the ioqueue key. |
| */ |
| pj_grp_lock_t *grp_lock; |
| |
| /** |
| * Number of concurrent asynchronous operations that is to be supported |
| * by the active socket. This value only affects socket receive and |
| * accept operations -- the active socket will issue one or more |
| * asynchronous read and accept operations based on the value of this |
| * field. Setting this field to more than one will allow more than one |
| * incoming data or incoming connections to be processed simultaneously |
| * on multiprocessor systems, when the ioqueue is polled by more than |
| * one threads. |
| * |
| * The default value is 1. |
| */ |
| unsigned async_cnt; |
| |
| /** |
| * The ioqueue concurrency to be forced on the socket when it is |
| * registered to the ioqueue. See #pj_ioqueue_set_concurrency() for more |
| * info about ioqueue concurrency. |
| * |
| * When this value is -1, the concurrency setting will not be forced for |
| * this socket, and the socket will inherit the concurrency setting of |
| * the ioqueue. When this value is zero, the active socket will disable |
| * concurrency for the socket. When this value is +1, the active socket |
| * will enable concurrency for the socket. |
| * |
| * The default value is -1. |
| */ |
| int concurrency; |
| |
| /** |
| * If this option is specified, the active socket will make sure that |
| * asynchronous send operation with stream oriented socket will only |
| * call the callback after all data has been sent. This means that the |
| * active socket will automatically resend the remaining data until |
| * all data has been sent. |
| * |
| * Please note that when this option is specified, it is possible that |
| * error is reported after partial data has been sent. Also setting |
| * this will disable the ioqueue concurrency for the socket. |
| * |
| * Default value is 1. |
| */ |
| pj_bool_t whole_data; |
| |
| } pj_activesock_cfg; |
| |
| |
| /** |
| * Initialize the active socket configuration with the default values. |
| * |
| * @param cfg The configuration to be initialized. |
| */ |
| PJ_DECL(void) pj_activesock_cfg_default(pj_activesock_cfg *cfg); |
| |
| |
| /** |
| * Create the active socket for the specified socket. This will register |
| * the socket to the specified ioqueue. |
| * |
| * @param pool Pool to allocate memory from. |
| * @param sock The socket handle. |
| * @param sock_type Specify socket type, either pj_SOCK_DGRAM() or |
| * pj_SOCK_STREAM(). The active socket needs this |
| * information to handle connection closure for |
| * connection oriented sockets. |
| * @param ioqueue The ioqueue to use. |
| * @param opt Optional settings. When this setting is not specifed, |
| * the default values will be used. |
| * @param cb Pointer to structure containing application |
| * callbacks. |
| * @param user_data Arbitrary user data to be associated with this |
| * active socket. |
| * @param p_asock Pointer to receive the active socket instance. |
| * |
| * @return PJ_SUCCESS if the operation has been successful, |
| * or the appropriate error code on failure. |
| */ |
| PJ_DECL(pj_status_t) pj_activesock_create(pj_pool_t *pool, |
| pj_sock_t sock, |
| int sock_type, |
| const pj_activesock_cfg *opt, |
| pj_ioqueue_t *ioqueue, |
| const pj_activesock_cb *cb, |
| void *user_data, |
| pj_activesock_t **p_asock); |
| |
| /** |
| * Create UDP socket descriptor, bind it to the specified address, and |
| * create the active socket for the socket descriptor. |
| * |
| * @param pool Pool to allocate memory from. |
| * @param addr Specifies the address family of the socket and the |
| * address where the socket should be bound to. If |
| * this argument is NULL, then AF_INET is assumed and |
| * the socket will be bound to any addresses and port. |
| * @param opt Optional settings. When this setting is not specifed, |
| * the default values will be used. |
| * @param cb Pointer to structure containing application |
| * callbacks. |
| * @param user_data Arbitrary user data to be associated with this |
| * active socket. |
| * @param p_asock Pointer to receive the active socket instance. |
| * @param bound_addr If this argument is specified, it will be filled with |
| * the bound address on return. |
| * |
| * @return PJ_SUCCESS if the operation has been successful, |
| * or the appropriate error code on failure. |
| */ |
| PJ_DECL(pj_status_t) pj_activesock_create_udp(pj_pool_t *pool, |
| const pj_sockaddr *addr, |
| const pj_activesock_cfg *opt, |
| pj_ioqueue_t *ioqueue, |
| const pj_activesock_cb *cb, |
| void *user_data, |
| pj_activesock_t **p_asock, |
| pj_sockaddr *bound_addr); |
| |
| /** |
| * Close the active socket. This will unregister the socket from the |
| * ioqueue and ultimately close the socket. |
| * |
| * @param asock The active socket. |
| * |
| * @return PJ_SUCCESS if the operation has been successful, |
| * or the appropriate error code on failure. |
| */ |
| PJ_DECL(pj_status_t) pj_activesock_close(pj_activesock_t *asock); |
| |
| #if (defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ |
| PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0) || \ |
| defined(DOXYGEN) |
| /** |
| * Set iPhone OS background mode setting. Setting to 1 will enable TCP |
| * active socket to receive incoming data when application is in the |
| * background. Setting to 0 will disable it. Default value of this |
| * setting is PJ_ACTIVESOCK_TCP_IPHONE_OS_BG. |
| * |
| * This API is only available if PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT |
| * is set to non-zero. |
| * |
| * @param asock The active socket. |
| * @param val The value of background mode setting. |
| * |
| */ |
| PJ_DECL(void) pj_activesock_set_iphone_os_bg(pj_activesock_t *asock, |
| int val); |
| |
| /** |
| * Enable/disable support for iPhone OS background mode. This setting |
| * will apply globally and will affect any active sockets created |
| * afterwards, if you want to change the setting for a particular |
| * active socket, use #pj_activesock_set_iphone_os_bg() instead. |
| * By default, this setting is enabled. |
| * |
| * This API is only available if PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT |
| * is set to non-zero. |
| * |
| * @param val The value of global background mode setting. |
| * |
| */ |
| PJ_DECL(void) pj_activesock_enable_iphone_os_bg(pj_bool_t val); |
| #endif |
| |
| /** |
| * Associate arbitrary data with the active socket. Application may |
| * inspect this data in the callbacks and associate it with higher |
| * level processing. |
| * |
| * @param asock The active socket. |
| * @param user_data The user data to be associated with the active |
| * socket. |
| * |
| * @return PJ_SUCCESS if the operation has been successful, |
| * or the appropriate error code on failure. |
| */ |
| PJ_DECL(pj_status_t) pj_activesock_set_user_data(pj_activesock_t *asock, |
| void *user_data); |
| |
| /** |
| * Retrieve the user data previously associated with this active |
| * socket. |
| * |
| * @param asock The active socket. |
| * |
| * @return The user data. |
| */ |
| PJ_DECL(void*) pj_activesock_get_user_data(pj_activesock_t *asock); |
| |
| |
| /** |
| * Starts read operation on this active socket. This function will create |
| * \a async_cnt number of buffers (the \a async_cnt parameter was given |
| * in \a pj_activesock_create() function) where each buffer is \a buff_size |
| * long. The buffers are allocated from the specified \a pool. Once the |
| * buffers are created, it then issues \a async_cnt number of asynchronous |
| * \a recv() operations to the socket and returns back to caller. Incoming |
| * data on the socket will be reported back to application via the |
| * \a on_data_read() callback. |
| * |
| * Application only needs to call this function once to initiate read |
| * operations. Further read operations will be done automatically by the |
| * active socket when \a on_data_read() callback returns non-zero. |
| * |
| * @param asock The active socket. |
| * @param pool Pool used to allocate buffers for incoming data. |
| * @param buff_size The size of each buffer, in bytes. |
| * @param flags Flags to be given to pj_ioqueue_recv(). |
| * |
| * @return PJ_SUCCESS if the operation has been successful, |
| * or the appropriate error code on failure. |
| */ |
| PJ_DECL(pj_status_t) pj_activesock_start_read(pj_activesock_t *asock, |
| pj_pool_t *pool, |
| unsigned buff_size, |
| pj_uint32_t flags); |
| |
| /** |
| * Same as #pj_activesock_start_read(), except that the application |
| * supplies the buffers for the read operation so that the acive socket |
| * does not have to allocate the buffers. |
| * |
| * @param asock The active socket. |
| * @param pool Pool used to allocate buffers for incoming data. |
| * @param buff_size The size of each buffer, in bytes. |
| * @param readbuf Array of packet buffers, each has buff_size size. |
| * @param flags Flags to be given to pj_ioqueue_recv(). |
| * |
| * @return PJ_SUCCESS if the operation has been successful, |
| * or the appropriate error code on failure. |
| */ |
| PJ_DECL(pj_status_t) pj_activesock_start_read2(pj_activesock_t *asock, |
| pj_pool_t *pool, |
| unsigned buff_size, |
| void *readbuf[], |
| pj_uint32_t flags); |
| |
| /** |
| * Same as pj_activesock_start_read(), except that this function is used |
| * only for datagram sockets, and it will trigger \a on_data_recvfrom() |
| * callback instead. |
| * |
| * @param asock The active socket. |
| * @param pool Pool used to allocate buffers for incoming data. |
| * @param buff_size The size of each buffer, in bytes. |
| * @param flags Flags to be given to pj_ioqueue_recvfrom(). |
| * |
| * @return PJ_SUCCESS if the operation has been successful, |
| * or the appropriate error code on failure. |
| */ |
| PJ_DECL(pj_status_t) pj_activesock_start_recvfrom(pj_activesock_t *asock, |
| pj_pool_t *pool, |
| unsigned buff_size, |
| pj_uint32_t flags); |
| |
| /** |
| * Same as #pj_activesock_start_recvfrom() except that the recvfrom() |
| * operation takes the buffer from the argument rather than creating |
| * new ones. |
| * |
| * @param asock The active socket. |
| * @param pool Pool used to allocate buffers for incoming data. |
| * @param buff_size The size of each buffer, in bytes. |
| * @param readbuf Array of packet buffers, each has buff_size size. |
| * @param flags Flags to be given to pj_ioqueue_recvfrom(). |
| * |
| * @return PJ_SUCCESS if the operation has been successful, |
| * or the appropriate error code on failure. |
| */ |
| PJ_DECL(pj_status_t) pj_activesock_start_recvfrom2(pj_activesock_t *asock, |
| pj_pool_t *pool, |
| unsigned buff_size, |
| void *readbuf[], |
| pj_uint32_t flags); |
| |
| /** |
| * Send data using the socket. |
| * |
| * @param asock The active socket. |
| * @param send_key The operation key to send the data, which is useful |
| * if application wants to submit multiple pending |
| * send operations and want to track which exact data |
| * has been sent in the \a on_data_sent() callback. |
| * @param data The data to be sent. This data must remain valid |
| * until the data has been sent. |
| * @param size The size of the data. |
| * @param flags Flags to be given to pj_ioqueue_send(). |
| * |
| * |
| * @return PJ_SUCCESS if data has been sent immediately, or |
| * PJ_EPENDING if data cannot be sent immediately. In |
| * this case the \a on_data_sent() callback will be |
| * called when data is actually sent. Any other return |
| * value indicates error condition. |
| */ |
| PJ_DECL(pj_status_t) pj_activesock_send(pj_activesock_t *asock, |
| pj_ioqueue_op_key_t *send_key, |
| const void *data, |
| pj_ssize_t *size, |
| unsigned flags); |
| |
| /** |
| * Send datagram using the socket. |
| * |
| * @param asock The active socket. |
| * @param send_key The operation key to send the data, which is useful |
| * if application wants to submit multiple pending |
| * send operations and want to track which exact data |
| * has been sent in the \a on_data_sent() callback. |
| * @param data The data to be sent. This data must remain valid |
| * until the data has been sent. |
| * @param size The size of the data. |
| * @param flags Flags to be given to pj_ioqueue_send(). |
| * @param addr The destination address. |
| * @param addr_len The length of the address. |
| * |
| * @return PJ_SUCCESS if data has been sent immediately, or |
| * PJ_EPENDING if data cannot be sent immediately. In |
| * this case the \a on_data_sent() callback will be |
| * called when data is actually sent. Any other return |
| * value indicates error condition. |
| */ |
| PJ_DECL(pj_status_t) pj_activesock_sendto(pj_activesock_t *asock, |
| pj_ioqueue_op_key_t *send_key, |
| const void *data, |
| pj_ssize_t *size, |
| unsigned flags, |
| const pj_sockaddr_t *addr, |
| int addr_len); |
| |
| #if PJ_HAS_TCP |
| /** |
| * Starts asynchronous socket accept() operations on this active socket. |
| * Application must bind the socket before calling this function. This |
| * function will issue \a async_cnt number of asynchronous \a accept() |
| * operations to the socket and returns back to caller. Incoming |
| * connection on the socket will be reported back to application via the |
| * \a on_accept_complete() callback. |
| * |
| * Application only needs to call this function once to initiate accept() |
| * operations. Further accept() operations will be done automatically by |
| * the active socket when \a on_accept_complete() callback returns non-zero. |
| * |
| * @param asock The active socket. |
| * @param pool Pool used to allocate some internal data for the |
| * operation. |
| * |
| * @return PJ_SUCCESS if the operation has been successful, |
| * or the appropriate error code on failure. |
| */ |
| PJ_DECL(pj_status_t) pj_activesock_start_accept(pj_activesock_t *asock, |
| pj_pool_t *pool); |
| |
| /** |
| * Starts asynchronous socket connect() operation for this socket. Once |
| * the connection is done (either successfully or not), the |
| * \a on_connect_complete() callback will be called. |
| * |
| * @param asock The active socket. |
| * @param pool The pool to allocate some internal data for the |
| * operation. |
| * @param remaddr Remote address. |
| * @param addr_len Length of the remote address. |
| * |
| * @return PJ_SUCCESS if connection can be established immediately, |
| * or PJ_EPENDING if connection cannot be established |
| * immediately. In this case the \a on_connect_complete() |
| * callback will be called when connection is complete. |
| * Any other return value indicates error condition. |
| */ |
| PJ_DECL(pj_status_t) pj_activesock_start_connect(pj_activesock_t *asock, |
| pj_pool_t *pool, |
| const pj_sockaddr_t *remaddr, |
| int addr_len); |
| |
| |
| #endif /* PJ_HAS_TCP */ |
| |
| /** |
| * @} |
| */ |
| |
| PJ_END_DECL |
| |
| #endif /* __PJ_ASYNCSOCK_H__ */ |
| |