changed void to int for some event handlers.
deprecated the on_accepted callback for tcp. added stio_dev_send(), stio_tcp_dev_send() and changed stio_exec() to send queued messages moved tcp and udp defintions to stio-tcp.h and stio-udp.h respectively
This commit is contained in:
		@ -1,2 +1,2 @@
 | 
			
		||||
all:
 | 
			
		||||
	cc -o stio main.c stio.c stio-tcp.c stio-udp.c stio-sck.c
 | 
			
		||||
	cc -g -I. -Wall -o stio main.c stio.c stio-tcp.c stio-udp.c stio-sck.c
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,10 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "stio.h"
 | 
			
		||||
#include <stio.h>
 | 
			
		||||
#include <stio-tcp.h>
 | 
			
		||||
#include <stio-udp.h>
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
@ -50,13 +53,6 @@ static stio_mmgr_t mmgr =
 | 
			
		||||
	STIO_NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void tcp_on_connected (stio_dev_tcp_t* tcp)
 | 
			
		||||
{
 | 
			
		||||
	printf ("REALLY CONNECTED.......\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tcp_on_disconnected (stio_dev_tcp_t* tcp)
 | 
			
		||||
{
 | 
			
		||||
	if (tcp->state & STIO_DEV_TCP_LISTENING)
 | 
			
		||||
@ -76,12 +72,33 @@ static void tcp_on_disconnected (stio_dev_tcp_t* tcp)
 | 
			
		||||
		printf ("TCP DISCONNECTED - THIS MUST NOT HAPPEN (%d)\n", tcp->sck);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
static void tcp_on_accepted (stio_dev_tcp_t* tcp, stio_dev_tcp_t* clitcp)
 | 
			
		||||
static int tcp_on_connected (stio_dev_tcp_t* tcp)
 | 
			
		||||
{
 | 
			
		||||
	printf ("device accepted client device... ....\n");
 | 
			
		||||
 | 
			
		||||
	if (tcp->state & STIO_DEV_TCP_CONNECTED)
 | 
			
		||||
	{
 | 
			
		||||
printf ("device connected to a remote server... .asdfjkasdfkljasdlfkjasdj...\n");
 | 
			
		||||
	}
 | 
			
		||||
	else if (tcp->state & STIO_DEV_TCP_ACCEPTED)
 | 
			
		||||
	{
 | 
			
		||||
printf ("device accepted client device... .asdfjkasdfkljasdlfkjasdj...\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return stio_dev_tcp_send  (tcp, "hello", 5, STIO_NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int tcp_on_sent (stio_dev_tcp_t* tcp, void* sendctx)
 | 
			
		||||
{
 | 
			
		||||
	printf (">>> TCP SENT MESSAGE\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int tcp_on_recv (stio_dev_tcp_t* tcp, const void* buf, stio_len_t len)
 | 
			
		||||
{
 | 
			
		||||
	return stio_dev_tcp_send  (tcp, "HELLO", 5, STIO_NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static stio_t* g_stio;
 | 
			
		||||
 | 
			
		||||
static void handle_signal (int sig)
 | 
			
		||||
@ -99,6 +116,7 @@ int main ()
 | 
			
		||||
	struct sigaction sigact;
 | 
			
		||||
	stio_dev_tcp_connect_t tcp_conn;
 | 
			
		||||
	stio_dev_tcp_listen_t tcp_lstn;
 | 
			
		||||
	stio_dev_tcp_make_t tcp_make;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	stio = stio_open (&mmgr, 0, STIO_NULL);
 | 
			
		||||
@ -169,7 +187,13 @@ int main ()
 | 
			
		||||
	}
 | 
			
		||||
#else
 | 
			
		||||
	sin.sin_port = htons(1234);
 | 
			
		||||
	tcp = stio_dev_tcp_make (stio, (stio_sckadr_t*)&sin);
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	STIO_MEMCPY (&tcp_make.addr, &sin, STIO_SIZEOF(sin));
 | 
			
		||||
	tcp_make.on_sent = tcp_on_sent; /* inherit this handler */
 | 
			
		||||
	tcp_make.on_recv = tcp_on_recv; /* inherit this handler */
 | 
			
		||||
 | 
			
		||||
	tcp = stio_dev_tcp_make (stio, 0, &tcp_make);
 | 
			
		||||
	if (!tcp)
 | 
			
		||||
	{
 | 
			
		||||
		printf ("Cannot make tcp\n");
 | 
			
		||||
@ -177,7 +201,7 @@ int main ()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tcp_lstn.backlogs = 100;
 | 
			
		||||
	tcp_lstn.on_accepted = tcp_on_accepted;
 | 
			
		||||
	tcp_lstn.on_connected = tcp_on_connected;
 | 
			
		||||
	tcp_lstn.on_disconnected = tcp_on_disconnected;
 | 
			
		||||
	if (stio_dev_tcp_listen (tcp, &tcp_lstn) <= -1)
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
@ -62,6 +62,8 @@ stio_sckhnd_t stio_openasyncsck (int domain, int type);
 | 
			
		||||
void stio_closeasyncsck (stio_sckhnd_t sck);
 | 
			
		||||
int stio_makesckasync (stio_sckhnd_t sck);
 | 
			
		||||
 | 
			
		||||
int stio_getsckadrinfo (stio_t* stio, const stio_sckadr_t* addr, stio_scklen_t* len, stio_sckfam_t* family);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,10 @@
 | 
			
		||||
#include "stio-prv.h"
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------ */
 | 
			
		||||
void stio_closeasyncsck (stio_sckhnd_t sck)
 | 
			
		||||
@ -83,3 +86,23 @@ stio_sckhnd_t stio_openasyncsck (int domain, int type)
 | 
			
		||||
	return sck;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stio_getsckadrinfo (stio_t* stio, const stio_sckadr_t* addr, stio_scklen_t* len, stio_sckfam_t* family)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr* saddr = (struct sockaddr*)addr;
 | 
			
		||||
 | 
			
		||||
	if (saddr->sa_family == AF_INET) 
 | 
			
		||||
	{
 | 
			
		||||
		if (len) *len = STIO_SIZEOF(struct sockaddr_in);
 | 
			
		||||
		if (family) *family = AF_INET;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	else if (saddr->sa_family == AF_INET6)
 | 
			
		||||
	{
 | 
			
		||||
		if (len) *len =  STIO_SIZEOF(struct sockaddr_in6);
 | 
			
		||||
		if (family) *family = AF_INET6;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stio->errnum = STIO_EINVAL;
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,9 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "stio-prv.h"
 | 
			
		||||
#include "stio-tcp.h"
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
@ -38,38 +40,29 @@ static int tcp_make (stio_dev_t* dev, void* ctx)
 | 
			
		||||
/* NOTE: this can be extended to use ctx to tell between INET and INET6 or other types of sockets without creating a new dev method set. */
 | 
			
		||||
 | 
			
		||||
	stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
			
		||||
	struct sockaddr* saddr = (struct sockaddr*)ctx;
 | 
			
		||||
	stio_dev_tcp_make_t* arg = (stio_dev_tcp_make_t*)ctx;
 | 
			
		||||
	stio_scklen_t len;
 | 
			
		||||
	stio_sckfam_t family;
 | 
			
		||||
	int iv;
 | 
			
		||||
 | 
			
		||||
	tcp->sck = stio_openasyncsck (AF_INET, SOCK_STREAM);
 | 
			
		||||
	if (stio_getsckadrinfo(dev->stio, &arg->addr, &len, &family) <= -1) return -1;
 | 
			
		||||
 | 
			
		||||
	tcp->sck = stio_openasyncsck (family, SOCK_STREAM);
 | 
			
		||||
	if (tcp->sck == STIO_SCKHND_INVALID) goto oops;
 | 
			
		||||
 | 
			
		||||
	if (saddr)
 | 
			
		||||
	//setsockopt (udp->sck, SOL_SOCKET, SO_REUSEADDR, ...);
 | 
			
		||||
	// TRANSPARENT, ETC.
 | 
			
		||||
	iv = 1;
 | 
			
		||||
	if (setsockopt (tcp->sck, SOL_SOCKET, SO_REUSEADDR, &iv, STIO_SIZEOF(iv)) == -1 ||
 | 
			
		||||
	    bind (tcp->sck, (struct sockaddr*)&arg->addr, len) == -1) 
 | 
			
		||||
	{
 | 
			
		||||
		stio_scklen_t len;
 | 
			
		||||
		int iv;
 | 
			
		||||
 | 
			
		||||
		if (saddr->sa_family == AF_INET) 
 | 
			
		||||
			len = STIO_SIZEOF(struct sockaddr_in);
 | 
			
		||||
		else if (saddr->sa_family == AF_INET6)
 | 
			
		||||
			len = STIO_SIZEOF(struct sockaddr_in6);
 | 
			
		||||
		else	
 | 
			
		||||
		{
 | 
			
		||||
			dev->stio->errnum = STIO_EINVAL;
 | 
			
		||||
			goto oops;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//setsockopt (udp->sck, SOL_SOCKET, SO_REUSEADDR, ...);
 | 
			
		||||
		// TRANSPARENT, ETC.
 | 
			
		||||
 | 
			
		||||
		iv = 1;
 | 
			
		||||
		if (setsockopt (tcp->sck, SOL_SOCKET, SO_REUSEADDR, &iv, STIO_SIZEOF(iv)) == -1 ||
 | 
			
		||||
		    bind (tcp->sck, saddr, len) == -1) 
 | 
			
		||||
		{
 | 
			
		||||
			//dev->stio->errnum = STIO_EINVAL; TODO:
 | 
			
		||||
			goto oops;
 | 
			
		||||
		}
 | 
			
		||||
		// TODO: set errnum from errno ...
 | 
			
		||||
		//dev->stio->errnum = STIO_EINVAL;
 | 
			
		||||
		goto oops;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tcp->on_sent = arg->on_sent;
 | 
			
		||||
	tcp->on_recv = arg->on_recv; 
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
oops:
 | 
			
		||||
@ -92,7 +85,6 @@ static int tcp_make_accepted (stio_dev_t* dev, void* ctx)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void tcp_kill (stio_dev_t* dev)
 | 
			
		||||
{
 | 
			
		||||
	stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
			
		||||
@ -119,13 +111,13 @@ static stio_syshnd_t tcp_getsyshnd (stio_dev_t* dev)
 | 
			
		||||
static int tcp_recv (stio_dev_t* dev, void* buf, stio_len_t* len)
 | 
			
		||||
{
 | 
			
		||||
	stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
			
		||||
	int x;
 | 
			
		||||
	ssize_t x;
 | 
			
		||||
 | 
			
		||||
printf ("TCP RECV...\n");
 | 
			
		||||
	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;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -135,26 +127,29 @@ printf ("TCP RECV...\n");
 | 
			
		||||
 | 
			
		||||
static int tcp_send (stio_dev_t* dev, const void* data, stio_len_t* len)
 | 
			
		||||
{
 | 
			
		||||
	stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)tcp;
 | 
			
		||||
	stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
			
		||||
	ssize_t x;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	x = sendto (tcp->sck, data, *len, skad, stio_getskadlen(skad));
 | 
			
		||||
/* flags MSG_DONTROUTE, MSG_DONTWAIT, MSG_MORE, MSG_OOB, MSG_NOSIGNAL */
 | 
			
		||||
	x = sendto (tcp->sck, data, *len, 0, STIO_NULL, 0);
 | 
			
		||||
	if (x <= -1) 
 | 
			
		||||
	{
 | 
			
		||||
		if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0;  /* no data can be written */
 | 
			
		||||
		if (errno == EINTR) return 0;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
/* for UDP, if the data chunk can't be written at one go, it's actually a failure */
 | 
			
		||||
	if (x != *len) return -1; /* TODO: can i hava an indicator for this in stio? */
 | 
			
		||||
/***************/
 | 
			
		||||
{
 | 
			
		||||
static int x = 0;
 | 
			
		||||
if (x <= 2) { x++;  return 0; }
 | 
			
		||||
}
 | 
			
		||||
/***************/
 | 
			
		||||
 | 
			
		||||
	*len = x;
 | 
			
		||||
#endif
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int tcp_ioctl (stio_dev_t* dev, int cmd, void* arg)
 | 
			
		||||
{
 | 
			
		||||
	stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
			
		||||
@ -166,15 +161,10 @@ static int tcp_ioctl (stio_dev_t* dev, int cmd, void* arg)
 | 
			
		||||
			stio_dev_tcp_bind_t* bnd = (stio_dev_tcp_bind_t*)arg;
 | 
			
		||||
			struct sockaddr* sa = (struct sockaddr*)&bnd->addr;
 | 
			
		||||
			stio_scklen_t sl;
 | 
			
		||||
			stio_sckfam_t fam;
 | 
			
		||||
			int x;
 | 
			
		||||
 | 
			
		||||
			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;
 | 
			
		||||
			}
 | 
			
		||||
			if (stio_getsckadrinfo (dev->stio, &bnd->addr, &sl, &fam) <= -1) return -1;
 | 
			
		||||
 | 
			
		||||
		#if defined(_WIN32)
 | 
			
		||||
			/* TODO */
 | 
			
		||||
@ -257,7 +247,7 @@ static int tcp_ioctl (stio_dev_t* dev, int cmd, void* arg)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			tcp->state |= STIO_DEV_TCP_LISTENING;
 | 
			
		||||
			tcp->on_accepted = lstn->on_accepted;
 | 
			
		||||
			tcp->on_connected = lstn->on_connected;
 | 
			
		||||
			tcp->on_disconnected = lstn->on_disconnected;
 | 
			
		||||
			return 0;
 | 
			
		||||
		#endif
 | 
			
		||||
@ -267,21 +257,6 @@ static int tcp_ioctl (stio_dev_t* dev, int cmd, void* arg)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stio_dev_tcp_bind (stio_dev_tcp_t* tcp, stio_dev_tcp_bind_t* bind)
 | 
			
		||||
{
 | 
			
		||||
	return stio_dev_ioctl ((stio_dev_t*)tcp, STIO_DEV_TCP_BIND, bind);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stio_dev_tcp_connect (stio_dev_tcp_t* tcp, stio_dev_tcp_connect_t* conn)
 | 
			
		||||
{
 | 
			
		||||
	return stio_dev_ioctl ((stio_dev_t*)tcp, STIO_DEV_TCP_CONNECT, conn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stio_dev_tcp_listen (stio_dev_tcp_t* tcp, stio_dev_tcp_listen_t* lstn)
 | 
			
		||||
{
 | 
			
		||||
	return stio_dev_ioctl ((stio_dev_t*)tcp, STIO_DEV_TCP_LISTEN, lstn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static stio_dev_mth_t tcp_mth = 
 | 
			
		||||
{
 | 
			
		||||
@ -304,7 +279,6 @@ static stio_dev_mth_t tcp_acc_mth =
 | 
			
		||||
	tcp_send
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------ */
 | 
			
		||||
 | 
			
		||||
static int tcp_ready (stio_dev_t* dev, int events)
 | 
			
		||||
@ -325,7 +299,6 @@ printf ("TCP READY...%p\n", dev);
 | 
			
		||||
				printf ("CANNOT CONNECT ERRORCODE - %s\n", strerror(errcode));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
printf ("Cannot connect....\n");
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
		else if (events & STIO_DEV_EVENT_OUT)
 | 
			
		||||
@ -339,6 +312,8 @@ printf ("Cannot connect....\n");
 | 
			
		||||
			len = STIO_SIZEOF(errcode);
 | 
			
		||||
			if (getsockopt (tcp->sck, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1)
 | 
			
		||||
			{
 | 
			
		||||
				printf ("CANNOT GET SOCKET CONNECTION STATE....\n");
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
			else if (errcode == 0)
 | 
			
		||||
			{
 | 
			
		||||
@ -347,11 +322,15 @@ printf ("Cannot connect....\n");
 | 
			
		||||
 | 
			
		||||
				if (stio_dev_event ((stio_dev_t*)tcp, STIO_DEV_EVENT_MOD, STIO_DEV_EVENT_IN) <= -1)
 | 
			
		||||
				{
 | 
			
		||||
					printf ("CAANOT MANIPULTE EVENT ... KILL DEVICE...\n");
 | 
			
		||||
					printf ("CAANOT MANIPULTE EVENT ...\n");
 | 
			
		||||
					return -1;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (tcp->on_connected) tcp->on_connected (tcp);
 | 
			
		||||
				if (tcp->on_connected (tcp) <= -1) 
 | 
			
		||||
				{
 | 
			
		||||
					printf ("ON_CONNECTE HANDLER RETURNEF FAILURE...\n");
 | 
			
		||||
					return -1;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if (errcode == EINPROGRESS || errcode == EWOULDBLOCK)
 | 
			
		||||
			{
 | 
			
		||||
@ -371,6 +350,7 @@ printf ("Cannot connect....\n");
 | 
			
		||||
		stio_sckhnd_t clisck;
 | 
			
		||||
		stio_sckadr_t peer;
 | 
			
		||||
		stio_scklen_t addrlen;
 | 
			
		||||
		stio_dev_tcp_t* clitcp;
 | 
			
		||||
 | 
			
		||||
		/* this is a server(lisening) socket */
 | 
			
		||||
 | 
			
		||||
@ -379,53 +359,43 @@ printf ("Cannot connect....\n");
 | 
			
		||||
		if (clisck == -1)
 | 
			
		||||
		{
 | 
			
		||||
			if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0;
 | 
			
		||||
			if (errno == EINTR) return 0; /* if interrupted by a signal, treat it as if it's EINPROGRESS */
 | 
			
		||||
 | 
			
		||||
			/* TODO: set tcp->stio->errnum from errno */
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (tcp->on_accepted) 
 | 
			
		||||
 | 
			
		||||
		/* addr is the address of the peer */
 | 
			
		||||
		/* local addresss is inherited from the server */
 | 
			
		||||
		clitcp = (stio_dev_tcp_t*)stio_makedev (tcp->stio, STIO_SIZEOF(*tcp), &tcp_acc_mth, tcp->evcb, &clisck); 
 | 
			
		||||
		if (!clitcp) 
 | 
			
		||||
		{
 | 
			
		||||
			stio_dev_tcp_t* clitcp;
 | 
			
		||||
 | 
			
		||||
			/* addr is the address of the peer */
 | 
			
		||||
			/* local addresss is inherited from the server */
 | 
			
		||||
 | 
			
		||||
			clitcp = (stio_dev_tcp_t*)stio_makedev (tcp->stio, STIO_SIZEOF(*tcp), &tcp_acc_mth, tcp->evcb, &clisck); 
 | 
			
		||||
			if (!clitcp) 
 | 
			
		||||
			{
 | 
			
		||||
				close (clisck);
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			clitcp->state |= STIO_DEV_TCP_ACCEPTED;
 | 
			
		||||
			clitcp->peer = peer;
 | 
			
		||||
			clitcp->parent = tcp;
 | 
			
		||||
 | 
			
		||||
			/* inherit the parent's on_disconnected() handler.
 | 
			
		||||
			 * you can still change it inside the on_accepted handler */
 | 
			
		||||
			clitcp->on_disconnected = tcp->on_disconnected; 
 | 
			
		||||
 | 
			
		||||
			tcp->on_accepted (tcp, clitcp);
 | 
			
		||||
		}
 | 
			
		||||
		else 
 | 
			
		||||
		{
 | 
			
		||||
			/* no on_accepted callback is set. close the client socket 
 | 
			
		||||
			 * without doing anything meaningful */
 | 
			
		||||
			close (clisck);
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		clitcp->state |= STIO_DEV_TCP_ACCEPTED;
 | 
			
		||||
		clitcp->peer = peer;
 | 
			
		||||
		clitcp->parent = tcp;
 | 
			
		||||
 | 
			
		||||
		/* inherit some event handlers from the parent.
 | 
			
		||||
		 * you can still change them inside the on_connected handler */
 | 
			
		||||
		clitcp->on_connected = tcp->on_connected;
 | 
			
		||||
		clitcp->on_disconnected = tcp->on_disconnected; 
 | 
			
		||||
		clitcp->on_sent = tcp->on_sent;
 | 
			
		||||
		clitcp->on_recv = tcp->on_recv;
 | 
			
		||||
 | 
			
		||||
		if (clitcp->on_connected (clitcp) <= -1) stio_dev_tcp_kill (clitcp);
 | 
			
		||||
		return 0; /* success but don't invoke on_recv() */ 
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
printf ("READY WITH %d\n", events);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	if (events & (STIO_DEV_EVENT_ERR | STIO_DEV_EVENT_HUP))
 | 
			
		||||
	{
 | 
			
		||||
printf ("DISCONNECTED or ERROR \n");
 | 
			
		||||
		stio_killdev (dev->stio, dev);
 | 
			
		||||
		return 0;
 | 
			
		||||
		return -1; /* the caller must kill the device */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1; /* the device is ok. carry on reading or writing */
 | 
			
		||||
@ -434,21 +404,13 @@ printf ("DISCONNECTED or ERROR \n");
 | 
			
		||||
static int tcp_on_recv (stio_dev_t* dev, const void* data, stio_len_t len)
 | 
			
		||||
{
 | 
			
		||||
	stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
			
		||||
 | 
			
		||||
printf ("TCP dATA received %d bytes\n", (int)len);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
	return tcp->on_recv (tcp, data, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int tcp_on_sent (stio_dev_t* dev, const void* data, stio_len_t len)
 | 
			
		||||
static int tcp_on_sent (stio_dev_t* dev, void* sendctx)
 | 
			
		||||
{
 | 
			
		||||
	stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
			
		||||
 | 
			
		||||
	/* TODO: do something */
 | 
			
		||||
printf ("TCP dATA sent %d bytes\n", (int)len);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
	return tcp->on_sent (tcp, sendctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static stio_dev_evcb_t tcp_evcb =
 | 
			
		||||
@ -458,18 +420,32 @@ static stio_dev_evcb_t tcp_evcb =
 | 
			
		||||
	tcp_on_sent
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
stio_dev_tcp_t* stio_dev_tcp_make (stio_t* stio, stio_sckadr_t* addr)
 | 
			
		||||
stio_dev_tcp_t* stio_dev_tcp_make (stio_t* stio, stio_size_t xtnsize, const stio_dev_tcp_make_t* arg)
 | 
			
		||||
{
 | 
			
		||||
	stio_dev_tcp_t* tcp;
 | 
			
		||||
 | 
			
		||||
	tcp = (stio_dev_tcp_t*)stio_makedev (stio, STIO_SIZEOF(*tcp), &tcp_mth, &tcp_evcb, addr);
 | 
			
		||||
 | 
			
		||||
	return tcp;
 | 
			
		||||
	return (stio_dev_tcp_t*)stio_makedev (stio, STIO_SIZEOF(stio_dev_tcp_t) + xtnsize, &tcp_mth, &tcp_evcb, (void*)arg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void stio_dev_tcp_kill (stio_dev_tcp_t* tcp)
 | 
			
		||||
{
 | 
			
		||||
	stio_killdev (tcp->stio, (stio_dev_t*)tcp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stio_dev_tcp_bind (stio_dev_tcp_t* tcp, stio_dev_tcp_bind_t* bind)
 | 
			
		||||
{
 | 
			
		||||
	return stio_dev_ioctl ((stio_dev_t*)tcp, STIO_DEV_TCP_BIND, bind);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stio_dev_tcp_connect (stio_dev_tcp_t* tcp, stio_dev_tcp_connect_t* conn)
 | 
			
		||||
{
 | 
			
		||||
	return stio_dev_ioctl ((stio_dev_t*)tcp, STIO_DEV_TCP_CONNECT, conn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stio_dev_tcp_listen (stio_dev_tcp_t* tcp, stio_dev_tcp_listen_t* lstn)
 | 
			
		||||
{
 | 
			
		||||
	return stio_dev_ioctl ((stio_dev_t*)tcp, STIO_DEV_TCP_LISTEN, lstn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stio_dev_tcp_send (stio_dev_tcp_t* tcp, const void* data, stio_len_t len, void* sendctx)
 | 
			
		||||
{
 | 
			
		||||
	return stio_dev_send ((stio_dev_t*)tcp, data, len, sendctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										168
									
								
								stio/lib/stio-tcp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								stio/lib/stio-tcp.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,168 @@
 | 
			
		||||
/*
 | 
			
		||||
 * $Id$
 | 
			
		||||
 *
 | 
			
		||||
    Copyright (c) 2015-2016 Chung, Hyung-Hwan. All rights reserved.
 | 
			
		||||
 | 
			
		||||
    Redistribution and use in source and binary forms, with or without
 | 
			
		||||
    modification, are permitted provided that the following conditions
 | 
			
		||||
    are met:
 | 
			
		||||
    1. Redistributions of source code must retain the above copyright
 | 
			
		||||
       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
    2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
       documentation and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
    THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
 | 
			
		||||
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES
 | 
			
		||||
    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 | 
			
		||||
    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | 
			
		||||
    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 | 
			
		||||
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _STIO_TCP_H_
 | 
			
		||||
#define _STIO_TCP_H_
 | 
			
		||||
 | 
			
		||||
#include <stio.h>
 | 
			
		||||
 | 
			
		||||
enum stio_dev_tcp_ioctl_cmd_t
 | 
			
		||||
{
 | 
			
		||||
	STIO_DEV_TCP_BIND, 
 | 
			
		||||
	STIO_DEV_TCP_CONNECT,
 | 
			
		||||
	STIO_DEV_TCP_LISTEN
 | 
			
		||||
};
 | 
			
		||||
typedef enum stio_dev_tcp_ioctl_cmd_t stio_dev_tcp_ioctl_cmd_t;
 | 
			
		||||
 | 
			
		||||
enum stio_dev_tcp_state_t
 | 
			
		||||
{
 | 
			
		||||
	STIO_DEV_TCP_CONNECTING = (1 << 0),
 | 
			
		||||
	STIO_DEV_TCP_CONNECTED  = (1 << 1),
 | 
			
		||||
	STIO_DEV_TCP_LISTENING  = (1 << 2),
 | 
			
		||||
	STIO_DEV_TCP_ACCEPTED   = (1 << 3)
 | 
			
		||||
};
 | 
			
		||||
typedef enum stio_dev_tcp_state_t stio_dev_tcp_state_t;
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_tcp_t stio_dev_tcp_t;
 | 
			
		||||
 | 
			
		||||
typedef int (*stio_dev_tcp_on_connected_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_disconnected_t) (stio_dev_tcp_t* dev);
 | 
			
		||||
 | 
			
		||||
typedef int (*stio_dev_tcp_on_recv_t) (stio_dev_tcp_t* dev, const void* data, stio_len_t len);
 | 
			
		||||
typedef int (*stio_dev_tcp_on_sent_t) (stio_dev_tcp_t* dev, void* sendctx);
 | 
			
		||||
 | 
			
		||||
struct stio_dev_tcp_t
 | 
			
		||||
{
 | 
			
		||||
	STIO_DEV_HEADERS;
 | 
			
		||||
 | 
			
		||||
	stio_sckhnd_t sck;
 | 
			
		||||
 | 
			
		||||
	unsigned int state;
 | 
			
		||||
 | 
			
		||||
	/* peer address - valid if one of the followings is set:
 | 
			
		||||
	 *  STIO_DEV_TCP_ACCEPTED
 | 
			
		||||
	 *  STIO_DEV_TCP_CONNECTED
 | 
			
		||||
	 *  STIO_DEV_TCP_CONNECTING */
 | 
			
		||||
	stio_sckadr_t peer;
 | 
			
		||||
 | 
			
		||||
	/* parent tcp device. valid if STIO_DEV_TCP_ACCEPTED is set */
 | 
			
		||||
	stio_dev_tcp_t* parent;
 | 
			
		||||
 | 
			
		||||
	/** 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_tcp_on_connected_t on_connected;
 | 
			
		||||
 | 
			
		||||
	stio_dev_tcp_on_disconnected_t on_disconnected;
 | 
			
		||||
	stio_dev_tcp_on_recv_t on_recv;
 | 
			
		||||
	stio_dev_tcp_on_sent_t on_sent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_tcp_make_t stio_dev_tcp_make_t;
 | 
			
		||||
struct stio_dev_tcp_make_t
 | 
			
		||||
{
 | 
			
		||||
	/* TODO: options: REUSEADDR for binding?? */
 | 
			
		||||
	stio_sckadr_t addr; /* binding address. */
 | 
			
		||||
	stio_dev_tcp_on_sent_t on_sent;
 | 
			
		||||
	stio_dev_tcp_on_recv_t on_recv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_tcp_bind_t stio_dev_tcp_bind_t;
 | 
			
		||||
struct stio_dev_tcp_bind_t
 | 
			
		||||
{
 | 
			
		||||
	int options; /* TODO: REUSEADDR , TRANSPARENT, etc  or someting?? */
 | 
			
		||||
	stio_sckadr_t addr;
 | 
			
		||||
	/* TODO: add device name for BIND_TO_DEVICE */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_tcp_connect_t stio_dev_tcp_connect_t;
 | 
			
		||||
struct stio_dev_tcp_connect_t
 | 
			
		||||
{
 | 
			
		||||
	stio_sckadr_t addr;
 | 
			
		||||
/* TODO: add timeout */
 | 
			
		||||
	stio_dev_tcp_on_connected_t on_connected;
 | 
			
		||||
	stio_dev_tcp_on_disconnected_t on_disconnected;
 | 
			
		||||
	/* stio_dev_tcp_on_timeout_t on_timeout; should the timeout handler be here? what about write timeout? or accept timeout? */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_tcp_listen_t stio_dev_tcp_listen_t;
 | 
			
		||||
struct stio_dev_tcp_listen_t
 | 
			
		||||
{
 | 
			
		||||
	int backlogs;
 | 
			
		||||
	stio_dev_tcp_on_connected_t on_connected; /* optional, but new connections are dropped immediately without this */
 | 
			
		||||
	stio_dev_tcp_on_disconnected_t on_disconnected; /* should on_discconneted be part of on_accept_t??? */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_tcp_accept_t stio_dev_tcp_accept_t;
 | 
			
		||||
struct stio_dev_tcp_accept_t
 | 
			
		||||
{
 | 
			
		||||
	stio_syshnd_t   sck;
 | 
			
		||||
/* TODO: add timeout */
 | 
			
		||||
	stio_dev_tcp_t* parent; /* TODO: is this really needed? */
 | 
			
		||||
	stio_sckadr_t   peer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
stio_dev_tcp_t* stio_dev_tcp_make (
 | 
			
		||||
	stio_t*                    stio,
 | 
			
		||||
	stio_size_t                xtnsize,
 | 
			
		||||
	const stio_dev_tcp_make_t* data
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
void stio_dev_tcp_kill (
 | 
			
		||||
	stio_dev_tcp_t* tcp
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
int stio_dev_tcp_bind (
 | 
			
		||||
	stio_dev_tcp_t*         tcp,
 | 
			
		||||
	stio_dev_tcp_bind_t*    bind
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
int stio_dev_tcp_connect (
 | 
			
		||||
	stio_dev_tcp_t*         tcp,
 | 
			
		||||
	stio_dev_tcp_connect_t* conn);
 | 
			
		||||
 | 
			
		||||
int stio_dev_tcp_listen (
 | 
			
		||||
	stio_dev_tcp_t*         tcp,
 | 
			
		||||
	stio_dev_tcp_listen_t*  lstn
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
int stio_dev_tcp_send (
 | 
			
		||||
	stio_dev_tcp_t*  tcp,
 | 
			
		||||
	const void*      data,
 | 
			
		||||
	stio_len_t       len,
 | 
			
		||||
	void*            sendctx
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -26,6 +26,7 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "stio-prv.h"
 | 
			
		||||
#include "stio-udp.h"
 | 
			
		||||
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
@ -172,7 +173,7 @@ printf ("dATA received %d bytes\n", (int)len);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int udp_on_sent (stio_dev_t* dev, const void* data, stio_len_t len)
 | 
			
		||||
static int udp_on_sent (stio_dev_t* dev, void* msgid)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
@ -186,12 +187,11 @@ static stio_dev_evcb_t udp_evcb =
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
stio_dev_udp_t* stio_dev_udp_make (stio_t* stio, stio_sckadr_t* addr)
 | 
			
		||||
stio_dev_udp_t* stio_dev_udp_make (stio_t* stio, stio_size_t xtnsize, stio_sckadr_t* addr)
 | 
			
		||||
{
 | 
			
		||||
	stio_dev_udp_t* udp;
 | 
			
		||||
 | 
			
		||||
	udp = (stio_dev_udp_t*)stio_makedev (stio, STIO_SIZEOF(*udp), &udp_mth, &udp_evcb, addr);
 | 
			
		||||
	udp = (stio_dev_udp_t*)stio_makedev (stio, STIO_SIZEOF(*udp) + xtnsize, &udp_mth, &udp_evcb, addr);
 | 
			
		||||
 | 
			
		||||
	return udp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										62
									
								
								stio/lib/stio-udp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								stio/lib/stio-udp.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
/*
 | 
			
		||||
 * $Id$
 | 
			
		||||
 *
 | 
			
		||||
    Copyright (c) 2015-2016 Chung, Hyung-Hwan. All rights reserved.
 | 
			
		||||
 | 
			
		||||
    Redistribution and use in source and binary forms, with or without
 | 
			
		||||
    modification, are permitted provided that the following conditions
 | 
			
		||||
    are met:
 | 
			
		||||
    1. Redistributions of source code must retain the above copyright
 | 
			
		||||
       notice, this list of conditions and the following disclaimer.
 | 
			
		||||
    2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
       notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
       documentation and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
    THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
 | 
			
		||||
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES
 | 
			
		||||
    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 | 
			
		||||
    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | 
			
		||||
    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 | 
			
		||||
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef _STIO_UDP_H_
 | 
			
		||||
#define _STIO_UDP_H_
 | 
			
		||||
 | 
			
		||||
#include <stio.h>
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_udp_t stio_dev_udp_t;
 | 
			
		||||
 | 
			
		||||
struct stio_dev_udp_t
 | 
			
		||||
{
 | 
			
		||||
	STIO_DEV_HEADERS;
 | 
			
		||||
	stio_sckhnd_t sck;
 | 
			
		||||
	stio_sckadr_t peer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
stio_dev_udp_t* stio_dev_udp_make (
 | 
			
		||||
	stio_t*        stio,
 | 
			
		||||
	stio_size_t    xtnsize,
 | 
			
		||||
	stio_sckadr_t* addr
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
void stio_dev_udp_kill (
 | 
			
		||||
	stio_dev_udp_t* udp
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										176
									
								
								stio/lib/stio.c
									
									
									
									
									
								
							
							
						
						
									
										176
									
								
								stio/lib/stio.c
									
									
									
									
									
								
							@ -68,7 +68,6 @@ void stio_close (stio_t* stio)
 | 
			
		||||
	STIO_MMGR_FREE (stio->mmgr, stio);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
stio_dev_t* stio_makedev (stio_t* stio, stio_size_t dev_size, stio_dev_mth_t* dev_mth, stio_dev_evcb_t* dev_evcb, void* make_ctx)
 | 
			
		||||
{
 | 
			
		||||
	stio_dev_t* dev;
 | 
			
		||||
@ -90,6 +89,7 @@ stio_dev_t* stio_makedev (stio_t* stio, stio_size_t dev_size, stio_dev_mth_t* de
 | 
			
		||||
	dev->stio = stio;
 | 
			
		||||
	dev->mth = dev_mth;
 | 
			
		||||
	dev->evcb = dev_evcb;
 | 
			
		||||
	STIO_WQ_INIT(&dev->wq);
 | 
			
		||||
 | 
			
		||||
	/* call the callback function first */
 | 
			
		||||
	stio->errnum = STIO_ENOERR;
 | 
			
		||||
@ -133,7 +133,19 @@ void stio_killdev (stio_t* stio, stio_dev_t* dev)
 | 
			
		||||
{
 | 
			
		||||
	STIO_ASSERT (stio == dev->stio);
 | 
			
		||||
 | 
			
		||||
	/* delink the dev object first */
 | 
			
		||||
	/* clear pending send requests */
 | 
			
		||||
	while (!STIO_WQ_ISEMPTY(&dev->wq))
 | 
			
		||||
	{
 | 
			
		||||
		stio_wq_t* wq;
 | 
			
		||||
 | 
			
		||||
		wq = STIO_WQ_HEAD(&dev->wq);
 | 
			
		||||
printf ("DELETING UNSENT REQUETS...%p\n", wq);
 | 
			
		||||
		STIO_WQ_DEQ (&dev->wq);
 | 
			
		||||
 | 
			
		||||
		STIO_MMGR_FREE (stio->mmgr, wq);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* delink the dev object */
 | 
			
		||||
	if (dev->prev)
 | 
			
		||||
		dev->prev->next = dev->next;
 | 
			
		||||
	else
 | 
			
		||||
@ -165,12 +177,13 @@ void stio_killdev (stio_t* stio, stio_dev_t* dev)
 | 
			
		||||
 | 
			
		||||
int stio_prologue (stio_t* stio)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	/* TODO: */
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void stio_epilogue (stio_t* stio)
 | 
			
		||||
{
 | 
			
		||||
	/* TODO: */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stio_exec (stio_t* stio)
 | 
			
		||||
@ -202,8 +215,6 @@ int stio_exec (stio_t* stio)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	nentries = epoll_wait (stio->mux, stio->revs, STIO_COUNTOF(stio->revs), timeout);
 | 
			
		||||
	if (nentries <= -1)
 | 
			
		||||
	{
 | 
			
		||||
@ -227,23 +238,29 @@ int stio_exec (stio_t* stio)
 | 
			
		||||
 | 
			
		||||
			/* return value of ready()
 | 
			
		||||
			 *   <= -1 - failure. kill the device.
 | 
			
		||||
			 *   == 0 - ok. but don't invoke recv() or send(). if you want to kill the device within the ready callback, return 0.
 | 
			
		||||
			 *   == 0 - ok. but don't invoke recv() or send().
 | 
			
		||||
			 *   >= 1 - everything is ok. */
 | 
			
		||||
/* TODO: can the revs array contain the same file descriptor again??? */
 | 
			
		||||
			if ((x = dev->evcb->ready (dev, events)) <= -1) 
 | 
			
		||||
			{
 | 
			
		||||
				stio_killdev (stio, dev);
 | 
			
		||||
			else if (x >= 1) goto invoke_evcb;
 | 
			
		||||
				dev = STIO_NULL;
 | 
			
		||||
			}
 | 
			
		||||
			else if (x >= 1) 
 | 
			
		||||
			{
 | 
			
		||||
				goto invoke_evcb;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
		invoke_evcb:
 | 
			
		||||
			if (stio->revs[i].events & EPOLLPRI)
 | 
			
		||||
			if (dev && stio->revs[i].events & EPOLLPRI)
 | 
			
		||||
			{
 | 
			
		||||
				/* urgent data */
 | 
			
		||||
	printf ("has urgent data...\n");
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (stio->revs[i].events & EPOLLIN)
 | 
			
		||||
			if (dev && stio->revs[i].events & EPOLLIN)
 | 
			
		||||
			{
 | 
			
		||||
				stio_len_t len;
 | 
			
		||||
				int x;
 | 
			
		||||
@ -254,30 +271,93 @@ int stio_exec (stio_t* stio)
 | 
			
		||||
printf ("DATA...recv %d  length %d\n", (int)x, len);
 | 
			
		||||
				if (x <= -1)
 | 
			
		||||
				{
 | 
			
		||||
					/*TODO: waht to do? killdev? how to indicate an error? call on_recv? with erro rindicator?? */
 | 
			
		||||
					stio_killdev (stio, dev);
 | 
			
		||||
					dev = STIO_NULL;
 | 
			
		||||
				}
 | 
			
		||||
				else if (x == 0)
 | 
			
		||||
				{
 | 
			
		||||
					/* EOF received. kill the device. */
 | 
			
		||||
					stio_killdev (stio, dev);
 | 
			
		||||
					dev = STIO_NULL;
 | 
			
		||||
				}
 | 
			
		||||
				else if (x >= 1)
 | 
			
		||||
				{
 | 
			
		||||
					/* data available??? */
 | 
			
		||||
					dev->evcb->on_recv (dev, stio->bigbuf, len);
 | 
			
		||||
					if (dev->evcb->on_recv (dev, stio->bigbuf, len) <= -1)
 | 
			
		||||
					{
 | 
			
		||||
						stio_killdev (stio, dev);
 | 
			
		||||
						dev = STIO_NULL;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (stio->revs[i].events & EPOLLOUT)
 | 
			
		||||
			if (dev && stio->revs[i].events & EPOLLOUT)
 | 
			
		||||
			{
 | 
			
		||||
				/*
 | 
			
		||||
				if (there is data to write)
 | 
			
		||||
				while (!STIO_WQ_ISEMPTY(&dev->wq))
 | 
			
		||||
				{
 | 
			
		||||
					x = dev->mth->send (dev, stio->bigbuf, &len);
 | 
			
		||||
					stio_wq_t* q;
 | 
			
		||||
					const stio_uint8_t* uptr;
 | 
			
		||||
					stio_len_t urem, ulen;
 | 
			
		||||
					int x;
 | 
			
		||||
 | 
			
		||||
					q = STIO_WQ_HEAD(&dev->wq);
 | 
			
		||||
 | 
			
		||||
					uptr = q->ptr;
 | 
			
		||||
					urem = q->len;
 | 
			
		||||
 | 
			
		||||
				send_leftover:
 | 
			
		||||
					ulen = urem;
 | 
			
		||||
					x = dev->mth->send (dev, uptr, &ulen);
 | 
			
		||||
					if (x <= -1)
 | 
			
		||||
					{
 | 
			
		||||
						/* TODO: error handling? call callback? or what? */
 | 
			
		||||
						stio_killdev (stio, dev);
 | 
			
		||||
						dev = STIO_NULL;
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					else if (x == 0)
 | 
			
		||||
					{
 | 
			
		||||
						/* keep the left-over */
 | 
			
		||||
						STIO_MEMMOVE (q->ptr, uptr, urem);
 | 
			
		||||
						q->len = urem;
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						uptr += ulen;
 | 
			
		||||
						urem -= ulen;
 | 
			
		||||
 | 
			
		||||
					dev->evcb->on_sent (dv, stio->bigbuf, x);
 | 
			
		||||
				}*/
 | 
			
		||||
						if (urem <= 0)
 | 
			
		||||
						{
 | 
			
		||||
							int y;
 | 
			
		||||
 | 
			
		||||
							STIO_WQ_UNLINK (q); /* STIO_WQ_DEQ(&dev->wq); */
 | 
			
		||||
							y = dev->evcb->on_sent (dev, q->ctx);
 | 
			
		||||
							STIO_MMGR_FREE (dev->stio->mmgr, q);
 | 
			
		||||
 | 
			
		||||
							if (y <= -1)
 | 
			
		||||
							{
 | 
			
		||||
								stio_killdev (stio, dev);
 | 
			
		||||
								dev = STIO_NULL;
 | 
			
		||||
								break;
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						else goto send_leftover;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (dev && STIO_WQ_ISEMPTY(&dev->wq))
 | 
			
		||||
				{
 | 
			
		||||
					/* no pending request to write. 
 | 
			
		||||
					 * watch input only. disable output watching */
 | 
			
		||||
					if (stio_dev_event (dev, STIO_DEV_EVENT_MOD, STIO_DEV_EVENT_IN) <= -1)
 | 
			
		||||
					{
 | 
			
		||||
						/* TODO: call an error handler??? */
 | 
			
		||||
						stio_killdev (stio, dev);
 | 
			
		||||
						dev = STIO_NULL;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -301,7 +381,6 @@ int stio_loop (stio_t* stio)
 | 
			
		||||
 | 
			
		||||
	while (!stio->stopreq && stio->dev.head)
 | 
			
		||||
	{
 | 
			
		||||
printf ("executing stio_exec...%p \n", stio->dev.head);
 | 
			
		||||
		if (stio_exec (stio) <= -1) break;
 | 
			
		||||
		/* you can do other things here */
 | 
			
		||||
	}
 | 
			
		||||
@ -322,6 +401,7 @@ int stio_dev_event (stio_dev_t* dev, stio_dev_event_cmd_t cmd, int flags)
 | 
			
		||||
{
 | 
			
		||||
#if defined(_WIN32)
 | 
			
		||||
 | 
			
		||||
	/* TODO */
 | 
			
		||||
#else
 | 
			
		||||
	struct epoll_event ev;
 | 
			
		||||
	int epoll_op;
 | 
			
		||||
@ -330,6 +410,7 @@ int stio_dev_event (stio_dev_t* dev, stio_dev_event_cmd_t cmd, int flags)
 | 
			
		||||
#if defined(EPOLLRDHUP)
 | 
			
		||||
	ev.events |= EPOLLRDHUP;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (flags & STIO_DEV_EVENT_IN) ev.events |= EPOLLIN;
 | 
			
		||||
	if (flags & STIO_DEV_EVENT_OUT) ev.events |= EPOLLOUT;
 | 
			
		||||
	if (flags & STIO_DEV_EVENT_PRI) ev.events |= EPOLLPRI;
 | 
			
		||||
@ -363,3 +444,64 @@ int stio_dev_event (stio_dev_t* dev, stio_dev_event_cmd_t cmd, int flags)
 | 
			
		||||
	return 0;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int stio_dev_send (stio_dev_t* dev, const void* data, stio_len_t len, void* sendctx)
 | 
			
		||||
{
 | 
			
		||||
	const stio_uint8_t* uptr;
 | 
			
		||||
	stio_len_t urem, ulen;
 | 
			
		||||
	int x;
 | 
			
		||||
 | 
			
		||||
	uptr = data;
 | 
			
		||||
	urem = len;
 | 
			
		||||
 | 
			
		||||
	while (urem > 0)
 | 
			
		||||
	{
 | 
			
		||||
		ulen = urem;
 | 
			
		||||
		x = dev->mth->send (dev, data, &ulen);
 | 
			
		||||
		if (x <= -1) 
 | 
			
		||||
		{
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
		else if (x == 0)
 | 
			
		||||
		{
 | 
			
		||||
			stio_wq_t* q;
 | 
			
		||||
			int wq_empty;
 | 
			
		||||
 | 
			
		||||
			/* queue the uremaining data*/
 | 
			
		||||
			wq_empty = STIO_WQ_ISEMPTY(&dev->wq);
 | 
			
		||||
 | 
			
		||||
			q = (stio_wq_t*)STIO_MMGR_ALLOC (dev->stio->mmgr, STIO_SIZEOF(*q) + urem);
 | 
			
		||||
			if (!q)
 | 
			
		||||
			{
 | 
			
		||||
				dev->stio->errnum = STIO_ENOMEM;
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			q->ctx = sendctx;
 | 
			
		||||
			q->ptr = (stio_uint8_t*)(q + 1);
 | 
			
		||||
			q->len = urem;
 | 
			
		||||
			STIO_MEMCPY (q->ptr, uptr, urem);
 | 
			
		||||
 | 
			
		||||
			STIO_WQ_ENQ (&dev->wq, q);
 | 
			
		||||
			if (wq_empty)
 | 
			
		||||
			{
 | 
			
		||||
				if (stio_dev_event (dev, STIO_DEV_EVENT_MOD, STIO_DEV_EVENT_IN | STIO_DEV_EVENT_OUT) <= -1)
 | 
			
		||||
				{
 | 
			
		||||
					STIO_WQ_UNLINK (q); /* unlink the ENQed item */
 | 
			
		||||
					STIO_MMGR_FREE (dev->stio->mmgr, q);
 | 
			
		||||
					return -1;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		else 
 | 
			
		||||
		{
 | 
			
		||||
			urem -= ulen;
 | 
			
		||||
			uptr += ulen;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev->evcb->on_sent (dev, sendctx);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										247
									
								
								stio/lib/stio.h
									
									
									
									
									
								
							
							
						
						
									
										247
									
								
								stio/lib/stio.h
									
									
									
									
									
								
							@ -38,6 +38,8 @@ typedef signed char stio_int8_t;
 | 
			
		||||
typedef unsigned char stio_uint8_t;
 | 
			
		||||
typedef unsigned long stio_size_t;
 | 
			
		||||
#define STIO_MEMSET(dst,byte,count) memset(dst,byte,count)
 | 
			
		||||
#define STIO_MEMCPY(dst,src,count) memcpy(dst,src,count)
 | 
			
		||||
#define STIO_MEMMOVE(dst,src,count) memmove(dst,src,count)
 | 
			
		||||
#define STIO_ASSERT assert
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -84,6 +86,7 @@ typedef struct stio_sckadr_t stio_sckadr_t;
 | 
			
		||||
	typedef int stio_syshnd_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef int stio_sckfam_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------- */
 | 
			
		||||
@ -91,6 +94,8 @@ typedef struct stio_t stio_t;
 | 
			
		||||
typedef struct stio_dev_t stio_dev_t;
 | 
			
		||||
typedef struct stio_dev_mth_t stio_dev_mth_t;
 | 
			
		||||
typedef struct stio_dev_evcb_t stio_dev_evcb_t;
 | 
			
		||||
 | 
			
		||||
typedef struct stio_wq_t stio_wq_t;
 | 
			
		||||
typedef unsigned int stio_len_t; /* TODO: remove it? */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -109,35 +114,102 @@ typedef enum stio_errnum_t stio_errnum_t;
 | 
			
		||||
 | 
			
		||||
struct stio_dev_mth_t
 | 
			
		||||
{
 | 
			
		||||
	/* --------------------------------------------------------------------------------------------- */
 | 
			
		||||
	int           (*make)      (stio_dev_t* dev, void* ctx); /* mandatory. called in stix_makedev() */
 | 
			
		||||
	void          (*kill)      (stio_dev_t* dev); /* mandatory. called in stix_killdev(). called in stix_makedev() upon failure after make() success */
 | 
			
		||||
	stio_syshnd_t (*getsyshnd) (stio_dev_t* dev); /* mandatory. called in stix_makedev() after successful make() */
 | 
			
		||||
	/* ------------------------------------------------------------------ */
 | 
			
		||||
	int           (*make)         (stio_dev_t* dev, void* ctx); /* mandatory. called in stix_makedev() */
 | 
			
		||||
 | 
			
		||||
	/* ------------------------------------------------------------------ */
 | 
			
		||||
	void          (*kill)         (stio_dev_t* dev); /* mandatory. called in stix_killdev(). called in stix_makedev() upon failure after make() success */
 | 
			
		||||
 | 
			
		||||
	int           (*ioctl)     (stio_dev_t* dev, int cmd, void* arg);
 | 
			
		||||
	/* ------------------------------------------------------------------ */
 | 
			
		||||
#if 0
 | 
			
		||||
/* TODO: countsyshnds() if the device has multiple handles.
 | 
			
		||||
 * getsyshnd() to accept the handle id between 0 and countsysnhnds() - 1
 | 
			
		||||
 */
 | 
			
		||||
	int           (*countsyshnds) (stio_dev_t* dev); /* optional */
 | 
			
		||||
#endif
 | 
			
		||||
	stio_syshnd_t (*getsyshnd)    (stio_dev_t* dev); /* mandatory. called in stix_makedev() after successful make() */
 | 
			
		||||
 | 
			
		||||
	/* --------------------------------------------------------------------------------------------- */
 | 
			
		||||
	int           (*recv)      (stio_dev_t* dev, void* data, stio_len_t* len);
 | 
			
		||||
	/* --------------------------------------------------------------------------------------------- */
 | 
			
		||||
	int           (*send)      (stio_dev_t* dev, const void* data, stio_len_t* len);
 | 
			
		||||
	/* --------------------------------------------------------------------------------------------- */
 | 
			
		||||
	/* ------------------------------------------------------------------ */
 | 
			
		||||
	int           (*ioctl)        (stio_dev_t* dev, int cmd, void* arg);
 | 
			
		||||
 | 
			
		||||
	/* ------------------------------------------------------------------ */
 | 
			
		||||
	int           (*recv)         (stio_dev_t* dev, void* data, stio_len_t* len);
 | 
			
		||||
 | 
			
		||||
	/* ------------------------------------------------------------------ */
 | 
			
		||||
	int           (*send)         (stio_dev_t* dev, const void* data, stio_len_t* len);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct stio_dev_evcb_t
 | 
			
		||||
{
 | 
			
		||||
	int           (*ready)            (stio_dev_t* dev, int events);
 | 
			
		||||
	/*int           (*on_error)         (stio_dev_t* dev);
 | 
			
		||||
	int           (*on_hangup)        (stio_dev_t* dev);*/
 | 
			
		||||
	int           (*on_recv)          (stio_dev_t* dev, const void* data, stio_len_t len);
 | 
			
		||||
	int           (*on_sent)          (stio_dev_t* dev, const void* data, stio_len_t len);
 | 
			
		||||
	
 | 
			
		||||
	/* return -1 on failure. 0 or 1 on success.
 | 
			
		||||
	 * when 0 is returned, it doesn't attempt to perform actual I/O.
 | 
			
		||||
	 * when 1 is returned, it attempts to perform actual I/O.
 | 
			
		||||
	 * it must not kill the device */
 | 
			
		||||
	int           (*ready)        (stio_dev_t* dev, int events);
 | 
			
		||||
 | 
			
		||||
	/* return -1 on failure, 0 on success
 | 
			
		||||
	 * it must not kill the device */
 | 
			
		||||
	int           (*on_recv)      (stio_dev_t* dev, const void* data, stio_len_t len);
 | 
			
		||||
 | 
			
		||||
	/* return -1 on failure, 0 on success. 
 | 
			
		||||
	 * it must not kill the device */
 | 
			
		||||
	int           (*on_sent)      (stio_dev_t* dev, void* sendctx);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct stio_wq_t
 | 
			
		||||
{
 | 
			
		||||
	stio_wq_t*    next;
 | 
			
		||||
	stio_wq_t*    prev;
 | 
			
		||||
 | 
			
		||||
	stio_uint8_t* ptr;
 | 
			
		||||
	stio_len_t    len;
 | 
			
		||||
	void*         ctx;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define STIO_WQ_INIT(wq) ((wq)->next = (wq)->prev = (wq))
 | 
			
		||||
#define STIO_WQ_TAIL(wq) ((wq)->prev)
 | 
			
		||||
#define STIO_WQ_HEAD(wq) ((wq)->next)
 | 
			
		||||
#define STIO_WQ_ISEMPTY(wq) (STIO_WQ_HEAD(wq) == (wq))
 | 
			
		||||
#define STIO_WQ_ISNODE(wq,x) ((wq) != (x))
 | 
			
		||||
#define STIO_WQ_ISHEAD(wq,x) (STIO_WQ_HEAD(wq) == (x))
 | 
			
		||||
#define STIO_WQ_ISTAIL(wq,x) (STIO_WQ_TAIL(wq) == (x))
 | 
			
		||||
 | 
			
		||||
#define STIO_WQ_NEXT(x) ((x)->next)
 | 
			
		||||
#define STIO_WQ_PREV(x) ((x)->prev)
 | 
			
		||||
 | 
			
		||||
#define STIO_WQ_LINK(p,x,n) do { \
 | 
			
		||||
	stio_wq_t* pp = (p), * nn = (n); \
 | 
			
		||||
	(x)->prev = (p); \
 | 
			
		||||
	(x)->next = (n); \
 | 
			
		||||
	nn->prev = (x); \
 | 
			
		||||
	pp->next = (x); \
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
#define STIO_WQ_UNLINK(x) do { \
 | 
			
		||||
	stio_wq_t* pp = (x)->prev, * nn = (x)->next; \
 | 
			
		||||
	nn->prev = pp; pp->next = nn; \
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
#define STIO_WQ_REPL(o,n) do { \
 | 
			
		||||
	stio_wq_t* oo = (o), * nn = (n); \
 | 
			
		||||
	nn->next = oo->next; \
 | 
			
		||||
	nn->next->prev = nn; \
 | 
			
		||||
	nn->prev = oo->prev; \
 | 
			
		||||
	nn->prev->next = nn; \
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
/* insert an item at the back of the queue */
 | 
			
		||||
/*#define STIO_WQ_ENQ(wq,x)  STIO_WQ_LINK(STIO_WQ_TAIL(wq), x, STIO_WQ_TAIL(wq)->next)*/
 | 
			
		||||
#define STIO_WQ_ENQ(wq,x)  STIO_WQ_LINK(STIO_WQ_TAIL(wq), x, wq)
 | 
			
		||||
 | 
			
		||||
/* remove an item in the front from the queue */
 | 
			
		||||
#define STIO_WQ_DEQ(wq) STIO_WQ_UNLINK(STIO_WQ_HEAD(wq))
 | 
			
		||||
 | 
			
		||||
#define STIO_DEV_HEADERS \
 | 
			
		||||
	stio_t* stio; \
 | 
			
		||||
	stio_dev_mth_t* mth; \
 | 
			
		||||
	stio_dev_evcb_t* evcb; \
 | 
			
		||||
	stio_wq_t wq; \
 | 
			
		||||
	stio_dev_t* prev; \
 | 
			
		||||
	stio_dev_t* next 
 | 
			
		||||
 | 
			
		||||
@ -161,114 +233,10 @@ enum stio_dev_event_flag_t
 | 
			
		||||
	STIO_DEV_EVENT_PRI = (1 << 2),
 | 
			
		||||
	STIO_DEV_EVENT_HUP = (1 << 3),
 | 
			
		||||
	STIO_DEV_EVENT_ERR = (1 << 4)
 | 
			
		||||
	
 | 
			
		||||
};
 | 
			
		||||
typedef enum stio_dev_event_flag_t stio_dev_event_flag_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
enum stio_dev_tcp_ioctl_cmd_t
 | 
			
		||||
{
 | 
			
		||||
	STIO_DEV_TCP_BIND, 
 | 
			
		||||
	STIO_DEV_TCP_CONNECT,
 | 
			
		||||
	STIO_DEV_TCP_LISTEN
 | 
			
		||||
};
 | 
			
		||||
typedef enum stio_dev_tcp_ioctl_cmd_t stio_dev_tcp_ioctl_cmd_t;
 | 
			
		||||
 | 
			
		||||
enum stio_dev_tcp_state_t
 | 
			
		||||
{
 | 
			
		||||
	STIO_DEV_TCP_CONNECTING = (1 << 0),
 | 
			
		||||
	STIO_DEV_TCP_CONNECTED  = (1 << 1),
 | 
			
		||||
	STIO_DEV_TCP_LISTENING  = (1 << 2),
 | 
			
		||||
	STIO_DEV_TCP_ACCEPTED   = (1 << 3)
 | 
			
		||||
};
 | 
			
		||||
typedef enum stio_dev_tcp_state_t stio_dev_tcp_state_t;
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_tcp_t stio_dev_tcp_t;
 | 
			
		||||
 | 
			
		||||
typedef void (*stio_dev_tcp_on_connected_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_disconnected_t) (stio_dev_tcp_t* dev);
 | 
			
		||||
 | 
			
		||||
struct stio_dev_tcp_t
 | 
			
		||||
{
 | 
			
		||||
	STIO_DEV_HEADERS;
 | 
			
		||||
 | 
			
		||||
	stio_sckhnd_t sck;
 | 
			
		||||
 | 
			
		||||
	unsigned int state;
 | 
			
		||||
 | 
			
		||||
	/* peer address - valid if one of the followings is set:
 | 
			
		||||
	 *  STIO_DEV_TCP_ACCEPTED
 | 
			
		||||
	 *  STIO_DEV_TCP_CONNECTED
 | 
			
		||||
	 *  STIO_DEV_TCP_CONNECTING */
 | 
			
		||||
	stio_sckadr_t peer;
 | 
			
		||||
 | 
			
		||||
	/* parent tcp device. valid if STIO_DEV_TCP_ACCEPTED is set */
 | 
			
		||||
	stio_dev_tcp_t* parent;
 | 
			
		||||
 | 
			
		||||
	stio_dev_tcp_on_connected_t on_connected;
 | 
			
		||||
	stio_dev_tcp_on_disconnected_t on_disconnected;
 | 
			
		||||
	stio_dev_tcp_on_accepted_t on_accepted;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_tcp_bind_t stio_dev_tcp_bind_t;
 | 
			
		||||
struct stio_dev_tcp_bind_t
 | 
			
		||||
{
 | 
			
		||||
	int options; /* TODO: REUSEADDR , TRANSPARENT, etc  or someting?? */
 | 
			
		||||
	stio_sckadr_t addr;
 | 
			
		||||
	/* TODO: add device name for BIND_TO_DEVICE */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
struct stio_dev_tcp_make_t
 | 
			
		||||
{
 | 
			
		||||
	set io callbacks.. 
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_tcp_connect_t stio_dev_tcp_connect_t;
 | 
			
		||||
struct stio_dev_tcp_connect_t
 | 
			
		||||
{
 | 
			
		||||
	stio_sckadr_t addr;
 | 
			
		||||
	stio_dev_tcp_on_connected_t on_connected;
 | 
			
		||||
	stio_dev_tcp_on_disconnected_t on_disconnected;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_tcp_listen_t stio_dev_tcp_listen_t;
 | 
			
		||||
struct stio_dev_tcp_listen_t
 | 
			
		||||
{
 | 
			
		||||
	int backlogs;
 | 
			
		||||
	stio_dev_tcp_on_accepted_t on_accepted; /* optional, but new connections are dropped immediately without this */
 | 
			
		||||
	stio_dev_tcp_on_disconnected_t on_disconnected;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_tcp_accept_t stio_dev_tcp_accept_t;
 | 
			
		||||
struct stio_dev_tcp_accept_t
 | 
			
		||||
{
 | 
			
		||||
	stio_syshnd_t sck;
 | 
			
		||||
	stio_dev_tcp_t* parent;
 | 
			
		||||
	stio_sckadr_t peer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
typedef struct stio_dev_udp_t stio_dev_udp_t;
 | 
			
		||||
 | 
			
		||||
struct stio_dev_udp_t
 | 
			
		||||
{
 | 
			
		||||
	STIO_DEV_HEADERS;
 | 
			
		||||
	stio_sckhnd_t sck;
 | 
			
		||||
 | 
			
		||||
	stio_sckadr_t peer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
@ -283,6 +251,18 @@ void stio_close (
 | 
			
		||||
	stio_t* stio
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
int stio_exec (
 | 
			
		||||
	stio_t* stio
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
int stio_loop (
 | 
			
		||||
	stio_t* stio
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
void stio_stop (
 | 
			
		||||
	stio_t* stio
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
stio_dev_t* stio_makedev (
 | 
			
		||||
	stio_t*          stio,
 | 
			
		||||
	stio_size_t      dev_size,
 | 
			
		||||
@ -296,24 +276,23 @@ void stio_killdev (
 | 
			
		||||
	stio_dev_t* dev
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
stio_dev_tcp_t* stio_dev_tcp_make (
 | 
			
		||||
	stio_t*        stio,
 | 
			
		||||
	stio_sckadr_t* addr
 | 
			
		||||
int stio_dev_ioctl (
 | 
			
		||||
	stio_dev_t* dev,
 | 
			
		||||
	int         cmd,
 | 
			
		||||
	void*       arg
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
void stio_dev_tcp_kill (
 | 
			
		||||
	stio_dev_tcp_t* tcp
 | 
			
		||||
int stio_dev_event (
 | 
			
		||||
	stio_dev_t*          dev,
 | 
			
		||||
	stio_dev_event_cmd_t cmd,
 | 
			
		||||
	int                  flags
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
stio_dev_udp_t* stio_dev_udp_make (
 | 
			
		||||
	stio_t*        stio,
 | 
			
		||||
	stio_sckadr_t* addr
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
void stio_dev_udp_kill (
 | 
			
		||||
	stio_dev_udp_t* udp
 | 
			
		||||
int stio_dev_send (
 | 
			
		||||
	stio_dev_t*   dev,
 | 
			
		||||
	const void*   data,
 | 
			
		||||
	stio_len_t    len,
 | 
			
		||||
	void*         sendctx
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user