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
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
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
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
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
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
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 }
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 }
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
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 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
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)