示例#1
0
 def __init__(self, url, root):
     self.url = url
     self.root = root
     #NOTE: setting long poll connections to not be persistent
     #This is to correct stability/memory leak issues
     self.agent = Agent(reactor, persistent=False)
     self.polling = False
示例#2
0
class LongPoller(object):
    """Polls a long poll URL, reporting any parsed work results to the
    callback function.
    """

    def __init__(self, url, root):
        self.url = url
        self.root = root
        self.agent = Agent(reactor, persistent=True)
        self.polling = False

    def start(self):
        """Begin requesting data from the LP server, if we aren't already..."""
        if self.polling:
            return
        self.polling = True

        self._request()

    def _request(self):
        if self.polling:
            d = self.agent.request(
                "GET", self.url, Headers({"Authorization": [self.root.auth], "User-Agent": [self.root.version]})
            )
            d.addBoth(self._requestComplete)

    def stop(self):
        """Stop polling. This LongPoller probably shouldn't be reused."""
        self.polling = False

    @defer.inlineCallbacks
    def _requestComplete(self, response):
        if not self.polling:
            return

        if isinstance(response, failure.Failure):
            self._request()
            return

        d = defer.Deferred()
        response.deliverBody(BodyLoader(d))
        try:
            data = yield d
        except ResponseFailed:
            self._request()
            return

        try:
            result = RPCPoller.parse(data)
        except ValueError:
            self._request()
            return
        except ServerMessage:
            exctype, value = sys.exc_info()[:2]
            self.root.runCallback("msg", str(value))
            self._request()
            return

        self._request()
        self.root.handleWork(result, True)
示例#3
0
class LongPoller(object):
    """Polls a long poll URL, reporting any parsed work results to the
    callback function.
    """
    def __init__(self, url, root):
        self.url = url
        self.root = root
        self.agent = Agent(reactor, persistent=True)
        self.polling = False

    def start(self):
        """Begin requesting data from the LP server, if we aren't already..."""
        if self.polling:
            return
        self.polling = True

        self._request()

    def _request(self):
        if self.polling:
            d = self.agent.request(
                'GET', self.url,
                Headers({
                    'Authorization': [self.root.auth],
                    'User-Agent': [self.root.version]
                }))
            d.addBoth(self._requestComplete)

    def stop(self):
        """Stop polling. This LongPoller probably shouldn't be reused."""
        self.polling = False

    @defer.inlineCallbacks
    def _requestComplete(self, response):
        if not self.polling:
            return

        if isinstance(response, failure.Failure):
            self._request()
            return

        d = defer.Deferred()
        response.deliverBody(BodyLoader(d))
        try:
            data = yield d
        except ResponseFailed:
            self._request()
            return

        try:
            result = RPCPoller.parse(data)
        except ValueError:
            self._request()
            return

        self._request()
        self.root.handleWork(result, True)
示例#4
0
 def __init__(self, root):
     self.root = root
     self.agent = Agent(reactor, persistent=True)
     self.askInterval = None
     self.askCall = None
     self.currentlyAsking = False
示例#5
0
class RPCPoller(object):
    """Polls the root's chosen bitcoind or pool RPC server for work."""

    def __init__(self, root):
        self.root = root
        self.agent = Agent(reactor, persistent=True)
        self.askInterval = None
        self.askCall = None
        self.currentlyAsking = False

    def setInterval(self, interval):
        """Change the interval at which to poll the getwork() function."""
        self.askInterval = interval
        self._startCall()

    def _startCall(self):
        self._stopCall()
        if self.askInterval:
            self.askCall = reactor.callLater(self.askInterval, self.ask)
        else:
            self.askCall = None

    def _stopCall(self):
        if self.askCall:
            try:
                self.askCall.cancel()
            except (error.AlreadyCancelled, error.AlreadyCalled):
                pass
            except:
                pass
            self.askCall = None

    def ask(self):
        """Run a getwork request immediately."""

        if self.currentlyAsking:
            return
        self.currentlyAsking = True
        self._stopCall()

        d = self.call("getwork")

        def errback(failure):
            if not self.currentlyAsking:
                return
            self.currentlyAsking = False
            if failure.check(ServerMessage):
                self.root.runCallback("msg", failure.getErrorMessage())

            self.root._failure()
            self._startCall()

        def errback_delay(x):
            reactor.callLater(0, errback, x)

        d.addErrback(errback_delay)

        def callback(x):
            if not self.currentlyAsking:
                return
            self.currentlyAsking = False
            try:
                (headers, result) = x
            except TypeError:
                return
            self.root.handleWork(result)
            self.root.handleHeaders(headers)
            self._startCall()

        # Minor bug in the #3420 patch; you can't start new requests during
        # callbacks from old ones, so this function has the reactor call it a
        # little bit later (with no artificial delay)
        def callback_delay(x):
            reactor.callLater(0, callback, x)

        d.addCallback(callback_delay)

        # since i can't fix the damn idle bug this workaround will have to do
        # this doesn't need to be cancelled, since it will just throw an
        # alreadycalled error and silently pass
        def idleFix(x):
            try:
                x.errback(failure.Failure())
            except:
                pass

        reactor.callLater(15, idleFix, d)

    @defer.inlineCallbacks
    def call(self, method, params=[]):
        """Call the specified remote function."""

        body = json.dumps({"method": method, "params": params, "id": 1})
        response = yield self.agent.request(
            "POST",
            self.root.url,
            Headers(
                {
                    "Authorization": [self.root.auth],
                    "User-Agent": [self.root.version],
                    "Content-Type": ["application/json"],
                }
            ),
            StringBodyProducer(body),
        )

        d = defer.Deferred()
        response.deliverBody(BodyLoader(d))
        data = yield d
        result = self.parse(data)

        defer.returnValue((response.headers, result))

    @classmethod
    def parse(cls, data):
        """Attempt to load JSON-RPC data."""

        response = json.loads(data)
        try:
            message = response["error"]["message"]
        except (KeyError, TypeError):
            pass
        else:
            raise ServerMessage(message)

        return response.get("result")
示例#6
0
 def __init__(self, url, root):
     self.url = url
     self.root = root
     self.agent = Agent(reactor, persistent=True)
     self.polling = False
示例#7
0
 def __init__(self, root):
     self.root = root
     self.agent = Agent(reactor, persistent=True)
     self.askInterval = None
     self.askCall = None
     self.currentlyAsking = False
示例#8
0
class RPCPoller(object):
    """Polls the root's chosen bitcoind or pool RPC server for work."""
    def __init__(self, root):
        self.root = root
        self.agent = Agent(reactor, persistent=True)
        self.askInterval = None
        self.askCall = None
        self.currentlyAsking = False

    def setInterval(self, interval):
        """Change the interval at which to poll the getwork() function."""
        self.askInterval = interval
        self._startCall()

    def _startCall(self):
        self._stopCall()
        if self.askInterval:
            self.askCall = reactor.callLater(self.askInterval, self.ask)
        else:
            self.askCall = None

    def _stopCall(self):
        if self.askCall:
            try:
                self.askCall.cancel()
            except (error.AlreadyCancelled, error.AlreadyCalled):
                pass
            except:
                pass
            self.askCall = None

    def ask(self):
        """Run a getwork request immediately."""

        if self.currentlyAsking:
            return
        self.currentlyAsking = True
        self._stopCall()

        d = self.call('getwork')

        def errback(failure):
            if not self.currentlyAsking:
                return
            self.currentlyAsking = False
            if failure.check(ServerMessage):
                self.root.runCallback('msg', failure.getErrorMessage())

            self.root._failure()
            self._startCall()

        def errback_delay(x):
            reactor.callLater(0, errback, x)

        d.addErrback(errback_delay)

        def callback(x):
            if not self.currentlyAsking:
                return
            self.currentlyAsking = False
            try:
                (headers, result) = x
            except TypeError:
                return
            self.root.handleWork(result)
            self.root.handleHeaders(headers)
            self._startCall()

        # Minor bug in the #3420 patch; you can't start new requests during
        # callbacks from old ones, so this function has the reactor call it a
        # little bit later (with no artificial delay)
        def callback_delay(x):
            reactor.callLater(0, callback, x)

        d.addCallback(callback_delay)

        #since i can't fix the damn idle bug this workaround will have to do
        #this doesn't need to be cancelled, since it will just throw an
        #alreadycalled error and silently pass
        def idleFix(x):
            try:
                x.errback(failure.Failure())
            except:
                pass

        reactor.callLater(15, idleFix, d)

    @defer.inlineCallbacks
    def call(self, method, params=[]):
        """Call the specified remote function."""

        body = json.dumps({'method': method, 'params': params, 'id': 1})
        response = yield self.agent.request(
            'POST', self.root.url,
            Headers({
                'Authorization': [self.root.auth],
                'User-Agent': [self.root.version],
                'Content-Type': ['application/json']
            }), StringBodyProducer(body))

        d = defer.Deferred()
        response.deliverBody(BodyLoader(d))
        data = yield d
        result = self.parse(data)

        defer.returnValue((response.headers, result))

    @classmethod
    def parse(cls, data):
        """Attempt to load JSON-RPC data."""

        response = json.loads(data)
        try:
            message = response['error']['message']
        except (KeyError, TypeError):
            pass
        else:
            raise ServerMessage(message)

        return response.get('result')
示例#9
0
 def __init__(self, url, root):
     self.url = url
     self.root = root
     self.agent = Agent(reactor, persistent=True)
     self.polling = False
示例#10
0
class RPCPoller(object):
    """Polls the root's chosen bitcoind or pool RPC server for work."""
    
    def __init__(self, root):
        self.root = root
        self.agent = Agent(reactor, persistent=True)
        self.askInterval = None
        self.askCall = None
        self.currentlyAsking = False
    
    def setInterval(self, interval):
        """Change the interval at which to poll the getwork() function."""
        self.askInterval = interval
        self._startCall()
    
    def _startCall(self):
        self._stopCall()
        #if self.currentlyAsking:
            #return # ask() will _startCall when it finishes
        if self.askInterval:
            self.askCall = reactor.callLater(self.askInterval, self.ask)
        else:
            self.askCall = None
    
    def _stopCall(self):
        if self.askCall:
            try:
                self.askCall.cancel()
            except (error.AlreadyCancelled, error.AlreadyCalled):
                pass
            self.askCall = None
    
    def ask(self):
        """Run a getwork request immediately."""
        
        if self.currentlyAsking:
            return
        self.currentlyAsking = True
        self._stopCall()
        
        d = self.call('getwork')
        
        def errback(failure):
            if not self.currentlyAsking:
                return
            self.currentlyAsking = False
            if failure.check(ServerMessage):
                self.root.runCallback('msg', failure.getErrorMessage())
            self.root._failure()
            self._startCall()
        def errback_delay(x): reactor.callLater(0, errback, x)
        d.addErrback(errback_delay)
        
        def callback(x):
            if not self.currentlyAsking:
                return
            self.currentlyAsking = False
            try:
                (headers, result) = x
            except TypeError:
                return
            self.root.handleWork(result)
            self.root.handleHeaders(headers)
            self._startCall()
        # Minor bug in the #3420 patch; you can't start new requests during
        # callbacks from old ones, so this function has the reactor call it a
        # little bit later (with no artificial delay)
        def callback_delay(x): reactor.callLater(0, callback, x)
        d.addCallback(callback_delay)
    
    @defer.inlineCallbacks
    def call(self, method, params=[]):
        """Call the specified remote function."""
        
        body = json.dumps({'method': method, 'params': params, 'id': 1})
        response = yield self.agent.request('POST',
            self.root.url,
            Headers({
                'Authorization': [self.root.auth],
                'User-Agent': [self.root.version],
                'Content-Type': ['application/json']
            }), StringBodyProducer(body))
        
        d = defer.Deferred()
        response.deliverBody(BodyLoader(d))
        data = yield d
        result = self.parse(data)

        defer.returnValue((response.headers, result))
    
    @classmethod
    def parse(cls, data):
        """Attempt to load JSON-RPC data."""
        
        response = json.loads(data)
        try:
            message = response['error']['message']
        except (KeyError, TypeError):
            pass
        else:
            raise ServerMessage(message)
        
        return response.get('result')
class RPCPoller(object):
    """Polls the root's chosen bitcoind or pool RPC server for work."""
    
    def __init__(self, root):
        self.root = root
        self.agent = Agent(reactor, persistent=True)
        self.askInterval = None
        self.askCall = None
        self.currentAsk = None
    
    def setInterval(self, interval):
        """Change the interval at which to poll the getwork() function."""
        self.askInterval = interval
        self._startCall()
    
    def _startCall(self):
        self._stopCall()
        if self.root.disconnected:
            return
        if self.askInterval:
            self.askCall = reactor.callLater(self.askInterval, self.ask)
        else:
            self.askCall = None
    
    def _stopCall(self):
        if self.askCall:
            try:
                self.askCall.cancel()
            except (error.AlreadyCancelled, error.AlreadyCalled):
                pass
            except:
                pass
            self.askCall = None

    def ask(self):
        """Run a getwork request immediately."""
        
        if self.currentAsk and not self.currentAsk.called:
             return
        self._stopCall()

        startTime = time()
        self.currentAsk = self.call('getwork', timeout=15.0)
        
        def errback(failure):
            try:
                if failure.check(ServerMessage):
                    self.root.runCallback('msg', failure.getErrorMessage())
                else:
                    self.root.runCallback('debug', failure.getErrorMessage())
                    
                self.root._failure()
            finally:
                self._startCall()
            
        def errback_delay(x): reactor.callLater(0, errback, x)
        self.currentAsk.addErrback(errback_delay)
        
        def callback(x):
            try:
                try:
                    headers, result, metaData = x
                except TypeError:
                    return
                endTime = time()

                self.root.recordGetworkTime(startTime, endTime)

                self.root.handleWork(result, headers, metaData)
                self.root.handleHeaders(headers)
            finally:
                self._startCall()
        # Minor bug in the #3420 patch; you can't start new requests during
        # callbacks from old ones, so this function has the reactor call it a
        # little bit later (with no artificial delay)
        def callback_delay(x): reactor.callLater(0, callback, x)
        self.currentAsk.addCallback(callback_delay)
    
    @defer.inlineCallbacks
    def call(self, method, params=[], timeout=None):
        """Call the specified remote function."""
        
        body = json.dumps({'method': method, 'params': params, 'id': 1})
        headers = {
                'Authorization': [self.root.auth],
                'User-Agent': [self.root.version],
                'Content-Type': ['application/json']
            }

        if method == 'getwork':
            headers['X-Mining-Hashrate'] = [self.root.getMiningHashrate()]

            miningExtensions = self.root.handler.getMiningExtensions()
            if miningExtensions is not None and len(miningExtensions) > 0:
                headers['X-Mining-Extensions'] = [' '.join(miningExtensions)]

        startTime = time()
        response = yield self.agent.request('POST',
            self.root.url, Headers(headers), StringBodyProducer(body))
        
        d = defer.Deferred()
        if timeout:
            def cancelDeferred():
                try:
                    d.errback(error.TimeoutError())
                except defer.AlreadyCalledError: pass
            reactor.callLater(timeout, cancelDeferred)
        response.deliverBody(BodyLoader(d))
        endTime = time()
        data = yield d
        result = self.parse(data)

        metaData = {}
        metaData['receivedAt'] = endTime
        metaData['duration'] = endTime - startTime

        defer.returnValue((response.headers, result, metaData))
    
    @classmethod
    def parse(cls, data):
        """Attempt to load JSON-RPC data."""
        
        response = json.loads(data)
        try:
            message = response['error']['message']
        except (KeyError, TypeError):
            pass
        else:
            raise ServerMessage(message)
        
        return response.get('result')
class LongPoller(object):
    """Polls a long poll URL, reporting any parsed work results to the
    callback function.
    """
    
    def __init__(self, url, root):
        self.url = url
        self.root = root
        #NOTE: setting long poll connections to not be persistent
        #This is to correct stability/memory leak issues
        self.agent = Agent(reactor, persistent=False)
        self.polling = False
    
    def start(self):
        """Begin requesting data from the LP server, if we aren't already..."""
        if self.polling:
            return
        self.polling = True
        self._request()
        
    def _request(self):
        if self.polling:
            d = self.agent.request('GET', self.url,
                Headers({
                    'Authorization': [self.root.auth],
                    'User-Agent': [self.root.version]
                }))
            d.addBoth(self._requestComplete)
    
    def stop(self):
        """Stop polling. This LongPoller probably shouldn't be reused."""
        self.polling = False
    
    @defer.inlineCallbacks
    def _requestComplete(self, response):
        try:
            if not self.polling:
                return
        
            if isinstance(response, failure.Failure):
                return
            
            d = defer.Deferred()
            response.deliverBody(BodyLoader(d))
            try:
                data = yield d
            except ResponseFailed:
                return
            
            try:
                result = RPCPoller.parse(data)
                headers = response.headers
            except ValueError:
                return
            except ServerMessage:
                exctype, value = sys.exc_info()[:2]
                self.root.runCallback('msg', str(value))
                return
        
        finally:
            self._request()

        self.root.handleWork(result, headers, None, pushed=True)