/* 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); };