3 thoughts on “Anycast”

    1. With bash, Perl, PHP and JavaScript 🙂 It is just a prototype, but works well enough for me. I put all the codebits in github, in case you are interested: .gist table { margin-bottom: 0; } "Instructions" 1) Install index.php to some webserver, and run "latlongudp.pl" on the same server. 2) Then feed IPs to the latlongudp.pl server with something like this: tail -F /var/log/nginx/access_log|perl -e '$|=1;while(<>){print "someidentifier,$1n" if/(d+.d+.d+.d+)/}'|nc -u somenode.example.com 5001 Modify someidentifier to to fit your needs. 3) Enjoy the map… view raw README hosted with ❤ by GitHub <?php $dbh = new SQLite3( '/dev/shm/hits.db' ); if ( isset( $_GET['g'] ) ) { $dbh->busyTimeout(1000); $stmt = $dbh->prepare( 'SELECT host,lat,lng FROM hit WHERE service = ? GROUP BY lat,lng ORDER BY RANDOM() LIMIT 10000;'); $stmt->bindValue(1, preg_replace( '/[^a-z]/', '', $_GET['g'] ), SQLITE3_TEXT); $stmt->execute(); $result = $stmt->execute(); $stats = array(); while( $row = $result->fetchArray( SQLITE3_ASSOC ) ) { $stats[] = $row; } header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Pragma: no-cache"); if ( isset( $_GET['callback'] ) ) { header("Content-type: text/javascript"); $callback = preg_replace( '/[^a-zA-Z0-9_]/', '', $_GET['callback'] ); echo "$callback(" . json_encode( $stats ) . ");"; } else { echo json_encode( $stats ); } } else { ?><!DOCTYPE html> <html> <head> <title>anycast map</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <meta charset="UTF-8"> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <style> #map canvas { /* padding:0;margin:0;*/ /*border:1px solid #111;*/ position:absolute; } * {margin:0;padding:0; } body, html { background:black; } /* height:100%;margin:0; padding:0px; /*padding:10px; background:black; }*/ </style> <script> // ctx.fillStyle = "rgb(200,0,0)"; // ctx.fillRect (10, 10, 55, 50); var map, heatmap; var hitdata=new Array(); var running = 0; var data = new Array(); var dcs = new Array(); var dcss = new Array(); dcss["lax"] = new Array(0,0,255); //"blue"//["rgba(0, 0, 255, 0.0)","rgba(0, 0, 255, 1.0)"]; dcss["lhr"] = new Array(255,0,0);//"red"//["rgba(255,0,0,0.0)","rgba(255,0,0,1.0)"]; dcss["iad"] = new Array(0,255,0); //"green"//["rgba(0,255,0,0.0)","rgba(0,255,0,1.0)"]; dcss["sat"] = new Array(255,127,0);//"orange"//["rgba(151,0,151,0.0)","rgba(151,0,151,1.0)"]; dcss["yyz"] = new Array(255,0,255);//"purple"//["rgba(151,0,151,0.0)","rgba(151,0,151,1.0)"]; dcss["mia"] = new Array(255,255,0); //"yellow" // dcss["dfw"] = new Array(255,255,255); // "white" // dcss["fra"] = new Array(0,255,255); // "light blue" // dcss["sin"] = new Array(46,139,87); // "dark green" // dcss["sjc"] = new Array(102,0,12); // "dark purple" // var canvas var image var w=1000; var h=500; var ww=w/360; var hh=h/180; var getint $(document).ready(function() { get_size(); highlight(); getdata(); getint=setInterval( function(){getdata();}, 1000 ); create_canvas(); setInterval( function(){addstuff();}, 100 ); setInterval( function(){fadecanvas();}, 200 ); setInterval( function(){rotate_canvas();}, 30000 ); }); function highlight() { if( matches = window.location.search.match(/dc=(w+)/) ){ for( i in dcss ) { if(i == matches[1]){ dcss[i] = new Array(255,0,0); }else{ dcss[i] = new Array(0,0,255); } } } } function get_size(){ var matches; if ( matches = window.location.search.match(/w=(d+)/) ){ w=matches[1]; ww=w/360; } if ( matches = window.location.search.match(/h=(d+)/) ){ h=matches[1]; hh=h/180; } } var fade=null function rotate_canvas() { if (document.getElementById('map').children.length > 4 && fade==null ) { fade=document.getElementById('map').firstElementChild } create_canvas(); } function fadecanvas() { if(fade){ if(fade.style.opacity<=0.3){ document.getElementById('map').removeChild(fade); fade=null; }else{ fade.style.opacity-=0.1; fade.style.filter = 'alpha(opacity=' + Math.ceil(fade.style.opacity*10) + ')'; } } } function create_canvas() { element=document.createElement('canvas'); canvas=element.getContext('2d'); canvas.canvas.width=w; canvas.canvas.height=h; element.style.opacity=1; image = canvas.createImageData(w,h) for( i in dcss ) { dcs[i] = canvas.createImageData(1,1) dcs[i].data[0] = dcss[i][0]; dcs[i].data[1] = dcss[i][1]; dcs[i].data[2] = dcss[i][2]; dcs[i].data[3] = 255; } document.getElementById('map').appendChild(element); } var jqxhr; var service="wpcom"; if( matches = window.location.search.match(/s=(w+)/) ){ service=matches[1]; } function getdata(){ if (!running){ $.ajax( "?g="+service, { cache:true, crossDomain:true, dataType:"jsonp", jsonpCallback:"jsonpcallback", timeout:4000, } ).done( function(data) { if( data.length ) { hitdata=data; hitdata.sort(function() {return 0.5 – Math.random()}); } running=0; }).fail(function( jqXHR, textStatus,errorThrown ) { // alert( "Request failed: " + textStatus + " : " + errorThrown); }).always(function() { running=0; // alert("foo"); }); running=1; } } var max=1000; var per_iter = 1000; data=new Array(); function addstuff() { for (k=0;k<per_iter;k++){ var point = hitdata.pop(); if (point){ x=Math.ceil((180+point['lng'])*ww); y=Math.ceil((90–point['lat'])*hh); canvas.putImageData(dcs[point['host']], x,y); } } per_iter=130; } </script> </head> <body> <div id="map"></div> </body> </html><? } view raw index.php hosted with ❤ by GitHub #!/usr/bin/perl # feeder on LBs # tail -F /var/log/nginx/access_log|perl -e '$|=1;while(<>){($f,$f,$ip)=split/s+/;$ip=~s/"//g;print "lax,$ipn"}'|nc -u somenode.example.com 5001 use strict; use warnings; use IO::Socket; use IO::Socket::INET; use Math::Round qw( nhimult nearest ); use Geo::IP; use DBI; my $gi = Geo::IP->open("geocity.dat", GEOIP_MEMORY_CACHE); my $sock = new IO::Socket::INET ( LocalPort => '5001', Proto => 'udp', ) or die "ERROR in Socket Creation : $!n"; # hits.db created with #CREATE TABLE hit (time INTEGER, lat REAL,lng REAL, host TEXT); #CREATE INDEX time ON hit (time); my $dbh = DBI->connect("dbi:SQLite:dbname=/dev/shm/hits.db","","",{AutoCommit=>0}); $dbh->do("CREATE TABLE hit (time INTEGER, lat REAL,lng REAL, host TEXT, service TEXT);"); $dbh->do("CREATE INDEX time ON hit (time);"); $dbh->do("CREATE INDEX service ON hit (service);"); my $sth = $dbh->prepare("INSERT OR REPLACE INTO hit (lat,lng,host,time,service) VALUES(?,?,?,?,?)"); my $old_time; my $data; my $c=0; $|++; my $round=0.001;#.5; while ($sock->recv($data, 30)) { print "."; print "n" if ++$c %80==0; chomp($data); # print "$datan"; my ($dc,$ip,$service) = split /,/,$data; $service||="wpcom"; my $r=$gi->record_by_addr($ip); next if !$r || $r->longitude==0; my ($lat,$lng) = ($r->latitude, $r->longitude); # gunzip($recieved_data => $output); my $curtime = time(); my $time = nhimult(2, $curtime); if( $old_time != $time ){ $dbh->do("DELETE FROM hit WHERE time < " . ($curtime – 11) ); $dbh->commit; $old_time=$time; print "commitn"; } $sth->execute(nearest($round,$lat), nearest($round, $lng), $dc, time(),$service); } view raw latlongudp.pl hosted with ❤ by GitHub

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s