/* RpcBonsai.c Client and Server Lupine-level functions for RPC L. Stewart, January 18, 1983 5:16 PM, create from rpcfir.c L. Stewart, January 19, 1983 10:49 AM, length bugs L. Stewart, March 2, 1983 3:33 PM, Dispatcher bugs L. Stewart, March 3, 1983 10:03 AM, Dispatcher bugs L. Stewart, March 6, 1983 4:04 PM, GetFixed (temporary!!!) L. Stewart, May 24, 1983 4:28 PM, swapped1 */ #include <Signal.h> #include <Queue.h> #include <Ec.h> #include <Env.h> #include <Rpc.h> #include <RpcInternal.h> #include <RpcLupine.h> #include <RpcPkt.h> #include <RpcBind.h> #include <RpcBonsai.h> #define lupineOffset 4 /* from RpcPktIO, etc. */ extern int Call(); extern int *mySoc; extern StartCall(); /* from RpcSignals */ extern int RejectUnbound; /* from Pup Package */ extern struct PBI *GetPBI(); extern ReleasePBI(); /* from Signaller */ extern DISABLE(); extern ENABLEWithFrame(); extern SIGNAL(); /* from Runtime */ extern Call1(); extern CallersFrame(); extern MoveBlock(); extern MyFrame(); /* First proc index is 4. */ static UnwindPkt(sig, code, seal) int sig, code; struct Seal1 *seal; { ReleasePBI(seal->data[0]); DISABLE(seal); }; static struct PBI *GetUnwindPkt(seal) struct Seal1 *seal; { struct PBI *pkt; pkt = GetPBI(mySoc); ENABLEWithFrame(UNWIND, &UnwindPkt, seal, CallersFrame(MyFrame())); seal->data[0] = (int) pkt; return (pkt); }; /* *************** Client Interface to RPC *************** */ /* The client calls StartBonsai(seal) to receive a buffer area. (Really a pointer into a PBI) The client constructs the call The client calls CallBonsai(seal, length); The results of the call, if any are found in the same place. The client calls CleanupCall(seal) to finish. */ int *StartBonsai(interface, seal) struct ImportInstance *interface; struct Seal1 *seal; { struct PBI *pkt; struct Header *hdr; /* Releases on unwind ! */ pkt = GetUnwindPkt(seal); StartCall(pkt, interface, interface->currentConversation); hdr = pkt->pup; return(&hdr->callData.words[0]); }; CallBonsai(seal, arglen) struct Seal1 *seal; int arglen; { Call(seal->data[0], arglen, maxDataLength); }; CleanupCall(seal) struct Seal1 *seal; { ReleasePBI(seal->data[0]); DISABLE(seal); }; /* client procedure is called with integer pointer to procedure index. (First argument is ptr[1].) Client procedure will store return arguments starting at ptr[0] and return the number of words of return arguments */ int BonsaiDispatcher(pkt, newLength, conversation, sSpecsT) struct PBI *pkt; int newLength; int *conversation; struct SSpecsTable *sSpecsT; { int rout, argLen, *wp; int thisProc; struct Header *hdr; hdr = pkt->pup; wp = &hdr->callData.words[0]; rout = Swab(*wp); if ((rout < lupineOffset) || (rout > sSpecsT->maxProcs)) SIGNAL(RejectUnbound); thisProc = sSpecsT->procs[rout]; if (thisProc == 0) SIGNAL(RejectUnbound); return (Call1(thisProc, wp)); }; /* GetServerConversation is the same as the one in RPCFir */ /* ***** Utilities ***** */ int *StringToPkt(pp, s) int *pp; struct ShortSTRING *s; { int len; if (s == 0) *pp++ = swapped1; /* isNil */ else { *pp++ = 0; /* isNil */ *pp++ = Swab(s->length); len = (s->length+1) >> 1; /* text only */ MoveBlock(pp, &s->text[0], len); pp += len; }; return (pp); }; /* These procedures return the allocated object, but also update the client's copy of the pointer into the packet. */ struct ShortSTRING *AllocStringFromPkt(pp) int **pp; { int len, *wp; struct ShortSTRING *s; wp = *pp; if (*wp) { *pp = wp+1; return(0); }; len = (Swab(wp[1])+5)/2; if (len > 100) CallSwat(ecLarkImpl + 22); s = (struct ShortSTRING *) GetFixed(len); MoveBlock(s, wp, len); s->maxLength = Swab(s->maxLength); s->length = s->maxLength; *pp = wp + len; return(s); }; int *AllocWordsFromPkt(pp, swap) int **pp; int swap; /* boolean */ { int len, *wp; int *wseq; wp = *pp; if (*wp) { *pp = wp+1; return(0); }; len = Swab(wp[1]); if (len > 100) CallSwat(ecLarkImpl + 22); wseq = GetFixed(len+1); *wseq = Swab(wp[3]); Marshall(swap, wseq+1, &wp[4], len); *pp = wp + len + 4; return(wseq); }; SwabInPlace(addr, words) int *addr, words; { Marshall(true, addr, addr, words); };