#include <sys/times.h>
#include <lib/defs.h>
#include <sys/uio.h>

#define DRHSIZE		256
#define DRHMASK		(DRHSIZE-1)

/*
 * MSG_ flags that may not be implemented on a particular OS
 */

#ifndef MSG_WAITALL
#define MSG_WAITALL	0
#endif
#ifndef MSG_EOR
#define MSG_EOR		0
#endif

struct ServReq;
struct Timer;

#define THREAD_LISTEN	1	/* listening thread		*/
#define THREAD_DNS	2	/* dns resolver thread		*/
#define THREAD_READER	3	/* reader thread		*/
#define THREAD_SDNS	4	/* server dns resolver thread	*/
#define THREAD_DRCMD	5	/* drcmd listener thread	*/

#define THREAD_NNTP	6	/* nntp connection		*/
#define THREAD_SPOOL	7	/* spool connection		*/
#define THREAD_POST	8	/* outgoing post		*/
#define THREAD_FEEDER	9	/* feeder thread		*/

#define OVERVIEW_FMT	"Subject:\r\nFrom:\r\nDate:\r\nMessage-ID:\r\nReferences:\r\nBytes:\r\nLines:\r\nXref:full\r\n"
#define DEFMAXARTSINGROUP		1024
#define DEFARTSINGROUP			512
#define OV_CACHE_MAX			8	/* open fd's for N groups */
#define MAX_OVERVIEW_CACHE_REGIONS      2       /* 256x2 = 512 articles   */
#define MAX_CROSS			64

/*
 * THREAD_QSIZE is the number of spool requests that can be queued to
 * a spool thread before we back off to a higher d_Pri.
 *
 * THREAD_PSIZE is the number of post requests that can be queued to
 * a spool thread before we back off to a higher d_Pri.
 */

#define THREAD_QSIZE	16	/* for spool access		*/
#define THREAD_PSIZE	2	/* for posting			*/
#define THREAD_LIMSIZE	(((THREAD_QSIZE > THREAD_PSIZE) ? THREAD_QSIZE : THREAD_PSIZE) * 2)

#ifndef INET6
typedef struct sockaddr sockaddr_storage;
#endif

/*
 * ForkDesc - structure used to manage descriptors for select() threads
 */

typedef struct ForkDesc {
    struct Timer *d_Timer;	/* active timer		*/
    struct ForkDesc *d_Next;	/* linked list @ pri	*/ 
    struct ForkDesc *d_Prev;	/* linked list @ pri	*/ 
    char	*d_Id;		/* host name 		*/
    pid_t	d_Pid;
    int		d_Slot;		/* status reporting slot*/
    int		d_Fd;
    int		d_Type;
    int		d_FdPend;	/* save pending fd	*/
    int		d_Count;	/* active subthreads	*/
    int		d_Pri;
    void	*d_Data;
    struct sockaddr_storage d_SaveRSin;
    char	*d_LocalSpool;	/* direct spool access	*/
    int		d_Cache;	/* is spooler to be locally cached */
    int		d_CacheMin;	/* min article size to be cached */
    int		d_CacheMax;	/* max article size to be cached */
    int		d_CacheableTime;	/* oldest article to be cached */
    double	d_ReadNewRatio;	/* read/new articles ratio to reach to cache a group */
    double	d_CacheReadRatio;	/* cachehits/read articles ratio to reach to cache a group */
#ifdef	DREADER_CLIENT_TIMING
    clock_t	d_utime;
    clock_t	d_stime;
#endif
} ForkDesc;

/*
 * Authentication structures
 */

/*
 * The current output mode of the server to the client
 */
#define	DRBC_NONE	0
#define	DRBC_ARTICLE	1
#define	DRBC_HEAD	2
#define	DRBC_BODY	3
#define	DRBC_LIST	4
#define	DRBC_XOVER	5
#define	DRBC_XHDR	6
#define DRBC_XXXX	7	/* The last of the DRBC_ defines */

#define	OPT_NONE	0
#define	OPT_VSERVER	1
#define	OPT_GROUPS	2
#define	OPT_AUTH	3
#define	OPT_READERGRP	4

#define DEFNAMELEN	128

typedef struct Vserver {		/* Define a virtual server	*/
    char vs_Name[DEFNAMELEN];
    char vs_ClusterName[64];
    char vs_HostName[64];
    char vs_PostPath[64];
    char vs_NewsAdm[64];
    char vs_Org[128];
    char vs_AbuseTo[64];
    char vs_CryptPw[32];
    struct sockaddr_storage vs_Interface;
    char vs_AccessFile[128];
    int vs_NoXrefHostUpdate;
    int vs_NoReadPath;
    char vs_Welcome[256];
    char vs_Comments[256];
    char vs_PostTrailer[256];
} Vserver;

typedef struct GroupDef {		/* Define a group access list	*/
    char *gr_Name;
    int  gr_Count;
    struct GroupList *gr_Groups;
    struct GroupDef *gr_Next;
} GroupDef;

typedef struct AuthDef {		/* Define an authentication type */
    char au_Name[DEFNAMELEN];
    char au_File[255];
    char au_Cdb[255];
    char au_Db[255];
    char au_External[255];
    char au_Radius[255];
    char au_User[255];
    char au_Pass[255];
    char au_Realm[255];
    char au_AddRealm[255];
    char au_NetRemote[255];
    char au_LDAP[255];
    char au_Perl[255];
    char au_PAM[255];
    int au_Ident;
} AuthDef;

typedef struct ReaderDef {		/* Define a reader group	*/
    char rd_Name[DEFNAMELEN];
    char rd_Auth[DEFNAMELEN];
    char rd_Groups[DEFNAMELEN];
    char rd_ListGroups[DEFNAMELEN];
    char rd_PostGroups[DEFNAMELEN];
    char rd_Vserver[DEFNAMELEN];
    int rd_Read;
    int rd_Post;
    int rd_Feed;
    int rd_Status;
    int rd_Quiet;
    int rd_ControlPost;
    int rd_MaxConnTotal;
    int rd_MaxConnPerHost;
    int rd_MaxConnPerUser;
    int rd_MaxConnPerGroup;
    int rd_MaxConnUniqueHostLimit;
    int rd_MaxConnPerVs;
    int rd_RateLimit[DRBC_XXXX];
    int rd_RateLimitTax;
    int rd_ByteLimit;
    int rd_PathComponents;
    int rd_GroupLog;
    int rd_UseVerifiedDns;
    int rd_DenyMismatchedDns;
    int rd_DenyNoDns;
    int rd_AllowNewnews;
    int rd_SpoolHeaders;
    int rd_IgnoreAuthInfo;
    int rd_CheckPostGroups;
    int rd_LogCmd;
    time_t rd_IdleTimeout;
    time_t rd_SessionTimeout;
} ReaderDef;

typedef struct AccessDef {		/* Define the access list	*/
    char ad_Pattern[100];
    char ad_IdentUser[16];
    char ad_Reader[DEFNAMELEN];
    int ad_MatchExit;
} AccessDef;

typedef struct AccessMap {		/* Define an access mapping	*/
    Vserver *VServerList;
    int VServerCount;
    GroupDef *GroupsList;
    int GroupCount;
    void *GroupMap;
    long GroupMapSize;
    AuthDef *AuthList;
    int AuthCount;
    ReaderDef *ReaderList;
    int ReaderCount;
    AccessDef *AccessList;
    int AccessCount;
} AccessMap;

/*
 * DnsReq/DnsRes - structures used to manage DNS lookups
 *
 * At this point, I'm having doubts as to the wisdom of using
 * two structures, and wonder if it wouldn't be more prudent to
 * use DnsRes to talk to DnsTest.  Unless dreaderd is rewritten
 * with real threads, using DnsTest to handle arbitrary time-
 * intensive tasks such as dealing with auth is very attractive,
 * and will eventually end up requiring many DnsRes vars to be
 * stuffed into DnsReq.  Yech.  JG200106061214
 */

typedef struct DnsReq {
    struct sockaddr_storage dr_LSin;	/* local interface		*/
    struct sockaddr_storage dr_RSin;	/* remote ip:port		*/
    char dr_AuthUser[64];		/* authinfo user		*/
    char dr_AuthPass[16];		/* authinfo pass		*/
    int dr_ResultFlags;			/* see #defines below		*/
    double dr_ByteCount;		/* how many bytes sent - stats	*/
    int dr_GrpCount;			/* number of groups entered	*/
    int dr_ArtCount;			/* number of articles fetched	*/
    double dr_PostBytes;		/* how many bytes posted 	*/
    int dr_PostCount;			/* number of articles posted	*/
    int dr_PostFailCount;		/* number of failed postings	*/
    double dr_ByteCountArticle;		/* Bytes sent for art fetches	*/
    double dr_ByteCountHead;		/* Bytes sent for head fetches	*/
    double dr_ByteCountBody;		/* Bytes sent for body fetches	*/
    double dr_ByteCountList;		/* Bytes sent for list fetches	*/
    double dr_ByteCountXover;		/* Bytes sent for xover fetches	*/
    double dr_ByteCountXhdr;		/* Bytes sent for xhdr fetches	*/
    double dr_ByteCountOther;		/* Bytes sent for other fetches	*/
    time_t dr_SessionLength;		/* duration of session in secs	*/
} DnsReq;

/*
 * Define some values used in dr_ResultFlags
 */
#define	DR_REQUIRE_DNS	0x0001		/* authinfo check required	*/
#define	DR_SERVER_STATS	0x0002		/* struct has info server stats	*/
#define	DR_SESSEXIT_RPT	0x0004		/* reporting session term stats	*/

typedef struct DnsRes {
    struct DnsRes *dr_HNext;		/* main process hash link	*/
    int dr_Code;			/* the auth result code		*/
    int dr_Flags;			/* what options are enabled	*/
    int dr_ArtCount;			/* how many articles fetched	*/
    int dr_PostCount;			/* how many articles posted	*/
    int dr_PostBytes;			/* how many bytes posted	*/
    int dr_PostFailCount;		/* how many posts failed	*/
    double dr_ByteCount;		/* how many bytes sent		*/
    int dr_GrpCount;			/* how many groups accessed	*/
    double dr_ByteCountArticle;		/* Bytes sent for art fetches	*/
    double dr_ByteCountHead;		/* Bytes sent for head fetches	*/
    double dr_ByteCountBody;		/* Bytes sent for body fetches	*/
    double dr_ByteCountList;		/* Bytes sent for list fetches	*/
    double dr_ByteCountXover;		/* Bytes sent for xover fetches	*/
    double dr_ByteCountXhdr;		/* Bytes sent for xhdr fetches	*/
    double dr_ByteCountOther;		/* Bytes sent for other fetches	*/
    time_t dr_TimeStart;		/* Time connection was made	*/
    int dr_ReaderPid;			/* process ID of reader process	*/
    struct sockaddr_storage dr_Addr;	/* remote IP address and port	*/
    char dr_Host[64];			/* the remote hostname		*/
    char dr_ReaderName[DEFNAMELEN];	/* the reader group name	*/
    char dr_VServer[DEFNAMELEN];	/* the virtual server		*/
    char dr_IdentUser[16];		/* the ident username		*/
    char dr_AuthUser[64];		/* the authinfo user		*/
    char dr_AuthPass[16];		/* the authinfo pass		*/
    int dr_DnsMismatch;			/* Fwd/Rev DNS don't match	*/
    int dr_ResultFlags;			/* see #defines above		*/
    int dr_StaticAuth;			/* don't change auth details	*/
    int dr_ConnCount;			/* for rate limit calculation	*/
    ReaderDef *dr_ReaderDef;		/* reader group	pointer		*/
    Vserver *dr_VServerDef;		/* vserver pointer		*/
    GroupDef *dr_GroupDef;		/* group list pointer		*/
    GroupDef *dr_ListGroupDef;		/* list group list pointer	*/
    GroupDef *dr_PostGroupDef;		/* post group list pointer	*/
    AuthDef *dr_AuthDef;		/* auth def pointer		*/
} DnsRes;

#define DF_FEED		0x00000001	/* can feed			*/
#define DF_READ		0x00000002	/* can read			*/
#define DF_POST		0x00000004	/* can post			*/
#define DF_STATUS	0x00000008	/* only want status report	*/
#define DF_QUIET	0x00000010	/* don't log			*/
#define DF_CONTROLPOST	0x00000020	/* allowed to post Control:	*/
#define DF_AUTHREQUIRED	0x00000040	/* authentication required	*/
#define DF_FEEDONLY	0x00000080 	/* feed-only thread		*/
#define	DF_GROUPLOG	0x00000100	/* log groups accessed by user  */
#define	DF_AUTH		0x00000200	/* user valid with AUTHINFO	*/

/*
 * MBuf - structure used to manage read and write buffers
 */

typedef struct MBuf {
    struct MBuf *mb_Next;
    char	*mb_Buf;
    int		mb_Index;	/* finished index		*/
    int		mb_NLScan;	/* newline scan index 		*/
    int		mb_Size;
    int		mb_Max;
} MBuf;

typedef struct MBufHead {
    MBuf	*mh_MBuf;
    MemPool	**mh_MemPool;
    MemPool	**mh_BufPool;
    int		mh_Bytes;
    int		mh_Wait;
    int		mh_Fd;
    double	mh_TotalBytes;
    char	mh_REof;
    char	mh_WEof;
    char	mh_RError;
    char	mh_WError;
} MBufHead;

/*
 * Timer
 */

typedef struct Timer {
    struct Timer   *ti_Next;
    struct Timer   *ti_Prev;
    struct ForkDesc *ti_Desc;
    struct timeval ti_To;	/* requested timeout		*/
    struct timeval ti_Tv;	/* absolute time of timeout	*/
    int		ti_Flags;
} Timer;

#define TIF_READ	0x01
#define TIF_WRITE	0x02

typedef struct TimeRestrict {
    time_t	     tr_Time;
} TimeRestrict;

#define MAX_HDR_CC	0x08

#define LF		0x01
#define CR		0x02
#define CRLF		0x03
#define FLAG_PATH	0x01
#define FLAG_XREF	0x02
#define FLAG_NEEDED	0x03

#define INBODY		-1
#define JMPBDY		-2
#define HDRCPY		-3
#define HDRDEL		-4
#define WRDDEL		-5

#define BLOCK_OK	0
#define BLOCK_ERROR	1
#define BLOCK_END	2

#ifdef __linux__
#define USE_AIO		1
#define USE_LINUX_KAIO	0
#else
#define USE_AIO		0
#endif

typedef struct DirectFileAccess {
#if USE_AIO
    struct aiocb *dfa_AIOcb;
    int		lock;
#else
    int		dfa_Fd;
#endif
    int		dfa_Size;
    char	dfa_Buffer[4096];
    char	dfa_Field[MAX_HDR_CC];
    char	dfa_InHdr;
    char	dfa_LF;
    char	dfa_Flag;
    struct DirectFileAccess *dfa_Next;
} DirectFileAccess;

/*
 * Connection - structure used to manage an NNTP connection
 *
 * note(1): Server requests are attached in two places:  The co_SReq in a 
 *	    THREAD_NNTP connection and the co_SReq in a THREAD_SPOOL or
 *	    THREAD_POST connection.
 */

#define CACHE_OFF		0x0000
#define CACHE_ON		0x0001
#define CACHE_LAZY		0x0002
#define CACHE_SCOREBOARD	0x0003

typedef struct Connection {
    ForkDesc	*co_Desc;
    void	(*co_Func)(struct Connection *conn);
    int		(*co_ArtFuncHead)(struct Connection *conn, char *buf, int len);
    int		(*co_ArtFuncBody)(struct Connection *conn, char *buf, int len);
    const char	*co_State;
    MemPool	*co_MemPool;
    MemPool	*co_BufPool;
    MBufHead	co_TMBuf;
    MBufHead	co_RMBuf;
    time_t	co_SessionStartTime;
    time_t	co_LastActiveTime;
    int		co_FCounter;
    double	co_ByteCounter;
    int		co_BytesHeader;
    int		co_Flags;
    TimeRestrict co_TimeRestrict;
    DnsRes	co_Auth;
    char	*co_GroupName;	/* current group or NULL	*/
    char	*co_IHaveMsgId;
    Control	*co_Ctl;	/* control lookup cache		*/
    struct ServReq *co_SReq;	/* see note(1)			*/
    int		co_ListRec;
    int		co_ListRecLen;
    char	*co_ListPat;
    char	*co_ListHdrs;
    int		co_ListBegNo;
    int		co_ListEndNo;
    int		co_ListCacheMode;
    struct activeCacheEnt *co_ListCachePtr;
    struct GroupList *co_ListCacheGroups;
    int		co_ArtMode;	/* current article mode		*/
    int		co_ArtNo;	/* current article number	*/
    int		co_ArtBeg;
    int		co_ArtEnd;
    int		co_RequestFlags;	/* 0x01 = art by message-id */
					/* 0x02 = art by art number */
    struct DirectFileAccess *co_DirectFA;	/* Direct file access */

    HashFeed	co_RequestHash;
    struct timeval co_RateTv;
    int		co_RateCounter;

    time_t		co_LastServerLog;
    unsigned long	co_ServerByteCount;
    unsigned long	co_ServerArticleCount;
    unsigned long	co_ServerArticleRequestedCount;
    unsigned long	co_ServerArticleNotFoundErrorCount;
    unsigned long	co_ServerArticleMiscErrorCount;
    double		co_ClientTotalByteCount;
    unsigned long	co_ClientTotalArticleCount;
    double		co_ClientGroupByteCount;
    unsigned long	co_ClientGroupArticleCount;
    unsigned long	co_ClientPostCount;
    unsigned long	co_ClientGroupCount;
    int 		co_ByteCountType; /* Temp for by-type byte count */

    MBufHead	co_ArtBuf;	/* article buffer		*/
} Connection;

#define COF_SERVER	0x00000001
#define COF_HEADFEED	0x00000002
#define COF_STREAM	0x00000004
#define COF_IHAVE	0x00000008	/* temporary ihave->takethis */
#define COF_POST	0x00000010	/* post command, else feed   */
#define COF_INHEADER	0x00000020	/* post/feed, reading headers*/
#define COF_DORANGE	0x00000040	/* do article range, else msgid */
#define COF_WASCONTROL	0x00000080
#define COF_MODEREADER  0x00000100	/* spool fetch, do mode reader	*/
#define COF_CLOSESERVER 0x00010000	/* close server ASAP	     	*/
#define COF_PATISWILD	0x00020000	/* list pattern is wildcard	*/
#define COF_MAYCLOSESRV 0x00040000	/* maybe close server 		*/
#define COF_INPROGRESS	0x00080000	/* operation in progress	*/
#define COF_ININIT	0x00100000	/* see server.c			*/
#define COF_MAYNOTCLOSE 0x00200000	/* may not close the connection	*/
#define	COF_READONLY	0x00400000	/* send ``mode readonly''	*/
#define	COF_LOGIN	0x00800000	/* send ``authinfo'' to log in	*/
#define	COF_POSTTOOBIG	0x01000000	/* posted article is too big	*/

#define MBUF_SIZE	1024
#define MBUF_HIWAT	(MBUF_SIZE*2-256)

#define COM_ARTICLE	0
#define COM_BODY	1
#define COM_HEAD	2
#define COM_STAT	3
#define COM_BODYNOSTAT	4
#define COM_FUNC	5

#define COM_ACTIVE	6		/* list active			*/
#define COM_GROUPDESC	7		/* list newsgroups grouppat	*/

#define COM_XHDR	8
#define COM_XOVER	9
#define COM_XPAT	10

#define COM_NEWGROUPS	11		/* newgroups			*/
#define COM_ARTICLEWVF	12		/* verify body before output	*/
#define COM_BODYWVF	13		/* verify body before output	*/
#define COM_NEWNEWS	14

#define	ARTFETCH_MSGID	0x01		/* Request was by Message-ID */
#define	ARTFETCH_ARTNO	0x02		/* Request was by article number */

typedef struct ServReq {
    struct ServReq *sr_Next;	/* linked list of requests	*/
    Connection *sr_CConn;	/* client making request	*/
    Connection *sr_SConn;	/* server handling request	*/
    char	*sr_Group;	/* request related to group	*/
    int		sr_GrpIter;	/* Group iteration, for cachehits hash */
    int		sr_endNo;	/* last group article, for cachehits */
    char	*sr_MsgId;	/* request related to messageid	*/
    time_t	sr_Time;	/* time of request for timeout calc	*/
    FILE	*sr_Cache;	/* cache write (locked for duration)	*/
    int		sr_TimeRcvd;	/* article received time (NNRetrieveHead) */
    int		sr_Rolodex;	/* see server.c		*/
    int		sr_NoPass;	/* see server.c		*/
} ServReq;

#define SREQ_RETRIEVE	1
#define SREQ_POST	2


/*
 * Overview record.	over.groupname	(overview information - headers)
 *			numa.groupname	(article number assignment file)
 */

typedef union OverHead {
    struct {
	int	reserved[32];
    } u;
    struct {
	int	version;
	int	byteOrder;
	int	headSize;
	int	maxArts;
	char	gName[256];
    } v;
} OverHead;

#define oh_Version	v.version
#define oh_HeadSize	v.headSize
#define oh_MaxArts	v.maxArts	/* adjusted by dexpireover -s */
#define oh_ByteOrder	v.byteOrder
#define oh_Gname	v.gName

#define OH_VERSION	2
#define OH_BYTEORDER	((int)0xF1E2D3C4)

typedef struct OverArt {
    int         oa_ArtNo;       /* article number                       */
    int         oa_SeekPos;     /* seek in data.grouphash file          */
    int		oa_Bytes;	/* bytes of headers in data.grphash file*/
    hash_t	oa_MsgHash;	/* locate message-id (used by cancel)	*/
    int		oa_ArtSize;	/* used for xover Bytes: header		*/
    int		oa_TimeRcvd;	/* time received			*/
    int		oa_Unused2;
} OverArt;

typedef struct OverData {
    struct OverData *od_Next;
    int		od_HFd;
    int		od_ArtBase;
    int		od_HMapPos;
    int		od_HMapBytes;
    const char *od_HMapBase;
} OverData;

typedef struct OverInfo {
    struct OverInfo *ov_Next;
    int		ov_Refs;
    char        *ov_Group;
    int         ov_MaxArts;     /* maximum number of articles in group  */
    OverData	*ov_HData;	/* hdata file reference linked list	*/
    OverData	*ov_HCache;	/* last accessed file reference		*/
    int         ov_OFd;
    OverHead	*ov_Head;
    int		ov_Size;
    int		ov_Iter;
    int		ov_endNo;
} OverInfo;

typedef struct ArtNumAss {
    struct ArtNumAss *an_Next;
    const char	     *an_GroupName;	/* NOT TERMINATED	*/
    int	 	     an_GroupLen;
    int		     an_ArtNo;
} ArtNumAss;

/*
 * Active file cache for LIST-type commands
 */

typedef struct activeCacheEnt {
    struct GroupList	*nglist;
    int			cts;
    struct activeCacheEnt *next, *prev;
    struct activeCacheEnt *left, *right;
    struct activeCacheEnt *parent;
} activeCacheEnt;

#define	ACMODE_NONE	0
#define	ACMODE_READ	1
#define	ACMODE_WRITE	2

/*
 * This structure is to share info between the master process and
 * all the child processes. The info is mainly stats gathering.
 */
struct SharedInfo {
    struct in_addr dr_Addr;		/* remote IP address	*/
    int		dr_Port;		/* remote port 		*/
    int		si_RateLimit;
    double	si_ServerByteCount;
    double	si_ServerArticleCount;
    double	si_ClientTotalByteCount;
    double	si_ClientTotalArticleCount;
    double	si_ClientGroupByteCount;
    double	si_ClientGroupArticleCount;
    double	si_ClientPostCount;
    double	si_ClientPostBytes;
    double	si_ClientPostFail;
    double	si_ClientGroupCount;
};

#include <obj/dreaderd-protos.h>



syntax highlighted by Code2HTML, v. 0.9.1