#!/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 { }