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