# Path: txtorcon/socks.py
# class TorSocksEndpoint(object):
#     """
#     Represents an endpoint which will talk to a Tor SOCKS port.
# 
#     These should usually not be instantiated directly, instead use
#     :meth:`txtorcon.TorConfig.socks_endpoint`.
#     """
#     # XXX host, port args should be (host, port) tuple, or
#     # IAddress-implementer?
#     def __init__(self, socks_endpoint, host, port, tls=False):
#         self._proxy_ep = socks_endpoint  # can be Deferred
#         assert self._proxy_ep is not None
#         if six.PY2 and isinstance(host, str):
#             host = unicode(host)  # noqa
#         if six.PY3 and isinstance(host, bytes):
#             host = host.decode('ascii')
#         self._host = host
#         self._port = port
#         self._tls = tls
#         self._socks_factory = None
#         self._when_address = util.SingleObserver()
# 
#     def _get_address(self):
#         """
#         Returns a Deferred that fires with the source IAddress of the
#         underlying SOCKS connection (i.e. usually a
#         twisted.internet.address.IPv4Address)
# 
#         circuit.py uses this; better suggestions welcome!
#         """
#         return self._when_address.when_fired()
# 
#     @inlineCallbacks
#     def connect(self, factory):
#         # further wrap the protocol if we're doing TLS.
#         # "pray i do not wrap the protocol further".
#         if self._tls:
#             # XXX requires Twisted 14+
#             from twisted.internet.ssl import optionsForClientTLS
#             if self._tls is True:
#                 context = optionsForClientTLS(self._host)
#             else:
#                 context = self._tls
#             tls_factory = tls.TLSMemoryBIOFactory(context, True, factory)
#             socks_factory = _TorSocksFactory(
#                 self._host, self._port, 'CONNECT', tls_factory,
#             )
#         else:
#             socks_factory = _TorSocksFactory(
#                 self._host, self._port, 'CONNECT', factory,
#             )
# 
#         self._socks_factory = socks_factory
#         # forward our address (when we get it) to any listeners
#         self._socks_factory._get_address().addBoth(self._when_address.fire)
#         # XXX isn't this just maybeDeferred()
#         if isinstance(self._proxy_ep, Deferred):
#             proxy_ep = yield self._proxy_ep
#             if not IStreamClientEndpoint.providedBy(proxy_ep):
#                 raise ValueError(
#                     "The Deferred provided as 'socks_endpoint' must "
#                     "resolve to an IStreamClientEndpoint provider (got "
#                     "{})".format(type(proxy_ep).__name__)
#                 )
#         else:
#             proxy_ep = self._proxy_ep
# 
#         # socks_proto = yield proxy_ep.connect(socks_factory)
#         proto = yield proxy_ep.connect(socks_factory)
#         wrapped_proto = yield proto.when_done()
#         if self._tls:
#             returnValue(wrapped_proto.wrappedProtocol)
#         else:
#             returnValue(wrapped_proto)
# 
# Path: txtorcon/util.py
# class SingleObserver(object):
#     """
#     A helper for ".when_*()" sort of functions.
#     """
#     _NotFired = object()
# 
#     def __init__(self):
#         self._observers = []
#         self._fired = self._NotFired
# 
#     def when_fired(self):
#         d = defer.Deferred()
#         if self._fired is not self._NotFired:
#             d.callback(self._fired)
#         else:
#             self._observers.append(d)
#         return d
# 
#     def fire(self, value):
#         if self._observers is None:
#             return  # raise RuntimeError("already fired") ?
#         self._fired = value
#         for d in self._observers:
#             d.callback(self._fired)
#         self._observers = None
#         return value  # so we're transparent if used as a callback


from twisted.web.iweb import IAgentEndpointFactory
from twisted.web.client import Agent
from twisted.internet.defer import inlineCallbacks, returnValue, Deferred
from twisted.internet.endpoints import TCP4ClientEndpoint, UNIXClientEndpoint
from zope.interface import implementer
from txtorcon.socks import TorSocksEndpoint
from txtorcon.log import txtorlog
from txtorcon.util import SingleObserver
        from txtorcon.circuit import TorCircuitEndpoint
        self._proxy_ep = SingleObserver()
        # if _proxy_ep is Deferred, but we get called twice, we must
        # remember the resolved object here
        if isinstance(tor_socks_endpoint, Deferred):
            tor_socks_endpoint.addCallback(self._set_proxy)
        else:
            self._proxy_ep.fire(tor_socks_endpoint)

    def _set_proxy(self, p):
        self._proxy_ep.fire(p)
        return p

    def endpointForURI(self, uri):
        return TorSocksEndpoint(
            self._proxy_ep.when_fired(),
            uri.host,
            uri.port,
            tls=(uri.scheme == b'https'),
        )


@implementer(IAgentEndpointFactory)
class _AgentEndpointFactoryForCircuit(object):
    def __init__(self, reactor, tor_socks_endpoint, circ):
        self._reactor = reactor
        self._socks_ep = tor_socks_endpoint
        self._circ = circ

    def endpointForURI(self, uri):
        """IAgentEndpointFactory API"""

# Path: txtorcon/socks.py
# class TorSocksEndpoint(object):
#     """
#     Represents an endpoint which will talk to a Tor SOCKS port.
# 
#     These should usually not be instantiated directly, instead use
#     :meth:`txtorcon.TorConfig.socks_endpoint`.
#     """
#     # XXX host, port args should be (host, port) tuple, or
#     # IAddress-implementer?
#     def __init__(self, socks_endpoint, host, port, tls=False):
#         self._proxy_ep = socks_endpoint  # can be Deferred
#         assert self._proxy_ep is not None
#         if six.PY2 and isinstance(host, str):
#             host = unicode(host)  # noqa
#         if six.PY3 and isinstance(host, bytes):
#             host = host.decode('ascii')
#         self._host = host
#         self._port = port
#         self._tls = tls
#         self._socks_factory = None
#         self._when_address = util.SingleObserver()
# 
#     def _get_address(self):
#         """
#         Returns a Deferred that fires with the source IAddress of the
#         underlying SOCKS connection (i.e. usually a
#         twisted.internet.address.IPv4Address)
# 
#         circuit.py uses this; better suggestions welcome!
#         """
#         return self._when_address.when_fired()
# 
#     @inlineCallbacks
#     def connect(self, factory):
#         # further wrap the protocol if we're doing TLS.
#         # "pray i do not wrap the protocol further".
#         if self._tls:
#             # XXX requires Twisted 14+
#             from twisted.internet.ssl import optionsForClientTLS
#             if self._tls is True:
#                 context = optionsForClientTLS(self._host)
#             else:
#                 context = self._tls
#             tls_factory = tls.TLSMemoryBIOFactory(context, True, factory)
#             socks_factory = _TorSocksFactory(
#                 self._host, self._port, 'CONNECT', tls_factory,
#             )
#         else:
#             socks_factory = _TorSocksFactory(
#                 self._host, self._port, 'CONNECT', factory,
#             )
# 
#         self._socks_factory = socks_factory
#         # forward our address (when we get it) to any listeners
#         self._socks_factory._get_address().addBoth(self._when_address.fire)
#         # XXX isn't this just maybeDeferred()
#         if isinstance(self._proxy_ep, Deferred):
#             proxy_ep = yield self._proxy_ep
#             if not IStreamClientEndpoint.providedBy(proxy_ep):
#                 raise ValueError(
#                     "The Deferred provided as 'socks_endpoint' must "
#                     "resolve to an IStreamClientEndpoint provider (got "
#                     "{})".format(type(proxy_ep).__name__)
#                 )
#         else:
#             proxy_ep = self._proxy_ep
# 
#         # socks_proto = yield proxy_ep.connect(socks_factory)
#         proto = yield proxy_ep.connect(socks_factory)
#         wrapped_proto = yield proto.when_done()
#         if self._tls:
#             returnValue(wrapped_proto.wrappedProtocol)
#         else:
#             returnValue(wrapped_proto)
# 
# Path: txtorcon/util.py
# class SingleObserver(object):
#     """
#     A helper for ".when_*()" sort of functions.
#     """
#     _NotFired = object()
# 
#     def __init__(self):
#         self._observers = []
#         self._fired = self._NotFired
# 
#     def when_fired(self):
#         d = defer.Deferred()
#         if self._fired is not self._NotFired:
#             d.callback(self._fired)
#         else:
#             self._observers.append(d)
#         return d
# 
#     def fire(self, value):
#         if self._observers is None:
#             return  # raise RuntimeError("already fired") ?
#         self._fired = value
#         for d in self._observers:
#             d.callback(self._fired)
#         self._observers = None
#         return value  # so we're transparent if used as a callback


# Path: txtorcon/web.py
from twisted.web.iweb import IAgentEndpointFactory
from twisted.web.client import Agent
from twisted.internet.defer import inlineCallbacks, returnValue, Deferred
from twisted.internet.endpoints import TCP4ClientEndpoint, UNIXClientEndpoint
from zope.interface import implementer
from txtorcon.socks import TorSocksEndpoint
from txtorcon.log import txtorlog
from txtorcon.util import SingleObserver
        from txtorcon.circuit import TorCircuitEndpoint

        self._proxy_ep = SingleObserver()
        # if _proxy_ep is Deferred, but we get called twice, we must
        # remember the resolved object here
        if isinstance(tor_socks_endpoint, Deferred):
            tor_socks_endpoint.addCallback(self._set_proxy)
        else:
            self._proxy_ep.fire(tor_socks_endpoint)

    def _set_proxy(self, p):
        self._proxy_ep.fire(p)
        return p

    def endpointForURI(self, uri):
        return TorSocksEndpoint(
            self._proxy_ep.when_fired(),
            uri.host,
            uri.port,
            tls=(uri.scheme == b'https'),
        )


@implementer(IAgentEndpointFactory)
class _AgentEndpointFactoryForCircuit(object):
    def __init__(self, reactor, tor_socks_endpoint, circ):
        self._reactor = reactor
        self._socks_ep = tor_socks_endpoint
        self._circ = circ

    def endpointForURI(self, uri):
        """IAgentEndpointFactory API"""

        torsocks = TorSocksEndpoint(