599 lines
25 KiB
C
599 lines
25 KiB
C
/*
|
|
* 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 PJ_TRUE.
|
|
*/
|
|
pj_bool_t whole_data;
|
|
|
|
/**
|
|
* If this option is specified, set close-on-exec flag for socket.
|
|
* This option is only used by #pj_activesock_create_udp()
|
|
*
|
|
* Default value is PJ_TRUE.
|
|
*/
|
|
pj_bool_t sock_cloexec;
|
|
|
|
} 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 ioqueue The ioqueue.
|
|
* @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__ */
|
|
|