#
#include	"/mos/lib/defs.h"
#include	"../../mos/mos.h"
#include	"../../aux/mosu.h"
#include	"../src/const.h"
#include	"../src/defs.h"
#include	"../src/macs.h"
#include	"../src/net.h"
#include	"../src/ext.h"
#include	"in.h"
#include	"inparam.h"
#include	"inext.h"

#include	"inpro.h"
#include	"ggp.h"
#include	"inrte.h"

hndlre	*ggphnd;
opc	ggpopc;
opc	ggpwk;

inaddr	ggpme;

unsw	ggpseq;

#define NGGP	4
unsw	nggp	NGGP;
struct ggpnn	ggpnn[NGGP] {
/*	012, 02, 0, 054*/	/* MIT-TSTGW */
	012, 03, 0, 050,	/* BBN */
	012, 02, 0, 031,	/* CSS-GW */
	012, 01, 0, 024,	/* DCEC */
	012, 03, 0, 0110	/* RCC-GW */
	};

/* Nets from which MITgw is 2 hops */
#define NHOP2	3
unsw	nhop2	NHOP2;
struct ggpnn	hop2[NHOP2] {
	0200, 037, 0, 0,	/* MIT Chaosnet */
	0300, 012, 051, 0,	/* Symbolicsnet */
	0200, 064, 0, 0		/* MIT AI-IP net */
	};

static char ggpnonet[]	"GGP no direct net to %o %o %o %o\n";

INITGGP()
{
	void			null();
	void			ggpjob();
	reg	struct inrte	*inn;
	reg	net		*netp;

	ggphnd = init_tsk(GGPMXHND, GGPMXTSK);
	ggpopc = addshnd(ggphnd, &null);
	ggpwk = addshnd(ggphnd, &ggpjob);

	if ( ((inn = infnet(&ggpnn[0])) == NULL) ||
		((netp = inn->inr_netp) == NULL) ||
		(inn->inr_gw.i_wordh != NULL) ) {
		iflog(L_ERRU)
			dolog(ggpnonet, mksina(&ggpnn[0]));
		return;
		}
	ggpme.i_long = mkina(&(iniatlst[netp->n_net]->inia_addr))->i_long;

	stime(ggpwk, &ggpnn[0], (10*NTICKS));
	run_tsk(ggphnd, gwmsgq);

	return;
}

ggpjob(gwp)
reg	struct ggpnn	*gwp;
{
	if (gwp < &ggpnn[nggp])
		ggpsupd(gwp);

	if (++gwp < &ggpnn[nggp])
		addtsk(ggphnd, GGPPRI, &ggpjob, gwp);
	else {
		ggpseq++;
		stime(ggpwk, &ggpnn[0], (60*NTICKS));
		}

	return;
}

ggpsupd(gwp)
reg	struct ggpnn	*gwp;
{
	reg	iorb	*iob;
	reg	ggpkt	*ggp;
		unsw	len;

	if ((iob = mkiorb(getbuf(bufsiz))) == NULL)
		return;
	ggp = ((byte *) iob) + pktoff + sizeof(inpkt);
	len = mkggupd(ggp);
	mkinpkt(iob, &ggpme, mkina(gwp), INGGP, len);
	inxaddq(iob);
	return;
}

mkggupd(ggp)
reg	ggpkt	*ggp;
{
	reg	struct ggpnn	*inp;
		struct ggpnn	*inl;
	reg	byte		*up;
		unsw		len;

	ggp->ggp_type = GGPNRU;
	ggp->ggp_code = 0;
	ggp->ggp_seqno = swab(ggpseq);

	up = (byte *) ggp + sizeof(ggpkt);
	*up++ = 0;	/* Don't need update */
	*up++ = 2;	/* Distance count */
	*up++ = 1;	/* Distance - 1 hop */
	*up++ = 1;	/* 1 net at 1 hop */
	*up++ = myanet;	/* net 18 */

	*up++ = 2;	/* Distance - 2 hops */
	*up++ = nhop2;	/* No. nets at 2 hops */
	for (inp = &hop2[0], inl = &hop2[nhop2]; inp < inl; inp++) {
		switch((inp->ggp_nnam[0] & CLMSK) >> CLSHFT) {
		case CLA0:
		case CLA1:
		case CLA2:
		case CLA3:
			*up++ = inp->ggp_nnam[0];
			break;

		case CLB0:
		case CLB1:
			*up++ = inp->ggp_nnam[0];
			*up++ = inp->ggp_nnam[1];
			break;

		case CLC:
			*up++ = inp->ggp_nnam[0];
			*up++ = inp->ggp_nnam[1];
			*up++ = inp->ggp_nnam[2];
			break;

		default:
			bughlt("Bad GGP net");
			}
		}

	len = (up - (byte *) ggp);
	return(len);
}
