From e74a5554f258228e8add7fc251d67b6b3fb77044 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sun, 8 Aug 2021 04:10:29 +0000 Subject: [PATCH] added hio_dev_cap_to_bcstr() for easier debugging. added hio_concat_uchars_to_ucstr()/hio_concat_bchars_to_bcstr() added hio_concat_ucstr()/hio_concat_bcstr() --- hio/bin/t06.c | 6 ++ hio/lib/dns.c | 4 +- hio/lib/hio-utl.h | 51 ++++++++-- hio/lib/hio.c | 34 +++++++ hio/lib/hio.h | 51 ++++++---- hio/lib/sck.c | 218 ++++++++++++++++++++++++++++++++----------- hio/lib/utl-str.c | 133 ++++++++++++++++++++++---- hio/lib/utl-str.c.m4 | 82 +++++++++++++--- 8 files changed, 457 insertions(+), 122 deletions(-) diff --git a/hio/bin/t06.c b/hio/bin/t06.c index aaed44c..24f9bc0 100644 --- a/hio/bin/t06.c +++ b/hio/bin/t06.c @@ -562,6 +562,12 @@ int main (int argc, char* argv[]) g_dev_type4 = HIO_DEV_SCK_SCTP4; g_dev_type6 = HIO_DEV_SCK_SCTP6; } + else if (strcmp(argv[i], "-ss") == 0) + { + i++; + g_dev_type4 = HIO_DEV_SCK_SCTP4_SP; + g_dev_type6 = HIO_DEV_SCK_SCTP6_SP; + } else if (strcmp(argv[i], "-t") == 0) { i++; diff --git a/hio/lib/dns.c b/hio/lib/dns.c index 5530f11..cc6c152 100644 --- a/hio/lib/dns.c +++ b/hio/lib/dns.c @@ -472,8 +472,8 @@ hio_dns_pkt_info_t* hio_dns_make_pkt_info (hio_t* hio, const hio_dns_pkt_t* pkt, HIO_MEMSET (&pib, 0, HIO_SIZEOF(pib)); - /* this is used a initial workspace and also indicates that it's the first run. - * at the second run, it is set to a dynamically allocated memory block large enough + /* pib is used as the initial workspace and also indicates that it's the first run. + * at the second run, pii is set to a dynamically allocated memory block large enough * to hold actual data. */ pii = &pib; diff --git a/hio/lib/hio-utl.h b/hio/lib/hio-utl.h index e893bbc..5de9dc6 100644 --- a/hio/lib/hio-utl.h +++ b/hio/lib/hio-utl.h @@ -245,6 +245,14 @@ enum hio_trim_oochars_flag_t extern "C" { #endif +HIO_EXPORT hio_oow_t hio_count_ucstr ( + const hio_uch_t* str +); + +HIO_EXPORT hio_oow_t hio_count_bcstr ( + const hio_bch_t* str +); + /** * The hio_equal_uchars() function determines equality of two strings * of the same length \a len. @@ -408,6 +416,32 @@ HIO_EXPORT hio_oow_t hio_copy_bcstr_unlimited ( const hio_bch_t* src ); +HIO_EXPORT hio_oow_t hio_concat_uchars_to_ucstr ( + hio_uch_t* buf, + hio_oow_t bsz, + const hio_uch_t* src, + hio_oow_t len +); + +HIO_EXPORT hio_oow_t hio_concat_bchars_to_bcstr ( + hio_bch_t* buf, + hio_oow_t bsz, + const hio_bch_t* src, + hio_oow_t len +); + +HIO_EXPORT hio_oow_t hio_concat_ucstr ( + hio_uch_t* buf, + hio_oow_t bsz, + const hio_uch_t* src +); + +HIO_EXPORT hio_oow_t hio_concat_bcstr ( + hio_bch_t* buf, + hio_oow_t bsz, + const hio_bch_t* src +); + HIO_EXPORT void hio_fill_uchars ( hio_uch_t* dst, const hio_uch_t ch, @@ -496,15 +530,9 @@ HIO_EXPORT int hio_split_bcstr ( hio_bch_t escape ); -HIO_EXPORT hio_oow_t hio_count_ucstr ( - const hio_uch_t* str -); - -HIO_EXPORT hio_oow_t hio_count_bcstr ( - const hio_bch_t* str -); #if defined(HIO_OOCH_IS_UCH) +# define hio_count_oocstr hio_count_ucstr # define hio_equal_oochars hio_equal_uchars # define hio_comp_oochars hio_comp_uchars # define hio_comp_oocstr_bcstr hio_comp_ucstr_bcstr @@ -524,6 +552,9 @@ HIO_EXPORT hio_oow_t hio_count_bcstr ( # define hio_copy_oocstr hio_copy_ucstr # define hio_copy_oocstr_unlimited hio_copy_ucstr_unlimited +# define hio_concat_oochars_to_ucstr hio_concat_uchars_to_ucstr +# define hio_concat_oocstr hio_concat_ucstr + # define hio_fill_oochars hio_fill_uchars # define hio_find_oocstr_word_in_oocstr hio_find_ucstr_word_in_ucstr # define hio_find_oochar hio_find_uchar @@ -532,8 +563,8 @@ HIO_EXPORT hio_oow_t hio_count_bcstr ( # define hio_trim_oochars hio_trim_uchars # define hio_split_oocstr hio_split_ucstr -# define hio_count_oocstr hio_count_ucstr #else +# define hio_count_oocstr hio_count_bcstr # define hio_equal_oochars hio_equal_bchars # define hio_comp_oochars hio_comp_bchars # define hio_comp_oocstr_bcstr hio_comp_bcstr @@ -553,6 +584,9 @@ HIO_EXPORT hio_oow_t hio_count_bcstr ( # define hio_copy_oocstr hio_copy_bcstr # define hio_copy_oocstr_unlimited hio_copy_bcstr_unlimited +# define hio_concat_oochars_to_bcstr hio_concat_bchars_to_bcstr +# define hio_concat_oocstr hio_concat_bcstr + # define hio_fill_oochars hio_fill_bchars # define hio_find_oocstr_word_in_oocstr hio_find_bcstr_word_in_bcstr # define hio_find_oochar hio_find_bchar @@ -561,7 +595,6 @@ HIO_EXPORT hio_oow_t hio_count_bcstr ( # define hio_trim_oochars hio_trim_bchars # define hio_split_oocstr hio_split_bcstr -# define hio_count_oocstr hio_count_bcstr #endif /* ------------------------------------------------------------------------- */ diff --git a/hio/lib/hio.c b/hio/lib/hio.c index a6cbcb2..b39e147 100644 --- a/hio/lib/hio.c +++ b/hio/lib/hio.c @@ -2195,3 +2195,37 @@ hio_oow_t hio_fmttobcstr (hio_t* hio, hio_bch_t* buf, hio_oow_t bufsz, const hio } /* ------------------------------------------------------------------------ */ + +hio_oow_t hio_dev_cap_to_bcstr (hio_bitmask_t cap, hio_bch_t* buf, hio_oow_t size) +{ + hio_oow_t len = 0; + + if (size <= 0) return 0; + buf[len] = '\0'; + + if (cap & HIO_DEV_CAP_VIRTUAL) len += hio_copy_bcstr(&buf[len], size - len, "virtual|"); + if (cap & HIO_DEV_CAP_IN) len += hio_copy_bcstr(&buf[len], size - len, "in|"); + if (cap & HIO_DEV_CAP_OUT) len += hio_copy_bcstr(&buf[len], size - len, "out|"); + if (cap & HIO_DEV_CAP_PRI) len += hio_copy_bcstr(&buf[len], size - len, "pri|"); + if (cap & HIO_DEV_CAP_STREAM) len += hio_copy_bcstr(&buf[len], size - len, "stream|"); + if (cap & HIO_DEV_CAP_IN_DISABLED) len += hio_copy_bcstr(&buf[len], size - len, "in_disabled|"); + if (cap & HIO_DEV_CAP_OUT_UNQUEUEABLE) len += hio_copy_bcstr(&buf[len], size - len, "out_unqueueable|"); + + if (cap & HIO_DEV_CAP_IN_CLOSED) len += hio_copy_bcstr(&buf[len], size - len, "in_closed|"); + if (cap & HIO_DEV_CAP_OUT_CLOSED) len += hio_copy_bcstr(&buf[len], size - len, "out_closed|"); + if (cap & HIO_DEV_CAP_IN_WATCHED) len += hio_copy_bcstr(&buf[len], size - len, "in_watched|"); + if (cap & HIO_DEV_CAP_OUT_WATCHED) len += hio_copy_bcstr(&buf[len], size - len, "out_watched|"); + if (cap & HIO_DEV_CAP_PRI_WATCHED) len += hio_copy_bcstr(&buf[len], size - len, "pri_watched|"); + if (cap & HIO_DEV_CAP_ACTIVE) len += hio_copy_bcstr(&buf[len], size - len, "active|"); + if (cap & HIO_DEV_CAP_HALTED) len += hio_copy_bcstr(&buf[len], size - len, "halted|"); + if (cap & HIO_DEV_CAP_ZOMBIE) len += hio_copy_bcstr(&buf[len], size - len, "zombie|"); + if (cap & HIO_DEV_CAP_RENEW_REQUIRED) len += hio_copy_bcstr(&buf[len], size - len, "renew_required|"); + if (cap & HIO_DEV_CAP_WATCH_STARTED) len += hio_copy_bcstr(&buf[len], size - len, "watch_started|"); + if (cap & HIO_DEV_CAP_WATCH_SUSPENDED) len += hio_copy_bcstr(&buf[len], size - len, "watch_suspended|"); + if (cap & HIO_DEV_CAP_WATCH_REREG_REQUIRED) len += hio_copy_bcstr(&buf[len], size - len, "watch_rereg_required|"); + + if (buf[len - 1] == '|') buf[--len] = '\0'; + return len; +} + + diff --git a/hio/lib/hio.h b/hio/lib/hio.h index 248a00f..002d5b1 100644 --- a/hio/lib/hio.h +++ b/hio/lib/hio.h @@ -367,7 +367,7 @@ struct hio_wq_t #define HIO_DEV_HEADER \ hio_t* hio; \ hio_oow_t dev_size; \ - int dev_cap; \ + hio_bitmask_t dev_cap; \ hio_dev_mth_t* dev_mth; \ hio_dev_evcb_t* dev_evcb; \ hio_ntime_t rtmout; \ @@ -409,31 +409,36 @@ struct hio_dev_t enum hio_dev_cap_t { - HIO_DEV_CAP_VIRTUAL = (1 << 0), - HIO_DEV_CAP_IN = (1 << 1), - HIO_DEV_CAP_OUT = (1 << 2), - HIO_DEV_CAP_PRI = (1 << 3), /* meaningful only if #HIO_DEV_CAP_IN is set */ - HIO_DEV_CAP_STREAM = (1 << 4), - HIO_DEV_CAP_IN_DISABLED = (1 << 5), - HIO_DEV_CAP_OUT_UNQUEUEABLE = (1 << 6), + /* don't forget to update hio_dev_cap_to_bcstr() + * when you add/delete these enumerators */ + + HIO_DEV_CAP_VIRTUAL = ((hio_bitmask_t)1 << 0), + HIO_DEV_CAP_IN = ((hio_bitmask_t)1 << 1), + HIO_DEV_CAP_OUT = ((hio_bitmask_t)1 << 2), + HIO_DEV_CAP_PRI = ((hio_bitmask_t)1 << 3), /* meaningful only if #HIO_DEV_CAP_IN is set */ + HIO_DEV_CAP_STREAM = ((hio_bitmask_t)1 << 4), /* byte stream */ + + + HIO_DEV_CAP_IN_DISABLED = ((hio_bitmask_t)1 << 5), + HIO_DEV_CAP_OUT_UNQUEUEABLE = ((hio_bitmask_t)1 << 6), HIO_DEV_CAP_ALL_MASK = (HIO_DEV_CAP_VIRTUAL | HIO_DEV_CAP_IN | HIO_DEV_CAP_OUT | HIO_DEV_CAP_PRI | HIO_DEV_CAP_STREAM | HIO_DEV_CAP_IN_DISABLED | HIO_DEV_CAP_OUT_UNQUEUEABLE), /* ------------------------------------------------------------------- * the followings bits are for internal use only. * never set these bits to the dev_cap field. * ------------------------------------------------------------------- */ - HIO_DEV_CAP_IN_CLOSED = (1 << 10), - HIO_DEV_CAP_OUT_CLOSED = (1 << 11), - HIO_DEV_CAP_IN_WATCHED = (1 << 12), - HIO_DEV_CAP_OUT_WATCHED = (1 << 13), - HIO_DEV_CAP_PRI_WATCHED = (1 << 14), /**< can be set only if HIO_DEV_CAP_IN_WATCHED is set */ - HIO_DEV_CAP_ACTIVE = (1 << 15), - HIO_DEV_CAP_HALTED = (1 << 16), - HIO_DEV_CAP_ZOMBIE = (1 << 17), - HIO_DEV_CAP_RENEW_REQUIRED = (1 << 18), - HIO_DEV_CAP_WATCH_STARTED = (1 << 19), - HIO_DEV_CAP_WATCH_SUSPENDED = (1 << 20), - HIO_DEV_CAP_WATCH_REREG_REQUIRED = (1 << 21), + HIO_DEV_CAP_IN_CLOSED = ((hio_bitmask_t)1 << 10), + HIO_DEV_CAP_OUT_CLOSED = ((hio_bitmask_t)1 << 11), + HIO_DEV_CAP_IN_WATCHED = ((hio_bitmask_t)1 << 12), + HIO_DEV_CAP_OUT_WATCHED = ((hio_bitmask_t)1 << 13), + HIO_DEV_CAP_PRI_WATCHED = ((hio_bitmask_t)1 << 14), /**< can be set only if HIO_DEV_CAP_IN_WATCHED is set */ + HIO_DEV_CAP_ACTIVE = ((hio_bitmask_t)1 << 15), + HIO_DEV_CAP_HALTED = ((hio_bitmask_t)1 << 16), + HIO_DEV_CAP_ZOMBIE = ((hio_bitmask_t)1 << 17), + HIO_DEV_CAP_RENEW_REQUIRED = ((hio_bitmask_t)1 << 18), + HIO_DEV_CAP_WATCH_STARTED = ((hio_bitmask_t)1 << 19), + HIO_DEV_CAP_WATCH_SUSPENDED = ((hio_bitmask_t)1 << 20), + HIO_DEV_CAP_WATCH_REREG_REQUIRED = ((hio_bitmask_t)1 << 21), }; typedef enum hio_dev_cap_t hio_dev_cap_t; @@ -1412,6 +1417,12 @@ HIO_EXPORT const hio_ooch_t* hio_errnum_to_errstr ( hio_errnum_t errnum ); +HIO_EXPORT hio_oow_t hio_dev_cap_to_bcstr ( + hio_bitmask_t cap, + hio_bch_t* buf, + hio_oow_t bsz +); + #ifdef __cplusplus } #endif diff --git a/hio/lib/sck.c b/hio/lib/sck.c index a6910a1..8b94985 100644 --- a/hio/lib/sck.c +++ b/hio/lib/sck.c @@ -39,6 +39,10 @@ #include #include +#if defined(HAVE_NETINET_SCTP_H) +# include +#endif + #if defined(HAVE_NETPACKET_PACKET_H) # include #endif @@ -182,8 +186,8 @@ static hio_syshnd_t open_async_bpf (hio_t* hio) if (fd == HIO_SYSHND_INVALID) goto oops; #if 0 - if (ioctl(fd, BIOCIMMEDIATE, &tmp) == -1) goto oops; - if (ioctl(fd, BIOCGBLEN, &bufsize) == -1) goto oops; + if (ioctl(fd, BIOCIMMEDIATE, &tmp) <= -1) goto oops; + if (ioctl(fd, BIOCGBLEN, &bufsize) <= -1) goto oops; #endif return fd; @@ -221,7 +225,11 @@ struct sck_type_map_t int domain; int type; int proto; - int extra_dev_cap; + + unsigned int connectable: 1; + unsigned int listenable: 1; + + hio_bitmask_t extra_dev_cap; }; #define __AF_BPF 999998 @@ -229,82 +237,82 @@ struct sck_type_map_t static struct sck_type_map_t sck_type_map[] = { /* HIO_DEV_SCK_QX */ - { HIO_AF_QX, 0, 0, 0 }, + { HIO_AF_QX, 0, 0, 0, 0, 0 }, #if defined(AF_UNIX) - { AF_UNIX, SOCK_STREAM, 0, HIO_DEV_CAP_STREAM }, + { AF_UNIX, SOCK_STREAM, 0, 1, 1, HIO_DEV_CAP_STREAM }, #else - { -1, 0, 0, 0 }, + { -1, 0, 0, 0, 0, 0 }, #endif /* HIO_DEV_SCK_TCP4 */ - { AF_INET, SOCK_STREAM, 0, HIO_DEV_CAP_STREAM }, + { AF_INET, SOCK_STREAM, 0, 1, 1, HIO_DEV_CAP_STREAM }, /* HIO_DEV_SCK_TCP6 */ - { AF_INET6, SOCK_STREAM, 0, HIO_DEV_CAP_STREAM }, + { AF_INET6, SOCK_STREAM, 0, 1, 1, HIO_DEV_CAP_STREAM }, - /* HIO_DEV_SCK_UPD4 */ - { AF_INET, SOCK_DGRAM, 0, 0 }, + /* HIO_DEV_SCK_UPD4 */ /* TODO: the socket api allows connect() on UDP sockets. should i mark it connectable? */ + { AF_INET, SOCK_DGRAM, 0, 0, 0, 0 }, /* HIO_DEV_SCK_UDP6 */ - { AF_INET6, SOCK_DGRAM, 0, 0 }, + { AF_INET6, SOCK_DGRAM, 0, 0, 0, 0 }, #if defined(IPPROTO_SCTP) /* HIO_DEV_SCK_SCTP4 */ - { AF_INET, SOCK_STREAM, IPPROTO_SCTP, HIO_DEV_CAP_STREAM }, + { AF_INET, SOCK_STREAM, IPPROTO_SCTP, 1, 1, HIO_DEV_CAP_STREAM }, /* HIO_DEV_SCK_SCTP6 */ - { AF_INET6, SOCK_STREAM, IPPROTO_SCTP, HIO_DEV_CAP_STREAM }, + { AF_INET6, SOCK_STREAM, IPPROTO_SCTP, 1, 1, HIO_DEV_CAP_STREAM }, /* HIO_DEV_SCK_SCTP4_SP - not implemented */ - { -1, SOCK_SEQPACKET, IPPROTO_SCTP, 0 }, + { AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, 1, 1, 0 }, /* HIO_DEV_SCK_SCTP6_SP - not implemented */ - { -1, SOCK_SEQPACKET, IPPROTO_SCTP, 0 }, + { AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 1, 1, 0 }, #else - { -1, 0, 0, 0 }, - { -1, 0, 0, 0 }, - { -1, 0, 0, 0 }, - { -1, 0, 0, 0 }, + { -1, 0, 0, 0, 0, 0 }, + { -1, 0, 0, 0, 0, 0 }, + { -1, 0, 0, 0, 0, 0 }, + { -1, 0, 0, 0, 0, 0 }, #endif /* HIO_DEV_SCK_ICMP4 - IP protocol field is 1 byte only. no byte order conversion is needed */ - { AF_INET, SOCK_RAW, IPPROTO_ICMP, 0 }, + { AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, 0, 0 }, /* HIO_DEV_SCK_ICMP6 - IP protocol field is 1 byte only. no byte order conversion is needed */ - { AF_INET6, SOCK_RAW, IPPROTO_ICMP, 0 }, + { AF_INET6, SOCK_RAW, IPPROTO_ICMP, 0, 0, 0 }, #if defined(AF_PACKET) && (HIO_SIZEOF_STRUCT_SOCKADDR_LL > 0) /* HIO_DEV_SCK_ARP - Ethernet type is 2 bytes long. Protocol must be specified in the network byte order */ - { AF_PACKET, SOCK_RAW, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0 }, + { AF_PACKET, SOCK_RAW, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0, 0, 0 }, /* HIO_DEV_SCK_ARP_DGRAM - link-level header removed*/ - { AF_PACKET, SOCK_DGRAM, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0 }, + { AF_PACKET, SOCK_DGRAM, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0, 0, 0 }, #elif defined(AF_LINK) && (HIO_SIZEOF_STRUCT_SOCKADDR_DL > 0) /* HIO_DEV_SCK_ARP */ - { AF_LINK, SOCK_RAW, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0 }, + { AF_LINK, SOCK_RAW, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0, 0, 0 }, /* HIO_DEV_SCK_ARP_DGRAM */ - { AF_LINK, SOCK_DGRAM, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0 }, + { AF_LINK, SOCK_DGRAM, HIO_CONST_HTON16(HIO_ETHHDR_PROTO_ARP), 0, 0, 0 }, #else - { -1, 0, 0, 0 }, - { -1, 0, 0, 0 }, + { -1, 0, 0, 0, 0, 0 }, + { -1, 0, 0, 0, 0, 0 }, #endif #if defined(AF_PACKET) && (HIO_SIZEOF_STRUCT_SOCKADDR_LL > 0) /* HIO_DEV_SCK_PACKET */ - { AF_PACKET, SOCK_RAW, HIO_CONST_HTON16(ETH_P_ALL), 0 }, + { AF_PACKET, SOCK_RAW, HIO_CONST_HTON16(ETH_P_ALL), 0, 0, 0 }, #elif defined(AF_LINK) && (HIO_SIZEOF_STRUCT_SOCKADDR_DL > 0) /* HIO_DEV_SCK_PACKET */ - { AF_LINK, SOCK_RAW, HIO_CONST_HTON16(0), 0 }, + { AF_LINK, SOCK_RAW, HIO_CONST_HTON16(0), 0, 0, 0 }, #else - { -1, 0, 0, 0 }, + { -1, 0, 0, 0, 0, 0 }, #endif /* HIO_DEV_SCK_BPF - arp */ - { __AF_BPF, 0, 0, 0 } /* not implemented yet */ + { __AF_BPF, 0, 0, 0, 0, 0 } /* not implemented yet */ }; /* ======================================================================== */ @@ -430,6 +438,18 @@ static int dev_sck_make (hio_dev_t* dev, void* ctx) { hnd = open_async_socket(hio, sck_type_map[arg->type].domain, sck_type_map[arg->type].type, sck_type_map[arg->type].proto); if (hnd == HIO_SYSHND_INVALID) goto oops; + + #if defined(IPPROTO_SCTP) + if (sck_type_map[arg->type].type == SOCK_SEQPACKET && + sck_type_map[arg->type].proto == IPPROTO_SCTP) + { + struct sctp_event_subscribe sctp_ev_s; + + HIO_MEMSET (&sctp_ev_s, 0, HIO_SIZEOF(sctp_ev_s)); + sctp_ev_s.sctp_data_io_event = 1; + setsockopt (hnd, IPPROTO_SCTP, SCTP_EVENTS, &sctp_ev_s, HIO_SIZEOF(sctp_ev_s)); + } + #endif } rdev->hnd = hnd; @@ -585,7 +605,7 @@ static int dev_sck_read_stateful (hio_dev_t* dev, void* buf, hio_iolen_t* len, h ssize_t x; x = recv(rdev->hnd, buf, *len, 0); - if (x == -1) + if (x <= -1) { if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data available */ if (errno == EINTR) return 0; @@ -636,6 +656,54 @@ static int dev_sck_read_bpf (hio_dev_t* dev, void* buf, hio_iolen_t* len, hio_de return -1; } + +#if defined(IPPROTO_SCTP) +static int dev_sck_read_sctp_sp (hio_dev_t* dev, void* buf, hio_iolen_t* len, hio_devaddr_t* srcaddr) +{ + hio_t* hio = dev->hio; + hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev; + hio_scklen_t srcaddrlen; + ssize_t x; + int msg_flags; + struct sctp_sndrcvinfo sri; + + srcaddrlen = HIO_SIZEOF(rdev->remoteaddr); +/* +struct sctp_sndrcvinfo { + __u16 sinfo_stream; + __u16 sinfo_ssn; + __u16 sinfo_flags; + __u32 sinfo_ppid; + __u32 sinfo_context; + __u32 sinfo_timetolive; + __u32 sinfo_tsn; + __u32 sinfo_cumtsn; + sctp_assoc_t sinfo_assoc_id; +}; +*/ + /* msg_flags -> flags such as MSG_NOTIFICATION or MSG_EOR */ + x = sctp_recvmsg(rdev->hnd, buf, *len, (struct sockaddr*)&rdev->remoteaddr, &srcaddrlen, &sri, &msg_flags); + if (x <= -1) + { + int eno = errno; + if (eno == EINPROGRESS || eno == EWOULDBLOCK || eno == EAGAIN) return 0; /* no data available */ + if (eno == EINTR) return 0; + + hio_seterrwithsyserr (hio, 0, eno); + + HIO_DEBUG2 (hio, "SCK(%p) - recvfrom failure - %hs", rdev, strerror(eno)); + return -1; + } + + srcaddr->ptr = &rdev->remoteaddr; + srcaddr->len = srcaddrlen; + + *len = x; + //*sid = sri.sinfo_stream; /* stream number */ + return 1; +} +#endif + /* ------------------------------------------------------------------------------ */ static int dev_sck_write_stateful (hio_dev_t* dev, const void* data, hio_iolen_t* len, const hio_devaddr_t* dstaddr) @@ -652,7 +720,7 @@ static int dev_sck_write_stateful (hio_dev_t* dev, const void* data, hio_iolen_t { /* it's a writing finish indicator. close the writing end of * the socket, probably leaving it in the half-closed state */ - if ((x = SSL_shutdown((SSL*)rdev->ssl)) == -1) + if ((x = SSL_shutdown((SSL*)rdev->ssl)) <= -1) { set_ssl_error (hio, SSL_get_error((SSL*)rdev->ssl, x)); return -1; @@ -682,7 +750,7 @@ static int dev_sck_write_stateful (hio_dev_t* dev, const void* data, hio_iolen_t /* the write handler for a stream device must handle a zero-length * writing request specially. it's a writing finish indicator. close * the writing end of the socket, probably leaving it in the half-closed state */ - if (shutdown(rdev->hnd, SHUT_WR) == -1) + if (shutdown(rdev->hnd, SHUT_WR) <= -1) { hio_seterrwithsyserr (hio, 0, errno); return -1; @@ -698,7 +766,7 @@ static int dev_sck_write_stateful (hio_dev_t* dev, const void* data, hio_iolen_t flags |= MSG_NOSIGNAL; #endif x = send(rdev->hnd, data, *len, flags); - if (x == -1) + if (x <= -1) { if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */ if (errno == EINTR) return 0; @@ -729,7 +797,7 @@ static int dev_sck_writev_stateful (hio_dev_t* dev, const hio_iovec_t* iov, hio_ { /* it's a writing finish indicator. close the writing end of * the socket, probably leaving it in the half-closed state */ - if ((x = SSL_shutdown((SSL*)rdev->ssl)) == -1) + if ((x = SSL_shutdown((SSL*)rdev->ssl)) <= -1) { set_ssl_error (hio, SSL_get_error((SSL*)rdev->ssl, x)); return -1; @@ -767,7 +835,7 @@ static int dev_sck_writev_stateful (hio_dev_t* dev, const hio_iovec_t* iov, hio_ { /* it's a writing finish indicator. close the writing end of * the socket, probably leaving it in the half-closed state */ - if (shutdown(rdev->hnd, SHUT_WR) == -1) + if (shutdown(rdev->hnd, SHUT_WR) <= -1) { hio_seterrwithsyserr (hio, 0, errno); return -1; @@ -792,7 +860,7 @@ static int dev_sck_writev_stateful (hio_dev_t* dev, const hio_iovec_t* iov, hio_ #else x = writev(rdev->hnd, (const struct iovec*)iov, *iovcnt); #endif - if (x == -1) + if (x <= -1) { if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */ if (errno == EINTR) return 0; @@ -883,6 +951,42 @@ static int dev_sck_writev_bpf (hio_dev_t* dev, const hio_iovec_t* iov, hio_iolen return -1; } +/* ------------------------------------------------------------------------------ */ +#if defined(IPPROTO_SCTPXX) +static int dev_sck_write_sctp_sp (hio_dev_t* dev, const void* data, hio_iolen_t* len, const hio_devaddr_t* dstaddr) +{ + hio_t* hio = dev->hio; + hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev; + ssize_t x; + + x = sctp_sendmsg(rdev->hnd, + data, *len, dstaddr->ptr, dstaddr->len, + sir->info_ppid, /* ppid - opaque */ + 0, /* flags (e.g. SCTP_UNORDERED, SCTP_EOF, SCT_ABORT, ...) */, + sid, /* stream number */ + 0, /* ttl */ + 0 /* context*/); + if (x <= -1) + { + if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */ + if (errno == EINTR) return 0; + hio_seterrwithsyserr (hio, 0, errno); + return -1; + } + + *len = x; + return 1; +} + +static int dev_sck_writev_sctp_sp (hio_dev_t* dev, const hio_iovec_t* iov, hio_iolen_t* iovcnt, const hio_devaddr_t* dstaddr) +{ + /* TODO: use sctp_sendv? */ + hio_t* hio = dev->hio; + hio_dev_sck_t* rdev = (hio_dev_sck_t*)dev; + hio_seterrwithsyserr (hio, 0, HIO_ENOIMPL); + return -1; +} +#endif /* ------------------------------------------------------------------------------ */ @@ -901,7 +1005,7 @@ static int dev_sck_sendfile_stateful (hio_dev_t* dev, hio_syshnd_t in_fd, hio_fo { /* it's a writing finish indicator. close the writing end of * the socket, probably leaving it in the half-closed state */ - if ((x = SSL_shutdown((SSL*)rdev->ssl)) == -1) + if ((x = SSL_shutdown((SSL*)rdev->ssl)) <= -1) { set_ssl_error (hio, SSL_get_error((SSL*)rdev->ssl, x)); return -1; @@ -930,7 +1034,7 @@ static int dev_sck_sendfile_stateful (hio_dev_t* dev, hio_syshnd_t in_fd, hio_fo /* the write handler for a stream device must handle a zero-length * writing request specially. it's a writing finish indicator. close * the writing end of the socket, probably leaving it in the half-closed state */ - if (shutdown(rdev->hnd, SHUT_WR) == -1) + if (shutdown(rdev->hnd, SHUT_WR) <= -1) { hio_seterrwithsyserr (hio, 0, errno); return -1; @@ -944,7 +1048,7 @@ static int dev_sck_sendfile_stateful (hio_dev_t* dev, hio_syshnd_t in_fd, hio_fo #if defined(HAVE_SENDFILE) /* TODO: cater for other systems */ x = sendfile(rdev->hnd, in_fd, &foff, *len); - if (x == -1) + if (x <= -1) { if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */ if (errno == EINTR) return 0; @@ -1072,7 +1176,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg) { /* TODO: should i make it into bnd->options? HIO_DEV_SCK_BIND_IPV6ONLY? applicable to ipv6 though. */ int v = 1; - if (setsockopt(rdev->hnd, IPPROTO_IPV6, IPV6_V6ONLY, &v, HIO_SIZEOF(v)) == -1) + if (setsockopt(rdev->hnd, IPPROTO_IPV6, IPV6_V6ONLY, &v, HIO_SIZEOF(v)) <= -1) { if (!(bnd->options & HIO_DEV_SCK_BIND_IGNERR)) { @@ -1085,7 +1189,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg) if (bnd->options & HIO_DEV_SCK_BIND_BROADCAST) { int v = 1; - if (setsockopt(rdev->hnd, SOL_SOCKET, SO_BROADCAST, &v, HIO_SIZEOF(v)) == -1) + if (setsockopt(rdev->hnd, SOL_SOCKET, SO_BROADCAST, &v, HIO_SIZEOF(v)) <= -1) { /* not affected by HIO_DEV_SCK_BIND_IGNERR */ hio_seterrbfmtwithsyserr (hio, 0, errno, "unable to set SO_BROADCAST"); @@ -1097,7 +1201,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg) { #if defined(SO_REUSEADDR) int v = 1; - if (setsockopt(rdev->hnd, SOL_SOCKET, SO_REUSEADDR, &v, HIO_SIZEOF(v)) == -1) + if (setsockopt(rdev->hnd, SOL_SOCKET, SO_REUSEADDR, &v, HIO_SIZEOF(v)) <= -1) { if (!(bnd->options & HIO_DEV_SCK_BIND_IGNERR)) { @@ -1117,7 +1221,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg) { #if defined(SO_REUSEPORT) int v = 1; - if (setsockopt(rdev->hnd, SOL_SOCKET, SO_REUSEPORT, &v, HIO_SIZEOF(v)) == -1) + if (setsockopt(rdev->hnd, SOL_SOCKET, SO_REUSEPORT, &v, HIO_SIZEOF(v)) <= -1) { if (!(bnd->options & HIO_DEV_SCK_BIND_IGNERR)) { @@ -1137,7 +1241,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg) { #if defined(IP_TRANSPARENT) int v = 1; - if (setsockopt(rdev->hnd, SOL_IP, IP_TRANSPARENT, &v, HIO_SIZEOF(v)) == -1) + if (setsockopt(rdev->hnd, SOL_IP, IP_TRANSPARENT, &v, HIO_SIZEOF(v)) <= -1) { hio_seterrbfmtwithsyserr (hio, 0, errno, "unable to set IP_TRANSPARENT"); return -1; @@ -1205,7 +1309,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg) } x = bind(rdev->hnd, (struct sockaddr*)&bnd->localaddr, hio_skad_size(&bnd->localaddr)); - if (x == -1) + if (x <= -1) { hio_seterrwithsyserr (hio, 0, errno); #if defined(USE_SSL) @@ -1240,7 +1344,7 @@ static int dev_sck_ioctl (hio_dev_t* dev, int cmd, void* arg) return -1; } - if (!IS_STATEFUL(rdev)) + if (!sck_type_map[rdev->type].connectable) { hio_seterrbfmt (hio, HIO_EPERM, "disallowed to connect stateless device"); return -1; @@ -1381,14 +1485,14 @@ fcntl (rdev->hnd, F_SETFL, flags | O_NONBLOCK); return -1; } - if (!IS_STATEFUL(rdev)) + if (!sck_type_map[rdev->type].listenable) { hio_seterrbfmt (hio, HIO_EPERM, "disallowed to listen on stateless device"); return -1; } x = listen(rdev->hnd, lstn->backlogs); - if (x == -1) + if (x <= -1) { hio_seterrwithsyserr (hio, 0, errno); return -1; @@ -1492,7 +1596,7 @@ static int harvest_outgoing_connection (hio_dev_sck_t* rdev) HIO_ASSERT (hio, !(rdev->state & HIO_DEV_SCK_CONNECTED)); len = HIO_SIZEOF(errcode); - if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1) + if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) <= -1) { hio_seterrbfmtwithsyserr (hio, 0, errno, "unable to get SO_ERROR"); return -1; @@ -1606,11 +1710,11 @@ static int make_accepted_client_connection (hio_dev_sck_t* rdev, hio_syshnd_t cl clidev->type = clisck_type; HIO_ASSERT (hio, clidev->hnd == clisck); - clidev->dev_cap |= HIO_DEV_CAP_IN | HIO_DEV_CAP_OUT | HIO_DEV_CAP_STREAM; + clidev->dev_cap |= HIO_DEV_CAP_IN | HIO_DEV_CAP_OUT | sck_type_map[clisck_type].extra_dev_cap; clidev->remoteaddr = *remoteaddr; addrlen = HIO_SIZEOF(clidev->localaddr); - if (getsockname(clisck, (struct sockaddr*)&clidev->localaddr, &addrlen) == -1) clidev->localaddr = rdev->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 @@ -1618,7 +1722,7 @@ static int make_accepted_client_connection (hio_dev_sck_t* rdev, hio_syshnd_t cl * the address of the local socket. In this case, it should * be same as the result of getsockname(). */ addrlen = HIO_SIZEOF(clidev->orgdstaddr); - if (getsockopt(clisck, SOL_IP, SO_ORIGINAL_DST, &clidev->orgdstaddr, &addrlen) == -1) clidev->orgdstaddr = rdev->localaddr; + if (getsockopt(clisck, SOL_IP, SO_ORIGINAL_DST, &clidev->orgdstaddr, &addrlen) <= -1) clidev->orgdstaddr = rdev->localaddr; #else clidev->orgdstaddr = rdev->localaddr; #endif @@ -1761,7 +1865,7 @@ static int dev_evcb_sck_ready_stateful (hio_dev_t* dev, int events) hio_scklen_t len; len = HIO_SIZEOF(errcode); - if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1) + if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) <= -1) { /* the error number is set to the socket error code. * errno resulting from getsockopt() doesn't reflect the actual @@ -1945,7 +2049,7 @@ static int dev_evcb_sck_ready_stateless (hio_dev_t* dev, int events) hio_scklen_t len; len = HIO_SIZEOF(errcode); - if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1) + if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) <= -1) { /* the error number is set to the socket error code. * errno resulting from getsockopt() doesn't reflect the actual @@ -2020,7 +2124,7 @@ static int dev_evcb_sck_ready_qx (hio_dev_t* dev, int events) hio_scklen_t len; len = HIO_SIZEOF(errcode); - if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1) + if (getsockopt(rdev->hnd, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) <= -1) { /* the error number is set to the socket error code. * errno resulting from getsockopt() doesn't reflect the actual diff --git a/hio/lib/utl-str.c b/hio/lib/utl-str.c index 6c3f0e1..a5d5316 100644 --- a/hio/lib/utl-str.c +++ b/hio/lib/utl-str.c @@ -38,6 +38,24 @@ +hio_oow_t hio_count_ucstr (const hio_uch_t* str) +{ + const hio_uch_t* ptr = str; + while (*ptr != '\0') ptr++; + return ptr - str; +} + + +hio_oow_t hio_count_bcstr (const hio_bch_t* str) +{ + const hio_bch_t* ptr = str; + while (*ptr != '\0') ptr++; + return ptr - str; +} + + + + int hio_equal_uchars (const hio_uch_t* str1, const hio_uch_t* str2, hio_oow_t len) { hio_oow_t i; @@ -208,6 +226,101 @@ int hio_comp_bcstr (const hio_bch_t* str1, const hio_bch_t* str2, int ignorecase + hio_oow_t hio_concat_uchars_to_ucstr (hio_uch_t* buf, hio_oow_t bsz, const hio_uch_t* str, hio_oow_t len) +{ + hio_uch_t* p, * p2; + const hio_uch_t* end; + hio_oow_t blen; + + blen = hio_count_ucstr(buf); + if (blen >= bsz) return blen; /* something wrong */ + + p = buf + blen; + p2 = buf + bsz - 1; + + end = str + len; + + while (p < p2) + { + if (str >= end) break; + *p++ = *str++; + } + + if (bsz > 0) *p = '\0'; + return p - buf; +} + + hio_oow_t hio_concat_bchars_to_bcstr (hio_bch_t* buf, hio_oow_t bsz, const hio_bch_t* str, hio_oow_t len) +{ + hio_bch_t* p, * p2; + const hio_bch_t* end; + hio_oow_t blen; + + blen = hio_count_bcstr(buf); + if (blen >= bsz) return blen; /* something wrong */ + + p = buf + blen; + p2 = buf + bsz - 1; + + end = str + len; + + while (p < p2) + { + if (str >= end) break; + *p++ = *str++; + } + + if (bsz > 0) *p = '\0'; + return p - buf; +} + + + + hio_oow_t hio_concat_ucstr (hio_uch_t* buf, hio_oow_t bsz, const hio_uch_t* str) +{ + hio_uch_t* p, * p2; + hio_oow_t blen; + + blen = hio_count_ucstr(buf); + if (blen >= bsz) return blen; /* something wrong */ + + p = buf + blen; + p2 = buf + bsz - 1; + + while (p < p2) + { + if (*str == '\0') break; + *p++ = *str++; + } + + if (bsz > 0) *p = '\0'; + return p - buf; +} + + hio_oow_t hio_concat_bcstr (hio_bch_t* buf, hio_oow_t bsz, const hio_bch_t* str) +{ + hio_bch_t* p, * p2; + hio_oow_t blen; + + blen = hio_count_bcstr(buf); + if (blen >= bsz) return blen; /* something wrong */ + + p = buf + blen; + p2 = buf + bsz - 1; + + while (p < p2) + { + if (*str == '\0') break; + *p++ = *str++; + } + + if (bsz > 0) *p = '\0'; + return p - buf; +} + + + + void hio_fill_uchars (hio_uch_t* dst, hio_uch_t ch, hio_oow_t len) { @@ -225,24 +338,6 @@ void hio_fill_bchars (hio_bch_t* dst, hio_bch_t ch, hio_oow_t len) -hio_oow_t hio_count_ucstr (const hio_uch_t* str) -{ - const hio_uch_t* ptr = str; - while (*ptr != '\0') ptr++; - return ptr - str; -} - - -hio_oow_t hio_count_bcstr (const hio_bch_t* str) -{ - const hio_bch_t* ptr = str; - while (*ptr != '\0') ptr++; - return ptr - str; -} - - - - hio_uch_t* hio_find_uchar (const hio_uch_t* ptr, hio_oow_t len, hio_uch_t c) { const hio_uch_t* end; @@ -903,8 +998,6 @@ exit_point: - - hio_intmax_t hio_uchars_to_intmax (const hio_uch_t* str, hio_oow_t len, int option, const hio_uch_t** endptr, int* is_sober) { diff --git a/hio/lib/utl-str.c.m4 b/hio/lib/utl-str.c.m4 index 1726036..581640b 100644 --- a/hio/lib/utl-str.c.m4 +++ b/hio/lib/utl-str.c.m4 @@ -37,6 +37,18 @@ dnl --------------------------------------------------------------------------- changequote(`[[', `]]') +dnl --------------------------------------------------------------------------- +define([[fn_count_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2) +hio_oow_t fn_name (const char_type* str) +{ + const char_type* ptr = str; + while (*ptr != '\0') ptr++; + return ptr - str; +} +]]) +fn_count_cstr(hio_count_ucstr, hio_uch_t) +fn_count_cstr(hio_count_bcstr, hio_bch_t) + dnl --------------------------------------------------------------------------- define([[fn_equal_chars]], [[ define([[fn_name]], $1) define([[char_type]], $2) int fn_name (const char_type* str1, const char_type* str2, hio_oow_t len) @@ -132,6 +144,62 @@ int fn_name (const char_type* str1, const char_type* str2, int ignorecase) fn_comp_cstr(hio_comp_ucstr, hio_uch_t, hio_uchu_t, hio_to_uch_lower) fn_comp_cstr(hio_comp_bcstr, hio_bch_t, hio_bchu_t, hio_to_bch_lower) +dnl --------------------------------------------------------------------------- +define([[fn_concat_chars_to_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2) dnl: $3 count_str +hio_oow_t fn_name (char_type* buf, hio_oow_t bsz, const char_type* str, hio_oow_t len) +{ + char_type* p, * p2; + const char_type* end; + hio_oow_t blen; + + blen = $3(buf); + if (blen >= bsz) return blen; /* something wrong */ + + p = buf + blen; + p2 = buf + bsz - 1; + + end = str + len; + + while (p < p2) + { + if (str >= end) break; + *p++ = *str++; + } + + if (bsz > 0) *p = '\0'; + return p - buf; +} +]]) +fn_concat_chars_to_cstr(hio_concat_uchars_to_ucstr, hio_uch_t, hio_count_ucstr) +fn_concat_chars_to_cstr(hio_concat_bchars_to_bcstr, hio_bch_t, hio_count_bcstr) + +dnl --------------------------------------------------------------------------- +define([[fn_concat_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2) dnl: $3 count_str +hio_oow_t fn_name (char_type* buf, hio_oow_t bsz, const char_type* str) +{ + char_type* p, * p2; + hio_oow_t blen; + + blen = $3(buf); + if (blen >= bsz) return blen; /* something wrong */ + + p = buf + blen; + p2 = buf + bsz - 1; + + while (p < p2) + { + if (*str == '\0') break; + *p++ = *str++; + } + + if (bsz > 0) *p = '\0'; + return p - buf; +} +]]) +fn_concat_cstr(hio_concat_ucstr, hio_uch_t, hio_count_ucstr) +fn_concat_cstr(hio_concat_bcstr, hio_bch_t, hio_count_bcstr) + + dnl --------------------------------------------------------------------------- define([[fn_fill_chars]], [[ define([[fn_name]], $1) define([[char_type]], $2) void fn_name (char_type* dst, char_type ch, hio_oow_t len) @@ -143,18 +211,6 @@ void fn_name (char_type* dst, char_type ch, hio_oow_t len) fn_fill_chars(hio_fill_uchars, hio_uch_t) fn_fill_chars(hio_fill_bchars, hio_bch_t) -dnl --------------------------------------------------------------------------- -define([[fn_count_cstr]], [[ define([[fn_name]], $1) define([[char_type]], $2) -hio_oow_t fn_name (const char_type* str) -{ - const char_type* ptr = str; - while (*ptr != '\0') ptr++; - return ptr - str; -} -]]) -fn_count_cstr(hio_count_ucstr, hio_uch_t) -fn_count_cstr(hio_count_bcstr, hio_bch_t) - dnl --------------------------------------------------------------------------- define([[fn_find_char]], [[ define([[fn_name]], $1) define([[char_type]], $2) char_type* fn_name (const char_type* ptr, hio_oow_t len, char_type c) @@ -504,8 +560,6 @@ exit_point: fn_split_cstr(hio_split_ucstr, hio_uch_t, hio_is_uch_space, hio_copy_ucstr_unlimited) fn_split_cstr(hio_split_bcstr, hio_bch_t, hio_is_bch_space, hio_copy_bcstr_unlimited) - - dnl --------------------------------------------------------------------------- define([[fn_chars_to_int]], [[ define([[fn_name]], $1) define([[char_type]], $2) define([[int_type]], $3) int_type fn_name (const char_type* str, hio_oow_t len, int option, const char_type** endptr, int* is_sober)