2015-06-17 23:44:20 +02:00
|
|
|
# Included modules
|
|
|
|
import os
|
Rev536, Fix stats page, Support ranged http requests for better video browser compatibility, setHashfield command, One by one send hashfield to connected peers if changed, Keep count hashfield changetime, PeerHashfield optimalizations, Wait for peers on checkmodification, Give more time to query trackers, Do not count udp trackers as error if udp disabled, Test hashfield push
2015-10-30 02:08:02 +01:00
|
|
|
import time
|
2016-04-20 23:38:22 +02:00
|
|
|
import json
|
2016-11-07 23:20:08 +01:00
|
|
|
import itertools
|
2015-06-17 23:44:20 +02:00
|
|
|
|
|
|
|
# Third party modules
|
|
|
|
import gevent
|
|
|
|
|
2015-01-17 18:50:56 +01:00
|
|
|
from Debug import Debug
|
2015-01-21 12:58:26 +01:00
|
|
|
from Config import config
|
2015-09-27 02:08:53 +02:00
|
|
|
from util import RateLimit
|
|
|
|
from util import StreamingMsgpack
|
|
|
|
from util import helper
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
from Plugin import PluginManager
|
2015-01-12 02:03:45 +01:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
FILE_BUFF = 1024 * 512
|
|
|
|
|
2015-01-12 02:03:45 +01:00
|
|
|
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
# Incoming requests
|
|
|
|
@PluginManager.acceptPlugins
|
rev125, Class statistics, OpenSSL disabled on OSX by default because of possible segfault, --disable_openssl command line parameter, Save memory on Connection, Peer and FileRequest objects using slots, Dont store modification time from the far future, Able to query modified files from peer, Allow reannounce in 30secs, Use with command in SiteStorage, Always create dir before write file, PeerCmd shell command to query specific command from peer
2015-04-29 23:12:45 +02:00
|
|
|
class FileRequest(object):
|
2015-06-17 23:44:20 +02:00
|
|
|
__slots__ = ("server", "connection", "req_id", "sites", "log", "responded")
|
|
|
|
|
|
|
|
def __init__(self, server, connection):
|
|
|
|
self.server = server
|
|
|
|
self.connection = connection
|
|
|
|
|
|
|
|
self.req_id = None
|
|
|
|
self.sites = self.server.sites
|
|
|
|
self.log = server.log
|
|
|
|
self.responded = False # Responded to the request
|
|
|
|
|
|
|
|
def send(self, msg, streaming=False):
|
|
|
|
if not self.connection.closed:
|
|
|
|
self.connection.send(msg, streaming)
|
|
|
|
|
2015-07-25 13:38:58 +02:00
|
|
|
def sendRawfile(self, file, read_bytes):
|
|
|
|
if not self.connection.closed:
|
|
|
|
self.connection.sendRawfile(file, read_bytes)
|
|
|
|
|
2015-06-17 23:44:20 +02:00
|
|
|
def response(self, msg, streaming=False):
|
|
|
|
if self.responded:
|
2016-03-06 00:55:50 +01:00
|
|
|
if config.verbose:
|
|
|
|
self.log.debug("Req id %s already responded" % self.req_id)
|
2015-06-17 23:44:20 +02:00
|
|
|
return
|
|
|
|
if not isinstance(msg, dict): # If msg not a dict create a {"body": msg}
|
|
|
|
msg = {"body": msg}
|
|
|
|
msg["cmd"] = "response"
|
|
|
|
msg["to"] = self.req_id
|
|
|
|
self.responded = True
|
|
|
|
self.send(msg, streaming=streaming)
|
|
|
|
|
|
|
|
# Route file requests
|
|
|
|
def route(self, cmd, req_id, params):
|
|
|
|
self.req_id = req_id
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
# Don't allow other sites than locked
|
|
|
|
if "site" in params and self.connection.site_lock and self.connection.site_lock not in (params["site"], "global"):
|
|
|
|
self.response({"error": "Invalid site"})
|
|
|
|
self.log.error("Site lock violation: %s != %s" % (self.connection.site_lock != params["site"]))
|
2016-03-12 23:09:26 +01:00
|
|
|
self.connection.badAction(5)
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
return False
|
2015-06-17 23:44:20 +02:00
|
|
|
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
if cmd == "update":
|
2015-06-17 23:44:20 +02:00
|
|
|
event = "%s update %s %s" % (self.connection.id, params["site"], params["inner_path"])
|
2015-07-12 20:36:46 +02:00
|
|
|
if not RateLimit.isAllowed(event): # There was already an update for this file in the last 10 second
|
2016-03-12 23:09:26 +01:00
|
|
|
time.sleep(5)
|
2015-06-17 23:44:20 +02:00
|
|
|
self.response({"ok": "File update queued"})
|
2016-11-07 23:19:17 +01:00
|
|
|
# If called more than once within 15 sec only keep the last update
|
|
|
|
RateLimit.callAsync(event, max(self.connection.bad_actions, 15), self.actionUpdate, params)
|
2015-06-17 23:44:20 +02:00
|
|
|
else:
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
func_name = "action" + cmd[0].upper() + cmd[1:]
|
|
|
|
func = getattr(self, func_name, None)
|
2016-11-07 23:19:17 +01:00
|
|
|
if cmd not in ["getFile", "streamFile"]: # Skip IO bound functions
|
|
|
|
s = time.time()
|
|
|
|
if self.connection.cpu_time > 0.5:
|
|
|
|
self.log.debug("Delay %s %s, cpu_time used by connection: %.3fs" % (self.connection.ip, cmd, self.connection.cpu_time))
|
|
|
|
time.sleep(self.connection.cpu_time)
|
|
|
|
if self.connection.cpu_time > 5:
|
|
|
|
self.connection.close()
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
if func:
|
|
|
|
func(params)
|
|
|
|
else:
|
|
|
|
self.actionUnknown(cmd, params)
|
2015-06-17 23:44:20 +02:00
|
|
|
|
2016-11-07 23:19:17 +01:00
|
|
|
if cmd not in ["getFile", "streamFile"]:
|
|
|
|
taken = time.time() - s
|
|
|
|
self.connection.cpu_time += taken
|
|
|
|
|
2015-06-17 23:44:20 +02:00
|
|
|
# Update a site file request
|
|
|
|
def actionUpdate(self, params):
|
|
|
|
site = self.sites.get(params["site"])
|
2015-07-12 20:36:46 +02:00
|
|
|
if not site or not site.settings["serving"]: # Site unknown or not serving
|
2015-06-17 23:44:20 +02:00
|
|
|
self.response({"error": "Unknown site"})
|
|
|
|
return False
|
2016-04-20 23:38:22 +02:00
|
|
|
|
2016-04-20 23:35:51 +02:00
|
|
|
if not params["inner_path"].endswith("content.json"):
|
|
|
|
self.response({"error": "Only content.json update allowed"})
|
|
|
|
return
|
2016-04-20 23:38:22 +02:00
|
|
|
|
|
|
|
content = json.loads(params["body"])
|
|
|
|
|
|
|
|
file_uri = "%s/%s:%s" % (site.address, params["inner_path"], content["modified"])
|
|
|
|
|
|
|
|
if self.server.files_parsing.get(file_uri): # Check if we already working on it
|
|
|
|
valid = None # Same file
|
|
|
|
else:
|
|
|
|
valid = site.content_manager.verifyFile(params["inner_path"], content)
|
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
if valid is True: # Valid and changed
|
2016-04-20 23:38:22 +02:00
|
|
|
self.log.info("Update for %s/%s looks valid, saving..." % (params["site"], params["inner_path"]))
|
|
|
|
self.server.files_parsing[file_uri] = True
|
|
|
|
site.storage.write(params["inner_path"], params["body"])
|
|
|
|
del params["body"]
|
2015-06-17 23:44:20 +02:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
site.onFileDone(params["inner_path"]) # Trigger filedone
|
|
|
|
|
|
|
|
if params["inner_path"].endswith("content.json"): # Download every changed file from peer
|
|
|
|
peer = site.addPeer(self.connection.ip, self.connection.port, return_peer=True) # Add or get peer
|
|
|
|
# On complete publish to other peers
|
2016-08-15 13:54:00 +02:00
|
|
|
diffs = params.get("diffs", {})
|
|
|
|
site.onComplete.once(lambda: site.publish(inner_path=params["inner_path"], diffs=diffs, limit=2), "publish_%s" % params["inner_path"])
|
2015-06-17 23:44:20 +02:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
# Load new content file and download changed files in new thread
|
2016-04-20 23:38:22 +02:00
|
|
|
def downloader():
|
|
|
|
site.downloadContent(params["inner_path"], peer=peer, diffs=params.get("diffs", {}))
|
|
|
|
del self.server.files_parsing[file_uri]
|
|
|
|
|
|
|
|
gevent.spawn(downloader)
|
|
|
|
else:
|
|
|
|
del self.server.files_parsing[file_uri]
|
2015-06-17 23:44:20 +02:00
|
|
|
|
|
|
|
self.response({"ok": "Thanks, file %s updated!" % params["inner_path"]})
|
2016-03-12 23:09:26 +01:00
|
|
|
self.connection.goodAction()
|
2015-06-17 23:44:20 +02:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
elif valid is None: # Not changed
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
if params.get("peer"):
|
|
|
|
peer = site.addPeer(*params["peer"], return_peer=True) # Add or get peer
|
|
|
|
else:
|
|
|
|
peer = site.addPeer(self.connection.ip, self.connection.port, return_peer=True) # Add or get peer
|
2015-06-17 23:44:20 +02:00
|
|
|
if peer:
|
2016-04-25 02:23:06 +02:00
|
|
|
if not peer.connection:
|
|
|
|
peer.connect(self.connection) # Assign current connection to peer
|
2016-04-27 09:45:32 +02:00
|
|
|
if params["inner_path"] in site.content_manager.contents:
|
|
|
|
peer.last_content_json_update = site.content_manager.contents[params["inner_path"]]["modified"]
|
2016-03-06 00:55:50 +01:00
|
|
|
if config.verbose:
|
|
|
|
self.log.debug(
|
|
|
|
"Same version, adding new peer for locked files: %s, tasks: %s" %
|
|
|
|
(peer.key, len(site.worker_manager.tasks))
|
|
|
|
)
|
2015-07-12 20:36:46 +02:00
|
|
|
for task in site.worker_manager.tasks: # New peer add to every ongoing task
|
2016-03-16 00:38:26 +01:00
|
|
|
if task["peers"] and not task["optional_hash_id"]:
|
2015-07-12 20:36:46 +02:00
|
|
|
# Download file from this peer too if its peer locked
|
|
|
|
site.needFile(task["inner_path"], peer=peer, update=True, blocking=False)
|
2015-06-17 23:44:20 +02:00
|
|
|
|
|
|
|
self.response({"ok": "File not changed"})
|
2016-03-12 23:09:26 +01:00
|
|
|
self.connection.badAction()
|
2015-06-17 23:44:20 +02:00
|
|
|
|
2016-03-30 23:05:43 +02:00
|
|
|
else: # Invalid sign or sha hash
|
2015-06-17 23:44:20 +02:00
|
|
|
self.log.debug("Update for %s is invalid" % params["inner_path"])
|
|
|
|
self.response({"error": "File invalid"})
|
2016-03-12 23:09:26 +01:00
|
|
|
self.connection.badAction(5)
|
2015-06-17 23:44:20 +02:00
|
|
|
|
|
|
|
# Send file content request
|
|
|
|
def actionGetFile(self, params):
|
|
|
|
site = self.sites.get(params["site"])
|
2015-07-12 20:36:46 +02:00
|
|
|
if not site or not site.settings["serving"]: # Site unknown or not serving
|
2015-06-17 23:44:20 +02:00
|
|
|
self.response({"error": "Unknown site"})
|
|
|
|
return False
|
|
|
|
try:
|
|
|
|
file_path = site.storage.getPath(params["inner_path"])
|
|
|
|
with StreamingMsgpack.FilePart(file_path, "rb") as file:
|
|
|
|
file.seek(params["location"])
|
|
|
|
file.read_bytes = FILE_BUFF
|
2015-08-16 11:51:00 +02:00
|
|
|
file_size = os.fstat(file.fileno()).st_size
|
2017-01-05 02:25:06 +01:00
|
|
|
if params["location"] > file_size:
|
|
|
|
self.connection.badAction(5)
|
|
|
|
raise Exception("Bad file location")
|
2015-09-28 00:22:27 +02:00
|
|
|
|
2015-07-12 20:36:46 +02:00
|
|
|
back = {
|
|
|
|
"body": file,
|
2015-08-16 11:51:00 +02:00
|
|
|
"size": file_size,
|
|
|
|
"location": min(file.tell() + FILE_BUFF, file_size)
|
2015-07-12 20:36:46 +02:00
|
|
|
}
|
2015-06-17 23:44:20 +02:00
|
|
|
self.response(back, streaming=True)
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
bytes_sent = min(FILE_BUFF, file_size - params["location"]) # Number of bytes we going to send
|
|
|
|
site.settings["bytes_sent"] = site.settings.get("bytes_sent", 0) + bytes_sent
|
2015-06-17 23:44:20 +02:00
|
|
|
if config.debug_socket:
|
2015-08-16 11:51:00 +02:00
|
|
|
self.log.debug("File %s at position %s sent %s bytes" % (file_path, params["location"], bytes_sent))
|
2015-06-17 23:44:20 +02:00
|
|
|
|
|
|
|
# Add peer to site if not added before
|
|
|
|
connected_peer = site.addPeer(self.connection.ip, self.connection.port)
|
2015-07-12 20:36:46 +02:00
|
|
|
if connected_peer: # Just added
|
2015-06-17 23:44:20 +02:00
|
|
|
connected_peer.connect(self.connection) # Assign current connection to peer
|
|
|
|
|
2016-11-07 23:19:33 +01:00
|
|
|
return {"bytes_sent": bytes_sent, "file_size": file_size, "location": params["location"]}
|
|
|
|
|
2015-06-17 23:44:20 +02:00
|
|
|
except Exception, err:
|
|
|
|
self.log.debug("GetFile read error: %s" % Debug.formatException(err))
|
|
|
|
self.response({"error": "File read error: %s" % Debug.formatException(err)})
|
|
|
|
return False
|
|
|
|
|
2015-07-25 13:38:58 +02:00
|
|
|
# New-style file streaming out of Msgpack context
|
|
|
|
def actionStreamFile(self, params):
|
|
|
|
site = self.sites.get(params["site"])
|
|
|
|
if not site or not site.settings["serving"]: # Site unknown or not serving
|
|
|
|
self.response({"error": "Unknown site"})
|
|
|
|
return False
|
|
|
|
try:
|
|
|
|
if config.debug_socket:
|
|
|
|
self.log.debug("Opening file: %s" % params["inner_path"])
|
|
|
|
with site.storage.open(params["inner_path"]) as file:
|
|
|
|
file.seek(params["location"])
|
2015-08-16 11:51:00 +02:00
|
|
|
file_size = os.fstat(file.fileno()).st_size
|
|
|
|
stream_bytes = min(FILE_BUFF, file_size - params["location"])
|
2017-01-05 02:25:06 +01:00
|
|
|
if stream_bytes < 0:
|
|
|
|
self.connection.badAction(5)
|
|
|
|
raise Exception("Bad file location")
|
2015-09-28 00:22:27 +02:00
|
|
|
|
2015-07-25 13:38:58 +02:00
|
|
|
back = {
|
2015-08-16 11:51:00 +02:00
|
|
|
"size": file_size,
|
|
|
|
"location": min(file.tell() + FILE_BUFF, file_size),
|
2015-07-25 13:38:58 +02:00
|
|
|
"stream_bytes": stream_bytes
|
|
|
|
}
|
|
|
|
if config.debug_socket:
|
|
|
|
self.log.debug(
|
|
|
|
"Sending file %s from position %s to %s" %
|
|
|
|
(params["inner_path"], params["location"], back["location"])
|
|
|
|
)
|
|
|
|
self.response(back)
|
|
|
|
self.sendRawfile(file, read_bytes=FILE_BUFF)
|
2015-08-16 11:51:00 +02:00
|
|
|
|
|
|
|
site.settings["bytes_sent"] = site.settings.get("bytes_sent", 0) + stream_bytes
|
2015-07-25 13:38:58 +02:00
|
|
|
if config.debug_socket:
|
2015-08-16 11:51:00 +02:00
|
|
|
self.log.debug("File %s at position %s sent %s bytes" % (params["inner_path"], params["location"], stream_bytes))
|
2015-07-25 13:38:58 +02:00
|
|
|
|
|
|
|
# Add peer to site if not added before
|
|
|
|
connected_peer = site.addPeer(self.connection.ip, self.connection.port)
|
|
|
|
if connected_peer: # Just added
|
|
|
|
connected_peer.connect(self.connection) # Assign current connection to peer
|
|
|
|
|
2016-11-07 23:19:33 +01:00
|
|
|
return {"bytes_sent": stream_bytes, "file_size": file_size, "location": params["location"]}
|
|
|
|
|
2015-07-25 13:38:58 +02:00
|
|
|
except Exception, err:
|
|
|
|
self.log.debug("GetFile read error: %s" % Debug.formatException(err))
|
|
|
|
self.response({"error": "File read error: %s" % Debug.formatException(err)})
|
|
|
|
return False
|
|
|
|
|
2015-06-17 23:44:20 +02:00
|
|
|
# Peer exchange request
|
|
|
|
def actionPex(self, params):
|
|
|
|
site = self.sites.get(params["site"])
|
2015-07-12 20:36:46 +02:00
|
|
|
if not site or not site.settings["serving"]: # Site unknown or not serving
|
2015-06-17 23:44:20 +02:00
|
|
|
self.response({"error": "Unknown site"})
|
|
|
|
return False
|
|
|
|
|
|
|
|
got_peer_keys = []
|
|
|
|
added = 0
|
2015-09-28 00:22:27 +02:00
|
|
|
|
|
|
|
# Add requester peer to site
|
|
|
|
connected_peer = site.addPeer(self.connection.ip, self.connection.port)
|
|
|
|
if connected_peer: # It was not registered before
|
2015-06-17 23:44:20 +02:00
|
|
|
added += 1
|
|
|
|
connected_peer.connect(self.connection) # Assign current connection to peer
|
|
|
|
|
2015-09-28 00:22:27 +02:00
|
|
|
# Add sent peers to site
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
for packed_address in params.get("peers", []):
|
2015-09-27 12:42:53 +02:00
|
|
|
address = helper.unpackAddress(packed_address)
|
2015-06-17 23:44:20 +02:00
|
|
|
got_peer_keys.append("%s:%s" % address)
|
2015-07-12 20:36:46 +02:00
|
|
|
if site.addPeer(*address):
|
|
|
|
added += 1
|
2015-09-28 00:22:27 +02:00
|
|
|
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
# Add sent peers to site
|
|
|
|
for packed_address in params.get("peers_onion", []):
|
|
|
|
address = helper.unpackOnionAddress(packed_address)
|
|
|
|
got_peer_keys.append("%s:%s" % address)
|
|
|
|
if site.addPeer(*address):
|
|
|
|
added += 1
|
|
|
|
|
2015-06-17 23:44:20 +02:00
|
|
|
# Send back peers that is not in the sent list and connectable (not port 0)
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
packed_peers = helper.packPeers(site.getConnectablePeers(params["need"], got_peer_keys))
|
|
|
|
|
2015-06-17 23:44:20 +02:00
|
|
|
if added:
|
|
|
|
site.worker_manager.onPeers()
|
2016-03-06 00:55:50 +01:00
|
|
|
if config.verbose:
|
|
|
|
self.log.debug(
|
|
|
|
"Added %s peers to %s using pex, sending back %s" %
|
|
|
|
(added, site, len(packed_peers["ip4"]) + len(packed_peers["onion"]))
|
|
|
|
)
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
|
|
|
|
back = {}
|
|
|
|
if packed_peers["ip4"]:
|
|
|
|
back["peers"] = packed_peers["ip4"]
|
|
|
|
if packed_peers["onion"]:
|
|
|
|
back["peers_onion"] = packed_peers["onion"]
|
|
|
|
|
|
|
|
self.response(back)
|
2015-06-17 23:44:20 +02:00
|
|
|
|
|
|
|
# Get modified content.json files since
|
|
|
|
def actionListModified(self, params):
|
|
|
|
site = self.sites.get(params["site"])
|
2015-07-12 20:36:46 +02:00
|
|
|
if not site or not site.settings["serving"]: # Site unknown or not serving
|
2015-06-17 23:44:20 +02:00
|
|
|
self.response({"error": "Unknown site"})
|
|
|
|
return False
|
2016-09-04 17:50:29 +02:00
|
|
|
modified_files = site.content_manager.listModified(params["since"])
|
2015-06-17 23:44:20 +02:00
|
|
|
|
|
|
|
# Add peer to site if not added before
|
|
|
|
connected_peer = site.addPeer(self.connection.ip, self.connection.port)
|
|
|
|
if connected_peer: # Just added
|
|
|
|
connected_peer.connect(self.connection) # Assign current connection to peer
|
|
|
|
|
|
|
|
self.response({"modified_files": modified_files})
|
|
|
|
|
2015-10-11 02:22:53 +02:00
|
|
|
def actionGetHashfield(self, params):
|
|
|
|
site = self.sites.get(params["site"])
|
|
|
|
if not site or not site.settings["serving"]: # Site unknown or not serving
|
|
|
|
self.response({"error": "Unknown site"})
|
|
|
|
return False
|
|
|
|
|
|
|
|
# Add peer to site if not added before
|
Rev536, Fix stats page, Support ranged http requests for better video browser compatibility, setHashfield command, One by one send hashfield to connected peers if changed, Keep count hashfield changetime, PeerHashfield optimalizations, Wait for peers on checkmodification, Give more time to query trackers, Do not count udp trackers as error if udp disabled, Test hashfield push
2015-10-30 02:08:02 +01:00
|
|
|
peer = site.addPeer(self.connection.ip, self.connection.port, return_peer=True)
|
|
|
|
if not peer.connection: # Just added
|
|
|
|
peer.connect(self.connection) # Assign current connection to peer
|
|
|
|
|
|
|
|
peer.time_my_hashfield_sent = time.time() # Don't send again if not changed
|
2015-10-11 02:22:53 +02:00
|
|
|
|
|
|
|
self.response({"hashfield_raw": site.content_manager.hashfield.tostring()})
|
|
|
|
|
2016-11-07 23:20:08 +01:00
|
|
|
def findHashIds(self, site, hash_ids, limit=100):
|
|
|
|
back_ip4 = {}
|
|
|
|
back_onion = {}
|
|
|
|
found = site.worker_manager.findOptionalHashIds(hash_ids, limit=limit)
|
|
|
|
|
|
|
|
for hash_id, peers in found.iteritems():
|
|
|
|
back_onion[hash_id] = list(itertools.islice((
|
|
|
|
helper.packOnionAddress(peer.ip, peer.port)
|
|
|
|
for peer in peers
|
|
|
|
if peer.ip.endswith("onion")
|
|
|
|
), 50))
|
|
|
|
back_ip4[hash_id] = list(itertools.islice((
|
|
|
|
helper.packAddress(peer.ip, peer.port)
|
|
|
|
for peer in peers
|
|
|
|
if not peer.ip.endswith("onion")
|
|
|
|
), 50))
|
|
|
|
return back_ip4, back_onion
|
|
|
|
|
2015-10-22 11:42:55 +02:00
|
|
|
def actionFindHashIds(self, params):
|
|
|
|
site = self.sites.get(params["site"])
|
2016-11-07 23:20:08 +01:00
|
|
|
s = time.time()
|
2015-10-22 11:42:55 +02:00
|
|
|
if not site or not site.settings["serving"]: # Site unknown or not serving
|
|
|
|
self.response({"error": "Unknown site"})
|
2016-03-12 23:09:26 +01:00
|
|
|
self.connection.badAction(5)
|
2015-10-22 11:42:55 +02:00
|
|
|
return False
|
|
|
|
|
2016-11-07 23:20:08 +01:00
|
|
|
event_key = "%s_findHashIds_%s_%s" % (self.connection.ip, params["site"], len(params["hash_ids"]))
|
|
|
|
if self.connection.cpu_time > 0.5 or not RateLimit.isAllowed(event_key, 60 * 5):
|
|
|
|
time.sleep(0.1)
|
|
|
|
back_ip4, back_onion = self.findHashIds(site, params["hash_ids"], limit=10)
|
|
|
|
else:
|
|
|
|
back_ip4, back_onion = self.findHashIds(site, params["hash_ids"])
|
|
|
|
RateLimit.called(event_key)
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
|
2015-10-28 01:28:29 +01:00
|
|
|
# Check my hashfield
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
if self.server.tor_manager and self.server.tor_manager.site_onions.get(site.address): # Running onion
|
|
|
|
my_ip = helper.packOnionAddress(self.server.tor_manager.site_onions[site.address], self.server.port)
|
|
|
|
my_back = back_onion
|
2016-03-21 09:43:53 +01:00
|
|
|
elif config.ip_external: # External ip defined
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
my_ip = helper.packAddress(config.ip_external, self.server.port)
|
|
|
|
my_back = back_ip4
|
|
|
|
else: # No external ip defined
|
|
|
|
my_ip = my_ip = helper.packAddress(self.server.ip, self.server.port)
|
|
|
|
my_back = back_ip4
|
|
|
|
|
2016-11-07 23:20:08 +01:00
|
|
|
my_hashfield_set = set(site.content_manager.hashfield)
|
2015-10-28 01:28:29 +01:00
|
|
|
for hash_id in params["hash_ids"]:
|
2016-11-07 23:20:08 +01:00
|
|
|
if hash_id in my_hashfield_set:
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
if hash_id not in my_back:
|
|
|
|
my_back[hash_id] = []
|
|
|
|
my_back[hash_id].append(my_ip) # Add myself
|
|
|
|
|
2016-03-06 00:55:50 +01:00
|
|
|
if config.verbose:
|
|
|
|
self.log.debug(
|
2016-11-07 23:20:08 +01:00
|
|
|
"Found: IP4: %s, Onion: %s for %s hashids in %.3fs" %
|
|
|
|
(len(back_ip4), len(back_onion), len(params["hash_ids"]), time.time() - s)
|
2016-03-06 00:55:50 +01:00
|
|
|
)
|
Rev957, Sidebar displays onion peers in graph, Sidebar display bad file retry number, Sidebar site Update/Pause/Delete, Ratelimit sidebar update, Encoded typo, Fix onion findHashId, More retry for bad files, Log file path errors, Testcase for self findhashIds, Testcase for Tor findHashId, Better Tor version parse, UiWebsocket callback on update/pause/resume/delete, Skip invalid postMessage messages
2016-03-09 00:48:57 +01:00
|
|
|
self.response({"peers": back_ip4, "peers_onion": back_onion})
|
2015-10-11 02:22:53 +02:00
|
|
|
|
Rev536, Fix stats page, Support ranged http requests for better video browser compatibility, setHashfield command, One by one send hashfield to connected peers if changed, Keep count hashfield changetime, PeerHashfield optimalizations, Wait for peers on checkmodification, Give more time to query trackers, Do not count udp trackers as error if udp disabled, Test hashfield push
2015-10-30 02:08:02 +01:00
|
|
|
def actionSetHashfield(self, params):
|
|
|
|
site = self.sites.get(params["site"])
|
|
|
|
if not site or not site.settings["serving"]: # Site unknown or not serving
|
|
|
|
self.response({"error": "Unknown site"})
|
2016-03-12 23:09:26 +01:00
|
|
|
self.connection.badAction(5)
|
Rev536, Fix stats page, Support ranged http requests for better video browser compatibility, setHashfield command, One by one send hashfield to connected peers if changed, Keep count hashfield changetime, PeerHashfield optimalizations, Wait for peers on checkmodification, Give more time to query trackers, Do not count udp trackers as error if udp disabled, Test hashfield push
2015-10-30 02:08:02 +01:00
|
|
|
return False
|
|
|
|
|
2016-04-20 23:38:22 +02:00
|
|
|
# Add or get peer
|
|
|
|
peer = site.addPeer(self.connection.ip, self.connection.port, return_peer=True, connection=self.connection)
|
Rev536, Fix stats page, Support ranged http requests for better video browser compatibility, setHashfield command, One by one send hashfield to connected peers if changed, Keep count hashfield changetime, PeerHashfield optimalizations, Wait for peers on checkmodification, Give more time to query trackers, Do not count udp trackers as error if udp disabled, Test hashfield push
2015-10-30 02:08:02 +01:00
|
|
|
if not peer.connection:
|
|
|
|
peer.connect(self.connection)
|
|
|
|
peer.hashfield.replaceFromString(params["hashfield_raw"])
|
|
|
|
self.response({"ok": "Updated"})
|
|
|
|
|
Rev571, Optional file sizes to sidebar, Download all optional files option in sidebar, Optional file number in peer stats, Delete removed or changed optional files, Auto download optional files if autodownloadoptional checked, SiteReload command, Peer use global file server if no site defined, Allow browser cache video files, Allow more keepalive connections, Gevent 1.1 ranged request bugfix, Dont sent optional files details on websocket, Remove files from workermanager tasks if no longer in bad_files, Notify local client about changes on external siteSign
2015-11-09 00:44:03 +01:00
|
|
|
def actionSiteReload(self, params):
|
|
|
|
if self.connection.ip != "127.0.0.1" and self.connection.ip != config.ip_external:
|
|
|
|
self.response({"error": "Only local host allowed"})
|
|
|
|
|
|
|
|
site = self.sites.get(params["site"])
|
|
|
|
site.content_manager.loadContent(params["inner_path"], add_bad_files=False)
|
|
|
|
site.storage.verifyFiles(quick_check=True)
|
|
|
|
site.updateWebsocket()
|
|
|
|
|
|
|
|
self.response({"ok": "Reloaded"})
|
|
|
|
|
2015-12-12 16:39:22 +01:00
|
|
|
def actionSitePublish(self, params):
|
|
|
|
if self.connection.ip != "127.0.0.1" and self.connection.ip != config.ip_external:
|
|
|
|
self.response({"error": "Only local host allowed"})
|
|
|
|
|
|
|
|
site = self.sites.get(params["site"])
|
2016-04-06 13:58:43 +02:00
|
|
|
num = site.publish(limit=8, inner_path=params.get("inner_path", "content.json"), diffs=params.get("diffs", {}))
|
2015-12-12 16:39:22 +01:00
|
|
|
|
|
|
|
self.response({"ok": "Successfuly published to %s peers" % num})
|
|
|
|
|
2015-06-17 23:44:20 +02:00
|
|
|
# Send a simple Pong! answer
|
Version 0.3.5, Rev830, Full Tor mode support with hidden services, Onion stats in Sidebar, GeoDB download fix using Tor, Gray out disabled sites in Stats page, Tor hidden service status in stat page, Benchmark sha256, Skyts tracker out expodie in, 2 new tracker using ZeroNet protocol, Keep SSL cert option between restarts, SSL Certificate pinning support for connections, Site lock support for connections, Certificate pinned connections using implicit SSL, Flood protection whitelist support, Foreign keys support for DB layer, Not support for SQL query helper, 0 length file get bugfix, Pex onion address support, Faster port testing, Faster uPnP port opening, Need connections more often on owned sites, Delay ZeroHello startup message if port check or Tor manager not ready yet, Use lockfiles to avoid double start, Save original socket on proxy monkey patching to get ability to connect localhost directly, Handle atomic write errors, Broken gevent https workaround helper, Rsa crypt functions, Plugin to Bootstrap using ZeroNet protocol
2016-01-05 00:20:52 +01:00
|
|
|
def actionPing(self, params):
|
2015-06-17 23:44:20 +02:00
|
|
|
self.response("Pong!")
|
|
|
|
|
|
|
|
# Unknown command
|
|
|
|
def actionUnknown(self, cmd, params):
|
|
|
|
self.response({"error": "Unknown command: %s" % cmd})
|
2016-03-12 23:09:26 +01:00
|
|
|
self.connection.badAction(5)
|