/*
 *	Name:				xferqint.h
 *
 * Description:	Private include file for xferq.library
 *
 * Copyright:		1992-1993 by David Jones.
 *
 * Distribution:
 *		This program is free software; you can redistribute it and/or modify
 *		it under the terms of the GNU General Public License as published by
 *		the Free Software Foundation; either version 2 of the License, or
 *		(at your option) any later version.
 *
 *		This program is distributed in the hope that it will be useful,
 *		but WITHOUT ANY WARRANTY; without even the implied warranty of
 *		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *		GNU General Public License for more details.
 *
 *		You should have received a copy of the GNU General Public License
 *		along with this program; if not, write to:
 *
 *				The Free Software Foundation		David Jones
 *				675 Mass Ave							6730 Tooney Drive
 *				Cambridge, MA							Orleans, Ontario
 *				02139										K1C 6R4
 *				USA										Canada
 *
 *	Usenet:	gnu@prep.ai.mit.edu					aa457@freenet.carleton.ca
 *	Fidonet:												1:163/109.8
 *
 *		$Log: $
 *
 */

#ifndef XFERQINT_H
#define XFERQINT_H

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif

#ifndef EXEC_NODES_H
#include <exec/nodes.h>
#endif

#define	USE_PRIVATE_POOL
#ifndef USE_PRIVATE_POOL
#ifndef EXEC_MEMORY_H
#include <exec/memory.h>
#endif
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

/*
*	Work node entry
*		Work nodes are used to hold attributes of files queued for
*		transmission.
*/

struct WorkNode {
	struct Node node;				/* ln_Name and ln_Pri are valid */
	UWORD userFlags;				/* User accessible flags */
	char *asname;					/* Name to send file as */
	struct SiteQueue *site;		/* Back pointer to site node */
	struct NetAddress *addr;	/* Address that node should be queued to */
	ULONG seq;						/* Error recovery sequence number */
	UBYTE sysFlags;				/* System-use flags */
	UBYTE status;					/* Transmission status of node */
};

/*
*	System flags
*/

#define	XQ_INQUEUE		64			/* Node is in queue */
#define	XQ_LOCKED		128		/* Node is locked by another */


/*
*	Session structures
*		A session cookie is a linked list of session nodes.  Each session
*		node points to an address.
*
*		The queue functions make use of the QueueWalk structure to
*		support the NULL/session/address polymorphism.
*/

struct Session {
	struct Node node;				/* Link into global structure */
	UWORD flags;					/* See below */
	struct MinList sessList;	/* List of sites */
};

struct SessNode {
	struct MinNode node;			/* Link into session cookie */
	struct NetAddress *addr;	/* Address to which session is up */
};

struct QueueWalk {
	struct SiteQueue *sq;		/* Current site queue */
	struct SessNode *sn;			/* Private for session walks */
	int actions;					/* Actions for FindSiteQueue() */
};


/*
*	Site entry
*		The queue database consists of a linked list of site nodes, one
*		per site.  The site node is a linked list of work nodes.
*/

struct SiteQueue {
	struct SessNode sn;			/* SiteNode is extension to SessNode */
	struct MinList workList;	/* List of work nodes queued to site */
	ULONG seq;						/* Filename sequence number */
	UWORD flags;					/* See below */
	UWORD numSessions;			/* Number of sessions up to node */
	UWORD numLocks;				/* Number of nested LockMailer() calls */
};

#define	XQSITE_DIRTY		1		/* needs to be written to disk */
#define	XQSITE_UNREAD		2		/* needs to be read in from disk */
#define	XQSITE_INDEXED		4		/* site appears in site index */
#define	XQSITE_WREMPTY		8		/* queue is empty for write purposes */

#define	FSQ_NOP				0		/* Do nothing */
#define	FSQ_SCAN				1		/* Scan queue before searching */
#define	FSQ_READ				2		/* Read queue if found */
#define	FSQ_CREATE			4		/* Create queue if not found */

/*
*	Error handling
*		Errors are maintained on a per-process basis.  A list of these
*		structures keeps the error info.  In addition, the library
*		tracks which users are ARexx and which are not through this
*		structure.
*/

struct ENode {
	struct MinNode node;
	struct Task *task;
	LONG error;
	LONG localError;
	struct TagItem *config;
	UWORD flags;
};

#define	EN_ISREXX		1					/* Process is spawned by ARexx */

/*
*	Variable lists
*
*	The SNVal structure is a combination string/numeric data item where
*	either or both of the string and numeric fields may be valid.
*	A VarList is a linked list of named SNVal structures.
*/

struct SNVal {
	char *str;						/* String value */
	long num;						/* Numeric value */
	short flags;					/* Type(s) of value */
};

#define	VAR_NUMERIC		1		/* numeric field is valid */
#define	VAR_STRING		2		/* string field is valid */
	
struct VarListEntry {
	struct Node node;				/* Link to varlist structure */
	short nameLen;					/* Length of name */
	struct SNVal val;				/* Value of variable */
};

struct VarList {
	struct MinList list;
};


/*
*	Address structure
*/

struct NetAddress {
	LONG type;						/* One of the XQNT_... types */
	char *userName;				/* Name of user */
	struct {
		struct {
			char *domain;			/* Fidonet */
			char *zone;				/* Numeric quantities are stored as strings */
			char *net;				/* to facilitate templates */
			char *node;
			char *point;
		} fido;
		char *machine;				/* UUCP machine name */
		char *fqda;					/* Fully qualified domain address */
		char *text;					/* Generic text */
	} addr;
};

#define	ADDR_MAX			8		/* Max. fields in address */

#define	ET_ERROR			0
#define	ET_NUMBER		1
#define	ET_ALPHA			2

#define	GAE_NONE			0		/* For most address fields */
#define	GAE_DOTOK		1		/* For user name/text fields */
#define	GAE_SPACEOK		2		/* For Fido user names */

/*
*	Objects
*		The following structure precedes all objects in memory.  It allows
*		for multiple use and type identification.
*/

struct XfqObject {
	struct MinNode link;
	ULONG size;
	UWORD useCount;
	UWORD type;
};

#define ObjectType(x) ((struct XfqObject *)(x))[-1].type
#define ObjectSize(x) ((struct XfqObject *)(x))[-1].size

/*
 *		Level 2/3 private data structures.
 *
 *	What follows are field descriptions of objects that can be examined
 * or modified.  The structures relate an ARexx field name to an offset
 * in the structure having a specified type.
 */

struct FieldDesc {
	char *name;							/* Name of field (for ARexx) */
	Tag tag;								/* Tag item for field */
	short type;							/* Type of field */
	short offset;						/* Offset into structure */
};

/* The following object types are PRIVATE! */
#define	XQO_SEQ			2
#define	XQO_ENODE		6
#define	XQO_APATH		7			/* AnchorPath */
#define	XQO_SITEQUEUE	8
#define	XQO_SESSNODE	9
#define	XQO_VARLIST		10
#define	XQO_VLENTRY		11			/* VarListEntry */
#define	XQO_MAX			12

#define	XQO_BYTE		256			/* Signed byte */
#define	XQO_WORD		257			/* Signed word */
#define	XQO_LONG		258			/* Long */
#define	XQO_NUMSTR	259			/* KLUDGE string <-> number */

#define	XQO_OBJECT	128

#define	XODIP_OK			0			/* Data xfer OK */
#define	XODIP_NOTFOUND	1			/* Item not found */
#define	XODIP_ERROR		2			/* Conversion error */

/*
 * All objects have the following descriptor to allow efficient
 * examines, modifies and copies.
 */

struct ObjectDesc {
	/* Level 2 */
	char *abbr;							/* Abbreviation for ARexx cookies */
	short size;							/* Size of base */
	void (*postCreate)(void *);	/* Function to call after create */
	void (*preDrop)(void *);		/* Function to call before dropping */
	/* Level 3 */
	struct FieldDesc *fields;		/* Description of fields */
	BOOL (*preExamine)(void *);	/* Function to call before examine */
	BOOL (*postExamine)(void *);	/* Function to call after examine */
	BOOL (*preModify)(void *);		/* Function to call before modify */
	BOOL (*postModify)(void *);	/* Function to call after modify */
};

/*
*	Tags for all functions
*/

#define	XQ_WNBase		(XQ_OBASE + 0)		/* Base of WorkNode tags */
#define	XQ_ADBase		(XQ_OBASE + 16)	/* Base of Address tags */
#define	XQ_SSBase		(XQ_OBASE + 32)	/* Base of session tags */
#define	XQ_SQBase		(XQ_OBASE + 48)	/* Base of sequence tags */
#define	XQ_Sequence		XQ_SQBase
#define	XQ_DeathKiss	(XQ_BASE + 64)		/* Shut down NOW!!! */
#define	XQ_GetCore		(XQ_BASE + 65)		/* Get memory list */
#define	XQ_Meter			(XQ_BASE + 66)		/* Data for memory meter */

/*
*	Internal functions
*/

ULONG InitMemory(void);
void DropMemory(void);

void *AllocObject(ULONG, ULONG);
void FreeObject(void *);
void CoreDump(void);
ULONG PValid(void *);
void PCheck(char *, ...);

void *DupObject(void *);

char *CopyStringN(char *, ULONG);
char *CopyString(char *);
char *NeedString(char *, ULONG);
BOOL ExamObject(void *, short (*func)(), void *);
void *ModifyObject(void *, short (*func)(), void *, BOOL);
BOOL ExamObjectVarList(void *, struct VarList *);
void *ModifyObjectVarList(void *, struct VarList *);

void NewSNVal(struct SNVal *);
void SetSNValNum(struct SNVal *, long);
BOOL SetSNValStr(struct SNVal *, char *, int);
BOOL GetSNValNum(struct SNVal *, long *);
char *GetSNValStr(struct SNVal *);
void CopySNVal(struct SNVal *, struct SNVal *);

struct Node *FindNameNoCase(struct MinList *, UBYTE *);
struct VarList *NewVarList(void);
void EmptyVarList(struct VarList *vl);
void DropVarList(struct VarList *vl);
BOOL AddVarListNum(struct VarList *, char *, int, long);
BOOL AddVarListStr(struct VarList *, char *, int, char *, int);
BOOL GetVarListNum(struct VarList *, char *, int, long *);
struct VarListEntry *FindVarList(struct VarList *, char *, int);
char *GetVarListStr(struct VarList *, char *, int);
struct VarList *CopyVarList(struct VarList *);
short GetNumber(char *string, short base, short maxLen, long *num);
short PutNumber(char *string, short base, short maxLen, long num);
int GetAddrElement(char **, int);
long ParseVarList(char *, char *, struct VarList *);

void InitErrors(void);
struct ENode *FindENode(BOOL);
void DropENode(struct ENode *);
void SetErrorTags(struct TagItem *);

void InitAddress(void);
BOOL CanonAddress(struct NetAddress *);

BOOL PreExamWork(struct WorkNode *);
BOOL PostExamWork(struct WorkNode *);
BOOL PreModifyWork(struct WorkNode *);
BOOL PostModifyWork(struct WorkNode *);
void SessionDownQueue(struct SiteQueue *);
struct SiteQueue *FindSiteQueue(struct NetAddress *, int);
struct SiteQueue *NewSiteQueue(struct NetAddress *);
struct SiteQueue *FirstSiteQueue(void *, struct QueueWalk *);
struct SiteQueue *NextSiteQueue(struct QueueWalk *);
ULONG SimpleAddWork(struct SiteQueue *, struct WorkNode *wn);
void InitQueue(void);
void DropQueue(void);
void DropSiteQueue(struct SiteQueue *);
BOOL AnyDirty(void);

void PostCreateSession(struct Session *);
void PreDropSession(struct Session *);
struct NetAddress *NextWalkSession(struct SessNode **);
struct NetAddress *StartWalkSession(struct Session *, struct SessNode **);

void ScanQueue(void);
void ReadSiteQueue(struct SiteQueue *);
char *FullPath(char *);
ULONG TruncateFile(char *);
void ReadConfig(void);
void InitSeq(void);

void InitRexx(void);

#ifdef DEBUG
int GetCount(void *);
void CheckCount(char *, void *, int);
#endif
void kprintf(const char *, ...);

ULONG __asm CallHookRes(register __a0 struct Hook *, register __a2 void *,
	register __a1 void *, register __a4 void *);
void *Geta4(void);

/*
*	Prototypes for internal functions
*
*	These work like their Xfq... counterparts, but do not set the
*	user error code.
*/

ULONG LibAddWork(struct NetAddress *, struct WorkNode *);
ULONG LibAddWorkQuick(char *, char *, char *, LONG, LONG);
ULONG LibAnyWork(void *, struct TagItem *);
struct WorkNode *LibGetWork(void *, struct TagItem *);
struct WorkNode *LibFindWork(struct TagItem *);
void LibUnlockWork(struct WorkNode *);
ULONG LibRemoveWork(struct WorkNode *);
LONG LibMaxSitePri(void *);
void LibWalkQueueCallBack(struct NetAddress *, struct TagItem *, void *);
struct Session *LibGetSiteList(void);
ULONG LibFlushQueue(void *object);

ULONG LibBeginSession(struct Session *, struct TagItem *);
void LibEndSession(struct Session *, void *);
ULONG LibSessionUp(struct NetAddress *);
void LibSortSession(struct Session *, struct TagItem *);
void LibWalkSessionCallBack(struct Session *, struct TagItem *, void *);

ULONG LibNextSeq(ULONG);
void *LibHook(struct TagItem *);

ULONG LibReadQueue(char *, struct NetAddress *, ULONG);
ULONG LibWriteQueue(char *, struct NetAddress *, ULONG);

struct NetAddress *LibGetAddress(char *, struct NetAddress *, struct TagItem *);
char *LibPutAddress(void *, struct TagItem *);
LONG LibCmpAddress(void *, void *, struct TagItem *);
struct NetAddress *LibMap(struct NetAddress *, struct TagItem *);
ULONG LibFilter(void *, struct TagItem *);

void *LibCreateObject(ULONG, struct TagItem *);
void LibDropObject(void *);
ULONG LibExamObject(void *, struct TagItem *);
void *LibModifyObject(void *, struct TagItem *);
void *LibCopyObject(void *);

ULONG LibHoldMailer(struct NetAddress *);
ULONG LibReleaseMailer(struct NetAddress *);

void *LibParseString(char *, char *, void *, struct TagItem *);
char *LibBuildString(char *, void *, struct TagItem *);
void LibScanDirCallBack(BPTR, char *, void *, struct TagItem *, void *);

ULONG LibSetAppConfig(struct TagItem *);

/*
*	Varargs prototypes
*/

ULONG LibBeginSessionTags(struct Session *, Tag, ...);

struct NetAddress *LibGetAddressTags(char *, struct NetAddress *, Tag, ...);
char *LibPutAddressTags(void *, Tag, ...);
LONG LibCmpAddressTags(void *, void *, Tag, ...);

void *LibCreateObjectTags(ULONG, Tag, ...);
ULONG LibExamObjectTags(void *, Tag, ...);
void *LibModifyObjectTags(void *, Tag, ...);

void LibScanDirCallBackTags(BPTR, char *, void *, Tag, ...);

#endif /* XFERQINT_H */
