def _maybe_attach(self, stream): """ If we've got a custom stream-attachment instance (see set_attacher) this will ask it for the appropriate circuit. Note that we ignore .exit URIs and let Tor deal with those (by passing circuit ID 0). The stream attacher is allowed to return a Deferred which will callback with the desired circuit. You may return the special object DO_NOT_ATTACH which will cause the circuit attacher to simply ignore the stream (neither attaching it, nor telling Tor to attach it). """ if self.attacher: if stream.target_host is not None and '.exit' in stream.target_host: ## we want to totally ignore .exit URIs as these are ## used to specify a particular exit node, and trying ## to do STREAMATTACH on them will fail with an error ## from Tor anyway. txtorlog.msg("ignore attacher:", stream) return circ = IStreamAttacher(self.attacher).attach_stream( stream, self.circuits) if circ is self.DO_NOT_ATTACH: return if circ is None: self.protocol.queue_command("ATTACHSTREAM %d 0" % stream.id) else: if isinstance(circ, defer.Deferred): class IssueStreamAttach: def __init__(self, state, streamid): self.stream_id = streamid self.state = state def __call__(self, arg): circid = arg.id self.state.protocol.queue_command( "ATTACHSTREAM %d %d" % (self.stream_id, circid)) circ.addCallback(IssueStreamAttach( self, stream.id)).addErrback(log.err) else: if circ.id not in self.circuits: raise RuntimeError( "Attacher returned a circuit unknown to me.") if circ.state != 'BUILT': raise RuntimeError( "Can only attach to BUILT circuits; %d is in %s." % (circ.id, circ.state)) self.protocol.queue_command("ATTACHSTREAM %d %d" % (stream.id, circ.id))
def _maybe_attach(self, stream): """ If we've got a custom stream-attachment instance (see set_attacher) this will ask it for the appropriate circuit. Note that we ignore .exit URIs and let Tor deal with those (by passing circuit ID 0). The stream attacher is allowed to return a Deferred which will callback with the desired circuit. You may return the special object DO_NOT_ATTACH which will cause the circuit attacher to simply ignore the stream (neither attaching it, nor telling Tor to attach it). """ if self.attacher: if stream.target_host is not None and ".exit" in stream.target_host: ## we want to totally ignore .exit URIs as these are ## used to specify a particular exit node, and trying ## to do STREAMATTACH on them will fail with an error ## from Tor anyway. txtorlog.msg("ignore attacher:", stream) return circ = IStreamAttacher(self.attacher).attach_stream(stream, self.circuits) if circ is self.DO_NOT_ATTACH: return if circ is None: self.protocol.queue_command("ATTACHSTREAM %d 0" % stream.id) else: if isinstance(circ, defer.Deferred): class IssueStreamAttach: def __init__(self, state, streamid): self.stream_id = streamid self.state = state def __call__(self, arg): circid = arg.id self.state.protocol.queue_command("ATTACHSTREAM %d %d" % (self.stream_id, circid)) circ.addCallback(IssueStreamAttach(self, stream.id)).addErrback(log.err) else: if circ.id not in self.circuits: raise RuntimeError("Attacher returned a circuit unknown to me.") if circ.state != "BUILT": raise RuntimeError("Can only attach to BUILT circuits; %d is in %s." % (circ.id, circ.state)) self.protocol.queue_command("ATTACHSTREAM %d %d" % (stream.id, circ.id))