def coerce_to_int(x): if isinstance(x, (int, long)): return x elif len(x) == 40: return big_endian_to_int(x.decode('hex')) else: return big_endian_to_int(x)
def decode_int64(v): return big_endian_to_int(v)
def decode_int(v): '''decodes and integer from serialization''' if len(v) > 0 and v[0] == '\x00': raise Exception("No leading zero bytes allowed for integers") return big_endian_to_int(v)
def recv_find_node(self, nodeid, payload, mdc): node = self.get_node(nodeid) log.debug('<<< find_node', remoteid=node) assert len(payload[0]) == kademlia.k_id_size / 8 target = rlp.big_endian_to_int(payload[0]) self.kademlia.recv_find_node(node, target)
def decode_frame(self, buffer): """ w/o encryption peak into buffer for frame_size return None if buffer is not long enough to decode frame """ if len(buffer) < Frame.header_size: return None, buffer def d16(data): return struct.unpack('>I', '\x00\x00' + data)[0] def garbage_collect(protocol_id): """ chunked packets of a sub protocol are send in order thus if a new frame_0 of a subprotocol is received others must be removed """ for sid, packet in self.chunked_buffers.items(): if packet.protocol_id == protocol_id: del self.chunked_buffers[sid] # header: frame-size || header-data || padding # frame-size: 3-byte integer size of frame, big endian encoded frame_size = struct.unpack('>I', '\x00' + buffer[:3])[0] # FIXME: frames are calculated with MACs, which we don't have yet real_no_mac_frame_size = frame_size - 16 - 32 remain = buffer[real_no_mac_frame_size:] if len(buffer) < real_no_mac_frame_size: return None, buffer buffer = buffer[:real_no_mac_frame_size] # END FIXME header_data = rlp.decode(buffer[3:Frame.header_size]) # normal, chunked-n: rlp.list(protocol-type[, sequence-id]) # chunked-0: rlp.list(protocol-type, sequence-id, total-packet-size) if len(header_data) == 3: chunked_0 = True # total-packet-size: < 2**32 total_payload_size = struct.unpack('>I', header_data[2])[0] else: chunked_0 = False total_payload_size = None # protocol-type: < 2**16 protocol_id = d16(header_data[0]) # sequence-id: < 2**16 (this value is optional for normal frames) if len(header_data) > 1: sequence_id = d16(header_data[1]) else: sequence_id = None # build packet body_offset = Frame.header_size if sequence_id in self.chunked_buffers: # body chunked-n: packet-data || padding packet = self.chunked_buffers.pop(sequence_id) packet.payload += buffer[body_offset:] if packet.total_payload_size == len(packet.payload): del packet.total_payload_size return packet, remain self.chunked_buffers[sequence_id + 1] = packet else: # body normal, chunked-0: rlp(packet-type) [|| rlp(packet-data)] || padding cmd_id = rlp.big_endian_to_int(rlp.decode(buffer[body_offset])) packet = Packet(protocol_id=protocol_id, cmd_id=cmd_id, payload=rlp.decode(buffer[body_offset + 1:])) if chunked_0: garbage_collect(protocol_id) assert sequence_id packet.total_payload_size = total_payload_size self.chunked_buffers[sequence_id + 1] = packet else: # normal return packet, remain return None, remain # for chunked, not finished data