Ejemplo n.º 1
0
Archivo: core.py Proyecto: r4sas/kote
    async def _send_message(self, request):
        """Send message and receive response data"""
        data = b''
        await self.online.wait()

        try:
            if request.destination not in self.dest_cache:
                self.dest_cache[request.destination] = await i2plib.dest_lookup(
                            request.destination + ".b32.i2p", loop=self.loop, 
                            sam_address=self.sam_address)

            reader, writer = await i2plib.stream_connect(self.session_name, 
                    self.dest_cache[request.destination], loop=self.loop, 
                    sam_address=self.sam_address)
        except (i2plib.CantReachPeer, i2plib.InvalidKey, i2plib.Timeout, \
                i2plib.KeyNotFound, i2plib.PeerNotFound, i2plib.I2PError):
            logger.debug("Can't connect to {}".format(request.destination))
        except ConnectionError:
            logger.warning("_send_message fails: can't connect to SAM")
        else:
            writer.write(bytes(request))
            data = await reader.read(MAX_MESSAGE_LENGTH)
            writer.close()

        return data
Ejemplo n.º 2
0
Archivo: core.py Proyecto: r4sas/kote
    async def _receive_message(self, reader, writer, destination):
        with suppress(asyncio.CancelledError):
            destination = i2plib.Destination(destination.decode())
            name = self.addressbook.get_name(destination.base32)
            if not name and self.ignore_unauthorized:
                writer.close()
                return

            try:
                data = await asyncio.wait_for(reader.read(MAX_MESSAGE_LENGTH), 
                                              DEFAULT_TIMEOUT)
            except asyncio.TimeoutError:
                writer.close()
                return

            try:
                request = Message.parse(data, destination.base32)
                request.name = name
            except ValidationError as e:
                logger.warning("Invalid request: "+str(e))
                writer.close()
                return

            if request.uuid.hex in self.uuid_log:
                logger.debug("Duplicate message: "+ str(request))
                writer.write(bytes(Message(code=Message.OK)))
                writer.close()
                return

            self.uuid_log.append(request.uuid.hex)
            logger.debug("Received message: " + str(request))


            if request.code == Message.PING \
                    or request.code == Message.AUTHORIZATION:
                writer.write(bytes(Message(code=Message.OK)))
                writer.close()

                if request.code == Message.PING:
                    await self.on_ping(request)
                elif request.code == Message.AUTHORIZATION:
                    await self.on_authorization(request)

            elif request.name:
                writer.write(bytes(Message(code=Message.OK)))
                writer.close()

                if request.code == Message.PRIVATE:
                    await self.on_private_message(request)
                elif request.code == Message.PUBLIC:
                    await self.on_public_message(request)
                elif request.code == Message.UNAUTHORIZED:
                    await self.on_unauthorized(request)
            else:
                writer.write(bytes(Message(code=Message.UNAUTHORIZED)))
                writer.close()
                return

            await self._dest_online(request.destination)
Ejemplo n.º 3
0
Archivo: core.py Proyecto: r4sas/kote
 async def _dest_online(self, destination):
     """Is triggered when any Message or data is received from the destination"""
     name = self.addressbook.get_name(destination)
     if name:
         if not self.addressbook.is_online(destination):
             logger.debug("Contact becomes online "+destination)
             await self.on_contact_online(name)
             await self.senders[destination].send_stash()
         self.addressbook.set_online(destination)
Ejemplo n.º 4
0
Archivo: core.py Proyecto: r4sas/kote
    async def start(self):
        """Start all tasks"""
        self.destination = await load_destination(self.loop, self.sam_address,
                self.datadir)

        c = await load_contacts(self.loop, self.datadir)
        self.addressbook.update(c)
        logger.debug("Contacts: " + str(self.addressbook))

        for address in self.addressbook.values():
            self.senders[address] = MessageSender(self.loop, self.sender)

        self.receiver_task = self.create_task(self.receiver())
        self.pinger_task = self.create_task(self.pinger())
        self.sam_session_loop_task = self.create_task(self.sam_session_loop())
Ejemplo n.º 5
0
Archivo: core.py Proyecto: r4sas/kote
    async def sam_session_loop(self):
        """Self-healing SAM session"""
        with suppress(asyncio.CancelledError):
            while True:
                try:
                    self.session_reader, self.session_writer = await \
                            i2plib.create_session(self.session_name, 
                                destination=self.destination, 
                                sam_address=self.sam_address, loop=self.loop)
                except (i2plib.DuplicatedDest):
                    logger.error("SAM destination already exists")
                except ConnectionError:
                    logger.error("SAM API is unavailable")
                else:
                    self.online.set()
                    logger.debug("SAM session is created: " \
                            + self.destination.base32)
                    await self.session_reader.read()
                    logger.error("SAM session is dead")
                    self.online.clear()

                logger.info("Restarting SAM session in {} seconds...".format(
                    SESSION_RESTART_TIMEOUT))
                await asyncio.sleep(SESSION_RESTART_TIMEOUT)
Ejemplo n.º 6
0
Archivo: core.py Proyecto: r4sas/kote
    async def sender(self, queue):
        """Message sender task"""
        with suppress(asyncio.CancelledError):
            while True:
                await self.online.wait()
                msg = await queue.get()
                delivered = False

                for x in range(SEND_RETRIES):
                    try:
                        data = await asyncio.wait_for(self._send_message(msg), 
                                DEFAULT_TIMEOUT)
                    except asyncio.TimeoutError:
                        pass
                    else:
                        if data:
                            try:
                                resp = Message.parse(data, msg.destination)
                            except ValidationError as e:
                                logger.warning(
                                    "Invalid response from {}: {}".format(
                                                msg.destination, e))
                            else:
                                delivered = True
                                await self._dest_online(msg.destination)
                                if resp.code == Message.OK:
                                    logger.debug(str(msg) + " delivered")
                                elif resp.code == Message.UNAUTHORIZED:
                                    logger.debug(str(msg) + " unauthorized")
                                    resp.name = self.addressbook.get_name(
                                            resp.destination)
                                    await self.on_unauthorized(resp)
                            break
                        else:
                            logger.debug(str(id(msg)) + " retrying")
                            await asyncio.sleep(DEFAULT_TIMEOUT / 2)

                if delivered:
                    logger.debug(str(msg) + " delivered, retries: " + str(x))
                else:
                    self.senders[msg.destination].stash(msg)