2021-02-02 06:58:06 +00:00
|
|
|
"""Onionr - Private P2P Communication.
|
|
|
|
|
|
|
|
Torgossip client
|
|
|
|
|
|
|
|
Create streams to random peers
|
|
|
|
"""
|
2021-02-08 01:52:12 +00:00
|
|
|
import sys
|
2021-02-06 06:35:18 +00:00
|
|
|
from base64 import b32encode
|
2021-02-05 22:16:10 +00:00
|
|
|
from os import path
|
2021-02-11 21:03:41 +00:00
|
|
|
from time import sleep
|
2021-02-05 22:16:10 +00:00
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
from random import SystemRandom
|
|
|
|
|
2021-02-06 06:35:18 +00:00
|
|
|
import socks as socket
|
2021-02-13 20:22:07 +00:00
|
|
|
from stem import SocketClosed
|
2021-02-06 06:35:18 +00:00
|
|
|
|
2021-02-05 22:16:10 +00:00
|
|
|
from netcontroller.torcontrol.onionserviceonline import service_online_recently
|
|
|
|
from netcontroller.torcontrol import torcontroller
|
2021-02-11 21:03:41 +00:00
|
|
|
import logger
|
2021-02-05 22:16:10 +00:00
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
from .peerdb import TorGossipPeers
|
2021-02-06 06:35:18 +00:00
|
|
|
from stem.control import Controller
|
2021-02-09 23:02:19 +00:00
|
|
|
sys.path.insert(0, path.dirname(path.realpath(__file__)))
|
2021-02-08 01:52:12 +00:00
|
|
|
|
|
|
|
from commands import GossipCommands
|
2021-02-11 21:03:41 +00:00
|
|
|
|
|
|
|
from clientfuncs import download_blocks
|
2021-02-13 20:22:07 +00:00
|
|
|
from constants import HOSTNAME_FILE
|
2021-02-02 06:58:06 +00:00
|
|
|
"""
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
2021-02-11 21:03:41 +00:00
|
|
|
def client_funcs(shared_state, socket_pool):
|
|
|
|
controller = torcontroller.get_controller()
|
2021-02-05 22:16:10 +00:00
|
|
|
|
2021-02-11 21:03:41 +00:00
|
|
|
def _client_pool(shared_state, socket_pool: dict):
|
|
|
|
peer_db: 'TorGossipPeers' = shared_state.get_by_string('TorGossipPeers')
|
|
|
|
socks_port = shared_state.get_by_string('NetController').socksPort
|
2021-02-05 22:16:10 +00:00
|
|
|
|
2021-02-11 21:03:41 +00:00
|
|
|
peers = peer_db.get_highest_score_peers(20)
|
|
|
|
SystemRandom().shuffle(peers)
|
2021-02-05 22:16:10 +00:00
|
|
|
|
2021-02-11 21:03:41 +00:00
|
|
|
for peer in peers:
|
2021-02-13 20:22:07 +00:00
|
|
|
peer = peer[0]
|
2021-02-11 21:03:41 +00:00
|
|
|
if peer in socket_pool:
|
|
|
|
continue
|
2021-02-13 20:22:07 +00:00
|
|
|
p_encoded = b32encode(peer).decode().lower() + ".onion"
|
|
|
|
if not service_online_recently(controller, p_encoded):
|
2021-02-11 21:03:41 +00:00
|
|
|
continue
|
|
|
|
s = socket.socksocket()
|
|
|
|
s.set_proxy(
|
|
|
|
socket.SOCKS5, '127.0.0.1', socks_port, rdns=True)
|
|
|
|
try:
|
2021-02-15 09:11:16 +00:00
|
|
|
s.connect(
|
2021-02-13 20:22:07 +00:00
|
|
|
(p_encoded, 2021))
|
2021-02-15 09:11:16 +00:00
|
|
|
socket_pool[peer] = s
|
|
|
|
logger.info(f"[TorGossip] Connected to {p_encoded}", terminal=True)
|
2021-02-05 22:16:10 +00:00
|
|
|
|
2021-02-11 21:03:41 +00:00
|
|
|
except socket.GeneralProxyError:
|
|
|
|
s.close()
|
2021-02-08 01:52:12 +00:00
|
|
|
|
2021-02-06 06:35:18 +00:00
|
|
|
|
2021-02-11 21:03:41 +00:00
|
|
|
def client_loop(shared_state, socket_pool):
|
|
|
|
sleep_t = 60
|
|
|
|
block_db = shared_state.get_by_string('SafeDB')
|
|
|
|
peer_db = shared_state.get_by_string('TorGossipPeers')
|
2021-02-06 06:35:18 +00:00
|
|
|
|
2021-02-11 21:03:41 +00:00
|
|
|
while True:
|
|
|
|
if not socket_pool:
|
2021-02-13 20:22:07 +00:00
|
|
|
try:
|
|
|
|
_client_pool(shared_state, socket_pool)
|
|
|
|
except SocketClosed: # Probably shutting down, or tor crashed
|
|
|
|
sleep(1)
|
|
|
|
continue
|
2021-02-11 21:03:41 +00:00
|
|
|
peers = list(socket_pool)
|
|
|
|
SystemRandom().shuffle(peers)
|
|
|
|
try:
|
|
|
|
peer = peers[0]
|
2021-02-15 09:11:16 +00:00
|
|
|
print(peer)
|
2021-02-11 21:03:41 +00:00
|
|
|
except IndexError:
|
|
|
|
logger.error(
|
|
|
|
"There are no known TorGossip peers." +
|
2021-02-13 20:22:07 +00:00
|
|
|
f" Sleeping for {sleep_t}s",
|
2021-02-11 21:03:41 +00:00
|
|
|
terminal=True)
|
|
|
|
sleep(sleep_t)
|
|
|
|
continue
|
2021-02-15 09:11:16 +00:00
|
|
|
try:
|
|
|
|
download_blocks(socket_pool[peer], 0, 'txt')
|
|
|
|
except BrokenPipeError:
|
|
|
|
del socket_pool[peer]
|
2021-02-08 07:32:31 +00:00
|
|
|
|
2021-02-11 21:03:41 +00:00
|
|
|
_client_pool(shared_state, socket_pool)
|
|
|
|
client_loop(shared_state, socket_pool)
|
2021-02-08 07:32:31 +00:00
|
|
|
|
2021-02-05 22:16:10 +00:00
|
|
|
|
2021-02-11 21:03:41 +00:00
|
|
|
def _add_bootstrap_peers(peer_db: 'TorGossipPeers'):
|
2021-02-13 20:22:07 +00:00
|
|
|
# If we have peers, ignore encrypt mark in db
|
|
|
|
if len(peer_db.db.db_conn.keys()) > 1:
|
2021-02-11 21:03:41 +00:00
|
|
|
return
|
2021-02-13 20:22:07 +00:00
|
|
|
with open(HOSTNAME_FILE, "rb") as hf:
|
|
|
|
our_host = b32encode(hf.read()).decode().lower()
|
2021-02-11 21:03:41 +00:00
|
|
|
bootstap_peers = path.dirname(path.realpath(__file__)) + "/bootstrap.txt"
|
|
|
|
with open(bootstap_peers, 'r') as bs_peers:
|
|
|
|
peers = bs_peers.read().split(',')
|
2021-02-15 09:11:16 +00:00
|
|
|
try:
|
|
|
|
peers.remove(our_host)
|
|
|
|
except ValueError:
|
|
|
|
pass
|
2021-02-11 21:03:41 +00:00
|
|
|
for peer in peers:
|
|
|
|
try:
|
|
|
|
peer_db.db.get(peer)
|
|
|
|
except KeyError:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
continue
|
|
|
|
if peer:
|
|
|
|
peer_db.add_peer(peer)
|
2021-02-02 23:24:35 +00:00
|
|
|
|
2021-02-02 06:58:06 +00:00
|
|
|
|
2021-02-08 01:52:12 +00:00
|
|
|
def start_client(shared_state):
|
|
|
|
# add boot strap peers to db if we need peers
|
|
|
|
_add_bootstrap_peers(shared_state.get_by_string('TorGossipPeers'))
|
|
|
|
# create and fill pool of sockets to peers (over tor socks)
|
|
|
|
socket_pool = {}
|
2021-02-11 21:03:41 +00:00
|
|
|
client_funcs(shared_state, socket_pool)
|