/*
 * incoming.c Copyright 1999 Christopher M Sedore. All Rights Reserved.
 * Please see the "COPYING" file for license details.
 * 
 * Implements incoming access controls.
 */

#include "main.h"

TAILQ_HEAD(inc_head,incoming_entry) incHead;

struct incoming_entry *
IncomingFind(char *name)
{
	struct incoming_entry *ie;

	for (ie=TAILQ_FIRST(&incHead);ie;ie=TAILQ_NEXT(ie,list)) {
		if (!strcmp(name,ie->name)) {
			return ie;
		}
	}
	
	return NULL;
}

void
IncomingMarkAll()
{
	struct incoming_entry *ie;

	for (ie=TAILQ_FIRST(&incHead);ie;ie=TAILQ_NEXT(ie,list)) {
		ie->mark=1;
	}
	
	return;
}

void
IncomingDeleteMarked()
{
	struct incoming_entry *ie,*n;

	for (ie=TAILQ_FIRST(&incHead);ie;ie=n) {
		n=TAILQ_NEXT(ie,list);

		if (ie->mark) {
			printf("deletion of incoming not supported (%s)\n",ie->name);
		}
	}
	
	return;
}

int
IncomingSet(char *site,char *name,char *value) 
{
	struct incoming_entry *ie;

	ie=IncomingFind(site);

	if (!ie) 
		return 0;	

	if (!strcmp(name,"rights")) {
		ie->rights=atoi(value);
		return 1;
	}

	if (!strcasecmp(name,"dist")) {
		if (ie->diststr) {
			free(ie->diststr);
		}
		
		if (strcmp(value,"*")) {
			ie->dist=NULL;  // XXX no cleanup
			return 1;
		}

		ie->diststr=strdup(value);
		ie->dist=CompileMatchString(value);
		return 1;
	}
		
	return 0;
}

int
IncomingAdd(char *name)
{
	struct incoming_entry *ie;

	ie=IncomingFind(name);

	if (ie) {
		ie->mark=0; 
		return 0;
	}	

	ie=malloc(sizeof(struct incoming_entry));

	bzero(ie,sizeof(struct incoming_entry));


	ie->maxConnections=7;
	strcpy(ie->name,name);

	TAILQ_INSERT_TAIL(&incHead,ie,list);
	TAILQ_INIT(&ie->activeConns);

	DnsAddName(name);
	
	return 1;
}

struct incoming_entry *
IncomingCheck(int addr)
{
	char *s;

	s=(char *)DnsGetName(addr);
	
	if (!s)
		return NULL;

	return IncomingFind(s);
}	

void
NntpFeedIn(struct context *cc)
{
	char *s,*c,*v;

	cc->bp+=7;

	s=strtok(cc->bp," \t");

	if (!strcmp(s,"create")) {
		c=strtok(NULL," \t");
		if (IncomingAdd(c)) {
			sprintf(&cc->obuf[cc->obuflen],"200 %s created\r\n",c);
                	cc->obuflen+=strlen(&cc->obuf[cc->obuflen]);
		} else {
			sprintf(&cc->obuf[cc->obuflen],"500 %s NOT created\r\n",c);
                	cc->obuflen+=strlen(&cc->obuf[cc->obuflen]);
		}
		return;
	}
	if (!strcmp(s,"set")) {
		s=strtok(NULL," \t");
		c=strtok(NULL," \t");
		v=strtok(NULL," \t");
		if (IncomingSet(s,c,v)) {
	 		sprintf(&cc->obuf[cc->obuflen],"200 %s set to %s for %s\r\n",c,v,s);
        	        cc->obuflen+=strlen(&cc->obuf[cc->obuflen]);
		} else {
	 		sprintf(&cc->obuf[cc->obuflen],"500 failed (%s set to %s for %s)\r\n",c,v,s);
        	        cc->obuflen+=strlen(&cc->obuf[cc->obuflen]);
		}
		return;
	}

	sprintf(&cc->obuf[cc->obuflen],"500 failed (%s unknown)\r\n",s);
        cc->obuflen+=strlen(&cc->obuf[cc->obuflen]);
 
}

void
PrintIStats()
{
        struct incoming_entry *i;
        struct context *c;

        for (i=TAILQ_FIRST(&incHead);i;i=TAILQ_NEXT(i,list)) {
                printf("%s - accept %i refuse %i reject %i error %i conn %i\n",
			i->name,i->accept,i->refuse,i->reject,i->error,i->connected);
                for (c=TAILQ_FIRST(&i->activeConns);c;c=TAILQ_NEXT(c,clist)) {
                        printf("\tconn state=%s (%s)\n"
                                ,c->state,c->cb.state);
                }
        }
}


void
IncomingInit()
{
	TAILQ_INIT(&incHead);
	IncomingAdd("localhost");
	IncomingAdd("static.maxwell.syr.edu");
	ScheduleCallback(30,9999999,PrintIStats,0);
}


