def set(self, payload, address): message = '' if payload[0] == 'request': value = self.relay(payload[1], payload[4], payload[6]) or '' if not value: self.data[payload[4]] = payload[6] result = [ 'response', 'set', self.queue.status(), 'key', payload[4], 'value', payload[6] ] message = encode_bencode(result) self.deliver(message, address, identifier=payload[2]) dispatch_status('set', 'response', 'to', address[1]) elif payload[0] == 'relay': value = '' if payload[4] in self.data: self.data[payload[4]] = payload[6] value = payload[6] result = [ 'relay', 'set', self.record, 'key', payload[4], 'value', value ] message = encode_bencode(result) self.transmit(message, address) dispatch_status('set', 'relay', 'to', address[1]) return message
def get(self, payload, address): message = '' if payload[0] == 'request': value = self.data.get(payload[4], '') if not value: value = self.relay( payload[1], payload[4]) or '' # returns empty string if result is None result = [ 'response', 'get', self.queue.status(), 'key', payload[4], 'value', value ] message = encode_bencode(result) self.deliver(message, address, identifier=payload[2]) dispatch_status('get', 'response', 'to', address[1]) elif payload[0] == 'relay': value = self.data.get(payload[4], '') result = [ 'relay', 'get', self.record, 'key', payload[4], 'value', value ] message = encode_bencode(result) self.transmit(message, address) dispatch_status('get', 'relay', 'to', address[1]) return message
def get(self, payload, address): message = '' if payload[0] == 'request': value = self.data.get(payload[4], '') if not value: value = self.relay(payload[1], payload[4]) result = [ 'response', 'get', payload[2], 'key', payload[4], 'value', value, 'status', self.egress.status() ] message = encode_bencode(result) self.deliver(message, address, identifier=payload[2]) dispatch_status('get', 'response', 'to', address[1]) elif payload[0] == 'relay-request': value = self.data.get(payload[4], '') result = [ 'relay-response', 'get', self.identifier, 'key', payload[4], 'value', value ] message = encode_bencode(result) self.transmit(message, address) dispatch_status('get', 'relay-response', 'to', address[1])
def exit(self): payload = ['request', 'exit', str(self.identifier)] message = encode_bencode(payload) self.broadcast(message) self.end = True sys.exit(0)
def reset(self): payload = ['request', 'reset', str(self.identifier)] message = encode_bencode(payload) self.broadcast(message) self.identifier = 0 self.activity = {target: 0 for target in self.targets}
def reset(self): payload = ['request', 'reset', str(self.counter)] message = encode_bencode(payload) for target in self.targets: address = (NODE_IP, target) self.send(message, address, drop_probability=0) self.counter = 0 self.status = {target: 0 for target in self.targets}
def status(self): payload = ['request', 'status', str(self.identifier)] message = encode_bencode(payload) self.broadcast(message) time.sleep(0.025) if not self.activity: return None for key, value in self.activity.iteritems(): sys.stderr.write(str(key) + ': ' + str(value) + '\n')
def execute(self, command): if command[0] == 'status': if os.getenv('BALANCER_DEBUG'): sys.stderr.write(str(dt.now()) + ' INFO status broadcast\n') self.broadcast() elif command[0] == 'reset': if os.getenv('BALANCER_DEBUG'): sys.stderr.write(str(dt.now()) + ' WARN database reset\n') self.reset() elif command[0] in ['get', 'set']: key = command[1] value = '' if command[0] == 'get' else command[2] payload = ['request', command[0], self.counter, 'key', key, 'value', value] message = encode_bencode(payload) target = self.choose() if os.getenv('BALANCER_DEBUG'): dispatch_status(payload[1], payload[0], 'to', target) attempt = 0 while attempt < 3: if os.getenv('BALANCER_DEBUG'): sys.stderr.write(str(dt.now()) + ' INFO attempt ' + str(attempt + 1) + ' of 3\n') increment = True if attempt == 0 else False # only increment if 1st attempt address = (NODE_IP, target) self.send(message, address, increment=increment) try: self.sock.settimeout(1) response, address = self.sock.recvfrom(1024) if os.getenv('BALANCER_DEBUG'): dispatch_status(command[0], 'response', 'from', target) result = decode_bencode(response) output = result[6] + '\n' if command[0] == 'get' else 'success!\n' self.status[target] = result[2] if os.getenv('EXAMPLE'): activity = [self.status[target] for target in self.targets] sys.stderr.write(str(activity)[1:-1] + '\n') break sys.stderr.write(output) break except socket.timeout: if os.getenv('BALANCER_DEBUG'): sys.stderr.write(str(dt.now()) + ' WARN timeout\n') attempt += 1 if attempt == 3 and not os.getenv('EXAMPLE'): sys.stderr.write('failed!\n')
def status(self, address): if not self.data: sys.stderr.write(str(dt.now()) + ' WARN database empty\n') return None sys.stderr.write(str(dt.now()) + ' INFO database contents start\n') for key, value in self.data.iteritems(): sys.stderr.write(key + ': ' + value + '\n') sys.stderr.write(str(dt.now()) + ' INFO database contents end\n') result = ['response', 'status', self.queue.status()] message = encode_bencode(result) self.sock.sendto(message, address) dispatch_status('status', 'response', 'to', address[1])
def get(self, command, send=True): target = self.choose() if os.getenv('BALANCER_DEBUG'): dispatch_status('get', 'request', 'to', target) payload = ['request', 'get', self.identifier, 'key', command[1]] message = encode_bencode(payload) address = (NODE_IP, target) if send: result = self.send(message, address, identifier=payload[2]) if not os.getenv('EXAMPLE'): sys.stderr.write(result + '\n') return message
def relay(self, task, key, value=''): payload = [ 'relay-request', task, str(self.identifier), 'key', key, 'value', value ] message = encode_bencode(payload) for peer in self.peers: address = (NODE_IP, peer) self.transmit(message, address) dispatch_status(task, 'relay-request', 'to', peer) time.sleep(0.01) if key in self.outcome.data: return self.outcome.get(key) return ''
def relay(self, task, key, value=''): ''' Sends message to all nodes to find specific key ''' payload = ['relay', task, str(self.record), 'key', key, 'value', value] message = encode_bencode(payload) for peer in self.peers: self.transmit(message, (NODE_IP, peer)) dispatch_status(payload[1], payload[0], 'to', peer) try: self.sock.settimeout(self.timeout) response, address = self.sock.recvfrom(1024) dispatch_status(payload[1], payload[0], 'from', peer) result = decode_bencode(response) if result[6]: return result[6] except socket.timeout: sys.stderr.write(str(dt.now()) + ' WARN timeout\n')
def broadcast(self): payload = ['request', 'status', str(self.counter)] message = encode_bencode(payload) for target in self.targets: address = (NODE_IP, target) self.send(message, address, drop_probability=0) try: self.sock.settimeout(1) response, address = self.sock.recvfrom(1024) result = decode_bencode(response) self.status[target] = result[2] except socket.timeout: pass if not self.status: return None for key, value in self.status.iteritems(): sys.stderr.write(str(key) + ': ' + str(value) + '\n')
def heartbeat(self, address): result = ['response', 'status', self.egress.status()] message = encode_bencode(result) self.deliver(message, address, drop_probability=0)
def test_encode_bencode(self): assert encode_bencode(None) == "" assert encode_bencode("") == "0:" assert encode_bencode([]) == "le" assert encode_bencode({}) == "de" assert encode_bencode(1) == "i1e" assert encode_bencode(-1) == "i-1e" assert encode_bencode(0) == "i0e" assert encode_bencode("foo") == "3:foo" assert encode_bencode([1]) == "li1ee" assert encode_bencode(["foo"]) == "l3:fooe" assert encode_bencode([1, "foo"]) == "li1e3:fooe" assert encode_bencode({"foo": 1}) == "d3:fooi1ee" assert encode_bencode([1, ["foo"]]) == "li1el3:fooee" assert encode_bencode({"foo": [1]}) == "d3:fooli1eee" assert encode_bencode([{"foo": 1}]) == "ld3:fooi1eee" assert encode_bencode({"foo": {"bar": "baz"}}) == "d3:food3:bar3:bazee"