/* 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  9:49 AM, format
   L. Stewart, January 1, 1983  4:48 PM, unflush CStringToString
 */

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

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

extern struct ZN *myZone;
extern int CallFailed;
extern int ImportFailed;

extern AddType();
extern int CallFormatted();
extern CONT();
extern dBlock();
extern ENABLE();
extern struct ImportInstance *ImportInterface();
extern struct ShortSTRING *CStringToString();


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

#define doAuthenticate 4
#define doInstanceForInterface 5

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

static struct ImportInstance *agentInstance;
static int args[10];
static struct ShortSTRING *specABN, *specAA, *specW;
static int zip[2];

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

 int /* really Authentication */
AgentAuthenticate(nonceId, caller, callee, lvAuthenticator)
   int nonceId, caller, callee, *lvAuthenticator;
  {
   struct Seal sl;
   int authentication;
   if (ENABLE(CallFailed, &CONT, &sl) || (agentInstance==0 && AgentInitialize()==false)) return (0);
  args[0] = nonceId;
  args[1] = caller;
  args[2] = callee;
  authentication = CallFormatted(agentInstance, doAuthenticate, specABN, specAA, args);
  *lvAuthenticator = args[4];
  return (authentication);
  };
  
int /* really ShortSTRING */
AgentInstanceForInterface(range, type, instance)
  int range, type, instance;
  {
  struct Seal sl;
  if (ENABLE(CallFailed, &CONT, &sl) || (agentInstance==0 && AgentInitialize()==false)) return (0);
  args[0] = range ? range: (int) zip;
  args[1] = type;
  args[2] = instance;
  return (swab(CallFormatted(agentInstance, doInstanceForInterface, specABN, specW, args)));
  };

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

int /*BOOL*/ AgentInitialize()
  {
  struct InterfaceName interface;
  struct Seal sl;
  Zero(&interface, lenInterfaceName);
  interface.type = CstringToString("Agent.Lark");
  interface.instance = 0;
    /* should be more selective? */
  if (ENABLE(ImportFailed, &CONT, &sl)) return false;
  agentInstance = ImportInterface(&interface);
    /* (nonce: LONG CARD, A, B: ROPE) */
  specABN = CstringToString("DSS");
    /* (authentication, authenticator: Frob (seq.))*/
  specAA = CstringToString("KK");
    /* AgentInstanceForInterface result */
  specW = CstringToString("W");
    /* Word Sequence, no byte swaps */
  AddType('K', dBlock(16, 1, 0, true, false));
    /* Caller will have to swab, unpack, as needed,
        after decrypting funny
     */
  Block();
  return (true);
  };