removed all aio* files. all relevant functions are available in a different project, mio
This commit is contained in:
		| @ -1,9 +1,6 @@ | ||||
| pkgincludedir = $(includedir)/qse/si | ||||
|  | ||||
| pkginclude_HEADERS = \ | ||||
| 	aio.h \ | ||||
| 	aio-pro.h \ | ||||
| 	aio-sck.h \ | ||||
| 	cnd.h \ | ||||
| 	dir.h \ | ||||
| 	fio.h  \ | ||||
|  | ||||
| @ -133,12 +133,11 @@ am__can_run_installinfo = \ | ||||
|     n|no|NO) false;; \ | ||||
|     *) (install-info --version) >/dev/null 2>&1;; \ | ||||
|   esac | ||||
| am__pkginclude_HEADERS_DIST = aio.h aio-pro.h aio-sck.h cnd.h dir.h \ | ||||
| 	fio.h fs.h glob.h intr.h log.h mtx.h mux.h netlink.h nwad.h \ | ||||
| 	nwif.h nwio.h os.h pio.h rwl.h sck.h sinfo.h sio.h spl.h \ | ||||
| 	task.h thr.h tio.h App.hpp Condition.hpp Mutex.hpp \ | ||||
| 	SocketAddress.hpp Socket.hpp SpinLock.hpp TcpServer.hpp \ | ||||
| 	Thread.hpp | ||||
| am__pkginclude_HEADERS_DIST = cnd.h dir.h fio.h fs.h glob.h intr.h \ | ||||
| 	log.h mtx.h mux.h netlink.h nwad.h nwif.h nwio.h os.h pio.h \ | ||||
| 	rwl.h sck.h sinfo.h sio.h spl.h task.h thr.h tio.h App.hpp \ | ||||
| 	Condition.hpp Mutex.hpp SocketAddress.hpp Socket.hpp \ | ||||
| 	SpinLock.hpp TcpServer.hpp Thread.hpp | ||||
| am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | ||||
| am__vpath_adj = case $$p in \ | ||||
|     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ | ||||
| @ -355,10 +354,9 @@ target_alias = @target_alias@ | ||||
| top_build_prefix = @top_build_prefix@ | ||||
| top_builddir = @top_builddir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| pkginclude_HEADERS = aio.h aio-pro.h aio-sck.h cnd.h dir.h fio.h fs.h \ | ||||
| 	glob.h intr.h log.h mtx.h mux.h netlink.h nwad.h nwif.h nwio.h \ | ||||
| 	os.h pio.h rwl.h sck.h sinfo.h sio.h spl.h task.h thr.h tio.h \ | ||||
| 	$(am__append_1) | ||||
| pkginclude_HEADERS = cnd.h dir.h fio.h fs.h glob.h intr.h log.h mtx.h \ | ||||
| 	mux.h netlink.h nwad.h nwif.h nwio.h os.h pio.h rwl.h sck.h \ | ||||
| 	sinfo.h sio.h spl.h task.h thr.h tio.h $(am__append_1) | ||||
| all: all-am | ||||
|  | ||||
| .SUFFIXES: | ||||
|  | ||||
| @ -1,164 +0,0 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright (c) 2006-2016 Chung, Hyung-Hwan. All rights reserved. | ||||
|  | ||||
|     Redistribution and use in source and binary forms, with or without | ||||
|     modification, are permitted provided that the following conditions | ||||
|     are met: | ||||
|     1. Redistributions of source code must retain the above copyright | ||||
|        notice, this list of conditions and the following disclaimer. | ||||
|     2. Redistributions in binary form must reproduce the above copyright | ||||
|        notice, this list of conditions and the following disclaimer in the | ||||
|        documentation and/or other materials provided with the distribution. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES | ||||
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
| #ifndef _QSE_SI_AIO_PRO_H_ | ||||
| #define _QSE_SI_AIO_PRO_H_ | ||||
|  | ||||
| #include <qse/si/aio.h> | ||||
|  | ||||
| enum qse_aio_dev_pro_sid_t | ||||
| { | ||||
| 	QSE_AIO_DEV_PRO_MASTER = -1, | ||||
| 	QSE_AIO_DEV_PRO_IN     =  0, | ||||
| 	QSE_AIO_DEV_PRO_OUT    =  1, | ||||
| 	QSE_AIO_DEV_PRO_ERR    =  2 | ||||
| }; | ||||
| typedef enum qse_aio_dev_pro_sid_t qse_aio_dev_pro_sid_t; | ||||
|  | ||||
| typedef struct qse_aio_dev_pro_t qse_aio_dev_pro_t; | ||||
| typedef struct qse_aio_dev_pro_slave_t qse_aio_dev_pro_slave_t; | ||||
|  | ||||
| typedef int (*qse_aio_dev_pro_on_read_t) (qse_aio_dev_pro_t* dev, const void* data, qse_aio_iolen_t len, qse_aio_dev_pro_sid_t sid); | ||||
| typedef int (*qse_aio_dev_pro_on_write_t) (qse_aio_dev_pro_t* dev, qse_aio_iolen_t wrlen, void* wrctx); | ||||
| typedef void (*qse_aio_dev_pro_on_close_t) (qse_aio_dev_pro_t* dev, qse_aio_dev_pro_sid_t sid); | ||||
|  | ||||
| struct qse_aio_dev_pro_t | ||||
| { | ||||
| 	QSE_AIO_DEV_HEADERS; | ||||
|  | ||||
| 	int flags; | ||||
| 	qse_intptr_t child_pid; /* defined to qse_intptr_t to hide pid_t */ | ||||
| 	qse_aio_dev_pro_slave_t* slave[3]; | ||||
| 	int slave_count; | ||||
|  | ||||
| 	qse_aio_dev_pro_on_read_t on_read; | ||||
| 	qse_aio_dev_pro_on_write_t on_write; | ||||
| 	qse_aio_dev_pro_on_close_t on_close; | ||||
|  | ||||
| 	qse_mchar_t* mcmd; | ||||
| }; | ||||
|  | ||||
| struct qse_aio_dev_pro_slave_t | ||||
| { | ||||
| 	QSE_AIO_DEV_HEADERS; | ||||
| 	qse_aio_dev_pro_sid_t id; | ||||
| 	qse_aio_syshnd_t pfd; | ||||
| 	qse_aio_dev_pro_t* master; /* parent device */ | ||||
| }; | ||||
|  | ||||
| enum qse_aio_dev_pro_make_flag_t | ||||
| { | ||||
| 	QSE_AIO_DEV_PRO_WRITEIN  = (1 << 0), | ||||
| 	QSE_AIO_DEV_PRO_READOUT  = (1 << 1), | ||||
| 	QSE_AIO_DEV_PRO_READERR  = (1 << 2), | ||||
|  | ||||
| 	QSE_AIO_DEV_PRO_ERRTOOUT = (1 << 3), | ||||
| 	QSE_AIO_DEV_PRO_OUTTOERR = (1 << 4), | ||||
|  | ||||
| 	QSE_AIO_DEV_PRO_INTONUL  = (1 << 5), | ||||
| 	QSE_AIO_DEV_PRO_OUTTONUL = (1 << 6), | ||||
| 	QSE_AIO_DEV_PRO_ERRTONUL = (1 << 7), | ||||
|  | ||||
| 	STUO_DEV_PRO_DROPIN   = (1 << 8), | ||||
| 	STUO_DEV_PRO_DROPOUT  = (1 << 9), | ||||
| 	STUO_DEV_PRO_DROPERR  = (1 << 10), | ||||
|  | ||||
|  | ||||
| 	QSE_AIO_DEV_PRO_SHELL                = (1 << 13), | ||||
|  | ||||
| 	/* perform no waitpid() on a child process upon device destruction. | ||||
| 	 * you should set this flag if your application has automatic child  | ||||
| 	 * process reaping enabled. for instance, SIGCHLD is set to SIG_IGN | ||||
| 	 * on POSIX.1-2001 compliant systems */ | ||||
| 	QSE_AIO_DEV_PRO_FORGET_CHILD         = (1 << 14), | ||||
|  | ||||
|  | ||||
| 	QSE_AIO_DEV_PRO_FORGET_DIEHARD_CHILD = (1 << 15) | ||||
| }; | ||||
| typedef enum qse_aio_dev_pro_make_flag_t qse_aio_dev_pro_make_flag_t; | ||||
|  | ||||
| typedef struct qse_aio_dev_pro_make_t qse_aio_dev_pro_make_t; | ||||
| struct qse_aio_dev_pro_make_t | ||||
| { | ||||
| 	int flags; /**< bitwise-ORed of qse_aio_dev_pro_make_flag_t enumerators */ | ||||
| 	const void* cmd; | ||||
| 	qse_aio_dev_pro_on_write_t on_write; /* mandatory */ | ||||
| 	qse_aio_dev_pro_on_read_t on_read; /* mandatory */ | ||||
| 	qse_aio_dev_pro_on_close_t on_close; /* optional */ | ||||
| }; | ||||
|  | ||||
|  | ||||
| enum qse_aio_dev_pro_ioctl_cmd_t | ||||
| { | ||||
| 	QSE_AIO_DEV_PRO_CLOSE, | ||||
| 	QSE_AIO_DEV_PRO_KILL_CHILD | ||||
| }; | ||||
| typedef enum qse_aio_dev_pro_ioctl_cmd_t qse_aio_dev_pro_ioctl_cmd_t; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| QSE_EXPORT  qse_aio_dev_pro_t* qse_aio_dev_pro_make ( | ||||
| 	qse_aio_t*                    aio, | ||||
| 	qse_size_t                xtnsize, | ||||
| 	const qse_aio_dev_pro_make_t* data | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT void qse_aio_dev_pro_kill ( | ||||
| 	qse_aio_dev_pro_t* pro | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_pro_write ( | ||||
| 	qse_aio_dev_pro_t*  pro, | ||||
| 	const void*         data, | ||||
| 	qse_aio_iolen_t     len, | ||||
| 	void*               wrctx | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_pro_timedwrite ( | ||||
| 	qse_aio_dev_pro_t*  pro, | ||||
| 	const void*         data, | ||||
| 	qse_aio_iolen_t     len, | ||||
| 	const qse_ntime_t*  tmout, | ||||
| 	void*               wrctx | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_pro_close ( | ||||
| 	qse_aio_dev_pro_t*     pro, | ||||
| 	qse_aio_dev_pro_sid_t  sid | ||||
| ); | ||||
|  | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_pro_killchild ( | ||||
| 	qse_aio_dev_pro_t*     pro | ||||
| ); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
| @ -1,597 +0,0 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright (c) 2006-2016 Chung, Hyung-Hwan. All rights reserved. | ||||
|  | ||||
|     Redistribution and use in source and binary forms, with or without | ||||
|     modification, are permitted provided that the following conditions | ||||
|     are met: | ||||
|     1. Redistributions of source code must retain the above copyright | ||||
|        notice, this list of conditions and the following disclaimer. | ||||
|     2. Redistributions in binary form must reproduce the above copyright | ||||
|        notice, this list of conditions and the following disclaimer in the | ||||
|        documentation and/or other materials provided with the distribution. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES | ||||
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
| #ifndef _QSE_SI_AIO_SCK_H_ | ||||
| #define _QSE_SI_AIO_SCK_H_ | ||||
|  | ||||
| #include <qse/si/aio.h> | ||||
|  | ||||
| /* ========================================================================= */ | ||||
| /* TOOD: move these to a separte file */ | ||||
|  | ||||
| #define QSE_AIO_ETHHDR_PROTO_IP4   0x0800 | ||||
| #define QSE_AIO_ETHHDR_PROTO_ARP   0x0806 | ||||
| #define QSE_AIO_ETHHDR_PROTO_8021Q 0x8100 /* 802.1Q VLAN */ | ||||
| #define QSE_AIO_ETHHDR_PROTO_IP6   0x86DD | ||||
|  | ||||
|  | ||||
| #define QSE_AIO_ARPHDR_OPCODE_REQUEST 1 | ||||
| #define QSE_AIO_ARPHDR_OPCODE_REPLY   2 | ||||
|  | ||||
| #define QSE_AIO_ARPHDR_HTYPE_ETH 0x0001 | ||||
| #define QSE_AIO_ARPHDR_PTYPE_IP4 0x0800 | ||||
|  | ||||
| #define QSE_AIO_ETHADDR_LEN 6 | ||||
| #define QSE_AIO_IP4ADDR_LEN 4 | ||||
| #define QSE_AIO_IP6ADDR_LEN 16  | ||||
|  | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| #	define QSE_AIO_PACKED __attribute__((__packed__)) | ||||
|  | ||||
| #else | ||||
| #	define QSE_AIO_PACKED  | ||||
| #	QSE_AIO_PACK_PUSH pack(push) | ||||
| #	QSE_AIO_PACK_PUSH pack(push) | ||||
| #	QSE_AIO_PACK(x) pack(x) | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| 	/* nothing */ | ||||
| #else | ||||
| 	#pragma pack(push) | ||||
| 	#pragma pack(1) | ||||
| #endif | ||||
| struct QSE_AIO_PACKED qse_aio_ethaddr_t | ||||
| { | ||||
| 	qse_uint8_t v[QSE_AIO_ETHADDR_LEN];  | ||||
| }; | ||||
| typedef struct qse_aio_ethaddr_t qse_aio_ethaddr_t; | ||||
|  | ||||
| struct QSE_AIO_PACKED qse_aio_ip4addr_t | ||||
| { | ||||
| 	qse_uint8_t v[QSE_AIO_IP4ADDR_LEN]; | ||||
| }; | ||||
| typedef struct qse_aio_ip4addr_t qse_aio_ip4addr_t; | ||||
|  | ||||
| struct QSE_AIO_PACKED qse_aio_ip6addr_t | ||||
| { | ||||
| 	qse_uint8_t v[QSE_AIO_IP6ADDR_LEN];  | ||||
| }; | ||||
| typedef struct qse_aio_ip6addr_t qse_aio_ip6addr_t; | ||||
|  | ||||
| struct QSE_AIO_PACKED qse_aio_ethhdr_t | ||||
| { | ||||
| 	qse_uint8_t  dest[QSE_AIO_ETHADDR_LEN]; | ||||
| 	qse_uint8_t  source[QSE_AIO_ETHADDR_LEN]; | ||||
| 	qse_uint16_t proto; | ||||
| }; | ||||
| typedef struct qse_aio_ethhdr_t qse_aio_ethhdr_t; | ||||
|  | ||||
| struct QSE_AIO_PACKED qse_aio_arphdr_t | ||||
| { | ||||
| 	qse_uint16_t htype;   /* hardware type (ethernet: 0x0001) */ | ||||
| 	qse_uint16_t ptype;   /* protocol type (ipv4: 0x0800) */ | ||||
| 	qse_uint8_t  hlen;    /* hardware address length (ethernet: 6) */ | ||||
| 	qse_uint8_t  plen;    /* protocol address length (ipv4 :4) */ | ||||
| 	qse_uint16_t opcode;  /* operation code */ | ||||
| }; | ||||
| typedef struct qse_aio_arphdr_t qse_aio_arphdr_t; | ||||
|  | ||||
| /* arp payload for ipv4 over ethernet */ | ||||
| struct QSE_AIO_PACKED qse_aio_etharp_t | ||||
| { | ||||
| 	qse_uint8_t sha[QSE_AIO_ETHADDR_LEN];   /* source hardware address */ | ||||
| 	qse_uint8_t spa[QSE_AIO_IP4ADDR_LEN];   /* source protocol address */ | ||||
| 	qse_uint8_t tha[QSE_AIO_ETHADDR_LEN];   /* target hardware address */ | ||||
| 	qse_uint8_t tpa[QSE_AIO_IP4ADDR_LEN];   /* target protocol address */ | ||||
| }; | ||||
| typedef struct qse_aio_etharp_t qse_aio_etharp_t; | ||||
|  | ||||
| struct QSE_AIO_PACKED qse_aio_etharp_pkt_t | ||||
| { | ||||
| 	qse_aio_ethhdr_t ethhdr; | ||||
| 	qse_aio_arphdr_t arphdr; | ||||
| 	qse_aio_etharp_t arppld; | ||||
| }; | ||||
| typedef struct qse_aio_etharp_pkt_t qse_aio_etharp_pkt_t; | ||||
|  | ||||
|  | ||||
| struct qse_aio_iphdr_t | ||||
| { | ||||
| #if defined(QSE_ENDIAN_LITTLE) | ||||
| 	qse_uint8_t ihl:4; | ||||
| 	qse_uint8_t version:4; | ||||
| #elif defined(QSE_ENDIAN_BIG) | ||||
| 	qse_uint8_t version:4; | ||||
| 	qse_uint8_t ihl:4; | ||||
| #else | ||||
| #	UNSUPPORTED ENDIAN | ||||
| #endif | ||||
| 	qse_int8_t tos; | ||||
| 	qse_int16_t tot_len; | ||||
| 	qse_int16_t id; | ||||
| 	qse_int16_t frag_off; | ||||
| 	qse_int8_t ttl; | ||||
| 	qse_int8_t protocol; | ||||
| 	qse_int16_t check; | ||||
| 	qse_int32_t saddr; | ||||
| 	qse_int32_t daddr; | ||||
| 	/*The options start here. */ | ||||
| }; | ||||
| typedef struct qse_aio_iphdr_t qse_aio_iphdr_t; | ||||
|  | ||||
|  | ||||
| struct QSE_AIO_PACKED qse_aio_icmphdr_t  | ||||
| { | ||||
| 	qse_uint8_t type; /* message type */ | ||||
| 	qse_uint8_t code; /* subcode */ | ||||
| 	qse_uint16_t checksum; | ||||
| 	union | ||||
| 	{ | ||||
| 		struct | ||||
| 		{ | ||||
| 			qse_uint16_t id; | ||||
| 			qse_uint16_t seq; | ||||
| 		} echo; | ||||
|  | ||||
| 		qse_uint32_t gateway; | ||||
|  | ||||
| 		struct | ||||
| 		{ | ||||
| 			qse_uint16_t frag_unused; | ||||
| 			qse_uint16_t mtu; | ||||
| 		} frag; /* path mut discovery */ | ||||
| 	} u; | ||||
| }; | ||||
| typedef struct qse_aio_icmphdr_t qse_aio_icmphdr_t; | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| 	/* nothing */ | ||||
| #else | ||||
| 	#pragma pack(pop) | ||||
| #endif | ||||
|  | ||||
| /* ICMP types */ | ||||
| #define QSE_AIO_ICMP_ECHO_REPLY        0 | ||||
| #define QSE_AIO_ICMP_UNREACH           3 /* destination unreachable */ | ||||
| #define QSE_AIO_ICMP_SOURCE_QUENCE     4 | ||||
| #define QSE_AIO_ICMP_REDIRECT          5 | ||||
| #define QSE_AIO_ICMP_ECHO_REQUEST      8 | ||||
| #define QSE_AIO_ICMP_TIME_EXCEEDED     11 | ||||
| #define QSE_AIO_ICMP_PARAM_PROBLEM     12 | ||||
| #define QSE_AIO_ICMP_TIMESTAMP_REQUEST 13 | ||||
| #define QSE_AIO_ICMP_TIMESTAMP_REPLY   14 | ||||
| #define QSE_AIO_ICMP_INFO_REQUEST      15 | ||||
| #define QSE_AIO_ICMP_INFO_REPLY        16 | ||||
| #define QSE_AIO_ICMP_ADDR_MASK_REQUEST 17 | ||||
| #define QSE_AIO_ICMP_ADDR_MASK_REPLY   18 | ||||
|  | ||||
| /* Subcode for QSE_AIO_ICMP_UNREACH */ | ||||
| #define QSE_AIO_ICMP_UNREACH_NET          0 | ||||
| #define QSE_AIO_ICMP_UNREACH_HOST         1 | ||||
| #define QSE_AIO_ICMP_UNREACH_PROTOCOL     2 | ||||
| #define QSE_AIO_ICMP_UNREACH_PORT         3 | ||||
| #define QSE_AIO_ICMP_UNREACH_FRAG_NEEDED  4 | ||||
|  | ||||
| /* Subcode for QSE_AIO_ICMP_REDIRECT */ | ||||
| #define QSE_AIO_ICMP_REDIRECT_NET      0 | ||||
| #define QSE_AIO_ICMP_REDIRECT_HOST     1 | ||||
| #define QSE_AIO_ICMP_REDIRECT_NETTOS   2 | ||||
| #define QSE_AIO_ICMP_REDIRECT_HOSTTOS  3 | ||||
|  | ||||
| /* Subcode for QSE_AIO_ICMP_TIME_EXCEEDED */ | ||||
| #define QSE_AIO_ICMP_TIME_EXCEEDED_TTL       0 | ||||
| #define QSE_AIO_ICMP_TIME_EXCEEDED_FRAGTIME  1 | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| typedef int qse_aio_sckfam_t; | ||||
|  | ||||
| struct qse_aio_sckaddr_t | ||||
| { | ||||
| 	qse_aio_sckfam_t family; | ||||
| 	qse_uint8_t data[128]; /* TODO: use the actual sockaddr size */ | ||||
| }; | ||||
| typedef struct qse_aio_sckaddr_t qse_aio_sckaddr_t; | ||||
|  | ||||
| #if (QSE_SIZEOF_SOCKLEN_T == QSE_SIZEOF_INT) | ||||
| 	#if defined(QSE_AIO_SOCKLEN_T_IS_SIGNED) | ||||
| 		typedef int qse_aio_scklen_t; | ||||
| 	#else | ||||
| 		typedef unsigned int qse_aio_scklen_t; | ||||
| 	#endif | ||||
| #elif (QSE_SIZEOF_SOCKLEN_T == QSE_SIZEOF_LONG) | ||||
| 	#if defined(QSE_AIO_SOCKLEN_T_IS_SIGNED) | ||||
| 		typedef long qse_aio_scklen_t; | ||||
| 	#else | ||||
| 		typedef unsigned long qse_aio_scklen_t; | ||||
| 	#endif | ||||
| #else | ||||
| 	typedef int qse_aio_scklen_t; | ||||
| #endif | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| #	define QSE_AIO_IOCP_KEY 1 | ||||
| 	/* | ||||
| 	typedef HANDLE qse_aio_syshnd_t; | ||||
| 	typedef SOCKET qse_aio_sckhnd_t; | ||||
| #	define QSE_AIO_SCKHND_INVALID (INVALID_SOCKET) | ||||
| 	*/ | ||||
|  | ||||
| 	typedef qse_uintptr_t qse_aio_sckhnd_t; | ||||
| #	define QSE_AIO_SCKHND_INVALID (~(qse_aio_sck_hnd_t)0) | ||||
|  | ||||
| #else | ||||
| 	typedef int qse_aio_sckhnd_t; | ||||
| #	define QSE_AIO_SCKHND_INVALID (-1) | ||||
| 	 | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| enum qse_aio_dev_sck_ioctl_cmd_t | ||||
| { | ||||
| 	QSE_AIO_DEV_SCK_BIND,  | ||||
| 	QSE_AIO_DEV_SCK_CONNECT, | ||||
| 	QSE_AIO_DEV_SCK_LISTEN | ||||
| }; | ||||
| typedef enum qse_aio_dev_sck_ioctl_cmd_t qse_aio_dev_sck_ioctl_cmd_t; | ||||
|  | ||||
|  | ||||
| #define QSE_AIO_DEV_SCK_SET_PROGRESS(dev,bit) do { \ | ||||
| 	(dev)->state &= ~QSE_AIO_DEV_SCK_ALL_PROGRESS_BITS; \ | ||||
| 	(dev)->state |= (bit); \ | ||||
| } while(0) | ||||
|  | ||||
| #define QSE_AIO_DEV_SCK_GET_PROGRESS(dev) ((dev)->state & QSE_AIO_DEV_SCK_ALL_PROGRESS_BITS) | ||||
|  | ||||
| enum qse_aio_dev_sck_state_t | ||||
| { | ||||
| 	/* the following items(progress bits) are mutually exclusive */ | ||||
| 	QSE_AIO_DEV_SCK_CONNECTING     = (1 << 0), | ||||
| 	QSE_AIO_DEV_SCK_CONNECTING_SSL = (1 << 1), | ||||
| 	QSE_AIO_DEV_SCK_CONNECTED      = (1 << 2), | ||||
| 	QSE_AIO_DEV_SCK_LISTENING      = (1 << 3), | ||||
| 	QSE_AIO_DEV_SCK_ACCEPTING_SSL  = (1 << 4), | ||||
| 	QSE_AIO_DEV_SCK_ACCEPTED       = (1 << 5), | ||||
|  | ||||
| 	/* the following items can be bitwise-ORed with an exclusive item above */ | ||||
| 	QSE_AIO_DEV_SCK_INTERCEPTED    = (1 << 15), | ||||
|  | ||||
|  | ||||
| 	/* convenience bit masks */ | ||||
| 	QSE_AIO_DEV_SCK_ALL_PROGRESS_BITS = (QSE_AIO_DEV_SCK_CONNECTING | | ||||
| 	                                  QSE_AIO_DEV_SCK_CONNECTING_SSL | | ||||
| 	                                  QSE_AIO_DEV_SCK_CONNECTED | | ||||
| 	                                  QSE_AIO_DEV_SCK_LISTENING | | ||||
| 	                                  QSE_AIO_DEV_SCK_ACCEPTING_SSL | | ||||
| 	                                  QSE_AIO_DEV_SCK_ACCEPTED) | ||||
| }; | ||||
| typedef enum qse_aio_dev_sck_state_t qse_aio_dev_sck_state_t; | ||||
|  | ||||
| typedef struct qse_aio_dev_sck_t qse_aio_dev_sck_t; | ||||
|  | ||||
| typedef int (*qse_aio_dev_sck_on_read_t) ( | ||||
| 	qse_aio_dev_sck_t*       dev, | ||||
| 	const void*           data, | ||||
| 	qse_aio_iolen_t          dlen, | ||||
| 	const qse_aio_sckaddr_t* srcaddr | ||||
| ); | ||||
|  | ||||
| typedef int (*qse_aio_dev_sck_on_write_t) ( | ||||
| 	qse_aio_dev_sck_t*       dev, | ||||
| 	qse_aio_iolen_t          wrlen, | ||||
| 	void*                 wrctx, | ||||
| 	const qse_aio_sckaddr_t* dstaddr | ||||
| ); | ||||
|  | ||||
| typedef void (*qse_aio_dev_sck_on_disconnect_t) ( | ||||
| 	qse_aio_dev_sck_t* dev | ||||
| ); | ||||
|  | ||||
| typedef int (*qse_aio_dev_sck_on_connect_t) ( | ||||
| 	qse_aio_dev_sck_t* dev | ||||
| ); | ||||
|  | ||||
| enum qse_aio_dev_sck_type_t | ||||
| { | ||||
| 	QSE_AIO_DEV_SCK_TCP4, | ||||
| 	QSE_AIO_DEV_SCK_TCP6, | ||||
| 	QSE_AIO_DEV_SCK_UPD4, | ||||
| 	QSE_AIO_DEV_SCK_UDP6, | ||||
|  | ||||
| 	/* ARP at the ethernet layer */ | ||||
| 	QSE_AIO_DEV_SCK_ARP, | ||||
| 	QSE_AIO_DEV_SCK_ARP_DGRAM, | ||||
|  | ||||
| 	/* ICMP at the IPv4 layer */ | ||||
| 	QSE_AIO_DEV_SCK_ICMP4, | ||||
|  | ||||
| 	/* ICMP at the IPv6 layer */ | ||||
| 	QSE_AIO_DEV_SCK_ICMP6 | ||||
|  | ||||
| #if 0 | ||||
| 	QSE_AIO_DEV_SCK_RAW,  /* raw L2-level packet */ | ||||
| #endif | ||||
| }; | ||||
| typedef enum qse_aio_dev_sck_type_t qse_aio_dev_sck_type_t; | ||||
|  | ||||
| typedef struct qse_aio_dev_sck_make_t qse_aio_dev_sck_make_t; | ||||
| struct qse_aio_dev_sck_make_t | ||||
| { | ||||
| 	qse_aio_dev_sck_type_t type; | ||||
| 	qse_aio_dev_sck_on_write_t on_write; | ||||
| 	qse_aio_dev_sck_on_read_t on_read; | ||||
| 	qse_aio_dev_sck_on_disconnect_t on_disconnect; | ||||
| }; | ||||
|  | ||||
| enum qse_aio_dev_sck_bind_option_t | ||||
| { | ||||
| 	QSE_AIO_DEV_SCK_BIND_BROADCAST   = (1 << 0), | ||||
| 	QSE_AIO_DEV_SCK_BIND_REUSEADDR   = (1 << 1), | ||||
| 	QSE_AIO_DEV_SCK_BIND_REUSEPORT   = (1 << 2), | ||||
| 	QSE_AIO_DEV_SCK_BIND_TRANSPARENT = (1 << 3), | ||||
|  | ||||
| /* TODO: more options --- SO_RCVBUF, SO_SNDBUF, SO_RCVTIMEO, SO_SNDTIMEO, SO_KEEPALIVE */ | ||||
| /*   BINDTODEVICE??? */ | ||||
|  | ||||
| 	QSE_AIO_DEV_SCK_BIND_SSL         = (1 << 15) | ||||
| }; | ||||
| typedef enum qse_aio_dev_sck_bind_option_t qse_aio_dev_sck_bind_option_t; | ||||
|  | ||||
| typedef struct qse_aio_dev_sck_bind_t qse_aio_dev_sck_bind_t; | ||||
| struct qse_aio_dev_sck_bind_t | ||||
| { | ||||
| 	int options; | ||||
| 	qse_aio_sckaddr_t localaddr; | ||||
| 	/* TODO: add device name for BIND_TO_DEVICE */ | ||||
|  | ||||
| 	const qse_mchar_t* ssl_certfile; | ||||
| 	const qse_mchar_t* ssl_keyfile; | ||||
| 	qse_ntime_t accept_tmout; | ||||
| }; | ||||
|  | ||||
| enum qse_aio_def_sck_connect_option_t | ||||
| { | ||||
| 	QSE_AIO_DEV_SCK_CONNECT_SSL = (1 << 15) | ||||
| }; | ||||
| typedef enum qse_aio_dev_sck_connect_option_t qse_aio_dev_sck_connect_option_t; | ||||
|  | ||||
| typedef struct qse_aio_dev_sck_connect_t qse_aio_dev_sck_connect_t; | ||||
| struct qse_aio_dev_sck_connect_t | ||||
| { | ||||
| 	int options; | ||||
| 	qse_aio_sckaddr_t remoteaddr; | ||||
| 	qse_ntime_t connect_tmout; | ||||
| 	qse_aio_dev_sck_on_connect_t on_connect; | ||||
| }; | ||||
|  | ||||
| typedef struct qse_aio_dev_sck_listen_t qse_aio_dev_sck_listen_t; | ||||
| struct qse_aio_dev_sck_listen_t | ||||
| { | ||||
| 	int backlogs; | ||||
| 	qse_aio_dev_sck_on_connect_t on_connect; /* optional, but new connections are dropped immediately without this */ | ||||
| }; | ||||
|  | ||||
| typedef struct qse_aio_dev_sck_accept_t qse_aio_dev_sck_accept_t; | ||||
| struct qse_aio_dev_sck_accept_t | ||||
| { | ||||
| 	qse_aio_syshnd_t  sck; | ||||
| /* TODO: add timeout */ | ||||
| 	qse_aio_sckaddr_t remoteaddr; | ||||
| }; | ||||
|  | ||||
| struct qse_aio_dev_sck_t | ||||
| { | ||||
| 	QSE_AIO_DEV_HEADERS; | ||||
|  | ||||
| 	qse_aio_dev_sck_type_t type; | ||||
| 	qse_aio_sckhnd_t sck; | ||||
|  | ||||
| 	int state; | ||||
|  | ||||
| 	/* remote peer address for a stateful stream socket. valid if one of the  | ||||
| 	 * followings is set in state: | ||||
| 	 *   QSE_AIO_DEV_TCP_ACCEPTING_SSL | ||||
| 	 *   QSE_AIO_DEV_TCP_ACCEPTED | ||||
| 	 *   QSE_AIO_DEV_TCP_CONNECTED | ||||
| 	 *   QSE_AIO_DEV_TCP_CONNECTING | ||||
| 	 *   QSE_AIO_DEV_TCP_CONNECTING_SSL | ||||
| 	 * | ||||
| 	 * also used as a placeholder to store source address for | ||||
| 	 * a stateless socket */ | ||||
| 	qse_aio_sckaddr_t remoteaddr;  | ||||
|  | ||||
| 	/* local socket address */ | ||||
| 	qse_aio_sckaddr_t localaddr; | ||||
|  | ||||
| 	/* original destination address */ | ||||
| 	qse_aio_sckaddr_t orgdstaddr; | ||||
|  | ||||
| 	qse_aio_dev_sck_on_write_t on_write; | ||||
| 	qse_aio_dev_sck_on_read_t on_read; | ||||
|  | ||||
| 	/* return 0 on succes, -1 on failure. | ||||
| 	 * called on a new tcp device for an accepted client or | ||||
| 	 *        on a tcp device conntected to a remote server */ | ||||
| 	qse_aio_dev_sck_on_connect_t on_connect; | ||||
| 	qse_aio_dev_sck_on_disconnect_t on_disconnect; | ||||
|  | ||||
| 	/* timer job index for handling | ||||
| 	 *  - connect() timeout for a connecting socket. | ||||
| 	 *  - SSL_accept() timeout for a socket accepting SSL */ | ||||
| 	qse_aio_tmridx_t tmrjob_index; | ||||
|  | ||||
| 	/* connect timeout, ssl-connect timeout, ssl-accept timeout. | ||||
| 	 * it denotes timeout duration under some circumstances | ||||
| 	 * or an absolute expiry time under some other circumstances. */ | ||||
| 	qse_ntime_t tmout; | ||||
|  | ||||
| 	void* ssl_ctx; | ||||
| 	void* ssl; | ||||
|  | ||||
| }; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| QSE_EXPORT qse_aio_sckhnd_t qse_aio_openasyncsck ( | ||||
| 	qse_aio_t* aio, | ||||
| 	int     domain,  | ||||
| 	int     type, | ||||
| 	int     proto | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT void qse_aio_closeasyncsck ( | ||||
| 	qse_aio_t*       aio, | ||||
| 	qse_aio_sckhnd_t sck | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_makesckasync ( | ||||
| 	qse_aio_t*       aio, | ||||
| 	qse_aio_sckhnd_t sck | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_getsckaddrinfo ( | ||||
| 	qse_aio_t*                aio, | ||||
| 	const qse_aio_sckaddr_t*  addr, | ||||
| 	qse_aio_scklen_t*         len, | ||||
| 	qse_aio_sckfam_t*         family | ||||
| ); | ||||
|  | ||||
| /* | ||||
|  * The qse_aio_getsckaddrport() function returns the port number of a socket | ||||
|  * address in the host byte order. If the address doesn't support the port | ||||
|  * number, it returns 0. | ||||
|  */ | ||||
| QSE_EXPORT qse_uint16_t qse_aio_getsckaddrport ( | ||||
| 	const qse_aio_sckaddr_t* addr | ||||
| ); | ||||
|  | ||||
| /* | ||||
|  * The qse_aio_getsckaddrifindex() function returns an interface number. | ||||
|  * If the address doesn't support the interface number, it returns 0. */ | ||||
| QSE_EXPORT int qse_aio_getsckaddrifindex ( | ||||
| 	const qse_aio_sckaddr_t* addr | ||||
| ); | ||||
|  | ||||
|  | ||||
| QSE_EXPORT void qse_aio_sckaddr_initforip4 ( | ||||
| 	qse_aio_sckaddr_t* sckaddr, | ||||
| 	qse_uint16_t   port, | ||||
| 	qse_aio_ip4addr_t* ip4addr | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT void qse_aio_sckaddr_initforip6 ( | ||||
| 	qse_aio_sckaddr_t* sckaddr, | ||||
| 	qse_uint16_t   port, | ||||
| 	qse_aio_ip6addr_t* ip6addr | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT void qse_aio_sckaddr_initforeth ( | ||||
| 	qse_aio_sckaddr_t* sckaddr, | ||||
| 	int                ifindex, | ||||
| 	qse_aio_ethaddr_t* ethaddr | ||||
| ); | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| QSE_EXPORT qse_aio_dev_sck_t* qse_aio_dev_sck_make ( | ||||
| 	qse_aio_t*                    aio, | ||||
| 	qse_size_t                    xtnsize, | ||||
| 	const qse_aio_dev_sck_make_t* info | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_sck_bind ( | ||||
| 	qse_aio_dev_sck_t*         dev, | ||||
| 	qse_aio_dev_sck_bind_t*    info | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_sck_connect ( | ||||
| 	qse_aio_dev_sck_t*         dev, | ||||
| 	qse_aio_dev_sck_connect_t* info | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_sck_listen ( | ||||
| 	qse_aio_dev_sck_t*         dev, | ||||
| 	qse_aio_dev_sck_listen_t*  info | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_sck_write ( | ||||
| 	qse_aio_dev_sck_t*        dev, | ||||
| 	const void*               data, | ||||
| 	qse_aio_iolen_t           len, | ||||
| 	void*                     wrctx, | ||||
| 	const qse_aio_sckaddr_t*  dstaddr | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_sck_timedwrite ( | ||||
| 	qse_aio_dev_sck_t*        dev, | ||||
| 	const void*               data, | ||||
| 	qse_aio_iolen_t           len, | ||||
| 	const qse_ntime_t*        tmout, | ||||
| 	void*                     wrctx, | ||||
| 	const qse_aio_sckaddr_t*  dstaddr | ||||
| ); | ||||
|  | ||||
| #if defined(QSE_AIO_HAVE_INLINE) | ||||
|  | ||||
| static QSE_INLINE void qse_aio_dev_sck_halt (qse_aio_dev_sck_t* sck) | ||||
| { | ||||
| 	qse_aio_dev_halt ((qse_aio_dev_t*)sck); | ||||
| } | ||||
|  | ||||
| static QSE_INLINE int qse_aio_dev_sck_read (qse_aio_dev_sck_t* sck, int enabled) | ||||
| { | ||||
| 	return qse_aio_dev_read ((qse_aio_dev_t*)sck, enabled); | ||||
| } | ||||
|  | ||||
| #else | ||||
|  | ||||
| #define qse_aio_dev_sck_halt(sck) qse_aio_dev_halt((qse_aio_dev_t*)sck) | ||||
| #define qse_aio_dev_sck_read(sck,enabled) qse_aio_dev_read((qse_aio_dev_t*)sck, enabled) | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| QSE_EXPORT qse_uint16_t qse_aio_checksumip ( | ||||
| 	const void* hdr, | ||||
| 	qse_size_t  len | ||||
| ); | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| #endif | ||||
| @ -1,438 +0,0 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright (c) 2006-2016 Chung, Hyung-Hwan. All rights reserved. | ||||
|  | ||||
|     Redistribution and use in source and binary forms, with or without | ||||
|     modification, are permitted provided that the following conditions | ||||
|     are met: | ||||
|     1. Redistributions of source code must retain the above copyright | ||||
|        notice, this list of conditions and the following disclaimer. | ||||
|     2. Redistributions in binary form must reproduce the above copyright | ||||
|        notice, this list of conditions and the following disclaimer in the | ||||
|        documentation and/or other materials provided with the distribution. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES | ||||
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
| #ifndef _QSE_SI_AIO_H_ | ||||
| #define _QSE_SI_AIO_H_ | ||||
|  | ||||
| #include <qse/types.h> | ||||
| #include <qse/macros.h> | ||||
| #include <qse/cmn/time.h> | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| 	typedef qse_uintptr_t qse_aio_syshnd_t; | ||||
| 	#define QSE_AIO_SYSHND_INVALID (~(qse_uintptr_t)0) | ||||
| #else | ||||
| 	typedef int qse_aio_syshnd_t; | ||||
| 	#define QSE_AIO_SYSHND_INVALID (-1) | ||||
| #endif | ||||
|  | ||||
| typedef struct qse_aio_devaddr_t qse_aio_devaddr_t; | ||||
| struct qse_aio_devaddr_t | ||||
| { | ||||
| 	int len; | ||||
| 	void* ptr; | ||||
| }; | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| typedef struct qse_aio_t qse_aio_t; | ||||
| typedef struct qse_aio_dev_t qse_aio_dev_t; | ||||
| typedef struct qse_aio_dev_mth_t qse_aio_dev_mth_t; | ||||
| typedef struct qse_aio_dev_evcb_t qse_aio_dev_evcb_t; | ||||
|  | ||||
| typedef struct qse_aio_wq_t qse_aio_wq_t; | ||||
| typedef qse_intptr_t qse_aio_iolen_t; /* NOTE: this is a signed type */ | ||||
|  | ||||
| enum qse_aio_errnum_t | ||||
| { | ||||
| 	QSE_AIO_ENOERR, | ||||
| 	QSE_AIO_ENOIMPL, | ||||
| 	QSE_AIO_ESYSERR, | ||||
| 	QSE_AIO_EINTERN, | ||||
|  | ||||
| 	QSE_AIO_ENOMEM, | ||||
| 	QSE_AIO_EINVAL, | ||||
| 	QSE_AIO_EEXIST, | ||||
| 	QSE_AIO_ENOENT, | ||||
| 	QSE_AIO_ENOSUP,     /* not supported */ | ||||
| 	QSE_AIO_EMFILE,     /* too many open files */ | ||||
| 	QSE_AIO_ENFILE, | ||||
| 	QSE_AIO_EAGAIN, | ||||
| 	QSE_AIO_ECONRF,     /* connection refused */ | ||||
| 	QSE_AIO_ECONRS,     /* connection reset */ | ||||
| 	QSE_AIO_ENOCAPA,    /* no capability */ | ||||
| 	QSE_AIO_ETMOUT,     /* timed out */ | ||||
| 	QSE_AIO_EPERM,      /* operation not permitted */ | ||||
|  | ||||
| 	QSE_AIO_EDEVMAKE, | ||||
| 	QSE_AIO_EDEVERR, | ||||
| 	QSE_AIO_EDEVHUP | ||||
| }; | ||||
|  | ||||
| typedef enum qse_aio_errnum_t qse_aio_errnum_t; | ||||
|  | ||||
| enum qse_aio_stopreq_t | ||||
| { | ||||
| 	QSE_AIO_STOPREQ_NONE = 0, | ||||
| 	QSE_AIO_STOPREQ_TERMINATION, | ||||
| 	QSE_AIO_STOPREQ_WATCHER_ERROR | ||||
| }; | ||||
| typedef enum qse_aio_stopreq_t qse_aio_stopreq_t; | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| #define QSE_AIO_TMRIDX_INVALID ((qse_aio_tmridx_t)-1) | ||||
|  | ||||
| typedef qse_size_t qse_aio_tmridx_t; | ||||
|  | ||||
| typedef struct qse_aio_tmrjob_t qse_aio_tmrjob_t; | ||||
|  | ||||
| typedef void (*qse_aio_tmrjob_handler_t) ( | ||||
| 	qse_aio_t*           aio, | ||||
| 	const qse_ntime_t*   now,  | ||||
| 	qse_aio_tmrjob_t*    tmrjob | ||||
| ); | ||||
|  | ||||
| struct qse_aio_tmrjob_t | ||||
| { | ||||
| 	void*                     ctx; | ||||
| 	qse_ntime_t               when; | ||||
| 	qse_aio_tmrjob_handler_t  handler; | ||||
| 	qse_aio_tmridx_t*         idxptr; /* pointer to the index holder */ | ||||
| }; | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| struct qse_aio_dev_mth_t | ||||
| { | ||||
| 	/* ------------------------------------------------------------------ */ | ||||
| 	/* mandatory. called in qse_aio_makedev() */ | ||||
| 	int           (*make)         (qse_aio_dev_t* dev, void* ctx);  | ||||
|  | ||||
| 	/* ------------------------------------------------------------------ */ | ||||
| 	/* mandatory. called in qse_aio_killdev(). also called in qse_aio_makedev() upon | ||||
| 	 * failure after make() success. | ||||
| 	 *  | ||||
| 	 * when 'force' is 0, the return value of -1 causes the device to be a | ||||
| 	 * zombie. the kill method is called periodically on a zombie device | ||||
| 	 * until the method returns 0. | ||||
| 	 * | ||||
| 	 * when 'force' is 1, the called should not return -1. If it does, the | ||||
| 	 * method is called once more only with the 'force' value of 2. | ||||
| 	 *  | ||||
| 	 * when 'force' is 2, the device is destroyed regardless of the return value. | ||||
| 	 */ | ||||
| 	int           (*kill)         (qse_aio_dev_t* dev, int force);  | ||||
|  | ||||
| 	/* ------------------------------------------------------------------ */ | ||||
| 	qse_aio_syshnd_t (*getsyshnd)    (qse_aio_dev_t* dev); /* mandatory. called in qse_aio_makedev() after successful make() */ | ||||
|  | ||||
|  | ||||
| 	/* ------------------------------------------------------------------ */ | ||||
| 	/* return -1 on failure, 0 if no data is availble, 1 otherwise. | ||||
| 	 * when returning 1, *len must be sent to the length of data read. | ||||
| 	 * if *len is set to 0, it's treated as EOF. */ | ||||
| 	int           (*read)         (qse_aio_dev_t* dev, void* data, qse_aio_iolen_t* len, qse_aio_devaddr_t* srcaddr); | ||||
|  | ||||
| 	/* ------------------------------------------------------------------ */ | ||||
| 	int           (*write)        (qse_aio_dev_t* dev, const void* data, qse_aio_iolen_t* len, const qse_aio_devaddr_t* dstaddr); | ||||
|  | ||||
| 	/* ------------------------------------------------------------------ */ | ||||
| 	int           (*ioctl)        (qse_aio_dev_t* dev, int cmd, void* arg); | ||||
|  | ||||
| }; | ||||
|  | ||||
| struct qse_aio_dev_evcb_t | ||||
| { | ||||
| 	/* return -1 on failure. 0 or 1 on success. | ||||
| 	 * when 0 is returned, it doesn't attempt to perform actual I/O. | ||||
| 	 * when 1 is returned, it attempts to perform actual I/O. */ | ||||
| 	int           (*ready)        (qse_aio_dev_t* dev, int events); | ||||
|  | ||||
| 	/* return -1 on failure, 0 or 1 on success. | ||||
| 	 * when 0 is returned, the main loop stops the attempt to read more data. | ||||
| 	 * when 1 is returned, the main loop attempts to read more data without*/ | ||||
| 	int           (*on_read)      (qse_aio_dev_t* dev, const void* data, qse_aio_iolen_t len, const qse_aio_devaddr_t* srcaddr); | ||||
|  | ||||
| 	/* return -1 on failure, 0 on success.  | ||||
| 	 * wrlen is the length of data written. it is the length of the originally | ||||
| 	 * posted writing request for a stream device. For a non stream device, it | ||||
| 	 * may be shorter than the originally posted length. */ | ||||
| 	int           (*on_write)     (qse_aio_dev_t* dev, qse_aio_iolen_t wrlen, void* wrctx, const qse_aio_devaddr_t* dstaddr); | ||||
| }; | ||||
|  | ||||
| struct qse_aio_wq_t | ||||
| { | ||||
| 	qse_aio_wq_t*       next; | ||||
| 	qse_aio_wq_t*       prev; | ||||
|  | ||||
| 	qse_aio_iolen_t     olen; /* original data length */ | ||||
| 	qse_uint8_t*    ptr;  /* pointer to data */ | ||||
| 	qse_aio_iolen_t     len;  /* remaining data length */ | ||||
| 	void*            ctx; | ||||
| 	qse_aio_dev_t*      dev; /* back-pointer to the device */ | ||||
|  | ||||
| 	qse_aio_tmridx_t    tmridx; | ||||
| 	qse_aio_devaddr_t   dstaddr; | ||||
| }; | ||||
|  | ||||
| #define QSE_AIO_WQ_INIT(wq) ((wq)->next = (wq)->prev = (wq)) | ||||
| #define QSE_AIO_WQ_TAIL(wq) ((wq)->prev) | ||||
| #define QSE_AIO_WQ_HEAD(wq) ((wq)->next) | ||||
| #define QSE_AIO_WQ_ISEMPTY(wq) (QSE_AIO_WQ_HEAD(wq) == (wq)) | ||||
| #define QSE_AIO_WQ_ISNODE(wq,x) ((wq) != (x)) | ||||
| #define QSE_AIO_WQ_ISHEAD(wq,x) (QSE_AIO_WQ_HEAD(wq) == (x)) | ||||
| #define QSE_AIO_WQ_ISTAIL(wq,x) (QSE_AIO_WQ_TAIL(wq) == (x)) | ||||
|  | ||||
| #define QSE_AIO_WQ_NEXT(x) ((x)->next) | ||||
| #define QSE_AIO_WQ_PREV(x) ((x)->prev) | ||||
|  | ||||
| #define QSE_AIO_WQ_LINK(p,x,n) do { \ | ||||
| 	qse_aio_wq_t* pp = (p), * nn = (n); \ | ||||
| 	(x)->prev = (p); \ | ||||
| 	(x)->next = (n); \ | ||||
| 	nn->prev = (x); \ | ||||
| 	pp->next = (x); \ | ||||
| } while (0) | ||||
|  | ||||
| #define QSE_AIO_WQ_UNLINK(x) do { \ | ||||
| 	qse_aio_wq_t* pp = (x)->prev, * nn = (x)->next; \ | ||||
| 	nn->prev = pp; pp->next = nn; \ | ||||
| } while (0) | ||||
|  | ||||
| #define QSE_AIO_WQ_REPL(o,n) do { \ | ||||
| 	qse_aio_wq_t* oo = (o), * nn = (n); \ | ||||
| 	nn->next = oo->next; \ | ||||
| 	nn->next->prev = nn; \ | ||||
| 	nn->prev = oo->prev; \ | ||||
| 	nn->prev->next = nn; \ | ||||
| } while (0) | ||||
|  | ||||
| /* insert an item at the back of the queue */ | ||||
| /*#define QSE_AIO_WQ_ENQ(wq,x)  QSE_AIO_WQ_LINK(QSE_AIO_WQ_TAIL(wq), x, QSE_AIO_WQ_TAIL(wq)->next)*/ | ||||
| #define QSE_AIO_WQ_ENQ(wq,x)  QSE_AIO_WQ_LINK(QSE_AIO_WQ_TAIL(wq), x, wq) | ||||
|  | ||||
| /* remove an item in the front from the queue */ | ||||
| #define QSE_AIO_WQ_DEQ(wq) QSE_AIO_WQ_UNLINK(QSE_AIO_WQ_HEAD(wq)) | ||||
|  | ||||
| #define QSE_AIO_DEV_HEADERS \ | ||||
| 	qse_aio_t*          aio; \ | ||||
| 	qse_size_t          dev_size; \ | ||||
| 	int                 dev_capa; \ | ||||
| 	qse_aio_dev_mth_t*  dev_mth; \ | ||||
| 	qse_aio_dev_evcb_t* dev_evcb; \ | ||||
| 	qse_aio_wq_t        wq; \ | ||||
| 	qse_aio_dev_t*      dev_prev; \ | ||||
| 	qse_aio_dev_t*      dev_next  | ||||
|  | ||||
| struct qse_aio_dev_t | ||||
| { | ||||
| 	QSE_AIO_DEV_HEADERS; | ||||
| }; | ||||
|  | ||||
| enum qse_aio_dev_capa_t | ||||
| { | ||||
| 	QSE_AIO_DEV_CAPA_VIRTUAL      = (1 << 0), | ||||
| 	QSE_AIO_DEV_CAPA_IN           = (1 << 1), | ||||
| 	QSE_AIO_DEV_CAPA_OUT          = (1 << 2), | ||||
| 	/* #QSE_AIO_DEV_CAPA_PRI is meaningful only if #QSE_AIO_DEV_CAPA_IN is set */ | ||||
| 	QSE_AIO_DEV_CAPA_PRI          = (1 << 3),  | ||||
| 	QSE_AIO_DEV_CAPA_STREAM       = (1 << 4), | ||||
| 	QSE_AIO_DEV_CAPA_OUT_QUEUED   = (1 << 5), | ||||
|  | ||||
| 	/* internal use only. never set this bit to the dev_capa field */ | ||||
| 	QSE_AIO_DEV_CAPA_IN_DISABLED  = (1 << 9), | ||||
| 	QSE_AIO_DEV_CAPA_IN_CLOSED    = (1 << 10), | ||||
| 	QSE_AIO_DEV_CAPA_OUT_CLOSED   = (1 << 11), | ||||
| 	QSE_AIO_DEV_CAPA_IN_WATCHED   = (1 << 12), | ||||
| 	QSE_AIO_DEV_CAPA_OUT_WATCHED  = (1 << 13), | ||||
| 	QSE_AIO_DEV_CAPA_PRI_WATCHED  = (1 << 14), /**< can be set only if QSE_AIO_DEV_CAPA_IN_WATCHED is set */ | ||||
|  | ||||
| 	QSE_AIO_DEV_CAPA_ACTIVE       = (1 << 15), | ||||
| 	QSE_AIO_DEV_CAPA_HALTED       = (1 << 16), | ||||
| 	QSE_AIO_DEV_CAPA_ZOMBIE       = (1 << 17) | ||||
| }; | ||||
| typedef enum qse_aio_dev_capa_t qse_aio_dev_capa_t; | ||||
|  | ||||
| enum qse_aio_dev_watch_cmd_t | ||||
| { | ||||
| 	QSE_AIO_DEV_WATCH_START, | ||||
| 	QSE_AIO_DEV_WATCH_UPDATE, | ||||
| 	QSE_AIO_DEV_WATCH_RENEW, /* automatic update */ | ||||
| 	QSE_AIO_DEV_WATCH_STOP | ||||
| }; | ||||
| typedef enum qse_aio_dev_watch_cmd_t qse_aio_dev_watch_cmd_t; | ||||
|  | ||||
| enum qse_aio_dev_event_t | ||||
| { | ||||
| 	QSE_AIO_DEV_EVENT_IN  = (1 << 0), | ||||
| 	QSE_AIO_DEV_EVENT_OUT = (1 << 1), | ||||
|  | ||||
| 	QSE_AIO_DEV_EVENT_PRI = (1 << 2), | ||||
| 	QSE_AIO_DEV_EVENT_HUP = (1 << 3), | ||||
| 	QSE_AIO_DEV_EVENT_ERR = (1 << 4) | ||||
| }; | ||||
| typedef enum qse_aio_dev_event_t qse_aio_dev_event_t; | ||||
|  | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| QSE_EXPORT qse_aio_t* qse_aio_open ( | ||||
| 	qse_mmgr_t*       mmgr, | ||||
| 	qse_size_t        xtnsize, | ||||
| 	qse_size_t        tmrcapa,  /**< initial timer capacity */ | ||||
| 	qse_aio_errnum_t* errnum | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT void qse_aio_close ( | ||||
| 	qse_aio_t* aio | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_init ( | ||||
| 	qse_aio_t*  aio, | ||||
| 	qse_mmgr_t* mmgr, | ||||
| 	qse_size_t  tmrcapa | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT void qse_aio_fini ( | ||||
| 	qse_aio_t*      aio | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_exec ( | ||||
| 	qse_aio_t* aio | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_loop ( | ||||
| 	qse_aio_t* aio | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT void qse_aio_stop ( | ||||
| 	qse_aio_t*        aio, | ||||
| 	qse_aio_stopreq_t stopreq | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT qse_aio_dev_t* qse_aio_makedev ( | ||||
| 	qse_aio_t*          aio, | ||||
| 	qse_size_t          dev_size, | ||||
| 	qse_aio_dev_mth_t*  dev_mth, | ||||
| 	qse_aio_dev_evcb_t* dev_evcb, | ||||
| 	void*               make_ctx | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT void qse_aio_killdev ( | ||||
| 	qse_aio_t*     aio, | ||||
| 	qse_aio_dev_t* dev | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_ioctl ( | ||||
| 	qse_aio_dev_t* dev, | ||||
| 	int         cmd, | ||||
| 	void*       arg | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_watch ( | ||||
| 	qse_aio_dev_t*          dev, | ||||
| 	qse_aio_dev_watch_cmd_t cmd, | ||||
| 	/** 0 or bitwise-ORed of #QSE_AIO_DEV_EVENT_IN and #QSE_AIO_DEV_EVENT_OUT */ | ||||
| 	int                     events | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_read ( | ||||
| 	qse_aio_dev_t*         dev, | ||||
| 	int                    enabled | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_aio_dev_write() function posts a writing request.  | ||||
|  * It attempts to write data immediately if there is no pending requests. | ||||
|  * If writing fails, it returns -1. If writing succeeds, it calls the | ||||
|  * on_write callback. If the callback fails, it returns -1. If the callback  | ||||
|  * succeeds, it returns 1. If no immediate writing is possible, the request | ||||
|  * is enqueued to a pending request list. If enqueing gets successful, | ||||
|  * it returns 0. otherwise it returns -1. | ||||
|  */  | ||||
| QSE_EXPORT int qse_aio_dev_write ( | ||||
| 	qse_aio_dev_t*            dev, | ||||
| 	const void*            data, | ||||
| 	qse_aio_iolen_t           len, | ||||
| 	void*                  wrctx, | ||||
| 	const qse_aio_devaddr_t*  dstaddr | ||||
| ); | ||||
|  | ||||
|  | ||||
| QSE_EXPORT int qse_aio_dev_timedwrite ( | ||||
| 	qse_aio_dev_t*           dev, | ||||
| 	const void*              data, | ||||
| 	qse_aio_iolen_t          len, | ||||
| 	const qse_ntime_t*       tmout, | ||||
| 	void*                    wrctx, | ||||
| 	const qse_aio_devaddr_t* dstaddr | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT void qse_aio_dev_halt ( | ||||
| 	qse_aio_dev_t* dev | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_aio_instmrjob() function schedules a new event. | ||||
|  * | ||||
|  * \return #QSE_AIO_TMRIDX_INVALID on failure, valid index on success. | ||||
|  */ | ||||
|  | ||||
| QSE_EXPORT qse_aio_tmridx_t qse_aio_instmrjob ( | ||||
| 	qse_aio_t*              aio, | ||||
| 	const qse_aio_tmrjob_t* job | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT qse_aio_tmridx_t qse_aio_updtmrjob ( | ||||
| 	qse_aio_t*              aio, | ||||
| 	qse_aio_tmridx_t        index, | ||||
| 	const qse_aio_tmrjob_t* job | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT void qse_aio_deltmrjob ( | ||||
| 	qse_aio_t*          aio, | ||||
| 	qse_aio_tmridx_t    index | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_aio_gettmrjob() function returns the | ||||
|  * pointer to the registered event at the given index. | ||||
|  */ | ||||
| QSE_EXPORT qse_aio_tmrjob_t* qse_aio_gettmrjob ( | ||||
| 	qse_aio_t*            aio, | ||||
| 	qse_aio_tmridx_t      index | ||||
| ); | ||||
|  | ||||
| QSE_EXPORT int qse_aio_gettmrjobdeadline ( | ||||
| 	qse_aio_t*            aio, | ||||
| 	qse_aio_tmridx_t      index, | ||||
| 	qse_ntime_t*          deadline | ||||
| ); | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #endif | ||||
| @ -5,16 +5,11 @@ AM_CPPFLAGS = \ | ||||
| 	-I$(top_srcdir)/include | ||||
|  | ||||
| noinst_HEADERS = \ | ||||
| 	aio-prv.h \ | ||||
| 	fs-prv.h \ | ||||
| 	glob-imp.h | ||||
|  | ||||
| lib_LTLIBRARIES = libqsesi.la | ||||
| libqsesi_la_SOURCES =  \ | ||||
| 	aio.c \ | ||||
| 	aio-pro.c  \ | ||||
| 	aio-sck.c  \ | ||||
| 	aio-tmr.c  \ | ||||
| 	cnd.c \ | ||||
| 	dir.c \ | ||||
| 	fio.c  \ | ||||
|  | ||||
| @ -138,10 +138,8 @@ am__installdirs = "$(DESTDIR)$(libdir)" | ||||
| LTLIBRARIES = $(lib_LTLIBRARIES) | ||||
| am__DEPENDENCIES_1 = | ||||
| libqsesi_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) | ||||
| am_libqsesi_la_OBJECTS = libqsesi_la-aio.lo libqsesi_la-aio-pro.lo \ | ||||
| 	libqsesi_la-aio-sck.lo libqsesi_la-aio-tmr.lo \ | ||||
| 	libqsesi_la-cnd.lo libqsesi_la-dir.lo libqsesi_la-fio.lo \ | ||||
| 	libqsesi_la-fs.lo libqsesi_la-fs-attr.lo \ | ||||
| am_libqsesi_la_OBJECTS = libqsesi_la-cnd.lo libqsesi_la-dir.lo \ | ||||
| 	libqsesi_la-fio.lo libqsesi_la-fs.lo libqsesi_la-fs-attr.lo \ | ||||
| 	libqsesi_la-fs-copy.lo libqsesi_la-fs-delete.lo \ | ||||
| 	libqsesi_la-fs-err.lo libqsesi_la-fs-make.lo \ | ||||
| 	libqsesi_la-fs-move.lo libqsesi_la-glob.lo libqsesi_la-intr.lo \ | ||||
| @ -424,16 +422,11 @@ AM_CPPFLAGS = \ | ||||
| 	-I$(top_srcdir)/include | ||||
|  | ||||
| noinst_HEADERS = \ | ||||
| 	aio-prv.h \ | ||||
| 	fs-prv.h \ | ||||
| 	glob-imp.h | ||||
|  | ||||
| lib_LTLIBRARIES = libqsesi.la $(am__append_1) | ||||
| libqsesi_la_SOURCES = \ | ||||
| 	aio.c \ | ||||
| 	aio-pro.c  \ | ||||
| 	aio-sck.c  \ | ||||
| 	aio-tmr.c  \ | ||||
| 	cnd.c \ | ||||
| 	dir.c \ | ||||
| 	fio.c  \ | ||||
| @ -564,10 +557,6 @@ distclean-compile: | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketAddress.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TcpServer.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Thread.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-pro.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-sck.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-tmr.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-cnd.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-dir.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-fio.Plo@am__quote@ | ||||
| @ -620,34 +609,6 @@ distclean-compile: | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||||
| @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< | ||||
|  | ||||
| libqsesi_la-aio.lo: aio.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-aio.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-aio.Tpo -c -o libqsesi_la-aio.lo `test -f 'aio.c' || echo '$(srcdir)/'`aio.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-aio.Tpo $(DEPDIR)/libqsesi_la-aio.Plo | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='aio.c' object='libqsesi_la-aio.lo' libtool=yes @AMDEPBACKSLASH@ | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||||
| @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-aio.lo `test -f 'aio.c' || echo '$(srcdir)/'`aio.c | ||||
|  | ||||
| libqsesi_la-aio-pro.lo: aio-pro.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-aio-pro.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-aio-pro.Tpo -c -o libqsesi_la-aio-pro.lo `test -f 'aio-pro.c' || echo '$(srcdir)/'`aio-pro.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-aio-pro.Tpo $(DEPDIR)/libqsesi_la-aio-pro.Plo | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='aio-pro.c' object='libqsesi_la-aio-pro.lo' libtool=yes @AMDEPBACKSLASH@ | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||||
| @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-aio-pro.lo `test -f 'aio-pro.c' || echo '$(srcdir)/'`aio-pro.c | ||||
|  | ||||
| libqsesi_la-aio-sck.lo: aio-sck.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-aio-sck.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-aio-sck.Tpo -c -o libqsesi_la-aio-sck.lo `test -f 'aio-sck.c' || echo '$(srcdir)/'`aio-sck.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-aio-sck.Tpo $(DEPDIR)/libqsesi_la-aio-sck.Plo | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='aio-sck.c' object='libqsesi_la-aio-sck.lo' libtool=yes @AMDEPBACKSLASH@ | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||||
| @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-aio-sck.lo `test -f 'aio-sck.c' || echo '$(srcdir)/'`aio-sck.c | ||||
|  | ||||
| libqsesi_la-aio-tmr.lo: aio-tmr.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-aio-tmr.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-aio-tmr.Tpo -c -o libqsesi_la-aio-tmr.lo `test -f 'aio-tmr.c' || echo '$(srcdir)/'`aio-tmr.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-aio-tmr.Tpo $(DEPDIR)/libqsesi_la-aio-tmr.Plo | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='aio-tmr.c' object='libqsesi_la-aio-tmr.lo' libtool=yes @AMDEPBACKSLASH@ | ||||
| @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||||
| @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-aio-tmr.lo `test -f 'aio-tmr.c' || echo '$(srcdir)/'`aio-tmr.c | ||||
|  | ||||
| libqsesi_la-cnd.lo: cnd.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-cnd.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-cnd.Tpo -c -o libqsesi_la-cnd.lo `test -f 'cnd.c' || echo '$(srcdir)/'`cnd.c | ||||
| @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-cnd.Tpo $(DEPDIR)/libqsesi_la-cnd.Plo | ||||
|  | ||||
| @ -1,853 +0,0 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright (c) 2006-2016 Chung, Hyung-Hwan. All rights reserved. | ||||
|  | ||||
|     Redistribution and use in source and binary forms, with or without | ||||
|     modification, are permitted provided that the following conditions | ||||
|     are met: | ||||
|     1. Redistributions of source code must retain the above copyright | ||||
|        notice, this list of conditions and the following disclaimer. | ||||
|     2. Redistributions in binary form must reproduce the above copyright | ||||
|        notice, this list of conditions and the following disclaimer in the | ||||
|        documentation and/or other materials provided with the distribution. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES | ||||
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
| #include <qse/si/aio-pro.h> | ||||
| #include "aio-prv.h" | ||||
|  | ||||
| #include <qse/cmn/str.h> | ||||
|  | ||||
| #include <unistd.h> | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <sys/wait.h> | ||||
| #include <signal.h> | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| struct slave_info_t | ||||
| { | ||||
| 	qse_aio_dev_pro_make_t* mi; | ||||
| 	qse_aio_syshnd_t pfd; | ||||
| 	int dev_capa; | ||||
| 	qse_aio_dev_pro_sid_t id; | ||||
| }; | ||||
|  | ||||
| typedef struct slave_info_t slave_info_t; | ||||
|  | ||||
| static qse_aio_dev_pro_slave_t* make_slave (qse_aio_t* aio, slave_info_t* si); | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| struct param_t | ||||
| { | ||||
| 	qse_mchar_t* mcmd; | ||||
| 	qse_mchar_t* fixed_argv[4]; | ||||
| 	qse_mchar_t** argv; | ||||
| }; | ||||
| typedef struct param_t param_t; | ||||
|  | ||||
| static void free_param (qse_aio_t* aio, param_t* param) | ||||
| { | ||||
| 	if (param->argv && param->argv != param->fixed_argv)  | ||||
| 		QSE_MMGR_FREE (aio->mmgr, param->argv); | ||||
| 	if (param->mcmd) QSE_MMGR_FREE (aio->mmgr, param->mcmd); | ||||
| 	QSE_MEMSET (param, 0, QSE_SIZEOF(*param)); | ||||
| } | ||||
|  | ||||
| static int make_param (qse_aio_t* aio, const qse_mchar_t* cmd, int flags, param_t* param) | ||||
| { | ||||
| 	int fcnt = 0; | ||||
| 	qse_mchar_t* mcmd = QSE_NULL; | ||||
|  | ||||
| 	QSE_MEMSET (param, 0, QSE_SIZEOF(*param)); | ||||
|  | ||||
| 	if (flags & QSE_AIO_DEV_PRO_SHELL) | ||||
| 	{ | ||||
| 		mcmd = (qse_mchar_t*)cmd; | ||||
|  | ||||
| 		param->argv = param->fixed_argv; | ||||
| 		param->argv[0] = QSE_MT("/bin/sh"); | ||||
| 		param->argv[1] = QSE_MT("-c"); | ||||
| 		param->argv[2] = mcmd; | ||||
| 		param->argv[3] = QSE_NULL; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		int i; | ||||
| 		qse_mchar_t** argv; | ||||
| 		qse_mchar_t* mcmdptr; | ||||
|  | ||||
| 		mcmd = qse_mbsdup (cmd, aio->mmgr); | ||||
| 		if (!mcmd)  | ||||
| 		{ | ||||
| 			aio->errnum = QSE_AIO_ENOMEM; | ||||
| 			goto oops; | ||||
| 		} | ||||
|  | ||||
| 		fcnt = qse_mbsspl (mcmd, QSE_MT(""), QSE_MT('\"'), QSE_MT('\"'), QSE_MT('\\'));  | ||||
| 		if (fcnt <= 0)  | ||||
| 		{ | ||||
| 			/* no field or an error */ | ||||
| 			aio->errnum = QSE_AIO_EINVAL; | ||||
| 			goto oops; | ||||
| 		} | ||||
|  | ||||
| 		if (fcnt < QSE_COUNTOF(param->fixed_argv)) | ||||
| 		{ | ||||
| 			param->argv = param->fixed_argv; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			param->argv = QSE_MMGR_ALLOC (aio->mmgr, (fcnt + 1) * QSE_SIZEOF(argv[0])); | ||||
| 			if (param->argv == QSE_NULL)  | ||||
| 			{ | ||||
| 				aio->errnum = QSE_AIO_ENOMEM; | ||||
| 				goto oops; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		mcmdptr = mcmd; | ||||
| 		for (i = 0; i < fcnt; i++) | ||||
| 		{ | ||||
| 			param->argv[i] = mcmdptr; | ||||
| 			while (*mcmdptr != QSE_MT('\0')) mcmdptr++; | ||||
| 			mcmdptr++; | ||||
| 		} | ||||
| 		param->argv[i] = QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (mcmd && mcmd != (qse_mchar_t*)cmd) param->mcmd = mcmd; | ||||
| 	return 0; | ||||
|  | ||||
| oops: | ||||
| 	if (mcmd && mcmd != cmd) QSE_MMGR_FREE (aio->mmgr, mcmd); | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static pid_t standard_fork_and_exec (qse_aio_t* aio, int pfds[], int flags, param_t* param) | ||||
| { | ||||
| 	pid_t pid; | ||||
|  | ||||
| 	pid = fork (); | ||||
| 	if (pid == -1)  | ||||
| 	{ | ||||
| 		aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (pid == 0) | ||||
| 	{ | ||||
| 		/* slave process */ | ||||
|  | ||||
| 		qse_aio_syshnd_t devnull = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| /* TODO: close all uneeded fds */ | ||||
|  | ||||
| 		if (flags & QSE_AIO_DEV_PRO_WRITEIN) | ||||
| 		{ | ||||
| 			/* slave should read */ | ||||
| 			close (pfds[1]); | ||||
| 			pfds[1] = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| 			/* let the pipe be standard input */ | ||||
| 			if (dup2 (pfds[0], 0) <= -1) goto slave_oops; | ||||
|  | ||||
| 			close (pfds[0]); | ||||
| 			pfds[0] = QSE_AIO_SYSHND_INVALID; | ||||
| 		} | ||||
|  | ||||
| 		if (flags & QSE_AIO_DEV_PRO_READOUT) | ||||
| 		{ | ||||
| 			/* slave should write */ | ||||
| 			close (pfds[2]); | ||||
| 			pfds[2] = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| 			if (dup2(pfds[3], 1) == -1) goto slave_oops; | ||||
|  | ||||
| 			if (flags & QSE_AIO_DEV_PRO_ERRTOOUT) | ||||
| 			{ | ||||
| 				if (dup2(pfds[3], 2) == -1) goto slave_oops; | ||||
| 			} | ||||
|  | ||||
| 			close (pfds[3]); | ||||
| 			pfds[3] = QSE_AIO_SYSHND_INVALID; | ||||
| 		} | ||||
|  | ||||
| 		if (flags & QSE_AIO_DEV_PRO_READERR) | ||||
| 		{ | ||||
| 			close (pfds[4]); | ||||
| 			pfds[4] = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| 			if (dup2(pfds[5], 2) == -1) goto slave_oops; | ||||
|  | ||||
| 			if (flags & QSE_AIO_DEV_PRO_OUTTOERR) | ||||
| 			{ | ||||
| 				if (dup2(pfds[5], 1) == -1) goto slave_oops; | ||||
| 			} | ||||
|  | ||||
| 			close (pfds[5]); | ||||
| 			pfds[5] = QSE_AIO_SYSHND_INVALID; | ||||
| 		} | ||||
|  | ||||
| 		if ((flags & QSE_AIO_DEV_PRO_INTONUL) || | ||||
| 		    (flags & QSE_AIO_DEV_PRO_OUTTONUL) || | ||||
| 		    (flags & QSE_AIO_DEV_PRO_ERRTONUL)) | ||||
| 		{ | ||||
| 		#if defined(O_LARGEFILE) | ||||
| 			devnull = open (QSE_MT("/dev/null"), O_RDWR | O_LARGEFILE, 0); | ||||
| 		#else | ||||
| 			devnull = open (QSE_MT("/dev/null"), O_RDWR, 0); | ||||
| 		#endif | ||||
| 			if (devnull == QSE_AIO_SYSHND_INVALID) goto slave_oops; | ||||
| 		} | ||||
|  | ||||
| 		execv (param->argv[0], param->argv); | ||||
|  | ||||
| 		/* if exec fails, free 'param' parameter which is an inherited pointer */ | ||||
| 		free_param (aio, param);  | ||||
|  | ||||
| 	slave_oops: | ||||
| 		if (devnull != QSE_AIO_SYSHND_INVALID) close(devnull); | ||||
| 		_exit (128); | ||||
| 	} | ||||
|  | ||||
| 	/* parent process */ | ||||
| 	return pid; | ||||
| } | ||||
|  | ||||
| static int dev_pro_make_master (qse_aio_dev_t* dev, void* ctx) | ||||
| { | ||||
| 	qse_aio_dev_pro_t* rdev = (qse_aio_dev_pro_t*)dev; | ||||
| 	qse_aio_dev_pro_make_t* info = (qse_aio_dev_pro_make_t*)ctx; | ||||
| 	qse_aio_syshnd_t pfds[6]; | ||||
| 	int i, minidx = -1, maxidx = -1; | ||||
| 	param_t param; | ||||
| 	pid_t pid; | ||||
|  | ||||
| 	if (info->flags & QSE_AIO_DEV_PRO_WRITEIN) | ||||
| 	{ | ||||
| 		if (pipe(&pfds[0]) == -1) | ||||
| 		{ | ||||
| 			dev->aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 			goto oops; | ||||
| 		} | ||||
| 		minidx = 0; maxidx = 1; | ||||
| 	} | ||||
|  | ||||
| 	if (info->flags & QSE_AIO_DEV_PRO_READOUT) | ||||
| 	{ | ||||
| 		if (pipe(&pfds[2]) == -1) | ||||
| 		{ | ||||
| 			dev->aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 			goto oops; | ||||
| 		} | ||||
| 		if (minidx == -1) minidx = 2; | ||||
| 		maxidx = 3; | ||||
| 	} | ||||
|  | ||||
| 	if (info->flags & QSE_AIO_DEV_PRO_READERR) | ||||
| 	{ | ||||
| 		if (pipe(&pfds[4]) == -1) | ||||
| 		{ | ||||
| 			dev->aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 			goto oops; | ||||
| 		} | ||||
| 		if (minidx == -1) minidx = 4; | ||||
| 		maxidx = 5; | ||||
| 	} | ||||
|  | ||||
| 	if (maxidx == -1) | ||||
| 	{ | ||||
| 		dev->aio->errnum = QSE_AIO_EINVAL; | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	if (make_param (rdev->aio, info->cmd, info->flags, ¶m) <= -1) goto oops; | ||||
|  | ||||
| /* TODO: more advanced fork and exec .. */ | ||||
| 	pid = standard_fork_and_exec (rdev->aio, pfds, info->flags, ¶m); | ||||
| 	if (pid <= -1)  | ||||
| 	{ | ||||
| 		free_param (rdev->aio, ¶m); | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	free_param (rdev->aio, ¶m); | ||||
| 	rdev->child_pid = pid; | ||||
|  | ||||
| 	/* this is the parent process */ | ||||
| 	if (info->flags & QSE_AIO_DEV_PRO_WRITEIN) | ||||
| 	{ | ||||
| 		/* | ||||
| 		 * 012345 | ||||
| 		 * rw---- | ||||
| 		 * X | ||||
| 		 * WRITE => 1 | ||||
| 		 */ | ||||
| 		close (pfds[0]); | ||||
| 		pfds[0] = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| 		if (qse_aio_makesyshndasync (dev->aio, pfds[1]) <= -1) goto oops; | ||||
| 	} | ||||
|  | ||||
| 	if (info->flags & QSE_AIO_DEV_PRO_READOUT) | ||||
| 	{ | ||||
| 		/* | ||||
| 		 * 012345 | ||||
| 		 * --rw-- | ||||
| 		 *    X | ||||
| 		 * READ => 2 | ||||
| 		 */ | ||||
| 		close (pfds[3]); | ||||
| 		pfds[3] = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| 		if (qse_aio_makesyshndasync (dev->aio, pfds[2]) <= -1) goto oops; | ||||
| 	} | ||||
|  | ||||
| 	if (info->flags & QSE_AIO_DEV_PRO_READERR) | ||||
| 	{ | ||||
| 		/* | ||||
| 		 * 012345 | ||||
| 		 * ----rw | ||||
| 		 *      X | ||||
| 		 * READ => 4 | ||||
| 		 */ | ||||
| 		close (pfds[5]); | ||||
| 		pfds[5] = QSE_AIO_SYSHND_INVALID; | ||||
|  | ||||
| 		if (qse_aio_makesyshndasync (dev->aio, pfds[4]) <= -1) goto oops; | ||||
| 	} | ||||
|  | ||||
| 	if (pfds[1] != QSE_AIO_SYSHND_INVALID) | ||||
| 	{ | ||||
| 		/* hand over pfds[2] to the first slave device */ | ||||
| 		slave_info_t si; | ||||
|  | ||||
| 		si.mi = info; | ||||
| 		si.pfd = pfds[1]; | ||||
| 		si.dev_capa = QSE_AIO_DEV_CAPA_OUT | QSE_AIO_DEV_CAPA_OUT_QUEUED | QSE_AIO_DEV_CAPA_STREAM; | ||||
| 		si.id = QSE_AIO_DEV_PRO_IN; | ||||
|  | ||||
| 		rdev->slave[QSE_AIO_DEV_PRO_IN] = make_slave (dev->aio, &si); | ||||
| 		if (!rdev->slave[QSE_AIO_DEV_PRO_IN]) goto oops; | ||||
|  | ||||
| 		pfds[1] = QSE_AIO_SYSHND_INVALID; | ||||
| 		rdev->slave_count++; | ||||
| 	} | ||||
|  | ||||
| 	if (pfds[2] != QSE_AIO_SYSHND_INVALID) | ||||
| 	{ | ||||
| 		/* hand over pfds[2] to the first slave device */ | ||||
| 		slave_info_t si; | ||||
|  | ||||
| 		si.mi = info; | ||||
| 		si.pfd = pfds[2]; | ||||
| 		si.dev_capa = QSE_AIO_DEV_CAPA_IN | QSE_AIO_DEV_CAPA_STREAM; | ||||
| 		si.id = QSE_AIO_DEV_PRO_OUT; | ||||
|  | ||||
| 		rdev->slave[QSE_AIO_DEV_PRO_OUT] = make_slave (dev->aio, &si); | ||||
| 		if (!rdev->slave[QSE_AIO_DEV_PRO_OUT]) goto oops; | ||||
|  | ||||
| 		pfds[2] = QSE_AIO_SYSHND_INVALID; | ||||
| 		rdev->slave_count++; | ||||
| 	} | ||||
|  | ||||
| 	if (pfds[4] != QSE_AIO_SYSHND_INVALID) | ||||
| 	{ | ||||
| 		/* hand over pfds[4] to the second slave device */ | ||||
| 		slave_info_t si; | ||||
|  | ||||
| 		si.mi = info; | ||||
| 		si.pfd = pfds[4]; | ||||
| 		si.dev_capa = QSE_AIO_DEV_CAPA_IN | QSE_AIO_DEV_CAPA_STREAM; | ||||
| 		si.id = QSE_AIO_DEV_PRO_ERR; | ||||
|  | ||||
| 		rdev->slave[QSE_AIO_DEV_PRO_ERR] = make_slave (dev->aio, &si); | ||||
| 		if (!rdev->slave[QSE_AIO_DEV_PRO_ERR]) goto oops; | ||||
|  | ||||
| 		pfds[4] = QSE_AIO_SYSHND_INVALID; | ||||
| 		rdev->slave_count++; | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; i < QSE_COUNTOF(rdev->slave); i++)  | ||||
| 	{ | ||||
| 		if (rdev->slave[i]) rdev->slave[i]->master = rdev; | ||||
| 	} | ||||
|  | ||||
| 	rdev->dev_capa = QSE_AIO_DEV_CAPA_VIRTUAL; /* the master device doesn't perform I/O */ | ||||
| 	rdev->flags = info->flags; | ||||
| 	rdev->on_read = info->on_read; | ||||
| 	rdev->on_write = info->on_write; | ||||
| 	rdev->on_close = info->on_close; | ||||
| 	return 0; | ||||
|  | ||||
| oops: | ||||
| 	for (i = minidx; i < maxidx; i++) | ||||
| 	{ | ||||
| 		if (pfds[i] != QSE_AIO_SYSHND_INVALID) close (pfds[i]); | ||||
| 	} | ||||
|  | ||||
| 	if (rdev->mcmd)  | ||||
| 	{ | ||||
| 		QSE_MMGR_FREE (rdev->aio->mmgr, rdev->mcmd); | ||||
| 		free_param (rdev->aio, ¶m); | ||||
| 	} | ||||
|  | ||||
| 	for (i = QSE_COUNTOF(rdev->slave); i > 0; ) | ||||
| 	{ | ||||
| 		i--; | ||||
| 		if (rdev->slave[i]) | ||||
| 		{ | ||||
| 			qse_aio_killdev (rdev->aio, (qse_aio_dev_t*)rdev->slave[i]); | ||||
| 			rdev->slave[i] = QSE_NULL; | ||||
| 		} | ||||
| 	} | ||||
| 	rdev->slave_count = 0; | ||||
|  | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static int dev_pro_make_slave (qse_aio_dev_t* dev, void* ctx) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* rdev = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	slave_info_t* si = (slave_info_t*)ctx; | ||||
|  | ||||
| 	rdev->dev_capa = si->dev_capa; | ||||
| 	rdev->id = si->id; | ||||
| 	rdev->pfd = si->pfd; | ||||
| 	/* keep rdev->master to QSE_NULL. it's set to the right master | ||||
| 	 * device in dev_pro_make() */ | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int dev_pro_kill_master (qse_aio_dev_t* dev, int force) | ||||
| { | ||||
| 	qse_aio_dev_pro_t* rdev = (qse_aio_dev_pro_t*)dev; | ||||
| 	int i, status; | ||||
| 	pid_t wpid; | ||||
|  | ||||
| 	if (rdev->slave_count > 0) | ||||
| 	{ | ||||
| 		for (i = 0; i < QSE_COUNTOF(rdev->slave); i++) | ||||
| 		{ | ||||
| 			if (rdev->slave[i]) | ||||
| 			{ | ||||
| 				qse_aio_dev_pro_slave_t* sdev = rdev->slave[i]; | ||||
|  | ||||
| 				/* nullify the pointer to the slave device | ||||
| 				 * before calling qse_aio_killdev() on the slave device. | ||||
| 				 * the slave device can check this pointer to tell from | ||||
| 				 * self-initiated termination or master-driven termination */ | ||||
| 				rdev->slave[i] = QSE_NULL; | ||||
|  | ||||
| 				qse_aio_killdev (rdev->aio, (qse_aio_dev_t*)sdev); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (rdev->child_pid >= 0) | ||||
| 	{ | ||||
| 		if (!(rdev->flags & QSE_AIO_DEV_PRO_FORGET_CHILD)) | ||||
| 		{ | ||||
| 			int killed = 0; | ||||
|  | ||||
| 		await_child: | ||||
| 			wpid = waitpid (rdev->child_pid, &status, WNOHANG); | ||||
| 			if (wpid == 0) | ||||
| 			{ | ||||
| 				if (force && !killed) | ||||
| 				{ | ||||
| 					if (!(rdev->flags & QSE_AIO_DEV_PRO_FORGET_DIEHARD_CHILD)) | ||||
| 					{ | ||||
| 						kill (rdev->child_pid, SIGKILL); | ||||
| 						killed = 1; | ||||
| 						goto await_child; | ||||
| 					} | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					/* child process is still alive */ | ||||
| 					rdev->aio->errnum = QSE_AIO_EAGAIN; | ||||
| 					return -1;  /* call me again */ | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			/* wpid == rdev->child_pid => full success | ||||
| 			 * wpid == -1 && errno == ECHILD => no such process. it's waitpid()'ed by some other part of the program? | ||||
| 			 * other cases ==> can't really handle properly. forget it by returning success | ||||
| 			 * no need not worry about EINTR because errno can't have the value when WNOHANG is set. | ||||
| 			 */ | ||||
| 		} | ||||
|  | ||||
| printf (">>>>>>>>>>>>>>>>>>> REAPED CHILD %d\n", (int)rdev->child_pid); | ||||
| 		rdev->child_pid = -1; | ||||
| 	} | ||||
|  | ||||
| 	if (rdev->on_close) rdev->on_close (rdev, QSE_AIO_DEV_PRO_MASTER); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int dev_pro_kill_slave (qse_aio_dev_t* dev, int force) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* rdev = (qse_aio_dev_pro_slave_t*)dev; | ||||
|  | ||||
| 	if (rdev->master) | ||||
| 	{ | ||||
| 		qse_aio_dev_pro_t* master; | ||||
|  | ||||
| 		master = rdev->master; | ||||
| 		rdev->master = QSE_NULL; | ||||
|  | ||||
| 		/* indicate EOF */ | ||||
| 		if (master->on_close) master->on_close (master, rdev->id); | ||||
|  | ||||
| 		QSE_ASSERT (master->slave_count > 0); | ||||
| 		master->slave_count--; | ||||
|  | ||||
| 		if (master->slave[rdev->id]) | ||||
| 		{ | ||||
| 			/* this call is started by the slave device itself. | ||||
| 			 * if this is the last slave, kill the master also */ | ||||
| 			if (master->slave_count <= 0)  | ||||
| 			{ | ||||
| 				qse_aio_killdev (rdev->aio, (qse_aio_dev_t*)master); | ||||
| 				/* the master pointer is not valid from this point onwards | ||||
| 				 * as the actual master device object is freed in qse_aio_killdev() */ | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* this call is initiated by this slave device itself. | ||||
| 			 * if it were by the master device, it would be QSE_NULL as | ||||
| 			 * nullified by the dev_pro_kill() */ | ||||
| 			master->slave[rdev->id] = QSE_NULL; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (rdev->pfd != QSE_AIO_SYSHND_INVALID) | ||||
| 	{ | ||||
| 		close (rdev->pfd); | ||||
| 		rdev->pfd = QSE_AIO_SYSHND_INVALID; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int dev_pro_read_slave (qse_aio_dev_t* dev, void* buf, qse_aio_iolen_t* len, qse_aio_devaddr_t* srcaddr) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* pro = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	ssize_t x; | ||||
|  | ||||
| 	x = read (pro->pfd, buf, *len); | ||||
| 	if (x <= -1) | ||||
| 	{ | ||||
| 		if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0;  /* no data available */ | ||||
| 		if (errno == EINTR) return 0; | ||||
| 		pro->aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	*len = x; | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static int dev_pro_write_slave (qse_aio_dev_t* dev, const void* data, qse_aio_iolen_t* len, const qse_aio_devaddr_t* dstaddr) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* pro = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	ssize_t x; | ||||
|  | ||||
| 	x = write (pro->pfd, data, *len); | ||||
| 	if (x <= -1) | ||||
| 	{ | ||||
| 		if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0;  /* no data can be written */ | ||||
| 		if (errno == EINTR) return 0; | ||||
| 		pro->aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	*len = x; | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| static qse_aio_syshnd_t dev_pro_getsyshnd (qse_aio_dev_t* dev) | ||||
| { | ||||
| 	return QSE_AIO_SYSHND_INVALID; | ||||
| } | ||||
|  | ||||
| static qse_aio_syshnd_t dev_pro_getsyshnd_slave (qse_aio_dev_t* dev) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* pro = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	return (qse_aio_syshnd_t)pro->pfd; | ||||
| } | ||||
|  | ||||
| static int dev_pro_ioctl (qse_aio_dev_t* dev, int cmd, void* arg) | ||||
| { | ||||
| 	qse_aio_dev_pro_t* rdev = (qse_aio_dev_pro_t*)dev; | ||||
|  | ||||
| 	switch (cmd) | ||||
| 	{ | ||||
| 		case QSE_AIO_DEV_PRO_CLOSE: | ||||
| 		{ | ||||
| 			qse_aio_dev_pro_sid_t sid = *(qse_aio_dev_pro_sid_t*)arg; | ||||
|  | ||||
| 			if (sid < QSE_AIO_DEV_PRO_IN || sid > QSE_AIO_DEV_PRO_ERR) | ||||
| 			{ | ||||
| 				rdev->aio->errnum = QSE_AIO_EINVAL; | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			if (rdev->slave[sid]) | ||||
| 			{ | ||||
| 				/* unlike dev_pro_kill_master(), i don't nullify rdev->slave[sid]. | ||||
| 				 * so i treat the closing ioctl as if it's a kill request  | ||||
| 				 * initiated by the slave device itself. */ | ||||
| 				qse_aio_killdev (rdev->aio, (qse_aio_dev_t*)rdev->slave[sid]); | ||||
| 			} | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		case QSE_AIO_DEV_PRO_KILL_CHILD: | ||||
| 			if (rdev->child_pid >= 0) | ||||
| 			{ | ||||
| 				if (kill (rdev->child_pid, SIGKILL) == -1) | ||||
| 				{ | ||||
| 					rdev->aio->errnum = qse_aio_syserrtoerrnum(errno); | ||||
| 					return -1; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			return 0; | ||||
|  | ||||
| 		default: | ||||
| 			dev->aio->errnum = QSE_AIO_EINVAL; | ||||
| 			return -1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static qse_aio_dev_mth_t dev_pro_methods =  | ||||
| { | ||||
| 	dev_pro_make_master, | ||||
| 	dev_pro_kill_master, | ||||
| 	dev_pro_getsyshnd, | ||||
|  | ||||
| 	QSE_NULL, | ||||
| 	QSE_NULL, | ||||
| 	dev_pro_ioctl | ||||
| }; | ||||
|  | ||||
| static qse_aio_dev_mth_t dev_pro_methods_slave = | ||||
| { | ||||
| 	dev_pro_make_slave, | ||||
| 	dev_pro_kill_slave, | ||||
| 	dev_pro_getsyshnd_slave, | ||||
|  | ||||
| 	dev_pro_read_slave, | ||||
| 	dev_pro_write_slave, | ||||
| 	dev_pro_ioctl | ||||
| }; | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| static int pro_ready (qse_aio_dev_t* dev, int events) | ||||
| { | ||||
| 	/* virtual device. no I/O */ | ||||
| 	dev->aio->errnum = QSE_AIO_EINTERN; | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static int pro_on_read (qse_aio_dev_t* dev, const void* data, qse_aio_iolen_t len, const qse_aio_devaddr_t* srcaddr) | ||||
| { | ||||
| 	/* virtual device. no I/O */ | ||||
| 	dev->aio->errnum = QSE_AIO_EINTERN; | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static int pro_on_write (qse_aio_dev_t* dev, qse_aio_iolen_t wrlen, void* wrctx, const qse_aio_devaddr_t* dstaddr) | ||||
| { | ||||
| 	/* virtual device. no I/O */ | ||||
| 	dev->aio->errnum = QSE_AIO_EINTERN; | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static qse_aio_dev_evcb_t dev_pro_event_callbacks = | ||||
| { | ||||
| 	pro_ready, | ||||
| 	pro_on_read, | ||||
| 	pro_on_write | ||||
| }; | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| static int pro_ready_slave (qse_aio_dev_t* dev, int events) | ||||
| { | ||||
| 	qse_aio_dev_pro_t* pro = (qse_aio_dev_pro_t*)dev; | ||||
|  | ||||
| 	if (events & QSE_AIO_DEV_EVENT_ERR) | ||||
| 	{ | ||||
| 		pro->aio->errnum = QSE_AIO_EDEVERR; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (events & QSE_AIO_DEV_EVENT_HUP) | ||||
| 	{ | ||||
| 		if (events & (QSE_AIO_DEV_EVENT_PRI | QSE_AIO_DEV_EVENT_IN | QSE_AIO_DEV_EVENT_OUT))  | ||||
| 		{ | ||||
| 			/* probably half-open? */ | ||||
| 			return 1; | ||||
| 		} | ||||
|  | ||||
| 		pro->aio->errnum = QSE_AIO_EDEVHUP; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	return 1; /* the device is ok. carry on reading or writing */ | ||||
| } | ||||
|  | ||||
|  | ||||
| static int pro_on_read_slave_out (qse_aio_dev_t* dev, const void* data, qse_aio_iolen_t len, const qse_aio_devaddr_t* srcaddr) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* pro = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	return pro->master->on_read (pro->master, data, len, QSE_AIO_DEV_PRO_OUT); | ||||
| } | ||||
|  | ||||
| static int pro_on_read_slave_err (qse_aio_dev_t* dev, const void* data, qse_aio_iolen_t len, const qse_aio_devaddr_t* srcaddr) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* pro = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	return pro->master->on_read (pro->master, data, len, QSE_AIO_DEV_PRO_ERR); | ||||
| } | ||||
|  | ||||
| static int pro_on_write_slave (qse_aio_dev_t* dev, qse_aio_iolen_t wrlen, void* wrctx, const qse_aio_devaddr_t* dstaddr) | ||||
| { | ||||
| 	qse_aio_dev_pro_slave_t* pro = (qse_aio_dev_pro_slave_t*)dev; | ||||
| 	return pro->master->on_write (pro->master, wrlen, wrctx); | ||||
| } | ||||
|  | ||||
| static qse_aio_dev_evcb_t dev_pro_event_callbacks_slave_in = | ||||
| { | ||||
| 	pro_ready_slave, | ||||
| 	QSE_NULL, | ||||
| 	pro_on_write_slave | ||||
| }; | ||||
|  | ||||
| static qse_aio_dev_evcb_t dev_pro_event_callbacks_slave_out = | ||||
| { | ||||
| 	pro_ready_slave, | ||||
| 	pro_on_read_slave_out, | ||||
| 	QSE_NULL | ||||
| }; | ||||
|  | ||||
| static qse_aio_dev_evcb_t dev_pro_event_callbacks_slave_err = | ||||
| { | ||||
| 	pro_ready_slave, | ||||
| 	pro_on_read_slave_err, | ||||
| 	QSE_NULL | ||||
| }; | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| static qse_aio_dev_pro_slave_t* make_slave (qse_aio_t* aio, slave_info_t* si) | ||||
| { | ||||
| 	switch (si->id) | ||||
| 	{ | ||||
| 		case QSE_AIO_DEV_PRO_IN: | ||||
| 			return (qse_aio_dev_pro_slave_t*)qse_aio_makedev ( | ||||
| 				aio, QSE_SIZEOF(qse_aio_dev_pro_t),  | ||||
| 				&dev_pro_methods_slave, &dev_pro_event_callbacks_slave_in, si); | ||||
|  | ||||
| 		case QSE_AIO_DEV_PRO_OUT: | ||||
| 			return (qse_aio_dev_pro_slave_t*)qse_aio_makedev ( | ||||
| 				aio, QSE_SIZEOF(qse_aio_dev_pro_t),  | ||||
| 				&dev_pro_methods_slave, &dev_pro_event_callbacks_slave_out, si); | ||||
|  | ||||
| 		case QSE_AIO_DEV_PRO_ERR: | ||||
| 			return (qse_aio_dev_pro_slave_t*)qse_aio_makedev ( | ||||
| 				aio, QSE_SIZEOF(qse_aio_dev_pro_t),  | ||||
| 				&dev_pro_methods_slave, &dev_pro_event_callbacks_slave_err, si); | ||||
|  | ||||
| 		default: | ||||
| 			aio->errnum = QSE_AIO_EINVAL; | ||||
| 			return QSE_NULL; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| qse_aio_dev_pro_t* qse_aio_dev_pro_make (qse_aio_t* aio, qse_size_t xtnsize, const qse_aio_dev_pro_make_t* info) | ||||
| { | ||||
| 	return (qse_aio_dev_pro_t*)qse_aio_makedev ( | ||||
| 		aio, QSE_SIZEOF(qse_aio_dev_pro_t) + xtnsize,  | ||||
| 		&dev_pro_methods, &dev_pro_event_callbacks, (void*)info); | ||||
| } | ||||
|  | ||||
| void qse_aio_dev_pro_kill (qse_aio_dev_pro_t* dev) | ||||
| { | ||||
| 	qse_aio_killdev (dev->aio, (qse_aio_dev_t*)dev); | ||||
| } | ||||
|  | ||||
| int qse_aio_dev_pro_write (qse_aio_dev_pro_t* dev, const void* data, qse_aio_iolen_t dlen, void* wrctx) | ||||
| { | ||||
| 	if (dev->slave[0]) | ||||
| 	{ | ||||
| 		return qse_aio_dev_write ((qse_aio_dev_t*)dev->slave[0], data, dlen, wrctx, QSE_NULL); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		dev->aio->errnum = QSE_AIO_ENOCAPA; /* TODO: is it the right error number? */ | ||||
| 		return -1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int qse_aio_dev_pro_timedwrite (qse_aio_dev_pro_t* dev, const void* data, qse_aio_iolen_t dlen, const qse_ntime_t* tmout, void* wrctx) | ||||
| { | ||||
| 	if (dev->slave[0]) | ||||
| 	{ | ||||
| 		return qse_aio_dev_timedwrite ((qse_aio_dev_t*)dev->slave[0], data, dlen, tmout, wrctx, QSE_NULL); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		dev->aio->errnum = QSE_AIO_ENOCAPA; /* TODO: is it the right error number? */ | ||||
| 		return -1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int qse_aio_dev_pro_close (qse_aio_dev_pro_t* dev, qse_aio_dev_pro_sid_t sid) | ||||
| { | ||||
| 	return qse_aio_dev_ioctl ((qse_aio_dev_t*)dev, QSE_AIO_DEV_PRO_CLOSE, &sid); | ||||
| } | ||||
|  | ||||
| int qse_aio_dev_pro_killchild (qse_aio_dev_pro_t* dev) | ||||
| { | ||||
| 	return qse_aio_dev_ioctl ((qse_aio_dev_t*)dev, QSE_AIO_DEV_PRO_KILL_CHILD, QSE_NULL); | ||||
| } | ||||
|  | ||||
| #if 0 | ||||
| qse_aio_dev_pro_t* qse_aio_dev_pro_getdev (qse_aio_dev_pro_t* pro, qse_aio_dev_pro_sid_t sid) | ||||
| { | ||||
| 	switch (type) | ||||
| 	{ | ||||
| 		case QSE_AIO_DEV_PRO_IN: | ||||
| 			return XXX; | ||||
|  | ||||
| 		case QSE_AIO_DEV_PRO_OUT: | ||||
| 			return XXX; | ||||
|  | ||||
| 		case QSE_AIO_DEV_PRO_ERR: | ||||
| 			return XXX; | ||||
| 	} | ||||
|  | ||||
| 	pro->dev->aio = QSE_AIO_EINVAL; | ||||
| 	return QSE_NULL; | ||||
| } | ||||
| #endif | ||||
| @ -1,115 +0,0 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright (c) 2006-2016 Chung, Hyung-Hwan. All rights reserved. | ||||
|  | ||||
|     Redistribution and use in source and binary forms, with or without | ||||
|     modification, are permitted provided that the following conditions | ||||
|     are met: | ||||
|     1. Redistributions of source code must retain the above copyright | ||||
|        notice, this list of conditions and the following disclaimer. | ||||
|     2. Redistributions in binary form must reproduce the above copyright | ||||
|        notice, this list of conditions and the following disclaimer in the | ||||
|        documentation and/or other materials provided with the distribution. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES | ||||
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
| #ifndef _QSE_LIB_SI_AIO_PRV_H_ | ||||
| #define _QSE_LIB_SI_AIO_PRV_H_ | ||||
|  | ||||
| #include <qse/si/aio.h> | ||||
| #include "../cmn/mem-prv.h" | ||||
|  | ||||
|  | ||||
| typedef struct qse_aio_mux_t qse_aio_mux_t; | ||||
|  | ||||
| struct qse_aio_t | ||||
| { | ||||
| 	qse_mmgr_t* mmgr; | ||||
|  | ||||
| 	qse_aio_errnum_t errnum; | ||||
| 	qse_aio_stopreq_t stopreq;  /* stop request to abort qse_aio_loop() */ | ||||
|  | ||||
| 	struct | ||||
| 	{ | ||||
| 		qse_aio_dev_t* head; | ||||
| 		qse_aio_dev_t* tail; | ||||
| 	} actdev; /* active devices */ | ||||
|  | ||||
| 	struct | ||||
| 	{ | ||||
| 		qse_aio_dev_t* head; | ||||
| 		qse_aio_dev_t* tail; | ||||
| 	} hltdev; /* halted devices */ | ||||
|  | ||||
| 	struct | ||||
| 	{ | ||||
| 		qse_aio_dev_t* head; | ||||
| 		qse_aio_dev_t* tail; | ||||
| 	} zmbdev; /* zombie devices */ | ||||
|  | ||||
| 	qse_uint8_t bigbuf[65535]; /* TODO: make this dynamic depending on devices added. device may indicate a buffer size required??? */ | ||||
|  | ||||
| 	unsigned int renew_watch: 1; | ||||
| 	unsigned int in_exec: 1; | ||||
|  | ||||
| 	struct | ||||
| 	{ | ||||
| 		qse_size_t     capa; | ||||
| 		qse_size_t     size; | ||||
| 		qse_aio_tmrjob_t*  jobs; | ||||
| 	} tmr; | ||||
|  | ||||
| 	/* platform specific fields below */ | ||||
| #if defined(_WIN32) | ||||
| 	HANDLE iocp; | ||||
| #else | ||||
| 	qse_aio_mux_t* mux; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| int qse_aio_makesyshndasync ( | ||||
| 	qse_aio_t*       aio, | ||||
| 	qse_aio_syshnd_t hnd | ||||
| ); | ||||
|  | ||||
| qse_aio_errnum_t qse_aio_syserrtoerrnum ( | ||||
| 	int no | ||||
| ); | ||||
|  | ||||
| void qse_aio_cleartmrjobs ( | ||||
| 	qse_aio_t* aio | ||||
| ); | ||||
|  | ||||
| void qse_aio_firetmrjobs ( | ||||
| 	qse_aio_t*         aio, | ||||
| 	const qse_ntime_t* tmbase, | ||||
| 	qse_size_t*    firecnt | ||||
| ); | ||||
|  | ||||
| int qse_aio_gettmrtmout ( | ||||
| 	qse_aio_t*         aio, | ||||
| 	const qse_ntime_t* tmbase, | ||||
| 	qse_ntime_t*       tmout | ||||
| ); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										1712
									
								
								qse/lib/si/aio-sck.c
									
									
									
									
									
								
							
							
						
						
									
										1712
									
								
								qse/lib/si/aio-sck.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,234 +0,0 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright (c) 2006-2016 Chung, Hyung-Hwan. All rights reserved. | ||||
|  | ||||
|     Redistribution and use in source and binary forms, with or without | ||||
|     modification, are permitted provided that the following conditions | ||||
|     are met: | ||||
|     1. Redistributions of source code must retain the above copyright | ||||
|        notice, this list of conditions and the following disclaimer. | ||||
|     2. Redistributions in binary form must reproduce the above copyright | ||||
|        notice, this list of conditions and the following disclaimer in the | ||||
|        documentation and/or other materials provided with the distribution. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES | ||||
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include "aio-prv.h" | ||||
|  | ||||
| #define HEAP_PARENT(x) (((x) - 1) / 2) | ||||
| #define HEAP_LEFT(x)   ((x) * 2 + 1) | ||||
| #define HEAP_RIGHT(x)  ((x) * 2 + 2) | ||||
|  | ||||
| #define YOUNGER_THAN(x,y) (qse_cmptime(&(x)->when, &(y)->when) < 0) | ||||
|  | ||||
| void qse_aio_cleartmrjobs (qse_aio_t* aio) | ||||
| { | ||||
| 	while (aio->tmr.size > 0) qse_aio_deltmrjob (aio, 0); | ||||
| } | ||||
|  | ||||
| static qse_aio_tmridx_t sift_up (qse_aio_t* aio, qse_aio_tmridx_t index, int notify) | ||||
| { | ||||
| 	qse_aio_tmridx_t parent; | ||||
|  | ||||
| 	parent = HEAP_PARENT(index); | ||||
| 	if (index > 0 && YOUNGER_THAN(&aio->tmr.jobs[index], &aio->tmr.jobs[parent])) | ||||
| 	{ | ||||
| 		qse_aio_tmrjob_t item; | ||||
|  | ||||
| 		item = aio->tmr.jobs[index];  | ||||
|  | ||||
| 		do | ||||
| 		{ | ||||
| 			/* move down the parent to my current position */ | ||||
| 			aio->tmr.jobs[index] = aio->tmr.jobs[parent]; | ||||
| 			if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
|  | ||||
| 			/* traverse up */ | ||||
| 			index = parent; | ||||
| 			parent = HEAP_PARENT(parent); | ||||
| 		} | ||||
| 		while (index > 0 && YOUNGER_THAN(&item, &aio->tmr.jobs[parent])); | ||||
|  | ||||
| 		aio->tmr.jobs[index] = item; | ||||
| 		if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
| 	} | ||||
|  | ||||
| 	return index; | ||||
| } | ||||
|  | ||||
| static qse_aio_tmridx_t sift_down (qse_aio_t* aio, qse_aio_tmridx_t index, int notify) | ||||
| { | ||||
| 	qse_size_t base = aio->tmr.size / 2; | ||||
|  | ||||
| 	if (index < base) /* at least 1 child is under the 'index' position */ | ||||
| 	{ | ||||
| 		qse_aio_tmrjob_t item; | ||||
|  | ||||
| 		item = aio->tmr.jobs[index]; | ||||
|  | ||||
| 		do | ||||
| 		{ | ||||
| 			qse_aio_tmridx_t left, right, younger; | ||||
|  | ||||
| 			left = HEAP_LEFT(index); | ||||
| 			right = HEAP_RIGHT(index); | ||||
|  | ||||
| 			if (right < aio->tmr.size && YOUNGER_THAN(&aio->tmr.jobs[right], &aio->tmr.jobs[left])) | ||||
| 			{ | ||||
| 				younger = right; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				younger = left; | ||||
| 			} | ||||
|  | ||||
| 			if (YOUNGER_THAN(&item, &aio->tmr.jobs[younger])) break; | ||||
|  | ||||
| 			aio->tmr.jobs[index] = aio->tmr.jobs[younger]; | ||||
| 			if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
|  | ||||
| 			index = younger; | ||||
| 		} | ||||
| 		while (index < base); | ||||
| 		 | ||||
| 		aio->tmr.jobs[index] = item; | ||||
| 		if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
| 	} | ||||
|  | ||||
| 	return index; | ||||
| } | ||||
|  | ||||
| void qse_aio_deltmrjob (qse_aio_t* aio, qse_aio_tmridx_t index) | ||||
| { | ||||
| 	qse_aio_tmrjob_t item; | ||||
|  | ||||
| 	QSE_ASSERT (index < aio->tmr.size); | ||||
|  | ||||
| 	item = aio->tmr.jobs[index]; | ||||
| 	if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = QSE_AIO_TMRIDX_INVALID; | ||||
|  | ||||
| 	aio->tmr.size = aio->tmr.size - 1; | ||||
| 	if (aio->tmr.size > 0 && index != aio->tmr.size) | ||||
| 	{ | ||||
| 		aio->tmr.jobs[index] = aio->tmr.jobs[aio->tmr.size]; | ||||
| 		if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
| 		YOUNGER_THAN(&aio->tmr.jobs[index], &item)? sift_up(aio, index, 1): sift_down(aio, index, 1); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| qse_aio_tmridx_t qse_aio_instmrjob (qse_aio_t* aio, const qse_aio_tmrjob_t* job) | ||||
| { | ||||
| 	qse_aio_tmridx_t index = aio->tmr.size; | ||||
|  | ||||
| 	if (index >= aio->tmr.capa) | ||||
| 	{ | ||||
| 		qse_aio_tmrjob_t* tmp; | ||||
| 		qse_size_t new_capa; | ||||
|  | ||||
| 		QSE_ASSERT (aio->tmr.capa >= 1); | ||||
| 		new_capa = aio->tmr.capa * 2; | ||||
| 		tmp = (qse_aio_tmrjob_t*)QSE_MMGR_REALLOC (aio->mmgr, aio->tmr.jobs, new_capa * QSE_SIZEOF(*tmp)); | ||||
| 		if (tmp == QSE_NULL)  | ||||
| 		{ | ||||
| 			aio->errnum = QSE_AIO_ENOMEM; | ||||
| 			return QSE_AIO_TMRIDX_INVALID; | ||||
| 		} | ||||
|  | ||||
| 		aio->tmr.jobs = tmp; | ||||
| 		aio->tmr.capa = new_capa; | ||||
| 	} | ||||
|  | ||||
| 	aio->tmr.size = aio->tmr.size + 1; | ||||
| 	aio->tmr.jobs[index] = *job; | ||||
| 	if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
| 	return sift_up (aio, index, 0); | ||||
| } | ||||
|  | ||||
| qse_aio_tmridx_t qse_aio_updtmrjob (qse_aio_t* aio, qse_aio_tmridx_t index, const qse_aio_tmrjob_t* job) | ||||
| { | ||||
| 	qse_aio_tmrjob_t item; | ||||
| 	item = aio->tmr.jobs[index]; | ||||
| 	aio->tmr.jobs[index] = *job; | ||||
| 	if (aio->tmr.jobs[index].idxptr) *aio->tmr.jobs[index].idxptr = index; | ||||
| 	return YOUNGER_THAN(job, &item)? sift_up (aio, index, 0): sift_down (aio, index, 0); | ||||
| } | ||||
|  | ||||
| void qse_aio_firetmrjobs (qse_aio_t* aio, const qse_ntime_t* tm, qse_size_t* firecnt) | ||||
| { | ||||
| 	qse_ntime_t now; | ||||
| 	qse_aio_tmrjob_t tmrjob; | ||||
| 	qse_size_t count = 0; | ||||
|  | ||||
| 	/* if the current time is not specified, get it from the system */ | ||||
| 	if (tm) now = *tm; | ||||
| 	else qse_gettime (&now); | ||||
|  | ||||
| 	while (aio->tmr.size > 0) | ||||
| 	{ | ||||
| 		if (qse_cmptime(&aio->tmr.jobs[0].when, &now) > 0) break; | ||||
|  | ||||
| 		tmrjob = aio->tmr.jobs[0]; /* copy the scheduled job */ | ||||
| 		qse_aio_deltmrjob (aio, 0); /* deschedule the job */ | ||||
|  | ||||
| 		count++; | ||||
| 		tmrjob.handler (aio, &now, &tmrjob); /* then fire the job */ | ||||
| 	} | ||||
|  | ||||
| 	if (firecnt) *firecnt = count; | ||||
| } | ||||
|  | ||||
| int qse_aio_gettmrtmout (qse_aio_t* aio, const qse_ntime_t* tm, qse_ntime_t* tmout) | ||||
| { | ||||
| 	qse_ntime_t now; | ||||
|  | ||||
| 	/* time-out can't be calculated when there's no job scheduled */ | ||||
| 	if (aio->tmr.size <= 0)  | ||||
| 	{ | ||||
| 		aio->errnum = QSE_AIO_ENOENT; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* if the current time is not specified, get it from the system */ | ||||
| 	if (tm) now = *tm; | ||||
| 	else qse_gettime (&now); | ||||
|  | ||||
| 	qse_subtime (&aio->tmr.jobs[0].when, &now, tmout); | ||||
| 	if (tmout->sec < 0) qse_cleartime (tmout); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| qse_aio_tmrjob_t* qse_aio_gettmrjob (qse_aio_t* aio, qse_aio_tmridx_t index) | ||||
| { | ||||
| 	if (index < 0 || index >= aio->tmr.size) | ||||
| 	{ | ||||
| 		aio->errnum = QSE_AIO_ENOENT; | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	return &aio->tmr.jobs[index]; | ||||
| } | ||||
|  | ||||
| int qse_aio_gettmrjobdeadline (qse_aio_t* aio, qse_aio_tmridx_t index, qse_ntime_t* deadline) | ||||
| { | ||||
| 	if (index < 0 || index >= aio->tmr.size) | ||||
| 	{ | ||||
| 		aio->errnum = QSE_AIO_ENOENT; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	*deadline = aio->tmr.jobs[index].when; | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										1468
									
								
								qse/lib/si/aio.c
									
									
									
									
									
								
							
							
						
						
									
										1468
									
								
								qse/lib/si/aio.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -6,7 +6,6 @@ AM_CPPFLAGS = \ | ||||
| 	-I$(includedir) | ||||
|  | ||||
| bin_PROGRAMS = \ | ||||
| 	aio01 \ | ||||
| 	dir01 \ | ||||
| 	fio01 \ | ||||
| 	fio02 \ | ||||
| @ -38,7 +37,6 @@ LDADD += $(UNICOWS_LIBS) | ||||
| endif | ||||
| endif | ||||
|  | ||||
| aio01_SOURCES = aio01.c | ||||
| dir01_SOURCES = dir01.c | ||||
| fio01_SOURCES = fio01.c | ||||
| fio02_SOURCES = fio02.c | ||||
|  | ||||
| @ -1,713 +0,0 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright (c) 2015-2016 Chung, Hyung-Hwan. All rights reserved. | ||||
|  | ||||
|     Redistribution and use in source and binary forms, with or without | ||||
|     modification, are permitted provided that the following conditions | ||||
|     are met: | ||||
|     1. Redistributions of source code must retain the above copyright | ||||
|        notice, this list of conditions and the following disclaimer. | ||||
|     2. Redistributions in binary form must reproduce the above copyright | ||||
|        notice, this list of conditions and the following disclaimer in the | ||||
|        documentation and/or other materials provided with the distribution. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | ||||
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES | ||||
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include <qse/si/aio.h> | ||||
| #include <qse/si/aio-sck.h> | ||||
| #include <qse/si/aio-pro.h> | ||||
| #include <qse/cmn/hton.h> | ||||
| #include <qse/cmn/mem.h> | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
| #include <arpa/inet.h> | ||||
| #include <signal.h> | ||||
|  | ||||
| #include <net/if.h> | ||||
|  | ||||
| #include <assert.h> | ||||
|  | ||||
| #if defined(HAVE_OPENSSL_SSL_H) && defined(HAVE_SSL) | ||||
| #	include <openssl/ssl.h> | ||||
| #	if defined(HAVE_OPENSSL_ERR_H) | ||||
| #		include <openssl/err.h> | ||||
| #	endif | ||||
| #	if defined(HAVE_OPENSSL_ENGINE_H) | ||||
| #		include <openssl/engine.h> | ||||
| #	endif | ||||
| #	define USE_SSL | ||||
| #endif | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| #if defined(USE_SSL) | ||||
| static void cleanup_openssl () | ||||
| { | ||||
| 	/* ERR_remove_state() should be called for each thread if the application is thread */ | ||||
| 	ERR_remove_state (0); | ||||
| #if defined(HAVE_ENGINE_CLEANUP) | ||||
| 	ENGINE_cleanup (); | ||||
| #endif | ||||
| 	ERR_free_strings (); | ||||
| 	EVP_cleanup (); | ||||
| #if defined(HAVE_CRYPTO_CLEANUP_ALL_EX_DATA) | ||||
| 	CRYPTO_cleanup_all_ex_data (); | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
|  | ||||
| struct tcp_server_t | ||||
| { | ||||
| 	int tally; | ||||
| }; | ||||
| typedef struct tcp_server_t tcp_server_t; | ||||
|  | ||||
| static void tcp_sck_on_disconnect (qse_aio_dev_sck_t* tcp) | ||||
| { | ||||
| 	switch (QSE_AIO_DEV_SCK_GET_PROGRESS(tcp)) | ||||
| 	{ | ||||
| 		case QSE_AIO_DEV_SCK_CONNECTING: | ||||
| 			printf ("OUTGOING SESSION DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_AIO_DEV_SCK_CONNECTING_SSL: | ||||
| 			printf ("OUTGOING SESSION DISCONNECTED - FAILED TO SSL-CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_AIO_DEV_SCK_LISTENING: | ||||
| 			printf ("SHUTTING DOWN THE SERVER SOCKET(%d)...\n", (int)tcp->sck); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_AIO_DEV_SCK_CONNECTED: | ||||
| 			printf ("OUTGOING CLIENT CONNECTION GOT TORN DOWN(%d).......\n", (int)tcp->sck); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_AIO_DEV_SCK_ACCEPTING_SSL: | ||||
| 			printf ("INCOMING SSL-ACCEPT GOT DISCONNECTED(%d) ....\n", (int)tcp->sck); | ||||
| 			break; | ||||
|  | ||||
| 		case QSE_AIO_DEV_SCK_ACCEPTED: | ||||
| 			printf ("INCOMING CLIENT BEING SERVED GOT DISCONNECTED(%d).......\n", (int)tcp->sck); | ||||
| 			break; | ||||
|  | ||||
| 		default: | ||||
| 			printf ("SOCKET DEVICE DISCONNECTED (%d - %x)\n", (int)tcp->sck, (unsigned int)tcp->state); | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| static int tcp_sck_on_connect (qse_aio_dev_sck_t* tcp) | ||||
| { | ||||
|  | ||||
| 	qse_aio_sckfam_t fam; | ||||
| 	qse_aio_scklen_t len; | ||||
| 	qse_mchar_t buf1[128], buf2[128]; | ||||
|  | ||||
| 	memset (buf1, 0, QSE_SIZEOF(buf1)); | ||||
| 	memset (buf2, 0, QSE_SIZEOF(buf2)); | ||||
|  | ||||
| 	qse_aio_getsckaddrinfo (tcp->aio, &tcp->localaddr, &len, &fam); | ||||
| 	inet_ntop (fam, tcp->localaddr.data, buf1, QSE_COUNTOF(buf1)); | ||||
|  | ||||
| 	qse_aio_getsckaddrinfo (tcp->aio, &tcp->remoteaddr, &len, &fam); | ||||
| 	inet_ntop (fam, tcp->remoteaddr.data, buf2, QSE_COUNTOF(buf2)); | ||||
|  | ||||
| 	if (tcp->state & QSE_AIO_DEV_SCK_CONNECTED) | ||||
| 	{ | ||||
|  | ||||
| printf ("device connected to a remote server... LOCAL %s:%d REMOTE %s:%d.", buf1, qse_aio_getsckaddrport(&tcp->localaddr), buf2, qse_aio_getsckaddrport(&tcp->remoteaddr)); | ||||
|  | ||||
| 	} | ||||
| 	else if (tcp->state & QSE_AIO_DEV_SCK_ACCEPTED) | ||||
| 	{ | ||||
| printf ("device accepted client device... .LOCAL %s:%d REMOTE %s:%d\n", buf1, qse_aio_getsckaddrport(&tcp->localaddr), buf2, qse_aio_getsckaddrport(&tcp->remoteaddr)); | ||||
| 	} | ||||
|  | ||||
| 	return qse_aio_dev_sck_write  (tcp, "hello", 5, QSE_NULL, QSE_NULL); | ||||
| } | ||||
|  | ||||
| static int tcp_sck_on_write (qse_aio_dev_sck_t* tcp, qse_aio_iolen_t wrlen, void* wrctx, const qse_aio_sckaddr_t* dstaddr) | ||||
| { | ||||
| 	tcp_server_t* ts; | ||||
|  | ||||
| if (wrlen <= -1) | ||||
| { | ||||
| printf ("SEDING TIMED OUT...........\n"); | ||||
| 	qse_aio_dev_sck_halt(tcp); | ||||
| } | ||||
| else | ||||
| { | ||||
| 	ts = (tcp_server_t*)(tcp + 1); | ||||
| 	printf (">>> SENT MESSAGE %d of length %ld\n", ts->tally, (long int)wrlen); | ||||
|  | ||||
| 	ts->tally++; | ||||
| //	if (ts->tally >= 2) qse_aio_dev_sck_halt (tcp); | ||||
|  | ||||
| printf ("ENABLING READING..............................\n"); | ||||
| 	qse_aio_dev_sck_read (tcp, 1); | ||||
|  | ||||
| 	//qse_aio_dev_sck_timedread (tcp, 1, 1000); | ||||
| } | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int tcp_sck_on_read (qse_aio_dev_sck_t* tcp, const void* buf, qse_aio_iolen_t len, const qse_aio_sckaddr_t* srcaddr) | ||||
| { | ||||
| 	int n; | ||||
|  | ||||
| 	if (len <= 0) | ||||
| 	{ | ||||
| 		printf ("STREAM DEVICE: EOF RECEIVED...\n"); | ||||
| 		/* no outstanding request. but EOF */ | ||||
| 		qse_aio_dev_sck_halt (tcp); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| printf ("on read %d\n", (int)len); | ||||
|  | ||||
| { | ||||
| qse_ntime_t tmout; | ||||
|  | ||||
| static char a ='A'; | ||||
| char* xxx = malloc (1000000); | ||||
| memset (xxx, a++ ,1000000); | ||||
|  | ||||
| 	//return qse_aio_dev_sck_write  (tcp, "HELLO", 5, QSE_NULL); | ||||
| 	qse_inittime (&tmout, 5, 0); | ||||
| 	n = qse_aio_dev_sck_timedwrite  (tcp, xxx, 1000000, &tmout, QSE_NULL, QSE_NULL); | ||||
| free (xxx); | ||||
|  | ||||
|  | ||||
| 	if (n <= -1) return -1; | ||||
| } | ||||
|  | ||||
|  | ||||
| printf ("DISABLING READING..............................\n"); | ||||
| 	qse_aio_dev_sck_read (tcp, 0); | ||||
|  | ||||
| 	/* post the write finisher */ | ||||
| 	n = qse_aio_dev_sck_write  (tcp, QSE_NULL, 0, QSE_NULL, QSE_NULL); | ||||
| 	if (n <= -1) return -1; | ||||
|  | ||||
| 	return 0; | ||||
|  | ||||
| /* return 1; let the main loop to read more greedily without consulting the multiplexer */ | ||||
| } | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| static void pro_on_close (qse_aio_dev_pro_t* dev, qse_aio_dev_pro_sid_t sid) | ||||
| { | ||||
| printf (">>>>>>>>>>>>> ON CLOSE OF SLAVE %d.\n", sid); | ||||
| } | ||||
|  | ||||
| static int pro_on_read (qse_aio_dev_pro_t* dev, const void* data, qse_aio_iolen_t dlen, qse_aio_dev_pro_sid_t sid) | ||||
| { | ||||
| printf ("PROCESS READ DATA on SLAVE[%d]... [%.*s]\n", (int)sid, (int)dlen, (char*)data); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int pro_on_write (qse_aio_dev_pro_t* dev, qse_aio_iolen_t wrlen, void* wrctx) | ||||
| { | ||||
| printf ("PROCESS WROTE DATA...\n"); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| static int arp_sck_on_read (qse_aio_dev_sck_t* dev, const void* data, qse_aio_iolen_t dlen, const qse_aio_sckaddr_t* srcaddr) | ||||
| { | ||||
| 	qse_aio_etharp_pkt_t* eap; | ||||
|  | ||||
|  | ||||
| 	if (dlen < QSE_SIZEOF(*eap)) return 0; /* drop */ | ||||
|  | ||||
| 	eap = (qse_aio_etharp_pkt_t*)data; | ||||
|  | ||||
| 	printf ("ARP ON IFINDEX %d OPCODE: %d", qse_aio_getsckaddrifindex(srcaddr), ntohs(eap->arphdr.opcode)); | ||||
|  | ||||
| 	printf (" SHA: %02X:%02X:%02X:%02X:%02X:%02X", eap->arppld.sha[0], eap->arppld.sha[1], eap->arppld.sha[2], eap->arppld.sha[3], eap->arppld.sha[4], eap->arppld.sha[5]); | ||||
| 	printf (" SPA: %d.%d.%d.%d", eap->arppld.spa[0], eap->arppld.spa[1], eap->arppld.spa[2], eap->arppld.spa[3]); | ||||
| 	printf (" THA: %02X:%02X:%02X:%02X:%02X:%02X", eap->arppld.tha[0], eap->arppld.tha[1], eap->arppld.tha[2], eap->arppld.tha[3], eap->arppld.tha[4], eap->arppld.tha[5]); | ||||
| 	printf (" TPA: %d.%d.%d.%d", eap->arppld.tpa[0], eap->arppld.tpa[1], eap->arppld.tpa[2], eap->arppld.tpa[3]); | ||||
| 	printf ("\n"); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int arp_sck_on_write (qse_aio_dev_sck_t* dev, qse_aio_iolen_t wrlen, void* wrctx, const qse_aio_sckaddr_t* dstaddr) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void arp_sck_on_disconnect (qse_aio_dev_sck_t* dev) | ||||
| { | ||||
| printf ("SHUTTING DOWN ARP SOCKET %d...\n", dev->sck); | ||||
| } | ||||
|  | ||||
| static int setup_arp_tester (qse_aio_t* aio) | ||||
| { | ||||
| 	qse_aio_sckaddr_t ethdst; | ||||
| 	qse_aio_etharp_pkt_t etharp; | ||||
| 	qse_aio_dev_sck_make_t sck_make; | ||||
| 	qse_aio_dev_sck_t* sck; | ||||
|  | ||||
| 	memset (&sck_make, 0, QSE_SIZEOF(sck_make)); | ||||
| 	sck_make.type = QSE_AIO_DEV_SCK_ARP; | ||||
| 	//sck_make.type = QSE_AIO_DEV_SCK_ARP_DGRAM; | ||||
| 	sck_make.on_write = arp_sck_on_write; | ||||
| 	sck_make.on_read = arp_sck_on_read; | ||||
| 	sck_make.on_disconnect = arp_sck_on_disconnect; | ||||
| 	sck = qse_aio_dev_sck_make (aio, 0, &sck_make); | ||||
| 	if (!sck) | ||||
| 	{ | ||||
| 		printf ("Cannot make socket device\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	//qse_aio_sckaddr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (qse_aio_ethaddr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF"); | ||||
| 	qse_aio_sckaddr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (qse_aio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF"); | ||||
|  | ||||
| 	memset (ðarp, 0, sizeof(etharp)); | ||||
|  | ||||
| 	memcpy (etharp.ethhdr.source, "\xB8\x6B\x23\x9C\x10\x76", QSE_AIO_ETHADDR_LEN); | ||||
| 	//memcpy (etharp.ethhdr.dest, "\xFF\xFF\xFF\xFF\xFF\xFF", QSE_AIO_ETHADDR_LEN); | ||||
| 	memcpy (etharp.ethhdr.dest, "\xAA\xBB\xFF\xCC\xDD\xFF", QSE_AIO_ETHADDR_LEN); | ||||
| 	etharp.ethhdr.proto = QSE_CONST_HTON16(QSE_AIO_ETHHDR_PROTO_ARP); | ||||
|  | ||||
| 	etharp.arphdr.htype = QSE_CONST_HTON16(QSE_AIO_ARPHDR_HTYPE_ETH); | ||||
| 	etharp.arphdr.ptype = QSE_CONST_HTON16(QSE_AIO_ARPHDR_PTYPE_IP4); | ||||
| 	etharp.arphdr.hlen = QSE_AIO_ETHADDR_LEN; | ||||
| 	etharp.arphdr.plen = QSE_AIO_IP4ADDR_LEN; | ||||
| 	etharp.arphdr.opcode = QSE_CONST_HTON16(QSE_AIO_ARPHDR_OPCODE_REQUEST); | ||||
|  | ||||
| 	memcpy (etharp.arppld.sha, "\xB8\x6B\x23\x9C\x10\x76", QSE_AIO_ETHADDR_LEN); | ||||
|  | ||||
| 	if (qse_aio_dev_sck_write (sck, ðarp, sizeof(etharp), NULL, ðdst) <= -1) | ||||
| 	//if (qse_aio_dev_sck_write (sck, ðarp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, ðaddr) <= -1) | ||||
| 	{ | ||||
| 		printf ("CANNOT WRITE ARP...\n"); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| struct icmpxtn_t | ||||
| { | ||||
| 	qse_uint16_t icmp_seq; | ||||
| 	qse_aio_tmridx_t tmout_jobidx; | ||||
| 	int reply_received; | ||||
| }; | ||||
|  | ||||
| typedef struct icmpxtn_t icmpxtn_t; | ||||
|  | ||||
| static int schedule_icmp_wait (qse_aio_dev_sck_t* dev); | ||||
|  | ||||
| static void send_icmp (qse_aio_dev_sck_t* dev, qse_uint16_t seq) | ||||
| { | ||||
| 	qse_aio_sckaddr_t dstaddr; | ||||
| 	qse_aio_ip4addr_t ia; | ||||
| 	qse_aio_icmphdr_t* icmphdr; | ||||
| 	qse_uint8_t buf[512]; | ||||
|  | ||||
| 	inet_pton (AF_INET, "192.168.1.131", &ia); | ||||
| 	qse_aio_sckaddr_initforip4 (&dstaddr, 0, &ia); | ||||
|  | ||||
| 	memset(buf, 0, QSE_SIZEOF(buf)); | ||||
| 	icmphdr = (qse_aio_icmphdr_t*)buf; | ||||
| 	icmphdr->type = QSE_AIO_ICMP_ECHO_REQUEST; | ||||
| 	icmphdr->u.echo.id = QSE_CONST_HTON16(100); | ||||
| 	icmphdr->u.echo.seq = qse_hton16(seq); | ||||
|  | ||||
| 	memset (&buf[QSE_SIZEOF(*icmphdr)], 'A', QSE_SIZEOF(buf) - QSE_SIZEOF(*icmphdr)); | ||||
| 	icmphdr->checksum = qse_aio_checksumip (icmphdr, QSE_SIZEOF(buf)); | ||||
|  | ||||
| 	if (qse_aio_dev_sck_write (dev, buf, QSE_SIZEOF(buf), NULL, &dstaddr) <= -1) | ||||
| 	{ | ||||
| 		printf ("CANNOT WRITE ICMP...\n"); | ||||
| 		qse_aio_dev_sck_halt (dev); | ||||
| 	} | ||||
|  | ||||
| 	if (schedule_icmp_wait (dev) <= -1) | ||||
| 	{ | ||||
| 		printf ("CANNOT SCHEDULE ICMP WAIT...\n"); | ||||
| 		qse_aio_dev_sck_halt (dev); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void on_icmp_due (qse_aio_t* aio, const qse_ntime_t* now, qse_aio_tmrjob_t* tmrjob) | ||||
| { | ||||
| 	qse_aio_dev_sck_t* dev; | ||||
| 	icmpxtn_t* icmpxtn; | ||||
|  | ||||
| 	dev = tmrjob->ctx; | ||||
| 	icmpxtn = (icmpxtn_t*)(dev + 1); | ||||
|  | ||||
| 	if (icmpxtn->reply_received) | ||||
| 		icmpxtn->reply_received = 0; | ||||
| 	else | ||||
| 		printf ("NO ICMP REPLY RECEIVED....\n"); | ||||
|  | ||||
| 	send_icmp (dev, ++icmpxtn->icmp_seq); | ||||
| } | ||||
|  | ||||
| static int schedule_icmp_wait (qse_aio_dev_sck_t* dev) | ||||
| { | ||||
| 	icmpxtn_t* icmpxtn; | ||||
| 	qse_aio_tmrjob_t tmrjob; | ||||
| 	qse_ntime_t fire_after; | ||||
|  | ||||
| 	icmpxtn = (icmpxtn_t*)(dev + 1); | ||||
| 	qse_inittime (&fire_after, 2, 0); | ||||
|  | ||||
| 	memset (&tmrjob, 0, QSE_SIZEOF(tmrjob)); | ||||
| 	tmrjob.ctx = dev; | ||||
| 	qse_gettime (&tmrjob.when); | ||||
| 	qse_addtime (&tmrjob.when, &fire_after, &tmrjob.when); | ||||
| 	tmrjob.handler = on_icmp_due; | ||||
| 	tmrjob.idxptr = &icmpxtn->tmout_jobidx; | ||||
|  | ||||
| 	assert (icmpxtn->tmout_jobidx == QSE_AIO_TMRIDX_INVALID); | ||||
|  | ||||
| 	return (qse_aio_instmrjob (dev->aio, &tmrjob) == QSE_AIO_TMRIDX_INVALID)? -1: 0; | ||||
| } | ||||
|  | ||||
| static int icmp_sck_on_read (qse_aio_dev_sck_t* dev, const void* data, qse_aio_iolen_t dlen, const qse_aio_sckaddr_t* srcaddr) | ||||
| { | ||||
| 	icmpxtn_t* icmpxtn; | ||||
| 	qse_aio_iphdr_t* iphdr; | ||||
| 	qse_aio_icmphdr_t* icmphdr; | ||||
|  | ||||
| 	/* when received, the data contains the IP header.. */ | ||||
| 	icmpxtn = (icmpxtn_t*)(dev + 1); | ||||
|  | ||||
| 	if (dlen < QSE_SIZEOF(*iphdr) + QSE_SIZEOF(*icmphdr)) | ||||
| 	{ | ||||
| 		printf ("INVALID ICMP PACKET.. TOO SHORT...%d\n", (int)dlen); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		/* TODO: consider IP options... */ | ||||
| 		iphdr = (qse_aio_iphdr_t*)data; | ||||
|  | ||||
| 		if (iphdr->ihl * 4 + QSE_SIZEOF(*icmphdr) > dlen) | ||||
| 		{ | ||||
| 			printf ("INVALID ICMP PACKET.. WRONG IHL...%d\n", (int)iphdr->ihl * 4); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			icmphdr = (qse_aio_icmphdr_t*)((qse_uint8_t*)data + (iphdr->ihl * 4)); | ||||
|  | ||||
| 			/* TODO: check srcaddr against target */ | ||||
|  | ||||
| 			if (icmphdr->type == QSE_AIO_ICMP_ECHO_REPLY &&  | ||||
| 			    qse_ntoh16(icmphdr->u.echo.seq) == icmpxtn->icmp_seq) /* TODO: more check.. echo.id.. */ | ||||
| 			{ | ||||
| 				icmpxtn->reply_received = 1; | ||||
| 				printf ("ICMP REPLY RECEIVED...ID %d SEQ %d\n", (int)qse_ntoh16(icmphdr->u.echo.id), (int)qse_ntoh16(icmphdr->u.echo.seq)); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				printf ("GARBAGE ICMP PACKET...LEN %d SEQ %d,%d\n", (int)dlen, (int)icmpxtn->icmp_seq, (int)qse_ntoh16(icmphdr->u.echo.seq)); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| static int icmp_sck_on_write (qse_aio_dev_sck_t* dev, qse_aio_iolen_t wrlen, void* wrctx, const qse_aio_sckaddr_t* dstaddr) | ||||
| { | ||||
| 	/*icmpxtn_t* icmpxtn; | ||||
|  | ||||
| 	icmpxtn = (icmpxtn_t*)(dev + 1); */ | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void icmp_sck_on_disconnect (qse_aio_dev_sck_t* dev) | ||||
| { | ||||
| 	icmpxtn_t* icmpxtn; | ||||
|  | ||||
| 	icmpxtn = (icmpxtn_t*)(dev + 1); | ||||
|  | ||||
| printf ("SHUTTING DOWN ICMP SOCKET %d...\n", dev->sck); | ||||
| 	if (icmpxtn->tmout_jobidx != QSE_AIO_TMRIDX_INVALID) | ||||
| 	{ | ||||
|  | ||||
| 		qse_aio_deltmrjob (dev->aio, icmpxtn->tmout_jobidx); | ||||
| 		icmpxtn->tmout_jobidx = QSE_AIO_TMRIDX_INVALID; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static int setup_ping4_tester (qse_aio_t* aio) | ||||
| { | ||||
| 	qse_aio_dev_sck_make_t sck_make; | ||||
| 	qse_aio_dev_sck_t* sck; | ||||
| 	icmpxtn_t* icmpxtn; | ||||
|  | ||||
| 	memset (&sck_make, 0, QSE_SIZEOF(sck_make)); | ||||
| 	sck_make.type = QSE_AIO_DEV_SCK_ICMP4; | ||||
| 	sck_make.on_write = icmp_sck_on_write; | ||||
| 	sck_make.on_read = icmp_sck_on_read; | ||||
| 	sck_make.on_disconnect = icmp_sck_on_disconnect; | ||||
|  | ||||
| 	sck = qse_aio_dev_sck_make (aio, QSE_SIZEOF(icmpxtn_t), &sck_make); | ||||
| 	if (!sck) | ||||
| 	{ | ||||
| 		printf ("Cannot make ICMP4 socket device\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	icmpxtn = (icmpxtn_t*)(sck + 1); | ||||
| 	icmpxtn->tmout_jobidx = QSE_AIO_TMRIDX_INVALID; | ||||
| 	icmpxtn->icmp_seq = 0; | ||||
|  | ||||
| 	/*TODO: qse_aio_dev_sck_setbroadcast (sck, 1);*/ | ||||
|  | ||||
| 	send_icmp (sck, ++icmpxtn->icmp_seq); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* ========================================================================= */ | ||||
|  | ||||
| static qse_aio_t* g_aio; | ||||
|  | ||||
| static void handle_signal (int sig) | ||||
| { | ||||
| 	if (g_aio) qse_aio_stop (g_aio, QSE_AIO_STOPREQ_TERMINATION); | ||||
| } | ||||
|  | ||||
| int main () | ||||
| { | ||||
| 	int i; | ||||
|  | ||||
| 	qse_aio_t* aio; | ||||
| 	qse_aio_dev_sck_t* tcp[3]; | ||||
|  | ||||
| 	struct sigaction sigact; | ||||
| 	qse_aio_dev_sck_connect_t tcp_conn; | ||||
| 	qse_aio_dev_sck_listen_t tcp_lstn; | ||||
| 	qse_aio_dev_sck_bind_t tcp_bind; | ||||
| 	qse_aio_dev_sck_make_t tcp_make; | ||||
|  | ||||
| 	tcp_server_t* ts; | ||||
|  | ||||
| #if defined(USE_SSL) | ||||
| 	SSL_load_error_strings (); | ||||
| 	SSL_library_init (); | ||||
| #endif | ||||
|  | ||||
| 	aio = qse_aio_open(QSE_MMGR_GETDFL(), 0, 512, QSE_NULL); | ||||
| 	if (!aio) | ||||
| 	{ | ||||
| 		printf ("Cannot open aio\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	g_aio = aio; | ||||
|  | ||||
| 	memset (&sigact, 0, QSE_SIZEOF(sigact)); | ||||
| 	sigact.sa_flags = SA_RESTART; | ||||
| 	sigact.sa_handler = handle_signal; | ||||
| 	sigaction (SIGINT, &sigact, QSE_NULL); | ||||
|  | ||||
| 	memset (&sigact, 0, QSE_SIZEOF(sigact)); | ||||
| 	sigact.sa_handler = SIG_IGN; | ||||
| 	sigaction (SIGPIPE, &sigact, QSE_NULL); | ||||
|  | ||||
| /* | ||||
| 	memset (&sigact, 0, QSE_SIZEOF(sigact)); | ||||
| 	sigact.sa_handler = SIG_IGN; | ||||
| 	sigaction (SIGCHLD, &sigact, QSE_NULL); | ||||
| */ | ||||
|  | ||||
| 	/*memset (&sin, 0, QSE_SIZEOF(sin)); | ||||
| 	sin.sin_family = AF_INET; | ||||
| 	sin.sin_port = htons(1234); */ | ||||
| /* | ||||
| 	udp = (qse_aio_dev_udp_t*)qse_aio_makedev (aio, QSE_SIZEOF(*udp), &udp_mth, &udp_evcb, &sin); | ||||
| 	if (!udp) | ||||
| 	{ | ||||
| 		printf ("Cannot make udp\n"); | ||||
| 		goto oops; | ||||
| 	} | ||||
| */ | ||||
|  | ||||
| 	memset (&tcp_make, 0, QSE_SIZEOF(&tcp_make)); | ||||
| 	tcp_make.type = QSE_AIO_DEV_SCK_TCP4; | ||||
| 	tcp_make.on_write = tcp_sck_on_write; | ||||
| 	tcp_make.on_read = tcp_sck_on_read; | ||||
| 	tcp_make.on_disconnect = tcp_sck_on_disconnect; | ||||
| 	tcp[0] = qse_aio_dev_sck_make(aio, QSE_SIZEOF(tcp_server_t), &tcp_make); | ||||
| 	if (!tcp[0]) | ||||
| 	{ | ||||
| 		printf ("Cannot make tcp\n"); | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	ts = (tcp_server_t*)(tcp[0] + 1); | ||||
| 	ts->tally = 0; | ||||
|  | ||||
|  | ||||
| 	memset (&tcp_conn, 0, QSE_SIZEOF(tcp_conn)); | ||||
| { | ||||
| 	in_addr_t ia = inet_addr("192.168.1.119"); | ||||
| 	qse_aio_sckaddr_initforip4 (&tcp_conn.remoteaddr, 9999, (qse_aio_ip4addr_t*)&ia); | ||||
| } | ||||
|  | ||||
| 	qse_inittime (&tcp_conn.connect_tmout, 5, 0); | ||||
| 	tcp_conn.on_connect = tcp_sck_on_connect; | ||||
| 	tcp_conn.options = QSE_AIO_DEV_SCK_CONNECT_SSL; | ||||
| 	if (qse_aio_dev_sck_connect(tcp[0], &tcp_conn) <= -1) | ||||
| 	{ | ||||
| 		printf ("qse_aio_dev_sck_connect() failed....\n"); | ||||
| 		/* carry on regardless of failure */ | ||||
| 	} | ||||
|  | ||||
| 	/* -------------------------------------------------------------- */ | ||||
| 	memset (&tcp_make, 0, QSE_SIZEOF(&tcp_make)); | ||||
| 	tcp_make.type = QSE_AIO_DEV_SCK_TCP4; | ||||
| 	tcp_make.on_write = tcp_sck_on_write; | ||||
| 	tcp_make.on_read = tcp_sck_on_read; | ||||
| 	tcp_make.on_disconnect = tcp_sck_on_disconnect; | ||||
|  | ||||
| 	tcp[1] = qse_aio_dev_sck_make(aio, QSE_SIZEOF(tcp_server_t), &tcp_make); | ||||
| 	if (!tcp[1]) | ||||
| 	{ | ||||
| 		printf ("Cannot make tcp\n"); | ||||
| 		goto oops; | ||||
| 	} | ||||
| 	ts = (tcp_server_t*)(tcp[1] + 1); | ||||
| 	ts->tally = 0; | ||||
|  | ||||
| 	memset (&tcp_bind, 0, QSE_SIZEOF(tcp_bind)); | ||||
| 	qse_aio_sckaddr_initforip4 (&tcp_bind.localaddr, 1234, QSE_NULL); | ||||
| 	tcp_bind.options = QSE_AIO_DEV_SCK_BIND_REUSEADDR; | ||||
|  | ||||
| 	if (qse_aio_dev_sck_bind (tcp[1],&tcp_bind) <= -1) | ||||
| 	{ | ||||
| 		printf ("qse_aio_dev_sck_bind() failed....\n"); | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	tcp_lstn.backlogs = 100; | ||||
| 	tcp_lstn.on_connect = tcp_sck_on_connect; | ||||
| 	if (qse_aio_dev_sck_listen (tcp[1], &tcp_lstn) <= -1) | ||||
| 	{ | ||||
| 		printf ("qse_aio_dev_sck_listen() failed....\n"); | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	/* -------------------------------------------------------------- */ | ||||
| 	memset (&tcp_make, 0, QSE_SIZEOF(&tcp_make)); | ||||
| 	tcp_make.type = QSE_AIO_DEV_SCK_TCP4; | ||||
| 	tcp_make.on_write = tcp_sck_on_write; | ||||
| 	tcp_make.on_read = tcp_sck_on_read; | ||||
| 	tcp_make.on_disconnect = tcp_sck_on_disconnect; | ||||
|  | ||||
| 	tcp[2] = qse_aio_dev_sck_make (aio, QSE_SIZEOF(tcp_server_t), &tcp_make); | ||||
| 	if (!tcp[2]) | ||||
| 	{ | ||||
| 		printf ("Cannot make tcp\n"); | ||||
| 		goto oops; | ||||
| 	} | ||||
| 	ts = (tcp_server_t*)(tcp[2] + 1); | ||||
| 	ts->tally = 0; | ||||
|  | ||||
| 	memset (&tcp_bind, 0, QSE_SIZEOF(tcp_bind)); | ||||
| 	qse_aio_sckaddr_initforip4 (&tcp_bind.localaddr, 1235, QSE_NULL); | ||||
| 	tcp_bind.options = QSE_AIO_DEV_SCK_BIND_REUSEADDR | /*QSE_AIO_DEV_SCK_BIND_REUSEPORT |*/ QSE_AIO_DEV_SCK_BIND_SSL;  | ||||
| 	tcp_bind.ssl_certfile = QSE_MT("localhost.crt"); | ||||
| 	tcp_bind.ssl_keyfile = QSE_MT("localhost.key"); | ||||
| 	qse_inittime (&tcp_bind.accept_tmout, 5, 1); | ||||
|  | ||||
| 	if (qse_aio_dev_sck_bind (tcp[2],&tcp_bind) <= -1) | ||||
| 	{ | ||||
| 		printf ("qse_aio_dev_sck_bind() failed....\n"); | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	tcp_lstn.backlogs = 100; | ||||
| 	tcp_lstn.on_connect = tcp_sck_on_connect; | ||||
| 	if (qse_aio_dev_sck_listen (tcp[2], &tcp_lstn) <= -1) | ||||
| 	{ | ||||
| 		printf ("qse_aio_dev_sck_listen() failed....\n"); | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	//qse_aio_dev_sck_sendfile (tcp[2], fd, offset, count); | ||||
|  | ||||
| 	if (setup_arp_tester(aio) <= -1) goto oops; | ||||
| 	if (setup_ping4_tester(aio) <= -1) goto oops; | ||||
|  | ||||
|  | ||||
| for (i = 0; i < 5; i++) | ||||
| { | ||||
| 	qse_aio_dev_pro_t* pro; | ||||
| 	qse_aio_dev_pro_make_t pro_make; | ||||
|  | ||||
| 	memset (&pro_make, 0, QSE_SIZEOF(pro_make)); | ||||
| 	pro_make.flags = QSE_AIO_DEV_PRO_READOUT | QSE_AIO_DEV_PRO_READERR | QSE_AIO_DEV_PRO_WRITEIN /*| QSE_AIO_DEV_PRO_FORGET_CHILD*/; | ||||
| 	//pro_make.cmd = "/bin/ls -laF /usr/bin"; | ||||
| 	//pro_make.cmd = "/bin/ls -laF"; | ||||
| 	pro_make.cmd = "./a"; | ||||
| 	pro_make.on_read = pro_on_read; | ||||
| 	pro_make.on_write = pro_on_write; | ||||
| 	pro_make.on_close = pro_on_close; | ||||
|  | ||||
| 	pro = qse_aio_dev_pro_make (aio, 0, &pro_make); | ||||
| 	if (!pro) | ||||
| 	{ | ||||
| 		printf ("CANNOT CREATE PROCESS PIPE\n"); | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| 	qse_aio_dev_pro_write (pro, "MY AIO LIBRARY\n", 16, QSE_NULL); | ||||
| //qse_aio_dev_pro_killchild (pro);  | ||||
| //qse_aio_dev_pro_close (pro, QSE_AIO_DEV_PRO_IN);  | ||||
| //qse_aio_dev_pro_close (pro, QSE_AIO_DEV_PRO_OUT);  | ||||
| //qse_aio_dev_pro_close (pro, QSE_AIO_DEV_PRO_ERR);  | ||||
| } | ||||
|  | ||||
| 	qse_aio_loop (aio); | ||||
|  | ||||
| 	g_aio = QSE_NULL; | ||||
| 	qse_aio_close (aio); | ||||
| #if defined(USE_SSL) | ||||
| 	cleanup_openssl (); | ||||
| #endif | ||||
|  | ||||
| 	return 0; | ||||
|  | ||||
| oops: | ||||
| 	g_aio = QSE_NULL; | ||||
| 	qse_aio_close (aio); | ||||
| #if defined(USE_SSL) | ||||
| 	cleanup_openssl (); | ||||
| #endif | ||||
| 	return -1; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user