-2

I am attempting to save a user’s local IP address to a variable in JavaScript. I found part of the solution in a post by mido in an earlier question titled How to get client’s IP address using javascript only?. The solution works well and uses WebRTC with JavaScript to display the local IP; however, I have been unable to pass these IP addresses to a variable. The code below shows what I am trying to do.

In it, I have created an html tag with id=saveIP. I am trying to replace its contents with the user's IP (IPv4 for the moment). I created a varialbe window.saveIP for this purpose, and I'm using the document.getElementById('saveIP').innerHTML method towards the bottom of the script to pass the value to my HTML tag.

I have seen other solutions, but they all appear to simply display the IP address without saving them.

My question is what modifications must I make to capture the user's local IP(s) and save it to a variable?

<html>
<body>

 <p id=saveIP> Replace this with IP </p>

<script>

function findIP(onNewIP) { //  onNewIp - your listener function for new IPs
  var myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; //compatibility for firefox and chrome
  var pc = new myPeerConnection({iceServers: []}),
    noop = function() {},
    localIPs = {},
    ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g,
    key;
    //window.saveIP = pc;
    //window.saveIP = localIPs; // Returns [object, object] or JSON.stringfy returns {}

  function ipIterate(ip) {
    if (!localIPs[ip]) onNewIP(ip);
    localIPs[ip] = true;  
  }
  pc.createDataChannel(""); //create a bogus data channel
  pc.createOffer(function(sdp) {
    sdp.sdp.split('\n').forEach(function(line) {
      if (line.indexOf('candidate') < 0) return;
      line.match(ipRegex).forEach(ipIterate);
});
    pc.setLocalDescription(sdp, noop, noop);
  }, noop); // create offer and set local description
  pc.onicecandidate = function(ice) { //listen for candidate events
    if (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) return;
    ice.candidate.candidate.match(ipRegex).forEach(ipIterate);
  };
}


var ul = document.createElement('ul');
ul.textContent = 'Your IPs are: '
document.body.appendChild(ul);

function addIP(ip) {
  console.log('got ip: ', ip);
  var li = document.createElement('li');
  li.textContent = ip;
  window.saveIP = ip;  // <--value captured is [object HTMLParagraph]; JSON.stringify returns {}
  ul.appendChild(li);
}

findIP(addIP);
document.getElementById('saveIP').innerHTML = JSON.stringify(window.saveIP);
</script>
</body>
</html>
Community
  • 1
  • 1
Jacob
  • 59
  • 6

2 Answers2

1

this call:

findIP(addIP);

is asynchronous, you are trying to set the result synchronously... move value assigning line inside addIP method.


Update:

try this min version:

var findIP = new Promise(r=>{var w=window,a=new (w.RTCPeerConnection||w.mozRTCPeerConnection||w.webkitRTCPeerConnection)({iceServers:[]}),b=()=>{};a.createDataChannel("");a.createOffer(c=>a.setLocalDescription(c,b,b),b);a.onicecandidate=c=>{try{c.candidate.candidate.match(/([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g).forEach(r)}catch(e){}}})

findIP.then(ip => document.getElementById('saveIP').innerHTML = ip).catch(e => console.error(e))
<html>
<body>

 <p id=saveIP> Replace this with IP </p>
mido
  • 24,198
  • 15
  • 92
  • 117
  • I thought I was doing that on line 45, window.saveIP = ip. – Jacob Aug 17 '16 at 19:06
  • @Jacob put this line also inside: `document.getElementById('saveIP').innerHTML = JSON.stringify(window.saveIP);` – mido Aug 17 '16 at 19:26
  • Thank you! That worked. I clicked to give your answer an up vote, but I don't yet have the reputation points required for it to take affect. It didn't occur to me to place the document.getElementById('saveIP').innerHTML = JSON.stringify(window.saveIP); In my limited use of JavaScript, I haven't executed any asynchronous code, so I've been leaving it outside my functions. I'll post my completed solution once I have it all working. – Jacob Aug 17 '16 at 19:46
0

Thank you mido for pointing out the incorrect placement of my document.getElementByID('saveIP').innerHTML =

In order to capture both IPs, I included a counter and an if statement. The completed solution follows below.

<html>
<body>

<p> You're IP's are: </p>
<p>
Local IP (IPv4): <text id=saveIP> Replace this with IP </text>
<br>
Local IP (IPv6): <text id=saveIP2> Replace this with IP </text>
</p>

<script>
var count = 0
function findIP(onNewIP) { //  onNewIp - your listener function for new IPs
  var myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; //compatibility for firefox and chrome
  var pc = new myPeerConnection({iceServers: []}),
    noop = function() {},
    localIPs = {},
    ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g,
    key;

  function ipIterate(ip) {
    if (!localIPs[ip]) onNewIP(ip);
    localIPs[ip] = true;  
  }
  pc.createDataChannel(""); //create a bogus data channel
  pc.createOffer(function(sdp) {
    sdp.sdp.split('\n').forEach(function(line) {
      if (line.indexOf('candidate') < 0) return;
      line.match(ipRegex).forEach(ipIterate);
    });
    pc.setLocalDescription(sdp, noop, noop);
  }, noop); // create offer and set local description
  pc.onicecandidate = function(ice) { //listen for candidate events
    if (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) return;
    ice.candidate.candidate.match(ipRegex).forEach(ipIterate);
  };
}

function addIP(ip) {
  console.log('got ip: ', ip);
  window.saveIP = ip;  // <--value captured is [object HTMLParagraph]; JSON.stringify returns {}
  if (count == 0){
  document.getElementById('saveIP').innerHTML = JSON.stringify(window.saveIP);  
  } else {document.getElementById('saveIP2').innerHTML = JSON.stringify(window.saveIP); 
  }
  count = count+1
}

findIP(addIP);
</script>
</body>
</html>
Jacob
  • 59
  • 6