added stio_dev_sck_t
This commit is contained in:
		@ -38,6 +38,9 @@
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
 | 
			
		||||
#include <netpacket/packet.h>
 | 
			
		||||
#include <net/if.h>
 | 
			
		||||
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
@ -34,6 +34,7 @@
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
@ -31,8 +31,60 @@
 | 
			
		||||
#include <stio-sck.h>
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -35,7 +35,7 @@
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------ */
 | 
			
		||||
/* ========================================================================= */
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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 (
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user