/* RPCAgent.c
   RPC: Intertface to remote Binding and Authentication services
   See [Indigo]<Voice>Agent>Agent.mesa
   Last modified by D. Swinehart, October 27, 1982  8:28 PM
   L. Stewart, January 1, 1983  4:48 PM, flush CStringToString
   L. Stewart, January 2, 1983  6:24 PM, try again
   L. Stewart, January 18, 1983  5:10 PM, Bonsai
   L. Stewart, January 20, 1983  2:06 PM, bugs
   L. Stewart, March 6, 1983  3:51 PM, remove Allocate
   L. Stewart, April 18, 1983  11:13 AM, new Agent
   L. Stewart, May 4, 1983  2:52 PM, AgentInitialize must be manual
 */

#include <Env.h>
#include <Signal.h>
#include <Context.h>
#include <Queue.h>
#include <rpc.h>
#include <rpcinternal.h>
#include <rpclupine.h>
#include <rpcpkt.h>
#include <rpcbind.h>

/* ---- Imports ---- */

extern int CallFailed;
extern int ImportFailed;

/* Bonsai package */
extern int *StartBonsai();
extern CallBonsai();
extern CleanupCall();
extern AllocWordsFromPkt();
extern StringToPkt();

/* OS */
extern Block();
extern Marshall();
extern MoveBlock();
extern Swab();
extern Zero();

/* signaller */
extern CONT();
extern ENABLE();

/* RPC */
extern struct ShortSTRING *CStringToString();
extern struct ImportInstance *ImportInterface();
extern struct VersionRange *matchAllVersions;

/* ---- Agent interface RPC indices ---- */

#define doAuthenticate 4
#define doVitae 5

/* ---- Types and variables ---- */

static struct ImportInstance agentInstance[1];
static struct ShortSTRING *agentRope;

/* ---- Agent procedures ---- */

/*
    Call is [nonceID: INT, caller, callee: ROPE]
   Return is
    [authentication, authenticator: SEQUENCE OF WORD]
 */

 int /* really Authentication */
AgentAuthenticate(nonceId, caller, callee, lvAuthenticator)
   int nonceId, caller, callee, *lvAuthenticator;
  {
  struct Seal sl;
  struct Seal1 csr;
  int *ap, *sp;
  int authentication;
  if (ENABLE(CallFailed, &CONT, &sl)) return (0);
  sp = ap = StartBonsai(agentInstance, &csr);
  *ap++ = Swab(doAuthenticate);  /* procedure index */
  if (nonceId) Marshall(true, ap, nonceId, 2);
  else Zero(ap, 2);
  ap += 2;
  ap = StringToPkt(ap, caller);
  ap = StringToPkt(ap, callee);
  CallBonsai(&csr, ap-sp);
  ap = sp;
  authentication = AllocWordsFromPkt(&ap, false);
  *lvAuthenticator = AllocWordsFromPkt(&ap, false);
  CleanupCall(&csr);
  return (authentication);
  };

/* Call is [clientMachine: Machine, range: INT, interfaceType: ROPE] */
/* Return is [Machine, ROPE, ROPE, ROPE] */

int Vitae(clientMachine, range, interfaceType, lvclientRname, lvclientInstance, lvserverInstance)
  int clientMachine;
  int *range;
  struct ShortSTRING *interfaceType;
  struct ShortSTRING **lvclientRname;
  struct ShortSTRING **lvclientInstance;
  struct ShortSTRING **lvserverInstance;
  {
  struct Seal sl;
  struct Seal1 csr;
  int serverMachine;
  int *ap, *sp;
  if (ENABLE(CallFailed, &CONT, &sl)) return (0);
/* this was 
  if (ENABLE(CallFailed, &CONT, &sl) || (agentInstance==0 && AgentInitialize() == false)) return (0);
 */
  sp = ap = StartBonsai(agentInstance, &csr);
  *ap++ = Swab(doVitae);  /* procedure index */
  *ap++ = clientMachine;  /* byte pair really */
  if (range) Marshall(true, ap, range, 2);
  else Zero(ap, 2);
  ap += 2;
  ap = StringToPkt(ap, interfaceType);
  CallBonsai(&csr, ap-sp);
  serverMachine = *sp++;
  *lvclientRname = AllocStringFromPkt(&sp);
  *lvclientInstance = AllocStringFromPkt(&sp);
  *lvserverInstance = AllocStringFromPkt(&sp);
  CleanupCall(&csr);
  return (serverMachine);
  };

/* ---- Initialization ---- */

int /*BOOL*/ AgentInitialize()
  {
  struct InterfaceName interface;
  struct Seal sl;
  Zero(&interface, lenInterfaceName);
  interface.type = agentRope;
  interface.instance = 0;
  Move2(&interface.version, matchAllVersions);
    /* should be more selective? */
  if (ENABLE(ImportFailed, &CONT, &sl)) return (false);
  ImportInterface(0, &interface, agentInstance);
  Block();
  return (true);
  };

AgentRopes()
  {
  agentRope = CStringToString("Agent.Lark");
  };