Example #1
0
def _pack(msg, crypto):
    return packer.pack(msg, crypto)
    async def send_message(self,
                           msg,
                           channel=ServiceChannel.Core,
                           addr: Optional[str] = None,
                           blocking: bool = True,
                           timeout: int = 5,
                           retries: int = 3) -> Optional[XStruct]:
        """
        Send message to console.

        Packing and encryption happens here.

        Args:
            msg: Unassembled message to send
            channel: Channel to send the message on,
                           Enum member of `ServiceChannel`
            addr: IP address of target console
            blocking: If set and `msg` is `Message`-packet, wait for ack
            timeout: Seconds to wait for ack, only useful if `blocking`
                           is `True`
            retries: Max retry count.

        Returns: None

        Raises:
            ProtocolError: On failure
        """
        if msg.header.pkt_type == PacketType.Message:
            msg.header(sequence_number=self._seq_mgr.next_sequence_num(),
                       target_participant_id=self.target_participant_id,
                       source_participant_id=self.source_participant_id,
                       channel_id=self._chl_mgr.get_channel_id(channel))

        if self.crypto:
            data = packer.pack(msg, self.crypto)
        else:
            data = packer.pack(msg)

        if self.address:
            addr = self.address

        if not addr:
            raise ProtocolError("No address specified in send_message")
        elif not data:
            raise ProtocolError("No data")

        if msg.header.pkt_type == PacketType.Message \
                and msg.header.flags.need_ack and blocking:
            LOGGER.debug("Sending %s message on ServiceChannel %s to %s",
                         msg.header.flags.msg_type.name,
                         channel.name,
                         addr,
                         extra={'_msg': msg})
            seqn = msg.header.sequence_number
            tries = 0
            result = None

            while tries < retries and not result:
                if tries > 0:
                    LOGGER.warning(
                        f"Message {msg.header.flags.msg_type.name} on "
                        f"ServiceChannel {channel.name} to {addr} not ack'd "
                        f"in time, attempt #{tries + 1}",
                        extra={'_msg': msg})

                await self._send(data, (addr, PORT))
                result = await self._await_ack('ack_%i' % seqn, timeout)
                tries += 1

            if result:
                return result

            raise ProtocolError("Exceeded retries")
        elif msg.header.pkt_type == PacketType.ConnectRequest:
            LOGGER.debug(f"Sending ConnectRequest to {addr}",
                         extra={'_msg': msg})

        await self._send(data, (addr, PORT))
Example #3
0
    def send_message(self,
                     msg,
                     channel=ServiceChannel.Core,
                     addr=None,
                     blocking=True,
                     timeout=5,
                     retries=3):
        """
        Send message to console.

        Packing and encryption happens here.

        Args:
            msg (:obj:`XStruct`): Unassembled message to send
            channel (:class:`ServiceChannel`): Channel to send the message on,
                           Enum member of `ServiceChannel`
            addr (str): IP address of target console
            blocking (bool): If set and `msg` is `Message`-packet, wait for ack
            timeout (int): Seconds to wait for ack, only useful if `blocking`
                           is `True`
            retries (int): Max retry count.

        Returns: None

        Raises:
            ProtocolError: On failure
        """
        if msg.header.pkt_type == PacketType.Message:
            msg.header(sequence_number=self._seq_mgr.next_sequence_num(),
                       target_participant_id=self.target_participant_id,
                       source_participant_id=self.source_participant_id,
                       channel_id=self._chl_mgr.get_channel_id(channel))

        if self.addr:
            addr = self.addr

        if self.crypto:
            data = packer.pack(msg, self.crypto)
        else:
            data = packer.pack(msg)

        if not addr:
            raise ProtocolError("No address specified in send_message")

        if not data:
            raise ProtocolError("No data")

        if msg.header.pkt_type == PacketType.Message \
                and msg.header.flags.need_ack and blocking:
            log.debug("Sending %s message on ServiceChannel %s to %s",
                      msg.header.flags.msg_type.name,
                      channel.name,
                      addr,
                      extra={'_msg': msg})
            seqn = msg.header.sequence_number
            tries = 0
            result = None

            while tries < retries and not result:
                if tries > 0:
                    log.warning(
                        "Message %s on ServiceChannel %s to %s not ack'd in time, attempt #%d",
                        msg.header.flags.msg_type.name,
                        channel.name,
                        addr,
                        tries + 1,
                        extra={'_msg': msg})

                self.socket.sendto(data, (addr, PORT))
                result = self._await_ack('ack_%i' % seqn, timeout)
                tries += 1

            if result:
                return result
            raise ProtocolError("Exceeded retries")
        elif msg.header.pkt_type == PacketType.ConnectRequest:
            log.debug("Sending ConnectRequest to %s",
                      addr,
                      extra={'_msg': msg})

        self.socket.sendto(data, (addr, PORT))