#
# Copyright (c) Xerox Corporation 1997, 1998. All rights reserved.
#
# License is granted to copy, to use, and to make and to use derivative
# works, provided that Xerox is acknowledged in all documentation
# pertaining to any such copy or derivative work. Xerox grants no other
# licenses expressed or implied. The Xerox trade name should not be used
# in any advertising without its written permission.
#
# XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE
# MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE
# FOR ANY PARTICULAR PURPOSE.  The software is provided "as is" without
# express or implied warranty of any kind.
#
# These notices must be retained in any copies of any part of this software.
#
#-------- generate html output ---------
#----- exported variables:
#-----    $webdir = the directory to write html output files
#-----       used by preamble
#-----    $web_copy = the file used to copy html output to the server
#-----       used by main
#-----    $statsfile = the route statistics file
#-----       used by archive and stats
#-----    $updatefile = the route statistics update file
#-----       used by stats
#-----    $search_cgi = the URL for CGI search search script
#-----       used by preamble
#-----    $rptint = the actual report interval
#-----       used by update
#-----    $noreach = the number of unreachable sources this hour
#-----       used by hour
#-----    $routes = the number of total sources this hour
#-----       used by hour
#-----    $max = the max number of flaps for a source this hour
#-----       used by hour
#-----    $maxsrc = the source with the max flaps this hour
#-----       used by hour
#-----    $stable = the number of stable sources this hour
#-----       used by hour
#-----    $wentdown = the number of sources that went down this hour
#-----       used by hour
#-----    $cameup = the number of sources that came up this hour
#-----       used by hour
#-----    $newup = the number of new sources this hour
#-----       used by util and hour
#-----    %asdata = the array of as data, indexed by as number
#-----       used by as
#-----    $dtime = the date of the last route table output
#-----       used by stats, month, week, hour, archive, and util
#----- internal variables:
#-----    $opt_w = the command line option for $webdir
#-----    $backhtml = the html file background image
#-----    $linehtml = the image for a horizontal line in html files
#-----    $sumhtml = the hourly summary output file
#-----    $weekhtml = the weekly worst routes output file
#-----    $monthhtml = the monthly worst routes output file
#-----    $lweekhtml = the weekly worst routes from last week
#-----    $printweek = the number routes to print in the weekly worst file
#-----    $printmonth = the number of routes to print in the monthly worst
#-----    $opt_s = the command line option for $search_cgi
#-----    $opt_R = the command line option for $web_copy
#-----    @weekworst = the array of this weeks worst AS numbers
#-----    @monthworst = the array of this months worst AS numbers
#
#----- fatal errors:
#-----   none
#----- warnings:
#-----   sumhtml = unable to write summary html file, write aborted
#-----   weekhtml = unable to write weekly worst html file, write aborted
#-----   monthhtml = unable to write monthly worst file, write aborted  
#-----   weekopen = unable to open weekly file for copy to last week, aborted
#-----   lweekhtml = unable to write last week's worst file, write aborted

sub init_html {
    # determine the web output directory
    if (defined($opt_w)) {
	$webdir = $opt_w;
    }
    $statsfile = "$webdir/route_stats";
    $updatefile = "$webdir/route_stats.update";
    $backhtml = "./stone.gif";
    $linehtml = "./hline.gif";
    $sumhtml = "$webdir/summary.html";
    $weekhtml = "$webdir/week.html";
    $monthhtml = "$webdir/month.html";
    $lweekhtml = "$webdir/last.html";
    $printmonth = 50;
    $printweek = 50;
    # determine the href to the cgi search script, used in creating $weekhtml
    # and $monthhtml
    if (defined $opt_s) {
	$search_cgi = $opt_s;
    }
    # determine if a script is need to copy the files to the web server
    if (defined($opt_R)) {
	$web_copy = $opt_R;
    } else {
	$web_copy = "no";
    }
}

sub compute_worst {
    my($wrank,$mrank);
    for($i =0; $i < $printweek; $i++) {
	$weekworst[$i] = -2;
	$wrank[$i] = 0;
    }
    for($i =0; $i < $printmonth; $i++) {
	$monthworst[$i] = -2;
	$mrank[$i] = 0;
    }
    my($newas,$newrank,$prev,$i);
    # AS number, num sources, num down, num flapping, worst source, worst flaps
    my($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax);
    foreach $newas (keys %asdata) {
	($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax) = 
	    split(" ",$asdata{$newas});
	if ($wmax >= $wrank[$printweek]) {
	# if the newas flaps enough to bump someone off the current list
	    # newrank is the spot on the list where new AS belongs
	    $newrank = $printweek -1;
	    while(($newrank >=0) && ($wmax >= $wrank[$newrank])) {
		$newrank = $newrank  -1;
	    }
	    $newrank++;
	    # move people below newrank down in the list
	    for($i=$printweek; $i > $newrank; $i--) {
		$prev = $i -1;
		$weekworst[$i] = $weekworst[$prev];
		$wrank[$i] = $wrank[$prev];
	    }
	    # put the new as in at newrank
	    $weekworst[$newrank] = $newas;
	    $wrank[$newrank] = $wmax;
	}
	if ($mmax >= $mrank[$printmonth]) {
	# if the newas flaps enough to bump someone off the current list
	    # newrank is the spot on the list where new AS belongs
	    $newrank = $printmonth -1;
	    while(($newrank >=0) && ($mmax >= $mrank[$newrank])) {
		$newrank = $newrank  -1;
	    }
	    $newrank++;
	    # move people below newrank down in the list
	    for($i=$printmonth; $i > $newrank; $i--) {
		$prev = $i -1;
		$monthworst[$i] = $monthworst[$prev];
		$mrank[$i] = $mrank[$prev];
	    }
	    # put the new as in at newrank
	    $monthworst[$newrank] = $newas;
	    $mrank[$newrank] = $mmax;
	}
    }
}
	
sub write_hourly_html {
    my($prct);
    my($sc,$mn,$hr,$dy,$mo,$yr,$wd,$yd,$isd) = gmtime($dtime);
    $mo = $mo + 1;
    if ($hr < 10) { $hr = "0$hr"; }
    if ($mn < 10) { $mn = "0$mn"; }
    if ($sc < 10) { $sc = "0$sc"; }
    # okay, let's get ready for year 2000...
    if ($yr < 100) { 
	$yr = "19$yr"; 
    } else {
    # this assumes gmtime really returns 108 for 2008 like it
    # should, but if different times implement different gmtime 
    # the we have trouble 
	$yr = $yr -100;
	$yr = "20$yr";
    }
    my($day) = "$mo/$dy/$yr";
    my($hour) = "$hr:$mn:$sc GMT";
    open(SUMHTML, ">$sumhtml") || &log_error(sumhtml,$sumhtml);
    print SUMHTML "<html> <head> <title>Route Report Summary</title> \n";
    print SUMHTML '<meta http-equiv="Refresh" content="3600"> </head>';
    print SUMHTML '<body background="';
    print SUMHTML "$backhtml";
    print SUMHTML '" text="#000000">';
    print SUMHTML "<center><h1>Multicast Routing Summary Report</h1></center>\n";
    print SUMHTML "<font size=4> \n";
    print SUMHTML "<ul> \n";
    if ($routes == 0) {
	$prct = 0;
    } else {
	$prct = int($stable/$routes * 100);
    }
    print SUMHTML "<li>Report for a $rptint minute period, dated $hour $day\n";
    print SUMHTML "<li> $stable routes did not change during report time\n";
    print SUMHTML "<font size=4 color=red>($prct%)</font> \n";
    print SUMHTML "<li> Max number of flaps was \n";
    print SUMHTML "<font size=4 color=red> $max </font> for route $maxsrc\n";
    print SUMHTML "<li> $routes Routes Advertised in Total \n";
    print SUMHTML "<li> $noreach routes listed unreachable at end of report period \n";
    print SUMHTML "<li> $cameup routes changed state to up this period \n";
    print SUMHTML "<li> $newup of routes which came up are new sources\n";
    print SUMHTML "<li> $wentdown routes changed state to down this period\n";
    print SUMHTML "</ul> </body> </html> \n";
    close(SUMHTML);
}

sub write_weekly_html {
    open(HTML, ">$weekhtml") || &log_error(weekhtml,$weekhtml);
    &start_worst(week);
    # AS number, num sources, num down, num flapping, worst source, worst flaps
    my($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax);
    my($i);
    for($i = 0; $i < $printweek; $i++) {
	($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax) =
	    split(" ",$asdata{$weekworst[$i]});
	$wmax = int($wmax);
	print HTML "      <tr>\n";
	print HTML "         <td align=left> $wsrc </td>\n";
	print HTML "         <td align=right>$wmax</td>\n";
	print HTML "         <td align=right>\n";
	print HTML '<a href="';
	print HTML "$search_cgi";
	print HTML "?use=state&use=change&use=asnum&use=wflaps&use=whour";
	print HTML "&care=state&use=wstates&asnum=$num&sortnum=wflaps";
	print HTML '">';
	print HTML "$num </a> </td>\n";
	print HTML "         <td align=right>$size</td>\n";
	print HTML "         <td align=right>$wflap</td>\n";
	print HTML "         <td align=right>$down</td>\n";
	print HTML "      </tr>\n";
    }
    # complete and close the html file
    &finish_worst;
    close(HTML);
}

sub write_monthly_html {
    open(HTML, ">$monthhtml") || &log_error(monthhtml,$monthhtml);
    &start_worst(month);
    # AS number, num sources, num down, num flapping, worst source, worst flaps
    my($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax);
    my($i);
    for($i=0; $i < $printmonth; $i++) {
	($num,$size,$down,$wflap,$wsrc,$wmax,$mflap,$msrc,$mmax) =
	    split(" ",$asdata{$monthworst[$i]});
	$mmax = int($mmax);
	print HTML "      <tr>\n";
	print HTML "         <td align=left> $msrc </td>\n";
	print HTML "         <td align=right>$mmax</td>\n";
	print HTML "         <td align=right>\n";
	print HTML '<a href="';
	print HTML "$search_cgi";
	print HTML "?use=state&use=change&use=asnum&use=mflaps&use=mhour";
	print HTML "&care=state&use=mstates&asnum=$num&sortnum=mflaps";
	print HTML '">';
	print HTML "$num </a> </td>\n";
	print HTML "         <td align=right>$size</td>\n";
	print HTML "         <td align=right>$mflap</td>\n";
	print HTML "         <td align=right>$down</td>\n";
	print HTML "      </tr>\n";
    }
    &finish_worst;
    close(HTML);
}

sub start_worst {
    my($sc,$mn,$hr,$dy,$mo,$yr,$wd,$yd,$isd) = gmtime($dtime);
    $mo = $mo + 1;
    if ($hr < 10) { $hr = "0$hr"; }
    if ($mn < 10) { $mn = "0$mn"; }
    if ($sc < 10) { $sc = "0$sc"; }
    # okay, let's get ready for year 2000...
    if ($yr < 100) { 
        $yr = "19$yr"; 
    } else {
    # this assumes gmtime really returns 108 for 2008 like it
    # should, but if different times implement different gmtime 
    # the we have trouble
        $yr = $yr - 100;
        $yr = "20$yr";
    }
    my($day) = "$mo/$dy/$yr";
    my($hour) = "$hr:$mn:$sc GMT";
    my($Capital,$normal);
    if ($_[0] eq "week") { 
	$Capital = "Week";
	$normal = "week";
    } else {
	$Capital = "Month";
	$normal = "month";
    }
    # set to expire/refresh in one hour
    print HTML "<html>\n\n";
    print HTML "<head>\n";
    print HTML "   <title> This ${Capital}'s Worst Routes </title>\n";
    print HTML '   <meta http-equiv="Refresh" content="3600">';
    print HTML "\n";
    print HTML "</head>\n\n";
    # start html body of the page
    print HTML "<body>\n";
    print HTML "   <center> <h1> This ${Capital}'s Worst Routes </h1> </center>\n\n";
    print HTML '   <br> <img src="';
    print HTML "$linehtml";
    print HTML '" width="100%"'; 
    print HTML "\n    alt=";
    print HTML '"----------------------------------------------------------">';
    print HTML "   <br>\n\n";
    print HTML "   <p> The table lists this ${normal}'s most unstable routes.\n";
    print HTML "   Our monitoring tool tracks the distance\n";
    print HTML "   to each source in the MBone.  A change in distance\n";
    print HTML "   indicates a change in the route to the source, ie a flap\n";
    print HTML "   Using this data, we calculate the <b>average number of\n";
    print HTML "   flaps per hour</b>.  This page reports the most unstable\n";
    print HTML "   routes observed during the current $normal.  This page is\n";
    print HTML "   updated hourly.  <b>Only one route per Autonomous System\n";
    print HTML "   is listed</b>.\n\n";
    print HTML "  <p>The cause of this instability is often one of the bugs\n";
    print HTML "   listed in the \n";
    print HTML ' <a href="http://ganef.cs.ucla.edu/~masseyd/Route/bugs.html">';
    print HTML "  \n";
    print HTML "   Current Bugs</a> page.  Note Autonomous Systems listed \n";
    print HTML "   here typically advertise many unstable routes, but only \n";
    print HTML "   the worst route for the AS is reported.  For a full \n";
    print HTML "   report on the AS, click on the AS number. \n\n"; 
    print HTML '   <br> <img src="';
    print HTML "$linehtml";
    print HTML '" width="100%"'; 
    print HTML "   \n    alt=";
    print HTML '"----------------------------------------------------------">';
    print HTML "   <br>\n\n";
    print HTML "   <font size=4>";
    print HTML "   <p> Data last updated at $day $hour <br> \n";
    #start the table for the worst routes
    print HTML "   <table border=2 cellpadding=2 cellspacing=4> \n";
    print HTML "      <tr>\n";
    print HTML "         <th align=center> Source</th>\n";
    print HTML "         <th align=center> Avg. Flaps/Hour </th> \n";
    print HTML "         <th align=center>AS Number</th> \n";
    print HTML "         <th align=center> Sources in AS </th> \n";
    print HTML "         <th align=center> Sources Flapping </th> \n";
    print HTML "         <th align=center> Sources Down </th> \n";
    print HTML "      </tr> \n";
}

sub finish_worst {
    # complete the html file
    print HTML "   </table>\n";
    print HTML "   <br>\n";
    print HTML "</body>\n\n";
    print HTML "</html>\n";
}

sub write_lweek_html {
    # simply copy the current week file to the last week file
    open(WEEK, "$weekhtml") || &log_error(weekopen,$weekhtml);
    open(LAST, ">$lweekhtml") || &log_error(lweekhtml,$lweekhtml);
    my($line);
    while($line = <WEEK>) {
	# change any references from this/current to last/previous
	$line =~ s/This Week/Last Week/g;
	$line =~ s/this week/last week/g;
	$line =~ s/current week/previous week/g;
	# change any search options from this week to last week
	$line =~ s/wflaps/lflaps/g;
	$line =~ s/whour/lhour/g;
	$line =~ s/wcount/lcount/g;
	$line =~ s/wstates/lstates/g;
   	print LAST $line;
    }
    close(WEEK);
    close(LAST);
}
