/* include xti_accept1 */
#include	"unpxti.h"

static int		ncli = -1, ndisconn;
static struct cli {
  int			connfd;	/* connected fd or -1 if disconnected */
  int			count;
  struct t_call	*tcallp;/* ptr to t_alloc'ed structure */
} *cli;					/* cli[0], cli[1], ..., cli[ncli-1] are in use */

int
xti_accept(int listenfd, struct netbuf *cliaddr, int rdwr)
{
	int				i, event;
	u_int			n;
	char			*ptr;
	struct t_discon	tdiscon;

	if (ncli == -1) {		/* initialize first time through */
		if (cli != NULL)
			err_quit("already initialized");
		if ( (ptr = getenv("LISTENQ")) != NULL)
			n = atoi(ptr);
		else
			n = LISTENQ;
		cli = Calloc(n, sizeof(struct cli));
		for (i = 0; i < n; i++)
			cli[i].tcallp = T_alloc(listenfd, T_CALL, T_ALL);
		ncli = 0;
	}
/* end xti_accept1 */

/* include xti_accept2 */
	for ( ; ; ) {
		if (ncli == 0) {	/* need to wait for a connection */
			T_listen(listenfd, cli[ncli].tcallp);	/* block here */
	
				/* 4following assumes caller called tcp_listen() */
			cli[ncli].connfd = T_open(xti_serv_dev, O_RDWR, NULL);
			T_bind(cli[ncli].connfd, NULL, NULL);
			cli[ncli].count++;
			ncli++;
		}
	
		if (t_accept(listenfd, cli[ncli-1].connfd,
					 cli[ncli-1].tcallp) == 0) {
			ncli--;			/* success */
			if (rdwr)
				Xti_rdwr(cli[ncli].connfd);
		
			if (cliaddr) {		/* return client's protocol address */
				n = min(cliaddr->maxlen, cli[ncli].tcallp->addr.len);
				memcpy(cliaddr->buf, cli[ncli].tcallp->addr.buf, n);
				cliaddr->len = n;
			}
			return(cli[ncli].connfd);
		
		} else if (t_errno == TLOOK) {
			if ( (event = T_look(listenfd)) == T_LISTEN) {
				T_listen(listenfd, cli[ncli].tcallp);	/* won't block */
				cli[ncli].connfd = T_open(xti_serv_dev, O_RDWR, NULL);
				T_bind(cli[ncli].connfd, NULL, NULL);
				cli[ncli].count++;
				ncli++;
	
			} else if (event == T_DISCONNECT) {
				T_rcvdis(listenfd, &tdiscon);
				for (i = 0; i < ncli; i++) {
					if (cli[i].tcallp->sequence == tdiscon.sequence) {
						T_close(cli[i].connfd);
#ifdef	NOTDEF
						printf("disconnect received from %s\n",
								Xti_ntop(&cli[i].tcallp->addr));
#endif
						ndisconn++;
						ncli--;
						if ( (n = ncli - i) > 0)
							memmove(&cli[i], &cli[i+1],
									n*sizeof(struct cli));
						break;
					}
				}
			} else
				err_quit("unexpected t_look event %d", event);
		} else
			err_xti("unexpected t_accept error");
	}
}
/* end xti_accept2 */

void
xti_accept_dump(void)
{
	int		i, total;

	for (i = total = 0; ; i++) {
		if (cli[i].count == 0)
			break;
		printf("%2d %5d\n", i, cli[i].count);
		total += cli[i].count;
	}
	printf("#disconnects = %d\n", ndisconn);
	printf("total = %d\n", total);
}


syntax highlighted by Code2HTML, v. 0.9.1