Skip to content

Commit 0f72f30

Browse files
committed
Refactor peers geo data
1 parent f51d12d commit 0f72f30

3 files changed

Lines changed: 74 additions & 76 deletions

File tree

src/Config.php.example

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ class Config {
2222
const RPC_PASSWORD = "PASSWORD";
2323

2424

25-
// Use ip-api.com to get country and isp of peers. API is limited to 150 requests per minutes.
25+
// Ip-api.com is used to get country and isp of peers. API is limited to 15 requests per minutes.
2626
// Peer geo data is stored as long as the peer is connected. A page reload (main/peers) only
27-
// causes an API request if new peers connected (older than 2 minutes) since the last load. Up to
27+
// causes an API request if new peers connected (older than 5 minutes) since the last load. Up to
2828
// 100 ips/peers are checked per request. You should not run into any trouble with the API limit.
29-
// Set the FALSE to not use the API.
29+
// Set the FALSE to not use the Geo API.
3030
const PEERS_GEO = TRUE;
3131
// Maxmimum of seconds to wait for response from ip-api.com
32-
const PEERS_GEO_TIMEOUT = 2;
32+
const GEO_TIMEOUT = 2;
3333

3434
// Number of TXs displayed on mempool page
3535
const DISPLAY_TXS = 100;

src/Content.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function createMainContent(){
1212
$content['last24h'] = $banListInfo['lastCount'];
1313
$content['node'] = new Node();
1414
if(Config::PEERS_GEO){
15-
$content['map'] = createMapJs($peerCount);
15+
$content['map'] = createMapJs($peerCount, $peersInfo['countryList']);
1616
}
1717
$content['geo'] = Config::PEERS_GEO;
1818
$content['nPeers'] = $peersInfo["newPeersCount"];

src/Utility.php

Lines changed: 69 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -451,45 +451,35 @@ function getMostPop($peers){
451451

452452
// Peer functions
453453

454-
function getPeerData(bool $geo = NULL){
455-
global $bitcoind;
456-
457-
// If not set, use config setting
458-
if(is_null($geo)){
459-
$geo = CONFIG::PEERS_GEO;
460-
}
454+
function getPeerData(bool $geo = CONFIG::PEERS_GEO){
455+
global $bitcoind;
456+
$peersData = [];
461457

462458
$peerInfo = $bitcoind->getpeerinfo();
463459

464460
if($geo){
465-
$peers = createPeersGeo($peerInfo);
461+
$peersData = createPeersGeo($peerInfo);
466462
}else{
467-
$peers = createPeers($peerInfo);
463+
$peersData["peers"] = [];
464+
$peersData["cTraffic"] = 0;
465+
$peersData["cTrafficIn"] = 0;
466+
$peersData["cTrafficOut"] = 0;
467+
$peersData["newPeersCount"] = 0;
468+
469+
foreach($peerinfo as $peer){
470+
$peerObj = new Peer($peer);
471+
$peersData["peers"][] = $peerObj;
472+
$peersData["cTraffic"] += $peerObj->traffic;
473+
$peersData["cTrafficIn"] += $peerObj->trafficIn;
474+
$peersData["cTrafficOut"] += $peerObj->trafficOut;
475+
}
468476
}
469477

470-
return $peers;
471-
}
472-
473-
function createPeers($peerinfo){
474-
$peersInfo["peers"] = [];
475-
$peersInfo["cTraffic"] = 0;
476-
$peersInfo["cTrafficIn"] = 0;
477-
$peersInfo["cTrafficOut"] = 0;
478-
$peersInfo["newPeersCount"] = 0;
479-
480-
foreach($peerinfo as $peer){
481-
$peerObj = new Peer($peer);
482-
$peersInfo["peers"][] = $peerObj;
483-
$peersInfo["cTraffic"] += $peerObj->traffic;
484-
$peersInfo["cTrafficIn"] += $peerObj->trafficIn;
485-
$peersInfo["cTrafficOut"] += $peerObj->trafficOut;
486-
}
487-
488-
return $peersInfo;
478+
return $peersData;
489479
}
490480

491481
function createPeersGeo($peerinfo){
492-
global $countryList;
482+
$peersInfo['countryList'] = [];
493483
$peersInfo["peers"] = [];
494484
// Current traffic
495485
$peersInfo["cTraffic"] = 0;
@@ -511,7 +501,7 @@ function createPeersGeo($peerinfo){
511501
$oldestPeerId = reset($peerinfo)["id"];
512502
$oldestPeerIp = getCleanIP(reset($peerinfo)["addr"]);
513503
$delete = false;
514-
// Checks if we know about the oldest peer, if not we assume that we don't known any peer
504+
// Checks if we know about the oldest peer, if not we assume that we don't known any peer
515505
foreach($arrayPeers as $key => $peer){
516506
if($oldestPeerIp == $peer[0]){
517507
$delete = true;
@@ -533,49 +523,53 @@ function createPeersGeo($peerinfo){
533523
$noGeoData = true;
534524
}
535525

536-
// Find Ips that we don't have geo data for and that are "older" than 2 minutes
526+
// Find Ips that we don't have geo data for and that are "older" than 5 minutes
537527
// First interation through all peers is used to collect ips for geo api call. This way the batch functionality can be used
538-
$ips = [];
539-
foreach($peerinfo as &$peer){
528+
$ips = [];
529+
$ipData = [];
530+
531+
foreach($peerinfo as $peer){
540532
$tempIP = getCleanIP($peer['addr']);
541533
$age = round((time()-$peer["conntime"])/60);
542-
if ($age > 2 AND ($noGeoData OR !in_array($tempIP,array_column($arrayPeers,0)))){
534+
if ($age > 5 AND ($noGeoData OR !in_array($tempIP,array_column($arrayPeers,0)))){
543535
$ips[] = $tempIP;
544536
}
545537
}
546-
unset($peer);
547538

548539
if(!empty($ips)){
549-
$ipData = getIpData($ips);
550-
}
540+
$apiData = getIpData($ips);
541+
$ipData = $apiData['geojson'];
542+
$peerData['api'] = $apiData['api'];
543+
}
544+
551545
// 2nd interation through peers to create final peer list for output
552546
foreach($peerinfo as $peer){
553547
// Creates new peer object
554548
$peerObj = new Peer($peer);
555549

556550
// Checks if peer is new or if we can read data from disk (geodatapeers.inc)
557-
if($noGeoData OR !in_array($peerObj->ip,array_column($arrayPeers,0))){
558-
if(isset($ipData[0]) AND $peerObj->age > 2){
559-
// Only counted for peers older than 2 minutes
560-
$peersInfo["newPeersCount"]++;
561-
562-
$countryInfo = $ipData[array_search($peerObj->ip, array_column($ipData, 'query'))];
563-
$countryCode = checkCountryCode($countryInfo['countryCode']);
564-
$country = checkString($countryInfo['country']);
565-
$isp = checkString($countryInfo['isp']);
551+
if($noGeoData OR !in_array($peerObj->ip,array_column($arrayPeers,0))){
552+
$index = array_search($peerObj->ip, array_column($ipData, 'query'));
553+
if(isset($ipData[0]) AND $peerObj->age > 5 AND is_numeric($index)){
554+
$ipInfo = $ipData[$index];
555+
$countryCode = checkCountryCode($ipInfo['countryCode']);
556+
$country = checkString($ipInfo['country']);
557+
$isp = checkString($ipInfo['isp']);
566558
$hosted = checkHosted($isp);
567559
// Adds the new peer to the save list
568-
$arrayPeers[$peerObj->id] = array($peerObj->ip, $countryCode, $country, $isp, $hosted, 1);
569-
}elseif($peerObj->age > 2){
560+
$arrayPeers[$peerObj->id] = array($peerObj->ip, $countryCode, $country, $isp, $hosted, 1);
561+
// Only counted for peers older than 5 minutes
562+
$peersInfo["newPeersCount"]++;
563+
}elseif($peerObj->age > 5){
570564
// If IP-Api.com call failed we set all data to Unknown and don't store the data
571565
$countryCode = "UN";
572566
$country = "Unknown";
573567
$isp = "Unknown";
574568
$hosted = false;
575-
// Only counted for peers older than 2 minutes
569+
// Only counted for peers older than 5 minutes
576570
$peersInfo["newPeersCount"]++;
577571
}else{
578-
// If peer is younger than 2 minutes
572+
// If peer is younger than 5 minutes
579573
$countryCode = "NX";
580574
$country = "New";
581575
$isp = "New";
@@ -596,11 +590,11 @@ function createPeersGeo($peerinfo){
596590
}
597591

598592
// Counts the countries
599-
if(isset($countryList[$country])){
600-
$countryList[$country]['count']++;
593+
if(isset($peersInfo['countryList'][$country])){
594+
$peersInfo['countryList'][$country]['count']++;
601595
}else{
602-
$countryList[$country]['code'] = $countryCode;
603-
$countryList[$country]['count'] = 1;
596+
$peersInfo['countryList'][$country]['code'] = $countryCode;
597+
$peersInfo['countryList'][$country]['count'] = 1;
604598
}
605599

606600
// Adds country data to peer object
@@ -624,7 +618,7 @@ function createPeersGeo($peerinfo){
624618
}
625619

626620
// Only if new peers connected
627-
if(isset($ipData)) {
621+
if(!empty($ipData)) {
628622
// Removes all peers that the node is not connected to anymore.
629623
foreach($arrayPeers as $key => $peer){
630624
if($peer[5] == 0){
@@ -641,12 +635,14 @@ function createPeersGeo($peerinfo){
641635

642636
function getIpData($ips){
643637
global $error;
644-
645-
$numOfIps = count($ips);
646-
// A maximum of 300 IPs can be checked (theoratical limit by ip-api.com is 15000 per min (150 x 100) if batch requests are used)
647-
if($numOfIps > 300){
648-
$numOfIps = 300;
649-
}
638+
$apiData['api']['callc'] = 0;
639+
640+
// ip-api.com allows 15 requests with 100 ips per minute. The limit here is lower since
641+
// new peers could connect within a minute a trigger additional calls.
642+
$numOfIps = count($ips);
643+
if($numOfIps > 1200) $numOfIps = 1200;
644+
645+
$apiData['api']['ipc'] = $numOfIps;
650646
$j = 0;
651647
// A mamxium of 100 Ips can be checked per API call (limit by ip-api.com)
652648
$m = 100;
@@ -659,34 +655,36 @@ function getIpData($ips){
659655
$postvars[$j][] = array("query" => $ips[$i+$j]);
660656
}
661657
$j += $i;
662-
}
658+
}
659+
663660
// Curl
664661
$ch = curl_init();
665662
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
666663
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
667664
curl_setopt($ch, CURLOPT_POST, true);
668-
curl_setopt($ch, CURLOPT_URL,'http://ip-api.com/batch?fields=query,country,countryCode,isp,status');
665+
curl_setopt($ch, CURLOPT_URL,'http://ip-api.com/batch?fields=query,country,countryCode,city,isp,status');
669666
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
670-
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT , CONFIG::PEERS_GEO_TIMEOUT);
671-
curl_setopt($ch, CURLOPT_TIMEOUT, CONFIG::PEERS_GEO_TIMEOUT+1);
667+
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT , CONFIG::GEO_TIMEOUT);
668+
curl_setopt($ch, CURLOPT_TIMEOUT, CONFIG::GEO_TIMEOUT+1);
672669

673670
// One call for each 100 ips
674-
$geojsonraw = [];
671+
$apiData['geojson'] = [];
675672
foreach($postvars as $postvar){
673+
$apiData['api']['callc']++;
676674
$postvarJson = json_encode($postvar);
677675
curl_setopt($ch,CURLOPT_POSTFIELDS, $postvarJson);
678676
$result = json_decode(curl_exec($ch),true);
679677
if(empty($result)){
680678
$error = "Geo API (ip-api.com) Timeout";
681679
$result = [];
682680
}
683-
$geojsonraw = array_merge($geojsonraw, $result);
684-
}
685-
return $geojsonraw;
681+
$apiData['geojson'] = array_merge($apiData['geojson'], $result);
682+
}
683+
684+
return $apiData;
686685
}
687686

688-
function createMapJs(int $peerCount){
689-
global $countryList;
687+
function createMapJs(int $peerCount, array $countryList){
690688

691689
// Sorting country list
692690
function compare($a, $b)

0 commit comments

Comments
 (0)