added SSL to the listening socket

This commit is contained in:
hyung-hwan 2016-04-18 14:21:23 +00:00
parent 3ca7bcd549
commit ec4bd54e53
12 changed files with 1230 additions and 898 deletions

View File

@ -33,7 +33,8 @@ libstio_la_SOURCES = \
stio-pro.c \
stio-sck.c \
stio-tim.c \
stio-tmr.c
stio-tmr.c \
stio-utl.c
libstio_la_CPPFLAGS = $(CPPFLAGS_LIB_COMMON)
libstio_la_LDFLAGS = $(LDFLAGS_LIB_COMMON)
libstio_la_LIBADD = $(LIBADD_LIB_COMMON) $(SSL_LIBS)

View File

@ -105,7 +105,7 @@ am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
libstio_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
am_libstio_la_OBJECTS = libstio_la-stio.lo libstio_la-stio-pro.lo \
libstio_la-stio-sck.lo libstio_la-stio-tim.lo \
libstio_la-stio-tmr.lo
libstio_la-stio-tmr.lo libstio_la-stio-utl.lo
libstio_la_OBJECTS = $(am_libstio_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -338,7 +338,8 @@ libstio_la_SOURCES = \
stio-pro.c \
stio-sck.c \
stio-tim.c \
stio-tmr.c
stio-tmr.c \
stio-utl.c
libstio_la_CPPFLAGS = $(CPPFLAGS_LIB_COMMON)
libstio_la_LDFLAGS = $(LDFLAGS_LIB_COMMON)
@ -491,6 +492,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libstio_la-stio-sck.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libstio_la-stio-tim.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libstio_la-stio-tmr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libstio_la-stio-utl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libstio_la-stio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stio-main.Po@am__quote@
@ -550,6 +552,13 @@ libstio_la-stio-tmr.lo: stio-tmr.c
@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) $(libstio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libstio_la-stio-tmr.lo `test -f 'stio-tmr.c' || echo '$(srcdir)/'`stio-tmr.c
libstio_la-stio-utl.lo: stio-utl.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libstio_la-stio-utl.lo -MD -MP -MF $(DEPDIR)/libstio_la-stio-utl.Tpo -c -o libstio_la-stio-utl.lo `test -f 'stio-utl.c' || echo '$(srcdir)/'`stio-utl.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libstio_la-stio-utl.Tpo $(DEPDIR)/libstio_la-stio-utl.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stio-utl.c' object='libstio_la-stio-utl.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) $(libstio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libstio_la-stio-utl.lo `test -f 'stio-utl.c' || echo '$(srcdir)/'`stio-utl.c
stio-main.o: main.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stio_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stio-main.o -MD -MP -MF $(DEPDIR)/stio-main.Tpo -c -o stio-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stio-main.Tpo $(DEPDIR)/stio-main.Po

View File

@ -145,19 +145,34 @@ static void tcp_sck_on_disconnect (stio_dev_sck_t* tcp)
static int tcp_sck_on_connect (stio_dev_sck_t* tcp)
{
stio_sckfam_t fam;
stio_scklen_t len;
stio_mchar_t buf1[128], buf2[128];
memset (buf1, 0, STIO_SIZEOF(buf1));
memset (buf2, 0, STIO_SIZEOF(buf2));
stio_getsckaddrinfo (tcp->stio, &tcp->localaddr, &len, &fam);
inet_ntop (fam, tcp->localaddr.data, buf1, STIO_COUNTOF(buf1));
stio_getsckaddrinfo (tcp->stio, &tcp->remoteaddr, &len, &fam);
inet_ntop (fam, tcp->remoteaddr.data, buf2, STIO_COUNTOF(buf2));
if (tcp->state & STIO_DEV_SCK_CONNECTED)
{
printf ("device connected to a remote server... .asdfjkasdfkljasdlfkjasdj...\n");
printf ("device connected to a remote server... LOCAL %s:%d REMOTE %s:%d.", buf1, stio_getsckaddrport(&tcp->localaddr), buf2, stio_getsckaddrport(&tcp->remoteaddr));
}
else if (tcp->state & STIO_DEV_SCK_ACCEPTED)
{
printf ("device accepted client device... .asdfjkasdfkljasdlfkjasdj...\n");
printf ("device accepted client device... .LOCAL %s:%d REMOTE %s:%d\n", buf1, stio_getsckaddrport(&tcp->localaddr), buf2, stio_getsckaddrport(&tcp->remoteaddr));
}
return stio_dev_sck_write (tcp, "hello", 5, STIO_NULL, STIO_NULL);
}
static int tcp_sck_on_write (stio_dev_sck_t* tcp, stio_iolen_t wrlen, void* wrctx, const stio_sckadr_t* dstadr)
static int tcp_sck_on_write (stio_dev_sck_t* tcp, stio_iolen_t wrlen, void* wrctx, const stio_sckaddr_t* dstaddr)
{
tcp_server_t* ts;
@ -180,7 +195,7 @@ printf ("ENABLING READING..............................\n");
return 0;
}
static int tcp_sck_on_read (stio_dev_sck_t* tcp, const void* buf, stio_iolen_t len, const stio_sckadr_t* srcadr)
static int tcp_sck_on_read (stio_dev_sck_t* tcp, const void* buf, stio_iolen_t len, const stio_sckaddr_t* srcaddr)
{
if (len <= 0)
{
@ -217,10 +232,10 @@ printf ("DISABLING READING..............................\n");
/* ========================================================================= */
static int arp_sck_on_read (stio_dev_sck_t* dev, const void* data, stio_iolen_t dlen, const stio_sckadr_t* srcadr)
static int arp_sck_on_read (stio_dev_sck_t* dev, const void* data, stio_iolen_t dlen, const stio_sckaddr_t* srcaddr)
{
stio_etharp_pkt_t* eap;
struct sockaddr_ll* sll = (struct sockaddr_ll*)srcadr;
struct sockaddr_ll* sll = (struct sockaddr_ll*)srcaddr;
if (dlen < STIO_SIZEOF(*eap)) return 0; /* drop */
@ -234,7 +249,7 @@ static int arp_sck_on_read (stio_dev_sck_t* dev, const void* data, stio_iolen_t
return 0;
}
static int arp_sck_on_write (stio_dev_sck_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_sckadr_t* dstadr)
static int arp_sck_on_write (stio_dev_sck_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_sckaddr_t* dstaddr)
{
return 0;
}
@ -344,7 +359,7 @@ int main ()
memset (&tcp_conn, 0, STIO_SIZEOF(tcp_conn));
{
in_addr_t ia = inet_addr("192.168.1.119");
stio_sckadr_initforip4 (&tcp_conn.addr, 9999, (stio_ip4adr_t*)&ia);
stio_sckaddr_initforip4 (&tcp_conn.remoteaddr, 9999, (stio_ip4addr_t*)&ia);
}
tcp_conn.tmout.sec = 5;
tcp_conn.on_connect = tcp_sck_on_connect;
@ -372,7 +387,7 @@ int main ()
ts->tally = 0;
memset (&tcp_bind, 0, STIO_SIZEOF(tcp_bind));
stio_sckadr_initforip4 (&tcp_bind.addr, 1234, STIO_NULL);
stio_sckaddr_initforip4 (&tcp_bind.localaddr, 1234, STIO_NULL);
tcp_bind.options = STIO_DEV_SCK_BIND_REUSEADDR;
if (stio_dev_sck_bind (tcp[1],&tcp_bind) <= -1)
@ -408,32 +423,31 @@ int main ()
ts->tally = 0;
memset (&tcp_bind, 0, STIO_SIZEOF(tcp_bind));
stio_sckadr_initforip4 (&tcp_bind.addr, 1235, STIO_NULL);
tcp_bind.options = STIO_DEV_SCK_BIND_REUSEADDR | STIO_DEV_SCK_BIND_SECURE;
tcp_bind.certfile = STIO_MT("stio.certfile");
tcp_bind.keyfile = STIO_MT("stio.keyfile");
stio_sckaddr_initforip4 (&tcp_bind.localaddr, 1235, STIO_NULL);
tcp_bind.options = STIO_DEV_SCK_BIND_REUSEADDR | /*STIO_DEV_SCK_BIND_REUSEPORT |*/ STIO_DEV_SCK_BIND_SSL;
tcp_bind.certfile = STIO_MT("localhost.crt");
tcp_bind.keyfile = STIO_MT("localhost.key");
if (stio_dev_sck_bind (tcp[1],&tcp_bind) <= -1)
if (stio_dev_sck_bind (tcp[2],&tcp_bind) <= -1)
{
printf ("stio_dev_sck_bind() failed....\n");
goto oops;
}
tcp_lstn.backlogs = 100;
tcp_lstn.on_connect = tcp_sck_on_connect;
tcp_lstn.on_disconnect = tcp_sck_on_disconnect;
if (stio_dev_sck_listen (tcp[1], &tcp_lstn) <= -1)
if (stio_dev_sck_listen (tcp[2], &tcp_lstn) <= -1)
{
printf ("stio_dev_sck_listen() failed....\n");
goto oops;
}
//stio_dev_sck_sendfile (tcp[2], fd, offset, count);
#if 1
{
stio_sckadr_t ethdst;
stio_sckaddr_t ethdst;
stio_etharp_pkt_t etharp;
memset (&sck_make, 0, STIO_SIZEOF(sck_make));
@ -448,26 +462,26 @@ int main ()
goto oops;
}
//stio_sckadr_initforeth (&ethdst, if_nametoindex("enp0s25.3"), (stio_ethadr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF");
stio_sckadr_initforeth (&ethdst, if_nametoindex("enp0s25.3"), (stio_ethadr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF");
//stio_sckaddr_initforeth (&ethdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF");
stio_sckaddr_initforeth (&ethdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF");
memset (&etharp, 0, sizeof(etharp));
memcpy (etharp.ethhdr.source, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADR_LEN);
//memcpy (etharp.ethhdr.dest, "\xFF\xFF\xFF\xFF\xFF\xFF", STIO_ETHADR_LEN);
memcpy (etharp.ethhdr.dest, "\xAA\xBB\xFF\xCC\xDD\xFF", STIO_ETHADR_LEN);
memcpy (etharp.ethhdr.source, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADDR_LEN);
//memcpy (etharp.ethhdr.dest, "\xFF\xFF\xFF\xFF\xFF\xFF", STIO_ETHADDR_LEN);
memcpy (etharp.ethhdr.dest, "\xAA\xBB\xFF\xCC\xDD\xFF", STIO_ETHADDR_LEN);
etharp.ethhdr.proto = STIO_CONST_HTON16(STIO_ETHHDR_PROTO_ARP);
etharp.arphdr.htype = STIO_CONST_HTON16(STIO_ARPHDR_HTYPE_ETH);
etharp.arphdr.ptype = STIO_CONST_HTON16(STIO_ARPHDR_PTYPE_IP4);
etharp.arphdr.hlen = STIO_ETHADR_LEN;
etharp.arphdr.plen = STIO_IP4ADR_LEN;
etharp.arphdr.hlen = STIO_ETHADDR_LEN;
etharp.arphdr.plen = STIO_IP4ADDR_LEN;
etharp.arphdr.opcode = STIO_CONST_HTON16(STIO_ARPHDR_OPCODE_REQUEST);
memcpy (etharp.arppld.sha, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADR_LEN);
memcpy (etharp.arppld.sha, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADDR_LEN);
if (stio_dev_sck_write (sck, &etharp, sizeof(etharp), NULL, &ethdst) <= -1)
//if (stio_dev_sck_write (sck, &etharp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, &ethadr) <= -1)
//if (stio_dev_sck_write (sck, &etharp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, &ethaddr) <= -1)
{
printf ("CANNOT WRITE ARP...\n");
}

View File

@ -1,192 +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 "stio-arp.h"
#include "stio-prv.h"
#include <sys/socket.h>
#include <netinet/if_ether.h>
#include <netpacket/packet.h>
#include <arpa/inet.h>
#include <errno.h>
#if 0
/* ======================================================================== */
static int arp_make (stio_dev_t* dev, void* ctx)
{
stio_dev_arp_t* arp = (stio_dev_arp_t*)dev;
stio_dev_arp_make_t* arg = (stio_dev_arp_make_t*)ctx;
arp->sck = stio_openasyncsck (dev->stio, PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
if (arp->sck == STIO_SCKHND_INVALID) goto oops;
arp->on_write = arg->on_write;
arp->on_read = arg->on_read;
return 0;
oops:
if (arp->sck != STIO_SCKHND_INVALID)
{
stio_closeasyncsck (arp->stio, arp->sck);
arp->sck = STIO_SCKHND_INVALID;
}
return -1;
}
static void arp_kill (stio_dev_t* dev)
{
stio_dev_arp_t* arp = (stio_dev_arp_t*)dev;
if (arp->sck != STIO_SCKHND_INVALID)
{
stio_closeasyncsck (arp->stio, arp->sck);
arp->sck = STIO_SCKHND_INVALID;
}
}
static stio_syshnd_t arp_getsyshnd (stio_dev_t* dev)
{
stio_dev_arp_t* arp = (stio_dev_arp_t*)dev;
return (stio_syshnd_t)arp->sck;
}
static int arp_read (stio_dev_t* dev, void* buf, stio_iolen_t* len)
{
stio_dev_arp_t* arp = (stio_dev_arp_t*)dev;
stio_scklen_t addrlen;
int x;
struct sockaddr_ll from;
/* TODO: arp_read need source address ... have to extend the send callback to accept the source address */
printf ("ARP RECVFROM...\n");
addrlen = STIO_SIZEOF(from);
x = recvfrom (arp->sck, buf, *len, 0, (struct sockaddr*)&from, &addrlen);
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0; /* no data available */
if (errno == EINTR) return 0;
arp->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
*len = x;
return 1;
}
static int arp_write (stio_dev_t* dev, const void* data, stio_iolen_t* len)
{
stio_dev_arp_t* arp = (stio_dev_arp_t*)arp;
ssize_t x;
#if 0
/* TODO: arp_write need target address ... have to extend the send callback to accept the target address */
x = sendto (arp->sck, data, *len, skad, stio_getskadlen(skad));
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0; /* no data can be written */
if (errno == EINTR) return 0;
arp->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
/* for UDP, if the data chunk can't be written at one go, it's actually a failure */
if (x != *len) return -1; /* TODO: can i hava an indicator for this in stio? */
*len = x;
#endif
return 1;
}
static int arp_ioctl (stio_dev_t* dev, int cmd, void* arg)
{
return 0;
}
static stio_dev_mth_t arp_mth =
{
arp_make,
arp_kill,
arp_getsyshnd,
arp_read,
arp_write,
arp_ioctl, /* ioctl */
};
/* ======================================================================== */
static int arp_ready (stio_dev_t* dev, int events)
{
/* TODO: ... */
if (events & STIO_DEV_EVENT_ERR) printf ("UDP READY ERROR.....\n");
if (events & STIO_DEV_EVENT_HUP) printf ("UDP READY HANGUP.....\n");
if (events & STIO_DEV_EVENT_PRI) printf ("UDP READY PRI.....\n");
if (events & STIO_DEV_EVENT_IN) printf ("UDP READY IN.....\n");
if (events & STIO_DEV_EVENT_OUT) printf ("UDP READY OUT.....\n");
return 0;
}
static int arp_on_read (stio_dev_t* dev, const void* data, stio_iolen_t len)
{
printf ("dATA received %d bytes\n", (int)len);
return 0;
}
static int arp_on_write (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx)
{
return 0;
}
static stio_dev_evcb_t arp_evcb =
{
arp_ready,
arp_on_read,
arp_on_write
};
/* ======================================================================== */
stio_dev_arp_t* stio_dev_arp_make (stio_t* stio, stio_size_t xtnsize, const stio_dev_arp_make_t* data)
{
return (stio_dev_arp_t*)stio_makedev (stio, STIO_SIZEOF(stio_dev_arp_t) + xtnsize, &arp_mth, &arp_evcb, (void*)data);
}
int stio_dev_arp_write (stio_dev_arp_t* dev, const stio_pkt_arp_t* arp, void* wrctx)
{
return stio_dev_write ((stio_dev_t*)dev, arp, STIO_SIZEOF(*arp), wrctx);
}
int stio_dev_arp_timedwrite (stio_dev_arp_t* dev, const stio_pkt_arp_t* arp, const stio_ntime_t* tmout, void* wrctx)
{
return stio_dev_write ((stio_dev_t*)dev, arp, STIO_SIZEOF(*arp), wrctx);
}
#endif

View File

@ -1,84 +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.
*/
#ifndef _STIO_ARP_H_
#define _STIO_ARP_H_
#include <stio.h>
#include <stio-sck.h>
#if 0
typedef int (*stio_dev_arp_on_read_t) (stio_dev_arp_t* dev, stio_pkt_arp_t* pkt, stio_iolen_t len);
typedef int (*stio_dev_arp_on_write_t) (stio_dev_arp_t* dev, void* wrctx);
typedef struct stio_dev_arp_make_t stio_dev_arp_make_t;
struct stio_dev_arp_make_t
{
stio_dev_arp_on_write_t on_write;
stio_dev_arp_on_read_t on_read;
};
struct stio_dev_arp_t
{
STIO_DEV_HEADERS;
stio_sckhnd_t sck;
stio_dev_arp_on_write_t on_write;
stio_dev_arp_on_read_t on_read;
};
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if 0
STIO_EXPORT stio_dev_arp_t* stio_dev_arp_make (
stio_t* stio,
stio_size_t xtnsize,
const stio_dev_arp_make_t* data
);
STIO_EXPORT int stio_dev_arp_write (
stio_dev_arp_t* dev,
const stio_pkt_arp_t* arp,
void* wrctx
);
STIO_EXPORT int stio_dev_arp_timedwrite (
stio_dev_arp_t* dev,
const stio_pkt_arp_t* arp,
const stio_ntime_t* tmout,
void* wrctx
);
#endif
#ifdef __cplusplus
extern "C" {
#endif
#endif

View File

@ -540,7 +540,7 @@ static int dev_pro_kill_slave (stio_dev_t* dev, int force)
return 0;
}
static int dev_pro_read_slave (stio_dev_t* dev, void* buf, stio_iolen_t* len, stio_devadr_t* srcadr)
static int dev_pro_read_slave (stio_dev_t* dev, void* buf, stio_iolen_t* len, stio_devaddr_t* srcaddr)
{
stio_dev_pro_slave_t* pro = (stio_dev_pro_slave_t*)dev;
ssize_t x;
@ -548,7 +548,7 @@ static int dev_pro_read_slave (stio_dev_t* dev, void* buf, stio_iolen_t* len, st
x = read (pro->pfd, buf, *len);
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0; /* no data available */
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data available */
if (errno == EINTR) return 0;
pro->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
@ -558,7 +558,7 @@ static int dev_pro_read_slave (stio_dev_t* dev, void* buf, stio_iolen_t* len, st
return 1;
}
static int dev_pro_write_slave (stio_dev_t* dev, const void* data, stio_iolen_t* len, const stio_devadr_t* dstadr)
static int dev_pro_write_slave (stio_dev_t* dev, const void* data, stio_iolen_t* len, const stio_devaddr_t* dstaddr)
{
stio_dev_pro_slave_t* pro = (stio_dev_pro_slave_t*)dev;
ssize_t x;
@ -566,7 +566,7 @@ static int dev_pro_write_slave (stio_dev_t* dev, const void* data, stio_iolen_t*
x = write (pro->pfd, data, *len);
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0; /* no data can be written */
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
if (errno == EINTR) return 0;
pro->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
@ -662,14 +662,14 @@ static int pro_ready (stio_dev_t* dev, int events)
return -1;
}
static int pro_on_read (stio_dev_t* dev, const void* data, stio_iolen_t len, const stio_devadr_t* srcadr)
static int pro_on_read (stio_dev_t* dev, const void* data, stio_iolen_t len, const stio_devaddr_t* srcaddr)
{
/* virtual device. no I/O */
dev->stio->errnum = STIO_EINTERN;
return -1;
}
static int pro_on_write (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_devadr_t* dstadr)
static int pro_on_write (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_devaddr_t* dstaddr)
{
/* virtual device. no I/O */
dev->stio->errnum = STIO_EINTERN;
@ -711,19 +711,19 @@ static int pro_ready_slave (stio_dev_t* dev, int events)
}
static int pro_on_read_slave_out (stio_dev_t* dev, const void* data, stio_iolen_t len, const stio_devadr_t* srcadr)
static int pro_on_read_slave_out (stio_dev_t* dev, const void* data, stio_iolen_t len, const stio_devaddr_t* srcaddr)
{
stio_dev_pro_slave_t* pro = (stio_dev_pro_slave_t*)dev;
return pro->master->on_read (pro->master, data, len, STIO_DEV_PRO_OUT);
}
static int pro_on_read_slave_err (stio_dev_t* dev, const void* data, stio_iolen_t len, const stio_devadr_t* srcadr)
static int pro_on_read_slave_err (stio_dev_t* dev, const void* data, stio_iolen_t len, const stio_devaddr_t* srcaddr)
{
stio_dev_pro_slave_t* pro = (stio_dev_pro_slave_t*)dev;
return pro->master->on_read (pro->master, data, len, STIO_DEV_PRO_ERR);
}
static int pro_on_write_slave (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_devadr_t* dstadr)
static int pro_on_write_slave (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_devaddr_t* dstaddr)
{
stio_dev_pro_slave_t* pro = (stio_dev_pro_slave_t*)dev;
return pro->master->on_write (pro->master, wrlen, wrctx);

View File

@ -39,6 +39,7 @@
#define STIO_MEMSET(dst,byte,count) memset(dst,byte,count)
#define STIO_MEMCPY(dst,src,count) memcpy(dst,src,count)
#define STIO_MEMMOVE(dst,src,count) memmove(dst,src,count)
#define STIO_MEMCMP(dst,src,count) memcmp(dst,src,count)
#define STIO_ASSERT assert

View File

@ -37,6 +37,22 @@
#include <arpa/inet.h>
#include <netpacket/packet.h>
#if defined(__linux__)
# include <limits.h>
# if defined(HAVE_LINUX_NETFILTER_IPV4_H)
# include <linux/netfilter_ipv4.h> /* SO_ORIGINAL_DST */
# endif
# if !defined(SO_ORIGINAL_DST)
# define SO_ORIGINAL_DST 80
# endif
# if !defined(IP_TRANSPARENT)
# define IP_TRANSPARENT 19
# endif
# if !defined(SO_REUSEPORT)
# define SO_REUSEPORT 15
# endif
#endif
#if defined(HAVE_OPENSSL_SSL_H) && defined(HAVE_SSL)
# include <openssl/ssl.h>
# if defined(HAVE_OPENSSL_ERR_H)
@ -48,11 +64,6 @@
# define USE_SSL
#endif
#if defined(USE_SSL)
# define HANDLE_TO_SSL(x) ((SSL*)(x))
# define SSL_TO_HANDLE(x) ((qse_httpd_hnd_t)(x))
#endif
/* ========================================================================= */
void stio_closeasyncsck (stio_t* stio, stio_sckhnd_t sck)
{
@ -117,7 +128,7 @@ stio_sckhnd_t stio_openasyncsck (stio_t* stio, int domain, int type, int proto)
return sck;
}
int stio_getsckadrinfo (stio_t* stio, const stio_sckadr_t* addr, stio_scklen_t* len, stio_sckfam_t* family)
int stio_getsckaddrinfo (stio_t* stio, const stio_sckaddr_t* addr, stio_scklen_t* len, stio_sckfam_t* family)
{
struct sockaddr* saddr = (struct sockaddr*)addr;
@ -135,70 +146,99 @@ int stio_getsckadrinfo (stio_t* stio, const stio_sckadr_t* addr, stio_scklen_t*
case AF_PACKET:
if (len) *len = STIO_SIZEOF(struct sockaddr_ll);
if (family) *family = AF_INET6;
if (family) *family = AF_PACKET;
return 0;
/* TODO: more address type */
}
stio->errnum = STIO_EINVAL;
return -1;
}
stio_uint16_t stio_getsckaddrport (const stio_sckaddr_t* addr)
{
struct sockaddr* saddr = (struct sockaddr*)addr;
switch (saddr->sa_family)
{
case AF_INET:
return stio_ntoh16(((struct sockaddr_in*)addr)->sin_port);
case AF_INET6:
return stio_ntoh16(((struct sockaddr_in6*)addr)->sin6_port);
}
return 0;
}
int stio_equalsckaddrs (stio_t* stio, const stio_sckaddr_t* addr1, const stio_sckaddr_t* addr2)
{
stio_sckfam_t fam1, fam2;
stio_scklen_t len1, len2;
stio_getsckaddrinfo (stio, addr1, &len1, &fam1);
stio_getsckaddrinfo (stio, addr2, &len2, &fam2);
return fam1 == fam2 && len1 == len2 && STIO_MEMCMP (addr1, addr2, len1) == 0;
}
/* ========================================================================= */
void stio_sckadr_initforip4 (stio_sckadr_t* sckadr, stio_uint16_t port, stio_ip4adr_t* ip4adr)
void stio_sckaddr_initforip4 (stio_sckaddr_t* sckaddr, stio_uint16_t port, stio_ip4addr_t* ip4addr)
{
struct sockaddr_in* sin = (struct sockaddr_in*)sckadr;
struct sockaddr_in* sin = (struct sockaddr_in*)sckaddr;
STIO_MEMSET (sin, 0, STIO_SIZEOF(*sin));
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
if (ip4adr) STIO_MEMCPY (&sin->sin_addr, ip4adr, STIO_IP4ADR_LEN);
if (ip4addr) STIO_MEMCPY (&sin->sin_addr, ip4addr, STIO_IP4ADDR_LEN);
}
void stio_sckadr_initforip6 (stio_sckadr_t* sckadr, stio_uint16_t port, stio_ip6adr_t* ip6adr)
void stio_sckaddr_initforip6 (stio_sckaddr_t* sckaddr, stio_uint16_t port, stio_ip6addr_t* ip6addr)
{
struct sockaddr_in6* sin = (struct sockaddr_in6*)sckadr;
struct sockaddr_in6* sin = (struct sockaddr_in6*)sckaddr;
/* TODO: include sin6_scope_id */
STIO_MEMSET (sin, 0, STIO_SIZEOF(*sin));
sin->sin6_family = AF_INET;
sin->sin6_port = htons(port);
if (ip6adr) STIO_MEMCPY (&sin->sin6_addr, ip6adr, STIO_IP6ADR_LEN);
if (ip6addr) STIO_MEMCPY (&sin->sin6_addr, ip6addr, STIO_IP6ADDR_LEN);
}
void stio_sckadr_initforeth (stio_sckadr_t* sckadr, int ifindex, stio_ethadr_t* ethadr)
void stio_sckaddr_initforeth (stio_sckaddr_t* sckaddr, int ifindex, stio_ethaddr_t* ethaddr)
{
struct sockaddr_ll* sll = (struct sockaddr_ll*)sckadr;
struct sockaddr_ll* sll = (struct sockaddr_ll*)sckaddr;
STIO_MEMSET (sll, 0, STIO_SIZEOF(*sll));
sll->sll_family = AF_PACKET;
sll->sll_ifindex = ifindex;
if (ethadr)
if (ethaddr)
{
sll->sll_halen = STIO_ETHADR_LEN;
STIO_MEMCPY (sll->sll_addr, ethadr, STIO_ETHADR_LEN);
sll->sll_halen = STIO_ETHADDR_LEN;
STIO_MEMCPY (sll->sll_addr, ethaddr, STIO_ETHADDR_LEN);
}
}
/* ========================================================================= */
static stio_devadr_t* sckadr_to_devadr (stio_dev_sck_t* dev, const stio_sckadr_t* sckadr, stio_devadr_t* devadr)
static stio_devaddr_t* sckaddr_to_devaddr (stio_dev_sck_t* dev, const stio_sckaddr_t* sckaddr, stio_devaddr_t* devaddr)
{
if (sckadr)
if (sckaddr)
{
stio_scklen_t len;
stio_getsckadrinfo (dev->stio, sckadr, &len, STIO_NULL);
devadr->ptr = (void*)sckadr;
devadr->len = len;
return devadr;
stio_getsckaddrinfo (dev->stio, sckaddr, &len, STIO_NULL);
devaddr->ptr = (void*)sckaddr;
devaddr->len = len;
return devaddr;
}
return STIO_NULL;
}
static STIO_INLINE stio_sckadr_t* devadr_to_sckadr (stio_dev_sck_t* dev, const stio_devadr_t* devadr, stio_sckadr_t* sckadr)
static STIO_INLINE stio_sckaddr_t* devaddr_to_sckaddr (stio_dev_sck_t* dev, const stio_devaddr_t* devaddr, stio_sckaddr_t* sckaddr)
{
return (stio_sckadr_t*)devadr->ptr;
return (stio_sckaddr_t*)devaddr->ptr;
}
/* ========================================================================= */
@ -279,8 +319,22 @@ static int dev_sck_make_client (stio_dev_t* dev, void* ctx)
stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
stio_syshnd_t* sck = (stio_syshnd_t*)ctx;
/* nothing special is done here except setting the socket handle.
* most of the initialization is done by the listening socket device
* after a client socket has been created. */
rdev->sck = *sck;
if (stio_makesckasync (rdev->stio, rdev->sck) <= -1) return -1;
#if defined(FD_CLOEXEC)
{
int flags = fcntl (rdev->sck, F_GETFD, 0);
if (fcntl (rdev->sck, F_SETFD, flags | FD_CLOEXEC) == -1)
{
rdev->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
}
#endif
return 0;
}
@ -308,20 +362,26 @@ static int dev_sck_kill (stio_dev_t* dev, int force)
STIO_ASSERT (rdev->tmridx_connect == STIO_TMRIDX_INVALID);
}
#if defined(USE_SSL)
if (rdev->ssl)
{
SSL_shutdown ((SSL*)rdev->ssl); /* is this needed? */
SSL_free ((SSL*)rdev->ssl);
rdev->ssl = STIO_NULL;
}
if (!(rdev->state & (STIO_DEV_SCK_ACCEPTED | STIO_DEV_SCK_ACCEPTING_SSL)) && rdev->sslctx)
{
SSL_CTX_free ((SSL_CTX*)rdev->sslctx);
rdev->sslctx = STIO_NULL;
}
#endif
if (rdev->sck != STIO_SCKHND_INVALID)
{
stio_closeasyncsck (rdev->stio, rdev->sck);
rdev->sck = STIO_SCKHND_INVALID;
}
#if defined(USE_SSL)
if (rdev->secure_ctx)
{
SSL_CTX_free ((SSL_CTX*)rdev->secure_ctx);
rdev->secure_ctx = STIO_NULL;
}
#endif
return 0;
}
@ -331,93 +391,153 @@ static stio_syshnd_t dev_sck_getsyshnd (stio_dev_t* dev)
return (stio_syshnd_t)rdev->sck;
}
static int dev_sck_read_stateful (stio_dev_t* dev, void* buf, stio_iolen_t* len, stio_devadr_t* srcadr)
{
stio_dev_sck_t* tcp = (stio_dev_sck_t*)dev;
ssize_t x;
x = recv (tcp->sck, buf, *len, 0);
if (x == -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0; /* no data available */
if (errno == EINTR) return 0;
tcp->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
*len = x;
return 1;
}
static int dev_sck_read_stateless (stio_dev_t* dev, void* buf, stio_iolen_t* len, stio_devadr_t* srcadr)
static int dev_sck_read_stateful (stio_dev_t* dev, void* buf, stio_iolen_t* len, stio_devaddr_t* srcaddr)
{
stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
stio_scklen_t srcadrlen;
ssize_t x;
srcadrlen = STIO_SIZEOF(rdev->peeradr);
x = recvfrom (rdev->sck, buf, *len, 0, (struct sockaddr*)&rdev->peeradr, &srcadrlen);
if (x <= -1)
#if defined(USE_SSL)
if (rdev->ssl)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0; /* no data available */
if (errno == EINTR) return 0;
rdev->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
int x;
srcadr->ptr = &rdev->peeradr;
srcadr->len = srcadrlen;
*len = x;
return 1;
}
static int dev_sck_write_stateful (stio_dev_t* dev, const void* data, stio_iolen_t* len, const stio_devadr_t* dstadr)
{
stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
ssize_t x;
int flags = 0;
if (*len <= 0)
{
/* it's a writing finish indicator. close the writing end of
* the socket, probably leaving it in the half-closed state */
if (shutdown (rdev->sck, SHUT_WR) == -1)
x = SSL_read ((SSL*)rdev->ssl, buf, *len);
if (x <= -1)
{
int err = SSL_get_error ((SSL*)rdev->ssl, x);
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) return 0;
rdev->stio->errnum = STIO_ESYSERR;
return -1;
}
*len = x;
}
else
{
#endif
ssize_t x;
x = recv (rdev->sck, buf, *len, 0);
if (x == -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data available */
if (errno == EINTR) return 0;
rdev->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
return 1;
*len = x;
#if defined(USE_SSL)
}
/* TODO: flags MSG_DONTROUTE, MSG_DONTWAIT, MSG_MORE, MSG_OOB, MSG_NOSIGNAL */
#if defined(MSG_NOSIGNAL)
flags |= MSG_NOSIGNAL;
#endif
x = send (rdev->sck, data, *len, flags);
if (x == -1)
return 1;
}
static int dev_sck_read_stateless (stio_dev_t* dev, void* buf, stio_iolen_t* len, stio_devaddr_t* srcaddr)
{
stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
stio_scklen_t srcaddrlen;
ssize_t x;
srcaddrlen = STIO_SIZEOF(rdev->remoteaddr);
x = recvfrom (rdev->sck, buf, *len, 0, (struct sockaddr*)&rdev->remoteaddr, &srcaddrlen);
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0; /* no data can be written */
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data available */
if (errno == EINTR) return 0;
rdev->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
srcaddr->ptr = &rdev->remoteaddr;
srcaddr->len = srcaddrlen;
*len = x;
return 1;
}
static int dev_sck_write_stateless (stio_dev_t* dev, const void* data, stio_iolen_t* len, const stio_devadr_t* dstadr)
static int dev_sck_write_stateful (stio_dev_t* dev, const void* data, stio_iolen_t* len, const stio_devaddr_t* dstaddr)
{
stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
#if defined(USE_SSL)
if (rdev->ssl)
{
int x;
if (*len <= 0)
{
/* it's a writing finish indicator. close the writing end of
* the socket, probably leaving it in the half-closed state */
if (SSL_shutdown ((SSL*)rdev->ssl) == -1)
{
rdev->stio->errnum = STIO_ESYSERR;
return -1;
}
return 1;
}
x = SSL_write ((SSL*)rdev->ssl, data, *len);
if (x <= -1)
{
int err = SSL_get_error ((SSL*)rdev->ssl, x);
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) return 0;
rdev->stio->errnum = STIO_ESYSERR;
return -1;
}
*len = x;
}
else
{
#endif
ssize_t x;
int flags = 0;
if (*len <= 0)
{
/* it's a writing finish indicator. close the writing end of
* the socket, probably leaving it in the half-closed state */
if (shutdown (rdev->sck, SHUT_WR) == -1)
{
rdev->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
return 1;
}
/* TODO: flags MSG_DONTROUTE, MSG_DONTWAIT, MSG_MORE, MSG_OOB, MSG_NOSIGNAL */
#if defined(MSG_NOSIGNAL)
flags |= MSG_NOSIGNAL;
#endif
x = send (rdev->sck, data, *len, flags);
if (x == -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
if (errno == EINTR) return 0;
rdev->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
*len = x;
#if defined(USE_SSL)
}
#endif
return 1;
}
static int dev_sck_write_stateless (stio_dev_t* dev, const void* data, stio_iolen_t* len, const stio_devaddr_t* dstaddr)
{
stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
ssize_t x;
x = sendto (rdev->sck, data, *len, 0, dstadr->ptr, dstadr->len);
x = sendto (rdev->sck, data, *len, 0, dstaddr->ptr, dstaddr->len);
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0; /* no data can be written */
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
if (errno == EINTR) return 0;
rdev->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
@ -436,12 +556,12 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg)
case STIO_DEV_SCK_BIND:
{
stio_dev_sck_bind_t* bnd = (stio_dev_sck_bind_t*)arg;
struct sockaddr* sa = (struct sockaddr*)&bnd->addr;
struct sockaddr* sa = (struct sockaddr*)&bnd->localaddr;
stio_scklen_t sl;
stio_sckfam_t fam;
int x;
#if defined(USE_SSL)
SSL_CTX* ssl = STIO_NULL;
SSL_CTX* ssl_ctx = STIO_NULL;
#endif
if (bnd->options & STIO_DEV_SCK_BIND_BROADCAST)
@ -456,65 +576,109 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg)
if (bnd->options & STIO_DEV_SCK_BIND_REUSEADDR)
{
#if defined(SO_REUSEADDR)
int v = 1;
if (setsockopt (rdev->sck, SOL_SOCKET, SO_REUSEADDR, &v, STIO_SIZEOF(v)) == -1)
{
rdev->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
}
if (bnd->options & STIO_DEV_SCK_BIND_SECURE)
{
#if defined(USE_SSL)
SSL_CTX* ssl;
ssl = SSL_CTX_new (SSLv23_server_method());
if (!ssl)
{
rdev->stio->errnum = STIO_ESYSERR;
return -1;
}
if (SSL_CTX_use_certificate_file (ssl, bnd->certfile, SSL_FILETYPE_PEM) == 0 ||
SSL_CTX_use_PrivateKey_file (ssl, bnd->keyfile, SSL_FILETYPE_PEM) == 0 ||
SSL_CTX_check_private_key (ssl) == 0)
{
rdev->stio->errnum = STIO_ESYSERR;
SSL_CTX_free (ssl);
return -1;
}
SSL_CTX_set_read_ahead (ssl, 0);
#else
#else
rdev->stio->errnum = STIO_ENOIMPL;
return -1;
#endif
#endif
}
if (stio_getsckadrinfo (dev->stio, &bnd->addr, &sl, &fam) <= -1) return -1;
if (bnd->options & STIO_DEV_SCK_BIND_REUSEPORT)
{
#if defined(SO_REUSEPORT)
int v = 1;
if (setsockopt (rdev->sck, SOL_SOCKET, SO_REUSEPORT, &v, STIO_SIZEOF(v)) == -1)
{
rdev->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
#else
rdev->stio->errnum = STIO_ENOIMPL;
return -1;
#endif
}
if (bnd->options & STIO_DEV_SCK_BIND_TRANSPARENT)
{
#if defined(IP_TRANSPARENT)
int v = 1;
if (setsockopt (rdev->sck, SOL_IP, IP_TRANSPARENT, &v, STIO_SIZEOF(v)) == -1)
{
rdev->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
#else
rdev->stio->errnum = STIO_ENOIMPL;
return -1;
#endif
}
if (bnd->options & STIO_DEV_SCK_BIND_SSL)
{
#if defined(USE_SSL)
if (!bnd->certfile || !bnd->keyfile)
{
rdev->stio->errnum = STIO_EINVAL;
return -1;
}
ssl_ctx = SSL_CTX_new (SSLv23_server_method());
if (!ssl_ctx)
{
rdev->stio->errnum = STIO_ESYSERR;
return -1;
}
if (SSL_CTX_use_certificate_file (ssl_ctx, bnd->certfile, SSL_FILETYPE_PEM) == 0 ||
SSL_CTX_use_PrivateKey_file (ssl_ctx, bnd->keyfile, SSL_FILETYPE_PEM) == 0 ||
SSL_CTX_check_private_key (ssl_ctx) == 0 /*||
SSL_CTX_use_certificate_chain_file (ssl_ctx, bnd->chainfile) == 0*/)
{
rdev->stio->errnum = STIO_ESYSERR;
SSL_CTX_free (ssl_ctx);
return -1;
}
SSL_CTX_set_read_ahead (ssl_ctx, 0);
#else
rdev->stio->errnum = STIO_ENOIMPL;
return -1;
#endif
}
if (stio_getsckaddrinfo (dev->stio, &bnd->localaddr, &sl, &fam) <= -1) return -1;
x = bind (rdev->sck, sa, sl);
if (x == -1)
{
rdev->stio->errnum = stio_syserrtoerrnum(errno);
#if defined(USE_SSL)
if (ssl) SSL_CTX_free (ssl);
#endif
#if defined(USE_SSL)
if (ssl_ctx) SSL_CTX_free (ssl_ctx);
#endif
return -1;
}
rdev->localaddr = bnd->localaddr;
#if defined(USE_SSL)
rdev->secure_ctx = ssl;
rdev->sslctx = ssl_ctx;
#endif
return 0;
}
case STIO_DEV_SCK_CONNECT:
{
stio_dev_sck_connect_t* conn = (stio_dev_sck_connect_t*)arg;
struct sockaddr* sa = (struct sockaddr*)&conn->addr;
struct sockaddr* sa = (struct sockaddr*)&conn->remoteaddr;
stio_scklen_t sl;
stio_sckaddr_t localaddr;
int x;
if (!IS_STATEFUL(rdev))
@ -535,7 +699,7 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg)
x = connect (rdev->sck, sa, sl);
if (x == -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK)
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN)
{
if (stio_dev_watch ((stio_dev_t*)rdev, STIO_DEV_WATCH_UPDATE, STIO_DEV_EVENT_IN | STIO_DEV_EVENT_OUT) >= 0)
{
@ -562,7 +726,7 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg)
}
rdev->state |= STIO_DEV_SCK_CONNECTING;
rdev->peeradr = conn->addr;
rdev->remoteaddr = conn->remoteaddr;
rdev->on_connect = conn->on_connect;
rdev->on_disconnect = conn->on_disconnect;
return 0;
@ -575,9 +739,12 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg)
/* connected immediately */
rdev->state |= STIO_DEV_SCK_CONNECTED;
rdev->peeradr = conn->addr;
rdev->remoteaddr = conn->remoteaddr;
rdev->on_connect = conn->on_connect;
rdev->on_disconnect = conn->on_disconnect;
sl = STIO_SIZEOF(localaddr);
if (getsockname (rdev->sck, (struct sockaddr*)&localaddr, &sl) == 0) rdev->localaddr = localaddr;
return 0;
}
@ -700,6 +867,9 @@ static int dev_evcb_sck_ready_stateful (stio_dev_t* dev, int events)
}
else if (errcode == 0)
{
stio_sckaddr_t localaddr;
stio_scklen_t addrlen;
rdev->state &= ~STIO_DEV_SCK_CONNECTING;
rdev->state |= STIO_DEV_SCK_CONNECTED;
@ -711,6 +881,9 @@ static int dev_evcb_sck_ready_stateful (stio_dev_t* dev, int events)
STIO_ASSERT (rdev->tmridx_connect == STIO_TMRIDX_INVALID);
}
addrlen = STIO_SIZEOF(localaddr);
if (getsockname (rdev->sck, (struct sockaddr*)&localaddr, &addrlen) == 0) rdev->localaddr = localaddr;
if (rdev->on_connect (rdev) <= -1) return -1;
}
else if (errcode == EINPROGRESS || errcode == EWOULDBLOCK)
@ -742,17 +915,17 @@ static int dev_evcb_sck_ready_stateful (stio_dev_t* dev, int events)
else if (events & STIO_DEV_EVENT_IN)
{
stio_sckhnd_t clisck;
stio_sckadr_t peer;
stio_sckaddr_t remoteaddr;
stio_scklen_t addrlen;
stio_dev_sck_t* clidev;
/* this is a server(lisening) socket */
addrlen = STIO_SIZEOF(peer);
clisck = accept (rdev->sck, (struct sockaddr*)&peer, &addrlen);
addrlen = STIO_SIZEOF(remoteaddr);
clisck = accept (rdev->sck, (struct sockaddr*)&remoteaddr, &addrlen);
if (clisck == STIO_SCKHND_INVALID)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0;
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0;
if (errno == EINTR) return 0; /* if interrupted by a signal, treat it as if it's EINPROGRESS */
rdev->stio->errnum = stio_syserrtoerrnum(errno);
@ -770,10 +943,55 @@ static int dev_evcb_sck_ready_stateful (stio_dev_t* dev, int events)
return -1;
}
clidev->dev_capa |= STIO_DEV_CAPA_IN | STIO_DEV_CAPA_OUT | STIO_DEV_CAPA_STREAM;
clidev->state |= STIO_DEV_SCK_ACCEPTED;
clidev->peeradr = peer;
STIO_ASSERT (clidev->sck == clisck);
clidev->dev_capa |= STIO_DEV_CAPA_IN | STIO_DEV_CAPA_OUT | STIO_DEV_CAPA_STREAM | STIO_DEV_CAPA_OUT_QUEUED;
if (rdev->sslctx)
clidev->state |= STIO_DEV_SCK_ACCEPTING_SSL;
else
clidev->state |= STIO_DEV_SCK_ACCEPTED;
/*clidev->parent = sck;*/
clidev->remoteaddr = remoteaddr;
addrlen = STIO_SIZEOF(clidev->localaddr);
if (getsockname(clisck, (struct sockaddr*)&clidev->localaddr, &addrlen) == -1) clidev->localaddr = rdev->localaddr;
#if defined(SO_ORIGINAL_DST)
/* if REDIRECT is used, SO_ORIGINAL_DST returns the original
* destination address. When REDIRECT is not used, it returnes
* the address of the local socket. In this case, it should
* be same as the result of getsockname(). */
addrlen = STIO_SIZEOF(clidev->orgdstaddr);
if (getsockopt (clisck, SOL_IP, SO_ORIGINAL_DST, &clidev->orgdstaddr, &addrlen) == -1) clidev->orgdstaddr = rdev->localaddr;
#else
clidev->orgdstaddr = rdev->localaddr;
#endif
if (!stio_equalsckaddrs (rdev->stio, &clidev->orgdstaddr, &clidev->localaddr))
{
clidev->state |= STIO_DEV_SCK_INTERCEPTED;
}
else if (stio_getsckaddrport (&clidev->localaddr) != stio_getsckaddrport(&rdev->localaddr))
{
/* When TPROXY is used, getsockname() and SO_ORIGNAL_DST return
* the same addresses. however, the port number may be different
* as a typical TPROXY rule is set to change the port number.
* However, this check is fragile if the server port number is
* set to 0.
*
* Take note that the above assumption gets wrong if the TPROXY
* rule doesn't change the port number. so it won't be able
* to handle such a TPROXYed packet without port transformation. */
clidev->state |= STIO_DEV_SCK_INTERCEPTED;
}
#if 0
else if ((clidev->initial_ifindex = resolve_ifindex (fd, clidev->localaddr)) <= -1)
{
/* the local_address is not one of a local address.
* it's probably proxied. */
clidev->state |= STIO_DEV_SCK_INTERCEPTED;
}
#endif
/* inherit some event handlers from the parent.
* you can still change them inside the on_connect handler */
@ -782,12 +1000,87 @@ static int dev_evcb_sck_ready_stateful (stio_dev_t* dev, int events)
clidev->on_write = rdev->on_write;
clidev->on_read = rdev->on_read;
clidev->tmridx_connect = STIO_TMRIDX_INVALID;
if (clidev->on_connect(clidev) <= -1) stio_dev_sck_halt (clidev);
if (clidev->state & STIO_DEV_SCK_ACCEPTED)
{
STIO_ASSERT (!(clidev->state & STIO_DEV_SCK_ACCEPTING_SSL));
clidev->tmridx_connect = STIO_TMRIDX_INVALID;
if (clidev->on_connect(clidev) <= -1) stio_dev_sck_halt (clidev);
}
else
{
STIO_ASSERT (clidev->state & STIO_DEV_SCK_ACCEPTING_SSL);
/* actual SSL acceptance must be completed in the client device */
/* let the client device know the SSL context to use */
clidev->sslctx = rdev->sslctx;
/* TODO: secure accept timeout handling */
/* clidev->tmridx_connect??? */
clidev->tmridx_connect = STIO_TMRIDX_INVALID;
printf ("TO DO SSL ...............................\n");
}
return 0; /* success but don't invoke on_read() */
}
}
else if (rdev->state & STIO_DEV_SCK_ACCEPTING_SSL)
{
#if defined(USE_SSL)
int ret;
printf ("SSL IN ACCPEING>.. %p.......................\n", rdev);
/* client socket has been accepted. SSL accpetance is needed here */
if (!rdev->ssl)
{
SSL* ssl;
printf ("SSL CREATED.....................\n");
ssl = SSL_new (rdev->sslctx);
if (!ssl)
{
printf ("SSL ERROR 1>..................... %s\n", ERR_reason_error_string(ERR_get_error()));
rdev->stio->errnum = STIO_ESYSERR;
return -1;
}
if (SSL_set_fd (ssl, rdev->sck) == 0)
{
printf ("SSL ERROR 2>..................... %s\n", ERR_reason_error_string(ERR_get_error()));
rdev->stio->errnum = STIO_ESYSERR;
return -1;
}
SSL_set_read_ahead (ssl, 0);
rdev->ssl = ssl;
}
ret = SSL_accept ((SSL*)rdev->ssl);
if (ret <= 0)
{
int err = SSL_get_error (rdev->ssl, ret);
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
{
/* handshaking isn't complete */
return 0;
}
printf ("SSL ERROR 3>..................... %s\n", ERR_reason_error_string(err));
rdev->stio->errnum = STIO_ESYSERR;
return -1;
}
printf ("SSL ACCEPTED.....................\n");
rdev->state &= ~STIO_DEV_SCK_ACCEPTING_SSL;
rdev->state |= STIO_DEV_SCK_ACCEPTED;
if (rdev->on_connect(rdev) <= -1) stio_dev_sck_halt (rdev);
return 0; /* no reading or writing yet */
#else
rdev->stio->errnum = STIO_EINTERN;
return -1;
#endif
}
else if (events & STIO_DEV_EVENT_HUP)
{
if (events & (STIO_DEV_EVENT_PRI | STIO_DEV_EVENT_IN | STIO_DEV_EVENT_OUT))
@ -836,28 +1129,28 @@ static int dev_evcb_sck_ready_stateless (stio_dev_t* dev, int events)
return 1; /* the device is ok. carry on reading or writing */
}
static int dev_evcb_sck_on_read_stateful (stio_dev_t* dev, const void* data, stio_iolen_t dlen, const stio_devadr_t* srcadr)
static int dev_evcb_sck_on_read_stateful (stio_dev_t* dev, const void* data, stio_iolen_t dlen, const stio_devaddr_t* srcaddr)
{
stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
return rdev->on_read (rdev, data, dlen, STIO_NULL);
}
static int dev_evcb_sck_on_write_stateful (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_devadr_t* dstadr)
static int dev_evcb_sck_on_write_stateful (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_devaddr_t* dstaddr)
{
stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
return rdev->on_write (rdev, wrlen, wrctx, STIO_NULL);
}
static int dev_evcb_sck_on_read_stateless (stio_dev_t* dev, const void* data, stio_iolen_t dlen, const stio_devadr_t* srcadr)
static int dev_evcb_sck_on_read_stateless (stio_dev_t* dev, const void* data, stio_iolen_t dlen, const stio_devaddr_t* srcaddr)
{
stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
return rdev->on_read (rdev, data, dlen, srcadr->ptr);
return rdev->on_read (rdev, data, dlen, srcaddr->ptr);
}
static int dev_evcb_sck_on_write_stateless (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_devadr_t* dstadr)
static int dev_evcb_sck_on_write_stateless (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_devaddr_t* dstaddr)
{
stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
return rdev->on_write (rdev, wrlen, wrctx, dstadr->ptr);
return rdev->on_write (rdev, wrlen, wrctx, dstaddr->ptr);
}
static stio_dev_evcb_t dev_sck_event_callbacks_stateful =
@ -917,14 +1210,14 @@ int stio_dev_sck_listen (stio_dev_sck_t* dev, stio_dev_sck_listen_t* info)
return stio_dev_ioctl ((stio_dev_t*)dev, STIO_DEV_SCK_LISTEN, info);
}
int stio_dev_sck_write (stio_dev_sck_t* dev, const void* data, stio_iolen_t dlen, void* wrctx, const stio_sckadr_t* dstadr)
int stio_dev_sck_write (stio_dev_sck_t* dev, const void* data, stio_iolen_t dlen, void* wrctx, const stio_sckaddr_t* dstaddr)
{
stio_devadr_t devadr;
return stio_dev_write ((stio_dev_t*)dev, data, dlen, wrctx, sckadr_to_devadr(dev, dstadr, &devadr));
stio_devaddr_t devaddr;
return stio_dev_write ((stio_dev_t*)dev, data, dlen, wrctx, sckaddr_to_devaddr(dev, dstaddr, &devaddr));
}
int stio_dev_sck_timedwrite (stio_dev_sck_t* dev, const void* data, stio_iolen_t dlen, const stio_ntime_t* tmout, void* wrctx, const stio_sckadr_t* dstadr)
int stio_dev_sck_timedwrite (stio_dev_sck_t* dev, const void* data, stio_iolen_t dlen, const stio_ntime_t* tmout, void* wrctx, const stio_sckaddr_t* dstaddr)
{
stio_devadr_t devadr;
return stio_dev_timedwrite ((stio_dev_t*)dev, data, dlen, tmout, wrctx, sckadr_to_devadr(dev, dstadr, &devadr));
stio_devaddr_t devaddr;
return stio_dev_timedwrite ((stio_dev_t*)dev, data, dlen, tmout, wrctx, sckaddr_to_devaddr(dev, dstaddr, &devaddr));
}

View File

@ -29,13 +29,14 @@
#include <stio.h>
struct stio_sckadr_t
typedef int stio_sckfam_t;
struct stio_sckaddr_t
{
int family;
stio_sckfam_t family;
stio_uint8_t data[128]; /* TODO: use the actual sockaddr size */
};
typedef struct stio_sckadr_t stio_sckadr_t;
typedef struct stio_sckaddr_t stio_sckaddr_t;
#if (STIO_SIZEOF_SOCKLEN_T == STIO_SIZEOF_INT)
#if defined(STIO_SOCKLEN_T_IS_SIGNED)
@ -70,8 +71,6 @@ typedef struct stio_sckadr_t stio_sckadr_t;
#endif
typedef int stio_sckfam_t;
#define STIO_SCK_ETH_PROTO_IP4 0x0800
#define STIO_SCK_ETH_PROTO_ARP 0x0806
@ -91,26 +90,28 @@ typedef enum stio_dev_sck_ioctl_cmd_t stio_dev_sck_ioctl_cmd_t;
enum stio_dev_sck_state_t
{
STIO_DEV_SCK_CONNECTING = (1 << 0),
STIO_DEV_SCK_CONNECTED = (1 << 1),
STIO_DEV_SCK_LISTENING = (1 << 2),
STIO_DEV_SCK_ACCEPTED = (1 << 3)
STIO_DEV_SCK_CONNECTING = (1 << 0),
STIO_DEV_SCK_CONNECTED = (1 << 1),
STIO_DEV_SCK_LISTENING = (1 << 2),
STIO_DEV_SCK_ACCEPTING_SSL = (1 << 3),
STIO_DEV_SCK_ACCEPTED = (1 << 4),
STIO_DEV_SCK_INTERCEPTED = (1 << 5)
};
typedef enum stio_dev_sck_state_t stio_dev_sck_state_t;
typedef struct stio_dev_sck_t stio_dev_sck_t;
typedef int (*stio_dev_sck_on_read_t) (
stio_dev_sck_t* dev,
const void* data,
stio_iolen_t dlen,
const stio_sckadr_t* srcadr
stio_dev_sck_t* dev,
const void* data,
stio_iolen_t dlen,
const stio_sckaddr_t* srcaddr
);
typedef int (*stio_dev_sck_on_write_t) (
stio_dev_sck_t* dev,
stio_iolen_t wrlen,
void* wrctx,
const stio_sckadr_t* dstadr
stio_dev_sck_t* dev,
stio_iolen_t wrlen,
void* wrctx,
const stio_sckaddr_t* dstaddr
);
typedef int (*stio_dev_sck_on_connect_t) (stio_dev_sck_t* dev);
@ -144,11 +145,15 @@ struct stio_dev_sck_make_t
enum stio_dev_sck_bind_option_t
{
STIO_DEV_SCK_BIND_BROADCAST = (1 << 0),
STIO_DEV_SCK_BIND_REUSEADDR = (1 << 1),
/* TODO: more options --- TRANSPARENT...SO_RCVBUF, SO_SNDBUF, SO_RCVTIMEO, SO_SNDTIMEO, SO_KEEPALIVE */
STIO_DEV_SCK_BIND_BROADCAST = (1 << 0),
STIO_DEV_SCK_BIND_REUSEADDR = (1 << 1),
STIO_DEV_SCK_BIND_REUSEPORT = (1 << 2),
STIO_DEV_SCK_BIND_TRANSPARENT = (1 << 3),
STIO_DEV_SCK_BIND_SECURE = (1 << 15)
/* TODO: more options --- SO_RCVBUF, SO_SNDBUF, SO_RCVTIMEO, SO_SNDTIMEO, SO_KEEPALIVE */
/* BINDTODEVICE??? */
STIO_DEV_SCK_BIND_SSL = (1 << 15)
};
typedef enum stio_dev_sck_bind_option_t stio_dev_sck_bind_option_t;
@ -156,7 +161,7 @@ typedef struct stio_dev_sck_bind_t stio_dev_sck_bind_t;
struct stio_dev_sck_bind_t
{
int options;
stio_sckadr_t addr;
stio_sckaddr_t localaddr;
/* TODO: add device name for BIND_TO_DEVICE */
const stio_mchar_t* certfile;
@ -166,7 +171,7 @@ struct stio_dev_sck_bind_t
typedef struct stio_dev_sck_connect_t stio_dev_sck_connect_t;
struct stio_dev_sck_connect_t
{
stio_sckadr_t addr;
stio_sckaddr_t remoteaddr;
stio_ntime_t tmout; /* connect timeout */
stio_dev_sck_on_connect_t on_connect;
stio_dev_sck_on_disconnect_t on_disconnect;
@ -185,7 +190,7 @@ struct stio_dev_sck_accept_t
{
stio_syshnd_t sck;
/* TODO: add timeout */
stio_sckadr_t peeradr;
stio_sckaddr_t remoteaddr;
};
struct stio_dev_sck_t
@ -194,15 +199,18 @@ struct stio_dev_sck_t
stio_dev_sck_type_t type;
stio_sckhnd_t sck;
void* secure_ctx;
void* sslctx;
void* ssl;
stio_dev_sck_on_write_t on_write;
stio_dev_sck_on_read_t on_read;
int state;
/** 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 */
/* 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 */
stio_dev_sck_on_connect_t on_connect;
stio_dev_sck_on_disconnect_t on_disconnect;
stio_tmridx_t tmridx_connect;
@ -215,7 +223,10 @@ struct stio_dev_sck_t
*
* also used as a placeholder to store source address for
* a stateless socket */
stio_sckadr_t peeradr;
stio_sckaddr_t remoteaddr;
stio_sckaddr_t localaddr;
stio_sckaddr_t orgdstaddr;
};
#ifdef __cplusplus
@ -239,30 +250,38 @@ STIO_EXPORT int stio_makesckasync (
stio_sckhnd_t sck
);
STIO_EXPORT int stio_getsckadrinfo (
STIO_EXPORT int stio_getsckaddrinfo (
stio_t* stio,
const stio_sckadr_t* addr,
const stio_sckaddr_t* addr,
stio_scklen_t* len,
stio_sckfam_t* family
);
void stio_sckadr_initforip4 (
stio_sckadr_t* sckadr,
stio_uint16_t port,
stio_ip4adr_t* ip4adr
/*
* The stio_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.
*/
STIO_EXPORT stio_uint16_t stio_getsckaddrport (
const stio_sckaddr_t* addr
);
void stio_sckadr_initforip6 (
stio_sckadr_t* sckadr,
STIO_EXPORT void stio_sckaddr_initforip4 (
stio_sckaddr_t* sckaddr,
stio_uint16_t port,
stio_ip6adr_t* ip6adr
stio_ip4addr_t* ip4addr
);
void stio_sckadr_initforeth (
stio_sckadr_t* sckadr,
STIO_EXPORT void stio_sckaddr_initforip6 (
stio_sckaddr_t* sckaddr,
stio_uint16_t port,
stio_ip6addr_t* ip6addr
);
STIO_EXPORT void stio_sckaddr_initforeth (
stio_sckaddr_t* sckaddr,
int ifindex,
stio_ethadr_t* ethadr
stio_ethaddr_t* ethaddr
);
/* ========================================================================= */
@ -293,7 +312,7 @@ STIO_EXPORT int stio_dev_sck_write (
const void* data,
stio_iolen_t len,
void* wrctx,
const stio_sckadr_t* dstadr
const stio_sckaddr_t* dstaddr
);
STIO_EXPORT int stio_dev_sck_timedwrite (
@ -302,7 +321,7 @@ STIO_EXPORT int stio_dev_sck_timedwrite (
stio_iolen_t len,
const stio_ntime_t* tmout,
void* wrctx,
const stio_sckadr_t* dstadr
const stio_sckaddr_t* dstaddr
);
#if defined(STIO_HAVE_INLINE)

524
stio/lib/stio-utl.c Normal file
View File

@ -0,0 +1,524 @@
/*
* $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 "stio-prv.h"
/* ========================================================================= */
#if defined(STIO_HAVE_UINT16_T)
stio_uint16_t stio_ntoh16 (stio_uint16_t x)
{
#if defined(STIO_ENDIAN_BIG)
return x;
#elif defined(STIO_ENDIAN_LITTLE)
stio_uint8_t* c = (stio_uint8_t*)&x;
return (stio_uint16_t)(
((stio_uint16_t)c[0] << 8) |
((stio_uint16_t)c[1] << 0));
#else
# error Unknown endian
#endif
}
stio_uint16_t stio_hton16 (stio_uint16_t x)
{
#if defined(STIO_ENDIAN_BIG)
return x;
#elif defined(STIO_ENDIAN_LITTLE)
stio_uint8_t* c = (stio_uint8_t*)&x;
return (stio_uint16_t)(
((stio_uint16_t)c[0] << 8) |
((stio_uint16_t)c[1] << 0));
#else
# error Unknown endian
#endif
}
#endif
/* ========================================================================= */
#if defined(STIO_HAVE_UINT32_T)
stio_uint32_t stio_ntoh32 (stio_uint32_t x)
{
#if defined(STIO_ENDIAN_BIG)
return x;
#elif defined(STIO_ENDIAN_LITTLE)
stio_uint8_t* c = (stio_uint8_t*)&x;
return (stio_uint32_t)(
((stio_uint32_t)c[0] << 24) |
((stio_uint32_t)c[1] << 16) |
((stio_uint32_t)c[2] << 8) |
((stio_uint32_t)c[3] << 0));
#else
# error Unknown endian
#endif
}
stio_uint32_t stio_hton32 (stio_uint32_t x)
{
#if defined(STIO_ENDIAN_BIG)
return x;
#elif defined(STIO_ENDIAN_LITTLE)
stio_uint8_t* c = (stio_uint8_t*)&x;
return (stio_uint32_t)(
((stio_uint32_t)c[0] << 24) |
((stio_uint32_t)c[1] << 16) |
((stio_uint32_t)c[2] << 8) |
((stio_uint32_t)c[3] << 0));
#else
# error Unknown endian
#endif
}
#endif
/* ========================================================================= */
#if defined(STIO_HAVE_UINT64_T)
stio_uint64_t stio_ntoh64 (stio_uint64_t x)
{
#if defined(STIO_ENDIAN_BIG)
return x;
#elif defined(STIO_ENDIAN_LITTLE)
stio_uint8_t* c = (stio_uint8_t*)&x;
return (stio_uint64_t)(
((stio_uint64_t)c[0] << 56) |
((stio_uint64_t)c[1] << 48) |
((stio_uint64_t)c[2] << 40) |
((stio_uint64_t)c[3] << 32) |
((stio_uint64_t)c[4] << 24) |
((stio_uint64_t)c[5] << 16) |
((stio_uint64_t)c[6] << 8) |
((stio_uint64_t)c[7] << 0));
#else
# error Unknown endian
#endif
}
stio_uint64_t stio_hton64 (stio_uint64_t x)
{
#if defined(STIO_ENDIAN_BIG)
return x;
#elif defined(STIO_ENDIAN_LITTLE)
stio_uint8_t* c = (stio_uint8_t*)&x;
return (stio_uint64_t)(
((stio_uint64_t)c[0] << 56) |
((stio_uint64_t)c[1] << 48) |
((stio_uint64_t)c[2] << 40) |
((stio_uint64_t)c[3] << 32) |
((stio_uint64_t)c[4] << 24) |
((stio_uint64_t)c[5] << 16) |
((stio_uint64_t)c[6] << 8) |
((stio_uint64_t)c[7] << 0));
#else
# error Unknown endian
#endif
}
#endif
/* ========================================================================= */
#if defined(STIO_HAVE_UINT128_T)
stio_uint128_t stio_ntoh128 (stio_uint128_t x)
{
#if defined(STIO_ENDIAN_BIG)
return x;
#elif defined(STIO_ENDIAN_LITTLE)
stio_uint8_t* c = (stio_uint8_t*)&x;
return (stio_uint128_t)(
((stio_uint128_t)c[0] << 120) |
((stio_uint128_t)c[1] << 112) |
((stio_uint128_t)c[2] << 104) |
((stio_uint128_t)c[3] << 96) |
((stio_uint128_t)c[4] << 88) |
((stio_uint128_t)c[5] << 80) |
((stio_uint128_t)c[6] << 72) |
((stio_uint128_t)c[7] << 64) |
((stio_uint128_t)c[8] << 56) |
((stio_uint128_t)c[9] << 48) |
((stio_uint128_t)c[10] << 40) |
((stio_uint128_t)c[11] << 32) |
((stio_uint128_t)c[12] << 24) |
((stio_uint128_t)c[13] << 16) |
((stio_uint128_t)c[14] << 8) |
((stio_uint128_t)c[15] << 0));
#else
# error Unknown endian
#endif
}
stio_uint128_t stio_hton128 (stio_uint128_t x)
{
#if defined(STIO_ENDIAN_BIG)
return x;
#elif defined(STIO_ENDIAN_LITTLE)
stio_uint8_t* c = (stio_uint8_t*)&x;
return (stio_uint128_t)(
((stio_uint128_t)c[0] << 120) |
((stio_uint128_t)c[1] << 112) |
((stio_uint128_t)c[2] << 104) |
((stio_uint128_t)c[3] << 96) |
((stio_uint128_t)c[4] << 88) |
((stio_uint128_t)c[5] << 80) |
((stio_uint128_t)c[6] << 72) |
((stio_uint128_t)c[7] << 64) |
((stio_uint128_t)c[8] << 56) |
((stio_uint128_t)c[9] << 48) |
((stio_uint128_t)c[10] << 40) |
((stio_uint128_t)c[11] << 32) |
((stio_uint128_t)c[12] << 24) |
((stio_uint128_t)c[13] << 16) |
((stio_uint128_t)c[14] << 8) |
((stio_uint128_t)c[15] << 0));
#else
# error Unknown endian
#endif
}
#endif
/* ========================================================================= */
#define IS_MSPACE(x) ((x) == STIO_MT(' ') || (x) == STIO_MT('\t') || (x) == STIO_MT('\n') || (x) == STIO_MT('\r'))
stio_mchar_t* stio_mbsdup (stio_t* stio, const stio_mchar_t* src)
{
stio_mchar_t* dst;
stio_size_t len;
dst = (stio_mchar_t*)src;
while (*dst != STIO_MT('\0')) dst++;
len = dst - src;
dst = STIO_MMGR_ALLOC (stio->mmgr, (len + 1) * STIO_SIZEOF(*src));
if (!dst)
{
stio->errnum = STIO_ENOMEM;
return STIO_NULL;
}
STIO_MEMCPY (dst, src, (len + 1) * STIO_SIZEOF(*src));
return dst;
}
stio_size_t stio_mbscpy (stio_mchar_t* buf, const stio_mchar_t* str)
{
stio_mchar_t* org = buf;
while ((*buf++ = *str++) != STIO_MT('\0'));
return buf - org - 1;
}
int stio_mbsspltrn (
stio_mchar_t* s, const stio_mchar_t* delim,
stio_mchar_t lquote, stio_mchar_t rquote,
stio_mchar_t escape, const stio_mchar_t* trset)
{
stio_mchar_t* p = s, *d;
stio_mchar_t* sp = STIO_NULL, * ep = STIO_NULL;
int delim_mode;
int cnt = 0;
if (delim == STIO_NULL) delim_mode = 0;
else
{
delim_mode = 1;
for (d = (stio_mchar_t*)delim; *d != STIO_MT('\0'); d++)
if (!IS_MSPACE(*d)) delim_mode = 2;
}
if (delim_mode == 0)
{
/* skip preceding space characters */
while (IS_MSPACE(*p)) p++;
/* when 0 is given as "delim", it has an effect of cutting
preceding and trailing space characters off "s". */
if (lquote != STIO_MT('\0') && *p == lquote)
{
stio_mbscpy (p, p + 1);
for (;;)
{
if (*p == STIO_MT('\0')) return -1;
if (escape != STIO_MT('\0') && *p == escape)
{
if (trset != STIO_NULL && p[1] != STIO_MT('\0'))
{
const stio_mchar_t* ep = trset;
while (*ep != STIO_MT('\0'))
{
if (p[1] == *ep++)
{
p[1] = *ep;
break;
}
}
}
stio_mbscpy (p, p + 1);
}
else
{
if (*p == rquote)
{
p++;
break;
}
}
if (sp == 0) sp = p;
ep = p;
p++;
}
while (IS_MSPACE(*p)) p++;
if (*p != STIO_MT('\0')) return -1;
if (sp == 0 && ep == 0) s[0] = STIO_MT('\0');
else
{
ep[1] = STIO_MT('\0');
if (s != (stio_mchar_t*)sp) stio_mbscpy (s, sp);
cnt++;
}
}
else
{
while (*p)
{
if (!IS_MSPACE(*p))
{
if (sp == 0) sp = p;
ep = p;
}
p++;
}
if (sp == 0 && ep == 0) s[0] = STIO_MT('\0');
else
{
ep[1] = STIO_MT('\0');
if (s != (stio_mchar_t*)sp) stio_mbscpy (s, sp);
cnt++;
}
}
}
else if (delim_mode == 1)
{
stio_mchar_t* o;
while (*p)
{
o = p;
while (IS_MSPACE(*p)) p++;
if (o != p) { stio_mbscpy (o, p); p = o; }
if (lquote != STIO_MT('\0') && *p == lquote)
{
stio_mbscpy (p, p + 1);
for (;;)
{
if (*p == STIO_MT('\0')) return -1;
if (escape != STIO_MT('\0') && *p == escape)
{
if (trset != STIO_NULL && p[1] != STIO_MT('\0'))
{
const stio_mchar_t* ep = trset;
while (*ep != STIO_MT('\0'))
{
if (p[1] == *ep++)
{
p[1] = *ep;
break;
}
}
}
stio_mbscpy (p, p + 1);
}
else
{
if (*p == rquote)
{
*p++ = STIO_MT('\0');
cnt++;
break;
}
}
p++;
}
}
else
{
o = p;
for (;;)
{
if (*p == STIO_MT('\0'))
{
if (o != p) cnt++;
break;
}
if (IS_MSPACE (*p))
{
*p++ = STIO_MT('\0');
cnt++;
break;
}
p++;
}
}
}
}
else /* if (delim_mode == 2) */
{
stio_mchar_t* o;
int ok;
while (*p != STIO_MT('\0'))
{
o = p;
while (IS_MSPACE(*p)) p++;
if (o != p) { stio_mbscpy (o, p); p = o; }
if (lquote != STIO_MT('\0') && *p == lquote)
{
stio_mbscpy (p, p + 1);
for (;;)
{
if (*p == STIO_MT('\0')) return -1;
if (escape != STIO_MT('\0') && *p == escape)
{
if (trset != STIO_NULL && p[1] != STIO_MT('\0'))
{
const stio_mchar_t* ep = trset;
while (*ep != STIO_MT('\0'))
{
if (p[1] == *ep++)
{
p[1] = *ep;
break;
}
}
}
stio_mbscpy (p, p + 1);
}
else
{
if (*p == rquote)
{
*p++ = STIO_MT('\0');
cnt++;
break;
}
}
p++;
}
ok = 0;
while (IS_MSPACE(*p)) p++;
if (*p == STIO_MT('\0')) ok = 1;
for (d = (stio_mchar_t*)delim; *d != STIO_MT('\0'); d++)
{
if (*p == *d)
{
ok = 1;
stio_mbscpy (p, p + 1);
break;
}
}
if (ok == 0) return -1;
}
else
{
o = p; sp = ep = 0;
for (;;)
{
if (*p == STIO_MT('\0'))
{
if (ep)
{
ep[1] = STIO_MT('\0');
p = &ep[1];
}
cnt++;
break;
}
for (d = (stio_mchar_t*)delim; *d != STIO_MT('\0'); d++)
{
if (*p == *d)
{
if (sp == STIO_NULL)
{
stio_mbscpy (o, p); p = o;
*p++ = STIO_MT('\0');
}
else
{
stio_mbscpy (&ep[1], p);
stio_mbscpy (o, sp);
o[ep - sp + 1] = STIO_MT('\0');
p = &o[ep - sp + 2];
}
cnt++;
/* last empty field after delim */
if (*p == STIO_MT('\0')) cnt++;
goto exit_point;
}
}
if (!IS_MSPACE (*p))
{
if (sp == STIO_NULL) sp = p;
ep = p;
}
p++;
}
exit_point:
;
}
}
}
return cnt;
}
int stio_mbsspl (
stio_mchar_t* s, const stio_mchar_t* delim,
stio_mchar_t lquote, stio_mchar_t rquote, stio_mchar_t escape)
{
return stio_mbsspltrn (s, delim, lquote, rquote, escape, STIO_NULL);
}

View File

@ -33,7 +33,6 @@
#define DEV_CAPA_ALL_WATCHED (STIO_DEV_CAPA_IN_WATCHED | STIO_DEV_CAPA_OUT_WATCHED | STIO_DEV_CAPA_PRI_WATCHED)
#define IS_MSPACE(x) ((x) == STIO_MT(' ') || (x) == STIO_MT('\t'))
static int schedule_kill_zombie_job (stio_dev_t* dev);
static int kill_and_free_device (stio_dev_t* dev, int force);
@ -252,7 +251,8 @@ printf ("has urgent data...\n");
send_leftover:
ulen = urem;
x = dev->dev_mth->write (dev, uptr, &ulen, &q->dstadr);
printf ("&&&&&&&&&&&&&&&&&&&&&&&&&&&&7WRITING..........................\n");
x = dev->dev_mth->write (dev, uptr, &ulen, &q->dstaddr);
if (x <= -1)
{
stio_dev_halt (dev);
@ -286,7 +286,7 @@ printf ("has urgent data...\n");
}
unlink_wq (stio, q);
y = dev->dev_evcb->on_write (dev, q->olen, q->ctx, &q->dstadr);
y = dev->dev_evcb->on_write (dev, q->olen, q->ctx, &q->dstaddr);
STIO_MMGR_FREE (stio->mmgr, q);
if (y <= -1)
@ -331,7 +331,7 @@ printf ("has urgent data...\n");
if (dev && stio->revs[i].events & EPOLLIN)
{
stio_devadr_t srcadr;
stio_devaddr_t srcaddr;
stio_iolen_t len;
int x;
@ -341,7 +341,7 @@ printf ("has urgent data...\n");
while (1)
{
len = STIO_COUNTOF(stio->bigbuf);
x = dev->dev_mth->read (dev, stio->bigbuf, &len, &srcadr);
x = dev->dev_mth->read (dev, stio->bigbuf, &len, &srcaddr);
if (x <= -1)
{
stio_dev_halt (dev);
@ -363,7 +363,7 @@ printf ("has urgent data...\n");
stio->renew_watch = 1;
/* call the on_read callback to report EOF */
if (dev->dev_evcb->on_read (dev, stio->bigbuf, len, &srcadr) <= -1 ||
if (dev->dev_evcb->on_read (dev, stio->bigbuf, len, &srcaddr) <= -1 ||
(dev->dev_capa & STIO_DEV_CAPA_OUT_CLOSED))
{
/* 1. input ended and its reporting failed or
@ -382,7 +382,7 @@ printf ("has urgent data...\n");
* when x == 0 or <= -1. you can */
/* data available */
y = dev->dev_evcb->on_read (dev, stio->bigbuf, len, &srcadr);
y = dev->dev_evcb->on_read (dev, stio->bigbuf, len, &srcaddr);
if (y <= -1)
{
stio_dev_halt (dev);
@ -877,11 +877,10 @@ int stio_dev_watch (stio_dev_t* dev, stio_dev_watch_cmd_t cmd, int events)
if (epoll_op == EPOLL_CTL_MOD && (dev_capa & DEV_CAPA_ALL_WATCHED) == (dev->dev_capa & DEV_CAPA_ALL_WATCHED))
{
/* skip calling epoll_ctl */
/* no change in the device capacity. skip calling epoll_ctl */
}
else
{
printf ("MODING cmd=%d %d\n", (int)cmd, (int)dev->dev_mth->getsyshnd(dev));
if (epoll_ctl (dev->stio->mux, epoll_op, dev->dev_mth->getsyshnd(dev), &ev) == -1)
{
dev->stio->errnum = stio_syserrtoerrnum(errno);
@ -930,7 +929,7 @@ static void on_write_timeout (stio_t* stio, const stio_ntime_t* now, stio_tmrjob
dev = q->dev;
dev->stio->errnum = STIO_ETMOUT;
x = dev->dev_evcb->on_write (dev, -1, q->ctx, &q->dstadr);
x = dev->dev_evcb->on_write (dev, -1, q->ctx, &q->dstaddr);
STIO_ASSERT (q->tmridx == STIO_TMRIDX_INVALID);
STIO_WQ_UNLINK(q);
@ -939,7 +938,7 @@ static void on_write_timeout (stio_t* stio, const stio_ntime_t* now, stio_tmrjob
if (x <= -1) stio_dev_halt (dev);
}
static int __dev_write (stio_dev_t* dev, const void* data, stio_iolen_t len, const stio_ntime_t* tmout, void* wrctx, const stio_devadr_t* dstadr)
static int __dev_write (stio_dev_t* dev, const void* data, stio_iolen_t len, const stio_ntime_t* tmout, void* wrctx, const stio_devaddr_t* dstaddr)
{
const stio_uint8_t* uptr;
stio_iolen_t urem, ulen;
@ -968,7 +967,7 @@ static int __dev_write (stio_dev_t* dev, const void* data, stio_iolen_t len, con
do
{
ulen = urem;
x = dev->dev_mth->write (dev, data, &ulen, dstadr);
x = dev->dev_mth->write (dev, data, &ulen, dstaddr);
if (x <= -1) return -1;
else if (x == 0)
{
@ -994,18 +993,18 @@ static int __dev_write (stio_dev_t* dev, const void* data, stio_iolen_t len, con
dev->dev_capa |= STIO_DEV_CAPA_OUT_CLOSED;
}
if (dev->dev_evcb->on_write (dev, len, wrctx, dstadr) <= -1) return -1;
if (dev->dev_evcb->on_write (dev, len, wrctx, dstaddr) <= -1) return -1;
}
else
{
ulen = urem;
x = dev->dev_mth->write (dev, data, &ulen, dstadr);
x = dev->dev_mth->write (dev, data, &ulen, dstaddr);
if (x <= -1) return -1;
else if (x == 0) goto enqueue_data;
/* partial writing is still considered ok for a non-stream device */
if (dev->dev_evcb->on_write (dev, ulen, wrctx, dstadr) <= -1) return -1;
if (dev->dev_evcb->on_write (dev, ulen, wrctx, dstaddr) <= -1) return -1;
}
return 1; /* written immediately and called on_write callback */
@ -1014,11 +1013,12 @@ enqueue_data:
if (!(dev->dev_capa & STIO_DEV_CAPA_OUT_QUEUED))
{
/* writing queuing is not requested. so return failure */
dev->stio->errnum = STIO_ENOCAPA;
return -1;
}
/* queue the remaining data*/
q = (stio_wq_t*)STIO_MMGR_ALLOC (dev->stio->mmgr, STIO_SIZEOF(*q) + (dstadr? dstadr->len: 0) + urem);
q = (stio_wq_t*)STIO_MMGR_ALLOC (dev->stio->mmgr, STIO_SIZEOF(*q) + (dstaddr? dstaddr->len: 0) + urem);
if (!q)
{
dev->stio->errnum = STIO_ENOMEM;
@ -1029,23 +1029,22 @@ enqueue_data:
q->dev = dev;
q->ctx = wrctx;
if (dstadr)
if (dstaddr)
{
q->dstadr.ptr = (stio_uint8_t*)(q + 1);
q->dstadr.len = dstadr->len;
STIO_MEMCPY (q->dstadr.ptr, dstadr->ptr, dstadr->len);
q->dstaddr.ptr = (stio_uint8_t*)(q + 1);
q->dstaddr.len = dstaddr->len;
STIO_MEMCPY (q->dstaddr.ptr, dstaddr->ptr, dstaddr->len);
}
else
{
q->dstadr.len = 0;
q->dstaddr.len = 0;
}
q->ptr = (stio_uint8_t*)(q + 1) + q->dstadr.len;
q->ptr = (stio_uint8_t*)(q + 1) + q->dstaddr.len;
q->len = urem;
q->olen = len;
STIO_MEMCPY (q->ptr, uptr, urem);
if (tmout && !stio_isnegtime(tmout))
{
stio_tmrjob_t tmrjob;
@ -1061,6 +1060,7 @@ enqueue_data:
if (q->tmridx == STIO_TMRIDX_INVALID)
{
STIO_MMGR_FREE (dev->stio->mmgr, q);
printf ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZz222222\n");
return -1;
}
}
@ -1073,6 +1073,7 @@ enqueue_data:
{
unlink_wq (dev->stio, q);
STIO_MMGR_FREE (dev->stio->mmgr, q);
printf ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZz11111\n");
return -1;
}
}
@ -1081,17 +1082,18 @@ enqueue_data:
dev->stio->renew_watch = 1;
}
printf ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZz\n");
return 0; /* request pused to a write queue. */
}
int stio_dev_write (stio_dev_t* dev, const void* data, stio_iolen_t len, void* wrctx, const stio_devadr_t* dstadr)
int stio_dev_write (stio_dev_t* dev, const void* data, stio_iolen_t len, void* wrctx, const stio_devaddr_t* dstaddr)
{
return __dev_write (dev, data, len, STIO_NULL, wrctx, dstadr);
return __dev_write (dev, data, len, STIO_NULL, wrctx, dstaddr);
}
int stio_dev_timedwrite (stio_dev_t* dev, const void* data, stio_iolen_t len, const stio_ntime_t* tmout, void* wrctx, const stio_devadr_t* dstadr)
int stio_dev_timedwrite (stio_dev_t* dev, const void* data, stio_iolen_t len, const stio_ntime_t* tmout, void* wrctx, const stio_devaddr_t* dstaddr)
{
return __dev_write (dev, data, len, tmout, wrctx, dstadr);
return __dev_write (dev, data, len, tmout, wrctx, dstaddr);
}
int stio_makesyshndasync (stio_t* stio, stio_syshnd_t hnd)
@ -1134,8 +1136,15 @@ stio_errnum_t stio_syserrtoerrnum (int no)
return STIO_ENFILE;
#endif
#if defined(EAGAIN)
#if defined(EWOULDBLOCK) && defined(EAGAIN) && (EWOULDBLOCK != EAGAIN)
case EAGAIN:
case EWOULDBLOCK:
return STIO_EAGAIN;
#elif defined(EAGAIN)
case EAGAIN:
return STIO_EAGAIN;
#elif defined(EWOULDBLOCK)
case EWOULDBLOCK:
return STIO_EAGAIN;
#endif
@ -1153,316 +1162,3 @@ stio_errnum_t stio_syserrtoerrnum (int no)
return STIO_ESYSERR;
}
}
stio_mchar_t* stio_mbsdup (stio_t* stio, const stio_mchar_t* src)
{
stio_mchar_t* dst;
stio_size_t len;
dst = (stio_mchar_t*)src;
while (*dst != STIO_MT('\0')) dst++;
len = dst - src;
dst = STIO_MMGR_ALLOC (stio->mmgr, (len + 1) * STIO_SIZEOF(*src));
if (!dst)
{
stio->errnum = STIO_ENOMEM;
return STIO_NULL;
}
STIO_MEMCPY (dst, src, (len + 1) * STIO_SIZEOF(*src));
return dst;
}
stio_size_t stio_mbscpy (stio_mchar_t* buf, const stio_mchar_t* str)
{
stio_mchar_t* org = buf;
while ((*buf++ = *str++) != STIO_MT('\0'));
return buf - org - 1;
}
int stio_mbsspltrn (
stio_mchar_t* s, const stio_mchar_t* delim,
stio_mchar_t lquote, stio_mchar_t rquote,
stio_mchar_t escape, const stio_mchar_t* trset)
{
stio_mchar_t* p = s, *d;
stio_mchar_t* sp = STIO_NULL, * ep = STIO_NULL;
int delim_mode;
int cnt = 0;
if (delim == STIO_NULL) delim_mode = 0;
else
{
delim_mode = 1;
for (d = (stio_mchar_t*)delim; *d != STIO_MT('\0'); d++)
if (!IS_MSPACE(*d)) delim_mode = 2;
}
if (delim_mode == 0)
{
/* skip preceding space characters */
while (IS_MSPACE(*p)) p++;
/* when 0 is given as "delim", it has an effect of cutting
preceding and trailing space characters off "s". */
if (lquote != STIO_MT('\0') && *p == lquote)
{
stio_mbscpy (p, p + 1);
for (;;)
{
if (*p == STIO_MT('\0')) return -1;
if (escape != STIO_MT('\0') && *p == escape)
{
if (trset != STIO_NULL && p[1] != STIO_MT('\0'))
{
const stio_mchar_t* ep = trset;
while (*ep != STIO_MT('\0'))
{
if (p[1] == *ep++)
{
p[1] = *ep;
break;
}
}
}
stio_mbscpy (p, p + 1);
}
else
{
if (*p == rquote)
{
p++;
break;
}
}
if (sp == 0) sp = p;
ep = p;
p++;
}
while (IS_MSPACE(*p)) p++;
if (*p != STIO_MT('\0')) return -1;
if (sp == 0 && ep == 0) s[0] = STIO_MT('\0');
else
{
ep[1] = STIO_MT('\0');
if (s != (stio_mchar_t*)sp) stio_mbscpy (s, sp);
cnt++;
}
}
else
{
while (*p)
{
if (!IS_MSPACE(*p))
{
if (sp == 0) sp = p;
ep = p;
}
p++;
}
if (sp == 0 && ep == 0) s[0] = STIO_MT('\0');
else
{
ep[1] = STIO_MT('\0');
if (s != (stio_mchar_t*)sp) stio_mbscpy (s, sp);
cnt++;
}
}
}
else if (delim_mode == 1)
{
stio_mchar_t* o;
while (*p)
{
o = p;
while (IS_MSPACE(*p)) p++;
if (o != p) { stio_mbscpy (o, p); p = o; }
if (lquote != STIO_MT('\0') && *p == lquote)
{
stio_mbscpy (p, p + 1);
for (;;)
{
if (*p == STIO_MT('\0')) return -1;
if (escape != STIO_MT('\0') && *p == escape)
{
if (trset != STIO_NULL && p[1] != STIO_MT('\0'))
{
const stio_mchar_t* ep = trset;
while (*ep != STIO_MT('\0'))
{
if (p[1] == *ep++)
{
p[1] = *ep;
break;
}
}
}
stio_mbscpy (p, p + 1);
}
else
{
if (*p == rquote)
{
*p++ = STIO_MT('\0');
cnt++;
break;
}
}
p++;
}
}
else
{
o = p;
for (;;)
{
if (*p == STIO_MT('\0'))
{
if (o != p) cnt++;
break;
}
if (IS_MSPACE (*p))
{
*p++ = STIO_MT('\0');
cnt++;
break;
}
p++;
}
}
}
}
else /* if (delim_mode == 2) */
{
stio_mchar_t* o;
int ok;
while (*p != STIO_MT('\0'))
{
o = p;
while (IS_MSPACE(*p)) p++;
if (o != p) { stio_mbscpy (o, p); p = o; }
if (lquote != STIO_MT('\0') && *p == lquote)
{
stio_mbscpy (p, p + 1);
for (;;)
{
if (*p == STIO_MT('\0')) return -1;
if (escape != STIO_MT('\0') && *p == escape)
{
if (trset != STIO_NULL && p[1] != STIO_MT('\0'))
{
const stio_mchar_t* ep = trset;
while (*ep != STIO_MT('\0'))
{
if (p[1] == *ep++)
{
p[1] = *ep;
break;
}
}
}
stio_mbscpy (p, p + 1);
}
else
{
if (*p == rquote)
{
*p++ = STIO_MT('\0');
cnt++;
break;
}
}
p++;
}
ok = 0;
while (IS_MSPACE(*p)) p++;
if (*p == STIO_MT('\0')) ok = 1;
for (d = (stio_mchar_t*)delim; *d != STIO_MT('\0'); d++)
{
if (*p == *d)
{
ok = 1;
stio_mbscpy (p, p + 1);
break;
}
}
if (ok == 0) return -1;
}
else
{
o = p; sp = ep = 0;
for (;;)
{
if (*p == STIO_MT('\0'))
{
if (ep)
{
ep[1] = STIO_MT('\0');
p = &ep[1];
}
cnt++;
break;
}
for (d = (stio_mchar_t*)delim; *d != STIO_MT('\0'); d++)
{
if (*p == *d)
{
if (sp == STIO_NULL)
{
stio_mbscpy (o, p); p = o;
*p++ = STIO_MT('\0');
}
else
{
stio_mbscpy (&ep[1], p);
stio_mbscpy (o, sp);
o[ep - sp + 1] = STIO_MT('\0');
p = &o[ep - sp + 2];
}
cnt++;
/* last empty field after delim */
if (*p == STIO_MT('\0')) cnt++;
goto exit_point;
}
}
if (!IS_MSPACE (*p))
{
if (sp == STIO_NULL) sp = p;
ep = p;
}
p++;
}
exit_point:
;
}
}
}
return cnt;
}
int stio_mbsspl (
stio_mchar_t* s, const stio_mchar_t* delim,
stio_mchar_t lquote, stio_mchar_t rquote, stio_mchar_t escape)
{
return stio_mbsspltrn (s, delim, lquote, rquote, escape, STIO_NULL);
}

View File

@ -48,8 +48,8 @@ struct stio_ntime_t
#define STIO_SYSHND_INVALID (-1)
#endif
typedef struct stio_devadr_t stio_devadr_t;
struct stio_devadr_t
typedef struct stio_devaddr_t stio_devaddr_t;
struct stio_devaddr_t
{
int len;
void* ptr;
@ -79,7 +79,8 @@ struct stio_devadr_t
# error UNKNOWN ENDIAN
#endif
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
typedef struct stio_t stio_t;
typedef struct stio_dev_t stio_dev_t;
typedef struct stio_dev_mth_t stio_dev_mth_t;
@ -133,7 +134,8 @@ typedef void (*stio_tmrjob_updater_t) (
struct stio_dev_mth_t
{
/* ------------------------------------------------------------------ */
int (*make) (stio_dev_t* dev, void* ctx); /* mandatory. called in stio_makedev() */
/* mandatory. called in stio_makedev() */
int (*make) (stio_dev_t* dev, void* ctx);
/* ------------------------------------------------------------------ */
/* mandatory. called in stio_killdev(). also called in stio_makedev() upon
@ -144,7 +146,9 @@ struct stio_dev_mth_t
* until the method returns 0.
*
* when 'force' is 1, the called should not return -1. If it does, the
* method is not called again.
* 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) (stio_dev_t* dev, int force);
@ -156,10 +160,10 @@ struct stio_dev_mth_t
/* 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) (stio_dev_t* dev, void* data, stio_iolen_t* len, stio_devadr_t* srcadr);
int (*read) (stio_dev_t* dev, void* data, stio_iolen_t* len, stio_devaddr_t* srcaddr);
/* ------------------------------------------------------------------ */
int (*write) (stio_dev_t* dev, const void* data, stio_iolen_t* len, const stio_devadr_t* dstadr);
int (*write) (stio_dev_t* dev, const void* data, stio_iolen_t* len, const stio_devaddr_t* dstaddr);
/* ------------------------------------------------------------------ */
int (*ioctl) (stio_dev_t* dev, int cmd, void* arg);
@ -176,28 +180,28 @@ struct stio_dev_evcb_t
/* 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) (stio_dev_t* dev, const void* data, stio_iolen_t len, const stio_devadr_t* srcadr);
int (*on_read) (stio_dev_t* dev, const void* data, stio_iolen_t len, const stio_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) (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_devadr_t* dstadr);
int (*on_write) (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_devaddr_t* dstaddr);
};
struct stio_wq_t
{
stio_wq_t* next;
stio_wq_t* prev;
stio_wq_t* next;
stio_wq_t* prev;
stio_iolen_t olen; /* original data length */
stio_uint8_t* ptr; /* pointer to data */
stio_uint8_t* ptr; /* pointer to data */
stio_iolen_t len; /* remaining data length */
void* ctx;
stio_dev_t* dev; /* back-pointer to the device */
void* ctx;
stio_dev_t* dev; /* back-pointer to the device */
stio_tmridx_t tmridx;
stio_devadr_t dstadr;
stio_tmridx_t tmridx;
stio_devaddr_t dstaddr;
};
#define STIO_WQ_INIT(wq) ((wq)->next = (wq)->prev = (wq))
@ -311,9 +315,9 @@ typedef enum stio_dev_event_t stio_dev_event_t;
#define STIO_ARPHDR_HTYPE_ETH 0x0001
#define STIO_ARPHDR_PTYPE_IP4 0x0800
#define STIO_ETHADR_LEN 6
#define STIO_IP4ADR_LEN 4
#define STIO_IP6ADR_LEN 16
#define STIO_ETHADDR_LEN 6
#define STIO_IP4ADDR_LEN 4
#define STIO_IP6ADDR_LEN 16
#if defined(__GNUC__)
@ -333,29 +337,29 @@ typedef enum stio_dev_event_t stio_dev_event_t;
#pragma pack(push)
#pragma pack(1)
#endif
struct STIO_PACKED stio_ethadr_t
struct STIO_PACKED stio_ethaddr_t
{
stio_uint8_t v[STIO_ETHADR_LEN];
stio_uint8_t v[STIO_ETHADDR_LEN];
};
typedef struct stio_ethadr_t stio_ethadr_t;
typedef struct stio_ethaddr_t stio_ethaddr_t;
struct STIO_PACKED stio_ip4adr_t
struct STIO_PACKED stio_ip4addr_t
{
stio_uint8_t v[STIO_IP4ADR_LEN];
stio_uint8_t v[STIO_IP4ADDR_LEN];
};
typedef struct stio_ip4adr_t stio_ip4adr_t;
typedef struct stio_ip4addr_t stio_ip4addr_t;
struct STIO_PACKED stio_ip6adr_t
struct STIO_PACKED stio_ip6addr_t
{
stio_uint8_t v[STIO_IP6ADR_LEN];
stio_uint8_t v[STIO_IP6ADDR_LEN];
};
typedef struct stio_ip6adr_t stio_ip6adr_t;
typedef struct stio_ip6addr_t stio_ip6addr_t;
struct STIO_PACKED stio_ethhdr_t
{
stio_uint8_t dest[STIO_ETHADR_LEN];
stio_uint8_t source[STIO_ETHADR_LEN];
stio_uint8_t dest[STIO_ETHADDR_LEN];
stio_uint8_t source[STIO_ETHADDR_LEN];
stio_uint16_t proto;
};
typedef struct stio_ethhdr_t stio_ethhdr_t;
@ -373,10 +377,10 @@ typedef struct stio_arphdr_t stio_arphdr_t;
/* arp payload for ipv4 over ethernet */
struct STIO_PACKED stio_etharp_t
{
stio_uint8_t sha[STIO_ETHADR_LEN]; /* source hardware address */
stio_uint8_t spa[STIO_IP4ADR_LEN]; /* source protocol address */
stio_uint8_t tha[STIO_ETHADR_LEN]; /* target hardware address */
stio_uint8_t tpa[STIO_IP4ADR_LEN]; /* target protocol address */
stio_uint8_t sha[STIO_ETHADDR_LEN]; /* source hardware address */
stio_uint8_t spa[STIO_IP4ADDR_LEN]; /* source protocol address */
stio_uint8_t tha[STIO_ETHADDR_LEN]; /* target hardware address */
stio_uint8_t tpa[STIO_IP4ADDR_LEN]; /* target protocol address */
};
typedef struct stio_etharp_t stio_etharp_t;
@ -475,21 +479,21 @@ STIO_EXPORT int stio_dev_read (
* it returns 0. otherwise it returns -1.
*/
STIO_EXPORT int stio_dev_write (
stio_dev_t* dev,
const void* data,
stio_iolen_t len,
void* wrctx,
const stio_devadr_t* dstadr
stio_dev_t* dev,
const void* data,
stio_iolen_t len,
void* wrctx,
const stio_devaddr_t* dstaddr
);
STIO_EXPORT int stio_dev_timedwrite (
stio_dev_t* dev,
const void* data,
stio_iolen_t len,
const stio_ntime_t* tmout,
void* wrctx,
const stio_devadr_t* dstadr
stio_dev_t* dev,
const void* data,
stio_iolen_t len,
const stio_ntime_t* tmout,
void* wrctx,
const stio_devaddr_t* dstaddr
);
STIO_EXPORT void stio_dev_halt (
@ -497,7 +501,7 @@ STIO_EXPORT void stio_dev_halt (
);
/* ------------------------------------------------ */
/* ========================================================================= */
#define stio_inittime(x,s,ns) (((x)->sec = (s)), ((x)->nsec = (ns)))
#define stio_cleartime(x) stio_inittime(x,0,0)
@ -565,6 +569,53 @@ STIO_EXPORT stio_tmrjob_t* stio_gettmrjob (
stio_tmridx_t index
);
/* ========================================================================= */
#if defined(STIO_HAVE_UINT16_T)
STIO_EXPORT stio_uint16_t stio_ntoh16 (
stio_uint16_t x
);
STIO_EXPORT stio_uint16_t stio_hton16 (
stio_uint16_t x
);
#endif
#if defined(STIO_HAVE_UINT32_T)
STIO_EXPORT stio_uint32_t stio_ntoh32 (
stio_uint32_t x
);
STIO_EXPORT stio_uint32_t stio_hton32 (
stio_uint32_t x
);
#endif
#if defined(STIO_HAVE_UINT64_T)
STIO_EXPORT stio_uint64_t stio_ntoh64 (
stio_uint64_t x
);
STIO_EXPORT stio_uint64_t stio_hton64 (
stio_uint64_t x
);
#endif
#if defined(STIO_HAVE_UINT128_T)
STIO_EXPORT stio_uint128_t stio_ntoh128 (
stio_uint128_t x
);
STIO_EXPORT stio_uint128_t stio_hton128 (
stio_uint128_t x
);
#endif
/* ========================================================================= */
#ifdef __cplusplus
}
#endif