/*
    This file is part of pload - a program to monitor ppp activity for X
    Copyright (C) 1999-2000  Matt Smith <mdsmith@engr.utk.edu>

    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.

*/


/* get_stat.c */
#include <stdio.h>		/* perror */
#include <stdlib.h>		/* exit, atoi */
#include <unistd.h>		/* gettimeofday */
#include <sys/time.h>		/* gettimeofday */
#include <string.h>		/* memset */
#include <errno.h>		/* perror */
#include "pload.h"

/* global variables */
extern int errno;

void ifd_initialize(	if_data *ifd,
			char *device,
			int histsize,
			int useProc)
{
	memset(ifd, 0, sizeof(if_data));
	ifd->device = device;
	ifd->history_size = histsize;
#ifdef STREAMS	
	/* note: It is assumed that the device number
	   is just the 4th character.  This currently
	   isn't a problem because dev_n is only used
	   in the stream based interface. I only know
	   how to get ppp statistics from streams. */
	ifd->dev_n = atoi(device+3);	/* the X of pppX */
#endif		
#ifdef LINUXPROC
	if (useProc)
		ifd->getstats = proc_stat;	/* use /proc/net/dev */
	else
		ifd->getstats = ioctl_stat;	/* use ioctl() */
#else
	ifd->getstats = ioctl_stat;	/* non-linuxproc gets ioctl always */
#endif
	/* allocate the arrays to average points over */
	if (histsize < 1) die("number of average points can't be < 1");
	ifd->in_history =  (double *)calloc(ifd->history_size, sizeof(double));
	ifd->out_history = (double *)calloc(ifd->history_size, sizeof(double));
	
	if ((ifd->in_history == NULL) || (ifd->out_history == NULL))
		die("calloc failed");
	
}

void ifd_stop(if_data *ifd)
{
	free(ifd->in_history);
	free(ifd->out_history);
	memset(ifd, 0, sizeof(if_data));
}


void get_stat(if_data *ifd)
{
	double delta_t;
	double rate;
	double sum;
	int i;
	
	/* get in_bytes and out_bytes */
	ifd->getstats(ifd);
	
	if (gettimeofday(&ifd->curr_time, NULL) != 0)
		die("gettimeofday");
	
	/* double seconds */	
	delta_t = (double)
		((ifd->curr_time.tv_sec - ifd->prev_time.tv_sec) * 1000000L
		+(ifd->curr_time.tv_usec - ifd->prev_time.tv_usec)) / 1000000.0;
	
	/******** in rate ******************/
	if ((ifd->in_bytes_old == 0UL) || (ifd->in_bytes_old > ifd->in_bytes))
		/* first time around or hangups */
		rate = 0.0;
	else
		rate =(double)(ifd->in_bytes - ifd->in_bytes_old) / delta_t;
	
	sum = 0.0;
	for (i=0;i<=ifd->history_size-2;i++)	/* doesn't happen if size==1 */
	{
		ifd->in_history[i] =
			ifd->in_history[i+1];	/* shift all past values down */
		sum +=ifd->in_history[i];	/* keep a running total */
	}
	
	ifd->in_history[ifd->history_size-1] = rate;	/* put current at end */
	
	/* averaged rate */
	ifd->in_rate = (sum + ifd->in_history[ifd->history_size-1])
		 / (double)ifd->history_size;
	/***********************************/
	
	/******** out rate ******************/
	if ((ifd->out_bytes_old == 0UL) || (ifd->out_bytes_old > ifd->out_bytes))
		/* first time around or hangups */
		rate = 0.0;
	else
		rate =(double)(ifd->out_bytes - ifd->out_bytes_old) / delta_t;
	
	sum = 0.0;
	for (i=0;i<=ifd->history_size-2;i++)	/* doesn't happen if size==1 */
	{
		ifd->out_history[i] = 
			ifd->out_history[i+1];	/* shift all past values down */
		sum +=ifd->out_history[i];	/* keep a running total */
	}
	
	ifd->out_history[ifd->history_size-1] = rate;	/* put current at end */
	
	/* averaged rate */
	ifd->out_rate = (sum + ifd->out_history[ifd->history_size-1])
		 / (double)ifd->history_size;
	/***********************************/
	
	/* find maximum rates */
	if (ifd->in_rate > ifd->in_max) ifd->in_max = ifd->in_rate;
	if (ifd->out_rate > ifd->out_max) ifd->out_max = ifd->out_rate;
	
	/* old = new */
	memcpy(&ifd->prev_time, &ifd->curr_time, sizeof(struct timeval));
	ifd->in_bytes_old = ifd->in_bytes;
	ifd->out_bytes_old = ifd->out_bytes; 
	
	return;
}


void die(char *m)
{
	perror(m);
	exit(EXIT_FAILURE);
}



syntax highlighted by Code2HTML, v. 0.9.1