PageRenderTime 58ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/v1.9/peerlist.php

https://bitbucket.org/rev22/timekoin
PHP | 789 lines | 547 code | 115 blank | 127 comment | 144 complexity | 75e563f8a57b0265bad18c4bffab34ca MD5 | raw file
  1. <?PHP
  2. include 'configuration.php';
  3. include 'function.php';
  4. set_time_limit(60);
  5. //***********************************************************************************
  6. //***********************************************************************************
  7. if(PEERLIST_DISABLED == TRUE || TIMEKOIN_DISABLED == TRUE)
  8. {
  9. // This has been disabled
  10. exit;
  11. }
  12. //***********************************************************************************
  13. //***********************************************************************************
  14. // Open connection to database
  15. mysql_connect(MYSQL_IP,MYSQL_USERNAME,MYSQL_PASSWORD);
  16. mysql_select_db(MYSQL_DATABASE);
  17. // Check for banned IP address
  18. $ip = mysql_result(mysql_query("SELECT * FROM `ip_banlist` WHERE `ip` = '" . $_SERVER['REMOTE_ADDR'] . "' LIMIT 1"),0,0);
  19. if(empty($ip) == FALSE)
  20. {
  21. // Sorry, your IP address has been banned :(
  22. exit;
  23. }
  24. //***********************************************************************************
  25. //***********************************************************************************
  26. // Answer poll challenge
  27. if($_GET["action"] == "poll" && empty($_GET["challenge"]) == FALSE)
  28. {
  29. echo hash('crc32', intval($_GET["challenge"]));
  30. // Check if Ambient Peer Restart is enabled (randomize to avoid DB spamming)
  31. if(rand(1,30) == 15)
  32. {
  33. $allow_ambient_peer_restart = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'allow_ambient_peer_restart' LIMIT 1"),0,"field_data");
  34. if($allow_ambient_peer_restart == 1 && $allow_ambient_peer_restart !== FALSE) // Check against DB failure also
  35. {
  36. // Check to make sure Timekoin has not be stopped for any unknown reason
  37. $script_loop_active = mysql_result(mysql_query("SELECT * FROM `main_loop_status` WHERE `field_name` = 'main_heartbeat_active' LIMIT 1"),0,"field_data");
  38. $script_last_heartbeat = mysql_result(mysql_query("SELECT * FROM `main_loop_status` WHERE `field_name` = 'main_last_heartbeat' LIMIT 1"),0,"field_data");
  39. if($script_loop_active > 0)
  40. {
  41. // Main should still be active
  42. if((time() - $script_last_heartbeat) > 30) // Greater than triple the loop time, something is wrong
  43. {
  44. // Main stop was unexpected
  45. write_log("Main Timekoin Processor has Failed, going to try an Ambient Peer Restart", "PL");
  46. // Database Initialization
  47. initialization_database();
  48. mysql_query("UPDATE `main_loop_status` SET `field_data` = '" . time() . "' WHERE `main_loop_status`.`field_name` = 'main_last_heartbeat' LIMIT 1");
  49. // Set loop at active now
  50. mysql_query("UPDATE `main_loop_status` SET `field_data` = '1' WHERE `main_loop_status`.`field_name` = 'main_heartbeat_active' LIMIT 1");
  51. source_bg('main.php');
  52. activate(TIMEKOINSYSTEM, 1); // In case this was disabled from a emergency stop call in the server GUI
  53. }
  54. }
  55. // Check watchdog script to make sure it is still running
  56. $script_loop_active = mysql_result(mysql_query("SELECT * FROM `main_loop_status` WHERE `field_name` = 'watchdog_heartbeat_active' LIMIT 1"),0,"field_data");
  57. $script_last_heartbeat = mysql_result(mysql_query("SELECT * FROM `main_loop_status` WHERE `field_name` = 'watchdog_last_heartbeat' LIMIT 1"),0,"field_data");
  58. if($script_loop_active > 0)
  59. {
  60. // Watchdog should still be active
  61. if((time() - $script_last_heartbeat) > 60) // Greater than double the loop time, something is wrong
  62. {
  63. // Watchdog stop was unexpected
  64. write_log("Watchdog has Failed, going to try an Ambient Peer Restart", "PL");
  65. mysql_query("UPDATE `main_loop_status` SET `field_data` = '" . time() . "' WHERE `main_loop_status`.`field_name` = 'watchdog_last_heartbeat' LIMIT 1");
  66. // Set loop at active now
  67. mysql_query("UPDATE `main_loop_status` SET `field_data` = '1' WHERE `main_loop_status`.`field_name` = 'watchdog_heartbeat_active' LIMIT 1");
  68. source_bg('watchdog.php', TRUE);
  69. }
  70. }
  71. } // End Ambient Peer Restart Active Check
  72. } // End Randomize Check
  73. // Log inbound IP activity
  74. mysql_query("INSERT INTO `ip_activity` (`timestamp` ,`ip`, `attribute`)VALUES ('" . time() . "', '" . $_SERVER['REMOTE_ADDR'] . "', 'PL')");
  75. exit;
  76. }
  77. //***********************************************************************************
  78. //***********************************************************************************
  79. // Answer poll challenge
  80. if($_GET["action"] == "polltime")
  81. {
  82. echo time();
  83. // Log inbound IP activity
  84. mysql_query("INSERT INTO `ip_activity` (`timestamp` ,`ip`, `attribute`)VALUES ('" . time() . "', '" . $_SERVER['REMOTE_ADDR'] . "', 'PL')");
  85. exit;
  86. }
  87. //***********************************************************************************
  88. //***********************************************************************************
  89. // Answer a request to see our new/active peer list (Random 10 from new peer list, Random 5 from active peer list)
  90. if($_GET["action"] == "new_peers")
  91. {
  92. $allow_lan_peers = intval(mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'allow_LAN_peers' LIMIT 1"),0,"field_data"));
  93. // Only show peers that have less than 10 poll failures
  94. $sql = "SELECT * FROM `new_peers_list` WHERE `poll_failures` < 10 ORDER BY RAND() LIMIT 10";
  95. $sql_result = mysql_query($sql);
  96. $sql_num_results = mysql_num_rows($sql_result);
  97. $peer_counter = 1;
  98. for ($i = 0; $i < $sql_num_results; $i++)
  99. {
  100. $sql_row = mysql_fetch_array($sql_result);
  101. $ip_address = $sql_row["IP_Address"];
  102. $domain = $sql_row["domain"];
  103. $subfolder = $sql_row["subfolder"];
  104. $port_number = $sql_row["port_number"];
  105. // Check for non-private IP range
  106. if(is_private_ip($ip_address, $allow_lan_peers) == FALSE)
  107. {
  108. echo "-----IP$peer_counter=$ip_address-----domain$peer_counter=$domain-----subfolder$peer_counter=$subfolder-----port_number$peer_counter=$port_number-----";
  109. $peer_counter++;
  110. }
  111. }
  112. $sql = "SELECT * FROM `active_peer_list` ORDER BY RAND() LIMIT 5";
  113. $sql_result = mysql_query($sql);
  114. $sql_num_results = mysql_num_rows($sql_result);
  115. for ($i = 0; $i < $sql_num_results; $i++)
  116. {
  117. $sql_row = mysql_fetch_array($sql_result);
  118. $ip_address = $sql_row["IP_Address"];
  119. $domain = $sql_row["domain"];
  120. $subfolder = $sql_row["subfolder"];
  121. $port_number = $sql_row["port_number"];
  122. // Check for non-private IP range
  123. if(is_private_ip($ip_address, $allow_lan_peers) == FALSE)
  124. {
  125. echo "-----IP$peer_counter=$ip_address-----domain$peer_counter=$domain-----subfolder$peer_counter=$subfolder-----port_number$peer_counter=$port_number-----";
  126. $peer_counter++;
  127. }
  128. }
  129. // Log inbound IP activity
  130. mysql_query("INSERT INTO `ip_activity` (`timestamp` ,`ip`, `attribute`)VALUES ('" . time() . "', '" . $_SERVER['REMOTE_ADDR'] . "', 'PL')");
  131. exit;
  132. }
  133. //***********************************************************************************
  134. //***********************************************************************************
  135. // Answer join request
  136. if($_GET["action"] == "join")
  137. {
  138. $max_active_peers = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'max_active_peers' LIMIT 1"),0,"field_data");
  139. // How many active peers do we have?
  140. $sql = "SELECT * FROM `active_peer_list`";
  141. $active_peers = mysql_num_rows(mysql_query($sql));
  142. if($active_peers >= $max_active_peers)
  143. {
  144. // Server is full for active peers
  145. echo "FULL";
  146. }
  147. else
  148. {
  149. // Server has room for another peer
  150. echo "OK";
  151. }
  152. // Log inbound IP activity
  153. mysql_query("INSERT INTO `ip_activity` (`timestamp` ,`ip`, `attribute`)VALUES ('" . time() . "', '" . $_SERVER['REMOTE_ADDR'] . "', 'PL')");
  154. exit;
  155. }
  156. //***********************************************************************************
  157. //***********************************************************************************
  158. // Answer exchange request
  159. if($_GET["action"] == "exchange")
  160. {
  161. $allow_lan_peers = intval(mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'allow_LAN_peers' LIMIT 1"),0,"field_data"));
  162. $max_active_peers = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'max_active_peers' LIMIT 1"),0,"field_data");
  163. // How many active peers do we have?
  164. $sql = "SELECT * FROM `active_peer_list`";
  165. $active_peers = mysql_num_rows(mysql_query($sql));
  166. if($active_peers >= $max_active_peers)
  167. {
  168. // Server is full for active peers
  169. echo "FULL";
  170. }
  171. else
  172. {
  173. // Server has room for another peer
  174. $my_server_domain = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'server_domain' LIMIT 1"),0,"field_data");
  175. $my_server_subfolder = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'server_subfolder' LIMIT 1"),0,"field_data");
  176. $my_server_port_number = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'server_port_number' LIMIT 1"),0,"field_data");
  177. $ip_address = $_SERVER['REMOTE_ADDR'];
  178. $domain = filter_sql($_GET["domain"]);
  179. $subfolder = filter_sql($_GET["subfolder"]);
  180. $port_number = intval($_GET["port_number"]);
  181. // Check to make sure that this peer is not already in our active peer list
  182. $duplicate_check1 = mysql_result(mysql_query("SELECT * FROM `active_peer_list` WHERE `IP_Address` = '$ip_address' LIMIT 1"),0,"join_peer_list");
  183. $duplicate_check2 = mysql_result(mysql_query("SELECT * FROM `active_peer_list` WHERE `domain` LIKE '$domain' LIMIT 1"),0,"join_peer_list");
  184. if(empty($ip_address) == TRUE)
  185. {
  186. //Don't have an IP address, check for duplicate domain
  187. if(empty($duplicate_check2) == TRUE)
  188. {
  189. if($my_server_domain == $domain)
  190. {
  191. $duplicate_peer = TRUE;
  192. }
  193. else
  194. {
  195. // Neither IP nor Domain exist
  196. $duplicate_peer = FALSE;
  197. }
  198. }
  199. else
  200. {
  201. $duplicate_peer = TRUE;
  202. }
  203. }
  204. else
  205. {
  206. // Using IP only, is there a duplicate
  207. if(empty($duplicate_check1) == TRUE)
  208. {
  209. if($my_server_domain == $domain || empty($duplicate_check2) == FALSE)
  210. {
  211. $duplicate_peer = TRUE;
  212. }
  213. else
  214. {
  215. // Check for non-private IP range
  216. if(is_private_ip($ip_address, $allow_lan_peers) == FALSE)
  217. {
  218. // Neither IP nor Domain exist
  219. $duplicate_peer = FALSE;
  220. }
  221. else
  222. {
  223. $duplicate_peer = TRUE;
  224. }
  225. }
  226. }
  227. else
  228. {
  229. $duplicate_peer = TRUE;
  230. }
  231. }
  232. if($duplicate_peer == FALSE)
  233. {
  234. if(empty($domain) == FALSE)
  235. {
  236. //Assign by domain only if one is included, instead of having both IP and Domain at the same time.
  237. $ip_address = NULL;
  238. }
  239. $sql = "INSERT INTO `active_peer_list` (`IP_Address` ,`domain` ,`subfolder` ,`port_number` ,`last_heartbeat` ,`join_peer_list` ,`failed_sent_heartbeat`)
  240. VALUES ('$ip_address', '$domain', '$subfolder', '$port_number', '" . time() . "', '" . time() . "', '0');";
  241. if(mysql_query($sql) == TRUE)
  242. {
  243. // Exchange was saved, now output our peer information
  244. echo "-----status=OK-----domain=$my_server_domain-----subfolder=$my_server_subfolder-----port_number=$my_server_port_number-----";
  245. }
  246. else
  247. {
  248. // Could not save peer, report error problem
  249. echo "-----status=FAILED-----domain";
  250. }
  251. }
  252. else
  253. {
  254. // Already in our list, might be a re-connect, so give the other peer the OK
  255. echo "-----status=OK-----domain=$my_server_domain-----subfolder=$my_server_subfolder-----port_number=$my_server_port_number-----";
  256. }
  257. }
  258. // Log inbound IP activity
  259. mysql_query("INSERT INTO `ip_activity` (`timestamp` ,`ip`, `attribute`)VALUES ('" . time() . "', '" . $_SERVER['REMOTE_ADDR'] . "', 'PL')");
  260. exit;
  261. }
  262. //***********************************************************************************
  263. //***********************************************************************************
  264. $loop_active = mysql_result(mysql_query("SELECT * FROM `main_loop_status` WHERE `field_name` = 'peerlist_heartbeat_active' LIMIT 1"),0,"field_data");
  265. // Check if loop is already running
  266. if($loop_active == 0)
  267. {
  268. // Set the working status of 1
  269. $sql = "UPDATE `main_loop_status` SET `field_data` = '1' WHERE `main_loop_status`.`field_name` = 'peerlist_heartbeat_active' LIMIT 1";
  270. mysql_query($sql);
  271. }
  272. else
  273. {
  274. // Loop called while still working
  275. exit;
  276. }
  277. //***********************************************************************************
  278. //***********************************************************************************
  279. ini_set('user_agent', 'Timekoin Server (Peerlist) v' . TIMEKOIN_VERSION);
  280. ini_set('default_socket_timeout', 3); // Timeout for request in seconds
  281. $context = stream_context_create(array('http' => array('header'=>'Connection: close'))); // Force close socket after complete
  282. $max_active_peers = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'max_active_peers' LIMIT 1"),0,"field_data");
  283. $max_new_peers = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'max_new_peers' LIMIT 1"),0,"field_data");
  284. $allow_lan_peers = intval(mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'allow_LAN_peers' LIMIT 1"),0,"field_data"));
  285. // How many active peers do we have?
  286. $sql = "SELECT * FROM `active_peer_list`";
  287. $active_peers = mysql_num_rows(mysql_query($sql));
  288. $sql = "SELECT * FROM `new_peers_list`";
  289. $new_peers = mysql_num_rows(mysql_query($sql));
  290. if($active_peers == 0 && $new_peers == 0)
  291. {
  292. // No active or new peers to poll from, start with the first contact servers
  293. // and copy them to the new peer list
  294. $sql = "SELECT * FROM `options` WHERE `field_name` = 'first_contact_server'";
  295. $sql_result = mysql_query($sql);
  296. $sql_num_results = mysql_num_rows($sql_result);
  297. // First Contact Server Format
  298. //---ip=192.168.0.1---domain=timekoin.com---subfolder=timekoin---port=80---end
  299. for ($i = 0; $i < $sql_num_results; $i++)
  300. {
  301. $sql_row = mysql_fetch_array($sql_result);
  302. $peer_ip = find_string("---ip=", "---domain", $sql_row["field_data"]);
  303. $peer_domain = find_string("---domain=", "---subfolder", $sql_row["field_data"]);
  304. $peer_subfolder = find_string("---subfolder=", "---port", $sql_row["field_data"]);
  305. $peer_port_number = find_string("---port=", "---end", $sql_row["field_data"]);
  306. // Insert into database as first contact server(s)
  307. $sql = "INSERT INTO `active_peer_list` (`IP_Address` ,`domain` ,`subfolder` ,`port_number` ,`last_heartbeat`, `join_peer_list`, `failed_sent_heartbeat`)
  308. VALUES ('$peer_ip', '$peer_domain', '$peer_subfolder', '$peer_port_number', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '0');";
  309. mysql_query($sql);
  310. }
  311. }
  312. if($active_peers < $max_active_peers)
  313. {
  314. //Start polling peers from the new peers list
  315. $sql = "SELECT * FROM `new_peers_list` ORDER BY RAND() LIMIT 10";
  316. $sql_result = mysql_query($sql);
  317. $sql_num_results = mysql_num_rows($sql_result);
  318. $my_server_domain = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'server_domain' LIMIT 1"),0,"field_data");
  319. $my_server_subfolder = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'server_subfolder' LIMIT 1"),0,"field_data");
  320. $my_server_port_number = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'server_port_number' LIMIT 1"),0,"field_data");
  321. // Peer difference
  322. $peer_difference_count = $max_active_peers - $active_peers;
  323. for ($i = 0; $i < $sql_num_results; $i++)
  324. {
  325. $sql_row = mysql_fetch_array($sql_result);
  326. $ip_address = $sql_row["IP_Address"];
  327. $domain = $sql_row["domain"];
  328. $subfolder = $sql_row["subfolder"];
  329. $port_number = $sql_row["port_number"];
  330. $poll_failures = $sql_row["poll_failures"];
  331. // Check to make sure that this peer is not already in our active peer list
  332. $duplicate_check1 = mysql_result(mysql_query("SELECT * FROM `active_peer_list` WHERE `IP_Address` = '$ip_address' LIMIT 1"),0,"join_peer_list");
  333. $duplicate_check2 = mysql_result(mysql_query("SELECT * FROM `active_peer_list` WHERE `domain` LIKE '$domain' LIMIT 1"),0,"join_peer_list");
  334. if(empty($ip_address) == TRUE)
  335. {
  336. //Don't have an IP address, check for duplicate domain or my own domain
  337. if(empty($duplicate_check2) == TRUE && $my_server_domain != $domain)
  338. {
  339. // Neither IP nor Domain exist
  340. $duplicate_peer = FALSE;
  341. }
  342. else
  343. {
  344. $duplicate_peer = TRUE;
  345. }
  346. }
  347. else
  348. {
  349. // Check for non-private IP range
  350. if(is_private_ip($ip_address, $allow_lan_peers) == FALSE)
  351. {
  352. // Using IP only, is there a duplicate IP or Domain
  353. if(empty($duplicate_check1) == TRUE && empty($duplicate_check2) == TRUE)
  354. {
  355. $duplicate_peer = FALSE;
  356. }
  357. else
  358. {
  359. $duplicate_peer = TRUE;
  360. }
  361. }
  362. else
  363. {
  364. // Filter private IP ranges
  365. $duplicate_peer = TRUE;
  366. }
  367. }
  368. if($duplicate_peer == FALSE)
  369. {
  370. //Send a challenge hash to see if a timekoin server is active
  371. $poll_challenge = rand(1, 999999);
  372. $hash_solution = hash('crc32', $poll_challenge);
  373. if(empty($domain) == TRUE)
  374. {
  375. $site_address = $ip_address;
  376. }
  377. else
  378. {
  379. $site_address = $domain;
  380. }
  381. if($port_number == 443)
  382. {
  383. $ssl = "s";
  384. }
  385. else
  386. {
  387. $ssl = NULL;
  388. }
  389. //Use site address to poll
  390. $poll_peer = filter_sql(file_get_contents("http$ssl://$site_address:$port_number/$subfolder/peerlist.php?action=poll&challenge=$poll_challenge", FALSE, $context, NULL, 10));
  391. if($poll_peer == $hash_solution)
  392. {
  393. //Got a response from an active Timekoin server
  394. // Ask to be added to the other server's peerlist
  395. $poll_peer = filter_sql(file_get_contents("http$ssl://$site_address:$port_number/$subfolder/peerlist.php?action=join", FALSE, $context, NULL, 10));
  396. if($poll_peer == "OK")
  397. {
  398. // Add this peer to the active list
  399. $poll_peer = filter_sql(file_get_contents("http$ssl://$site_address:$port_number/$subfolder/peerlist.php?action=exchange&domain=$my_server_domain&subfolder=$my_server_subfolder&port_number=$my_server_port_number", FALSE, $context, NULL, 512));
  400. $exchange_status = find_string("-----status=", "-----domain", $poll_peer);
  401. if($exchange_status == "OK")
  402. {
  403. // Insert this peer into our active peer table
  404. $peer_domain = find_string("-----domain=", "-----subfolder", $poll_peer);
  405. $peer_subfolder = find_string("-----subfolder=", "-----port_number", $poll_peer);
  406. $peer_port_number = find_string("-----port_number=", "-----", $poll_peer);
  407. $peer_port_number = intval($peer_port_number);
  408. // Save only domain name if both IP and Domain exist
  409. if(empty($peer_domain) == FALSE)
  410. {
  411. $ip_address = NULL;
  412. }
  413. // Store new peer in active list
  414. $sql = "INSERT INTO `active_peer_list` (`IP_Address` ,`domain` ,`subfolder` ,`port_number` ,`last_heartbeat` ,`join_peer_list` ,`failed_sent_heartbeat`)
  415. VALUES ('$ip_address', '$peer_domain', '$peer_subfolder', '$peer_port_number', '" . time() . "', '" . time() . "', '0');";
  416. if(mysql_query($sql) == TRUE)
  417. {
  418. // Subtract 1 from the peer difference count
  419. $peer_difference_count--;
  420. }
  421. }
  422. else if($exchange_status == "FULL")
  423. {
  424. // Server is full already
  425. }
  426. }
  427. else
  428. {
  429. // Server is either full or not responding, record polling failure
  430. $poll_failures++;
  431. $sql = "UPDATE `new_peers_list` SET `poll_failures` = '$poll_failures' WHERE `IP_Address` = '$ip_address' AND `domain` = '$domain' AND `subfolder` = '$subfolder' AND `port_number` = $port_number LIMIT 1";
  432. mysql_query($sql);
  433. }
  434. }
  435. else
  436. {
  437. //No response, record polling failure for future reference
  438. $poll_failures++;
  439. $sql = "UPDATE `new_peers_list` SET `poll_failures` = '$poll_failures' WHERE `IP_Address` = '$ip_address' AND `domain` = '$domain' AND `subfolder` = '$subfolder' AND `port_number` = $port_number LIMIT 1";
  440. mysql_query($sql);
  441. }
  442. } // End Duplicate Peer Check
  443. else
  444. {
  445. // Active response will remove poll failures
  446. if($poll_failures > 0)
  447. {
  448. $poll_failures--;
  449. $sql = "UPDATE `new_peers_list` SET `poll_failures` = '$poll_failures' WHERE `IP_Address` = '$ip_address' AND `domain` = '$domain' AND `subfolder` = '$subfolder' AND `port_number` = $port_number LIMIT 1";
  450. mysql_query($sql);
  451. }
  452. }
  453. // Clean up active peer list by removing those that have no responded for over 30 poll attempts
  454. if($poll_failures >= 30)
  455. {
  456. // Server has been offline too long, remove it from the active peers list
  457. $sql = "DELETE FROM `new_peers_list` WHERE `IP_Address` = '$ip_address' AND `domain` = '$domain' AND `subfolder` = '$subfolder' AND `port_number` = $port_number LIMIT 1";
  458. mysql_query($sql);
  459. }
  460. // Check to see if enough peers have been added
  461. if($peer_difference_count <= 0)
  462. {
  463. // Break out of loop
  464. break;
  465. }
  466. } // End For Loop
  467. } // End Active vs Max Peer Check
  468. //***********************************************************************************
  469. //***********************************************************************************
  470. // Add more peers to the new peers list to satisfy new peer limit
  471. // How many new peers do we have?
  472. $sql = "SELECT * FROM `new_peers_list`";
  473. $new_peers_numbers = mysql_num_rows(mysql_query($sql));
  474. if($new_peers_numbers < $max_new_peers && rand(1,3) == 2)//Randomize a little to avoid spamming for new peers
  475. {
  476. $my_server_domain = mysql_result(mysql_query("SELECT * FROM `options` WHERE `field_name` = 'server_domain' LIMIT 1"),0,"field_data");
  477. // Add more possible peers to the new peer list by polling what the active peers have
  478. $sql = "SELECT * FROM `active_peer_list`";
  479. $sql_result = mysql_query($sql);
  480. $sql_num_results = mysql_num_rows($sql_result);
  481. $new_peer_difference = $max_new_peers - $new_peers_numbers;
  482. for ($i = 0; $i < $sql_num_results; $i++)
  483. {
  484. $sql_row = mysql_fetch_array($sql_result);
  485. $ip_address = $sql_row["IP_Address"];
  486. $domain = $sql_row["domain"];
  487. $subfolder = $sql_row["subfolder"];
  488. $port_number = $sql_row["port_number"];
  489. if(empty($domain) == TRUE)
  490. {
  491. $site_address = $ip_address;
  492. }
  493. else
  494. {
  495. $site_address = $domain;
  496. }
  497. if($port_number == 443)
  498. {
  499. $ssl = "s";
  500. }
  501. else
  502. {
  503. $ssl = NULL;
  504. }
  505. //Use site address name to poll
  506. $poll_peer = filter_sql(file_get_contents("http$ssl://$site_address:$port_number/$subfolder/peerlist.php?action=new_peers", FALSE, $context, NULL, 10000));
  507. $peer_counter = 1; // Reset peer counter
  508. while($peer_counter <= 15) // Max response is 15 peers at any one time
  509. {
  510. $peer_IP = NULL;
  511. $peer_domain = NULL;
  512. $peer_subfolder = NULL;
  513. $peer_port_number = NULL;
  514. // Sort Data
  515. $peer_IP = find_string("-----IP$peer_counter=", "-----domain$peer_counter", $poll_peer);
  516. $peer_domain = find_string("-----domain$peer_counter=", "-----subfolder$peer_counter", $poll_peer);
  517. $peer_subfolder = find_string("-----subfolder$peer_counter=", "-----port_number$peer_counter", $poll_peer);
  518. $peer_port_number = find_string("-----port_number$peer_counter=", "-----", $poll_peer);
  519. if(empty($peer_port_number) == TRUE && empty($peer_subfolder) == TRUE)
  520. {
  521. // No more peers, end this loop early
  522. break;
  523. }
  524. // Check to make sure that this peer is not already in our new peer list
  525. $duplicate_check1 = mysql_result(mysql_query("SELECT * FROM `new_peers_list` WHERE `IP_Address` = '$peer_IP' LIMIT 1"),0,"port_number");
  526. $duplicate_check2 = mysql_result(mysql_query("SELECT * FROM `new_peers_list` WHERE `domain` LIKE '$peer_domain' LIMIT 1"),0,"port_number");
  527. if(empty($peer_IP) == TRUE)
  528. {
  529. //Don't have an IP address, check for duplicate domain
  530. if(empty($duplicate_check2) == TRUE)
  531. {
  532. if($my_server_domain == $peer_domain)
  533. {
  534. $duplicate_peer = TRUE;
  535. }
  536. else
  537. {
  538. // Neither IP nor Domain exist
  539. $duplicate_peer = FALSE;
  540. }
  541. }
  542. else
  543. {
  544. $duplicate_peer = TRUE;
  545. }
  546. }
  547. else
  548. {
  549. // Using IP only, is there a duplicate
  550. if(empty($duplicate_check1) == TRUE)
  551. {
  552. if($my_server_domain == $peer_domain || empty($duplicate_check2) == FALSE)
  553. {
  554. $duplicate_peer = TRUE;
  555. }
  556. else
  557. {
  558. // Check for non-private IP range
  559. if(is_private_ip($peer_IP, $allow_lan_peers) == FALSE)
  560. {
  561. // Neither IP nor Domain exist
  562. $duplicate_peer = FALSE;
  563. }
  564. else
  565. {
  566. $duplicate_peer = TRUE;
  567. }
  568. }
  569. }
  570. else
  571. {
  572. $duplicate_peer = TRUE;
  573. }
  574. }
  575. if($duplicate_peer == FALSE)
  576. {
  577. // Save only domain name if both IP and Domain exist
  578. if(empty($peer_domain) == FALSE)
  579. {
  580. $peer_IP = NULL;
  581. }
  582. // This is a fresh new peer, add it to the database list
  583. $sql = "INSERT INTO `new_peers_list` (`IP_Address` ,`domain` ,`subfolder` ,`port_number` ,`poll_failures`)
  584. VALUES ('$peer_IP', '$peer_domain', '$peer_subfolder', '$peer_port_number', '0');";
  585. if(mysql_query($sql) == TRUE)
  586. {
  587. // Subtract one from total left to find
  588. $new_peer_difference--;
  589. }
  590. }
  591. if($new_peer_difference <= 0)
  592. {
  593. // Enough new peers saved, break out of while loop early
  594. break;
  595. }
  596. $peer_counter++;
  597. } // End While loop check
  598. if($new_peer_difference <= 0)
  599. {
  600. // Enough new peers saved, break out of for loop early
  601. break;
  602. }
  603. } // End For loop check
  604. } // End New Peers vs Max New Peers check
  605. //***********************************************************************************
  606. //***********************************************************************************
  607. // Send a heartbeat to all peers in our list to make sure they are still online
  608. $sql = "SELECT * FROM `active_peer_list`";
  609. $sql_result = mysql_query($sql);
  610. $sql_num_results = mysql_num_rows($sql_result);
  611. for ($i = 0; $i < $sql_num_results; $i++)
  612. {
  613. $sql_row = mysql_fetch_array($sql_result);
  614. $ip_address = $sql_row["IP_Address"];
  615. $domain = $sql_row["domain"];
  616. $subfolder = $sql_row["subfolder"];
  617. $port_number = $sql_row["port_number"];
  618. $last_heartbeat = $sql_row["last_heartbeat"];
  619. $join_peer_list = $sql_row["join_peer_list"];
  620. $failed_sent_heartbeat = $sql_row["failed_sent_heartbeat"];
  621. //Send a challenge hash to see if a timekoin server is active
  622. $poll_challenge = rand(1, 999999);
  623. $hash_solution = hash('crc32', $poll_challenge);
  624. if(empty($domain) == TRUE)
  625. {
  626. $site_address = $ip_address;
  627. }
  628. else
  629. {
  630. $site_address = $domain;
  631. }
  632. if($port_number == 443)
  633. {
  634. $ssl = "s";
  635. }
  636. else
  637. {
  638. $ssl = NULL;
  639. }
  640. if(rand(1,3) == 2)// Randomize to avoid spamming
  641. {
  642. //Send out poll request
  643. $poll_peer = filter_sql(file_get_contents("http$ssl://$site_address:$port_number/$subfolder/peerlist.php?action=poll&challenge=$poll_challenge", FALSE, $context, NULL, 10));
  644. if($poll_peer == $hash_solution)
  645. {
  646. //Got a response from an active Timekoin server
  647. $sql = "UPDATE `active_peer_list` SET `last_heartbeat` = '" . time() . "' WHERE `IP_Address` = '$ip_address' AND `domain` = '$domain' AND `subfolder` = '$subfolder' AND `port_number` = $port_number LIMIT 1";
  648. mysql_query($sql);
  649. }
  650. else
  651. {
  652. //No response, record polling failure for future reference
  653. $failed_sent_heartbeat++;
  654. $sql = "UPDATE `active_peer_list` SET `failed_sent_heartbeat` = '$failed_sent_heartbeat' WHERE `IP_Address` = '$ip_address' AND `domain` = '$domain' AND `subfolder` = '$subfolder' AND `port_number` = $port_number LIMIT 1";
  655. mysql_query($sql);
  656. }
  657. }
  658. // Clean up active peer list by removing those that have no responded for over 5 minutes
  659. if((time() - $last_heartbeat) > 300 && $join_peer_list != 0)
  660. {
  661. // Server has been offline too long, remove it from the active peers list
  662. $sql = "DELETE FROM `active_peer_list` WHERE `IP_Address` = '$ip_address' AND `domain` = '$domain' AND `subfolder` = '$subfolder' AND `port_number` = $port_number AND `join_peer_list` = $join_peer_list LIMIT 1";
  663. mysql_query($sql);
  664. }
  665. } // End for Loop
  666. //***********************************************************************************
  667. //***********************************************************************************
  668. // Script finished, set status to 0
  669. $sql = "UPDATE `main_loop_status` SET `field_data` = '0' WHERE `main_loop_status`.`field_name` = 'peerlist_heartbeat_active' LIMIT 1";
  670. mysql_query($sql);
  671. // Record when this script finished
  672. $sql = "UPDATE `main_loop_status` SET `field_data` = '" . time() . "' WHERE `main_loop_status`.`field_name` = 'peerlist_last_heartbeat' LIMIT 1";
  673. mysql_query($sql);
  674. ?>