/* timer.c -- timer support routines */

/*
 *  srouted -- silent routing daemon
 *  Copyright (C) 1995 Kevin Buhr
 *
 *  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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef lint
static char rcsid[] = "$Id: timer.c,v 1.3 1995/02/17 17:42:46 buhr Exp $";
#endif /* not lint */

#include "table.h"
#include "error.h"
#include "timer.h"


/*
 *	Set timeout timer
 */

void tm_settimeout( int route )
{
   note1( ERCTM_SETTO, route );
   tb_route[route].tbrt_timer = time(NULL) + TM_TIMEOUT;
   tb_route[route].tbrt_flags &= ~TBRTF_TIMERON;
   tb_route[route].tbrt_flags |= TBRTF_TIMEOUT;
}


/*
 *	Set garbage collection timer
 */

void tm_setgarbcoll( int route )
{
   note1( ERCTM_SETGC, route );
   tb_route[route].tbrt_timer = time(NULL) + TM_GARBCOLL;
   tb_route[route].tbrt_flags &= ~TBRTF_TIMERON;
   tb_route[route].tbrt_flags |= TBRTF_GARBCOLL;
}


/*
 *	Kill the timer
 */

void tm_killtimer( int route )
{
   note1( ERCTM_KILL, route );
   tb_route[route].tbrt_timer = 0;
   tb_route[route].tbrt_flags &= ~TBRTF_TIMERON;
}


/*
 *	Act on all expired timers, return time of next expiry
 */

time_t tm_expire( time_t now )
{
   int rti, nextroute;
   struct tb_route *route;
   time_t next;

   next=0;
   for( rti=0; rti<TB_ROUTE_SIZE; rti++ ) {
      route = &tb_route[rti];
      if( (route->tbrt_flags & TBRTF_USED) == 0
	 || route->tbrt_flags & TBRTF_KILLED
	 || (route->tbrt_flags & TBRTF_TIMERON)==0 )
	 continue;
      if( route->tbrt_timer < now+TM_NOW_FUZZ ) {
	 switch( route->tbrt_flags & TBRTF_TIMERON ) {
	 case TBRTF_TIMEOUT:
	    note1( ERCTM_TIMEOUT, rti );
	    tb_delroute( rti, NULL );
	    break;
	 case TBRTF_GARBCOLL:
	    note1( ERCTM_GARBCOLL, rti );
	    tb_killroute( rti );
	    break;
	 }
      } else {
	 if( next==0 || route->tbrt_timer < next ) {
	    next = route->tbrt_timer;
	    nextroute = rti;
	 }
      }
   }

   if( next ) {
      if(tb_route[nextroute].tbrt_flags & TBRTF_TIMEOUT)
	 note1( ERCTM_NETO, nextroute );
      else
	 note1( ERCTM_NETO, nextroute );
   } else
      note0( ERCTM_NENONE );
   return(next);
}
