/*
 * hostinfo.h
 *
 * This file defines the database structure used to keep track of all the
 * URLs and their associated authorization/cookie/state info. All state
 * information is maintained solely in memory, and never stored on disk.
 */

/* A simple structure for mapping request types to number and port number.
 * The Requests are numbered in the same order as CAB's proxy structure.
 * This sequence must be maintained in order for proxy lookups to work.
 */
typedef struct service {
	char *name;
	unsigned short port;
} service;

#define	FTP	0
#define	HTTP	1
#define	WAIS	2
#define	GOPHER	3
#define	NNTP	4
#define	NO_PROXY	5	/* empty slot */
#define	MAIL	6
#define	NEWS	7
#define	HTTPS	8
#define	SNEWS	9

#define	RQ_FIRST	FTP
#define	RQ_LAST		SNEWS
#define	RQ_PROXIES	(NEWS+1)

/*
 * The basics - a Pascal-ish string, with associated length. Storing the
 * string length makes searches faster. The text of the string must be
 * allocated contiguously with the block, so it doesn't need a separate
 * free operation during cleanup.
 */
typedef struct lstr
{
	int len;
	char *txt;
} lstr;

/* A cookieB is used for HTTP cookies. The name and value are allocated
 * contiguously with the structure.
 */
typedef struct cookieB
{
	struct cookieB *next;
	char *name;
	char *value;
} cookieB;

/* This definition maps onto the first two fields of each of the following
 * block definitions. It's only used to facilitate a generic allocator for
 * the block types.
 */
typedef struct genericB
{
	struct genericB *next;
	lstr name;
} genericB;

/* An authB holds authentication info. The realm name is allocated
 * contiguously with the structure.
 */
typedef struct authB
{
	struct authB *next;
	lstr name;
	char *user;
	char *pass;
	char *nonce;	/* for Digest auth info */
	char *opaque;	/* for Digest auth info */
} authB;

/* A pathB holds cookie info for a specific path in a given realm. The
 * path is allocated contiguously with the block.
 */
typedef struct pathB
{
	struct pathB *next;
	lstr name;
	cookieB *cookies;
	authB *auth;
	unsigned long expire;	/* cookie expiration for this path */
	int version;	/* cookie version for this path */
	int flags;
} pathB;

#define	P_AUTH_PROXY	1	/* This is proxy auth info */
#define	P_AUTH_DIGEST	2	/* This uses Digest auth instead of Basic */
#define P_COOK_SECURE	4	/* This cookie can only be sent if secure */
#define	P_COOK_DOMAIN	8	/* This cookie has explicit domain set */
#define	P_COOK_PATH	16	/* This cookie has explicit path set */

/* A particular authorization domain. The name is allocated contiguously with
 * the block. This object can be referenced from multiple hosts, and cannot
 * be deallocated until all hosts have freed it.
 */
typedef struct domainB
{
	pathB *paths;
	lstr name;
	int refs;
} domainB;

/* A domainH is a host-specific pointer to a domainB. These are chained off
 * the hostB structure defined below.
 */
typedef struct domainH
{
	struct domainH *next;
	struct domainB *domain;
} domainH;

/* A nodeB stores the state of a particular URL object.
 */

typedef struct nodeB
{
	struct nodeB *next;
	lstr name;
	unsigned long size;
	unsigned long time;
	char *type;
	char *etag;
} nodeB;

/* A blkL is a counted list of blocks. */
typedef struct blkL
{
	int num;
	genericB *lst;
} blkL;

typedef void (freefunc)(genericB *ptr);

/* A set of parameters for manipulating a list of blocks */
typedef struct lstX
{
	int max;	/* Is there a maximum size for this list? */
	int icase;	/* Do we ignore case when searching this list? */
	size_t size;	/* How big is a list element, for allocating? */
	freefunc *free;	/* How do we free it? */
} lstX;

/* A hostB forms the root of the tree of info maintained for the particular
 * host. 
 *
 */
#define	HB_ADDRS	4	/* Track up to 4 addresses, max */
typedef struct hostB
{
	struct hostB *next;
	lstr name;
	long addr[HB_ADDRS];
	domainH *domains;
	blkL nodes;
} hostB;

/* The list of hosts is maintained in Most-recently-used order, as is the
 * list of nodes on each host. The number of nodes per host and total number
 * of hosts is limited to prevent hogging system memory. When the host list
 * reaches the maximum size, all of its associated data are freed.
 */
#define	MAX_HOSTS	16
#define	MAX_NODES	32
#define	MIN_HOSTS	2
#define	MIN_NODES	2


/* A sockB tracks an open connection. Currently we only save state for two
 * connections: current and previous.
 */
typedef struct sockB
{
	hostB *host;
	FILE *sp;
	void *ssl_con;		/* Only used if compiled with -DUSE_SSL */
	int s;
	unsigned short port;
} sockB;

/* A urlB collects all the information required to connect to a URL. The
 * path referenced here is one residing on the given host, we just store
 * the pointer again so it doesn't need to be searched twice.
 */

typedef struct urlB
{
	unsigned short port;
	char request;
	char flags;
	hostB *host;
	nodeB *path;
	lstr user;
	lstr pass;
} urlB;

#define	U_USE_PROXY	1
#define	U_DID_REDIR	2
#define	U_USE_SSL	4

#define	PARSE_HOST	0
#define	PARSE_PROXY	1

int parseUrl(char *url, urlB *pUrl, int is_proxy);

void FreeCookieB(cookieB *ptr);
void FreePathB(pathB *ptr);
void FreeDomainB(domainB *ptr);
void FreeNodeB(nodeB *ptr);
void FreeHostB(hostB *ptr);

cookieB *NewCookie(lstr *name, lstr *value);
void *NewBlock(lstr *name, size_t blkSize);

#define	NewPathB(a)	NewBlock(a, sizeof(pathB))
#define	NewDomainB(a)	NewBlock(a, sizeof(domainB))
#define	NewNodeB(a)	NewBlock(a, sizeof(nodeB))
#define	NewHostB(a)	NewBlock(a, sizeof(hostB))

domainB *GetDomainB(lstr *name, hostB *host, int *newdomain);
pathB *GetPathB(lstr *name, domainB *domain);
authB *GetAuthB(lstr *name, pathB *path);

extern lstX hostX, nodeX;
