added SSL to the listening socket
This commit is contained in:
		@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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 (ðdst, if_nametoindex("enp0s25.3"), (stio_ethadr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF");
 | 
			
		||||
	stio_sckadr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (stio_ethadr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF");
 | 
			
		||||
	//stio_sckaddr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF");
 | 
			
		||||
	stio_sckaddr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF");
 | 
			
		||||
 | 
			
		||||
	memset (ðarp, 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, ðarp, sizeof(etharp), NULL, ðdst) <= -1)
 | 
			
		||||
	//if (stio_dev_sck_write (sck, ðarp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, ðadr) <= -1)
 | 
			
		||||
	//if (stio_dev_sck_write (sck, ðarp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, ðaddr) <= -1)
 | 
			
		||||
	{
 | 
			
		||||
		printf ("CANNOT WRITE ARP...\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
@ -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
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
									
								
							
							
						
						
									
										524
									
								
								stio/lib/stio-utl.c
									
									
									
									
									
										Normal 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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										378
									
								
								stio/lib/stio.c
									
									
									
									
									
								
							
							
						
						
									
										378
									
								
								stio/lib/stio.c
									
									
									
									
									
								
							@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										143
									
								
								stio/lib/stio.h
									
									
									
									
									
								
							
							
						
						
									
										143
									
								
								stio/lib/stio.h
									
									
									
									
									
								
							@ -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
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user