enhanced stio_dev_sck_to support a stream operations
This commit is contained in:
		@ -97,23 +97,23 @@ static void tcp_on_disconnect (stio_dev_tcp_t* tcp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	if (tcp->state & STIO_DEV_TCP_CONNECTING)
 | 
						if (tcp->state & STIO_DEV_TCP_CONNECTING)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		printf ("TCP DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER\n", tcp->sck);
 | 
							printf ("TCP DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if (tcp->state & STIO_DEV_TCP_LISTENING)
 | 
						else if (tcp->state & STIO_DEV_TCP_LISTENING)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		printf ("SHUTTING DOWN THE SERVER SOCKET(%d)...\n", tcp->sck);
 | 
							printf ("SHUTTING DOWN THE SERVER SOCKET(%d)...\n", (int)tcp->sck);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if (tcp->state & STIO_DEV_TCP_CONNECTED)
 | 
						else if (tcp->state & STIO_DEV_TCP_CONNECTED)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		printf ("CLIENT ORIGINATING FROM HERE GOT DISCONNECTED(%d).......\n", tcp->sck);
 | 
							printf ("CLIENT ORIGINATING FROM HERE GOT DISCONNECTED(%d).......\n", (int)tcp->sck);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if (tcp->state & STIO_DEV_TCP_ACCEPTED)
 | 
						else if (tcp->state & STIO_DEV_TCP_ACCEPTED)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		printf ("CLIENT BEING SERVED GOT DISCONNECTED(%d).......\n", tcp->sck);
 | 
							printf ("CLIENT BEING SERVED GOT DISCONNECTED(%d).......\n", (int)tcp->sck);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		printf ("TCP DISCONNECTED - THIS MUST NOT HAPPEN (%d)\n", tcp->sck);
 | 
							printf ("TCP DISCONNECTED - THIS MUST NOT HAPPEN (%d - %x)\n", (int)tcp->sck, (unsigned int)tcp->state);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
static int tcp_on_connect (stio_dev_tcp_t* tcp)
 | 
					static int tcp_on_connect (stio_dev_tcp_t* tcp)
 | 
				
			||||||
@ -143,8 +143,6 @@ printf ("SEDING TIMED OUT...........\n");
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ts = (tcp_server_t*)(tcp + 1);
 | 
						ts = (tcp_server_t*)(tcp + 1);
 | 
				
			||||||
	printf (">>> SENT MESSAGE %d of length %ld\n", ts->tally, (long int)wrlen);
 | 
						printf (">>> SENT MESSAGE %d of length %ld\n", ts->tally, (long int)wrlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -194,12 +192,23 @@ printf ("DISABLING READING..............................\n");
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* ========================================================================= */
 | 
					/* ========================================================================= */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int sck_on_read (stio_dev_sck_t* dev, const void* buf, stio_len_t len, const stio_sckadr_t* srcadr)
 | 
					static int arp_sck_on_read (stio_dev_sck_t* dev, const void* data, stio_len_t dlen, const stio_adr_t* srcadr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						stio_etharp_pkt_t* eap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dlen < STIO_SIZEOF(*eap)) return 0; /* drop */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						eap = (stio_etharp_pkt_t*)data;
 | 
				
			||||||
 | 
						printf ("ARP OPCODE: %d", ntohs(eap->arphdr.opcode));
 | 
				
			||||||
 | 
						printf (" SHA: %02X:%02X:%02X:%02X:%02X:%02X", eap->arppld.sha[0], eap->arppld.sha[1], eap->arppld.sha[2], eap->arppld.sha[3], eap->arppld.sha[4], eap->arppld.sha[5]);
 | 
				
			||||||
 | 
						printf (" SPA: %d.%d.%d.%d", eap->arppld.spa[0], eap->arppld.spa[1], eap->arppld.spa[2], eap->arppld.spa[3]);
 | 
				
			||||||
 | 
						printf (" THA: %02X:%02X:%02X:%02X:%02X:%02X", eap->arppld.tha[0], eap->arppld.tha[1], eap->arppld.tha[2], eap->arppld.tha[3], eap->arppld.tha[4], eap->arppld.tha[5]);
 | 
				
			||||||
 | 
						printf (" TPA: %d.%d.%d.%d", eap->arppld.tpa[0], eap->arppld.tpa[1], eap->arppld.tpa[2], eap->arppld.tpa[3]);
 | 
				
			||||||
 | 
						printf ("\n");
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int sck_on_write (stio_dev_sck_t* dev, stio_len_t wrlen, void* wrctx)
 | 
					static int arp_sck_on_write (stio_dev_sck_t* dev, stio_len_t wrlen, void* wrctx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -322,8 +331,8 @@ int main ()
 | 
				
			|||||||
	memset (&sck_make, 0, STIO_SIZEOF(sck_make));
 | 
						memset (&sck_make, 0, STIO_SIZEOF(sck_make));
 | 
				
			||||||
	sck_make.type = STIO_DEV_SCK_ARP;
 | 
						sck_make.type = STIO_DEV_SCK_ARP;
 | 
				
			||||||
	//sck_make.type = STIO_DEV_SCK_ARP_DGRAM;
 | 
						//sck_make.type = STIO_DEV_SCK_ARP_DGRAM;
 | 
				
			||||||
	sck_make.on_write = sck_on_write;
 | 
						sck_make.on_write = arp_sck_on_write;
 | 
				
			||||||
	sck_make.on_read = sck_on_read;
 | 
						sck_make.on_read = arp_sck_on_read;
 | 
				
			||||||
	sck = stio_dev_sck_make (stio, 0, &sck_make);
 | 
						sck = stio_dev_sck_make (stio, 0, &sck_make);
 | 
				
			||||||
	if (!sck)
 | 
						if (!sck)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -341,16 +350,15 @@ int main ()
 | 
				
			|||||||
	adr.ptr = &sll;
 | 
						adr.ptr = &sll;
 | 
				
			||||||
	adr.len = sizeof(sll);
 | 
						adr.len = sizeof(sll);
 | 
				
			||||||
	sll.sll_family = AF_PACKET;
 | 
						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_protocol = STIO_CONST_HTON16(STIO_ETHHDR_PROTO_ARP);
 | 
					//	sll.sll_hatype = STIO_CONST_HTON16(STIO_ARPHDR_HTYPE_ETH);
 | 
				
			||||||
	sll.sll_hatype = STIO_CONST_HTON16(STIO_ARPHDR_HTYPE_ETH);
 | 
					 | 
				
			||||||
	sll.sll_halen = STIO_ETHADR_LEN;
 | 
						sll.sll_halen = STIO_ETHADR_LEN;
 | 
				
			||||||
	memcpy (sll.sll_addr, "\xFF\xFF\xFF\xFF\xFF\xFF", sll.sll_halen);
 | 
						memcpy (sll.sll_addr, "\xFF\xFF\xFF\xFF\xFF\xFF", sll.sll_halen);
 | 
				
			||||||
	sll.sll_ifindex = if_nametoindex ("enp0s25.3");
 | 
						sll.sll_ifindex = if_nametoindex ("enp0s25.3");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* if unicast ... */
 | 
						/* if unicast ... */
 | 
				
			||||||
	//sll.sll_pkttype = PACKET_OTHERHOST;
 | 
						//sll.sll_pkttype = PACKET_OTHERHOST;
 | 
				
			||||||
	sll.sll_pkttype = PACKET_BROADCAST;
 | 
					//	sll.sll_pkttype = PACKET_BROADCAST;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset (ðarp, 0, sizeof(etharp));
 | 
						memset (ðarp, 0, sizeof(etharp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -158,7 +158,6 @@ static int arp_on_read (stio_dev_t* dev, const void* data, stio_len_t len)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
printf ("dATA received %d bytes\n", (int)len);
 | 
					printf ("dATA received %d bytes\n", (int)len);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int arp_on_write (stio_dev_t* dev, stio_len_t wrlen, void* wrctx)
 | 
					static int arp_on_write (stio_dev_t* dev, stio_len_t wrlen, void* wrctx)
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,6 @@
 | 
				
			|||||||
#include <stio.h>
 | 
					#include <stio.h>
 | 
				
			||||||
#include <stio-sck.h>
 | 
					#include <stio-sck.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct stio_dev_arp_t stio_dev_arp_t;
 | 
					 | 
				
			||||||
#define STIO_ETHHDR_PROTO_IP4 0x0800
 | 
					#define STIO_ETHHDR_PROTO_IP4 0x0800
 | 
				
			||||||
#define STIO_ETHHDR_PROTO_ARP 0x0806
 | 
					#define STIO_ETHHDR_PROTO_ARP 0x0806
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -80,8 +79,8 @@ struct stio_etharp_pkt_t
 | 
				
			|||||||
	stio_etharp_t arppld;
 | 
						stio_etharp_t arppld;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
typedef struct stio_etharp_pkt_t stio_etharp_pkt_t;
 | 
					typedef struct stio_etharp_pkt_t stio_etharp_pkt_t;
 | 
				
			||||||
#pragma pack(pop)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma pack(pop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if 0
 | 
					#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_read_t) (stio_dev_arp_t* dev, stio_pkt_arp_t* pkt, stio_len_t len);
 | 
				
			||||||
 | 
				
			|||||||
@ -42,18 +42,12 @@
 | 
				
			|||||||
#define STIO_ASSERT assert
 | 
					#define STIO_ASSERT assert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STIO_USE_TMRJOB_IDXPTR
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct stio_tmrjob_t
 | 
					struct stio_tmrjob_t
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	void*                  ctx;
 | 
						void*                  ctx;
 | 
				
			||||||
	stio_ntime_t           when;
 | 
						stio_ntime_t           when;
 | 
				
			||||||
	stio_tmrjob_handler_t  handler;
 | 
						stio_tmrjob_handler_t  handler;
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
	stio_tmridx_t*         idxptr; /* pointer to the index holder */
 | 
						stio_tmridx_t*         idxptr; /* pointer to the index holder */
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	stio_tmrjob_updater_t  updater;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STIO_TMRIDX_INVALID ((stio_tmridx_t)-1)
 | 
					#define STIO_TMRIDX_INVALID ((stio_tmridx_t)-1)
 | 
				
			||||||
 | 
				
			|||||||
@ -111,40 +111,66 @@ int stio_getsckadrinfo (stio_t* stio, const stio_sckadr_t* addr, stio_scklen_t*
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ========================================================================= */
 | 
					/* ========================================================================= */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IS_STATEFUL(sck) ((sck)->dev_capa & STIO_DEV_CAPA_STREAM)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sck_type_map_t
 | 
					struct sck_type_map_t
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int domain;
 | 
						int domain;
 | 
				
			||||||
	int type;
 | 
						int type;
 | 
				
			||||||
	int proto;
 | 
						int proto;
 | 
				
			||||||
} sck_type_map[] =
 | 
						int extra_dev_capa;
 | 
				
			||||||
{
 | 
						int sck_capa;
 | 
				
			||||||
	{ 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 struct sck_type_map_t sck_type_map[] =
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						{ AF_INET,    SOCK_STREAM,    0,                         STIO_DEV_CAPA_STREAM  | STIO_DEV_CAPA_OUT_QUEUED },
 | 
				
			||||||
 | 
						{ AF_INET6,   SOCK_STREAM,    0,                         STIO_DEV_CAPA_STREAM  | STIO_DEV_CAPA_OUT_QUEUED },
 | 
				
			||||||
 | 
						{ AF_INET,    SOCK_DGRAM,     0,                         0                                                },
 | 
				
			||||||
 | 
						{ AF_INET6,   SOCK_DGRAM,     0,                         0                                                },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{ AF_PACKET,  SOCK_RAW,       STIO_CONST_HTON16(0x0806), 0                                                },
 | 
				
			||||||
 | 
						{ AF_PACKET,  SOCK_DGRAM,     STIO_CONST_HTON16(0x0806), 0                                                } 
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ======================================================================== */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void tmr_connect_handle (stio_t* stio, const stio_ntime_t* now, stio_tmrjob_t* job)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_sck_t* rdev = (stio_dev_sck_t*)job->ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						STIO_ASSERT (IS_STATEFUL(rdev));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rdev->state & STIO_DEV_SCK_CONNECTING)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* the state check for STIO_DEV_TCP_CONNECTING is actually redundant
 | 
				
			||||||
 | 
							 * as it must not be fired  after it gets connected. the timer job 
 | 
				
			||||||
 | 
							 * doesn't need to be deleted when it gets connected for this check 
 | 
				
			||||||
 | 
							 * here. this libarary, however, deletes the job when it gets 
 | 
				
			||||||
 | 
							 * connected. */
 | 
				
			||||||
 | 
							stio_dev_sck_halt (rdev);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ======================================================================== */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_sck_make (stio_dev_t* dev, void* ctx)
 | 
					static int dev_sck_make (stio_dev_t* dev, void* ctx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
						stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
				
			||||||
	stio_dev_sck_make_t* arg = (stio_dev_sck_make_t*)ctx;
 | 
						stio_dev_sck_make_t* arg = (stio_dev_sck_make_t*)ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						STIO_ASSERT (arg->type >= 0 && arg->type < STIO_COUNTOF(sck_type_map));
 | 
				
			||||||
	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);
 | 
						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;
 | 
						if (rdev->sck == STIO_SCKHND_INVALID) goto oops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rdev->dev_capa = STIO_DEV_CAPA_IN | STIO_DEV_CAPA_OUT;
 | 
						rdev->dev_capa = STIO_DEV_CAPA_IN | STIO_DEV_CAPA_OUT | sck_type_map[arg->type].extra_dev_capa;
 | 
				
			||||||
	rdev->on_write = arg->on_write;
 | 
						rdev->on_write = arg->on_write;
 | 
				
			||||||
	rdev->on_read = arg->on_read;
 | 
						rdev->on_read = arg->on_read;
 | 
				
			||||||
 | 
						rdev->type = arg->type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdev->tmridx_connect = STIO_TMRIDX_INVALID;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
oops:
 | 
					oops:
 | 
				
			||||||
@ -156,9 +182,40 @@ oops:
 | 
				
			|||||||
	return -1;
 | 
						return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dev_sck_make_client (stio_dev_t* dev, void* ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
				
			||||||
 | 
						stio_syshnd_t* sck = (stio_syshnd_t*)ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rdev->sck = *sck;
 | 
				
			||||||
 | 
						if (stio_makesckasync (rdev->stio, rdev->sck) <= -1) return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void dev_sck_kill (stio_dev_t* dev)
 | 
					static void dev_sck_kill (stio_dev_t* dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
						stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (IS_STATEFUL(rdev))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (rdev->state & (STIO_DEV_SCK_ACCEPTED | STIO_DEV_SCK_CONNECTED | STIO_DEV_SCK_CONNECTING | STIO_DEV_SCK_LISTENING))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (rdev->on_disconnect) rdev->on_disconnect (rdev);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (rdev->tmridx_connect != STIO_TMRIDX_INVALID)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								stio_deltmrjob (dev->stio, rdev->tmridx_connect);
 | 
				
			||||||
 | 
								STIO_ASSERT (rdev->tmridx_connect == STIO_TMRIDX_INVALID);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							STIO_ASSERT (rdev->state == 0);
 | 
				
			||||||
 | 
							STIO_ASSERT (rdev->tmridx_connect == STIO_TMRIDX_INVALID);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (rdev->sck != STIO_SCKHND_INVALID) 
 | 
						if (rdev->sck != STIO_SCKHND_INVALID) 
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		stio_closeasyncsck (rdev->stio, rdev->sck);
 | 
							stio_closeasyncsck (rdev->stio, rdev->sck);
 | 
				
			||||||
@ -172,11 +229,29 @@ static stio_syshnd_t dev_sck_getsyshnd (stio_dev_t* dev)
 | 
				
			|||||||
	return (stio_syshnd_t)rdev->sck;
 | 
						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)
 | 
					static int dev_sck_read_stateful (stio_dev_t* dev, void* buf, stio_len_t* len, stio_adr_t* srcadr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_sck_t* tcp = (stio_dev_sck_t*)dev;
 | 
				
			||||||
 | 
						ssize_t x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x = recv (tcp->sck, buf, *len, 0);
 | 
				
			||||||
 | 
						if (x == -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0;  /* no data available */
 | 
				
			||||||
 | 
							if (errno == EINTR) return 0;
 | 
				
			||||||
 | 
							tcp->stio->errnum = stio_syserrtoerrnum(errno);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*len = x;
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dev_sck_read_stateless (stio_dev_t* dev, void* buf, stio_len_t* len, stio_adr_t* srcadr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
						stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
				
			||||||
	stio_scklen_t srcadrlen;
 | 
						stio_scklen_t srcadrlen;
 | 
				
			||||||
	int x;
 | 
						ssize_t x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	srcadrlen = srcadr->len;
 | 
						srcadrlen = srcadr->len;
 | 
				
			||||||
	x = recvfrom (rdev->sck, buf, *len, 0, srcadr->ptr, &srcadrlen);
 | 
						x = recvfrom (rdev->sck, buf, *len, 0, srcadr->ptr, &srcadrlen);
 | 
				
			||||||
@ -193,7 +268,44 @@ static int dev_sck_read (stio_dev_t* dev, void* buf, stio_len_t* len, stio_adr_t
 | 
				
			|||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_sck_write (stio_dev_t* dev, const void* data, stio_len_t* len, const stio_adr_t* dstadr)
 | 
					
 | 
				
			||||||
 | 
					static int dev_sck_write_stateful (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;
 | 
				
			||||||
 | 
						int flags = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (*len <= 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* it's a writing finish indicator. close the writing end of
 | 
				
			||||||
 | 
							 * the socket, probably leaving it in the half-closed state */
 | 
				
			||||||
 | 
							if (shutdown (rdev->sck, SHUT_WR) == -1)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								rdev->stio->errnum = stio_syserrtoerrnum(errno);
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* TODO: flags MSG_DONTROUTE, MSG_DONTWAIT, MSG_MORE, MSG_OOB, MSG_NOSIGNAL */
 | 
				
			||||||
 | 
					#if defined(MSG_NOSIGNAL)
 | 
				
			||||||
 | 
						flags |= MSG_NOSIGNAL;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						x = send (rdev->sck, data, *len, flags);
 | 
				
			||||||
 | 
						if (x == -1) 
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (errno == EINPROGRESS || errno == EWOULDBLOCK) 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_write_stateless (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;
 | 
						stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
				
			||||||
	ssize_t x;
 | 
						ssize_t x;
 | 
				
			||||||
@ -211,64 +323,427 @@ static int dev_sck_write (stio_dev_t* dev, const void* data, stio_len_t* len, co
 | 
				
			|||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg)
 | 
					static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (cmd)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							case STIO_DEV_SCK_BIND:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								stio_dev_sck_bind_t* bnd = (stio_dev_sck_bind_t*)arg;
 | 
				
			||||||
 | 
								struct sockaddr* sa = (struct sockaddr*)&bnd->addr;
 | 
				
			||||||
 | 
								stio_scklen_t sl;
 | 
				
			||||||
 | 
								stio_sckfam_t fam;
 | 
				
			||||||
 | 
								int x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (stio_getsckadrinfo (dev->stio, &bnd->addr, &sl, &fam) <= -1) return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* the socket is already non-blocking */
 | 
				
			||||||
 | 
								x = bind (rdev->sck, sa, sl);
 | 
				
			||||||
 | 
								if (x == -1)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									rdev->stio->errnum = stio_syserrtoerrnum(errno);
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case STIO_DEV_SCK_CONNECT:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								stio_dev_sck_connect_t* conn = (stio_dev_sck_connect_t*)arg;
 | 
				
			||||||
 | 
								struct sockaddr* sa = (struct sockaddr*)&conn->addr;
 | 
				
			||||||
 | 
								stio_scklen_t sl;
 | 
				
			||||||
 | 
								int x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!IS_STATEFUL(rdev)) 
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									dev->stio->errnum = STIO_ENOCAPA;
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (sa->sa_family == AF_INET) sl = STIO_SIZEOF(struct sockaddr_in);
 | 
				
			||||||
 | 
								else if (sa->sa_family == AF_INET6) sl = STIO_SIZEOF(struct sockaddr_in6);
 | 
				
			||||||
 | 
								else 
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									dev->stio->errnum = STIO_EINVAL;
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* the socket is already non-blocking */
 | 
				
			||||||
 | 
								x = connect (rdev->sck, sa, sl);
 | 
				
			||||||
 | 
								if (x == -1)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (errno == EINPROGRESS || errno == EWOULDBLOCK)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										if (stio_dev_watch ((stio_dev_t*)rdev, STIO_DEV_WATCH_UPDATE, STIO_DEV_EVENT_IN | STIO_DEV_EVENT_OUT) >= 0)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											stio_tmrjob_t tmrjob;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if (!stio_isnegtime(&conn->tmout))
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												STIO_MEMSET (&tmrjob, 0, STIO_SIZEOF(tmrjob));
 | 
				
			||||||
 | 
												tmrjob.ctx = rdev;
 | 
				
			||||||
 | 
												stio_gettime (&tmrjob.when);
 | 
				
			||||||
 | 
												stio_addtime (&tmrjob.when, &conn->tmout, &tmrjob.when);
 | 
				
			||||||
 | 
												tmrjob.handler = tmr_connect_handle;
 | 
				
			||||||
 | 
												tmrjob.idxptr = &rdev->tmridx_connect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												STIO_ASSERT (rdev->tmridx_connect == STIO_TMRIDX_INVALID);
 | 
				
			||||||
 | 
												rdev->tmridx_connect = stio_instmrjob (rdev->stio, &tmrjob);
 | 
				
			||||||
 | 
												if (rdev->tmridx_connect == STIO_TMRIDX_INVALID)
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													stio_dev_watch ((stio_dev_t*)rdev, STIO_DEV_WATCH_UPDATE, STIO_DEV_EVENT_IN);
 | 
				
			||||||
 | 
													/* event manipulation failure can't be handled properly. so ignore it. 
 | 
				
			||||||
 | 
													 * anyway, it's already in a failure condition */
 | 
				
			||||||
 | 
													return -1;
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											rdev->state |= STIO_DEV_SCK_CONNECTING;
 | 
				
			||||||
 | 
											rdev->peer = conn->addr;
 | 
				
			||||||
 | 
											rdev->on_connect = conn->on_connect;
 | 
				
			||||||
 | 
											rdev->on_disconnect = conn->on_disconnect;
 | 
				
			||||||
 | 
											return 0;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									rdev->stio->errnum = stio_syserrtoerrnum(errno);
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* connected immediately */
 | 
				
			||||||
 | 
								rdev->state |= STIO_DEV_SCK_CONNECTED;
 | 
				
			||||||
 | 
								rdev->peer = conn->addr;
 | 
				
			||||||
 | 
								rdev->on_connect = conn->on_connect;
 | 
				
			||||||
 | 
								rdev->on_disconnect = conn->on_disconnect;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case STIO_DEV_SCK_LISTEN:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								stio_dev_sck_listen_t* lstn = (stio_dev_sck_listen_t*)arg;
 | 
				
			||||||
 | 
								int x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!IS_STATEFUL(rdev)) 
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									dev->stio->errnum = STIO_ENOCAPA;
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								x = listen (rdev->sck, lstn->backlogs);
 | 
				
			||||||
 | 
								if (x == -1) 
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									rdev->stio->errnum = stio_syserrtoerrnum(errno);
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								rdev->state |= STIO_DEV_SCK_LISTENING;
 | 
				
			||||||
 | 
								rdev->on_connect = lstn->on_connect;
 | 
				
			||||||
 | 
								rdev->on_disconnect = lstn->on_disconnect;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static stio_dev_mth_t dev_mth_sck = 
 | 
					static stio_dev_mth_t dev_mth_sck_stateless = 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	dev_sck_make,
 | 
						dev_sck_make,
 | 
				
			||||||
	dev_sck_kill,
 | 
						dev_sck_kill,
 | 
				
			||||||
	dev_sck_getsyshnd,
 | 
						dev_sck_getsyshnd,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_sck_read,
 | 
						dev_sck_read_stateless,
 | 
				
			||||||
	dev_sck_write,
 | 
						dev_sck_write_stateless,
 | 
				
			||||||
	dev_sck_ioctl,     /* ioctl */
 | 
						dev_sck_ioctl,     /* ioctl */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static stio_dev_mth_t dev_mth_sck_stateful = 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						dev_sck_make,
 | 
				
			||||||
 | 
						dev_sck_kill,
 | 
				
			||||||
 | 
						dev_sck_getsyshnd,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_sck_read_stateful,
 | 
				
			||||||
 | 
						dev_sck_write_stateful,
 | 
				
			||||||
 | 
						dev_sck_ioctl,     /* ioctl */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static stio_dev_mth_t dev_mth_clisck =
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						dev_sck_make_client,
 | 
				
			||||||
 | 
						dev_sck_kill,
 | 
				
			||||||
 | 
						dev_sck_getsyshnd,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev_sck_read_stateful,
 | 
				
			||||||
 | 
						dev_sck_write_stateful,
 | 
				
			||||||
 | 
						dev_sck_ioctl
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
/* ========================================================================= */
 | 
					/* ========================================================================= */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_evcb_sck_ready (stio_dev_t* dev, int events)
 | 
					static int dev_evcb_sck_ready_stateful (stio_dev_t* dev, int events)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
/* TODO: ... */
 | 
						stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
				
			||||||
	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");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (events & STIO_DEV_EVENT_ERR)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int errcode;
 | 
				
			||||||
 | 
							stio_scklen_t len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							len = STIO_SIZEOF(errcode);
 | 
				
			||||||
 | 
							if (getsockopt (rdev->sck, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* the error number is set to the socket error code.
 | 
				
			||||||
 | 
								 * errno resulting from getsockopt() doesn't reflect the actual
 | 
				
			||||||
 | 
								 * socket error. so errno is not used to set the error number.
 | 
				
			||||||
 | 
								 * instead, the generic device error STIO_EDEVERRR is used */
 | 
				
			||||||
 | 
								rdev->stio->errnum = STIO_EDEVERR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								rdev->stio->errnum = stio_syserrtoerrnum (errcode);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* this socket can connect */
 | 
				
			||||||
 | 
						if (rdev->state & STIO_DEV_SCK_CONNECTING)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (events & STIO_DEV_EVENT_HUP)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* device hang-up */
 | 
				
			||||||
 | 
								rdev->stio->errnum = STIO_EDEVHUP;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (events & (STIO_DEV_EVENT_PRI | STIO_DEV_EVENT_IN))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* invalid event masks. generic device error */
 | 
				
			||||||
 | 
								rdev->stio->errnum = STIO_EDEVERR;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (events & STIO_DEV_EVENT_OUT)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								int errcode;
 | 
				
			||||||
 | 
								stio_scklen_t len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								STIO_ASSERT (!(rdev->state & STIO_DEV_SCK_CONNECTED));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								len = STIO_SIZEOF(errcode);
 | 
				
			||||||
 | 
								if (getsockopt (rdev->sck, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									rdev->stio->errnum = stio_syserrtoerrnum(errno);
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if (errcode == 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									rdev->state &= ~STIO_DEV_SCK_CONNECTING;
 | 
				
			||||||
 | 
									rdev->state |= STIO_DEV_SCK_CONNECTED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (stio_dev_watch ((stio_dev_t*)rdev, STIO_DEV_WATCH_RENEW, 0) <= -1) return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (rdev->tmridx_connect != STIO_TMRIDX_INVALID)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										stio_deltmrjob (rdev->stio, rdev->tmridx_connect);
 | 
				
			||||||
 | 
										STIO_ASSERT (rdev->tmridx_connect == STIO_TMRIDX_INVALID);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (rdev->on_connect (rdev) <= -1) 
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										printf ("ON_CONNECTE HANDLER RETURNEF FAILURE...\n");
 | 
				
			||||||
 | 
										return -1;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if (errcode == EINPROGRESS || errcode == EWOULDBLOCK)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									/* still in progress */
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									rdev->stio->errnum = stio_syserrtoerrnum(errcode);
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0; /* success but don't invoke on_read() */ 
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (rdev->state & STIO_DEV_SCK_LISTENING)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (events & STIO_DEV_EVENT_HUP)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* device hang-up */
 | 
				
			||||||
 | 
								rdev->stio->errnum = STIO_EDEVHUP;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (events & (STIO_DEV_EVENT_PRI | STIO_DEV_EVENT_OUT))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								rdev->stio->errnum = STIO_EDEVERR;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (events & STIO_DEV_EVENT_IN)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								stio_sckhnd_t clisck;
 | 
				
			||||||
 | 
								stio_sckadr_t peer;
 | 
				
			||||||
 | 
								stio_scklen_t addrlen;
 | 
				
			||||||
 | 
								stio_dev_sck_t* clidev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* this is a server(lisening) socket */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								addrlen = STIO_SIZEOF(peer);
 | 
				
			||||||
 | 
								clisck = accept (rdev->sck, (struct sockaddr*)&peer, &addrlen);
 | 
				
			||||||
 | 
								if (clisck == STIO_SCKHND_INVALID)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0;
 | 
				
			||||||
 | 
									if (errno == EINTR) return 0; /* if interrupted by a signal, treat it as if it's EINPROGRESS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									rdev->stio->errnum = stio_syserrtoerrnum(errno);
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* use rdev->dev_size when instantiating a client sck device
 | 
				
			||||||
 | 
								 * instead of STIO_SIZEOF(stio_dev_sck_t). therefore, the 
 | 
				
			||||||
 | 
								 * extension area as big as that of the master sck device
 | 
				
			||||||
 | 
								 * is created in the client sck device */
 | 
				
			||||||
 | 
								clidev = (stio_dev_sck_t*)stio_makedev (rdev->stio, rdev->dev_size, &dev_mth_clisck, rdev->dev_evcb, &clisck); 
 | 
				
			||||||
 | 
								if (!clidev) 
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									close (clisck);
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								clidev->dev_capa |= STIO_DEV_CAPA_IN | STIO_DEV_CAPA_OUT | STIO_DEV_CAPA_STREAM;
 | 
				
			||||||
 | 
								clidev->state |= STIO_DEV_SCK_ACCEPTED;
 | 
				
			||||||
 | 
								clidev->peer = peer;
 | 
				
			||||||
 | 
								/*clidev->parent = sck;*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* inherit some event handlers from the parent.
 | 
				
			||||||
 | 
								 * you can still change them inside the on_connect handler */
 | 
				
			||||||
 | 
								clidev->on_connect = rdev->on_connect;
 | 
				
			||||||
 | 
								clidev->on_disconnect = rdev->on_disconnect; 
 | 
				
			||||||
 | 
								clidev->on_write = rdev->on_write;
 | 
				
			||||||
 | 
								clidev->on_read = rdev->on_read;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								clidev->tmridx_connect = STIO_TMRIDX_INVALID;
 | 
				
			||||||
 | 
								if (clidev->on_connect(clidev) <= -1) stio_dev_sck_halt (clidev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return 0; /* success but don't invoke on_read() */ 
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (events & STIO_DEV_EVENT_HUP)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (events & (STIO_DEV_EVENT_PRI | STIO_DEV_EVENT_IN | STIO_DEV_EVENT_OUT)) 
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* probably half-open? */
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rdev->stio->errnum = STIO_EDEVHUP;
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1; /* the device is ok. carry on reading or writing */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dev_evcb_sck_ready_stateless (stio_dev_t* dev, int events)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (events & STIO_DEV_EVENT_ERR)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int errcode;
 | 
				
			||||||
 | 
							stio_scklen_t len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							len = STIO_SIZEOF(errcode);
 | 
				
			||||||
 | 
							if (getsockopt (rdev->sck, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* the error number is set to the socket error code.
 | 
				
			||||||
 | 
								 * errno resulting from getsockopt() doesn't reflect the actual
 | 
				
			||||||
 | 
								 * socket error. so errno is not used to set the error number.
 | 
				
			||||||
 | 
								 * instead, the generic device error STIO_EDEVERRR is used */
 | 
				
			||||||
 | 
								rdev->stio->errnum = STIO_EDEVERR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								rdev->stio->errnum = stio_syserrtoerrnum (errcode);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (events & STIO_DEV_EVENT_HUP)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							rdev->stio->errnum = STIO_EDEVHUP;
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 1; /* the device is ok. carry on reading or writing */
 | 
						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)
 | 
					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);
 | 
						stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
				
			||||||
	return 0;
 | 
						return rdev->on_read (rdev, data, dlen, adr);
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_evcb_sck_on_write (stio_dev_t* dev, stio_len_t wrlen, void* wrctx, const stio_adr_t* adr)
 | 
					static int dev_evcb_sck_on_write (stio_dev_t* dev, stio_len_t wrlen, void* wrctx, const stio_adr_t* adr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 0;
 | 
						stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev;
 | 
				
			||||||
 | 
						return rdev->on_write (rdev, wrlen, wrctx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static stio_dev_evcb_t dev_evcb_sck =
 | 
					static stio_dev_evcb_t dev_evcb_sck_stateful =
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	dev_evcb_sck_ready,
 | 
						dev_evcb_sck_ready_stateful,
 | 
				
			||||||
	dev_evcb_sck_on_read,
 | 
						dev_evcb_sck_on_read,
 | 
				
			||||||
	dev_evcb_sck_on_write
 | 
						dev_evcb_sck_on_write
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ======================================================================== */
 | 
					static stio_dev_evcb_t dev_evcb_sck_stateless =
 | 
				
			||||||
 | 
					 | 
				
			||||||
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);
 | 
						dev_evcb_sck_ready_stateless,
 | 
				
			||||||
 | 
						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* mkinf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_sck_t* rdev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mkinf->type < 0 && mkinf->type >= STIO_COUNTOF(sck_type_map))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stio->errnum = STIO_EINVAL;
 | 
				
			||||||
 | 
							return STIO_NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sck_type_map[mkinf->type].extra_dev_capa & STIO_DEV_CAPA_STREAM) /* can't use the IS_STATEFUL() macro yet */
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							rdev = (stio_dev_sck_t*)stio_makedev (stio, STIO_SIZEOF(stio_dev_sck_t) + xtnsize, &dev_mth_sck_stateful, &dev_evcb_sck_stateful, (void*)mkinf);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							rdev = (stio_dev_sck_t*)stio_makedev (stio, STIO_SIZEOF(stio_dev_sck_t) + xtnsize, &dev_mth_sck_stateless, &dev_evcb_sck_stateless, (void*)mkinf);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rdev;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int stio_dev_sck_bind (stio_dev_sck_t* dev, stio_dev_sck_bind_t* info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return stio_dev_ioctl ((stio_dev_t*)dev, STIO_DEV_SCK_BIND, info);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int stio_dev_sck_connect (stio_dev_sck_t* dev, stio_dev_sck_connect_t* info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return stio_dev_ioctl ((stio_dev_t*)dev, STIO_DEV_SCK_CONNECT, info);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int stio_dev_sck_listen (stio_dev_sck_t* dev, stio_dev_sck_listen_t* info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return stio_dev_ioctl ((stio_dev_t*)dev, STIO_DEV_SCK_LISTEN, info);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int stio_dev_sck_write (stio_dev_sck_t* dev, const void* data, stio_len_t dlen, void* wrctx, const stio_adr_t* dstadr)
 | 
					int stio_dev_sck_write (stio_dev_sck_t* dev, const void* data, stio_len_t dlen, void* wrctx, const stio_adr_t* dstadr)
 | 
				
			||||||
 | 
				
			|||||||
@ -80,11 +80,40 @@ typedef int stio_sckfam_t;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* ========================================================================= */
 | 
					/* ========================================================================= */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum stio_dev_sck_ioctl_cmd_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						STIO_DEV_SCK_BIND, 
 | 
				
			||||||
 | 
						STIO_DEV_SCK_CONNECT,
 | 
				
			||||||
 | 
						STIO_DEV_SCK_LISTEN
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					typedef enum stio_dev_sck_ioctl_cmd_t stio_dev_sck_ioctl_cmd_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum stio_dev_sck_state_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						STIO_DEV_SCK_CONNECTING = (1 << 0),
 | 
				
			||||||
 | 
						STIO_DEV_SCK_CONNECTED  = (1 << 1),
 | 
				
			||||||
 | 
						STIO_DEV_SCK_LISTENING  = (1 << 2),
 | 
				
			||||||
 | 
						STIO_DEV_SCK_ACCEPTED   = (1 << 3)
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					typedef enum stio_dev_sck_state_t stio_dev_sck_state_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct stio_dev_sck_t stio_dev_sck_t;
 | 
					typedef struct stio_dev_sck_t stio_dev_sck_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef int (*stio_dev_sck_on_read_t) (stio_dev_sck_t* dev, const void* data, stio_len_t dlen, const stio_sckadr_t* srcadr);
 | 
					typedef int (*stio_dev_sck_on_read_t) (
 | 
				
			||||||
typedef int (*stio_dev_sck_on_write_t) (stio_dev_sck_t* dev, stio_len_t wrlen, void* wrctx);
 | 
						stio_dev_sck_t*   dev,
 | 
				
			||||||
 | 
						const void*       data,
 | 
				
			||||||
 | 
						stio_len_t        dlen,
 | 
				
			||||||
 | 
						const stio_adr_t* srcadr
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					typedef int (*stio_dev_sck_on_write_t) (
 | 
				
			||||||
 | 
						stio_dev_sck_t*   dev,
 | 
				
			||||||
 | 
						stio_len_t        wrlen,
 | 
				
			||||||
 | 
						void*             wrctx
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef int (*stio_dev_sck_on_connect_t) (stio_dev_sck_t* dev);
 | 
				
			||||||
 | 
					typedef void (*stio_dev_sck_on_disconnect_t) (stio_dev_sck_t* dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum stio_dev_sck_type_t
 | 
					enum stio_dev_sck_type_t
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -106,20 +135,64 @@ struct stio_dev_sck_make_t
 | 
				
			|||||||
	stio_dev_sck_on_read_t on_read;
 | 
						stio_dev_sck_on_read_t on_read;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct stio_dev_sck_bind_t stio_dev_sck_bind_t;
 | 
				
			||||||
 | 
					struct stio_dev_sck_bind_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int opts; /* TODO: REUSEADDR , TRANSPARENT, etc  or someting?? */
 | 
				
			||||||
 | 
						stio_sckadr_t addr;
 | 
				
			||||||
 | 
						/* TODO: add device name for BIND_TO_DEVICE */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct stio_dev_sck_connect_t stio_dev_sck_connect_t;
 | 
				
			||||||
 | 
					struct stio_dev_sck_connect_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_sckadr_t addr;
 | 
				
			||||||
 | 
						stio_ntime_t tmout; /* connect timeout */
 | 
				
			||||||
 | 
						stio_dev_sck_on_connect_t on_connect;
 | 
				
			||||||
 | 
						stio_dev_sck_on_disconnect_t on_disconnect;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct stio_dev_sck_listen_t stio_dev_sck_listen_t;
 | 
				
			||||||
 | 
					struct stio_dev_sck_listen_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int backlogs;
 | 
				
			||||||
 | 
						stio_dev_sck_on_connect_t on_connect; /* optional, but new connections are dropped immediately without this */
 | 
				
			||||||
 | 
						stio_dev_sck_on_disconnect_t on_disconnect; /* should on_discconneted be part of on_accept_t??? */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct stio_dev_sck_accept_t stio_dev_sck_accept_t;
 | 
				
			||||||
 | 
					struct stio_dev_sck_accept_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_syshnd_t   sck;
 | 
				
			||||||
 | 
					/* TODO: add timeout */
 | 
				
			||||||
 | 
						stio_sckadr_t   peer;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct stio_dev_sck_t
 | 
					struct stio_dev_sck_t
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	STIO_DEV_HEADERS;
 | 
						STIO_DEV_HEADERS;
 | 
				
			||||||
 | 
						stio_dev_sck_type_t type;
 | 
				
			||||||
	stio_sckhnd_t sck;
 | 
						stio_sckhnd_t sck;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stio_dev_sck_on_write_t on_write;
 | 
						stio_dev_sck_on_write_t on_write;
 | 
				
			||||||
	stio_dev_sck_on_read_t on_read;
 | 
						stio_dev_sck_on_read_t on_read;
 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int state;
 | 
				
			||||||
 | 
						/** return 0 on succes, -1 on failure/
 | 
				
			||||||
 | 
						 *  called on a new tcp device for an accepted client or
 | 
				
			||||||
 | 
						 *         on a tcp device conntected to a remote server */
 | 
				
			||||||
 | 
						stio_dev_sck_on_connect_t on_connect;
 | 
				
			||||||
 | 
						stio_dev_sck_on_disconnect_t on_disconnect;
 | 
				
			||||||
 | 
						stio_tmridx_t tmridx_connect;
 | 
				
			||||||
 | 
						stio_sckadr_t peer;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
STIO_EXPORT stio_sckhnd_t stio_openasyncsck (
 | 
					STIO_EXPORT stio_sckhnd_t stio_openasyncsck (
 | 
				
			||||||
	stio_t* stio,
 | 
						stio_t* stio,
 | 
				
			||||||
	int     domain, 
 | 
						int     domain, 
 | 
				
			||||||
@ -149,7 +222,22 @@ STIO_EXPORT int stio_getsckadrinfo (
 | 
				
			|||||||
STIO_EXPORT stio_dev_sck_t* stio_dev_sck_make (
 | 
					STIO_EXPORT stio_dev_sck_t* stio_dev_sck_make (
 | 
				
			||||||
	stio_t*                    stio,
 | 
						stio_t*                    stio,
 | 
				
			||||||
	stio_size_t                xtnsize,
 | 
						stio_size_t                xtnsize,
 | 
				
			||||||
	const stio_dev_sck_make_t* data
 | 
						const stio_dev_sck_make_t* info
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					STIO_EXPORT int stio_dev_sck_bind (
 | 
				
			||||||
 | 
						stio_dev_sck_t*         dev,
 | 
				
			||||||
 | 
						stio_dev_sck_bind_t*    info
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					STIO_EXPORT int stio_dev_sck_connect (
 | 
				
			||||||
 | 
						stio_dev_sck_t*         dev,
 | 
				
			||||||
 | 
						stio_dev_sck_connect_t* info
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					STIO_EXPORT int stio_dev_sck_listen (
 | 
				
			||||||
 | 
						stio_dev_sck_t*         dev,
 | 
				
			||||||
 | 
						stio_dev_sck_listen_t*  info
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
STIO_EXPORT int stio_dev_sck_write (
 | 
					STIO_EXPORT int stio_dev_sck_write (
 | 
				
			||||||
@ -169,6 +257,45 @@ STIO_EXPORT int stio_dev_sck_timedwrite (
 | 
				
			|||||||
	const stio_adr_t*     dstadr
 | 
						const stio_adr_t*     dstadr
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(STIO_HAVE_INLINE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static STIO_INLINE void stio_dev_sck_halt (stio_dev_sck_t* sck)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_halt ((stio_dev_t*)sck);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static STIO_INLINE int stio_dev_sck_read (stio_dev_sck_t* sck, int enabled)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return stio_dev_read ((stio_dev_t*)sck, enabled);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					static STIO_INLINE int stio_dev_sck_write (stio_dev_sck_t* sck, const void* data, stio_len_t len, void* wrctx, const stio_adr_t* dstadr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return stio_dev_write ((stio_dev_t*)sck, data, len, wrctx, STIO_NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static STIO_INLINE int stio_dev_sck_timedwrite (stio_dev_sck_t* sck, const void* data, stio_len_t len, const stio_ntime_t* tmout, void* wrctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return stio_dev_timedwrite ((stio_dev_t*)sck, data, len, tmout, wrctx, STIO_NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define stio_dev_sck_halt(sck) stio_dev_halt((stio_dev_t*)sck)
 | 
				
			||||||
 | 
					#define stio_dev_sck_read(sck,enabled) stio_dev_read((stio_dev_t*)sck, enabled)
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					#define stio_dev_sck_write(sck,data,len,wrctx) stio_dev_write((stio_dev_t*)sck, data, len, wrctx, STIO_NULL)
 | 
				
			||||||
 | 
					#define stio_dev_sck_timedwrite(sck,data,len,tmout,wrctx) stio_dev_timedwrite((stio_dev_t*)sck, data, len, tmout, wrctx, STIO_NULL)
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -182,17 +182,6 @@ static void tmr_connect_handle (stio_t* stio, const stio_ntime_t* now, stio_tmrj
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
/* nothing to define */
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
static void tmr_connect_update (stio_t* stio, stio_tmridx_t old_index, stio_tmridx_t new_index, stio_tmrjob_t* job)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)job->ctx;
 | 
					 | 
				
			||||||
	tcp->tmridx_connect = new_index;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int tcp_ioctl (stio_dev_t* dev, int cmd, void* arg)
 | 
					static int tcp_ioctl (stio_dev_t* dev, int cmd, void* arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
						stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
				
			||||||
@ -261,11 +250,7 @@ static int tcp_ioctl (stio_dev_t* dev, int cmd, void* arg)
 | 
				
			|||||||
							stio_gettime (&tmrjob.when);
 | 
												stio_gettime (&tmrjob.when);
 | 
				
			||||||
							stio_addtime (&tmrjob.when, &conn->tmout, &tmrjob.when);
 | 
												stio_addtime (&tmrjob.when, &conn->tmout, &tmrjob.when);
 | 
				
			||||||
							tmrjob.handler = tmr_connect_handle;
 | 
												tmrjob.handler = tmr_connect_handle;
 | 
				
			||||||
						#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
							tmrjob.idxptr = &tcp->tmridx_connect;
 | 
												tmrjob.idxptr = &tcp->tmridx_connect;
 | 
				
			||||||
						#else
 | 
					 | 
				
			||||||
							tmrjob.updater = tmr_connect_update;
 | 
					 | 
				
			||||||
						#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
							STIO_ASSERT (tcp->tmridx_connect == STIO_TMRIDX_INVALID);
 | 
												STIO_ASSERT (tcp->tmridx_connect == STIO_TMRIDX_INVALID);
 | 
				
			||||||
							tcp->tmridx_connect = stio_instmrjob (tcp->stio, &tmrjob);
 | 
												tcp->tmridx_connect = stio_instmrjob (tcp->stio, &tmrjob);
 | 
				
			||||||
 | 
				
			|||||||
@ -50,7 +50,6 @@ typedef enum stio_dev_tcp_state_t stio_dev_tcp_state_t;
 | 
				
			|||||||
typedef struct stio_dev_tcp_t stio_dev_tcp_t;
 | 
					typedef struct stio_dev_tcp_t stio_dev_tcp_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef int (*stio_dev_tcp_on_connect_t) (stio_dev_tcp_t* dev);
 | 
					typedef int (*stio_dev_tcp_on_connect_t) (stio_dev_tcp_t* dev);
 | 
				
			||||||
typedef void (*stio_dev_tcp_on_accepted_t) (stio_dev_tcp_t* dev, stio_dev_tcp_t* clidev);
 | 
					 | 
				
			||||||
typedef void (*stio_dev_tcp_on_disconnect_t) (stio_dev_tcp_t* dev);
 | 
					typedef void (*stio_dev_tcp_on_disconnect_t) (stio_dev_tcp_t* dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef int (*stio_dev_tcp_on_read_t) (stio_dev_tcp_t* dev, const void* data, stio_len_t len);
 | 
					typedef int (*stio_dev_tcp_on_read_t) (stio_dev_tcp_t* dev, const void* data, stio_len_t len);
 | 
				
			||||||
 | 
				
			|||||||
@ -46,28 +46,14 @@ static stio_tmridx_t sift_up (stio_t* stio, stio_tmridx_t index, int notify)
 | 
				
			|||||||
	if (index > 0 && YOUNGER_THAN(&stio->tmr.jobs[index], &stio->tmr.jobs[parent]))
 | 
						if (index > 0 && YOUNGER_THAN(&stio->tmr.jobs[index], &stio->tmr.jobs[parent]))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		stio_tmrjob_t item;
 | 
							stio_tmrjob_t item;
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
		/* nothing */
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
		stio_tmridx_t old_index;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		item = stio->tmr.jobs[index]; 
 | 
							item = stio->tmr.jobs[index]; 
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
		/* nothing */
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
		old_index = index;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		do
 | 
							do
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/* move down the parent to my current position */
 | 
								/* move down the parent to my current position */
 | 
				
			||||||
			stio->tmr.jobs[index] = stio->tmr.jobs[parent];
 | 
								stio->tmr.jobs[index] = stio->tmr.jobs[parent];
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
			if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
								if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
			stio->tmr.jobs[index].updater (stio, parent, index, &stio->tmr.jobs[index]);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* traverse up */
 | 
								/* traverse up */
 | 
				
			||||||
			index = parent;
 | 
								index = parent;
 | 
				
			||||||
@ -76,15 +62,7 @@ static stio_tmridx_t sift_up (stio_t* stio, stio_tmridx_t index, int notify)
 | 
				
			|||||||
		while (index > 0 && YOUNGER_THAN(&item, &stio->tmr.jobs[parent]));
 | 
							while (index > 0 && YOUNGER_THAN(&item, &stio->tmr.jobs[parent]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		stio->tmr.jobs[index] = item;
 | 
							stio->tmr.jobs[index] = item;
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
		if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
							if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
		/* we send no notification if the item is added with stio_instmrjob()
 | 
					 | 
				
			||||||
		 * or updated with stio_updtmrjob(). the caller of these functions
 | 
					 | 
				
			||||||
		 * must rely on the return value. */
 | 
					 | 
				
			||||||
		if (notify && index != old_index)
 | 
					 | 
				
			||||||
			stio->tmr.jobs[index].updater (stio, old_index, index, &stio->tmr.jobs[index]);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return index;
 | 
						return index;
 | 
				
			||||||
@ -97,20 +75,9 @@ static stio_tmridx_t sift_down (stio_t* stio, stio_tmridx_t index, int notify)
 | 
				
			|||||||
	if (index < base) /* at least 1 child is under the 'index' position */
 | 
						if (index < base) /* at least 1 child is under the 'index' position */
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		stio_tmrjob_t item;
 | 
							stio_tmrjob_t item;
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
		/* nothing */
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
		stio_tmridx_t old_index;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		item = stio->tmr.jobs[index];
 | 
							item = stio->tmr.jobs[index];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
		/* nothing */
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
		old_index = index;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		do
 | 
							do
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			stio_tmridx_t left, right, younger;
 | 
								stio_tmridx_t left, right, younger;
 | 
				
			||||||
@ -130,23 +97,14 @@ static stio_tmridx_t sift_down (stio_t* stio, stio_tmridx_t index, int notify)
 | 
				
			|||||||
			if (YOUNGER_THAN(&item, &stio->tmr.jobs[younger])) break;
 | 
								if (YOUNGER_THAN(&item, &stio->tmr.jobs[younger])) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			stio->tmr.jobs[index] = stio->tmr.jobs[younger];
 | 
								stio->tmr.jobs[index] = stio->tmr.jobs[younger];
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
			if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
								if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
			stio->tmr.jobs[index].updater (stio, younger, index, &stio->tmr.jobs[index]);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			index = younger;
 | 
								index = younger;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		while (index < base);
 | 
							while (index < base);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		stio->tmr.jobs[index] = item;
 | 
							stio->tmr.jobs[index] = item;
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
		if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
							if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
		if (notify && index != old_index)
 | 
					 | 
				
			||||||
			stio->tmr.jobs[index].updater (stio, old_index, index, &stio->tmr.jobs[index]);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return index;
 | 
						return index;
 | 
				
			||||||
@ -159,21 +117,13 @@ void stio_deltmrjob (stio_t* stio, stio_tmridx_t index)
 | 
				
			|||||||
	STIO_ASSERT (index < stio->tmr.size);
 | 
						STIO_ASSERT (index < stio->tmr.size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	item = stio->tmr.jobs[index];
 | 
						item = stio->tmr.jobs[index];
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
	if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = STIO_TMRIDX_INVALID;
 | 
						if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = STIO_TMRIDX_INVALID;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	stio->tmr.jobs[index].updater (stio, index, STIO_TMRIDX_INVALID, &stio->tmr.jobs[index]);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stio->tmr.size = stio->tmr.size - 1;
 | 
						stio->tmr.size = stio->tmr.size - 1;
 | 
				
			||||||
	if (stio->tmr.size > 0 && index != stio->tmr.size)
 | 
						if (stio->tmr.size > 0 && index != stio->tmr.size)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		stio->tmr.jobs[index] = stio->tmr.jobs[stio->tmr.size];
 | 
							stio->tmr.jobs[index] = stio->tmr.jobs[stio->tmr.size];
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
		if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
							if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
		stio->tmr.jobs[index].updater (stio, stio->tmr.size, index, &stio->tmr.jobs[index]);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		YOUNGER_THAN(&stio->tmr.jobs[index], &item)? sift_up(stio, index, 1): sift_down(stio, index, 1);
 | 
							YOUNGER_THAN(&stio->tmr.jobs[index], &item)? sift_up(stio, index, 1): sift_down(stio, index, 1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -202,9 +152,7 @@ stio_tmridx_t stio_instmrjob (stio_t* stio, const stio_tmrjob_t* job)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	stio->tmr.size = stio->tmr.size + 1;
 | 
						stio->tmr.size = stio->tmr.size + 1;
 | 
				
			||||||
	stio->tmr.jobs[index] = *job;
 | 
						stio->tmr.jobs[index] = *job;
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
	if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
						if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	return sift_up (stio, index, 0);
 | 
						return sift_up (stio, index, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -213,9 +161,7 @@ stio_tmridx_t stio_updtmrjob (stio_t* stio, stio_tmridx_t index, const stio_tmrj
 | 
				
			|||||||
	stio_tmrjob_t item;
 | 
						stio_tmrjob_t item;
 | 
				
			||||||
	item = stio->tmr.jobs[index];
 | 
						item = stio->tmr.jobs[index];
 | 
				
			||||||
	stio->tmr.jobs[index] = *job;
 | 
						stio->tmr.jobs[index] = *job;
 | 
				
			||||||
#if defined(STIO_USE_TMRJOB_IDXPTR)
 | 
					 | 
				
			||||||
	if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
						if (stio->tmr.jobs[index].idxptr) *stio->tmr.jobs[index].idxptr = index;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	return YOUNGER_THAN(job, &item)? sift_up (stio, index, 0): sift_down (stio, index, 0);
 | 
						return YOUNGER_THAN(job, &item)? sift_up (stio, index, 0): sift_down (stio, index, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -847,7 +847,6 @@ enqueue_data:
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		q->dstadr.ptr = STIO_NULL;
 | 
					 | 
				
			||||||
		q->dstadr.len = 0;
 | 
							q->dstadr.len = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -48,12 +48,11 @@ struct stio_ntime_t
 | 
				
			|||||||
	#define STIO_SYSHND_INVALID (-1)
 | 
						#define STIO_SYSHND_INVALID (-1)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct stio_adr_t stio_adr_t;
 | 
					typedef struct stio_adr_t stio_adr_t;
 | 
				
			||||||
struct stio_adr_t
 | 
					struct stio_adr_t
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	void* ptr;
 | 
					 | 
				
			||||||
	int len;
 | 
						int len;
 | 
				
			||||||
 | 
						void* ptr;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STIO_CONST_SWAP16(x) \
 | 
					#define STIO_CONST_SWAP16(x) \
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user