JSFiddle - React, Tailwind, and code Playground

by Jak Wings

HTML

<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Anonymous+Pro:400,700|Droid+Sans+Mono|Open+Sans:400,700|Linden+Hill|Quattrocento:400,700|News+Cycle:400,700|Antic+Slab|Cabin+Condensed:400,700&amp;output=1.css">
<body onload="go()">
  <div id="container">
    <p>The script on this page will attempt to find your local ip addresses, using HTML5 WebRTC, and then use that info to probe for other live hosts on your lan(s).</p>
    <p>As provided it should work with Chrome and Firefox on Windows and OS X. Chromium on Linux does not work, Firefox reportedly does.</p>
    <p>See this post [<a href="https://2x.io/read/security-by-obscurity">https://2x.io/read/security-by-obscurity</a>] for a discussion on potential security and privacy consequences. Clues: Fingerprinting, Router / Printer exploitation.</p>
    <p>Note that reloading the page with F5 or similar tends to cause a lot of false positives. Reset the url instead.</p>
    <hr>
    <p>Your local ips appear to be:</p>
    <div id="localips"></div>
    <br/>
    <p>Other boxes on your LAN possibly include (this will take some time ..):</p>
    <div id="results"></div>
  </container>
</body>

CSS

body {
    font-family: 'Open Sans', Helvetica, Arial, FreeSans;
    font-size: 12pt;
    color: #666;
    margin-top: 40px;
    text-align: center;
  }
  #container {
    width: auto;
    display: inline-block;
    max-width: 700px;
    margin: 0 auto;
    text-align: left;
  }

JavaScript

function TaskController(numConcurrent, onDone) {
  this.numConcurrent = numConcurrent;
  this.onDone = onDone || function() {};
  this.pending = 0;
  this.queued = [];
  this.checkTimer = -1;
}

TaskController.prototype.deferCheck = function() {
  if (this.checkTimer != -1) return;
  this.checkTimer = setTimeout((function() {
    this.checkTimer = -1;
    this.check();
  }).bind(this), 0);
};

TaskController.prototype.check = function() {
  if (this.pending < 1 && this.queued.length == 0) return this.onDone();
  while (this.pending < this.numConcurrent && this.queued.length > 0) {
    try {
      this.pending += 1;
      setTimeout((function(task) {
        task((function() {
          this.pending -= 1;
          this.deferCheck();
        }).bind(this));
      }).bind(this, this.queued.shift()), 0);
    }
    catch (e) {
      this.pending -= 1;
      this.deferCheck();
    }
  }
};

TaskController.prototype.queue = function(task) {
  this.queued.push(task);
  this.deferCheck();
};

function probeIp(ip, timeout, cb) {
  var start = Date.now();
  var done = false;
  var img = document.createElement('img');
  var clean = function() {
    if (!img) return;
    document.body.removeChild(img);
    img = null;
  };
  var onResult = function(success) {
    if (done) return;
    done = true;
    clean();
    cb(ip, Date.now() - start < timeout);
  };
  document.body.appendChild(img);
  img.style.display = 'none';
  img.onload = function() { onResult(true); };
  img.onerror = function() { onResult(false); };
  img.src = 'https://' + ip + ':' + ~~(1024+1024*Math.random()) + '/I_DO_NOT_EXIST?' + Math.random();
  setTimeout(function() { if (img) img.src = ''; }, timeout + 500);
}

function probeNet(net, onHostFound, onDone) {
  net = net.replace(/(\d+\.\d+\.\d+)\.\d+/, '$1.');
  var timeout = 5000;
  var done = false;
  var found = [];
  var q = new TaskController(5, onDone);
  for (var i = 1; i < 256; ++i) {
    q.queue((function(i, cb) {
      probeIp(net + i, timeout,...