removed all aio* files. all relevant functions are available in a different project, mio

This commit is contained in:
hyung-hwan 2019-01-23 08:58:47 +00:00
parent b2d3050d8b
commit f850f459c4
14 changed files with 10 additions and 6355 deletions

View File

@ -1,9 +1,6 @@
pkgincludedir = $(includedir)/qse/si
pkginclude_HEADERS = \
aio.h \
aio-pro.h \
aio-sck.h \
cnd.h \
dir.h \
fio.h \

View File

@ -133,12 +133,11 @@ am__can_run_installinfo = \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__pkginclude_HEADERS_DIST = aio.h aio-pro.h aio-sck.h cnd.h dir.h \
fio.h fs.h glob.h intr.h log.h mtx.h mux.h netlink.h nwad.h \
nwif.h nwio.h os.h pio.h rwl.h sck.h sinfo.h sio.h spl.h \
task.h thr.h tio.h App.hpp Condition.hpp Mutex.hpp \
SocketAddress.hpp Socket.hpp SpinLock.hpp TcpServer.hpp \
Thread.hpp
am__pkginclude_HEADERS_DIST = cnd.h dir.h fio.h fs.h glob.h intr.h \
log.h mtx.h mux.h netlink.h nwad.h nwif.h nwio.h os.h pio.h \
rwl.h sck.h sinfo.h sio.h spl.h task.h thr.h tio.h App.hpp \
Condition.hpp Mutex.hpp SocketAddress.hpp Socket.hpp \
SpinLock.hpp TcpServer.hpp Thread.hpp
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@ -355,10 +354,9 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
pkginclude_HEADERS = aio.h aio-pro.h aio-sck.h cnd.h dir.h fio.h fs.h \
glob.h intr.h log.h mtx.h mux.h netlink.h nwad.h nwif.h nwio.h \
os.h pio.h rwl.h sck.h sinfo.h sio.h spl.h task.h thr.h tio.h \
$(am__append_1)
pkginclude_HEADERS = cnd.h dir.h fio.h fs.h glob.h intr.h log.h mtx.h \
mux.h netlink.h nwad.h nwif.h nwio.h os.h pio.h rwl.h sck.h \
sinfo.h sio.h spl.h task.h thr.h tio.h $(am__append_1)
all: all-am
.SUFFIXES:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -5,16 +5,11 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/include
noinst_HEADERS = \
aio-prv.h \
fs-prv.h \
glob-imp.h
lib_LTLIBRARIES = libqsesi.la
libqsesi_la_SOURCES = \
aio.c \
aio-pro.c \
aio-sck.c \
aio-tmr.c \
cnd.c \
dir.c \
fio.c \

View File

@ -138,10 +138,8 @@ am__installdirs = "$(DESTDIR)$(libdir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
am__DEPENDENCIES_1 =
libqsesi_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
am_libqsesi_la_OBJECTS = libqsesi_la-aio.lo libqsesi_la-aio-pro.lo \
libqsesi_la-aio-sck.lo libqsesi_la-aio-tmr.lo \
libqsesi_la-cnd.lo libqsesi_la-dir.lo libqsesi_la-fio.lo \
libqsesi_la-fs.lo libqsesi_la-fs-attr.lo \
am_libqsesi_la_OBJECTS = libqsesi_la-cnd.lo libqsesi_la-dir.lo \
libqsesi_la-fio.lo libqsesi_la-fs.lo libqsesi_la-fs-attr.lo \
libqsesi_la-fs-copy.lo libqsesi_la-fs-delete.lo \
libqsesi_la-fs-err.lo libqsesi_la-fs-make.lo \
libqsesi_la-fs-move.lo libqsesi_la-glob.lo libqsesi_la-intr.lo \
@ -424,16 +422,11 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/include
noinst_HEADERS = \
aio-prv.h \
fs-prv.h \
glob-imp.h
lib_LTLIBRARIES = libqsesi.la $(am__append_1)
libqsesi_la_SOURCES = \
aio.c \
aio-pro.c \
aio-sck.c \
aio-tmr.c \
cnd.c \
dir.c \
fio.c \
@ -564,10 +557,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketAddress.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TcpServer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Thread.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-pro.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-sck.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-tmr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-cnd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-dir.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-fio.Plo@am__quote@
@ -620,34 +609,6 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
libqsesi_la-aio.lo: aio.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-aio.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-aio.Tpo -c -o libqsesi_la-aio.lo `test -f 'aio.c' || echo '$(srcdir)/'`aio.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-aio.Tpo $(DEPDIR)/libqsesi_la-aio.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='aio.c' object='libqsesi_la-aio.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-aio.lo `test -f 'aio.c' || echo '$(srcdir)/'`aio.c
libqsesi_la-aio-pro.lo: aio-pro.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-aio-pro.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-aio-pro.Tpo -c -o libqsesi_la-aio-pro.lo `test -f 'aio-pro.c' || echo '$(srcdir)/'`aio-pro.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-aio-pro.Tpo $(DEPDIR)/libqsesi_la-aio-pro.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='aio-pro.c' object='libqsesi_la-aio-pro.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-aio-pro.lo `test -f 'aio-pro.c' || echo '$(srcdir)/'`aio-pro.c
libqsesi_la-aio-sck.lo: aio-sck.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-aio-sck.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-aio-sck.Tpo -c -o libqsesi_la-aio-sck.lo `test -f 'aio-sck.c' || echo '$(srcdir)/'`aio-sck.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-aio-sck.Tpo $(DEPDIR)/libqsesi_la-aio-sck.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='aio-sck.c' object='libqsesi_la-aio-sck.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-aio-sck.lo `test -f 'aio-sck.c' || echo '$(srcdir)/'`aio-sck.c
libqsesi_la-aio-tmr.lo: aio-tmr.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-aio-tmr.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-aio-tmr.Tpo -c -o libqsesi_la-aio-tmr.lo `test -f 'aio-tmr.c' || echo '$(srcdir)/'`aio-tmr.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-aio-tmr.Tpo $(DEPDIR)/libqsesi_la-aio-tmr.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='aio-tmr.c' object='libqsesi_la-aio-tmr.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-aio-tmr.lo `test -f 'aio-tmr.c' || echo '$(srcdir)/'`aio-tmr.c
libqsesi_la-cnd.lo: cnd.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-cnd.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-cnd.Tpo -c -o libqsesi_la-cnd.lo `test -f 'cnd.c' || echo '$(srcdir)/'`cnd.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-cnd.Tpo $(DEPDIR)/libqsesi_la-cnd.Plo

View File

@ -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, &param) <= -1) goto oops;
/* TODO: more advanced fork and exec .. */
pid = standard_fork_and_exec (rdev->aio, pfds, info->flags, &param);
if (pid <= -1)
{
free_param (rdev->aio, &param);
goto oops;
}
free_param (rdev->aio, &param);
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, &param);
}
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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,6 @@ AM_CPPFLAGS = \
-I$(includedir)
bin_PROGRAMS = \
aio01 \
dir01 \
fio01 \
fio02 \
@ -38,7 +37,6 @@ LDADD += $(UNICOWS_LIBS)
endif
endif
aio01_SOURCES = aio01.c
dir01_SOURCES = dir01.c
fio01_SOURCES = fio01.c
fio02_SOURCES = fio02.c

View File

@ -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 (&ethdst, if_nametoindex("enp0s25.3"), (qse_aio_ethaddr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF");
qse_aio_sckaddr_initforeth (&ethdst, if_nametoindex("enp0s25.3"), (qse_aio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF");
memset (&etharp, 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, &etharp, sizeof(etharp), NULL, &ethdst) <= -1)
//if (qse_aio_dev_sck_write (sck, &etharp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, &ethaddr) <= -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;
}