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 | ||||||
| { | { | ||||||
|  | 	int len; | ||||||
| 	void* ptr; | 	void* ptr; | ||||||
| 	int   len; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define STIO_CONST_SWAP16(x) \ | #define STIO_CONST_SWAP16(x) \ | ||||||
| @ -101,7 +100,7 @@ enum stio_errnum_t | |||||||
| 	STIO_ECONRF,     /* connection refused */ | 	STIO_ECONRF,     /* connection refused */ | ||||||
| 	STIO_ECONRS,     /* connection reset */ | 	STIO_ECONRS,     /* connection reset */ | ||||||
| 	STIO_ENOCAPA,    /* no capability */ | 	STIO_ENOCAPA,    /* no capability */ | ||||||
| 	STIO_ETMOUT,  /* timed out */ | 	STIO_ETMOUT,     /* timed out */ | ||||||
|  |  | ||||||
| 	STIO_EDEVMAKE, | 	STIO_EDEVMAKE, | ||||||
| 	STIO_EDEVERR, | 	STIO_EDEVERR, | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user