/* $Id$ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono * * 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 #include 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__ */