#

/* Copyright 1984 by the Massachusetts Institute of Technology */
/* See permission and disclaimer notice in file notice.h */
#include	<notice.h>


/* This file includes support for all CHAOS network support tasks;
 * other than routing. This includes STATUS and PULSAR at the moment.
 */


#include	<types.h>
#include	<sys.h>
#include	"../src/defs.h"
#include	"../src/macs.h"
#include	"../src/const.h"
#include	"../src/param.h"
#include	"../src/net.h"
#include	"../src/ext.h"
#include	"ch.h"
#include	"chparam.h"
#include	"chext.h"


/* Useful constants */

#define	CHARUT	4	/* Interval to age CHAOS routing info at */
#define	CHXRUT	15	/* Interval to send CHAOS routing info at */
#define	CSNMSZ	32	/* Max size of name in STATUS ANS */
#define	CSOLD	0	/* Old STATUS block, 16 bit counters */
#define	CSNEW	1	/* New, with 32 bit ones */


/* STATUS ANS packets contains entries of this form. Structure at end
 * is for accessing longs in netp for ANS in right way.
 */

struct	chstsd	{	unsl	cs_pin;
			unsl	cs_pout;
			unsl	cs_abort;
			unsl	cs_lost;
			unsl	cs_crcn;
			unsl	cs_crcb;
			unsl	cs_trunc;
			unsl	cs_rest;
		};

struct	chstsb	{	unsb	cs_snet;
			unsb	cs_type;
			unss	cs_len;
			struct	chstsd	cs_data;
			};

struct	chsts	{	char	cs_name[CSNMSZ];
/*			struct	chstsb	cs_stat[]; */
		};


/* Useful static */

unss	chplstm;	/* If non-zero, PULSAR time */
/* opc	chplsig;	/* Signal for PULSAR time delay */
/* opc	chpxsig;	/* Signal for PULSAR pkt sent done */


/* PULSAR packet */

struct	chpls	{	swrd	cp_data[2];
			swrd	cp_dest;
		} 	chpls =	{ 052525, 0 , 0177777 };


/* Error and info messages */

static char chsts[] =	"Rspnding to STATUS frm hst %o/%o\n";
static char chplsm[] =	"PULSAR srvc of %d fr hst %o/%o\n";
static char chplsi[] =	"Rspnding to PULSAR frm hst %o/%o\n";



/* Protocol initialization stuff. Set up to send routing packets,
 * age routing table entries and set up PULSAR server stuff. 
 */

chprinit()

{	void chxrut();
	void charut();

	itime(chxrut, 0, CHXRUT, CHRPRI);
	itime(charut, 0, CHARUT, CHRPRI);

	chplstm = 0;
}


/* Process STATUS RFC's. Notice the backward longs.
 */

chstatus(iob)
iorb	*iob;

{	reg	ochpkt	*pkt;
	struct	chstsb	*stb;
	struct	chsts	*st;
	chia	*iap;
	unss	i;
	unss	nsb = 0;

	pkt = mkoch(iob->i_addr);
	niflog(L_INFU)
	  dolog(chsts, mkscha(&pkt->oc_src));

	chmkans(pkt);

	{	reg	char	*p, *q;

		st = ((struct chsts *)(pkt + 1));
		p = &(st->cs_name[0]);
		q = name;
		i = 0;
		while ((i++ < CSNMSZ) && (*p++ = *q++));
		while (i++ < CSNMSZ)
			*p++ = '\0';
		}

	{	reg	net	*netp;
		reg	swrd	*std;

		stb = (struct chstsb *)(st + 1);
		netp = &nets[0];
		for (i = 0; i < nnets; i++) {
			if ((iap = chiatlst[netp->n_net]) == NULL)
				continue;
			stb->cs_snet = mkcha(iap->chia_addr)->oc_addr.oc_snt;
			stb->cs_type = CSNEW;
			stb->cs_len = (sizeof(struct chstsd) / sizeof(swrd));
			std = ((swrd *) &stb->cs_data);
			*std++ = loworder(netp->n_pkti);
			*std++ = hiorder(netp->n_pkti);
			*std++ = loworder(netp->n_pkto);
			*std++ = hiorder(netp->n_pkto);
			*std++ = netp->n_ioout;
			*std++ = 0;
			*std++ = 0;
			*std++ = 0;
			*std++ = netp->n_ioin;
			*std++ = 0;
			*std++ = 0;
			*std++ = 0;
			*std++ = 0;
			*std++ = 0;
			*std++ = (netp->n_disc + netp->n_ovfout);
			*std++ = 0;
			netp++;
			stb++;
			nsb++;
			}
		}

	pkt->oc_len = ((nsb * sizeof(struct chstsb)) + sizeof(struct chsts));
	if (pkt->oc_len > CHMAX)
		bughalt("too many entries to fit in STATUS ANS");
	iob->i_bxfr = (pkt->oc_len + sizeof(ochpkt));
	chaddq(iob);
}


/* Handle RFC's to turn on or ask about the PULSAR server.
 * Turns the server on or off as required and returns the ANS
 * with the server status.
 */

chpulsar(iob, period)
reg	iorb	*iob;
	char	*period;

{	reg	ochpkt	*pkt;
	reg	unss	time;
	void chxpls();

	pkt = mkoch(iob->i_addr);
	if (*period != '\0') {
		time = atoi(period);
		if (((chplstm == 0) && (time != 0)) ||
		    ((chplstm != 0) && (time == 0))) {
			niflog(L_INFU)
			  dolog(chplsm, time, mkscha(&pkt->oc_src));
			chplstm = time;
			itime(chxpls, 0, time, CHPLSPRI);
			}
		  else {
			chmkcls(iob, "PULSAR server in use");
			return;
			}
		}
	 else
		niflog(L_INFU)
		  dolog(chplsi, mkscha(&pkt->oc_src));

	chmkans(pkt);
	pkt->oc_len = 1;
	iob->i_bxfr = (1 + sizeof(ochpkt));
	((char *)(pkt + 1))[0] = ('0' + chplstm);

	chaddq(iob);
}


/* Called every so often, this actually sends the PULSAR packets. Uses
 * preprepared packet, just allocating IORB's.  Note also that there
 * is no flow control on PULSAR packets. 
 */

chxpls()
{
    return;

    /* I'll think about trying to make all this work later.

	reg	net	*netp;
	reg	iorb	*iob;

	for (netp = &nets[0]; netp < lstnet; netp++)
		if (netp->n_type == ((unsb) T_CH)) {
			if ((iob = mkiorb(getmem(sizeof(iorb)))) == NULL)
				bughalt("out of memory for PULSAR iorb");

			iob->i_dev = netp->n_odev;
			iob->i_opc = chpxsig;
			iob->i_addr = ((char *) &chpls);
			iob->i_xmem = 0;
			iob->i_breq = sizeof(struct chpls);
			sio(iob);
			}
	   */
}


/* Called after each PULSAR packet was actually sent */

swrd	chplsx(iob)
iorb	*iob;
{
/*	freemem(sizeof(iorb), iob);	Later I'll fix it */
}
