def handle_recv(self, pair): station, packet = pair message = PIAMessage() stream = StreamIn(packet.payload, self.settings) while not stream.eof(): peek = stream.peek(stream.available()) if all(x == 0xFF for x in peek): break message = message.copy() if not self.encoder.decode(stream, message): return if message.flags & 0x10: message.payload = zlib.decompress(message.payload) if station.id is None: station.id = message.station_id elif station.id != message.station_id: logger.error("Received message with wrong station id") return self.messages.append((station, message))
def decode(self, data): data = self.check_signature(data) if data is None: logger.error("Invalid packet signature") return False stream = StreamIn(data, self.settings) if stream.u32() != 0x32AB9864: logger.error("Invalid packet identifier") return False if self.settings.get("pia.header_version") > 0: byte = stream.u8() encrypted = byte >> 7 version = byte & 0x7F if version != self.settings.get("pia.header_version"): logger.error("Unexpected packet version: %i", version) return False else: encryption = stream.u8() if encryption not in [1, 2]: logger.error("Invalid encryption mode") return False encrypted = encryption == 2 self.connection_id = stream.u8() self.sequence_id = stream.u16() if self.settings.get("pia.header_version") == 0: self.session_timer = stream.u16() self.rtt_timer = stream.u16() if self.settings.get( "pia.encryption_method") == EncryptionMethod.AES_GCM: self.nonce = stream.u64() self.signature = stream.read(16) payload = stream.read(stream.available()) if encrypted: payload = self.decrypt(payload) if payload is None: return False self.payload = payload return True