
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>::Kademlia on P2PP::</title>
</head>

  
  <!-- Maps Api, Ajax Search Api and Stylesheet
  // Note: If you are already using the Maps API then do not include it again
  //       If you are already using the AJAX Search API, then do not include it
  //       or its stylesheet again
  //
  // The Key Embedded in the following script tags is designed to work with
  // the following site:
  // http://www1.cs.columbia.edu/~gg2265
  -->

  <script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAAc935VnAnF2dEeQAu3V_zjxT-ylC5EnPqBDCn-1Fg_c9eA8mcQRQEHVuvqppZGzIVXQoSHAmA8bW_5A"
    type="text/javascript"></script>
  <script src="http://www.google.com/uds/api?file=uds.js&v=1.0&source=uds-msw&key=ABQIAAAAc935VnAnF2dEeQAu3V_zjxT-ylC5EnPqBDCn-1Fg_c9eA8mcQRQEHVuvqppZGzIVXQoSHAmA8bW_5A"
    type="text/javascript"></script>
  <style type="text/css">
    @import url("http://www.google.com/uds/css/gsearch.css");
  </style>
  <script language="Javascript" src="helper.js" > </script>


  <body onunload="GUnload()">
  <h1>Kademlia on P2PP </h1>

	<p>
	Welcome to the geographical interface of our 500+ node Kademlia overlay
	network built using <a href="http://tools.ietf.org/html/draft-baset-p2psip-p2pp-01">P2PP-01 protocol</a>. 
	We are running three instances of the P2PP executable on ~180 planet lab machines 
	distributed around the world. Each peer has been assigned a randomly generated user-name.

	<p>In this page, you should see a list of markers at various geographical locations. 
	These markers correspond to the latitudes and longitudes of the planet lab site that is running
	our P2PP system. On the right side of this page, you should see a list of nodes, their
	port numbers, and the randomly generated user-name assigned to each node.</p>
	
	<p>
	To play with the system, just click on any marker or select a node from the list.
	In the pop-up, you can search for a user-name <b>(LookupUser)</b>,
	publish a key/value pair <b>(Publish)</b>, and look it up <b>(LookupObject)</b>. You 
	can also check the routing table of a peer <b>(Get routing table)</b>
	and the resource objects it stores <b>(Get resource table)</b>. Our system
	lets you perform these queries in a recursive or iterative fashion. For each
	operation, we also show the time taken to complete the operation and
	exponential weighted moving average of bytes sent and received.</p>

	<a href="index.html">Home</a>

    <!-- you can use tables or divs for the overall layout -->

    <table border=1>
   <!--
      <tr>
        <td>
           <div id="upper_bar" style="width: 1000px; height: 20px;"></div>
        </td>
      </tr>
   -->
      <tr>
        <td>
           <div id="map" style="width: 1000px; height: 1000px"></div>
        </td>
        <td width = 150 valign="top" style="text-decoration: underline; color: #4444ff;">
           <div id="side_bar" style="overflow:auto; height: 1000px; width: 300px;"></div>
        </td>
      </tr>

    </table>


    <noscript><b>JavaScript must be enabled in order for you to use Google Maps.</b> 
      However, it seems JavaScript is either disabled or not supported by your browser. 
      To view Google Maps, enable JavaScript by changing your browser options, and then 
      try again.
    </noscript>


    <script type="text/javascript">

    //<![CDATA[

    if (GBrowserIsCompatible()) {

      // create the map
      var map = new GMap2(document.getElementById("map"));
      map.addControl(new GLargeMapControl());
      map.addControl(new GMapTypeControl());
      map.setCenter(new GLatLng( 43.907787,-79.359741), 3);

      var side_bar_html = "";
      var upper_bar_html = "";

      var refmap ;


      // this variable will collect the html which will eventualkly be placed in the side_bar
      var side_bar_html = "";
    
      // arrays to hold copies of the markers and html used by the side_bar
      // because the function closure trick doesnt work there
      var greenIcon = new GIcon(G_DEFAULT_ICON);
      greenIcon.image = "imgs/green-dot.png";
      greenIcon.iconSize = new GSize(32, 32);
      greenIcon.shadowSize = new GSize(0, 0);
      greenIcon.iconAnchor = new GPoint(16, 32);
      var redIcon = new GIcon(G_DEFAULT_ICON);
      redIcon.image = "imgs/red-dot.png";
      redIcon.iconSize = new GSize(32, 32);
      redIcon.shadowSize = new GSize(0, 0);
      redIcon.iconAnchor = new GPoint(16, 32);
      var gmarkers = new Object();
      var IP = [];
      var rt = [];
      var htmls = [];
      var htmls2 = [];
      var htmls3 = new Object();
      var htmls4 = new Object();
      var overlays = new Object();
      var overlays1 = [];
      var i = 0;
      var oldPoly = [];
      var gmarkers2 = [];
      var great_circle_pts = [];
      var selectlisthtml='<?php include 'create_drop_down.php'; create_dropdown_list(); ?>';
      var html4 = ' </select> <form name="lookupform" action=";" onSubmit="return dolookup();" > <table> <tr>   <td valign="top"> <b>Recursive routing</b> </td> <td> <input type="checkbox" name="recursive" /> </td> </tr> <tr> <td> <br> </td> </tr> <tr>   <td valign="top"> <b>LookupUser</b> </td>      <td><input id="usrname" type="text" name="usrname" value="<?echo $usr?>"/></td>    </tr>    <tr>       <td> <font size=2> (enter/select username, <br>select host and press lookup) </font> </td> <td>'+selectlisthtml+'</td>    </tr>    <tr>      <td> <input type="submit"  name="lookup"  onclick="seturl(1)" value="Lookup User"/> </td>    </tr>    <tr> <td> <br> </td> </tr>    <tr>      <td> <b>LookupObject</b> </td>      <td> <input type="text" name="objname" value="<?echo $obj?>"/> </td>    </tr>    <tr>       <td> <font size=2> (enter objectname, <br>select host and press lookup) </font> </td>     </tr>    <tr>      <td> <input type="submit"  name="lookup" onclick="seturl(2)" value="Lookup Object"/> </td>    </tr>    <tr> <td> <br> </td> </tr>     <tr>      <td> <b>Publish</b> </td>    </tr>    <tr>      <td> Object (string)  </td>      <td> <input type="text" name="keystr" value="<?echo $key?>"/> </td>    </tr>    <tr>      <td> Value </td>      <td> <input type="text" name="valuestr" value="<?echo $value?>"/> </td>    </tr>    <tr>       <td> <font size=2> (enter object, value, <br>select host and press publish) </font> </td>     </tr>    <tr>      <td> <input type="submit"  name="insert" onclick="seturl(3)"  value="Publish"/> </td>    </tr>    <tr> <td> <br> </td> </tr>    <tr>      <td> <b>Get routing table</b> </td>    </tr>    <tr>       <td> <font size=2> (select host and <br> press get routing table) </font> </td>     </tr>    <tr>      <td> <input type="submit" name="getrt" onclick="seturl(4)" value="Get routing table"> </td>    </tr>    <tr> <td> <br> </td> </tr>    <tr>      <td> <b>Get resource table</b> </td>    </tr>    <tr>       <td> <font size=2> (select host and <br> press get resource table) </font> </td>     </tr>    <tr>      <td> <input type="submit" name="getro" onclick="seturl(5)" value="Get resource table"> </td>    </tr> <tr> <td> <br> </td> </tr> <tr>      <td> <b>Get TURN allocations</b> </td>    </tr>    <tr>       <td> <font size=2> (select peer and <br> press get TURN allocations) </font> </td>     </tr> <tr>      <td> <input type="submit" name="getturnalloc" onclick="seturl(6)" value="Get TURN allocations"> </td>    </tr>    <tr> <td> <br> </td> </tr>   </table>  </td></tr></table> </form>'; //getstr(); //" LookupUser   <input id=\"usrname\" type=\"text\" name=\"usrname\" value=\"<?echo $usr?>\"\/> <input type=\"submit\"  name=\"lookup\"  value=\"Lookup User\"\/> <\/form> ";
      var html3 = '<h4> Resource utilization ';
      var xmlHttp;
      var colormapindex=0;
      var colormap = ["#00008B","#FF1493","#00CED1","#DC143C","#008B8B","#8B000", "#DC143C", "#DC143C"];
      //alert(colormap[1]);
      function getnextcolor(){
	var re = colormap[colormapindex];
	colormapindex = (colormapindex + 1)%8;
	return re;
      }

      function GetXmlHttpObject()
      {
	var ret=null;
	try
	  {
	    // Firefox, Opera 8.0+, Safari
	    ret=new XMLHttpRequest();
	  }
	catch (e)
	{
	  //Internet Explorer
	  try
	    {
	      ret=new ActiveXObject("Msxml2.XMLHTTP");
	    }
	  catch (e)
	  {
	    ret=new ActiveXObject("Microsoft.XMLHTTP");
	  }
	}
	return ret;
      }


      function EraseGreatCircle() {
      if(oldPoly) {
      for (var i = 0; i < oldPoly.length; i++) {
      map.removeOverlay(oldPoly[i]);
      }
      }
      for (var i = 0; i < gmarkers2.length; i++) {
      map.removeOverlay(gmarkers2[i]);
      }
          for (var j=0;j <gmarkers2.length; ++j){
	    for (var k=0;k <overlays1[j].length; ++k){
	      map.removeOverlay(overlays1[j][k]);
	    } 
	  }

      }

      function ShowGreatCircle() {
      if(oldPoly) {
      for (var i = 0; i < oldPoly.length; i++) {
      map.addOverlay(oldPoly[i]);
      }
      }
      for (var i = 0; i < gmarkers2.length; i++) {
      map.addOverlay(gmarkers2[i]);
      }
      }

      function drawCircle(center, radius, color, thickness, opacity, node_count) {
      //Function created by Chris Haas

      var circleQuality = 360/node_count;//1 is best but more points, 5 looks pretty good, too
      var M = Math.PI / 180;//Create Radian conversion constant
      var L = map.getBounds();//Holds copy of map bounds for use below
      var sw = L.getSouthWest();
      var ne = L.getNorthEast();

      //The map is not completely square so this calculates the lat/lon ratio
      // this works because we create a square map
      var circleSquish = (ne.lng() - sw.lng()) / (ne.lat() - sw.lat());
      circleSquish = circleSquish/4;
      var points = []; //Init Point Array
      //Loop through all degrees from 0 to 360
      var j=0;
      for(var i=0; j<node_count; i+=circleQuality,j++){
      var P = new GLatLng(
      -20 + (80 * Math.sin(i * M))*circleSquish,
      -79 + (80 * Math.cos(i * M))
      );
      var marker1 = new GMarker(P);
      gmarkers2.push(marker1);
//      map.addOverlay(marker1);
      points.push(P);
      great_circle_pts.push(P);
      }
      points.push(points[0]);// close the circle
      var p = new GPolyline(points, color, thickness, opacity);
//      map.addOverlay(p);
      oldPoly.push(p);
      }

      function avoid_closure(html,overlay,marker){
	  for (var j=0;j <gmarkers.length; ++j){
	    for (var k=0;k <overlays[j].length; ++k){
	      map.removeOverlay(overlays[j][k]);
	      map.removeOverlay(overlays1[j][k]);
	    } 
	  }
	  for (var k=0;k <overlay.length; ++k){
	    map.addOverlay(overlay[k]);
	  } 
//alert(marker);
          this.openInfoWindowHtml(html,{autoScroll:true,maxHeight:400});
//alert(html);
      }

      function trim (str) {
        return str.replace(/^\s+/, '').replace(/\s+$/, '');
      }     

      var whichNode;
      var myurl="";

      function userselected(list){
	document.forms[0]["usrname"].value=list[list.selectedIndex].value;
      }

      function goto_node(ipport){
	var ip= ipport.split(":")[0];
	if(!gmarkers[ip]){
	  return;
	}
	myclick(ipport);
	
      }

      function clearOverlay(){
	for(var j in overlays){
	  for(var k=0;k<overlays[j].length;++k){
	    map.removeOverlay(overlays[j][k]);
	  }
	  overlays[j]=[];
	}
      }

      function show_progressbar() {
        var wait_html='<img src="imgs/wait.gif" border="0" alt="Loading, please wait..." />';
        var newarr = map.getInfoWindow().getTabs();
        newarr[newarr.length-1] = new GInfoWindowTab("Results",wait_html);
        map.updateInfoWindow(newarr);
        map.getInfoWindow().selectTab(2);
      }

      function phpCallback(){
	
	if (xmlHttp.readyState == 4) {
	  //alert(xmlHttp.responseText);
	  colormapindex=0;
	  clearOverlay();
	  var ipregex= /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{4,5})/;
	  var outstr="<table> ";
	  outstr+= "<tr> <td> <b> Result: </b></td> </tr>";
	  outstr+= "<tr> <td>";
	  outstr+= "<b>";

	  var myip = whichNode.split(":")[0];
	  var pts = [];
	  pts[0] =  new GLatLng(refmap[myip][1],refmap[myip][2]);
	  var resp = xmlHttp.responseText;
	  var data = resp.split("\n");
	  for(var j=0; j<data.length; ++j){
	    var tmpstr=data[j];
	    var tmparr=[];
	    if(data[j].search(ipregex)>=0){
	      //ipregex.exec(data[j]));
	      tmparr= data[j].match(ipregex);
              if(tmparr.length>0) {
                tmpstr=data[j].replace(ipregex, "<a href=\"javascript:goto_node('$1')\" >$1</a>");
              }
	    }//if
	    
	    if(tmpstr.match('Next hop')!=null){
	      var col=getnextcolor();

	      outstr += '<font color="'+col+'">'+ tmpstr +'</font> <br>\n';
	      //tmparr= data[j].match(ipregex);
	      if(tmparr.length>0){
		var ip = tmparr[0].split(":")[0];
                if(refmap[ip]!=null) {
                  pts[1]=new GLatLng(refmap[ip][1],refmap[ip][2]);
                  var poly = new GPolyline(pts,col,4);
                  overlays[myip].push(poly);
                  map.addOverlay(poly);
                  poly = new GPolyline(pts,col,4);
                  overlays[myip].push(poly);
                  map.addOverlay(poly);
                  pts[0]=pts[1];
                }
	      }
	    } else if( tmpstr.match('200 Ok')!=null){
              //alert("200 not ok");
	      outstr += '<font color="green">'+ tmpstr +'</font> <br>\n';
	      //tmparr= data[j].match(ipregex);
	      if(tmparr.length>0){
		var ip = tmparr[0].split(":")[0];
                if(refmap[ip]!=null) {
                  pts[1]=new GLatLng(refmap[ip][1],refmap[ip][2]);
                  pts[0]=pts[1];
                }
	      }
	    } else if( tmpstr.match('413 Timeout')!=null){
	      outstr += '<font color="orange">'+ tmpstr +'</font> <br>\n';
	    } else if( tmpstr.match('404 Not')!=null){
	      outstr += '<font color="red">'+ tmpstr +'</font> <br>\n';
	    } else {
	      outstr += tmpstr+ '<br>';
	      if(tmparr.length>0){
		var ip = tmparr[0].split(":")[0];
                if(refmap[ip]!=null) {
                  pts[1]=new GLatLng(refmap[ip][1],refmap[ip][2]);
                  var poly = new GPolyline(pts,"#FF0000",4);
                  overlays[myip].push(poly);
                  map.addOverlay(poly);
                }
		//pts[0]=pts[1];
	      }
	    }//if

	    
	    

	  }//for

	  outstr += "</b>";
	  outstr += "</tr> </td>";
	  outstr += "</table>";
	  
	  var newarr = map.getInfoWindow().getTabs();
	  newarr[newarr.length-1] = new GInfoWindowTab("Results",outstr);
	  map.updateInfoWindow(newarr);
	  map.getInfoWindow().selectTab(2);
	}//if xml
	
      }

      
      function seturl(formid){
	myurl= "dolookup.php";
	if(document.lookupform.recursive.checked==true){
	  myurl+="?rec=1";
	}else {
	  myurl+="?rec=0";
	}
	//alert(rec);
	if(formid==1){
	  myurl += "&cmd=lookupusr&usr=" + document.getElementById("usrname").value ;
	}
	if(formid==2){
	  myurl += "&cmd=lookupobj&obj=" + document.lookupform.objname.value ;
	}
	if(formid==3){
	   myurl += "&cmd=publish&key=" + document.lookupform.keystr.value +'&value='+ document.lookupform.valuestr.value;
	}
	if(formid==4){
	  myurl += "&cmd=getrt";
	}
	if(formid==5){
	  myurl += "&cmd=getro";
	}
	if(formid==6){
	  myurl += "&cmd=getturnalloc";
	}
      }

      function dolookup(){
        //show wait sign
        show_progressbar();

	//alert(ipport);
	var list = document.getElementById("ipselect");
	var ipport = list[list.selectedIndex].value;
	whichNode=ipport;
	xmlHttp = GetXmlHttpObject();

	if(xmlHttp==null){
	  alert("browser does not support ajax");
	  return false;
	}
	myurl += "&ip=" + ipport;
      	xmlHttp.onreadystatechange=phpCallback;
	xmlHttp.open("GET",myurl,true);
       	xmlHttp.send(null);
	//always return false
	return false;
      }

      // This function picks up the click and opens the corresponding info window
      function myclick(ipport) {
	var ip = ipport.split(":")[0];
	var port = ipport.split(":")[1];

	if(!gmarkers[ip] || !htmls4[ip] ){
	  return;
	}

	gmarkers[ip].openInfoWindowTabsHtml([new GInfoWindowTab("Operations",htmls4[ip]+html4),new GInfoWindowTab("Hotmetrics",html3+htmls3[ip]),new GInfoWindowTab("Results","")],{autoScroll:true,maxHeight:400});
      }

      // A function to create the marker and set up the event window
      function createMarker(point,hostport,ip,port,count,markericon,sbw,rbw,cpuutil) {
	var marker;
	if(!gmarkers[ip]){
	  var markeroptions = {icon:markericon};
	  marker = new GMarker(point, markeroptions);
	  gmarkers[ip]=marker;
	  GEvent.addListener(marker, "click", function(){
	      myclick(ip+":"+port);
	    }); 
	  map.addOverlay(marker);
	}else{
	  marker = gmarkers[ip];
	  if(markericon.image == "red-dot.png")
	    marker.setImage("red-dot.png");
	}
        overlays[ip]=[];
	//if(!htmls4[ip]){
	//  htmls4[ip] = new Object();
	//}
	//	var selectlisthtml1 = "<select id=\"ipselect\" name=\"ipselect\"  > <option  value=\""+ip+":7080\">"+host+":7080</option> <option  value=\""+ip+":9080\">"+host+":9080</option> <option value=\""+ip+":10080\">"+host+":10080</option> </select>";

	if(!htmls4[ip])
	  htmls4[ip] = "<select id=\"ipselect\" name=\"ipselect\"  > ";

	htmls4[ip] += "<option  value=\""+ip+ ":" +port+ "\">"+hostport+ "</option>";

	if(!htmls3[ip])
	  htmls3[ip] = '<h4>'+hostport+'</h4>' + 'SBW: ' + sbw + 'B/s RBW: ' + rbw+ 'B/s'+ '<br>CPU usage: ' + cpuutil+ '%';
	else
	  htmls3[ip] += '<h4>'+hostport+'</h4>' + 'SBW: ' + sbw + 'B/s RBW: ' + rbw + 'B/s' + '<br>CPU usage: ' + cpuutil+ '%';

	// selectlisthtml1 + /*"<h3>"+hostport+"</h4>*/ "<form name=\"lookupform\" action=\";\" onSubmit=\"return dolookup();\" >";
        // save the info we need to use later for the side_bar
        // add a line to the side_bar html
	//        side_bar_html += "<a href=\"javascript:myclick('" + ip+":"+port + "')\">" + hostport + "</a><br>";
        i++;
        return marker;
      }

      function setData(marker, overlay, html, html2, html3, count) {

	 GEvent.addListener(marker, "click", function() {
          for (var j=0;j <gmarkers2.length; ++j){
	    for (var k=0;k <overlays1[j].length; ++k){
	      map.removeOverlay(overlays1[j][k]);
	      map.removeOverlay(overlays[j][k]);
	    } 
	  }
//alert(html);
	  for (var k=0;k <overlay.length; ++k){
	    map.addOverlay(overlay[k]);
	  } 
          marker.openInfoWindowTabsHtml([new GInfoWindowTab("Tables",html),new GInfoWindowTab("Userinfo",html2),new GInfoWindowTab("Resources",html3)],{autoScroll:true,maxHeight:400});
        });
     }

      // === This function creates reference map of nodes
      reference_map = function(ref){
//alert(ref);      
      refmap = new Object();
        // === create a map out of reference document ===
	lines= ref.split("\n");
	for(var i=0; i<lines.length; i++) 
	{
	  if(lines[i].length <= 1)
	  {
	   continue;
	  }

	  parts = lines[i].split(" ");
	  refmap[parts[0]]= new Object();
	  refmap[parts[0]][0] = parts[1];
	  refmap[parts[0]][1] = parseFloat(parts[2]);	
          refmap[parts[0]][2] = parseFloat(parts[3]);
	  refmap[parts[0]][3] = 0;
	    
      }
     }

      // === Define the function thats going to process the data file ===
      process_it = function(doc) {
//alert(doc);
	var nodelabel;
	var lat;
	var lng;
	var point;
	var rt, sbw, rbw, iconimg, cpuutil;
        // === split the document into lines ===
        lines = doc.split("\n");
	var diag_time = lines[0];
	html3 += '('+diag_time+ '):</h4>';
	var node_count = parseInt(lines[1]);
	//drawCircle(map.getCenter(), 40, '#0000FF', 1, 1.0, node_count);
	var i=2;	
//alert(node_count);
	for (; i<(node_count*4)+1;++i){
          var ip=(lines[i].split(':'))[0];
          var port=(lines[i].split(':'))[1];
	  var name=(lines[i].split(':'))[2];
//alert(refmap[ip][port] + great_circle_pts[i-1]);
          //refmap[ip][port]=great_circle_pts[i-1];
	  nodelabel= refmap[ip][0]+":"+port+" ("+name+")";
	  lat= refmap[ip][1];
	  lng= refmap[ip][2];
	  refmap[ip][3]=1;
	  point= new GLatLng(lat,lng);
	  //get routing table size
	  ++i;
	  rt = parseInt(lines[i]);
	  ++i;
	  sbw = parseInt(lines[i]);
	  ++i;
	  rbw= parseInt(lines[i]);
	  ++i;
	  cpuutil= parseInt(lines[i]);
	  if(rt>0){
	    iconimg = greenIcon;
	  }else {
	    iconimg = redIcon;
	  }
	  var marker = createMarker(point,nodelabel,ip,port,i,iconimg,sbw,rbw,cpuutil);
	  //alert(ip +port);
	}

	for (ip in refmap) {
	  if(refmap[ip][3]>0) {
	    side_bar_html += "<a href=\"javascript:myclick('" + ip+ ":7080" + "')\">" + refmap[ip][0] + "</a><br>";
	  }
	}

	upper_bar_html+='<a href="javascript:ShowGreatCircle()">  Display circled view</a>&nbsp&nbsp&nbsp&nbsp';
	upper_bar_html+='<a href="javascript:EraseGreatCircle()">Clear circled view</a>';
        // put the assembled side_bar_html contents into the side_bar div
        document.getElementById("side_bar").innerHTML = side_bar_html;
	//document.getElementById("upper_bar").innerHTML = upper_bar_html;
      }        
          
      GDownloadUrl("sitelist.txt", reference_map);
      GDownloadUrl("data.txt", process_it);


    }

    else {
      alert("Sorry, the Google Maps API is not compatible with this browser");
    }
    // This Javascript is based on code provided by the
    // Blackpool Community Church Javascript Team
    // http://www.commchurch.freeserve.co.uk/   
    // http://econym.googlepages.com/index.htm

    //]]>

    var del=1800000;// set in milliseconds
    function re(){
      location.reload(true)
    }
    onload =function(){setTimeout('re()',del)}
    </script>
  </body>

</html>




