#ifndef	ACL_CONNECT_INCLUDE_H
#define	ACL_CONNECT_INCLUDE_H

#ifdef	__cplusplus
extern "C" {
#endif

#include "../stdlib/acl_define.h"

#ifdef  ACL_UNIX
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#endif

#define ACL_CONNECT_F_NONE		0		/* Nonthing */
#define ACL_CONNECT_F_SYS_ERR		(1 << 0)	/* ϵͳ errno */
#define ACL_CONNECT_F_CREATE_SOCKET_ERR	(1 << 1)	/*  socket  */
#define ACL_CONNECT_F_REUSE_ADDR_ERR	(1 << 2)	/* ظʹð󶨵ַ */
#define ACL_CONNECT_F_BIND_IP_OK	(1 << 3)	/* 󶨱 IP ɹ */
#define ACL_CONNECT_F_BIND_IP_ERR	(1 << 4)	/* 󶨱 IP ʧ */
#define ACL_CONNECT_F_BIND_IFACE_OK	(1 << 5)	/* 󶨱ɹ */
#define ACL_CONNECT_F_BIND_IFACE_ERR	(1 << 6)	/* 󶨱ʧ */
#define ACL_CONNECT_F_SO_ERROR		(1 << 7)	/* socket  */
#define ACL_CONNECT_F_INPROGRESS	(1 << 8);	/* ӹ */
#define ACL_CONNECT_F_WAIT_ERR		(1 << 9)	/* ȴӽʧ */

/* in acl_sane_connect.c */
/**
 * Զӷ
 * @param sock {ACL_SOCKET} ׽֣UNIXƽ̨»׽
 * @param sa {const struct sockaddr*} ַ
 * @param len {socklen_t} sa ĵַ
 * @return {int} 0: ӳɹ; -1: ʧ
 */
ACL_API int acl_sane_connect(ACL_SOCKET sock, const struct sockaddr * sa,
		socklen_t len);

/* in acl_timed_connect.c */

/**
 * ʱʱԶӷ
 * @param fd {ACL_SOCKET} ׽֣UNIXƽ̨»׽
 * @param sa {const struct sockaddr*} ַ
 * @param len {socklen_t} sa ĵַ
 * @param timeout {int} ӳʱʱ(뼶)
 * @return {int} 0: ӳɹ; -1: ʧ
 */
ACL_API int acl_timed_connect(ACL_SOCKET fd, const struct sockaddr * sa,
		socklen_t len, int timeout);

/**
 * ʱʱԶӷ
 * @param fd {ACL_SOCKET} ׽֣UNIXƽ̨»׽
 * @param sa {const struct sockaddr*} ַ
 * @param len {socklen_t} sa ĵַ
 * @param timeout {int} ӳʱʱ(뼶)
 * @param flags {unsigned*} ǿʱʧܵĴϢӵλ
 * @return {int} 0: ӳɹ; -1: ʧ
 */
ACL_API int acl_timed_connect_ms2(ACL_SOCKET fd, const struct sockaddr * sa,
		socklen_t len, int timeout, unsigned *flags);
ACL_API int acl_timed_connect_ms(ACL_SOCKET fd, const struct sockaddr * sa,
		socklen_t len, int timeout);

/* in acl_inet_connect.c */

/**
 * Զַ
 * @param addr {const char*} Զ̷ļַ磺192.168.0.1|80, 
 *  Ҫ󶨱صĵַʽΪ: remote_addr@local_ip,
 *  : www.sina.com|80@60.28.250.199
 * @param blocking {int} ģʽǷģʽ, ACL_BLOCKING  ACL_NON_BLOCKING
 * @param timeout {int} ӳʱʱ䣬 blocking Ϊ ACL_NON_BLOCKING ֵ
 * @return {ACL_SOCKET}  ACL_SOCKET_INVALID ʾʧ 
 */
ACL_API ACL_SOCKET acl_inet_connect(const char *addr, int blocking, int timeout);

/**
 * Զַ
 * @param addr {const char*} Զ̷ļַ磺192.168.0.1|80
 *  жַͨĳָӷʱĵַʽ
 *  remote_ip|remote_port@local_ip磺211.150.111.12|80@192.168.1.1
 * @param blocking {int} ģʽǷģʽ, ACL_BLOCKING  ACL_NON_BLOCKING
 * @param timeout {int} ӳʱʱ(뼶) blocking Ϊ ACL_NON_BLOCKING ֵ
 * @param flags {unsigned*} ǿʱʧܵĴϢӵλ
 * @return {ACL_SOCKET}  ACL_SOCKET_INVALID ʾʧ
 */
ACL_API ACL_SOCKET acl_inet_connect2(const char *addr, int blocking,
		int timeout, unsigned *flags);
#define acl_inet_connect_ex	acl_inet_connect2

/**
 * Զַ
 * @param addr {const char*} Զ̷ļַ磺192.168.0.1|80
 *  жַͨĳָӷʱĵַʽ
 *  remote_ip|remote_port@local_ip  remote_ip|remote_port#local_interface
 *  磺
 *    211.150.111.12|80@192.168.1.1
 *    211.150.111.12|80#interface
 * @param blocking {int} ģʽǷģʽ, ACL_BLOCKING  ACL_NON_BLOCKING
 * @param timeout {int} ӳʱʱ(뼶) blocking Ϊ ACL_NON_BLOCKING ֵ
 * @param flags {unsigned*} ǿʱʧܵĴϢӵλ
 * @return {ACL_SOCKET}  ACL_SOCKET_INVALID ʾʧ
 */
ACL_API ACL_SOCKET acl_inet_timed_connect(const char *addr, int blocking,
		int timeout, unsigned *flags);

#ifdef	ACL_UNIX

/* in acl_unix_connect.c */

/**
 * Ӽ׽ַ
 * @param addr {const char*} ׽ȫ·, : /tmp/test.sock
 *   Linux ƽ̨ĸΪ @ ڲԶó UNIX ׽ӿڽ
 * @param blocking {int} ģʽǷģʽ, ACL_BLOCKING  ACL_NON_BLOCKING
 * @param timeout {int} ӳʱʱ䣬 blocking Ϊ ACL_NON_BLOCKING ֵ
 * @return {ACL_SOCKET}  ACL_SOCKET_INVALID ʾʧ 
 */
ACL_API ACL_SOCKET acl_unix_connect(const char *addr, int blocking, int timeout);

/* in acl_stream_connect.c */
#ifdef SUNOS5
ACL_API int acl_stream_connect(const char *path, int blocking, int timeout);
#endif

#endif

#if defined(_WIN32) || defined(_WIN64)
typedef int (WINAPI *acl_connect_fn)(SOCKET, const struct sockaddr*, socklen_t);
#else
typedef int (*acl_connect_fn)(int, const struct sockaddr*, socklen_t);
#endif

ACL_API void acl_set_connect(acl_connect_fn fn);

#ifdef	__cplusplus
}
#endif

#endif
