#include <stdio.h>
#include <sys/param.h>
#include <pwd.h>
#include <time.h>
#include "Connect.h"
#include "inet-udp.h"
#include "protocol.h"
#include "machdefs.h"

#define printError() if (Error_Severity != S_INFO) fprintf(stderr, "%s\n", Error_String(Error))

#define VENDOR "MIT"
#define PROGRAM "test"
#define VERSION "0.0"

main(argc, argv)
     char **argv;
{
  Addr a, b;
  Packet p;
  char message[200];
  char name[50];
  P0Packet P;
  char hostname[MAXHOSTNAMELEN];
  struct passwd *pwd;
  u_long netip;
  time_t baseTime;

  if (Connect_Initialize())
    printError();
  if (Connect_RegisterDomain(&inetudp))
    printError();

  if (Connect_NameToAddress("inet-udp:.", &a))
    printError();
  if (Connect_NameToAddress("inet-udp:sullius-secundus/3711", &b))
    printError();

  if (Connect_OpenConnection(a, b))
    printError();

  p.Source = a;
  p.Destination = b;
  p.packet = message;

  P.packet = &p;
  P.type = P0_ACCESS_INITIALIZE;
  P.context = 0;
  P0_PutHeader(&P);

  pwd = getpwuid(getuid());
  if (pwd == NULL)
    {
      fprintf(stderr, "Your uid is not in the password file.\n");
      exit(1);
    }

  P0_PutString(&P, pwd->pw_name); /* user ID */

  P0_PutString(&P, SYSTEM);	/* machine ID */
  gethostname(hostname, sizeof(hostname));
  P0_PutString(&P, hostname);
  Udp_IP(a, &netip);
  P0_PutCard32(&P, netip);

  P0_PutString(&P, VENDOR);	/* package ID */
  P0_PutString(&P, PROGRAM);
  P0_PutString(&P, VERSION);

  P0_PutCard32(&P, 0);		/* have 0 licenses */
  P0_PutCard32(&P, 1);		/* want 1 license */
  P0_PutCard16(&P, 1);		/* keepopen */

  P0_PutLength(&P);

  if (Connect_SendPacket(&p))
    printError();

  baseTime = time((time_t *)0);

  while (1)
    {
      Card32 e, have, want;

      if (Connect_Wait(&p,
		       (T_ping - (time((time_t *)0) - baseTime) % T_ping)
		       * 1000))
	{
	  if (Error == CONNECT_TIMEOUT)
	    {
	      p.Source = a;
	      p.Destination = b;
	      p.packet = message;

	      P.packet = &p;
	      P.context = 0;
	      P.type = P0_STATUS_QUERY;
	      P0_PutHeader(&P);
	      P0_PutLength(&P);
	      if (Connect_SendPacket(&p))
		printError();
	      continue;
	    }
	  else
	    if (Error_Severity == S_FATAL)
	      {
		printError();
		continue;
	      }
	}

      if (P0_GetHeader(&P))
	{
	  printError();
	  free(p.packet);
	  continue;
	}

      switch(P.type)
	{
	case P0_ERROR:
	  if (P0_GetCard32(&P, &e))
	    break;

	  fprintf(stdout, "Server returns error %d\n", e);
	  break;

	case P0_ACCESS_UPGRADE:
	case P0_ACCESS_RESPONSE:
	  if (P0_GetCard32(&P, &have) ||
	      P0_GetCard32(&P, &want))
	    break;

	  if (have == want)
	    fprintf(stdout, "granted\n");
	  else
	    fprintf(stdout, "queued\n");
	  break;

	default:
	  break;
	}
      free(p.packet);
    }
}
