/* PupMisc.c
Swinehart, July 15, 1982 2:18 PM, Miscellaneous Network Services
Currently network time, routing request functions.
Cosmetic mods, L. Stewart October 20, 1982 9:42 PM
L. Stewart November 13, 1982 4:38 PM, more Blocking
L. Stewart November 13, 1982 5:45 PM, general munging
L. Stewart November 23, 1982 9:54 AM, restore statics
L. Stewart November 28, 1982 6:36 PM, formatting
L. Stewart December 27, 1982 2:53 PM
flush nested declarations
L. Stewart February 10, 1983 3:49 PM, routing
L. Stewart February 23, 1983 12:50 PM, remainder -> GetRem
L. Stewart March 6, 1983 4:28 PM, remove incl Alloc.h
July 11, 1983 9:25 AM by Stewart, Route changed
July 18, 1983 1:13 PM by Stewart, localHost
*/
#include <Ec.h>
#include <Env.h>
#include <Queue.h>
#include <Pup.h>
struct Calendar {
int time[2];
int zoneInfo;
int dstStartDay;
int dstEndDay;
int base[2]; /* last ms timer, for updating time */
};
struct RoutingEntry {
byte net; /* Target net */
byte gateNet; /* A net along the route */
byte gateHost; /* A gateway on gateNet */
byte hops; /* hops from responding gateway to target net */
};
/* OS */
extern Move2();
extern Timer();
extern DoubleDifference();
extern DoubleIncrement();
extern DoubleUDiv();
extern GetRem();
extern Marshall();
extern CallSwat();
extern SetTmr();
extern TmrExp();
extern Swab();
/* Queue package */
extern InitQueue();
/* context package */
extern Block();
/* Pup package */
extern GetPBI();
extern ReleasePBI();
extern OpenLevel1Socket();
extern WaitUntilSent();
extern CloseLevel1Socket();
extern AppendStringToPup();
extern SendPup();
/* Various counters */
static int simpleSent;
static int simpleRcvd;
static int calSent;
static int calRcvd;
static int routSent;
static int routRcvd;
/* ----------- Time and Date acquisition and maintenance -------------- */
struct Calendar calendar;
/*----------------------------------------------------------------------- */
ReadCalendar(c)
/*----------------------------------------------------------------------- */
int c[];
{
int t[], newbase[2], ms[2];
if (calendar.base[0] == 0) Timer(calendar.base);
t = calendar.time;
Timer(newbase);
Move2(ms, newbase);
DoubleDifference(ms, calendar.base);
DoubleIncrement(t, DoubleUDiv(ms, 1000));
ms[1] = 0;
ms[0] = GetRem();
DoubleDifference(newbase, ms);
/* newbase is now newbase0+m*1000 */
Move2(calendar.base, newbase);
Move2(c, t);
};
/*----------------------------------------------------------------------- */
InitCalendar()
/*----------------------------------------------------------------------- */
{
struct PBI *pbi;
struct Pup *p;
int temp;
Timer(calendar.base);
Timer(calendar.time); /* Default value, if no answer */
pbi = SimpleExch(0206, 0207, 4, 3);
calSent += simpleSent;
if (pbi == 0) return; /* didn't get an answer, fake it */
calRcvd += 1;
p = pbi->pup;
Marshall(true, calendar.time, p->data.words, 5);
ReleasePBI(pbi);
temp = calendar.time[0];
calendar.time[0] = calendar.time[1];
calendar.time[1] = temp;
};
/* ----------- Simple network routing table maintenance -------------- */
extern struct SocketEntry pupSockets[1 /*maxPupSockets*/];
extern struct Route routingTable[maxNetworks];
extern int localNet;
extern int localHost;
int routingSoc;
/*----------------------------------------------------------------------- */
static RoutePr(pbi)
/*----------------------------------------------------------------------- */
struct PBI *pbi;
{
struct Pup *p;
int numEntries, i;
struct RoutingEntry entries[];
int net, hops;
struct Route *route;
p = pbi->pup;
if (p->type == 0201) {
routRcvd += 1;
numEntries = (Swab(p->length) - pupOvBytes) >> 2;
entries = (struct RoutingEntry *) p->data.words;
for (i = 0; i < numEntries; i += 1) {
Block();
net = entries[i].net;
route = &routingTable[net];
hops = entries[i].hops + 1;
if ((route->hops > hops) || (route->host == p->sPort.host) || ((route->hops == hops) && (route->age == 0x00ff))) {
route->host = p->sPort.host;
route->hops = hops;
route->age = 0;
};
};
};
ReleasePBI(pbi);
};
/*----------------------------------------------------------------------- */
RequestRoute(net)
/*----------------------------------------------------------------------- */
int net;
{
/* net not used for anything at present. */
struct PBI *pbi;
struct SocketEntry *pse;
struct Port lclPort;
if (!routingSoc) {
lclPort.net = localNet;
lclPort.host = localHost;
lclPort.socket.LS = 0;
lclPort.socket.ms = Swab(2);
routingSoc = OpenLevel1Socket(&lclPort, &RoutePr, 0);
if (!routingSoc) return;
};
pbi = GetPBI();
/*
pse = &pupSockets[routingSoc];
Move2(&pbi->pup->sPort.socket, &pse->port.socket);
*/
pbi->pup->sPort.socket.LS = 0;
pbi->pup->sPort.socket.ms = Swab(2);
SimpleSend(pbi, 0200, 02);
routSent += 1;
};
/* ----- Simple broadcast services packet exchange implementation ----- */
static struct PBI *rcvPBI;
static int rcvType;
static int z[2]; /* actually a null ShortSTRING */
static int counter[2];
/*----------------------------------------------------------------------- */
static RcvPr(pbi)
/*----------------------------------------------------------------------- */
struct PBI *pbi;
{
if ((pbi->pup->type != rcvType) || (rcvPBI != 0)) ReleasePBI(pbi);
else {
rcvPBI = pbi;
simpleRcvd += 1;
};
};
/*----------------------------------------------------------------------- */
struct PBI *SimpleExch(sendType, recvType, servSoc, tries)
/*----------------------------------------------------------------------- */
/* Broadcasts packet of type sendType to servSoc, expects
packet of type recvType in response. Tries tries times.
Returns 0 if no joy, else recieved PBI.
*/
int sendType, recvType, servSoc, tries;
{
struct PBI *pbi;
struct Pup *p;
int soc, i;
struct Queue tQ[1];
int tmr[1];
int wait;
InitQueue(tQ)
pbi = GetPBI();
p = pbi->pup;
Timer(&p->sPort.socket.LS);
rcvPBI = 0;
if (!(soc = OpenLevel1Socket(&p->sPort, &RcvPr, 0))) CallSwat(ecPup1+10);
pbi->queue = tQ;
rcvType = recvType;
Timer(counter);
wait = 100;
for (i = 0; ((i<tries) && (rcvPBI == 0)); i += 1) {
simpleSent += 1;
SimpleSend(pbi, sendType, servSoc);
WaitUntilSent(pbi); /* Removed from tQ after sent */
SetTmr(wait, tmr);
/* Give answer time to arrive */
while ((!TmrExp(tmr)) && (rcvPBI == 0)) Block();
wait = wait + 500;
};
ReleasePBI(pbi);
CloseLevel1Socket(soc); /* We either got it or we didn't! */
return(rcvPBI);
};
/*----------------------------------------------------------------------- */
SimpleSend(pbi, sendType, servSoc)
/*----------------------------------------------------------------------- */
/* Broadcasts packet, assuming source port socket field is already set up,
and socket is Open to recieve */
struct PBI *pbi;
int sendType, servSoc;
{
struct Pup *p;
p = pbi->pup;
p->dPort.net = localNet;
/* Host is 0 . . . broadcast (zero'ed by GetPBI) */
p->dPort.socket.ms = Swab(servSoc);
p->sPort.net = localNet;
p->sPort.host = localHost;
p->type = sendType;
if (!counter[0]) Timer(counter);
DoubleInc(counter, 1);
p->id[0] = counter[1];
p->id[1] = counter[0];
Zero(z, 2);
AppendStringToPup(pbi, 0, z); /* Just to compute length of empty packet */
SendPup(pbi);
};