added stio_dev_sck_t

This commit is contained in:
hyung-hwan 2016-03-29 15:02:01 +00:00
parent e2b99ed2a3
commit 46d7bc216a
12 changed files with 483 additions and 57 deletions

View File

@ -38,6 +38,9 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <signal.h> #include <signal.h>
#include <netpacket/packet.h>
#include <net/if.h>
/* ========================================================================= */ /* ========================================================================= */
struct mmgr_stat_t 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; 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; return 0;
} }
@ -216,14 +219,14 @@ int main ()
stio_t* stio; stio_t* stio;
stio_dev_udp_t* udp; stio_dev_udp_t* udp;
stio_dev_arp_t* arp; stio_dev_sck_t* sck;
stio_dev_tcp_t* tcp[2]; stio_dev_tcp_t* tcp[2];
struct sockaddr_in sin; struct sockaddr_in sin;
struct sigaction sigact; struct sigaction sigact;
stio_dev_tcp_connect_t tcp_conn; stio_dev_tcp_connect_t tcp_conn;
stio_dev_tcp_listen_t tcp_lstn; stio_dev_tcp_listen_t tcp_lstn;
stio_dev_tcp_make_t tcp_make; 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; tcp_server_t* ts;
stio = stio_open (&mmgr, 0, 512, STIO_NULL); stio = stio_open (&mmgr, 0, 512, STIO_NULL);
@ -316,16 +319,61 @@ int main ()
} }
memset (&arp_make, 0, STIO_SIZEOF(arp_make)); memset (&sck_make, 0, STIO_SIZEOF(sck_make));
arp_make.on_write = arp_on_write; sck_make.type = STIO_DEV_SCK_ARP;
arp_make.on_read = arp_on_read; //sck_make.type = STIO_DEV_SCK_ARP_DGRAM;
arp = stio_dev_arp_make (stio, 0, &arp_make); sck_make.on_write = sck_on_write;
if (!arp) 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; 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 (&etharp, 0, sizeof(etharp));
memcpy (etharp.ethhdr.source, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADR_LEN);
memcpy (etharp.ethhdr.dest, "\xFF\xFF\xFF\xFF\xFF\xFF", STIO_ETHADR_LEN);
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, &etharp, sizeof(etharp), NULL, &adr) <= -1)
//if (stio_dev_sck_write (sck, &etharp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, &adr) <= -1)
{
printf ("CANNOT WRITE ARP...\n");
}
}
#endif
stio_loop (stio); stio_loop (stio);
g_stio = STIO_NULL; g_stio = STIO_NULL;

View File

@ -34,6 +34,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h> #include <errno.h>
#if 0
/* ======================================================================== */ /* ======================================================================== */
static int arp_make (stio_dev_t* dev, void* ctx) 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); return (stio_dev_arp_t*)stio_makedev (stio, STIO_SIZEOF(stio_dev_arp_t) + xtnsize, &arp_mth, &arp_evcb, (void*)data);
} }
int stio_dev_arp_write (stio_dev_arp_t* dev, const stio_pkt_arp_t* arp, void* wrctx)
{
return stio_dev_write ((stio_dev_t*)dev, arp, STIO_SIZEOF(*arp), wrctx);
}
int stio_dev_arp_timedwrite (stio_dev_arp_t* dev, const stio_pkt_arp_t* arp, const stio_ntime_t* tmout, void* wrctx)
{
return stio_dev_write ((stio_dev_t*)dev, arp, STIO_SIZEOF(*arp), wrctx);
}
#endif

View File

@ -31,8 +31,60 @@
#include <stio-sck.h> #include <stio-sck.h>
typedef struct stio_dev_arp_t stio_dev_arp_t; 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 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; 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_write_t on_write;
stio_dev_arp_on_read_t on_read; stio_dev_arp_on_read_t on_read;
}; };
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#if 0
STIO_EXPORT stio_dev_arp_t* stio_dev_arp_make ( STIO_EXPORT stio_dev_arp_t* stio_dev_arp_make (
stio_t* stio, stio_t* stio,
stio_size_t xtnsize, stio_size_t xtnsize,
const stio_dev_arp_make_t* data 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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@ -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) 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) 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 */ 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; stio_dev_pro_t* pro = (stio_dev_pro_t*)dev;
return pro->on_read (pro, data, len); 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; stio_dev_pro_t* pro = (stio_dev_pro_t*)dev;
return pro->on_write (pro, wrctx); return pro->on_write (pro, wrctx);

View File

@ -35,7 +35,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
/* ------------------------------------------------------------------------ */ /* ========================================================================= */
void stio_closeasyncsck (stio_t* stio, stio_sckhnd_t sck) void stio_closeasyncsck (stio_t* stio, stio_sckhnd_t sck)
{ {
#if defined(_WIN32) #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; stio->errnum = STIO_EINVAL;
return -1; 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);
}

View File

@ -72,6 +72,49 @@ typedef struct stio_sckadr_t stio_sckadr_t;
typedef int stio_sckfam_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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -101,10 +144,37 @@ STIO_EXPORT int stio_getsckadrinfo (
stio_sckfam_t* family 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 #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -59,7 +59,7 @@ static int tcp_make (stio_dev_t* dev, void* ctx)
goto oops; 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_write = arg->on_write;
tcp->on_read = arg->on_read; tcp->on_read = arg->on_read;
tcp->tmridx_connect = STIO_TMRIDX_INVALID; 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; 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; stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
ssize_t x; ssize_t x;
@ -131,7 +131,7 @@ static int tcp_read (stio_dev_t* dev, void* buf, stio_len_t* len)
return 1; 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; stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
ssize_t x; ssize_t x;

View File

@ -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) 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) 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) static STIO_INLINE void stio_dev_tcp_halt (stio_dev_tcp_t* tcp)
{ {
stio_dev_halt ((stio_dev_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 #else
#define stio_dev_tcp_read(tcp,enabled) stio_dev_read((stio_dev_t*)tcp, enabled) #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_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) #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) #define stio_dev_tcp_halt(tcp) stio_dev_halt((stio_dev_t*)tcp)
#endif #endif

View File

@ -82,7 +82,7 @@ static stio_syshnd_t udp_getsyshnd (stio_dev_t* dev)
return (stio_syshnd_t)udp->sck; 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_dev_udp_t* udp = (stio_dev_udp_t*)dev;
stio_scklen_t addrlen; stio_scklen_t addrlen;
@ -104,7 +104,7 @@ printf ("UDP RECVFROM...\n");
return 1; 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; stio_dev_udp_t* udp = (stio_dev_udp_t*)udp;
ssize_t x; ssize_t x;

View File

@ -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); 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) 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 #else
#define stio_dev_udp_read(udp,enabled) stio_dev_read((stio_dev_t*)udp, enabled) #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_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) stio_dev_timedwrite((stio_dev_t*)udp, data, len, tmout, wrctx) #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) #define stio_dev_udp_halt(udp) stio_dev_halt((stio_dev_t*)udp)
#endif #endif

View File

@ -187,7 +187,7 @@ printf ("has urgent data...\n");
send_leftover: send_leftover:
ulen = urem; ulen = urem;
x = dev->dev_mth->write (dev, uptr, &ulen); x = dev->dev_mth->write (dev, uptr, &ulen, &q->dstadr);
if (x <= -1) if (x <= -1)
{ {
stio_dev_halt (dev); stio_dev_halt (dev);
@ -221,7 +221,7 @@ printf ("has urgent data...\n");
} }
unlink_wq (stio, q); 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); STIO_MMGR_FREE (stio->mmgr, q);
if (y <= -1) if (y <= -1)
@ -266,6 +266,7 @@ printf ("has urgent data...\n");
if (dev && stio->revs[i].events & EPOLLIN) if (dev && stio->revs[i].events & EPOLLIN)
{ {
stio_adr_t srcadr;
stio_len_t len; stio_len_t len;
int x; int x;
@ -275,7 +276,7 @@ printf ("has urgent data...\n");
while (1) while (1)
{ {
len = STIO_COUNTOF(stio->bigbuf); 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) if (x <= -1)
{ {
stio_dev_halt (dev); stio_dev_halt (dev);
@ -297,7 +298,7 @@ printf ("has urgent data...\n");
stio->renew_watch = 1; stio->renew_watch = 1;
/* call the on_read callback to report EOF */ /* 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)) (dev->dev_capa & STIO_DEV_CAPA_OUT_CLOSED))
{ {
/* 1. input ended and its reporting failed or /* 1. input ended and its reporting failed or
@ -316,7 +317,7 @@ printf ("has urgent data...\n");
* when x == 0 or <= -1. you can */ * when x == 0 or <= -1. you can */
/* data available */ /* 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) if (y <= -1)
{ {
stio_dev_halt (dev); 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 = q->dev;
dev->stio->errnum = STIO_ETMOUT; 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_ASSERT (q->tmridx == STIO_TMRIDX_INVALID);
STIO_WQ_UNLINK(q); 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); 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; const stio_uint8_t* uptr;
stio_len_t urem, ulen; 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 do
{ {
ulen = urem; ulen = urem;
x = dev->dev_mth->write (dev, data, &ulen); x = dev->dev_mth->write (dev, data, &ulen, dstadr);
if (x <= -1) return -1; if (x <= -1) return -1;
else if (x == 0) 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; 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 else
{ {
ulen = urem; ulen = urem;
x = dev->dev_mth->write (dev, data, &ulen); x = dev->dev_mth->write (dev, data, &ulen, dstadr);
if (x <= -1) return -1; if (x <= -1) return -1;
else if (x == 0) goto enqueue_data; else if (x == 0) goto enqueue_data;
/* partial writing is still considered ok for a non-stream device */ /* 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 */ return 1; /* written immediately and called on_write callback */
enqueue_data: 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*/ /* 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) if (!q)
{ {
dev->stio->errnum = STIO_ENOMEM; dev->stio->errnum = STIO_ENOMEM;
@ -831,11 +838,25 @@ enqueue_data:
q->tmridx = STIO_TMRIDX_INVALID; q->tmridx = STIO_TMRIDX_INVALID;
q->dev = dev; q->dev = dev;
q->ctx = wrctx; 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->len = urem;
q->olen = len; q->olen = len;
STIO_MEMCPY (q->ptr, uptr, urem); STIO_MEMCPY (q->ptr, uptr, urem);
if (tmout && !stio_isnegtime(tmout)) if (tmout && !stio_isnegtime(tmout))
{ {
stio_tmrjob_t tmrjob; stio_tmrjob_t tmrjob;
@ -874,14 +895,14 @@ enqueue_data:
return 0; /* request pused to a write queue. */ 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) int stio_makesyshndasync (stio_t* stio, stio_syshnd_t hnd)

View File

@ -48,6 +48,38 @@ struct stio_ntime_t
#define STIO_SYSHND_INVALID (-1) #define STIO_SYSHND_INVALID (-1)
#endif #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_t stio_t;
typedef struct stio_dev_t stio_dev_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. /* 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. * when returning 1, *len must be sent to the length of data read.
* if *len is set to 0, it's treated as EOF. */ * 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); 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. /* return -1 on failure, 0 or 1 on success.
* when 0 is returned, the main loop stops the attempt to read more data. * 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*/ * 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. /* return -1 on failure, 0 on success.
* wrlen is the length of data written. it is the length of the originally * 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 * posted writing request for a stream device. For a non stream device, it
* may be shorter than the originally posted length. */ * 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 struct stio_wq_t
@ -146,13 +178,14 @@ struct stio_wq_t
stio_wq_t* next; stio_wq_t* next;
stio_wq_t* prev; stio_wq_t* prev;
stio_len_t olen; /* original length */ stio_len_t olen; /* original data length */
stio_uint8_t* ptr; stio_uint8_t* ptr; /* pointer to data */
stio_len_t len; stio_len_t len; /* remaining data length */
void* ctx; void* ctx;
stio_dev_t* dev; /* back-pointer to the device */ stio_dev_t* dev; /* back-pointer to the device */
stio_tmridx_t tmridx; stio_tmridx_t tmridx;
stio_adr_t dstadr;
}; };
#define STIO_WQ_INIT(wq) ((wq)->next = (wq)->prev = (wq)) #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_HALFOPEN = (1 << 3),*/
STIO_DEV_CAPA_STREAM = (1 << 4), 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 */ /* internal use only. never set this bit to the dev_capa field */
STIO_DEV_CAPA_IN_DISABLED = (1 << 9), STIO_DEV_CAPA_IN_DISABLED = (1 << 9),
@ -334,7 +368,8 @@ STIO_EXPORT int stio_dev_write (
stio_dev_t* dev, stio_dev_t* dev,
const void* data, const void* data,
stio_len_t len, 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, const void* data,
stio_len_t len, stio_len_t len,
const stio_ntime_t* tmout, const stio_ntime_t* tmout,
void* wrctx void* wrctx,
const stio_adr_t* dstadr
); );
STIO_EXPORT void stio_dev_halt ( STIO_EXPORT void stio_dev_halt (