/* Test.c 
   D. Swinehart 2 Sept. 1982 1:56 pm PDT (Thursday)
   L. Stewart October 20, 1982  9:44 PM
   L. Stewart December 27, 1982  3:20 PM, flush nested declarations
   L. Stewart January 1, 1983  4:17 PM, flush AllocZero
   L. Stewart January 3, 1983  1:28 PM, flush CStringToString
   L. Stewart March 6, 1983  4:44 PM, unflush CStringToString
*/

#include <Alloc.h>
#include <Queue.h>
#include <Ec.h>
#include <Env.h>
#include <Signal.h>
#include <rpc.h>
#include <rpcinternal.h>
#include <rpclupine.h>
#include <rpcbind.h>
#include <encrypt.h>

extern AddToDispatcherSpecs();
extern AddType();
extern int *Allocate();
extern struct ShortSTRING *CStringToString();
extern Block();
extern CallContext();
extern int CallFormatted();
extern CallSwat();
extern int CONT();
extern Dismiss();
extern Free();
extern int ExportFailed;
extern ExportInterface();
extern InitOS();
extern int ImportFailed;
extern int ImportInterface();
extern struct VersionRange *matchAllVersions;
extern Move2();
extern MoveBlock();
extern int mySoc;
extern RPCInitialize();
extern RPCInitializeCtx();
extern int *StartDispatcherSpecs();
extern StartNProcess();
extern int StdDispatcher();
extern Zero();

extern ReadCalendar();
extern int largest, totAv, routSent, routRcvd, calSent, calRcvd;
extern struct ZN *sysZone;
extern struct EncryptionKey nullKeyB;

static struct Queue ctxQ;
static int/*BOOL*/ running;
static int/*BOOL*/ beUser;
static int/*BOOL*/ beServer;
static struct ShortSTRING *retRope;
static struct ShortSTRING *srvr, *usr;

static struct ShortSTRING *spNl, *spWd, *spSt, *spSt2, *spSq;
static int remote;
static struct Conversation *shhhh;

/* RPC Procedure indices */
#define Simple 	4
#define SArg 	5
#define SRet 	6
#define SendRope 	7
#define GetRope 	8
#define SendSeq 	9
#define GetSeq 	10

extern/*forward*/ Client();

Main() {
  srvr = usr = 0;
  shhhh = unencrypted;
  InitOS(); /* Sets up sysZone */
  Zero(&ctxQ, 2);
  RPCInitialize(&ctxQ);
  spNl = (struct ShortSTRING *) Allocate(sysZone, 2);
  spWd = CStringToString("W");
  spSt = CStringToString("S");
  spSt2 = CStringToString("DSS");
  spSq = CStringToString("C");
  StartNProcess("Client", &ctxQ, &Client, 350, 90); /* ?? */
  while (true) { CallContext(ctxQ.head); }; };

static int time[2];
static struct ImportInstance handle[1];
static struct Seal sl;
static struct InterfaceName *clientInterface;
static struct ShortSTRING *tibet;
static struct ShortSTRING *seqRope;
static int res;
static int teddyMode; /* Silent, but fast. */
int args[10];

static Client() {
  	int c, go;
  while (true) {
  	go=false; remote=false; teddyMode=false;
	Wf("\r.");
	c = MyGetChar();
	putchar(c);
	switch (c) {
	  case 'q': teddyMode=true;break;	/* be QUIET */
	  case 'Q': teddyMode=false; break; /* shout */
	  case 'g': go=true;
	  case 'i': Initialize(); if (!go) break;
	  case 's': Server(); if (!go) break;
	  case 'b': Bind(); break
	  case 'r': remote = true; srvr = CStringToString("173#125#");
				/* usr = CStringToString("Constellation"); */
				break;
	  case 'x': {
		struct ShortSTRING *tester, *testee; /* random RNames, for now */
		tester = CStringToString("Swinehart.pa");
		testee = CStringToString("Einstein.lark");
		shhhh = StartConversation(tester, &nullKeyB, testee, slECB); break };
	  case '1':
		res=CallFormatted(handle, Simple, spNl, spNl, 0); break;
	  case '2': {
  		args[0]= 0x1234
  		res = CallFormatted(handle, SArg, spWd, spNl, args); break; };
	  case '3':
  		res = CallFormatted(handle, SRet, spNl, spWd, 0);
		Wf1("res = %xH\r", res); break;
	  case '4':
		args[0] = (int) time;
		args[1] = (int) tibet;
		args[2] = (int) tibet;
  		res = CallFormatted(handle, SendRope, spSt2, spNl, args); break;
	  case '5': WfNFree("res = %s\r",
				res=CallFormatted(handle, GetRope, spNl, spSt, 0)); break;
	  case '6': {
  		args[0] = 0;
  		res = CallFormatted(handle, SendSeq, spSq, spWd, args);
  		args[0] =((int) &seqRope->maxLength);
  		res = CallFormatted(handle, SendSeq, spSq, spWd, args);
		break; };
	  case '7': {
  		args[0]=0x4321
  		res = CallFormatted(handle, GetSeq, spWd, spSq, args);
		Wf1("res = %xH\r", res); break; };
	  case '8': {
		args[0] = (int) time;
		args[1] = (int) tibet;
		args[2] = (int) tibet;
		AttachConversation(handle, shhhh);
  		res = CallFormatted(handle, SendRope, spSt2, spNl, args);
		AttachConversation(handle, unencrypted); break; };
	  case '9': {
		AttachConversation(handle, shhhh);
		WfNFree("res = %s\r",
				res=CallFormatted(handle, GetRope, spNl, spSt, 0));
		AttachConversation(handle, unencrypted); break; };
	  case 'p':
		Wf1("res = %x\r", res); break;
	  case 't':
		ReadCalendar(time);
		Alloc(sysZone, 0);
		Wf4("Time = (%o, %o), TotAv = %d, Largest = %d\r",
			time[1], time[0], totAv, largest);
		Wf4("Rout/Cal Sent/Rcvd = %d, %d, %d, %d\r",
			routSent, routRcvd, calSent, calRcvd); break;
	  default: Wf(" ?? "); break; }; }; };

static int MyGetChar() {
	while (!chav()) Block();
	return getchar(); };

static WfNFree(pat, str) int *pat; struct ShortSTRING *str; {
	int *cstr;
	if (str==0) return;
	cstr = StringToCString(sysZone, str); Free(sysZone, str);
	if (!teddyMode) Wf1(pat, cstr); Free(sysZone, cstr); };

static Initialize() {
  RPCInitializeCtx(true);
  AddType('Z', 0);
  Zero(handle, lenImportInstance);
  clientInterface = (struct InterfaceName *) Allocate(sysZone, lenInterfaceName);
  clientInterface->type = CStringToString("TestLupine");
  clientInterface->instance = usr;
  Move2(&clientInterface->version, matchAllVersions);
  tibet = CStringToString("This rope went to Everest");
  seqRope = CStringToString("This is really a sequence"); };

static Bind () {
  { /* Implicit loop until ENABLE succeeds */
  int serverMachine;
  serverMachine = 0;
  if (ENABLE(ImportFailed, &CONT, &sl))
	CallSwat(ecPup1+100);
  ImportInterface(serverMachine, clientInterface, handle); }; /* endloop */ };

extern/*forward*/ DoSimple();
extern/*forward*/ DoSArg();
extern/*forward*/ int DoSRet();
extern/*forward*/ int DoSendRope();
extern/*forward*/ struct ShortSTRING *DoGetRope();
extern/*forward*/ int DoSendSeq();
extern/*forward*/ int DoGetSeq();

static Server()  {
  struct InterfaceName *interface;
  int *specs;
  interface = (struct InterfaceName *) Allocate(sysZone, lenInterfaceName);
  interface->type = CStringToString("TestLupine");
  interface->instance = srvr;	/* Field broadcasts if not remote (for now)! */
  Move2(&interface->version, matchAllVersions);
  specs = StartDispatcherSpecs(9);
  AddToDispatcherSpecs(specs, Simple, &DoSimple, spNl, spNl);
  AddToDispatcherSpecs(specs, SArg, &DoSArg, spWd, spNl);
  AddToDispatcherSpecs(specs, SRet, &DoSRet, spNl, spWd);
  AddToDispatcherSpecs(specs, SendRope, &DoSendRope, spSt2, spWd);
  AddToDispatcherSpecs(specs, GetRope, &DoGetRope, spNl, spSt);
  AddToDispatcherSpecs(specs, SendSeq, &DoSendSeq, spSq, spWd);
  AddToDispatcherSpecs(specs, GetSeq, &DoGetSeq, spWd, spSq);
  ExportInterface(interface, &StdDispatcher, specs);
  retRope = CStringToString("Don\'t fence me in"); };
  
static DoSimple() {};
static DoSArg(a) int a; {if (!teddyMode) Wf1("  ||SArg Called With %xH\r",a);};
static int DoSRet()  {return 0x7654; };
static int DoSendRope(d, r, s) struct ShortSTRING *r, *s; int *d; { 
	WfNFree("  ||SendRope Called With %s and %s and %d\r", r, s, d[0]); return 0-true; };
static struct ShortSTRING *DoGetRope() { return retRope; };
static int DoSendSeq(s) int *s; {
	if (!teddyMode) Wf1("  ||SendSeq Called With %xH\r",s); 
	if (s) Free(sysZone, s); return 0-true; };
static int DoGetSeq(a) int *a; {return ((int) &retRope->maxLength); };

char *StringToCString(zone, s)
  struct ZN *zone;
  struct ShortSTRING *s;
  {
  int len, i; char b[];
  len = s->length;
  b = (char *) Allocate(zone, len/2+1);
  for (i = 0; i<len; ++i) b[i] = s->text[i];
  b[i]=0;
  return(b);
  };