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 | pkgincludedir = $(includedir)/qse/si | ||||||
|  |  | ||||||
| pkginclude_HEADERS = \ | pkginclude_HEADERS = \ | ||||||
| 	aio.h \ |  | ||||||
| 	aio-pro.h \ |  | ||||||
| 	aio-sck.h \ |  | ||||||
| 	cnd.h \ | 	cnd.h \ | ||||||
| 	dir.h \ | 	dir.h \ | ||||||
| 	fio.h  \ | 	fio.h  \ | ||||||
|  | |||||||
| @ -133,12 +133,11 @@ am__can_run_installinfo = \ | |||||||
|     n|no|NO) false;; \ |     n|no|NO) false;; \ | ||||||
|     *) (install-info --version) >/dev/null 2>&1;; \ |     *) (install-info --version) >/dev/null 2>&1;; \ | ||||||
|   esac |   esac | ||||||
| am__pkginclude_HEADERS_DIST = aio.h aio-pro.h aio-sck.h cnd.h dir.h \ | am__pkginclude_HEADERS_DIST = cnd.h dir.h fio.h fs.h glob.h intr.h \ | ||||||
| 	fio.h fs.h glob.h intr.h log.h mtx.h mux.h netlink.h nwad.h \ | 	log.h mtx.h mux.h netlink.h nwad.h nwif.h nwio.h os.h pio.h \ | ||||||
| 	nwif.h nwio.h os.h pio.h rwl.h sck.h sinfo.h sio.h spl.h \ | 	rwl.h sck.h sinfo.h sio.h spl.h task.h thr.h tio.h App.hpp \ | ||||||
| 	task.h thr.h tio.h App.hpp Condition.hpp Mutex.hpp \ | 	Condition.hpp Mutex.hpp SocketAddress.hpp Socket.hpp \ | ||||||
| 	SocketAddress.hpp Socket.hpp SpinLock.hpp TcpServer.hpp \ | 	SpinLock.hpp TcpServer.hpp Thread.hpp | ||||||
| 	Thread.hpp |  | ||||||
| am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | ||||||
| am__vpath_adj = case $$p in \ | am__vpath_adj = case $$p in \ | ||||||
|     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ | ||||||
| @ -355,10 +354,9 @@ target_alias = @target_alias@ | |||||||
| top_build_prefix = @top_build_prefix@ | top_build_prefix = @top_build_prefix@ | ||||||
| top_builddir = @top_builddir@ | top_builddir = @top_builddir@ | ||||||
| top_srcdir = @top_srcdir@ | top_srcdir = @top_srcdir@ | ||||||
| pkginclude_HEADERS = aio.h aio-pro.h aio-sck.h cnd.h dir.h fio.h fs.h \ | pkginclude_HEADERS = cnd.h dir.h fio.h fs.h glob.h intr.h log.h mtx.h \ | ||||||
| 	glob.h intr.h log.h mtx.h mux.h netlink.h nwad.h nwif.h nwio.h \ | 	mux.h netlink.h nwad.h nwif.h nwio.h os.h pio.h rwl.h sck.h \ | ||||||
| 	os.h pio.h rwl.h sck.h sinfo.h sio.h spl.h task.h thr.h tio.h \ | 	sinfo.h sio.h spl.h task.h thr.h tio.h $(am__append_1) | ||||||
| 	$(am__append_1) |  | ||||||
| all: all-am | all: all-am | ||||||
|  |  | ||||||
| .SUFFIXES: | .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 | 	-I$(top_srcdir)/include | ||||||
|  |  | ||||||
| noinst_HEADERS = \ | noinst_HEADERS = \ | ||||||
| 	aio-prv.h \ |  | ||||||
| 	fs-prv.h \ | 	fs-prv.h \ | ||||||
| 	glob-imp.h | 	glob-imp.h | ||||||
|  |  | ||||||
| lib_LTLIBRARIES = libqsesi.la | lib_LTLIBRARIES = libqsesi.la | ||||||
| libqsesi_la_SOURCES =  \ | libqsesi_la_SOURCES =  \ | ||||||
| 	aio.c \ |  | ||||||
| 	aio-pro.c  \ |  | ||||||
| 	aio-sck.c  \ |  | ||||||
| 	aio-tmr.c  \ |  | ||||||
| 	cnd.c \ | 	cnd.c \ | ||||||
| 	dir.c \ | 	dir.c \ | ||||||
| 	fio.c  \ | 	fio.c  \ | ||||||
|  | |||||||
| @ -138,10 +138,8 @@ am__installdirs = "$(DESTDIR)$(libdir)" | |||||||
| LTLIBRARIES = $(lib_LTLIBRARIES) | LTLIBRARIES = $(lib_LTLIBRARIES) | ||||||
| am__DEPENDENCIES_1 = | am__DEPENDENCIES_1 = | ||||||
| libqsesi_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(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 \ | am_libqsesi_la_OBJECTS = libqsesi_la-cnd.lo libqsesi_la-dir.lo \ | ||||||
| 	libqsesi_la-aio-sck.lo libqsesi_la-aio-tmr.lo \ | 	libqsesi_la-fio.lo libqsesi_la-fs.lo libqsesi_la-fs-attr.lo \ | ||||||
| 	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-copy.lo libqsesi_la-fs-delete.lo \ | ||||||
| 	libqsesi_la-fs-err.lo libqsesi_la-fs-make.lo \ | 	libqsesi_la-fs-err.lo libqsesi_la-fs-make.lo \ | ||||||
| 	libqsesi_la-fs-move.lo libqsesi_la-glob.lo libqsesi_la-intr.lo \ | 	libqsesi_la-fs-move.lo libqsesi_la-glob.lo libqsesi_la-intr.lo \ | ||||||
| @ -424,16 +422,11 @@ AM_CPPFLAGS = \ | |||||||
| 	-I$(top_srcdir)/include | 	-I$(top_srcdir)/include | ||||||
|  |  | ||||||
| noinst_HEADERS = \ | noinst_HEADERS = \ | ||||||
| 	aio-prv.h \ |  | ||||||
| 	fs-prv.h \ | 	fs-prv.h \ | ||||||
| 	glob-imp.h | 	glob-imp.h | ||||||
|  |  | ||||||
| lib_LTLIBRARIES = libqsesi.la $(am__append_1) | lib_LTLIBRARIES = libqsesi.la $(am__append_1) | ||||||
| libqsesi_la_SOURCES = \ | libqsesi_la_SOURCES = \ | ||||||
| 	aio.c \ |  | ||||||
| 	aio-pro.c  \ |  | ||||||
| 	aio-sck.c  \ |  | ||||||
| 	aio-tmr.c  \ |  | ||||||
| 	cnd.c \ | 	cnd.c \ | ||||||
| 	dir.c \ | 	dir.c \ | ||||||
| 	fio.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)/SocketAddress.Plo@am__quote@ | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TcpServer.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)/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-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-dir.Plo@am__quote@ | ||||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-fio.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@ | @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ | ||||||
| @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< | @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 | 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_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 | @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) | 	-I$(includedir) | ||||||
|  |  | ||||||
| bin_PROGRAMS = \ | bin_PROGRAMS = \ | ||||||
| 	aio01 \ |  | ||||||
| 	dir01 \ | 	dir01 \ | ||||||
| 	fio01 \ | 	fio01 \ | ||||||
| 	fio02 \ | 	fio02 \ | ||||||
| @ -38,7 +37,6 @@ LDADD += $(UNICOWS_LIBS) | |||||||
| endif | endif | ||||||
| endif | endif | ||||||
|  |  | ||||||
| aio01_SOURCES = aio01.c |  | ||||||
| dir01_SOURCES = dir01.c | dir01_SOURCES = dir01.c | ||||||
| fio01_SOURCES = fio01.c | fio01_SOURCES = fio01.c | ||||||
| fio02_SOURCES = fio02.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