#include "Connect.h"
#include "Parse.h"
#include "protocol.h"

#define CONTEXTTABLESIZE 1000
#define MAXPORTS 20
#define MAXCONNS 20
#define MAXSERVERS 10

struct _License;
struct _Pool;
struct _Context;
struct _OldPool;

/*
 * Server contact values
 */
#define SERVER_CONNECTED 0	/* recent contact */
#define SERVER_DISCONNECTED 1	/* not so recent contact */
#define SERVER_DEAD 2		/* ancient contact */
#define SERVER_DOWN 3		/* informed down */

/*
 * Server state values
 */
#define MASTER 0		/* willing to grant, multicasting */
#define MASTER_REDUCE 1		/* same, and in reduction process */
#define BACKUP 2		/* referring requests, replying */

/*
 * Clues... Indicates level of knowledge of outside world.
 * Based on time awake.
 */
#define CLUELESS 0		/* no clue of world state */
#define SEMICLUED 1		/* knows about servers */
#define CLUEFUL 2		/* knows about clients too */

#define local(var) (s->servers[s->us].var)

typedef struct _OldPool {
  Card16 active;
  Card16 free;
} OldPool;

typedef struct _Server
{
  /* constants */
  Addr connection;
  Addr activitySource;

  /* computed on packets, timeouts */
  time_t last_handshake;	/* time of last connection activity */
  int contact;
  OldPool *poolState;	/* last known pool state of timed-out server */
  int groupSize;	/* group size with that state */

  /* from STATE packets */
  time_t last_contact;		/* time of last evidence of life */
  int state;
  int custodian;		/* index of custodian, if backup */
  int clue;

  int retryCount;		/* retransmissions for multicast */
  time_t nextRetry;		/* when to retransmit */
} Server;

#define CLIENTTIMEOUT 0		/* timeout for client code */
#define SERVERTIMEOUT 1		/* timeout for server code */

/*
 * Wakeup reasons
 */
#define MULTICAST 1		/* time for a server multicast */
#define RETRY 2			/* retry send on state packet */
#define SERVER_DISCONNECT 3	/* a backup server times out */
#define SERVER_DEATH 4		/* a server becomes considered dead */
#define GETSOMECLUE 5	    /* we've been around long enough to be clueful */
#define SERVER_CONNECT 6	/* reestablishing server contact */

typedef struct _srvinfo
{
  int portsInitialized;
  Addr ports[MAXPORTS];
  int connectionsInitialized;
  Addr fromConnections[MAXCONNS];
  Addr toConnections[MAXCONNS];
  int serverConns[MAXCONNS];
  Server servers[MAXSERVERS];
  MasterBlock *mb;
  struct _License *firstLicense;
  struct _Context *leastStale;
  struct _Context *mostStale;
  struct _Context *nextTimeout; /* most stale context with activity
				   since lastFreeze */

  P0Block *multi;

  /* server reduction - decider end */
  int reducee;			/* server we are reducing with */
  int newState;			/* state to change reducee to on completion */
  int sendCount;		/* pings left to send in verification */
  int acked;			/* was the last ping acked? */
  int acksFailed;		/* number of timed-out acks & restarts */
  time_t next;			/* wakeup for next send */

  /* server reduction - decidee end */
  int reducer;
  time_t last_reduce;

  int multicastMade;		/* for wrapping up server reduction */

  int numServers;
  int us;			/* index of our entry in server table */
  int checkQueues;
  int totalPools;		/* number of pools from all licenses */

  time_t startup;		/* server startup time */
  time_t nextMulticast;		/* time for next multicast */
  time_t nextWakeup;		/* time for next wakeup due to servers */
  time_t clueTime;		/* time to bump clue state */
  int reason;			/* reason for nextWakeup */
  time_t lastFreeze;		/* time of last global freeze */
} srvinfo;

typedef struct _License {
  char *vendor;
  char *program;
  char *version;
  int numPools;
  int checkQueue;		/* some licenses have been released */
  struct _Pool *firstPool;
  struct _Context *queue;	/* license queue */
  struct _Context *queueEnd;
  struct _License *next;
} License;

typedef struct _Pool {
  License *license;
  int licenses;		/* total licenses in pool */
  int active;		/* licenses in pool we have contact with */
  int free;		/* licenses in pool free for us to grant */
  ParseBlock *pb;
  struct _Pool *next;
} Pool;

extern Keywords mainwords[];
extern Keywords authorizewords[];

#define CONFIG "config"
#define PACKAGE "package"
#define POOL "pool"

#define PACKDATA "packdata"
#define POOLDATA "pooldata"

/* access description record */
typedef struct _Adr
{
  char *user;
  char *machine;
  char *hostname;
  u_long ip;
  char *vendor;
  char *program;
  char *version;
} Adr;

typedef struct _Context
{
  Addr connection;			/* connection number */
  int contextNum;			/* context per connection */
  char *user;				/* username */
  char *machine;			/* machine type info */
  Card32 authVec;			/* set of pools authorized for */
  Pool *what;				/* pool of granted licenses */
  int licensesHeld;			/* total licenses granted */
  int licensesRequested;		/* total licenses desired */
  Addr activitySource;			/* address received last packet */
  time_t activity;			/* time of last received packet */
  struct _Context *moreStale;		/* links in global context */
  struct _Context *lessStale;		/*   staleness queue */
  struct _Context *nextQueue;		/* per license queue */
  struct _Context *next;		/* global context bucket */
} Context;

#define GetUser(c) (c->user)
#define GetMachine(c) (c->machine)
/* Ack.
#define GetHostname(c)		not really doable in a macro
#define GetIP(c)		ditto
		abstraction barrier violation, but krb needs it
*/
#define GetVendor(c) (c->what->license->vendor)
#define GetProgram(c) (c->what->license->program)
#define GetVersion(c) (c->what->license->version)

#define NONE 0
#define PARTIAL 1
#define TOTAL 2

#define NOALLOC 0
#define ALLOC 1
