Exemplo n.º 1
0
 def rpc_addworker(self, account, params):
     if len(params) == 2:
         username = str(params[0])
         password = str(params[1])
     else:
         return False
     
     worker = WorkerAccount(self.server, username)
     if not worker.exists():
         id = worker.create()
         worker.setData('password', password)
         return id
Exemplo n.º 2
0
 def rpc_deleteworker(self, account, params):
     if len(params) == 1:
         username = str(params[0])
     else:
         return False
     
     worker = WorkerAccount(self.server, username)
     if not worker.exists():
         return False
     
     worker.delete()
     return True
Exemplo n.º 3
0
    def rpc_deleteworker(self, account, params):
        if len(params) == 1:
            username = str(params[0])
        else:
            return False

        worker = WorkerAccount(self.server, username)
        if not worker.exists():
            return False

        worker.delete()
        return True
Exemplo n.º 4
0
 def rpc_setworkerdata(self, account, params):
     if len(params) == 3:
         username = str(params[0])
         var = str(params[1])
         value = str(params[2])
     else:
         return False
     
     worker = WorkerAccount(self.server, username)
     if not worker.exists():
         return False
     
     worker.setData(var, value)
     return True
Exemplo n.º 5
0
    def rpc_setworkerdata(self, account, params):
        if len(params) == 3:
            username = str(params[0])
            var = str(params[1])
            value = str(params[2])
        else:
            return False

        worker = WorkerAccount(self.server, username)
        if not worker.exists():
            return False

        worker.setData(var, value)
        return True
Exemplo n.º 6
0
    def render_POST(self, request):
        request.setHeader('WWW-Authenticate', 'Basic realm="Multiminer RPC"')
        request.setHeader('Content-Type', 'application/json')
        account = WorkerAccount(self.server, request.getUser())
        if not account.exists():
            loggedIn = False
        else:
            loggedIn = account.checkPassword(request.getPassword())
        if not loggedIn:
            request.setResponseCode(401)
            return rpcError(-1, 'Username/password invalid.')

        try:
            data = json.loads(request.content.read())
            id = data['id']
            method = str(data['method'])
            params = list(data['params'])
        except ValueError:
            return rpcError(-32700, 'Parse error.')
        except (KeyError, TypeError):
            return rpcError(-32600, 'Invalid request.')

        if method != 'getwork':
            if not account.getData('admin', int, 0):
                return rpcError(-2, 'Non-admins restricted to getwork only.')

        func = getattr(self, 'rpc_' + method, None)
        if func is None:
            return rpcError(-32601, 'Method not found.')

        d = defer.maybeDeferred(func, account, params)

        def callback(result):
            jsonResult = json.dumps({
                'result': result,
                'error': None,
                'id': id
            })
            request.write(jsonResult)
            request.finish()

        d.addCallback(callback)

        return server.NOT_DONE_YET
Exemplo n.º 7
0
 def rpc_getworker(self, account, params):
     if len(params) == 1:
         username = str(params[0])
     else:
         return None
     
     worker = WorkerAccount(self.server, username)
     if not worker.exists():
         return None
     
     connections = map(self.dumpConnection,
                       self.server.listAccountConnections(username))
     
     return {
             "id": worker.id,
             "username": worker.username,
             "data": worker.getAllData(),
             "connections": connections
            }
Exemplo n.º 8
0
    def rpc_getworker(self, account, params):
        if len(params) == 1:
            username = str(params[0])
        else:
            return None

        worker = WorkerAccount(self.server, username)
        if not worker.exists():
            return None

        connections = map(self.dumpConnection,
                          self.server.listAccountConnections(username))

        return {
            "id": worker.id,
            "username": worker.username,
            "data": worker.getAllData(),
            "connections": connections
        }
Exemplo n.º 9
0
 def render_POST(self, request):
     request.setHeader('WWW-Authenticate', 'Basic realm="Multiminer RPC"')
     request.setHeader('Content-Type', 'application/json')
     account = WorkerAccount(self.server, request.getUser())
     if not account.exists():
         loggedIn = False
     else:
         loggedIn = account.checkPassword(request.getPassword())
     if not loggedIn:
         request.setResponseCode(401)
         return rpcError(-1, 'Username/password invalid.')
     
     try:
         data = json.loads(request.content.read())
         id = data['id']
         method = str(data['method'])
         params = list(data['params'])
     except ValueError:
         return rpcError(-32700, 'Parse error.')
     except (KeyError, TypeError):
         return rpcError(-32600, 'Invalid request.')
     
     if method != 'getwork':
         if not account.getData('admin', int, 0):
             return rpcError(-2, 'Non-admins restricted to getwork only.')
     
     func = getattr(self, 'rpc_' + method, None)
     if func is None:
         return rpcError(-32601, 'Method not found.')
     
     d = defer.maybeDeferred(func, account, params)
     
     def callback(result):
         jsonResult = json.dumps({'result': result, 'error': None, 'id': id})
         request.write(jsonResult)
         request.finish()
     d.addCallback(callback)
     
     return server.NOT_DONE_YET
Exemplo n.º 10
0
 def cmd_LOGIN(self, username, password):
     if self.account is not None:
         return self.kick('Received duplicate LOGIN command!')
     
     self.account = WorkerAccount(self.factory, username)
     if not self.account.exists():
         loggedIn = False
     else:
         loggedIn = self.account.checkPassword(password)
     if not loggedIn:
         return self.kick('Login failed. Please check your account details.')
     
     if not self.checkClones():
         return self.kick('Connection limit exceeded!')
     
     # Login succeeded, time to send the MOTD and some work.
     motd = self.getMOTD()
     if motd is not None:
         for line in motd.splitlines():
             self.sendMsg(line)
     
     self.sendBlock()
     self.sendWork()
Exemplo n.º 11
0
    def rpc_addworker(self, account, params):
        if len(params) == 2:
            username = str(params[0])
            password = str(params[1])
        else:
            return False

        worker = WorkerAccount(self.server, username)
        if not worker.exists():
            id = worker.create()
            worker.setData('password', password)
            return id
Exemplo n.º 12
0
class WorkerConnection(MMPProtocolBase):
    """This class represents an actual worker connected to the server.
    
    The worker connects via the MMP protocol. The MMPClient class implements
    an outbound MMP connection.
    """
    
    account = None
    connectedAt = None
    
    sendingWork = False
    sentTarget = None

    commands = {
        'LOGIN':    (str, str),
        'META':     (str, str),
        'MORE':     (),
        'RESULT':   (str,),
    }
    
    def connectionMade(self):
        self.factory.workers.append(self)
        self.connectedAt = time.time()
        self.meta = {}
        self.work = []
    def connectionLost(self, reason):
        self.factory.workers.remove(self)
    
    def illegalCommand(self, cmd):
        self.kick('Invalid %s command!' % cmd)
    
    def sendMsg(self, msg):
        """Send a message to the worker.
        
        This will typically be printed on the worker's console.
        """
        self.sendLine('MSG :' + msg)
    
    def kick(self, reason=None):
        """Kicks the worker off, with an optional reason."""
        if reason is not None:
            self.sendMsg('ERROR: ' + reason)
        self.transport.loseConnection()
    
    def checkClones(self):
        """Returns False if this account's connection limit is exceeded."""
        limit = self.account.getConfig('max_clones', int, None)
        if limit is None:
            return True
        
        connections = self.factory.listAccountConnections(self.account.username)
        return len(connections) <= limit
    
    def getMOTD(self):
        """Reads the MOTD file (specified in the 'motd' config variable)"""
        motdfile = self.account.getConfig('motd')
        if motdfile is not None:
            try:
                motd = open(motdfile,'r').read()
            except IOError:
                return None
            else:
                return motd
    
    def sendBlock(self):
        if self.factory.workProvider.block is not None:
            self.sendLine('BLOCK %d' % self.factory.workProvider.block)
    
    def sendWork(self):
        """Sends work to this client, unless the client is waiting on work
        already.
        """
        if self.sendingWork or not self.account:
            return
        
        self.sendingWork = True
        
        mask = self.account.getConfig('work_mask', int, 32)
        d = self.factory.workProvider.getWork(mask)
        
        def gotWork(w):
            self.sendingWork = False
            
            if self.work and not self.work[0].isSimilarTo(w):
                self.work = []
            self.work.append(w)
            
            if self.sentTarget != w.target:
                self.sendLine('TARGET %s' % w.target.encode('hex'))
                self.sentTarget = w.target
            
            self.sendLine('WORK %s %d' % (w.data.encode('hex'), w.mask))
            
        d.addCallback(gotWork)
    
    def cmd_LOGIN(self, username, password):
        if self.account is not None:
            return self.kick('Received duplicate LOGIN command!')
        
        self.account = WorkerAccount(self.factory, username)
        if not self.account.exists():
            loggedIn = False
        else:
            loggedIn = self.account.checkPassword(password)
        if not loggedIn:
            return self.kick('Login failed. Please check your account details.')
        
        if not self.checkClones():
            return self.kick('Connection limit exceeded!')
        
        # Login succeeded, time to send the MOTD and some work.
        motd = self.getMOTD()
        if motd is not None:
            for line in motd.splitlines():
                self.sendMsg(line)
        
        self.sendBlock()
        self.sendWork()
    
    def cmd_META(self, var, value):
        # TODO: Limit the number of METAs a worker can store.
        self.meta[var] = value
    
    def cmd_MORE(self):
        if self.account:
            self.sendWork()
    
    def _result(self, hex):
        """Returns True/False depending on whether the RESULT is good."""
        try:
            result = hex.decode('hex')
        except (TypeError, ValueError):
            return False
        
        for w in self.work:
            if w.checkResult(result):
                return True
        
        return False
    
    def cmd_RESULT(self, hex):
        if not self.account:
            return
        if self._result(hex):
            # Decoding hex is safe, because self._result checks that.
            self.factory.workProvider.sendResult(hex.decode('hex'))
            self.sendLine('ACCEPTED :%s' % hex)
        else:
            self.sendLine('REJECTED :%s' % hex)