removed all aio* files. all relevant functions are available in a different project, mio
This commit is contained in:
parent
b2d3050d8b
commit
f850f459c4
@ -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;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user