#!/usr/local/bin/perl
###############################################################################
# Required Modules
#
use CGI;
use Time::Local;
require "pingserverdefs.pl";
require "pingutils.pl";
use Fcntl ':flock'; # import LOCK_* constants
# Implement Notifier Experiment
# serve 50% of people using pingerdata and 50% of people using pingerdata2
if (rand(100)<50)
{
$pingerdatafile= "pingerdata.pm";
}
else
{
$pingerdatafile= "pingerdata2.pm";
}
require $pingerdatafile;
###############################################################################
# Load Internal Variables
#
$ksecond = 1;
$kminute = 60;
$khour = $kminute * 60;
$kday = $khour * 24;
$kweek = $kday * 7;
$kinterval = $kweek * 4;
###############################################################################
# Load External Variables
#
$q = new CGI;
$guideid = $q->param('guideid');
$nextping = $q->param('nextping');
$nextreminder = $q->param('nextreminder');
$actualping = $q->param('actualping');
$long = $q->param('long');
$uid = $q->param('uid');
$machineversion = $q->param('machineversion');
# if the user doesn't have a uid, create one
if (!$uid)
{
$newuid = sprintf("%d.%d", time(), rand(999999999));
}
###############################################################################
# Log all parameters into our log file.
#
my($logfilename) = &GetLogFileName();
if (open(LOGFILE,">>$logfilename"))
{
# make sure nobody writes to the file while we have it open
if (flock(LOGFILE,LOCK_EX))
{
seek(LOGFILE, 0, 2); # seek to the end of the file, in case someone appended while we were waiting
my($remoteaddr) = $ENV{'REMOTE_ADDR'};
my($timestamp) = &GetLogTimeStamp();
print LOGFILE "$timestamp;ipaddr=$remoteaddr;";
print LOGFILE "uid=$newuid;" if defined($newuid);
print LOGFILE $q->query_string;
print LOGFILE "\n";
# done
flock(LOGFILE,LOCK_UN);
}
close(LOGFILE);
}
###############################################################################
# Compute Response
#
my($currentdayofperiod) = &DayOfCollectionPeriod();
my($datacollectionperiod) = 7;
srand;
$lbias = &ParseDateBias($actualping);
$newNextPingT = CreateNewNextTime($nextping, $lbias, \@pingbuckets);
$newNextReminderT = CreateNewNextTime($nextreminder, $lbias, \@reminderbuckets);
if ($newNextPingT < $newNextReminderT)
{
# don't ping again until after chosen reminder
$newNextPingT += $kinterval;
}
$newNextPingString = MakeDateString($newNextPingT, $lbias);
$newNextReminderString = MakeDateString($newNextReminderT, $lbias);
print "Content-type:text/plain\n\n";
print "$newNextPingString\n";
print "$newNextReminderString\n";
print "$latestguideid\n";
print "$machineguideurl\n";
print "$siteguideurl\n";
print "$machineguideheight\n";
print "$machineguidewidth\n";
print "$adurl\n";
print "$timeoutminutes\n";
print "$pingurl\n";
# new fields for post-2.0 clients
if (defined($machineversion))
{
print "$datacollectionswitch\n";
print "$datacollectionperiod\n";
print "$currentdayofperiod\n";
# give the client a UID if he didn't already have one
print "$newuid\n" if defined($newuid);
}
if ($long eq "1")
{
print "$japan_latestguideid\n";
print "$japan_machineguideurl\n";
print "$japan_siteguideurl\n";
print "$japan_machineguideheight\n";
print "$japan_machineguidewidth\n";
print "$japan_adurl\n";
}
###############################################################################
# SUBROUTINES
sub CreateNewNextTime
{
# prepare arguments
my($nexttime);
my($bias);
my($buckets);
$nexttime= $_[0];
$bias= $_[1];
$buckets= $_[2];
if (length($nexttime) != 24)
{
# invalid or initial time, create a date from scratch
$newNextTimeT = PickRandomBucketTime($buckets, $bias);
}
else
{
# we had a valid nextreminder time, simply advance it by 1 interval
$newNextTimeT = &ParseDate($nexttime);
$newNextTimeT = $newNextTimeT + $kinterval;
# inforce that the time is in an allowable bucket - in case
# time was chosen with a different bucket configuration
$newNextTimeT = InforceBuckets($buckets, $newNextTimeT, $bias);
}
# inforce that the next time is in the future, based on the client's
# definition of actualPingTime + 30 minutes
# if client failed to specify actual ping time, use local now
if (length($actualpingtime) == 24)
{
$futureT= ParseDate($actualpingtime) + 30*$kminute;
}
else
{
$futureT= time() + 30*$kminute;
}
while ($newNextTimeT < $futureT)
{
$newNextTimeT += $kinterval;
}
return $newNextTimeT;
}
sub ParseBucket
{
# prepare arguments
my($bucket);
$bucket= $_[0];
@result = (0,0,0);
$bucket =~ ",";
$result[0]= int($`);
$bucket = $';
$bucket =~ ",";
$result[1]= int($`);
$result[2]= int($');
return @result;
}
sub PickRandomBucketTime
{
# prepare arguments
my($buckets);
my($bias);
$buckets = $_[0];
$bias = $_[1];
# choose a bucket at random
$count= @$buckets;
$bucketNumber= int(rand($count));
@bucket = ParseBucket(@$buckets[$bucketNumber]);
# return a corresponding time
@timea = localtime(time());
$timea[0] = int(rand(60)); # second
$timea[1] = int(rand(60)); # minute
$timea[2] = $bucket[1] + int(rand($bucket[2] - $bucket[1])); # hour
# do day of week as a post transform adjustment
$daysToAdvance = $bucket[0] - $timea[6];
if ($daysToAdvance < 0)
{
$daysToAdvance += 7;
}
$result= timelocal(@timea) + $daysToAdvance * $kday;
$result+= GetLocalBias() - $bias;
return $result;
}
sub InforceBuckets
{
# prepare arguments
my($buckets);
my($x);
my($bias);
$buckets= $_[0];
$x= $_[1];
$bias= $_[2];
# make sure time is in a bucket
$count= @$buckets;
$adjust= $bias - GetLocalBias();
@timea= localtime($x + $adjust);
$bInBucket= 0;
for ($i=0; $i<$count; $i++)
{
@bucket = ParseBucket(@$buckets[$i]);
if ($timea[6] == $bucket[0]) # wday matches
{
# is hour in bounds?
if ($timea[2] >= @bucket[1] && $timea[2] < @bucket[2])
{
# time is in a valid bucket
$bInBucket= 1;
break;
}
}
}
if ($bInBucket == 0)
{
# not in a bucket, so pick a random time that is
$x= PickRandomBucketTime($buckets, $bias);
}
return $x;
}
sub lock {
}
sub unlock
{
}