commited some initial works
This commit is contained in:
		
							
								
								
									
										2
									
								
								stio/lib/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								stio/lib/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					all:
 | 
				
			||||||
 | 
						cc -o stio main.c stio.c stio-tcp.c stio-udp.c stio-sck.c
 | 
				
			||||||
							
								
								
									
										175
									
								
								stio/lib/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								stio/lib/main.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,175 @@
 | 
				
			|||||||
 | 
					#include "stio.h"
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
 | 
					#include <signal.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void* mmgr_alloc (stio_mmgr_t* mmgr, stio_size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return malloc (size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void mmgr_free (stio_mmgr_t* mmgr, void* ptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return free (ptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static stio_mmgr_t mmgr = 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						mmgr_alloc,
 | 
				
			||||||
 | 
						mmgr_free,
 | 
				
			||||||
 | 
						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)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf ("SHUTTING DOWN THE SERVER SOCKET(%d)...\n", tcp->sck);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (tcp->state & STIO_DEV_TCP_CONNECTED)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf ("CLIENT ORIGINATING FROM HERE GOT DISCONNECTED(%d).......\n", tcp->sck);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (tcp->state & STIO_DEV_TCP_ACCEPTED)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf ("CLIENT BEING SERVED GOT DISCONNECTED(%d).......\n", tcp->sck);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						printf ("device accepted client device... ....\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static stio_t* g_stio;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_signal (int sig)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (g_stio) stio_stop (g_stio);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main ()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stio_t* stio;
 | 
				
			||||||
 | 
						stio_dev_udp_t* udp;
 | 
				
			||||||
 | 
						stio_dev_tcp_t* tcp;
 | 
				
			||||||
 | 
						struct sockaddr_in sin;
 | 
				
			||||||
 | 
						struct sigaction sigact;
 | 
				
			||||||
 | 
						stio_dev_tcp_connect_t tcp_conn;
 | 
				
			||||||
 | 
						stio_dev_tcp_listen_t tcp_lstn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stio = stio_open (&mmgr, 0, STIO_NULL);
 | 
				
			||||||
 | 
						if (!stio)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf ("Cannot open stio\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_stio = stio;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						STIO_MEMSET (&sigact, 0, STIO_SIZEOF(sigact));
 | 
				
			||||||
 | 
						sigact.sa_flags = SA_RESTART;
 | 
				
			||||||
 | 
						sigact.sa_handler = handle_signal;
 | 
				
			||||||
 | 
						sigaction (SIGINT, &sigact, STIO_NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						pkt = stio_pkt_open  (packet type, protocol type); // packet socket 
 | 
				
			||||||
 | 
						arp = stio_arp_open (binding_addr); // raw socket - arp filter
 | 
				
			||||||
 | 
						tcpd = stio_tcp_open (binding_addr); // crude tcp
 | 
				
			||||||
 | 
						udpd= stio_udp_open (binding_addr); // crude udp
 | 
				
			||||||
 | 
						httpd = stio_httpd_open (binding_addr);
 | 
				
			||||||
 | 
						httpsd = stio_httpsd_open (binding_addr);
 | 
				
			||||||
 | 
						radiusd = stio_radiusd_open (binding_addr); // udp - radius
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stio_register (stio, httpd);
 | 
				
			||||||
 | 
						stio_register (stio, httpsd);
 | 
				
			||||||
 | 
						stio_register (stio, radiusd);
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						STIO_MEMSET (&sin, 0, STIO_SIZEOF(sin));
 | 
				
			||||||
 | 
						sin.sin_family = AF_INET;
 | 
				
			||||||
 | 
						sin.sin_port = htons(1234);
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						udp = (stio_dev_udp_t*)stio_makedev (stio, STIO_SIZEOF(*udp), &udp_mth, &udp_evcb, &sin);
 | 
				
			||||||
 | 
						if (!udp)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf ("Cannot make udp\n");
 | 
				
			||||||
 | 
							goto oops;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						STIO_MEMSET (&sin, 0, STIO_SIZEOF(sin));
 | 
				
			||||||
 | 
						sin.sin_family = AF_INET;
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						tcp = (stio_dev_tcp_t*)stio_makedev (stio, STIO_SIZEOF(*tcp), &tcp_mth, &tcp_evcb, &sin);
 | 
				
			||||||
 | 
						if (!tcp)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf ("Cannot make tcp\n");
 | 
				
			||||||
 | 
							goto oops;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							struct sockaddr_in* p;
 | 
				
			||||||
 | 
							p = (struct sockaddr_in*)&tcp_conn.addr;
 | 
				
			||||||
 | 
							p->sin_family = AF_INET;
 | 
				
			||||||
 | 
							p->sin_port = htons(9999);
 | 
				
			||||||
 | 
							inet_pton (p->sin_family, "127.0.0.1", &p->sin_addr);
 | 
				
			||||||
 | 
							tcp_conn.on_connected = tcp_on_connected;
 | 
				
			||||||
 | 
							tcp_conn.on_disconnected = tcp_on_disconnected;
 | 
				
			||||||
 | 
							//tcp_conn.on_failure = .... (error code? etc???) or on_connect to access success or failure??? what is better??
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (stio_dev_tcp_connect (tcp, &tcp_conn) <= -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf ("stio_dev_tcp_connect() failed....\n");
 | 
				
			||||||
 | 
							goto oops;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						sin.sin_port = htons(1234);
 | 
				
			||||||
 | 
						tcp = stio_dev_tcp_make (stio, (stio_sckadr_t*)&sin);
 | 
				
			||||||
 | 
						if (!tcp)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf ("Cannot make tcp\n");
 | 
				
			||||||
 | 
							goto oops;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tcp_lstn.backlogs = 100;
 | 
				
			||||||
 | 
						tcp_lstn.on_accepted = tcp_on_accepted;
 | 
				
			||||||
 | 
						tcp_lstn.on_disconnected = tcp_on_disconnected;
 | 
				
			||||||
 | 
						if (stio_dev_tcp_listen (tcp, &tcp_lstn) <= -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							printf ("stio_dev_tcp_listen() failed....\n");
 | 
				
			||||||
 | 
							goto oops;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stio_loop (stio);
 | 
				
			||||||
 | 
						////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_stio = STIO_NULL;
 | 
				
			||||||
 | 
						stio_close (stio);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					oops:
 | 
				
			||||||
 | 
						g_stio = STIO_NULL;
 | 
				
			||||||
 | 
						stio_close (stio);
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										44
									
								
								stio/lib/stio-prv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								stio/lib/stio-prv.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					#ifndef _STIO_PRV_H_
 | 
				
			||||||
 | 
					#define _STIO_PRV_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "stio.h"
 | 
				
			||||||
 | 
					#include <sys/epoll.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct stio_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_mmgr_t* mmgr;
 | 
				
			||||||
 | 
						stio_errnum_t errnum;
 | 
				
			||||||
 | 
						int stopreq;  /* stop request to abort stio_loop() */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stio_dev_t* head;
 | 
				
			||||||
 | 
							stio_dev_t* tail;
 | 
				
			||||||
 | 
						} dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stio_uint8_t bigbuf[65535]; /* make this dynamic depending on devices added. device may indicate a buffer size required??? */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_WIN32)
 | 
				
			||||||
 | 
						HANDLE iocp;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						int mux;
 | 
				
			||||||
 | 
						struct epoll_event revs[100];
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stio_sckhnd_t stio_openasyncsck (int domain, int type);
 | 
				
			||||||
 | 
					void stio_closeasyncsck (stio_sckhnd_t sck);
 | 
				
			||||||
 | 
					int stio_makesckasync (stio_sckhnd_t sck);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										58
									
								
								stio/lib/stio-sck.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								stio/lib/stio-sck.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					#include "stio-prv.h"
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					void stio_closeasyncsck (stio_sckhnd_t sck)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if defined(_WIN32)
 | 
				
			||||||
 | 
						closesocket (sck);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						close (sck);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int stio_makesckasync (stio_sckhnd_t sck)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((flags = fcntl (sck, F_GETFL)) <= -1 ||
 | 
				
			||||||
 | 
						    (flags = fcntl (sck, F_SETFL, flags | O_NONBLOCK)) <= -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* stio_seterrnum (dev->stio, STIO_ESYSERR); or translate errno to stio errnum */
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stio_sckhnd_t stio_openasyncsck (int domain, int type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_sckhnd_t sck;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_WIN32)
 | 
				
			||||||
 | 
						sck = WSASocket (domain, type, 0, NULL, 0, WSA_FLAG_OVERLAPPED /*| WSA_FLAG_NO_HANDLE_INHERIT*/);
 | 
				
			||||||
 | 
						if (sck == STIO_SCKHND_INVALID) 
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* stio_seterrnum (dev->stio, STIO_ESYSERR); or translate errno to stio errnum */
 | 
				
			||||||
 | 
							return STIO_SCKHND_INVALID;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						sck = socket (domain, type, 0); /* NO CLOEXEC or somethign */
 | 
				
			||||||
 | 
						if (sck == STIO_SCKHND_INVALID) 
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* stio_seterrnum (dev->stio, STIO_ESYSERR); or translate errno to stio errnum */
 | 
				
			||||||
 | 
							return STIO_SCKHND_INVALID;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (stio_makesckasync (sck) <= -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							close (sck);
 | 
				
			||||||
 | 
							return STIO_SCKHND_INVALID;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sck;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										450
									
								
								stio/lib/stio-tcp.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										450
									
								
								stio/lib/stio-tcp.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,450 @@
 | 
				
			|||||||
 | 
					#include "stio-prv.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tcp->sck = stio_openasyncsck (AF_INET, SOCK_STREAM);
 | 
				
			||||||
 | 
						if (tcp->sck == STIO_SCKHND_INVALID) goto oops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (saddr)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							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;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					oops:
 | 
				
			||||||
 | 
						if (tcp->sck != STIO_SCKHND_INVALID)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stio_closeasyncsck (tcp->sck);
 | 
				
			||||||
 | 
							tcp->sck = STIO_SCKHND_INVALID;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int tcp_make_accepted (stio_dev_t* dev, void* ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
				
			||||||
 | 
						stio_syshnd_t* sck = (stio_syshnd_t*)ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tcp->sck = *sck;
 | 
				
			||||||
 | 
						if (stio_makesckasync (tcp->sck) <= -1) return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void tcp_kill (stio_dev_t* dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tcp->state | (STIO_DEV_TCP_ACCEPTED | STIO_DEV_TCP_CONNECTED))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (tcp->on_disconnected) tcp->on_disconnected (tcp);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tcp->sck != STIO_SCKHND_INVALID) 
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stio_closeasyncsck (tcp->sck);
 | 
				
			||||||
 | 
							tcp->sck = STIO_SCKHND_INVALID;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static stio_syshnd_t tcp_getsyshnd (stio_dev_t* dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
				
			||||||
 | 
						return (stio_syshnd_t)tcp->sck;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					printf ("TCP RECV...\n");
 | 
				
			||||||
 | 
						x = recv (tcp->sck, buf, *len, 0);
 | 
				
			||||||
 | 
						if (x <= -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0;  /* no data available */
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*len = x;
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
						ssize_t x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
						x = sendto (tcp->sck, data, *len, skad, stio_getskadlen(skad));
 | 
				
			||||||
 | 
						if (x <= -1) 
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0;  /* no data can be written */
 | 
				
			||||||
 | 
							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? */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (cmd)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							case STIO_DEV_TCP_BIND:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								stio_dev_tcp_bind_t* bnd = (stio_dev_tcp_bind_t*)arg;
 | 
				
			||||||
 | 
								struct sockaddr* sa = (struct sockaddr*)&bnd->addr;
 | 
				
			||||||
 | 
								stio_scklen_t sl;
 | 
				
			||||||
 | 
								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 defined(_WIN32)
 | 
				
			||||||
 | 
								/* TODO */
 | 
				
			||||||
 | 
							#else
 | 
				
			||||||
 | 
								/* the socket is already non-blocking */
 | 
				
			||||||
 | 
								x = bind (tcp->sck, sa, sl);
 | 
				
			||||||
 | 
								if (x == -1)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									/* TODO: set dev->errnum from errno */
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case STIO_DEV_TCP_CONNECT:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								stio_dev_tcp_connect_t* conn = (stio_dev_tcp_connect_t*)arg;
 | 
				
			||||||
 | 
								struct sockaddr* sa = (struct sockaddr*)&conn->addr;
 | 
				
			||||||
 | 
								stio_scklen_t sl;
 | 
				
			||||||
 | 
								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 defined(_WIN32)
 | 
				
			||||||
 | 
								/* TODO */
 | 
				
			||||||
 | 
							#else
 | 
				
			||||||
 | 
								/* the socket is already non-blocking */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								x = connect (tcp->sck, sa, sl);
 | 
				
			||||||
 | 
								if (x == -1)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (errno == EINPROGRESS || errno == EWOULDBLOCK)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										if (stio_dev_event ((stio_dev_t*)tcp, STIO_DEV_EVENT_MOD, STIO_DEV_EVENT_IN | STIO_DEV_EVENT_OUT) >= 0)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											tcp->state |= STIO_DEV_TCP_CONNECTING;
 | 
				
			||||||
 | 
											tcp->peer = conn->addr;
 | 
				
			||||||
 | 
											tcp->on_connected = conn->on_connected;
 | 
				
			||||||
 | 
											tcp->on_disconnected = conn->on_disconnected;
 | 
				
			||||||
 | 
											return 0;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/* TODO: set dev->errnum from errno */
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* connected immediately */
 | 
				
			||||||
 | 
								tcp->state |= STIO_DEV_TCP_CONNECTED;
 | 
				
			||||||
 | 
								tcp->peer = conn->addr;
 | 
				
			||||||
 | 
								tcp->on_connected = conn->on_connected;
 | 
				
			||||||
 | 
								tcp->on_disconnected = conn->on_disconnected;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							#endif
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case STIO_DEV_TCP_LISTEN:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								stio_dev_tcp_listen_t* lstn = (stio_dev_tcp_listen_t*)arg;
 | 
				
			||||||
 | 
								int x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							#if defined(_WIN32)
 | 
				
			||||||
 | 
								/* TODO */
 | 
				
			||||||
 | 
							#else
 | 
				
			||||||
 | 
								x = listen (tcp->sck, lstn->backlogs);
 | 
				
			||||||
 | 
								if (x == -1) 
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									/* TODO: set tcp->stio->errnum */
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								tcp->state |= STIO_DEV_TCP_LISTENING;
 | 
				
			||||||
 | 
								tcp->on_accepted = lstn->on_accepted;
 | 
				
			||||||
 | 
								tcp->on_disconnected = lstn->on_disconnected;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							#endif
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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 = 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						tcp_make,
 | 
				
			||||||
 | 
						tcp_kill,
 | 
				
			||||||
 | 
						tcp_getsyshnd,
 | 
				
			||||||
 | 
						tcp_ioctl, 
 | 
				
			||||||
 | 
						tcp_recv,
 | 
				
			||||||
 | 
						tcp_send
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* accepted tcp socket */
 | 
				
			||||||
 | 
					static stio_dev_mth_t tcp_acc_mth =
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						tcp_make_accepted,
 | 
				
			||||||
 | 
						tcp_kill,
 | 
				
			||||||
 | 
						tcp_getsyshnd,
 | 
				
			||||||
 | 
						tcp_ioctl, 
 | 
				
			||||||
 | 
						tcp_recv,
 | 
				
			||||||
 | 
						tcp_send
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int tcp_ready (stio_dev_t* dev, int events)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
				
			||||||
 | 
					printf ("TCP READY...%p\n", dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tcp->state & STIO_DEV_TCP_CONNECTING)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (events & (STIO_DEV_EVENT_ERR | STIO_DEV_EVENT_HUP | STIO_DEV_EVENT_PRI | STIO_DEV_EVENT_IN))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								int errcode;
 | 
				
			||||||
 | 
								stio_scklen_t len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								len = STIO_SIZEOF(errcode);
 | 
				
			||||||
 | 
								if (getsockopt (tcp->sck, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									printf ("CANNOT CONNECT ERRORCODE - %s\n", strerror(errcode));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					printf ("Cannot connect....\n");
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (events & STIO_DEV_EVENT_OUT)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								int errcode;
 | 
				
			||||||
 | 
								stio_scklen_t len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								STIO_ASSERT (!(tcp->state & STIO_DEV_TCP_CONNECTED));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printf ("XXXXXXXXXXXXXXX CONNECTED...\n");
 | 
				
			||||||
 | 
								len = STIO_SIZEOF(errcode);
 | 
				
			||||||
 | 
								if (getsockopt (tcp->sck, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if (errcode == 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									tcp->state &= ~STIO_DEV_TCP_CONNECTING;
 | 
				
			||||||
 | 
									tcp->state |= STIO_DEV_TCP_CONNECTED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (stio_dev_event ((stio_dev_t*)tcp, STIO_DEV_EVENT_MOD, STIO_DEV_EVENT_IN) <= -1)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										printf ("CAANOT MANIPULTE EVENT ... KILL DEVICE...\n");
 | 
				
			||||||
 | 
										return -1;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (tcp->on_connected) tcp->on_connected (tcp);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if (errcode == EINPROGRESS || errcode == EWOULDBLOCK)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									/* still in progress */
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									printf ("failed to get SOCKET PROGRESS CODE...\n");
 | 
				
			||||||
 | 
									return -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return 0; /* success but don't invoke on_recv() */ 
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (tcp->state & STIO_DEV_TCP_LISTENING)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stio_sckhnd_t clisck;
 | 
				
			||||||
 | 
							stio_sckadr_t peer;
 | 
				
			||||||
 | 
							stio_scklen_t addrlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* this is a server(lisening) socket */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							addrlen = STIO_SIZEOF(peer);
 | 
				
			||||||
 | 
							clisck = accept (tcp->sck, (struct sockaddr*)&peer, &addrlen);
 | 
				
			||||||
 | 
							if (clisck == -1)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* TODO: set tcp->stio->errnum from errno */
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (tcp->on_accepted) 
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								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 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 device is ok. carry on reading or writing */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int tcp_on_sent (stio_dev_t* dev, const void* data, stio_len_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_tcp_t* tcp = (stio_dev_tcp_t*)dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* TODO: do something */
 | 
				
			||||||
 | 
					printf ("TCP dATA sent %d bytes\n", (int)len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static stio_dev_evcb_t tcp_evcb =
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						tcp_ready,
 | 
				
			||||||
 | 
						tcp_on_recv,
 | 
				
			||||||
 | 
						tcp_on_sent
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stio_dev_tcp_t* stio_dev_tcp_make (stio_t* stio, stio_sckadr_t* addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_tcp_t* tcp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tcp = (stio_dev_tcp_t*)stio_makedev (stio, STIO_SIZEOF(*tcp), &tcp_mth, &tcp_evcb, addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return tcp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stio_dev_tcp_kill (stio_dev_tcp_t* tcp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_killdev (tcp->stio, (stio_dev_t*)tcp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										176
									
								
								stio/lib/stio-udp.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								stio/lib/stio-udp.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,176 @@
 | 
				
			|||||||
 | 
					#include "stio-prv.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int udp_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_udp_t* udp = (stio_dev_udp_t*)dev;
 | 
				
			||||||
 | 
						struct sockaddr* saddr = (struct sockaddr*)ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						udp->sck = stio_openasyncsck (AF_INET, SOCK_DGRAM);
 | 
				
			||||||
 | 
						if (udp->sck == STIO_SCKHND_INVALID) goto oops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (saddr)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stio_scklen_t len;
 | 
				
			||||||
 | 
							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, ...);
 | 
				
			||||||
 | 
							if (bind (udp->sck, saddr, len) == -1) 
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								//dev->stio->errnum = STIO_EINVAL; TODO:
 | 
				
			||||||
 | 
								goto oops;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					oops:
 | 
				
			||||||
 | 
						if (udp->sck != STIO_SCKHND_INVALID)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stio_closeasyncsck (udp->sck);
 | 
				
			||||||
 | 
							udp->sck = STIO_SCKHND_INVALID;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void udp_kill (stio_dev_t* dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_udp_t* udp = (stio_dev_udp_t*)dev;
 | 
				
			||||||
 | 
						if (udp->sck != STIO_SCKHND_INVALID) 
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stio_closeasyncsck (udp->sck);
 | 
				
			||||||
 | 
							udp->sck = STIO_SCKHND_INVALID;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static stio_syshnd_t udp_getsyshnd (stio_dev_t* dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_udp_t* udp = (stio_dev_udp_t*)dev;
 | 
				
			||||||
 | 
						return (stio_syshnd_t)udp->sck;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int udp_recv (stio_dev_t* dev, void* buf, stio_len_t* len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_udp_t* udp = (stio_dev_udp_t*)dev;
 | 
				
			||||||
 | 
						stio_scklen_t addrlen;
 | 
				
			||||||
 | 
						int x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					printf ("UDP RECVFROM...\n");
 | 
				
			||||||
 | 
						addrlen = STIO_SIZEOF(udp->peer);
 | 
				
			||||||
 | 
						x = recvfrom (udp->sck, buf, *len, 0, (struct sockaddr*)&udp->peer, &addrlen);
 | 
				
			||||||
 | 
						if (x <= -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0;  /* no data available */
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*len = x;
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int udp_send (stio_dev_t* dev, const void* data, stio_len_t* len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_dev_udp_t* udp = (stio_dev_udp_t*)udp;
 | 
				
			||||||
 | 
						ssize_t x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
						x = sendto (udp->sck, data, *len, skad, stio_getskadlen(skad));
 | 
				
			||||||
 | 
						if (x <= -1) 
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (errno == EINPROGRESS || errno == EWOULDBLOCK) return 0;  /* no data can be written */
 | 
				
			||||||
 | 
							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? */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*len = x;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int udp_ioctl (stio_dev_t* dev, int cmd, void* arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -----------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static stio_dev_mth_t udp_mth = 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						udp_make,
 | 
				
			||||||
 | 
						udp_kill,
 | 
				
			||||||
 | 
						udp_getsyshnd,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						udp_ioctl,     /* ioctl */
 | 
				
			||||||
 | 
						udp_recv,
 | 
				
			||||||
 | 
						udp_send
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int udp_ready (stio_dev_t* dev, int events)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (events & STIO_DEV_EVENT_ERR) printf ("UDP READY ERROR.....\n");
 | 
				
			||||||
 | 
						if (events & STIO_DEV_EVENT_HUP) printf ("UDP READY HANGUP.....\n");
 | 
				
			||||||
 | 
						if (events & STIO_DEV_EVENT_PRI) printf ("UDP READY PRI.....\n");
 | 
				
			||||||
 | 
						if (events & STIO_DEV_EVENT_IN) printf ("UDP READY IN.....\n");
 | 
				
			||||||
 | 
						if (events & STIO_DEV_EVENT_OUT) printf ("UDP READY OUT.....\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int udp_on_recv (stio_dev_t* dev, const void* data, stio_len_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					printf ("dATA received %d bytes\n", (int)len);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int udp_on_sent (stio_dev_t* dev, const void* data, stio_len_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static stio_dev_evcb_t udp_evcb =
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						udp_ready,
 | 
				
			||||||
 | 
						udp_on_recv,
 | 
				
			||||||
 | 
						udp_on_sent
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stio_dev_udp_t* stio_dev_udp_make (stio_t* stio, 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return udp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stio_dev_udp_kill (stio_dev_udp_t* udp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_killdev (udp->stio, (stio_dev_t*)udp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										347
									
								
								stio/lib/stio.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										347
									
								
								stio/lib/stio.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,347 @@
 | 
				
			|||||||
 | 
					#include "stio-prv.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <sys/epoll.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
 | 
					#include <signal.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stio_t* stio_open (stio_mmgr_t* mmgr, stio_size_t xtnsize, stio_errnum_t* errnum)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_t* stio;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stio = STIO_MMGR_ALLOC (mmgr, STIO_SIZEOF(*stio));
 | 
				
			||||||
 | 
						if (!stio) 
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (errnum) *errnum = STIO_ENOMEM;
 | 
				
			||||||
 | 
							return STIO_NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						STIO_MEMSET (stio, 0, STIO_SIZEOF(*stio));
 | 
				
			||||||
 | 
						stio->mmgr = mmgr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stio->mux = epoll_create (1000);
 | 
				
			||||||
 | 
						if (stio->mux == -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							//if (errnum) *errnum = XXXXX
 | 
				
			||||||
 | 
							STIO_MMGR_FREE (stio->mmgr, stio);
 | 
				
			||||||
 | 
							return STIO_NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stio;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stio_close (stio_t* stio)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						while (stio->dev.tail)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stio_killdev (stio, stio->dev.tail);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						close (stio->mux);
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dev_size < STIO_SIZEOF(stio_dev_t)) 
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stio->errnum = STIO_EINVAL;
 | 
				
			||||||
 | 
							return STIO_NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dev = STIO_MMGR_ALLOC (stio->mmgr, dev_size);
 | 
				
			||||||
 | 
						if (!dev)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stio->errnum = STIO_ENOMEM;
 | 
				
			||||||
 | 
							return STIO_NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						STIO_MEMSET (dev, 0, dev_size);
 | 
				
			||||||
 | 
						dev->stio = stio;
 | 
				
			||||||
 | 
						dev->mth = dev_mth;
 | 
				
			||||||
 | 
						dev->evcb = dev_evcb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* call the callback function first */
 | 
				
			||||||
 | 
						stio->errnum = STIO_ENOERR;
 | 
				
			||||||
 | 
						if (dev->mth->make (dev, make_ctx) <= -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (stio->errnum == STIO_ENOERR) stio->errnum = STIO_EDEVMAKE;
 | 
				
			||||||
 | 
							goto oops;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* ------------------------------------ */
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						#if defined(_WIN32)
 | 
				
			||||||
 | 
							if (CreateIoCompletionPort ((HANDLE)dev->mth->getsyshnd(dev), stio->iocp, STIO_IOCP_KEY, 0) == NULL)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* TODO: set errnum from GetLastError()... */
 | 
				
			||||||
 | 
								goto oops_after_make;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
						#else
 | 
				
			||||||
 | 
							if (stio_dev_event (dev, STIO_DEV_EVENT_ADD, STIO_DEV_EVENT_IN) <= -1) goto oops_after_make;
 | 
				
			||||||
 | 
						#endif
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/* ------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* and place the new dev at the back */
 | 
				
			||||||
 | 
						if (stio->dev.tail) stio->dev.tail->next = dev;
 | 
				
			||||||
 | 
						else stio->dev.head = dev;
 | 
				
			||||||
 | 
						dev->prev = stio->dev.tail;
 | 
				
			||||||
 | 
						stio->dev.tail = dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					oops_after_make:
 | 
				
			||||||
 | 
						dev->mth->kill (dev);
 | 
				
			||||||
 | 
					oops:
 | 
				
			||||||
 | 
						STIO_MMGR_FREE (stio->mmgr, dev);
 | 
				
			||||||
 | 
						return STIO_NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stio_killdev (stio_t* stio, stio_dev_t* dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						STIO_ASSERT (stio == dev->stio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* delink the dev object first */
 | 
				
			||||||
 | 
						if (dev->prev)
 | 
				
			||||||
 | 
							dev->prev->next = dev->next;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							stio->dev.head = dev->next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dev->next)
 | 
				
			||||||
 | 
							dev->next->prev = dev->prev;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							stio->dev.tail = dev->prev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* ------------------------------------ */
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						#if defined(_WIN32)
 | 
				
			||||||
 | 
							/* nothing - can't deassociate it. closing the socket
 | 
				
			||||||
 | 
							 * will do. kill should close it */
 | 
				
			||||||
 | 
						#else
 | 
				
			||||||
 | 
							struct epoll_event ev; /* dummy */
 | 
				
			||||||
 | 
							epoll_ctl (stio->mux, EPOLL_CTL_DEL, dev->mth->getsyshnd(dev), &ev); 
 | 
				
			||||||
 | 
							/* don't care about failure */
 | 
				
			||||||
 | 
						#endif
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/* ------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* and call the callback function */
 | 
				
			||||||
 | 
						dev->mth->kill (dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						STIO_MMGR_FREE (stio->mmgr, dev);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int stio_prologue (stio_t* stio)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stio_epilogue (stio_t* stio)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int stio_exec (stio_t* stio)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_WIN32)
 | 
				
			||||||
 | 
						ULONG nentries, i;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						int nentries, i;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*if (!stio->dev.head) return 0;*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						timeout = 1000; //TODO: get_timeout (stio); // use the task heap to get the timeout.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_WIN32)
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						if (GetQueuedCompletionStatusEx (stio->iocp, stio->ovls, STIO_COUNTOF(stio->ovls), &nentries, timeout, FALSE) == FALSE)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// TODO: set errnum 
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < nentries; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nentries = epoll_wait (stio->mux, stio->revs, STIO_COUNTOF(stio->revs), timeout);
 | 
				
			||||||
 | 
						if (nentries <= -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* TODO: set errnum */
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < nentries; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							stio_dev_t* dev = stio->revs[i].data.ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (dev->evcb->ready)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								int x, events = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (stio->revs[i].events & EPOLLERR) events |= STIO_DEV_EVENT_ERR;
 | 
				
			||||||
 | 
								if (stio->revs[i].events & (EPOLLHUP | EPOLLRDHUP)) events |= STIO_DEV_EVENT_HUP;
 | 
				
			||||||
 | 
								if (stio->revs[i].events & EPOLLIN) events |= STIO_DEV_EVENT_IN;
 | 
				
			||||||
 | 
								if (stio->revs[i].events & EPOLLOUT) events |= STIO_DEV_EVENT_OUT;
 | 
				
			||||||
 | 
								if (stio->revs[i].events & EPOLLPRI) events |= STIO_DEV_EVENT_PRI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* 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.
 | 
				
			||||||
 | 
								 *   >= 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;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							invoke_evcb:
 | 
				
			||||||
 | 
								if (stio->revs[i].events & EPOLLPRI)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									/* urgent data */
 | 
				
			||||||
 | 
						printf ("has urgent data...\n");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (stio->revs[i].events & EPOLLIN)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									stio_len_t len;
 | 
				
			||||||
 | 
									int x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									len = STIO_COUNTOF(stio->bigbuf);
 | 
				
			||||||
 | 
									x = dev->mth->recv (dev, stio->bigbuf, &len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					printf ("DATA...recv %d  length %d\n", (int)x, len);
 | 
				
			||||||
 | 
									if (x <= -1)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else if (x == 0)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										stio_killdev (stio, dev);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else if (x >= 1)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										/* data available??? */
 | 
				
			||||||
 | 
										dev->evcb->on_recv (dev, stio->bigbuf, len);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (stio->revs[i].events & EPOLLOUT)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									/*
 | 
				
			||||||
 | 
									if (there is data to write)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										x = dev->mth->send (dev, stio->bigbuf, &len);
 | 
				
			||||||
 | 
										if (x <= -1)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										dev->evcb->on_sent (dv, stio->bigbuf, x);
 | 
				
			||||||
 | 
									}*/
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stio_stop (stio_t* stio)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio->stopreq = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int stio_loop (stio_t* stio)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!stio->dev.head) return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stio->stopreq = 0;
 | 
				
			||||||
 | 
						if (stio_prologue (stio) <= -1) return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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 */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stio_epilogue (stio);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int stio_dev_ioctl (stio_dev_t* dev, int cmd, void* arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (dev->mth->ioctl) return dev->mth->ioctl (dev, cmd, arg);
 | 
				
			||||||
 | 
						dev->stio->errnum = STIO_ENOSUP; /* TODO: different error code ? */
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int stio_dev_event (stio_dev_t* dev, stio_dev_event_cmd_t cmd, int flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if defined(_WIN32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						struct epoll_event ev;
 | 
				
			||||||
 | 
						int epoll_op;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ev.events = EPOLLHUP | EPOLLERR;
 | 
				
			||||||
 | 
					#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;
 | 
				
			||||||
 | 
						ev.data.ptr = dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (cmd)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							case STIO_DEV_EVENT_ADD:
 | 
				
			||||||
 | 
								epoll_op = EPOLL_CTL_ADD;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case STIO_DEV_EVENT_MOD:
 | 
				
			||||||
 | 
								epoll_op = EPOLL_CTL_MOD;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case STIO_DEV_EVENT_DEL:
 | 
				
			||||||
 | 
								epoll_op = EPOLL_CTL_ADD;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								dev->stio->errnum = STIO_EINVAL;
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (epoll_ctl (dev->stio->mux, epoll_op, dev->mth->getsyshnd(dev), &ev) == -1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* TODO: set dev->stio->errnum from errno */
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										291
									
								
								stio/lib/stio.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										291
									
								
								stio/lib/stio.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,291 @@
 | 
				
			|||||||
 | 
					#ifndef _STIO_H_
 | 
				
			||||||
 | 
					#define _STIO_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* TODO: remove these headers */
 | 
				
			||||||
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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_ASSERT assert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STIO_SIZEOF(x) sizeof(x)
 | 
				
			||||||
 | 
					#define STIO_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
 | 
				
			||||||
 | 
					#define STIO_NULL ((void*)0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct stio_mmgr_t stio_mmgr_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void* (*stio_mmgr_alloc_t) (stio_mmgr_t* mmgr, stio_size_t size);
 | 
				
			||||||
 | 
					typedef void (*stio_mmgr_free_t) (stio_mmgr_t* mmgr, void* ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct stio_mmgr_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						stio_mmgr_alloc_t alloc;	
 | 
				
			||||||
 | 
						stio_mmgr_free_t free;
 | 
				
			||||||
 | 
						void* ctx;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STIO_MMGR_ALLOC(mmgr,size) (mmgr)->alloc(mmgr,size)
 | 
				
			||||||
 | 
					#define STIO_MMGR_FREE(mmgr,ptr) (mmgr)->free(mmgr,ptr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct stio_sckadr_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int family;
 | 
				
			||||||
 | 
						stio_uint8_t data[64]; /* TODO: use the actual sockaddr size */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct stio_sckadr_t stio_sckadr_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_WIN32)
 | 
				
			||||||
 | 
					#	define STIO_IOCP_KEY 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typedef int stio_scklen_t;
 | 
				
			||||||
 | 
						typedef SOCKET stio_sckhnd_t;
 | 
				
			||||||
 | 
					#	define STIO_SCKHND_INVALID (INVALID_SOCKET)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typedef HANDLE stio_syshnd_t;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						typedef socklen_t stio_scklen_t;
 | 
				
			||||||
 | 
						typedef int stio_sckhnd_t;
 | 
				
			||||||
 | 
					#	define STIO_SCKHND_INVALID (-1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typedef int stio_syshnd_t;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ------------------------------------------------------------------------- */
 | 
				
			||||||
 | 
					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 unsigned int stio_len_t; /* TODO: remove it? */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum stio_errnum_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						STIO_ENOERR,
 | 
				
			||||||
 | 
						STIO_ENOMEM,
 | 
				
			||||||
 | 
						STIO_EINVAL,
 | 
				
			||||||
 | 
						STIO_ENOSUP, /* not supported */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						STIO_EDEVMAKE
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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           (*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);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STIO_DEV_HEADERS \
 | 
				
			||||||
 | 
						stio_t* stio; \
 | 
				
			||||||
 | 
						stio_dev_mth_t* mth; \
 | 
				
			||||||
 | 
						stio_dev_evcb_t* evcb; \
 | 
				
			||||||
 | 
						stio_dev_t* prev; \
 | 
				
			||||||
 | 
						stio_dev_t* next 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct stio_dev_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						STIO_DEV_HEADERS;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum stio_dev_event_cmd_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						STIO_DEV_EVENT_ADD,
 | 
				
			||||||
 | 
						STIO_DEV_EVENT_MOD,
 | 
				
			||||||
 | 
						STIO_DEV_EVENT_DEL
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					typedef enum stio_dev_event_cmd_t stio_dev_event_cmd_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum stio_dev_event_flag_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						STIO_DEV_EVENT_IN  = (1 << 0),
 | 
				
			||||||
 | 
						STIO_DEV_EVENT_OUT = (1 << 1),
 | 
				
			||||||
 | 
						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 */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stio_t* stio_open (
 | 
				
			||||||
 | 
						stio_mmgr_t* mmgr,
 | 
				
			||||||
 | 
						stio_size_t xtnsize,
 | 
				
			||||||
 | 
						stio_errnum_t* errnum
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stio_close (
 | 
				
			||||||
 | 
						stio_t* 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
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stio_killdev (
 | 
				
			||||||
 | 
						stio_t*     stio,
 | 
				
			||||||
 | 
						stio_dev_t* dev
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stio_dev_tcp_t* stio_dev_tcp_make (
 | 
				
			||||||
 | 
						stio_t*        stio,
 | 
				
			||||||
 | 
						stio_sckadr_t* addr
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stio_dev_tcp_kill (
 | 
				
			||||||
 | 
						stio_dev_tcp_t* tcp
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		Reference in New Issue
	
	Block a user