From ec4bd54e53c837941a62368f47a6216de7a41bcb Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 18 Apr 2016 14:21:23 +0000 Subject: [PATCH] added SSL to the listening socket --- stio/lib/Makefile.am | 3 +- stio/lib/Makefile.in | 13 +- stio/lib/main.c | 68 +++-- stio/lib/stio-arp.c | 192 -------------- stio/lib/stio-arp.h | 84 ------ stio/lib/stio-pro.c | 18 +- stio/lib/stio-prv.h | 1 + stio/lib/stio-sck.c | 595 ++++++++++++++++++++++++++++++++----------- stio/lib/stio-sck.h | 109 ++++---- stio/lib/stio-utl.c | 524 +++++++++++++++++++++++++++++++++++++ stio/lib/stio.c | 378 +++------------------------ stio/lib/stio.h | 143 +++++++---- 12 files changed, 1230 insertions(+), 898 deletions(-) delete mode 100644 stio/lib/stio-arp.c delete mode 100644 stio/lib/stio-arp.h create mode 100644 stio/lib/stio-utl.c diff --git a/stio/lib/Makefile.am b/stio/lib/Makefile.am index 898fd8d..43dc668 100644 --- a/stio/lib/Makefile.am +++ b/stio/lib/Makefile.am @@ -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) diff --git a/stio/lib/Makefile.in b/stio/lib/Makefile.in index 0426766..5a20c90 100644 --- a/stio/lib/Makefile.in +++ b/stio/lib/Makefile.in @@ -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 diff --git a/stio/lib/main.c b/stio/lib/main.c index 0aa6fcf..46f6bd5 100644 --- a/stio/lib/main.c +++ b/stio/lib/main.c @@ -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"); } diff --git a/stio/lib/stio-arp.c b/stio/lib/stio-arp.c deleted file mode 100644 index 7a1c4a5..0000000 --- a/stio/lib/stio-arp.c +++ /dev/null @@ -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 -#include -#include -#include -#include - -#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 diff --git a/stio/lib/stio-arp.h b/stio/lib/stio-arp.h deleted file mode 100644 index 61191bb..0000000 --- a/stio/lib/stio-arp.h +++ /dev/null @@ -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 -#include - - -#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 diff --git a/stio/lib/stio-pro.c b/stio/lib/stio-pro.c index 516d8c9..a8c77d5 100644 --- a/stio/lib/stio-pro.c +++ b/stio/lib/stio-pro.c @@ -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); diff --git a/stio/lib/stio-prv.h b/stio/lib/stio-prv.h index 6a23c5b..85d6304 100644 --- a/stio/lib/stio-prv.h +++ b/stio/lib/stio-prv.h @@ -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 diff --git a/stio/lib/stio-sck.c b/stio/lib/stio-sck.c index f0ea330..1fb9e18 100644 --- a/stio/lib/stio-sck.c +++ b/stio/lib/stio-sck.c @@ -37,6 +37,22 @@ #include #include +#if defined(__linux__) +# include +# if defined(HAVE_LINUX_NETFILTER_IPV4_H) +# include /* 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 # 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)); } diff --git a/stio/lib/stio-sck.h b/stio/lib/stio-sck.h index fbf7b07..f3d652a 100644 --- a/stio/lib/stio-sck.h +++ b/stio/lib/stio-sck.h @@ -29,13 +29,14 @@ #include -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) diff --git a/stio/lib/stio-utl.c b/stio/lib/stio-utl.c new file mode 100644 index 0000000..2a8b8fa --- /dev/null +++ b/stio/lib/stio-utl.c @@ -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); +} diff --git a/stio/lib/stio.c b/stio/lib/stio.c index c705d3a..55998c0 100644 --- a/stio/lib/stio.c +++ b/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); -} diff --git a/stio/lib/stio.h b/stio/lib/stio.h index f7c7c1f..a603d23 100644 --- a/stio/lib/stio.h +++ b/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