clients.c

来自「Windows NT声卡驱动VXD」· C语言 代码 · 共 311 行

C
311
字号
#include "esd-server.h"#ifdef HAVE_SYS_IOCTL_H# include <sys/ioctl.h>#endif#ifdef HAVE_SYS_FILIO_H# include <sys/filio.h>#endif#ifdef USE_LIBWRAP#include <tcpd.h>#include <syslog.h>int allow_severity = LOG_INFO;int deny_severity = LOG_WARNING;#endif/*******************************************************************//* globals *//* the list of the currently connected clients */esd_client_t *esd_clients_list;/*******************************************************************//* prototypes */void dump_clients(void);void free_client( esd_client_t *client );/*******************************************************************//* for debugging purposes, dump the list of the clients and data */void dump_clients(){    long addr;    short port;    esd_client_t *clients = esd_clients_list;    if ( !esdbg_trace ) return;    while ( clients != NULL ) {	port = ntohs( clients->source.sin_port );	addr = ntohl( clients->source.sin_addr.s_addr );	printf( "(%02d) client from: %03u.%03u.%03u.%03u:%05d [%p]\n", 		clients->fd, (unsigned int) addr >> 24, 		(unsigned int) (addr >> 16) % 256, 		(unsigned int) (addr >> 8) % 256, 		(unsigned int) addr % 256, port, clients );	clients = clients->next;    }    return;}/*******************************************************************//* deallocate memory for the client */void free_client( esd_client_t *client ){    /* free the client memory */    free( client );    return;}/*******************************************************************//* add a complete new client into the list of clients at head */void add_new_client( esd_client_t *new_client ){    /* printf ( "adding client 0x%08x\n", new_client ); */    new_client->next = esd_clients_list;    esd_clients_list = new_client;    return;}/*******************************************************************//* erase a client from the client list */void erase_client( esd_client_t *client ){    esd_client_t *previous = NULL;    esd_client_t *current = esd_clients_list;    /* iterate until we hit a NULL */    while ( current != NULL )    {	/* see if we hit the target client */	if ( current == client ) {	    if( previous != NULL ){		/* we are deleting in the middle of the list */		previous->next = current->next;	    } else { 		/* we are deleting the head of the list */		esd_clients_list = current->next;	    }	    ESDBG_TRACE( printf ( "(%02d) closing client connection\n", 				  client->fd ); );	    close( client->fd );	    free_client( client );	    return;	}	/* iterate through the list */	previous = current;	current = current->next;    }    /* hmm, we didn't find the desired client, just get on with life */    ESDBG_TRACE( printf( "(%02d) client not found\n", client->fd ); );    return;}/*******************************************************************//* checks for new connections at listener - zero when done */int get_new_clients( int listen ){    int fd, nbl;    struct sockaddr_in incoming;    size_t size_in = sizeof(struct sockaddr_in);    esd_client_t *new_client = NULL;        unsigned long addr;    short port;    /* see who awakened us */    do {	fd = accept( listen, (struct sockaddr*) &incoming, &size_in );	if ( fd > 0 ) {	    port = ntohs( incoming.sin_port );	    addr = ntohl( incoming.sin_addr.s_addr );	    ESDBG_TRACE( 		printf( "(%02d) new client from: %03u.%03u.%03u.%03u:%05d\n", 			fd, (unsigned int) addr >> 24, 			(unsigned int) (addr >> 16) % 256, 			(unsigned int) (addr >> 8) % 256, 			(unsigned int) addr % 256, port ); );#ifdef USE_LIBWRAP	    {		struct request_info req;		struct servent *serv;		request_init( &req, RQ_DAEMON, "esound", RQ_FILE, fd, NULL );		fromhost( &req );		if ( !hosts_access( &req )) {		    ESDBG_TRACE( 			printf( "connection from %s refused by tcp_wrappers\n",				eval_client( &req ) ); );		    close( fd );		    continue;		}	    }#endif	    ESDBG_COMMS( printf( "================================\n" ); );	    /* make sure we have the memory to save the client... */	    new_client = (esd_client_t*) malloc( sizeof(esd_client_t) );	    if ( new_client == NULL ) {		close( fd );		return -1;	    }	    /* It appears that not all systems construct the new socket in	     * a blocking mode, if the listening socket is non-blocking, so	     * let's set that here...	     */	    nbl = 0;	    if ( ioctl( fd, FIONBIO, &nbl ) < 0 )	    {		ESDBG_TRACE( printf( "(%02d) couldn't turn on blocking for client\n", 				     fd ); );		close( fd );		return -1;	    }	    /* Reduce buffers on sockets to the minimum needed */	    esd_set_socket_buffers( fd, ESD_BITS16, 44100, esd_audio_rate );	    /* fill in the new_client structure - sockaddr = works!? */	    new_client->next = NULL;	    new_client->state = ESD_NEEDS_REQDATA;	    new_client->request = ESD_PROTO_CONNECT;	    new_client->fd = fd;	    new_client->source = incoming; 	    new_client->proto_data_length = 0;	    	    add_new_client( new_client );	}    } while ( fd > 0 );    return 0;}static int is_paused_here = 0;/*******************************************************************//* blocks waiting for data from the listener, and client conns. */int wait_for_clients_and_data( int listen ){    fd_set rd_fds;    struct timeval timeout;    struct timeval *timeout_ptr = NULL;    esd_client_t *client = esd_clients_list;    int max_fd = listen, ready;    /* add the listener to the file descriptor list */    FD_ZERO( &rd_fds );    FD_SET( listen, &rd_fds );    /* add the clients to the list, too */    while ( client != NULL )    {	/* add this client, but only if it's not monitoring */	if ( client->state == ESD_STREAMING_DATA &&	     client->request == ESD_PROTO_STREAM_MON )	{	    client = client->next;	    continue;	}	FD_SET( client->fd, &rd_fds );	/* update the maximum fd for the select() */	if ( client->fd > max_fd )	    max_fd = client->fd;	/* next client */	client = client->next;    }    /* if we're doing something useful, make sure we return immediately */    if ( esd_recorder || esd_playing_samples ) {	timeout.tv_sec = 0;	timeout.tv_usec = 0;	timeout_ptr = &timeout;    } else {	/* TODO: any reason not to pause indefinitely here? */	/* sample players that's why, if no players, can pause indefinitely */	/* if ( esd_on_autostandby 	        || (esd_autostandby_secs < 0 && !esd_playing_samples ) )	       timeout_ptr = NULL; else { ... } */	if ( is_paused_here ) {	    ESDBG_TRACE( printf( "paused, awaiting instructions.\n" ); );	    timeout_ptr = NULL;	} else {	    timeout.tv_sec = 0;	    /* funky math to make sure a long can hold it all, calulate in ms */	    timeout.tv_usec = (long) esd_buf_size_samples * 1000L		/ (long) esd_audio_rate / 4L; 	/* divide by two for stereo */	    timeout.tv_usec *= 1000L; 		/* convert to microseconds */	    timeout_ptr = &timeout;	}    }    ready = select( max_fd+1, &rd_fds, NULL, NULL, timeout_ptr );    ESDBG_COMMS( printf( 	"paused=%d, samples=%d, auto=%d, standby=%d, record=%d, ready=%d\n",	is_paused_here, esd_playing_samples, 	esd_autostandby_secs, esd_on_standby, 	(esd_recorder != 0), ready ); );    /* TODO: return ready, and do this in esd.c */    if ( ready <= 0 ) {	/* if < 0, something horrible happened:	   EBADF   invalid file descriptor - let individual read sort it out	   EINTR   non blocked signal caught - o well, no big deal	   EINVAL  n is negative - not bloody likely	   ENOMEM  unable to allocate internal tables - o well, no big deal */	if ( !is_paused_here && !esd_playing_samples && (esd_autostandby_secs<0) ) {	    ESDBG_TRACE( printf( "doing nothing, pausing server.\n" ); );	    esd_audio_flush();	    esd_audio_pause();	    esd_last_activity = time( NULL );	    is_paused_here = 1;	}	if ( !is_paused_here && !esd_playing_samples && !esd_recorder ) {	    if ( esd_autostandby_secs >= 0		 && ( time(NULL) > esd_last_activity + esd_autostandby_secs ) ) {		ESDBG_TRACE( printf( "bored, going to standby mode.\n" ); );		esd_server_standby();		esd_on_autostandby = 1;		is_paused_here = 1;	    }	}    } else {	is_paused_here = 0;    }    return ready;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?