diff --git a/stio/lib/main.c b/stio/lib/main.c index 5ff8e01..7f454ec 100644 --- a/stio/lib/main.c +++ b/stio/lib/main.c @@ -38,6 +38,9 @@ #include #include +#include +#include + /* ========================================================================= */ struct mmgr_stat_t @@ -191,12 +194,12 @@ printf ("DISABLING READING..............................\n"); /* ========================================================================= */ -static int arp_on_read (stio_dev_arp_t* arp, const void* buf, stio_len_t len, stio_sckadr_t* ) +static int sck_on_read (stio_dev_sck_t* dev, const void* buf, stio_len_t len, const stio_sckadr_t* srcadr) { return 0; } -static int arp_on_write (stio_dev_arp_t* arp, stio_len_t wrlen, void* wrctx) +static int sck_on_write (stio_dev_sck_t* dev, stio_len_t wrlen, void* wrctx) { return 0; } @@ -216,14 +219,14 @@ int main () stio_t* stio; stio_dev_udp_t* udp; - stio_dev_arp_t* arp; + stio_dev_sck_t* sck; stio_dev_tcp_t* tcp[2]; struct sockaddr_in sin; struct sigaction sigact; stio_dev_tcp_connect_t tcp_conn; stio_dev_tcp_listen_t tcp_lstn; stio_dev_tcp_make_t tcp_make; - stio_dev_arp_make_t arp_make; + stio_dev_sck_make_t sck_make; tcp_server_t* ts; stio = stio_open (&mmgr, 0, 512, STIO_NULL); @@ -316,16 +319,61 @@ int main () } - memset (&arp_make, 0, STIO_SIZEOF(arp_make)); - arp_make.on_write = arp_on_write; - arp_make.on_read = arp_on_read; - arp = stio_dev_arp_make (stio, 0, &arp_make); - if (!arp) + memset (&sck_make, 0, STIO_SIZEOF(sck_make)); + sck_make.type = STIO_DEV_SCK_ARP; + //sck_make.type = STIO_DEV_SCK_ARP_DGRAM; + sck_make.on_write = sck_on_write; + sck_make.on_read = sck_on_read; + sck = stio_dev_sck_make (stio, 0, &sck_make); + if (!sck) { - printf ("Cannot make arp\n"); + printf ("Cannot make socket device\n"); goto oops; } +#if 1 +{ + stio_etharp_pkt_t etharp; + struct sockaddr_ll sll; + stio_adr_t adr; + + memset (&sll, 0, sizeof(sll)); + adr.ptr = &sll; + adr.len = sizeof(sll); + sll.sll_family = AF_PACKET; + //sll.sll_protocol = STIO_CONST_HTON16(0x0003); /* P_ALL */ + sll.sll_protocol = STIO_CONST_HTON16(STIO_ETHHDR_PROTO_ARP); + sll.sll_hatype = STIO_CONST_HTON16(STIO_ARPHDR_HTYPE_ETH); + sll.sll_halen = STIO_ETHADR_LEN; + memcpy (sll.sll_addr, "\xFF\xFF\xFF\xFF\xFF\xFF", sll.sll_halen); + sll.sll_ifindex = if_nametoindex ("enp0s25.3"); + + /* if unicast ... */ + //sll.sll_pkttype = PACKET_OTHERHOST; + sll.sll_pkttype = PACKET_BROADCAST; + + 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); + 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.opcode = STIO_CONST_HTON16(STIO_ARPHDR_OPCODE_REQUEST); + + memcpy (etharp.arppld.sha, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADR_LEN); + + if (stio_dev_sck_write (sck, ðarp, sizeof(etharp), NULL, &adr) <= -1) + //if (stio_dev_sck_write (sck, ðarp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, &adr) <= -1) + { + printf ("CANNOT WRITE ARP...\n"); + } +} +#endif + stio_loop (stio); g_stio = STIO_NULL; diff --git a/stio/lib/stio-arp.c b/stio/lib/stio-arp.c index 4424d8a..90248fe 100644 --- a/stio/lib/stio-arp.c +++ b/stio/lib/stio-arp.c @@ -34,6 +34,7 @@ #include #include +#if 0 /* ======================================================================== */ static int arp_make (stio_dev_t* dev, void* ctx) @@ -179,3 +180,14 @@ stio_dev_arp_t* stio_dev_arp_make (stio_t* stio, stio_size_t xtnsize, const stio { 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 index b9f2900..12c6f5f 100644 --- a/stio/lib/stio-arp.h +++ b/stio/lib/stio-arp.h @@ -31,8 +31,60 @@ #include typedef struct stio_dev_arp_t stio_dev_arp_t; +#define STIO_ETHHDR_PROTO_IP4 0x0800 +#define STIO_ETHHDR_PROTO_ARP 0x0806 -typedef int (*stio_dev_arp_on_read_t) (stio_dev_arp_t* dev, const void* data, stio_len_t len); +#define STIO_ARPHDR_OPCODE_REQUEST 1 +#define STIO_ARPHDR_OPCODE_REPLY 2 + +#define STIO_ARPHDR_HTYPE_ETH 0x0001 +#define STIO_ARPHDR_PTYPE_IP4 0x0800 + +#define STIO_ETHADR_LEN 6 +#define STIO_IP4ADR_LEN 4 + +#pragma pack(push) +#pragma pack(1) +struct stio_ethhdr_t +{ + stio_uint8_t dest[STIO_ETHADR_LEN]; + stio_uint8_t source[STIO_ETHADR_LEN]; + stio_uint16_t proto; +}; +typedef struct stio_ethhdr_t stio_ethhdr_t; + +struct stio_arphdr_t +{ + stio_uint16_t htype; /* hardware type (ethernet: 0x0001) */ + stio_uint16_t ptype; /* protocol type (ipv4: 0x0800) */ + stio_uint8_t hlen; /* hardware address length (ethernet: 6) */ + stio_uint8_t plen; /* protocol address length (ipv4 :4) */ + stio_uint16_t opcode; /* operation code */ +}; +typedef struct stio_arphdr_t stio_arphdr_t; + +/* arp payload for ipv4 over ethernet */ +struct 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 */ +}; +typedef struct stio_etharp_t stio_etharp_t; + +struct stio_etharp_pkt_t +{ + stio_ethhdr_t ethhdr; + stio_arphdr_t arphdr; + stio_etharp_t arppld; +}; +typedef struct stio_etharp_pkt_t stio_etharp_pkt_t; +#pragma pack(pop) + + +#if 0 +typedef int (*stio_dev_arp_on_read_t) (stio_dev_arp_t* dev, stio_pkt_arp_t* pkt, stio_len_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; @@ -50,18 +102,33 @@ struct stio_dev_arp_t 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 diff --git a/stio/lib/stio-pro.c b/stio/lib/stio-pro.c index 606db29..e2fb117 100644 --- a/stio/lib/stio-pro.c +++ b/stio/lib/stio-pro.c @@ -154,6 +154,7 @@ static int pro_read (stio_dev_t* dev, void* buf, stio_len_t* len) static int pro_write (stio_dev_t* dev, const void* data, stio_len_t* len) { + return -1; } static stio_syshnd_t pro_getsyshnd (stio_dev_t* dev) @@ -204,13 +205,13 @@ printf ("PRO READY...%p\n", dev); return 1; /* the device is ok. carry on reading or writing */ } -static int pro_on_read (stio_dev_t* dev, const void* data, stio_len_t len) +static int pro_on_read (stio_dev_t* dev, const void* data, stio_len_t len, const stio_adr_t* srcadr) { stio_dev_pro_t* pro = (stio_dev_pro_t*)dev; return pro->on_read (pro, data, len); } -static int pro_on_write (stio_dev_t* dev, void* wrctx) +static int pro_on_write (stio_dev_t* dev, void* wrctx, const stio_adr_t* dstadr) { stio_dev_pro_t* pro = (stio_dev_pro_t*)dev; return pro->on_write (pro, wrctx); diff --git a/stio/lib/stio-sck.c b/stio/lib/stio-sck.c index 3e44fd7..3cb03da 100644 --- a/stio/lib/stio-sck.c +++ b/stio/lib/stio-sck.c @@ -35,7 +35,7 @@ #include #include -/* ------------------------------------------------------------------------ */ +/* ========================================================================= */ void stio_closeasyncsck (stio_t* stio, stio_sckhnd_t sck) { #if defined(_WIN32) @@ -108,3 +108,175 @@ int stio_getsckadrinfo (stio_t* stio, const stio_sckadr_t* addr, stio_scklen_t* stio->errnum = STIO_EINVAL; return -1; } + + +/* ========================================================================= */ +struct sck_type_map_t +{ + int domain; + int type; + int proto; +} sck_type_map[] = +{ + { AF_INET, SOCK_STREAM, 0 }, + { AF_INET6, SOCK_STREAM, 0 }, + { AF_INET, SOCK_DGRAM, 0 }, + { AF_INET6, SOCK_DGRAM, 0 }, + + { AF_PACKET, SOCK_RAW, STIO_CONST_HTON16(0x0806) }, + { AF_PACKET, SOCK_DGRAM, STIO_CONST_HTON16(0x0806) } +}; + +static int dev_sck_make (stio_dev_t* dev, void* ctx) +{ + stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev; + stio_dev_sck_make_t* arg = (stio_dev_sck_make_t*)ctx; + + + if (arg->type < 0 && arg->type >= STIO_COUNTOF(sck_type_map)) + { + dev->stio->errnum = STIO_EINVAL; + return -1; + } + + rdev->sck = stio_openasyncsck (dev->stio, sck_type_map[arg->type].domain, sck_type_map[arg->type].type, sck_type_map[arg->type].proto); + if (rdev->sck == STIO_SCKHND_INVALID) goto oops; + + rdev->dev_capa = STIO_DEV_CAPA_IN | STIO_DEV_CAPA_OUT; + rdev->on_write = arg->on_write; + rdev->on_read = arg->on_read; + return 0; + +oops: + if (rdev->sck != STIO_SCKHND_INVALID) + { + stio_closeasyncsck (rdev->stio, rdev->sck); + rdev->sck = STIO_SCKHND_INVALID; + } + return -1; +} + +static void dev_sck_kill (stio_dev_t* dev) +{ + stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev; + if (rdev->sck != STIO_SCKHND_INVALID) + { + stio_closeasyncsck (rdev->stio, rdev->sck); + rdev->sck = STIO_SCKHND_INVALID; + } +} + +static stio_syshnd_t dev_sck_getsyshnd (stio_dev_t* dev) +{ + stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev; + return (stio_syshnd_t)rdev->sck; +} + +static int dev_sck_read (stio_dev_t* dev, void* buf, stio_len_t* len, stio_adr_t* srcadr) +{ + stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev; + stio_scklen_t srcadrlen; + int x; + + srcadrlen = srcadr->len; + x = recvfrom (rdev->sck, buf, *len, 0, srcadr->ptr, &srcadrlen); + if (x <= -1) + { + if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0; /* no data available */ + if (errno == EINTR) return 0; + rdev->stio->errnum = stio_syserrtoerrnum(errno); + return -1; + } + + srcadr->len = srcadrlen; + *len = x; + return 1; +} + +static int dev_sck_write (stio_dev_t* dev, const void* data, stio_len_t* len, const stio_adr_t* dstadr) +{ + stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev; + ssize_t x; + + x = sendto (rdev->sck, data, *len, 0, dstadr->ptr, dstadr->len); + if (x <= -1) + { + if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0; /* no data can be written */ + if (errno == EINTR) return 0; + rdev->stio->errnum = stio_syserrtoerrnum(errno); + return -1; + } + + *len = x; + return 1; +} + + +static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg) +{ + return 0; +} + +static stio_dev_mth_t dev_mth_sck = +{ + dev_sck_make, + dev_sck_kill, + dev_sck_getsyshnd, + + dev_sck_read, + dev_sck_write, + dev_sck_ioctl, /* ioctl */ +}; + + +/* ========================================================================= */ + +static int dev_evcb_sck_ready (stio_dev_t* dev, int events) +{ +/* TODO: ... */ + if (events & STIO_DEV_EVENT_ERR) printf ("SCK READY ERROR.....\n"); + if (events & STIO_DEV_EVENT_HUP) printf ("SCK READY HANGUP.....\n"); + if (events & STIO_DEV_EVENT_PRI) printf ("SCK READY PRI.....\n"); + if (events & STIO_DEV_EVENT_IN) printf ("SCK READY IN.....\n"); + if (events & STIO_DEV_EVENT_OUT) printf ("SCK READY OUT.....\n"); + + + return 1; /* the device is ok. carry on reading or writing */ +} + +static int dev_evcb_sck_on_read (stio_dev_t* dev, const void* data, stio_len_t dlen, const stio_adr_t* adr) +{ +printf ("dATA received %d bytes\n", (int)dlen); + return 0; + +} + +static int dev_evcb_sck_on_write (stio_dev_t* dev, stio_len_t wrlen, void* wrctx, const stio_adr_t* adr) +{ + return 0; + +} + +static stio_dev_evcb_t dev_evcb_sck = +{ + dev_evcb_sck_ready, + dev_evcb_sck_on_read, + dev_evcb_sck_on_write +}; + +/* ======================================================================== */ + +stio_dev_sck_t* stio_dev_sck_make (stio_t* stio, stio_size_t xtnsize, const stio_dev_sck_make_t* data) +{ + return (stio_dev_sck_t*)stio_makedev (stio, STIO_SIZEOF(stio_dev_sck_t) + xtnsize, &dev_mth_sck, &dev_evcb_sck, (void*)data); +} + +int stio_dev_sck_write (stio_dev_sck_t* dev, const void* data, stio_len_t dlen, void* wrctx, const stio_adr_t* dstadr) +{ + return stio_dev_write ((stio_dev_t*)dev, data, dlen, wrctx, dstadr); +} + +int stio_dev_sck_timedwrite (stio_dev_sck_t* dev, const void* data, stio_len_t dlen, const stio_ntime_t* tmout, void* wrctx, const stio_adr_t* dstadr) +{ + return stio_dev_write ((stio_dev_t*)dev, data, dlen, wrctx, dstadr); +} diff --git a/stio/lib/stio-sck.h b/stio/lib/stio-sck.h index 435cc0b..41ad259 100644 --- a/stio/lib/stio-sck.h +++ b/stio/lib/stio-sck.h @@ -72,6 +72,49 @@ typedef struct stio_sckadr_t stio_sckadr_t; typedef int stio_sckfam_t; + +#define STIO_SCK_ETH_PROTO_IP4 0x0800 +#define STIO_SCK_ETH_PROTO_ARP 0x0806 +#define STIO_SCK_ETH_PROTO_8021Q 0x8100 /* 802.1Q VLAN */ +#define STIO_SCK_ETH_PROTO_IP6 0x86DD + +/* ========================================================================= */ + + +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_len_t dlen, const stio_sckadr_t* srcadr); +typedef int (*stio_dev_sck_on_write_t) (stio_dev_sck_t* dev, stio_len_t wrlen, void* wrctx); + +enum stio_dev_sck_type_t +{ + STIO_DEV_SCK_TCP4, + STIO_DEV_SCK_TCP6, + STIO_DEV_SCK_UPD4, + STIO_DEV_SCK_UDP6, + + STIO_DEV_SCK_ARP, + STIO_DEV_SCK_ARP_DGRAM +}; +typedef enum stio_dev_sck_type_t stio_dev_sck_type_t; + +typedef struct stio_dev_sck_make_t stio_dev_sck_make_t; +struct stio_dev_sck_make_t +{ + stio_dev_sck_type_t type; + stio_dev_sck_on_write_t on_write; + stio_dev_sck_on_read_t on_read; +}; + +struct stio_dev_sck_t +{ + STIO_DEV_HEADERS; + stio_sckhnd_t sck; + stio_dev_sck_on_write_t on_write; + stio_dev_sck_on_read_t on_read; +}; + + #ifdef __cplusplus extern "C" { #endif @@ -101,10 +144,37 @@ STIO_EXPORT int stio_getsckadrinfo ( stio_sckfam_t* family ); +/* ========================================================================= */ + +STIO_EXPORT stio_dev_sck_t* stio_dev_sck_make ( + stio_t* stio, + stio_size_t xtnsize, + const stio_dev_sck_make_t* data +); + +STIO_EXPORT int stio_dev_sck_write ( + stio_dev_sck_t* dev, + const void* data, + stio_len_t len, + void* wrctx, + const stio_adr_t* dstadr +); + +STIO_EXPORT int stio_dev_sck_timedwrite ( + stio_dev_sck_t* dev, + const void* data, + stio_len_t len, + const stio_ntime_t* tmout, + void* wrctx, + const stio_adr_t* dstadr +); + #ifdef __cplusplus } #endif + + #endif diff --git a/stio/lib/stio-tcp.c b/stio/lib/stio-tcp.c index b93f3cb..285f445 100644 --- a/stio/lib/stio-tcp.c +++ b/stio/lib/stio-tcp.c @@ -59,7 +59,7 @@ static int tcp_make (stio_dev_t* dev, void* ctx) goto oops; } - tcp->dev_capa = STIO_DEV_CAPA_IN | STIO_DEV_CAPA_OUT | STIO_DEV_CAPA_STREAM; + tcp->dev_capa = STIO_DEV_CAPA_IN | STIO_DEV_CAPA_OUT | STIO_DEV_CAPA_OUT_QUEUED | STIO_DEV_CAPA_STREAM; tcp->on_write = arg->on_write; tcp->on_read = arg->on_read; tcp->tmridx_connect = STIO_TMRIDX_INVALID; @@ -113,7 +113,7 @@ static stio_syshnd_t tcp_getsyshnd (stio_dev_t* dev) return (stio_syshnd_t)tcp->sck; } -static int tcp_read (stio_dev_t* dev, void* buf, stio_len_t* len) +static int tcp_read (stio_dev_t* dev, void* buf, stio_len_t* len, void* src_addr) { stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev; ssize_t x; @@ -131,7 +131,7 @@ static int tcp_read (stio_dev_t* dev, void* buf, stio_len_t* len) return 1; } -static int tcp_write (stio_dev_t* dev, const void* data, stio_len_t* len) +static int tcp_write (stio_dev_t* dev, const void* data, stio_len_t* len, const void* dest_addr) { stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev; ssize_t x; diff --git a/stio/lib/stio-tcp.h b/stio/lib/stio-tcp.h index 5b64839..050b27c 100644 --- a/stio/lib/stio-tcp.h +++ b/stio/lib/stio-tcp.h @@ -159,15 +159,14 @@ static STIO_INLINE int stio_dev_tcp_read (stio_dev_tcp_t* tcp, int enabled) static STIO_INLINE int stio_dev_tcp_write (stio_dev_tcp_t* tcp, const void* data, stio_len_t len, void* wrctx) { - return stio_dev_write ((stio_dev_t*)tcp, data, len, wrctx); + return stio_dev_write ((stio_dev_t*)tcp, data, len, wrctx, STIO_NULL); } static STIO_INLINE int stio_dev_tcp_timedwrite (stio_dev_tcp_t* tcp, const void* data, stio_len_t len, const stio_ntime_t* tmout, void* wrctx) { - return stio_dev_timedwrite ((stio_dev_t*)tcp, data, len, tmout, wrctx); + return stio_dev_timedwrite ((stio_dev_t*)tcp, data, len, tmout, wrctx, STIO_NULL); } - static STIO_INLINE void stio_dev_tcp_halt (stio_dev_tcp_t* tcp) { stio_dev_halt ((stio_dev_t*)tcp); @@ -175,8 +174,8 @@ static STIO_INLINE void stio_dev_tcp_halt (stio_dev_tcp_t* tcp) #else #define stio_dev_tcp_read(tcp,enabled) stio_dev_read((stio_dev_t*)tcp, enabled) -#define stio_dev_tcp_write(tcp,data,len,wrctx) stio_dev_write((stio_dev_t*)tcp, data, len, wrctx) -#define stio_dev_tcp_timedwrite(tcp,data,len,tmout,wrctx) stio_dev_timedwrite((stio_dev_t*)tcp, data, len, tmout, wrctx) +#define stio_dev_tcp_write(tcp,data,len,wrctx) stio_dev_write((stio_dev_t*)tcp, data, len, wrctx, STIO_NULL) +#define stio_dev_tcp_timedwrite(tcp,data,len,tmout,wrctx) stio_dev_timedwrite((stio_dev_t*)tcp, data, len, tmout, wrctx, STIO_NULL) #define stio_dev_tcp_halt(tcp) stio_dev_halt((stio_dev_t*)tcp) #endif diff --git a/stio/lib/stio-udp.c b/stio/lib/stio-udp.c index fec4836..47ff500 100644 --- a/stio/lib/stio-udp.c +++ b/stio/lib/stio-udp.c @@ -82,7 +82,7 @@ static stio_syshnd_t udp_getsyshnd (stio_dev_t* dev) return (stio_syshnd_t)udp->sck; } -static int udp_read (stio_dev_t* dev, void* buf, stio_len_t* len) +static int udp_read (stio_dev_t* dev, void* buf, stio_len_t* len, stio_adr_t* adr) { stio_dev_udp_t* udp = (stio_dev_udp_t*)dev; stio_scklen_t addrlen; @@ -104,7 +104,7 @@ printf ("UDP RECVFROM...\n"); return 1; } -static int udp_write (stio_dev_t* dev, const void* data, stio_len_t* len) +static int udp_write (stio_dev_t* dev, const void* data, stio_len_t* len, const stio_adr_t* adr) { stio_dev_udp_t* udp = (stio_dev_udp_t*)udp; ssize_t x; diff --git a/stio/lib/stio-udp.h b/stio/lib/stio-udp.h index 1bc5e6c..e45b7ce 100644 --- a/stio/lib/stio-udp.h +++ b/stio/lib/stio-udp.h @@ -74,14 +74,14 @@ static STIO_INLINE int stio_dev_udp_read (stio_dev_udp_t* udp, int enabled) return stio_dev_read ((stio_dev_t*)udp, enabled); } -static STIO_INLINE int stio_dev_udp_write (stio_dev_udp_t* udp, const void* data, stio_len_t len, void* wrctx) +static STIO_INLINE int stio_dev_udp_write (stio_dev_udp_t* udp, const void* data, stio_len_t len, void* wrctx, const stio_adr_t* dstadr) { - return stio_dev_write ((stio_dev_t*)udp, data, len, wrctx); + return stio_dev_write ((stio_dev_t*)udp, data, len, wrctx, dstadr); } -static STIO_INLINE int stio_dev_udp_timedwrite (stio_dev_udp_t* udp, const void* data, stio_len_t len, const stio_ntime_t* tmout, void* wrctx) +static STIO_INLINE int stio_dev_udp_timedwrite (stio_dev_udp_t* udp, const void* data, stio_len_t len, const stio_ntime_t* tmout, void* wrctx, const stio_adr_t* dstadr) { - return stio_dev_timedwrite ((stio_dev_t*)udp, data, len, tmout, wrctx); + return stio_dev_timedwrite ((stio_dev_t*)udp, data, len, tmout, wrctx, dstadr); } static STIO_INLINE void stio_dev_udp_halt (stio_dev_udp_t* udp) @@ -91,8 +91,8 @@ static STIO_INLINE void stio_dev_udp_halt (stio_dev_udp_t* udp) #else #define stio_dev_udp_read(udp,enabled) stio_dev_read((stio_dev_t*)udp, enabled) -#define stio_dev_udp_write(udp,data,len,wrctx) stio_dev_write((stio_dev_t*)udp, data, len, wrctx) -#define stio_dev_udp_timedwrite(udp,data,len,tmout,wrctx) stio_dev_timedwrite((stio_dev_t*)udp, data, len, tmout, wrctx) +#define stio_dev_udp_write(udp,data,len,wrctx,dstadr) stio_dev_write((stio_dev_t*)udp, data, len, wrctx, dstadr) +#define stio_dev_udp_timedwrite(udp,data,len,tmout,wrctx,dstadr) stio_dev_timedwrite((stio_dev_t*)udp, data, len, tmout, wrctx, dstadr) #define stio_dev_udp_halt(udp) stio_dev_halt((stio_dev_t*)udp) #endif diff --git a/stio/lib/stio.c b/stio/lib/stio.c index a4bf1a9..64a8e4f 100644 --- a/stio/lib/stio.c +++ b/stio/lib/stio.c @@ -187,7 +187,7 @@ printf ("has urgent data...\n"); send_leftover: ulen = urem; - x = dev->dev_mth->write (dev, uptr, &ulen); + x = dev->dev_mth->write (dev, uptr, &ulen, &q->dstadr); if (x <= -1) { stio_dev_halt (dev); @@ -221,7 +221,7 @@ printf ("has urgent data...\n"); } unlink_wq (stio, q); - y = dev->dev_evcb->on_write (dev, q->olen, q->ctx); + y = dev->dev_evcb->on_write (dev, q->olen, q->ctx, &q->dstadr); STIO_MMGR_FREE (stio->mmgr, q); if (y <= -1) @@ -266,6 +266,7 @@ printf ("has urgent data...\n"); if (dev && stio->revs[i].events & EPOLLIN) { + stio_adr_t srcadr; stio_len_t len; int x; @@ -275,7 +276,7 @@ printf ("has urgent data...\n"); while (1) { len = STIO_COUNTOF(stio->bigbuf); - x = dev->dev_mth->read (dev, stio->bigbuf, &len); + x = dev->dev_mth->read (dev, stio->bigbuf, &len, &srcadr); if (x <= -1) { stio_dev_halt (dev); @@ -297,7 +298,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) <= -1 || + if (dev->dev_evcb->on_read (dev, stio->bigbuf, len, &srcadr) <= -1 || (dev->dev_capa & STIO_DEV_CAPA_OUT_CLOSED)) { /* 1. input ended and its reporting failed or @@ -316,7 +317,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); + y = dev->dev_evcb->on_read (dev, stio->bigbuf, len, &srcadr); if (y <= -1) { stio_dev_halt (dev); @@ -740,7 +741,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); + x = dev->dev_evcb->on_write (dev, -1, q->ctx, &q->dstadr); STIO_ASSERT (q->tmridx == STIO_TMRIDX_INVALID); STIO_WQ_UNLINK(q); @@ -749,7 +750,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_len_t len, const stio_ntime_t* tmout, void* wrctx) +static int __dev_write (stio_dev_t* dev, const void* data, stio_len_t len, const stio_ntime_t* tmout, void* wrctx, const stio_adr_t* dstadr) { const stio_uint8_t* uptr; stio_len_t urem, ulen; @@ -778,7 +779,7 @@ static int __dev_write (stio_dev_t* dev, const void* data, stio_len_t len, const do { ulen = urem; - x = dev->dev_mth->write (dev, data, &ulen); + x = dev->dev_mth->write (dev, data, &ulen, dstadr); if (x <= -1) return -1; else if (x == 0) { @@ -804,24 +805,30 @@ static int __dev_write (stio_dev_t* dev, const void* data, stio_len_t len, const dev->dev_capa |= STIO_DEV_CAPA_OUT_CLOSED; } - if (dev->dev_evcb->on_write (dev, len, wrctx) <= -1) return -1; + if (dev->dev_evcb->on_write (dev, len, wrctx, dstadr) <= -1) return -1; } else { ulen = urem; - x = dev->dev_mth->write (dev, data, &ulen); + x = dev->dev_mth->write (dev, data, &ulen, dstadr); 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) <= -1) return -1; + if (dev->dev_evcb->on_write (dev, ulen, wrctx, dstadr) <= -1) return -1; } return 1; /* written immediately and called on_write callback */ enqueue_data: + if (!(dev->dev_capa & STIO_DEV_CAPA_OUT_QUEUED)) + { + /* writing queuing is not requested. so return failure */ + return -1; + } + /* queue the remaining data*/ - q = (stio_wq_t*)STIO_MMGR_ALLOC (dev->stio->mmgr, STIO_SIZEOF(*q) + urem); + q = (stio_wq_t*)STIO_MMGR_ALLOC (dev->stio->mmgr, STIO_SIZEOF(*q) + (dstadr? dstadr->len: 0) + urem); if (!q) { dev->stio->errnum = STIO_ENOMEM; @@ -831,11 +838,25 @@ enqueue_data: q->tmridx = STIO_TMRIDX_INVALID; q->dev = dev; q->ctx = wrctx; - q->ptr = (stio_uint8_t*)(q + 1); + + if (dstadr) + { + q->dstadr.ptr = (stio_uint8_t*)(q + 1); + q->dstadr.len = dstadr->len; + STIO_MEMCPY (q->dstadr.ptr, dstadr->ptr, dstadr->len); + } + else + { + q->dstadr.ptr = STIO_NULL; + q->dstadr.len = 0; + } + + q->ptr = (stio_uint8_t*)(q + 1) + q->dstadr.len; q->len = urem; q->olen = len; STIO_MEMCPY (q->ptr, uptr, urem); + if (tmout && !stio_isnegtime(tmout)) { stio_tmrjob_t tmrjob; @@ -874,14 +895,14 @@ enqueue_data: return 0; /* request pused to a write queue. */ } -int stio_dev_write (stio_dev_t* dev, const void* data, stio_len_t len, void* wrctx) +int stio_dev_write (stio_dev_t* dev, const void* data, stio_len_t len, void* wrctx, const stio_adr_t* dstadr) { - return __dev_write (dev, data, len, STIO_NULL, wrctx); + return __dev_write (dev, data, len, STIO_NULL, wrctx, dstadr); } -int stio_dev_timedwrite (stio_dev_t* dev, const void* data, stio_len_t len, const stio_ntime_t* tmout, void* wrctx) +int stio_dev_timedwrite (stio_dev_t* dev, const void* data, stio_len_t len, const stio_ntime_t* tmout, void* wrctx, const stio_adr_t* dstadr) { - return __dev_write (dev, data, len, tmout, wrctx); + return __dev_write (dev, data, len, tmout, wrctx, dstadr); } int stio_makesyshndasync (stio_t* stio, stio_syshnd_t hnd) diff --git a/stio/lib/stio.h b/stio/lib/stio.h index f86ca46..c32aee6 100644 --- a/stio/lib/stio.h +++ b/stio/lib/stio.h @@ -48,6 +48,38 @@ struct stio_ntime_t #define STIO_SYSHND_INVALID (-1) #endif + +typedef struct stio_adr_t stio_adr_t; +struct stio_adr_t +{ + void* ptr; + int len; +}; + +#define STIO_CONST_SWAP16(x) \ + ((stio_uint16_t)((((stio_uint16_t)(x) & (stio_uint16_t)0x00ffU) << 8) | \ + (((stio_uint16_t)(x) & (stio_uint16_t)0xff00U) >> 8) )) + +#define STIO_CONST_SWAP32(x) \ + ((stio_uint32_t)((((stio_uint32_t)(x) & (stio_uint32_t)0x000000ffUL) << 24) | \ + (((stio_uint32_t)(x) & (stio_uint32_t)0x0000ff00UL) << 8) | \ + (((stio_uint32_t)(x) & (stio_uint32_t)0x00ff0000UL) >> 8) | \ + (((stio_uint32_t)(x) & (stio_uint32_t)0xff000000UL) >> 24) )) + +#if defined(STIO_ENDIAN_LITTLE) +# define STIO_CONST_NTOH16(x) STIO_CONST_SWAP16(x) +# define STIO_CONST_HTON16(x) STIO_CONST_SWAP16(x) +# define STIO_CONST_NTOH32(x) STIO_CONST_SWAP32(x) +# define STIO_CONST_HTON32(x) STIO_CONST_SWAP32(x) +#elif defined(STIO_ENDIAN_BIG) +# define STIO_CONST_NTOH16(x) +# define STIO_CONST_HTON16(x) +# define STIO_CONST_NTOH32(x) +# define STIO_CONST_HTON32(x) +#else +# error UNKNOWN ENDIAN +#endif + /* ------------------------------------------------------------------------- */ typedef struct stio_t stio_t; typedef struct stio_dev_t stio_dev_t; @@ -112,10 +144,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_len_t* len); + int (*read) (stio_dev_t* dev, void* data, stio_len_t* len, stio_adr_t* srcadr); /* ------------------------------------------------------------------ */ - int (*write) (stio_dev_t* dev, const void* data, stio_len_t* len); + int (*write) (stio_dev_t* dev, const void* data, stio_len_t* len, const stio_adr_t* dstadr); /* ------------------------------------------------------------------ */ int (*ioctl) (stio_dev_t* dev, int cmd, void* arg); @@ -132,13 +164,13 @@ 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_len_t len); + int (*on_read) (stio_dev_t* dev, const void* data, stio_len_t len, const stio_adr_t* srcadr); /* 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_len_t wrlen, void* wrctx); + int (*on_write) (stio_dev_t* dev, stio_len_t wrlen, void* wrctx, const stio_adr_t* dstadr); }; struct stio_wq_t @@ -146,13 +178,14 @@ struct stio_wq_t stio_wq_t* next; stio_wq_t* prev; - stio_len_t olen; /* original length */ - stio_uint8_t* ptr; - stio_len_t len; + stio_len_t olen; /* original data length */ + stio_uint8_t* ptr; /* pointer to data */ + stio_len_t len; /* remaining data length */ void* ctx; stio_dev_t* dev; /* back-pointer to the device */ stio_tmridx_t tmridx; + stio_adr_t dstadr; }; #define STIO_WQ_INIT(wq) ((wq)->next = (wq)->prev = (wq)) @@ -219,6 +252,7 @@ enum stio_dev_capa_t /*STIO_DEV_CAPA_HALFOPEN = (1 << 3),*/ STIO_DEV_CAPA_STREAM = (1 << 4), + STIO_DEV_CAPA_OUT_QUEUED = (1 << 5), /* internal use only. never set this bit to the dev_capa field */ STIO_DEV_CAPA_IN_DISABLED = (1 << 9), @@ -334,7 +368,8 @@ STIO_EXPORT int stio_dev_write ( stio_dev_t* dev, const void* data, stio_len_t len, - void* wrctx + void* wrctx, + const stio_adr_t* dstadr ); @@ -343,7 +378,8 @@ STIO_EXPORT int stio_dev_timedwrite ( const void* data, stio_len_t len, const stio_ntime_t* tmout, - void* wrctx + void* wrctx, + const stio_adr_t* dstadr ); STIO_EXPORT void stio_dev_halt (