def got_interested(self, stream): if self.connector_side and self.state != SENT_NOT_INTERESTED: raise RuntimeError("INTERESTED when state != SENT_NOT_INTERESTED") if not self.connector_side and self.state != INITIAL: raise RuntimeError("INTERESTED when state != INITIAL") LOG.start("BitTorrent: uploading") self.state = UPLOADING stream.send_unchoke()
def connect_uri(self, uri=None, count=None): if not uri: address = self.conf["bittorrent.address"] port = self.conf["bittorrent.negotiate.port"] uri = "http://%s:%s/" % (address, port) LOG.start("BitTorrent: connecting to %s" % uri) ClientHTTP.connect_uri(self, uri, 1)
def connect(self, endpoint, count=1): self.connector_side = True # # In Neubot the listener does not have an infohash # and handshakes, including connector infohash, after # it receives the connector handshake. # self.infohash = self.conf["bittorrent.infohash"] LOG.start("BitTorrent: connecting to %s" % str(endpoint)) StreamHandler.connect(self, endpoint, count)
def got_unchoke(self, stream): if self.state != SENT_INTERESTED: raise RuntimeError("UNCHOKE when state != SENT_INTERESTED") else: self.state = DOWNLOADING LOG.start("BitTorrent: downloading %d bytes" % self.target_bytes) burst = self.sched_req.next() for index, begin, length in burst: stream.send_request(index, begin, length) self.inflight += 1
def connect_uri(self, uri=None, count=None): self._task = None if not uri: uri = "http://%s:9773/rendezvous" % CONFIG["agent.master"] LOG.start("* Rendezvous with %s" % uri) STATE.update("rendezvous") # We need to make just one connection ClientHTTP.connect_uri(self, uri, 1)
def connection_ready(self, stream): LOG.complete() STATE.update("negotiate") LOG.start("BitTorrent: negotiating") request = Message() body = json.dumps({"target_bytes": self.conf["bittorrent.bytes.up"]}) request.compose(method="GET", pathquery="/negotiate/bittorrent", host=self.host_header, body=body, mimetype="application/json") request["authorization"] = self.conf.get("_authorization", "") stream.send_request(request)
def connect_uri(self, uri=None, count=None): self._task = None if not privacy.allowed_to_run(): _open_browser_on_windows("privacy.html") privacy.complain() self._schedule() return if not uri: uri = "http://%s:9773/rendezvous" % CONFIG["agent.master"] LOG.start("* Rendezvous with %s" % uri) STATE.update("rendezvous") # We need to make just one connection ClientHTTP.connect_uri(self, uri, 1)
def peer_test_complete(self, stream, download_speed, rtt, target_bytes): self.success = True stream = self.http_stream # Update the downstream channel estimate estimate.DOWNLOAD = target_bytes self.my_side = { # The server will override our timestamp "timestamp": utils.timestamp(), "uuid": self.conf.get("uuid"), "internal_address": stream.myname[0], "real_address": self.conf.get("_real_address", ""), "remote_address": stream.peername[0], "privacy_informed": self.conf.get("privacy.informed", 0), "privacy_can_collect": self.conf.get("privacy.can_collect", 0), "privacy_can_publish": self.conf.get("privacy.can_publish", 0), # Upload speed measured at the server "connect_time": rtt, "download_speed": download_speed, # OS and version info "neubot_version": LibVersion.to_numeric("0.4.6-rc3"), "platform": sys.platform, } LOG.start("BitTorrent: collecting") STATE.update("collect") s = json.dumps(self.my_side) stringio = StringIO.StringIO(s) request = Message() request.compose(method="POST", pathquery="/collect/bittorrent", body=stringio, mimetype="application/json", host=self.host_header) request["authorization"] = self.conf.get("_authorization", "") stream.send_request(request)
import logging import sys if __name__ == "__main__": sys.path.insert(0, ".") from neubot.log import LOG from neubot.log import _log_info from neubot import compat if __name__ == "__main__": # Make sure the hackish name substitution works assert(logging.info == _log_info) LOG.start("Testing the in-progress feature") LOG.progress("...") LOG.progress() LOG.complete("success!") logging.info("INFO w/ logging.info") # The following should work because it should not interpolate logging.debug("DEBUG w/ logging.debug", "ciao") logging.warning("WARNING w/ logging.warning") logging.error("ERROR w/ logging.error") LOG.verbose() logging.info("INFO w/ logging.info") logging.debug("DEBUG w/ logging.debug") logging.warning("WARNING w/ logging.warning")
def update(self): if self.finished: return # # Decide whether we can transition to the next phase of # the speedtest or not. Fall through to next request if # needed, or return to the caller and rewind the stack. # ostate = self.state if not self.state: self.state = "negotiate" del QUEUE_HISTORY[:] elif self.state == "negotiate": if self.conf.get("speedtest.client.unchoked", False): LOG.complete("authorized to take the test\n") self.state = "latency" elif "speedtest.client.queuepos" in self.conf: queuepos = self.conf["speedtest.client.queuepos"] LOG.complete("waiting in queue, pos %s\n" % queuepos) STATE.update("negotiate", {"queue_pos": queuepos}) QUEUE_HISTORY.append(queuepos) elif self.state == "latency": tries = self.conf.get("speedtest.client.latency_tries", 10) if tries == 0: # Calculate average latency latency = self.conf["speedtest.client.latency"] latency = sum(latency) / len(latency) self.conf["speedtest.client.latency"] = latency # Advertise the result STATE.update("test_latency", utils.time_formatter(latency)) LOG.complete("done, %s\n" % utils.time_formatter(latency)) self.state = "download" else: self.conf["speedtest.client.latency_tries"] = tries - 1 elif self.state in ("download", "upload"): if len(self.streams) == self.conf.get("speedtest.client.nconn", 1): # Calculate average speed speed = self.conf["speedtest.client.%s" % self.state] elapsed = (max(map(lambda t: t[1], speed)) - min(map(lambda t: t[0], speed))) speed = sum(map(lambda t: t[2], speed)) / elapsed LOG.progress(".[%s,%s]." % (utils.time_formatter(elapsed), utils.speed_formatter(speed))) # # O(N) loopless adaptation to the channel w/ memory # TODO bittorrent/peer.py implements an enhanced version # of this algorithm, with a cap to the max number of # subsequent tests. In addition to that, the bittorrent # code also anticipates the update of target_bytes. # if elapsed > LO_THRESH: ESTIMATE[self.state] *= TARGET/elapsed self.conf["speedtest.client.%s" % self.state] = speed # Advertise STATE.update("test_%s" % self.state, utils.speed_formatter(speed)) LOG.complete("done, %s\n" % utils.speed_formatter(speed)) if self.state == "download": self.state = "upload" else: self.state = "collect" elif elapsed > LO_THRESH/3: del self.conf["speedtest.client.%s" % self.state] ESTIMATE[self.state] *= TARGET/elapsed else: del self.conf["speedtest.client.%s" % self.state] ESTIMATE[self.state] *= 2 else: # Wait for all pending requests to complete return elif self.state == "collect": LOG.complete() self.cleanup() return else: raise RuntimeError("Invalid state") # # Perform state transition and run the next phase of the # speedtest. Not all phases need to employ all the connection # with the upstream server. # if self.state == "negotiate": ctor, justone = ClientNegotiate, True elif self.state == "latency": ctor, justone = ClientLatency, True elif self.state == "download": ctor, justone = ClientDownload, False elif self.state == "upload": ctor, justone = ClientUpload, False elif self.state == "collect": ctor, justone = ClientCollect, True else: raise RuntimeError("Invalid state") if ostate != self.state: self.child = ctor(self.poller) self.child.configure(self.conf) self.child.host_header = self.host_header if self.state not in ("negotiate", "collect"): if ostate == "negotiate" and self.state == "latency": STATE.update("test_latency", "---", publish=False) STATE.update("test_download", "---", publish=False) STATE.update("test_upload", "---", publish=False) STATE.update("test", "speedtest") else: STATE.update(self.state) LOG.start("* speedtest: %s" % self.state) elif self.state == "negotiate": LOG.start("* speedtest: %s" % self.state) while self.streams: # # Override child Time-To-Connect (TTC) with our TTC # so for the child it's like it really performed the # connect(), not us. # self.child.rtts = self.rtts self.child.connection_ready(self.streams.popleft()) if justone: break
def connection_ready(self, stream): stream.send_bitfield(str(self.bitfield)) LOG.start("BitTorrent: receiving bitfield") if self.connector_side: self.state = SENT_INTERESTED stream.send_interested()