Example #1
0
    def _recv_bin32_header(self, timeout):
        '''
        Receive a header with 32 bit CRC.
        '''
        header = []
        mine = 0
        for x in xrange(0, 5):
            char = self._recv(timeout)
            if char is TIMEOUT:
                return 0, False
            else:
                mine = self.calc_crc32(chr(char), mine)
                header.append(char)

        # Read their crc
        rcrc  = self._recv(timeout)
        rcrc |= self._recv(timeout) << 0x08
        rcrc |= self._recv(timeout) << 0x10
        rcrc |= self._recv(timeout) << 0x18

        log.debug('My CRC = %08x, theirs = %08x' % (mine, rcrc))
        if mine != rcrc:
            log.error('Invalid CRC32 in header')
            return 0, False
        else:
            return 5, header
Example #2
0
    def _recv_32_data(self, timeout):
        char = 0
        data = []
        mine = 0
        while char < 0x100:
            char = self._recv(timeout)
            if char is TIMEOUT:
                return TIMEOUT, ''
            elif char < 0x100:
                mine = self.calc_crc32(chr(char & 0xff), mine)
                data.append(chr(char))

        # Calculate our crc, unescape the sub_frame_kind
        sub_frame_kind = char ^ ZDLEESC
        mine = self.calc_crc32(chr(sub_frame_kind), mine)

        # Read their crc
        rcrc = self._recv(timeout)
        rcrc |= self._recv(timeout) << 0x08
        rcrc |= self._recv(timeout) << 0x10
        rcrc |= self._recv(timeout) << 0x18

        log.debug('My CRC = %08x, theirs = %08x' % (mine, rcrc))
        if mine != rcrc:
            log.error('Invalid CRC32')
            return timeout, ''
        else:
            return sub_frame_kind, ''.join(data)
Example #3
0
    def _recv_hex_header(self, timeout):
        '''
        Receive a header with HEX encoding.
        '''
        header = []
        mine = 0
        for x in xrange(0, 5):
            char = self._recv_hex(timeout)
            if char is TIMEOUT:
                return TIMEOUT
            mine = self.calc_crc16(chr(char), mine)
            header.append(char)

        # Read their crc
        char = self._recv_hex(timeout)
        if char is TIMEOUT:
            return TIMEOUT
        rcrc = char << 0x08
        char = self._recv_hex(timeout)
        if char is TIMEOUT:
            return TIMEOUT
        rcrc |= char

        log.debug('My CRC = %04x, theirs = %04x' % (mine, rcrc))
        if mine != rcrc:
            log.error('Invalid CRC16 in receiving HEX header')
            return 0, False

        # Read to see if we receive a carriage return
        char = self.getc(1, timeout)
        if char == '\r':
            # Expect a second one (which we discard)
            self.getc(1, timeout)

        return 5, header
Example #4
0
    def _recv_32_data(self, timeout):
        char = 0
        data = []
        mine = 0
        while char < 0x100:
            char = self._recv(timeout)
            if char is TIMEOUT:
                return TIMEOUT, ''
            elif char < 0x100:
                mine = self.calc_crc32(chr(char & 0xff), mine)
                data.append(chr(char))

        # Calculate our crc, unescape the sub_frame_kind
        sub_frame_kind = char ^ ZDLEESC
        mine = self.calc_crc32(chr(sub_frame_kind), mine)

        # Read their crc
        rcrc  = self._recv(timeout)
        rcrc |= self._recv(timeout) << 0x08
        rcrc |= self._recv(timeout) << 0x10
        rcrc |= self._recv(timeout) << 0x18

        log.debug('My CRC = %08x, theirs = %08x' % (mine, rcrc))
        if mine != rcrc:
            log.error('Invalid CRC32')
            return timeout, ''
        else:
            return sub_frame_kind, ''.join(data)
Example #5
0
    def _recv_bin32_header(self, timeout):
        '''
        Receive a header with 32 bit CRC.
        '''
        header = []
        mine = 0
        for x in xrange(0, 5):
            char = self._recv(timeout)
            if char is TIMEOUT:
                return 0, False
            else:
                mine = self.calc_crc32(chr(char), mine)
                header.append(char)

        # Read their crc
        rcrc = self._recv(timeout)
        rcrc |= self._recv(timeout) << 0x08
        rcrc |= self._recv(timeout) << 0x10
        rcrc |= self._recv(timeout) << 0x18

        log.debug('My CRC = %08x, theirs = %08x' % (mine, rcrc))
        if mine != rcrc:
            log.error('Invalid CRC32 in header')
            return 0, False
        else:
            return 5, header
Example #6
0
    def _recv_16_data(self, timeout):
        char = 0
        data = []
        mine = 0
        while char < 0x100:
            char = self._recv(timeout)
            if char is INVDATA:
                return INVDATA, b''
            elif char is TIMEOUT:
                log.error('Invalid b16 data timeout: %d' % len(data))
                return TIMEOUT, b''
            elif char is ZCAN:
                return ZCAN, b''
            elif char < 0x100:
                mine = self.calc_crc16(char & 0xff, mine)
                #log.info("%02x"%char)
                data.append(bytes([char]))

        # Calculate our crc, unescape the sub_frame_kind
        sub_frame_kind = char ^ ZDLEESC
        mine = self.calc_crc16(sub_frame_kind, mine)
        #log.info("ch:0x%02x,crc:0x%08x"%(sub_frame_kind,mine))
        # Read their crc
        rcrc = self._recv(timeout) << 0x08
        rcrc |= self._recv(timeout)

        if mine != rcrc:
            log.error('Invalid b16 data My CRC = %08x, theirs = %08x, len:%d' %
                      (mine, rcrc, len(data)))
            return INVDATA, b''
        else:
            return sub_frame_kind, b''.join(data)
Example #7
0
    def _recv_bin32_header(self, timeout):
        '''
        Receive a header with 32 bit CRC.
        '''
        header = []
        mine = 0
        for x in range(0, 5):
            char = self._recv(timeout)
            if char is TIMEOUT:
                return 0, header
            else:
                mine = self.calc_crc32(bytes([char]), mine)
                header.append(char)

        # Read their crc
        rcrc = self._recv(timeout)
        rcrc |= self._recv(timeout) << 0x08
        rcrc |= self._recv(timeout) << 0x10
        rcrc |= self._recv(timeout) << 0x18

        if mine != rcrc:
            log.error('Invalid b32 header CRC = %08x, theirs = %08x' %
                      (mine, rcrc))
            return 0, header
        else:
            return 5, header
Example #8
0
    def _recv_hex_header(self, timeout):
        '''
        Receive a header with HEX encoding.
        '''
        header = []
        mine = 0
        for x in xrange(0, 5):
            char = self._recv_hex(timeout)
            if char is TIMEOUT:
                return TIMEOUT
            mine = self.calc_crc16(chr(char), mine)
            header.append(char)

        # Read their crc
        char = self._recv_hex(timeout)
        if char is TIMEOUT:
            return TIMEOUT
        rcrc = char << 0x08
        char = self._recv_hex(timeout)
        if char is TIMEOUT:
            return TIMEOUT
        rcrc |= char

        log.debug('My CRC = %04x, theirs = %04x' % (mine, rcrc))
        if mine != rcrc:
            log.error('Invalid CRC16 in receiving HEX header')
            return 0, False

        # Read to see if we receive a carriage return
        char = self.getc(1, timeout)
        if char == '\r':
            # Expect a second one (which we discard)
            self.getc(1, timeout)

        return 5, header
Example #9
0
    def _recv_32_data(self, timeout):
        char = 0
        data = []
        mine = 0
        while char < 0x100:
            char = self._recv(timeout)
            if char is TIMEOUT:
                return TIMEOUT, ''
            elif char < 0x100:
                mine = self.calc_crc32(bytes([char & 0xff]), mine)
                data.append(bytes([char]))

        # Calculate our crc, unescape the sub_frame_kind
        sub_frame_kind = char ^ ZDLEESC
        mine = self.calc_crc32(bytes([sub_frame_kind]), mine)

        # Read their crc
        rcrc = self._recv(timeout)
        rcrc |= self._recv(timeout) << 0x08
        rcrc |= self._recv(timeout) << 0x10
        rcrc |= self._recv(timeout) << 0x18

        if mine != rcrc:
            log.error('Invalid b32 data My CRC = %08x, theirs = %08x len:%d' %
                      (mine, rcrc, len(data)))
            return timeout, b''
        else:
            return sub_frame_kind, b''.join(data)
Example #10
0
    def _wait_recv(self, error_count, retry, timeout):
        '''
        Waits for a <NAK> or <CRC> before starting the transmission.

        Return <NAK> or <CRC> on success, ``False`` in case of failure
        '''
        # Initialize protocol
        cancel = 0
        # Loop until the first character is a control character (NAK, CRC) or
        # we reach the retry limit
        while True:
            char = self.getc(1)
            print char ;
            if char:
                if char in [NAK, CRC]:
                    print "char is NAK or CRC"
                    return char
                elif char == CAN:
                    # Cancel at two consecutive cancels
                    if cancel:
                        log.error(error.ABORT_RECV_CAN_CAN)
                        self.abort(timeout=timeout)
                        return False
                    else:
                        log.debug(error.DEBUG_RECV_CAN)
                        cancel = 1
                else:
                    # Ignore the rest
                    pass

            error_count += 1
            if error_count >= retry:
                self.abort(timeout=timeout)
                return False
Example #11
0
    def _wait_recv(self, error_count, timeout):
        '''
        Waits for a <NAK> or <CRC> before starting the transmission.

        Return <NAK> or <CRC> on success, ``False`` in case of failure
        '''
        # Initialize protocol
        cancel = 0
        # Loop until the first character is a control character (NAK, CRC) or
        # we reach the retry limit
        while True:
            char = self.getc(1)
            if char:
                if char in [NAK, CRC]:
                    return char
                elif char == CAN:
                    # Cancel at two consecutive cancels
                    if cancel:
                        log.error(error.ABORT_RECV_CAN_CAN)
                        self.abort(timeout=timeout)
                        return False
                    else:
                        log.debug(error.DEBUG_RECV_CAN)
                        cancel = 1
                else:
                    # Ignore the rest
                    pass

            error_count += 1
            if error_count >= retry:
                self.abort(timeout=timeout)
                return False
Example #12
0
    def _send_stream(self, stream, crc_mode, retry=16, timeout=0):
        '''
        Sends a stream according to the given protocol dialect:

            >>> stream = file('/etc/issue', 'rb')
            >>> print modem.send(stream)
            True

        Return ``True`` on success, ``False`` in case of failure.
        '''

        # Get packet size for current protocol
        packet_size = PACKET_SIZE.get(self.protocol, 128)

        # ASSUME THAT I'VE ALREADY RECEIVED THE INITIAL <CRC> OR <NAK>
        # SO START DIRECTLY WITH STREAM TRANSMISSION
        sequence = 1
        error_count = 0

        while True:
            data = stream.read(packet_size)
            # Check if we're done sending
            if not data:
                break

            # Select optimal packet size when using YMODEM
            if self.protocol == PROTOCOL_YMODEM:
                packet_size = (len(data) <= 128) and 128 or 1024

            # Align the packet
            data = data.ljust(packet_size, b'\x00')

            # Calculate CRC or checksum
            crc = crc_mode and self.calc_crc16(data) or \
                self.calc_checksum(data)

            # SENDS PACKET WITH CRC
            if not self._send_packet(sequence, data, packet_size, crc_mode,
                                     crc, error_count, retry, timeout):
                log.error(error.ERROR_SEND_PACKET)
                return False

            # Next sequence
            sequence = (sequence + 1) % 0x100

        # STREAM FINISHED, SEND EOT
        log.debug(error.DEBUG_SEND_EOT)
        if self._send_eot(error_count, retry, timeout):
            return True
        else:
            log.error(error.ERROR_SEND_EOT)
            return False
Example #13
0
    def _send_stream(self, stream, crc_mode, retry=16, timeout=0):
        '''
        Sends a stream according to the given protocol dialect:

            >>> stream = file('/etc/issue', 'rb')
            >>> print modem.send(stream)
            True

        Return ``True`` on success, ``False`` in case of failure.
        '''

        # Get packet size for current protocol
        packet_size = PACKET_SIZE.get(self.protocol, 128)

        # ASSUME THAT I'VE ALREADY RECEIVED THE INITIAL <CRC> OR <NAK>
        # SO START DIRECTLY WITH STREAM TRANSMISSION
        sequence = 1
        error_count = 0

        while True:
            data = stream.read(packet_size)
            # Check if we're done sending
            if not data:
                break

            # Select optimal packet size when using YMODEM
            if self.protocol == PROTOCOL_YMODEM:
                packet_size = (len(data) <= 128) and 128 or 1024

            # Align the packet
            data = data.ljust(packet_size, '\x00')

            # Calculate CRC or checksum
            crc = crc_mode and self.calc_crc16(data) or \
                self.calc_checksum(data)

            # SENDS PACKET WITH CRC
            if not self._send_packet(sequence, data, packet_size, crc_mode,
                crc, error_count, retry, timeout):
                log.error(error.ERROR_SEND_PACKET)
                return False

            # Next sequence
            sequence = (sequence + 1) % 0x100

        # STREAM FINISHED, SEND EOT
        log.debug(error.DEBUG_SEND_EOT)
        if self._send_eot(error_count, retry, timeout):
            return True
        else:
            log.error(error.ERROR_SEND_EOT)
            return False
Example #14
0
    def _send_packet(self, sequence, data, packet_size, crc_mode, crc,
                     error_count, retry, timeout):
        '''
        Sends one single packet of data, appending the checksum/CRC. It retries
        in case of errors and wait for the <ACK>.

        Return ``True`` on success, ``False`` in case of failure.
        '''
        start_char = SOH if packet_size == 128 else STX
        while True:
            self.putc(start_char)
            self.putc(sequence.to_bytes(1, 'big'))
            self.putc((0xff - sequence).to_bytes(1, 'big'))
            self.putc(data)
            if crc_mode:
                self.putc((crc >> 8).to_bytes(1, 'big'))
                self.putc((crc & 0xff).to_bytes(1, 'big'))
            else:
                # Send CRC or checksum
                self.putc((crc).to_bytes(1, 'big'))

            # Wait for the <ACK>
            char = self.getc(1, timeout)
            if char == ACK:
                # Transmission of the character was successful
                return True

            if char in [None, NAK]:
                error_count += 1
                if error_count >= retry:
                    # Excessive amounts of retransmissions requested
                    self.error(error.ABORT_ERROR_LIMIT)
                    self.abort(timeout=timeout)
                    return False
                continue

            # Protocol error
            log.error(error.ERROR_PROTOCOL)
            error_count += 1
            if error_count >= retry:
                log.error(error.ABORT_ERROR_LIMIT)
                self.abort(timeout=timeout)
                return False
Example #15
0
    def _send_packet(self, sequence, data, packet_size, crc_mode, crc,
        error_count, retry, timeout):
        '''
        Sends one single packet of data, appending the checksum/CRC. It retries
        in case of errors and wait for the <ACK>.

        Return ``True`` on success, ``False`` in case of failure.
        '''
        start_char = SOH if packet_size == 128 else STX
        while True:
            self.putc(start_char)
            self.putc(chr(sequence))
            self.putc(chr(0xff - sequence))
            self.putc(data)
            if crc_mode:
                self.putc(chr(crc >> 8))
                self.putc(chr(crc & 0xff))
            else:
                # Send CRC or checksum
                self.putc(chr(crc))

            # Wait for the <ACK>
            char = self.getc(1, timeout)
            if char == ACK:
                # Transmission of the character was successful
                return True

            if char in [None, NAK]:
                error_count += 1
                if error_count >= retry:
                    # Excessive amounts of retransmissions requested
                    self.error(error.ABORT_ERROR_LIMIT)
                    self.abort(timeout=timeout)
                    return False
                continue

            # Protocol error
            log.error(error.ERROR_PROTOCOL)
            error_count += 1
            if error_count >= retry:
                log.error(error.ABORT_ERROR_LIMIT)
                self.abort(timeout=timeout)
                return False
Example #16
0
    def send(self, stream, retry=16, timeout=60, quiet=0):
        '''
        Send a stream via the XMODEM protocol.

            >>> stream = file('/etc/issue', 'rb')
            >>> print modem.send(stream)
            True

        Returns ``True`` upon succesful transmission or ``False`` in case of
        failure.
        '''

        # initialize protocol
        error_count = 0
        crc_mode = 0
        cancel = 0
        while True:
            char = self.getc(1)
            if char:
                if char == NAK:
                    crc_mode = 0
                    break
                elif char == CRC:
                    crc_mode = 1
                    break
                elif char == CAN:
                    # We abort if we receive two consecutive <CAN> bytes
                    if cancel:
                        return False
                    else:
                        cancel = 1
                else:
                    log.error(error.ERROR_EXPECT_NAK_CRC % ord(char))

            error_count += 1
            if error_count >= retry:
                log.error(error.ABORT_ERROR_LIMIT)
                self.abort(timeout=timeout)
                return False

        # Start sending the stream
        return self._send_stream(stream, crc_mode, retry, timeout)
Example #17
0
    def send(self, stream, retry=16, timeout=60, quiet=0):
        '''
        Send a stream via the XMODEM protocol.

            >>> stream = file('/etc/issue', 'rb')
            >>> print modem.send(stream)
            True

        Returns ``True`` upon succesful transmission or ``False`` in case of
        failure.
        '''

        # initialize protocol
        error_count = 0
        crc_mode = 0
        cancel = 0
        while True:
            char = self.getc(1)
            if char:
                if char == NAK:
                    crc_mode = 0
                    break
                elif char == CRC:
                    crc_mode = 1
                    break
                elif char == CAN:
                    # We abort if we receive two consecutive <CAN> bytes
                    if cancel:
                        return False
                    else:
                        cancel = 1
                else:
                    log.error(error.ERROR_EXPECT_NAK_CRC % ord(char))

            error_count += 1
            if error_count >= retry:
                log.error(error.ABORT_ERROR_LIMIT)
                self.abort(timeout=timeout)
                return False

        # Start sending the stream
        return self._send_stream(stream, crc_mode, retry, timeout)
Example #18
0
    def _send_eot(self, error_count, retry, timeout):
        '''
        Sends an <EOT> code. It retries in case of errors and wait for the
        <ACK>.

        Return ``True`` on success, ``False`` in case of failure.
        '''
        while True:
            self.putc(EOT)
            # Wait for <ACK>
            char = self.getc(1, timeout)
            if char == ACK:
                # <EOT> confirmed
                return True
            else:
                error_count += 1
                if error_count >= retry:
                    # Excessive amounts of retransmissions requested,
                    # abort transfer
                    log.error(error.ABORT_ERROR_LIMIT)
                    return False
Example #19
0
    def _send_eot(self, error_count, retry, timeout):
        '''
        Sends an <EOT> code. It retries in case of errors and wait for the
        <ACK>.

        Return ``True`` on success, ``False`` in case of failure.
        '''
        while True:
            self.putc(EOT)
            # Wait for <ACK>
            char = self.getc(1, timeout)
            if char == ACK:
                # <EOT> confirmed
                return True
            else:
                error_count += 1
                if error_count >= retry:
                    # Excessive amounts of retransmissions requested,
                    # abort transfer
                    log.error(error.ABORT_ERROR_LIMIT)
                    return False
Example #20
0
    def _recv_bin16_header(self, timeout):
        '''
        Recieve a header with 16 bit CRC.
        '''
        header = []
        mine = 0
        for x in xrange(0, 5):
            char = self._recv(timeout)
            if char is TIMEOUT:
                return 0, False
            else:
                mine = self.calc_crc16(chr(char), mine)
                header.append(char)

        rcrc = self._recv(timeout) << 0x08
        rcrc |= self._recv(timeout)

        if mine != rcrc:
            log.error('Invalid CRC16 in header')
            return 0, False
        else:
            return 5, header
Example #21
0
    def _recv_bin16_header(self, timeout):
        '''
        Recieve a header with 16 bit CRC.
        '''
        header = []
        mine = 0
        for x in xrange(0, 5):
            char = self._recv(timeout)
            if char is TIMEOUT:
                return 0, False
            else:
                mine = self.calc_crc16(chr(char), mine)
                header.append(char)

        rcrc  = self._recv(timeout) << 0x08
        rcrc |= self._recv(timeout)

        if mine != rcrc:
            log.error('Invalid CRC16 in header')
            return 0, False
        else:
            return 5, header
Example #22
0
    def _recv_bin16_header(self, timeout):
        '''
        Recieve a header with 16 bit CRC.
        '''
        header = []
        mine = 0
        for x in range(0, 5):
            char = self._recv(timeout)
            if char is TIMEOUT:
                return 0, header
            else:
                mine = self.calc_crc16(char, mine)
                header.append(char)

        rcrc = self._recv(timeout) << 0x08
        rcrc |= self._recv(timeout)

        if mine != rcrc:
            log.error('Invalid b16 header CRC = %04x, theirs = %04x' %
                      (mine, rcrc))
            return 0, header
        else:
            return 5, header
Example #23
0
    def _recv_hex_header(self, timeout):
        '''
        Receive a header with HEX encoding.
        '''
        header = []
        mine = 0
        for x in range(0, 5):
            char = self._recv_hex(timeout)
            if char is TIMEOUT:
                return TIMEOUT, header
            mine = self.calc_crc16(char, mine)
            header.append(char)

        # Read their crc
        char = self._recv_hex(timeout)
        if char is TIMEOUT:
            return TIMEOUT, header
        rcrc = char << 0x08
        char = self._recv_hex(timeout)
        if char is TIMEOUT:
            return TIMEOUT, header
        rcrc |= char

        if mine != rcrc:
            log.error('Invalid hex header My CRC = %04x, theirs = %04x' %
                      (mine, rcrc))
            return 0, header

        # Read to see if we receive a carriage return
        char = self._recv_raw(timeout)
        if (char & 0x7F) == ord(b'\r'):
            # Expect a second one (which we discard)
            self._recv_raw(timeout)
        else:
            print('hex end:0x%2x' % char)
        return 5, header
Example #24
0
    def send(self, stream, retry=16, timeout=60):
        '''
        Send a stream via the XMODEM1K protocol.

            >>> stream = file('/etc/issue', 'rb')
            >>> print modem.send(stream)
            True

        Returns ``True`` upon succesful transmission or ``False`` in case of
        failure.
        '''

        # initialize protocol
        error_count = 0
        crc_mode = 0
        cancel = 0
        while True:
            char = self.getc(1)
            if char:
                if char == NAK:
                    crc_mode = 0
                    break
                elif char == CRC:
                    crc_mode = 1
                    break
                elif char == CAN:
                    if cancel:
                        log.debug(error.DEBUG_RECV_CAN)
                        return False
                    else:
                        log.error(error.ABORT_RECV_CAN_CAN)
                        cancel = 1
                else:
                    log.error(error.ERROR_EXPECT_NAK_CRC % ord(char))

            error_count += 1
            if error_count >= retry:
                self.abort(timeout=timeout)
                return False

        if self._send_stream(stream, crc_mode, retry, timeout):
            return True
        else:
            log.error(error.ABORT_SEND_STREAM)
            return False
    def send(self, stream, retry=16, timeout=60):
        '''
        Send a stream via the XMODEM1K protocol.

            >>> stream = file('/etc/issue', 'rb')
            >>> print modem.send(stream)
            True

        Returns ``True`` upon succesful transmission or ``False`` in case of
        failure.
        '''

        # initialize protocol
        error_count = 0
        crc_mode = 0
        cancel = 0
        while True:
            char = self.getc(1)
            if char:
                if char == NAK:
                    crc_mode = 0
                    break
                elif char == CRC:
                    crc_mode = 1
                    break
                elif char == CAN:
                    if cancel:
                        log.debug(error.DEBUG_RECV_CAN)
                        return False
                    else:
                        log.error(error.ABORT_RECV_CAN_CAN)
                        cancel = 1
                else:
                    log.error(error.ERROR_EXPECT_NAK_CRC % ord(char))

            error_count += 1
            if error_count >= retry:
                self.abort(timeout=timeout)
                return False

        if self._send_stream(stream, crc_mode, retry, timeout):
            return True
        else:
            log.error(error.ABORT_SEND_STREAM)
            return False
Example #26
0
    def _send_packet(self, sequence, data, packet_size, crc_mode, crc,
        error_count, retry, timeout):
        print('sequence', sequence)
        '''
        Sends one single packet of data, appending the checksum/CRC. It retries
        in case of errors and wait for the <ACK>.

        Return ``True`` on success, ``False`` in case of failure.
        '''
        start_char = SOH if packet_size == 128 else STX
        while True:
            self.putc(start_char)
            self.putc(bytes([sequence]))
            self.putc(bytes([0xff - sequence]))
            self.putc(data)
            if crc_mode:
                self.putc(bytes([crc >> 8]))
                self.putc(bytes([crc & 0xff]))
            else:
                # Send CRC or checksum
                self.putc(bytes([crc]))

            # Wait for the <ACK>
            char = self.getc(1, 0.1)
            # TODO: Due to the delay of the serial, there may be a miss of ACK,
            # so the timeout would send back CRC. We force it to ACK manually.
            char = ACK
            if char == ACK:
                # Transmission of the character was successful
                return True

            if char in [None, NAK]:
                error_count += 1
                if error_count >= retry:
                    # Excessive amounts of retransmissions requested
                    log.error(error.ABORT_ERROR_LIMIT)
                    return False
                continue

            # Protocol error
            log.error(error.ERROR_PROTOCOL)
            error_count += 1
            if error_count >= retry:
                log.error(error.ABORT_ERROR_LIMIT)
                return False
Example #27
0
    def _recv_file(self, basedir, timeout, retry):
        log.info('About to receive a file in %s' % (basedir, ))
        pos = 0

        # Read the data subpacket containing the file information
        kind, data = self._recv_data(pos, timeout)
        pos += len(data)
        if kind not in [FRAMEOK, ENDOFFRAME]:
            if not kind is TIMEOUT:
                # File info metadata corrupted
                self._send_znak(pos, timeout)
            return False

        # We got the file name
        part = data.split(b'\x00')
        filename = part[0]
        if not isinstance(basedir, bytes):
            basedir = bytes(basedir, "utf-8")
        filepath = os.path.join(basedir, os.path.basename(filename))
        fp = open(filepath, 'w+b')
        if not fp:
            log.error("open file [%s] err" % filepath)
            return False
        part = part[1].replace(b'  ', b' ').split(b' ')
        log.info('Meta %r' % (part, ))
        size = int(part[0])
        # Date is octal (!?)
        date = datetime.datetime.fromtimestamp(int(
            part[1])) if len(part) > 1 and part[1] else b''
        # We ignore mode and serial number, whatever, dude :-)

        log.info('kind:%d Receiving file "%s" with size %d, mtime %s' % \
            (kind, filename, size, date))

        # Receive contents
        start = time.time()
        kind = ZFILE
        total_size = 0
        continues_no_file_data_received_cnt = 0
        while continues_no_file_data_received_cnt < retry:
            kind, chunk_size = self._recv_file_data(kind, fp.tell(), fp,
                                                    timeout)
            print('size %08d/%08d, %d' % (total_size, size, chunk_size))

            if chunk_size <= 0:
                continues_no_file_data_received_cnt += 1
            else:
                total_size += chunk_size
                continues_no_file_data_received_cnt = 0

            if size > 0 and total_size >= size and continues_no_file_data_received_cnt > 3:
                break
            if kind == ZEOF:
                break

        # End of file
        speed = (total_size / (time.time() - start))

        if kind == ZEOF:
            log.info('Receiving file "%s" done at %.02f bps' %
                     (filename, speed))
        else:
            log.info('Receiving file "%s" Error at %.02f bps' %
                     (filename, speed))
        # Update file metadata
        fp.close()
        #mtime = time.mktime(date.timetuple()) #TODO JJJ
        #os.utime(filepath, (mtime, mtime))    #TODO JJJ
        return True
Example #28
0
    def send(self, filenames, retry=100, timeout=60):
        '''
        Send one or more files via the YMODEM protocol.

            >>> print modem.send('*.txt')
            True

        Returns ``True`` upon succesful transmission or ``False`` in case of
        failure.
        '''
	print "start sending..."
        # Get a list of files to send
        #filenames = glob.glob(pattern)
        if not filenames:
            return True
	print "after globbing.."
 
        # initialize protocol
        error_count = 0
        crc_mode = 0
        start_char = self._wait_recv(error_count, retry, timeout)
        if start_char:
            crc_mode = 1 if (start_char == CRC) else 0
        else:
            log.error(error.ABORT_PROTOCOL)
            # Already aborted
            return False
	print "StartChar received.."
        for filename in filenames:
            print "start filename: ", filename
            # Send meta data packet
            sequence = 0
            error_count = 0
            # REQUIREMENT 1,1a,1b,1c,1d
            print "s 1"
	
            data = ''.join([os.path.basename(filename), '\x00'])
            print "s 2"

            #log.debug(error.DEBUG_START_FILE % (filename,))
            print "s 3"
            # Pick a suitable packet length for the filename
            packet_size = 128 if (len(data) < 128) else 1024
            print "send filename"

            # Packet padding
            data = data.ljust(packet_size, '\0')
            print "s 4"

            # Calculate checksum
            crc = self.calc_crc16(data) if crc_mode else self.calc_checksum(data)
            print "s 5"

            # Emit packet
            if not self._send_packet(sequence, data, packet_size, crc_mode,
                crc, error_count, retry, timeout):
                self.abort(timeout=timeout)
                return False
            print "wating for CRC"

            # Wait for <CRC> before transmitting the file contents
            error_count = 0
            if not self._wait_recv(error_count, timeout):
                self.abort(timeout)
                return False

            filedesc = open(filename, 'rb')

            # AT THIS POINT
            # - PACKET 0 WITH METADATA TRANSMITTED
            # - INITIAL <CRC> OR <NAK> ALREADY RECEIVED
            print "wating for CRC"

            if not self._send_stream(filedesc, crc_mode, retry, timeout):
                #log.error(error.ABORT_SEND_STREAM)
                return False

            # AT THIS POINT
            # - FILE CONTENTS TRANSMITTED
            # - <EOT> TRANSMITTED
            # - <ACK> RECEIVED
            print "stream send"

            filedesc.close()
            # WAIT A <CRC> BEFORE NEXT FILE
            error_count = 0
            if not self._wait_recv(error_count,  retry, timeout):
                log.error(error.ABORT_INIT_NEXT)
                # Already aborted
                return False

        # End of batch transmission, send NULL file name
        sequence = 0
        error_count = 0
        packet_size = 128
        data = '\x00' * packet_size
        crc = self.calc_crc16(data) if crc_mode else self.calc_checksum(data)

        # Emit packet
        if not self._send_packet(sequence, data, packet_size, crc_mode, crc,
            error_count, retry, timeout):
            log.error(error.ABORT_SEND_PACKET)
            # Already aborted
            return False

        # All went fine
        return True
Example #29
0
    def recv(self, basedir, crc_mode=1, retry=16, timeout=60, delay=1):
        '''
        Receive some files via the YMODEM protocol and place them under
        ``basedir``::

            >>> print modem.recv(basedir)
            3

        Returns the number of files received on success or ``None`` in case of
        failure.

        N.B.: currently there are no control on the existence of files, so they
        will be silently overwritten.
        '''
        # Initiate protocol
        error_count = 0
        char = 0
        cancel = 0
        sequence = 0
        num_files = 0
        while True:
            # First try CRC mode, if this fails, fall back to checksum mode
            if error_count >= retry:
                self.abort(timeout=timeout)
                return None
            elif crc_mode and error_count < (retry / 2):
                if not self.putc(CRC):
                    time.sleep(delay)
                    error_count += 1
            else:
                crc_mode = 0
                if not self.putc(NAK):
                    time.sleep(delay)
                    error_count += 1

            # <CRC> or <NAK> sent, waiting answer
            char = self.getc(1, timeout)
            if char is None:
                error_count += 1
                continue
            elif char == CAN:
                if cancel:
                    log.error(error.ABORT_RECV_CAN_CAN)
                    return None
                else:
                    log.debug(error.DEBUG_RECV_CAN)
                    cancel = 1
                    continue
            elif char in [SOH, STX]:
                break
            else:
                error_count += 1
                continue

        # Receiver loop
        fileout = None
        while True:
            # Read next file in batch mode
            while True:
                if char is None:
                    error_count += 1
                elif char == CAN:
                    if cancel:
                        log.error(error.ABORT_RECV_CAN_CAN)
                        return None
                    else:
                        log.debug(debug.DEBUG_RECV_CAN)
                        cancel = 1
                        continue
                elif char in [SOH, STX]:
                    seq1 = ord(self.getc(1))
                    seq2 = 0xff - ord(self.getc(1))

                    if seq1 == sequence and seq2 == sequence:
                        packet_size = 128 if char == SOH else 1024
                        data = self.getc(packet_size + 1 + crc_mode)
                        data = self._check_crc(data, crc_mode)
                        if data:
                            filename = data.split('\x00')[0]
                            if not filename:
                                # No filename, end of batch reception
                                self.putc(ACK)
                                return num_files

                            log.info('Receiving %s to %s' %
                                     (filename, basedir))
                            fileout = open(
                                os.path.join(basedir,
                                             os.path.basename(filename)), 'wb')

                            if not fileout:
                                log.error(error.ABORT_OPEN_FILE)
                                self.putc(NAK)
                                self.abort(timeout=timeout)
                                return False
                            else:
                                self.putc(ACK)
                            break

                    # Request retransmission if something went wrong
                    self.getc(packet_size + 1 + crc_mode)
                    self.putc(NAK)
                    self.getc(1, timeout)
                    continue
                else:
                    error_count += 1

                self.getc(packet_size + 1 + crc_mode)
                self.putc(NAK)
                self.getc(1, timeout)

            stream_size = self._recv_stream(fileout, crc_mode, retry, timeout,
                                            delay)

            if not stream_size:
                log.error(error.ABORT_RECV_STREAM)
                return False

            log.debug('File transfer done, requesting next')
            fileout.close()
            num_files += 1
            sequence = 0

            # Ask for the next sequence and receive the reply
            self.putc(CRC)
            char = self.getc(1, timeout)
Example #30
0
    def send(self, pattern, retry=16, timeout=60, info_callback=None):
        # Get a list of files to send
        file_info_list = []
        try:
            if os.path.isdir(pattern):
                for dirpath, dirnames, topfilenames in os.walk(pattern):
                    file_info_list.extend([(os.path.join(dirpath, n),
                                            os.stat(os.path.join(dirpath, n)))
                                           for n in topfilenames])
                    for subdir in dirnames:
                        subdirpath, subdirnames, subfilenames = os.walk(
                            os.path.join(dirpath, subdir))
                        file_info_list.extend([
                            (os.path.join(dirpath,
                                          n), os.stat(os.path.join(dirpath,
                                                                   n)))
                            for n in subfilenames
                        ])
            elif os.path.isfile(pattern):
                file_info_list.append((pattern, os.stat(pattern)))
        except Exception as e:
            log.error("zmodem get file err:%s" % e)
        if not file_info_list:
            return True

        DATA_SIZE_100K = 1024 * 100
        DATA_SIZE_1M = 1014 * 1024
        DATA_SIZE_10M = 1014 * 1024 * 10
        SUB_PACKERT_SIZE = 1024
        MIDDLE_SUB_PACKET_SIZE = 512
        MIN_SUB_PACKET_SIZE = 256
        SUB_PACKERT_ACK_PER = 16
        SUB_PACKERT_ACK_PER_MIN = 4
        SUB_PACKERT_ACK_PER_MAX = 128
        # initialize protocol
        error_count = 0
        crc_mode = 0
        zr_init_flags = 0
        zr_init_buffer_size = 0
        total_file_cnt = len(file_info_list)
        last_state = cur_state = self.SENDER_WAIT_INTI
        self._send_wakeup(timeout)
        self._send_zsqinit(timeout)

        for file_index, file_info in enumerate(file_info_list):
            if cur_state == self.SEND_ALL_DONE_ABORT:
                print("receiver abort")
                break
            filename = file_info[0]
            filestat = file_info[1]
            fd = open(filename, "rb")
            if not fd:
                print("open %s fail,skip" % filename)
                continue
            file_stat = os.fstat(fd.fileno())
            left_all_file_size = self.get_left_file_size(
                file_info_list, file_index)
            last_send_pos = send_pos = recv_ack_pos = recv_zpos = 0
            send_data_frame_idx = 0

            left_files_to_tran = total_file_cnt - file_index
            data_frame_packet_size = SUB_PACKERT_SIZE
            if file_stat.st_size < DATA_SIZE_100K:
                send_data_frame_cnt = SUB_PACKERT_ACK_PER_MIN
            elif file_stat.st_size > DATA_SIZE_10M:
                send_data_frame_cnt = SUB_PACKERT_ACK_PER_MAX
            elif file_stat.st_size > DATA_SIZE_1M:  #1M ~ 10M
                send_data_frame_cnt = SUB_PACKERT_ACK_PER + (
                    (file_stat.st_size - DATA_SIZE_1M) / DATA_SIZE_100K) * (
                        SUB_PACKERT_ACK_PER_MAX - SUB_PACKERT_ACK_PER) / (
                            (DATA_SIZE_10M - DATA_SIZE_1M) / DATA_SIZE_100K)
            else:  # 100K ~ 1M
                send_data_frame_cnt = SUB_PACKERT_ACK_PER_MIN + (
                    (file_stat.st_size - DATA_SIZE_100K) // DATA_SIZE_100K) * (
                        SUB_PACKERT_ACK_PER - SUB_PACKERT_ACK_PER_MIN) / (
                            (DATA_SIZE_1M - DATA_SIZE_100K) / DATA_SIZE_100K)

            send_data_frame_cnt = int(send_data_frame_cnt)
            debug_info = 'filename:%s, size:%d, frmcnt:%d\n' % (
                filename, file_stat.st_size, send_data_frame_cnt)
            if info_callback:
                info_callback(debug_info)
            else:
                print(debug_info)
            if file_index > 0 and (cur_state
                                   == self.SENDING_ONE_DONE_AND_HAS_NEXT_FILE
                                   or cur_state == self.SENDING_SKIP):
                last_state = cur_state = self.SENDING_ZFILE_NEXT
            else:
                last_state = cur_state = self.SENDER_WAIT_INTI
            continues_zpos_cnt = 0
            continues_start_zpos = 0
            end_of_file_send = False
            send_zdata_frame_type = 0
            send_data_err_cnt = 0
            error_count = 0
            file_data_need_async_ack = 0
            data_need_ack_time = 0
            percent_last = percent_now = 0
            while True:
                percent_last = percent_now
                last_state = cur_state
                last_send_pos = send_pos
                recv_zpos_get = False
                header_need_ack = file_data_need_sync_ack = False

                if last_state == self.SENDING_ZDATA:
                    if send_zdata_frame_type == ZCRCQ:
                        file_data_need_async_ack += 1
                        data_need_ack_time = time.time()
                    elif send_zdata_frame_type == ZCRCW:
                        file_data_need_sync_ack = True
                        data_need_ack_time = time.time()
                elif last_state != self.SENDING_ZFILE_NEXT:
                    header_need_ack = True

                if header_need_ack or file_data_need_sync_ack:
                    recv_timeout = 0.3 + file_data_need_async_ack * 0.1 + error_count * 0.03
                elif file_data_need_async_ack > 1:
                    recv_timeout = file_data_need_async_ack * 0.03
                else:
                    recv_timeout = 0.0

                header = self._recv_header(recv_timeout)
                #print('h:%s, sync:%s async:%d, er:%d ->%f'%(header_need_ack, file_data_need_sync_ack, file_data_need_async_ack, error_count, recv_timeout))
                header_type = header[0]

                if header_type == ZRPOS:
                    recv_zpos_get = True
                    recv_zpos = header[ZP0] | (header[ZP1] << 8) | (
                        header[ZP2] << 16) | (header[ZP3] << 24)
                elif header_type == ZACK:
                    recv_ack_pos = header[ZP0] | (header[ZP1] << 8) | (
                        header[ZP2] << 16) | (header[ZP3] << 24)
                    if not file_data_need_sync_ack and file_data_need_async_ack > 0:
                        file_data_need_async_ack -= 1
                elif header_type == ZRINIT:
                    zr_init_flags = header[ZF0] | (header[ZF1] << 8)
                    zr_init_buffer_size = header[ZP0] | (header[ZP1] << 8)
                    print(header, '0x%x' % zr_init_flags, zr_init_buffer_size)
                elif header_type != TIMEOUT:
                    print('header_type:0x%x' %
                          header_type if header_type is not None else "None")

                last_state, cur_state = self._send_state_next(
                    last_state, header, end_of_file_send, left_files_to_tran)
                percent_now = 1000 * send_pos // (file_stat.st_size if
                                                  file_stat.st_size > 0 else 1)
                if header_need_ack or file_data_need_sync_ack or file_data_need_async_ack or header_type != TIMEOUT or cur_state != last_state or percent_now != percent_last:
                    process_info = '%3d.%d%% send:%-6d ack:%-6d zrpos:%d%s \n' % (
                        percent_now // 10, percent_now % 10, send_pos,
                        recv_ack_pos, recv_zpos,
                        '<N>' if recv_zpos_get else '')
                    debug_info = "0x%2x frm:%4d/%d %s" % (
                        cur_state, send_data_frame_idx, send_data_frame_cnt,
                        process_info)
                    if info_callback:
                        info_callback(debug_info)
                    else:
                        print(debug_info)

                if cur_state == last_state:
                    if cur_state == self.SENDING_ZDATA:
                        if file_data_need_sync_ack is True:
                            if header_type == TIMEOUT:
                                error_count += 1
                            elif error_count > 2:
                                error_count -= 2
                        elif file_data_need_async_ack > 3 and header_type == TIMEOUT:
                            error_count += 1
                    elif header_type == TIMEOUT:
                        error_count += 1

                    if error_count > retry or send_data_err_cnt > retry:
                        self._send_cancel_transfer()
                        if info_callback:
                            info_callback("too many errors, abort\n")
                        break
                elif error_count > 0:
                    error_count -= 1

                if recv_zpos_get is True and recv_zpos < send_pos:
                    send_pos = recv_zpos
                    send_data_frame_idx = 0
                    continues_zpos_cnt += 1
                    if continues_zpos_cnt == 1:
                        continues_start_zpos = recv_zpos
                    if continues_zpos_cnt > 2 and send_data_frame_cnt >= 2:
                        send_data_frame_cnt -= 1
                    elif continues_zpos_cnt > (retry + retry + -1) / 3:
                        data_frame_packet_size = MIDDLE_SUB_PACKET_SIZE
                    elif continues_zpos_cnt > (retry + retry + -1) / 2:
                        data_frame_packet_size = MIN_SUB_PACKET_SIZE
                    elif continues_zpos_cnt > retry and continues_start_zpos == recv_zpos:
                        self._send_cancel_transfer()
                        if info_callback:
                            info_callback("too many errors, abort\n")
                        break
                else:
                    continues_zpos_cnt = 0

                if cur_state == self.SENDING_ZRQINIT:
                    if error_count > 1 and error_count % 2 == 0:
                        self._send_wakeup(timeout)
                    self._send_zsqinit(timeout)
                elif cur_state == self.SENDING_ZFILE:
                    if self._send_zfile_header(
                            filename, file_stat.st_size, file_stat.st_mtime,
                            left_files_to_tran, left_all_file_size,
                            timeout) < 0:
                        send_data_err_cnt += 1
                    else:
                        send_data_err_cnt = 0
                elif cur_state == self.SENDING_ZDATA:
                    if last_send_pos != send_pos:
                        fd.seek(send_pos)
                    data = fd.read(data_frame_packet_size)
                    data_len = len(data)
                    if send_data_frame_idx == 0 and data_len > 0:
                        if send_zdata_frame_type == ZCRCG or send_zdata_frame_type == ZCRCQ:
                            fd.seek(last_send_pos)
                            fill_end_pack_data = fd.read(4)
                            if self._write_zdle_data(ZCRCW, fill_end_pack_data,
                                                     timeout) < 0:
                                send_data_err_cnt += 1
                            else:
                                send_data_err_cnt = 0
                            fd.seek(send_pos + data_len)
                        if self._send_zdata_header(send_pos, timeout) < 0:
                            send_data_err_cnt += 1
                        else:
                            send_data_err_cnt = 0
                    send_data_frame_idx += 1
                    send_pos += data_len

                    if data_len == 0:
                        #file ends
                        end_of_file_send = True
                        self._send_zeof_header(send_pos, timeout)
                        send_zdata_frame_type = ZEOF
                        send_data_frame_idx = 0
                    elif (send_data_frame_idx % send_data_frame_cnt) == 0:
                        if zr_init_buffer_size > 0 and zr_init_buffer_size <= send_data_frame_idx * data_frame_packet_size:
                            send_zdata_frame_type = ZCRCW
                            send_data_frame_idx = 0
                        elif zr_init_flags & CANFDX:
                            send_zdata_frame_type = ZCRCQ
                        else:
                            send_zdata_frame_type = ZCRCW
                            send_data_frame_idx = 0
                        if self._write_zdle_data(
                                send_zdata_frame_type, data,
                                timeout) < 0:  #ZACK expected, end of frame
                            send_data_err_cnt += 1
                        else:
                            send_data_err_cnt = 0
                    elif data_len < data_frame_packet_size:
                        #file end, and we recheck if really file end
                        data_next = fd.read(data_frame_packet_size)
                        send_zdata_frame_type = ZCRCE if not data_next else ZCRCW
                        if self._write_zdle_data(
                                send_zdata_frame_type, data, timeout
                        ) < 0:  # CRCE no ZACK expected, end of frame/file
                            send_data_err_cnt += 1
                        else:
                            send_data_err_cnt = 0
                        send_data_frame_idx = 0
                        #do not read the data, for next loop, and do not care of file offst for we will feek again
                    else:
                        if zr_init_buffer_size > 0 and zr_init_buffer_size <= send_data_frame_idx * data_frame_packet_size:
                            send_zdata_frame_type = ZCRCW
                            send_data_frame_idx = 0
                        elif zr_init_flags & CANOVIO:
                            #atleast one ack every 3 seconds
                            if time.time() > data_need_ack_time + 3.0:
                                send_zdata_frame_type = ZCRCG
                            else:
                                send_zdata_frame_type = ZCRCG
                        else:
                            send_zdata_frame_type = ZCRCW
                            send_data_frame_idx = 0
                        if self._write_zdle_data(
                                send_zdata_frame_type, data, timeout
                        ) < 0:  #NO ZACK expected, continue of frame
                            send_data_err_cnt += 1
                        else:
                            send_data_err_cnt = 0
                    #print('tsts',ts1-ts, ts2-ts1, ts3-ts2, ts4-ts3)
                elif cur_state == self.SENDING_ZFIN:
                    self._send_zfin_header(send_pos, timeout)
                elif cur_state == self.SENDING_ABORT_ZFIN:
                    self._send_zfin_header(send_pos, timeout)
                    if info_callback:
                        info_callback("abort by receiver\n")
                elif cur_state == self.SENDING_ONE_DONE_AND_HAS_NEXT_FILE:
                    if info_callback:
                        info_callback(
                            "one file send done, and to send next file\n")
                    break
                elif cur_state == self.SENDING_SKIP:
                    if info_callback:
                        info_callback("file skiped by receiver\n")
                    break
                elif cur_state == self.SEND_ALL_DONE or cur_state == self.SEND_ALL_DONE_ABORT:
                    self._send_over_and_out()
                    if info_callback:
                        info_callback("send over and out\n")
                    break
            fd.close()
        return True if cur_state == self.SEND_ALL_DONE else False
Example #31
0
    def recv(self, stream, crc_mode=1, retry=16, timeout=60, delay=1, quiet=0):
        '''
        Receive a stream via the XMODEM protocol.

            >>> stream = file('/etc/issue', 'wb')
            >>> print modem.recv(stream)
            2342

        Returns the number of bytes received on success or ``None`` in case of
        failure.
        '''

        # initiate protocol
        error_count = 0
        char = 0
        cancel = 0
        while True:
            # first try CRC mode, if this fails,
            # fall back to checksum mode
            if error_count >= retry:
                log.error(error.ABORT_ERROR_LIMIT)
                self.abort(timeout=timeout)
                return None
            elif crc_mode and error_count < (retry / 2):
                log.debug(error.DEBUG_TRY_CRC)
                if not self.putc(CRC):
                    time.sleep(delay)
                    error_count += 1
            else:
                log.debug(error.DEBUG_TRY_CHECKSUM)
                crc_mode = 0
                if not self.putc(NAK):
                    time.sleep(delay)
                    error_count += 1

            char = self.getc(1, timeout)
            if char is None:
                error_count += 1
                continue
            elif char in [SOH, STX]:
                break
            elif char == CAN:
                if cancel:
                    log.error(error.ABORT_RECV_CAN_CAN)
                    return None
                else:
                    log.debug(error.DEBUG_RECV_CAN)
                    cancel = 1
            else:
                error_count += 1

        # read data
        error_count = 0
        income_size = 0
        packet_size = 128
        sequence = 1
        cancel = 0
        while True:
            while True:
                if char == SOH:
                    packet_size = 128
                    break
                elif char == EOT:
                    # Acknowledge end of transmission
                    self.putc(ACK)
                    return income_size
                elif char == CAN:
                    # We abort if we receive two consecutive <CAN> bytes
                    if cancel:
                        return None
                    else:
                        cancel = 1
                else:
                    log.debug(error.DEBUG_EXPECT_SOH_EOT % ord(char))
                    error_count += 1
                    if error_count >= retry:
                        self.abort()
                        return None

            # read sequence
            error_count = 0
            cancel = 0
            seq1 = ord(self.getc(1))
            seq2 = 0xff - ord(self.getc(1))
            if seq1 == sequence and seq2 == sequence:
                # sequence is ok, read packet
                # packet_size + checksum
                data = self._check_crc(self.getc(packet_size + 1 + crc_mode),
                    crc_mode)

                # valid data, append chunk
                if data:
                    income_size += len(data)
                    stream.write(data)
                    self.putc(ACK)
                    sequence = (sequence + 1) % 0x100
                    char = self.getc(1, timeout)
                    continue
            else:
                # consume data
                self.getc(packet_size + 1 + crc_mode)
                log.warning(error.WARNS_SEQUENCE % (sequence, seq1, seq2))

            # something went wrong, request retransmission
            self.putc(NAK)
Example #32
0
    def _recv_stream(self, stream, crc_mode, retry, timeout, delay):
        '''
        Receives data and write it on a stream. It assumes the protocol has
        already been initialized (<CRC> or <NAK> sent and optional packet 0
        received).

        On success it exits after an <EOT> and returns the number of bytes
        received. In case of failure returns ``False``.
        '''
        # IN CASE OF YMODEM THE FILE IS ALREADY OPEN AND THE PACKET 0 RECEIVED

        error_count = 0
        cancel = 0
        sequence = 1
        income_size = 0
        self.putc(CRC)

        char = self.getc(1, timeout)
        while True:
            if char is None:
                error_count += 1
                if error_count >= retry:
                    log.error(error.ABORT_ERROR_LIMIT)
                    self.abort(timeout=timeout)
                    return None
                else:
                    continue
            elif char == CAN:
                if cancel:
                    return None
                else:
                    cancel = 1
            elif char in [SOH, STX]:
                packet_size = 128 if char == SOH else 1024
                # Check the requested packet size, only YMODEM has a variable
                # size
                if self.protocol != PROTOCOL_YMODEM and \
                    PACKET_SIZE.get(self.protocol) != packet_size:
                    log.error(error.ABORT_PACKET_SIZE)
                    self.abort(timeout=timeout)
                    return False

                # FIXME check error
                seq1 = self.getc(1)[0]
                seq2 = 0xff - self.getc(1)[0]

                if seq1 == sequence and seq2 == sequence:
                    data = self.getc(packet_size + 1 + crc_mode)
                    data = self._check_crc(data, crc_mode)

                    if data:
                        # Append data to the stream
                        income_size += len(data)
                        stream.write(data)
                        self.putc(ACK)
                        sequence = (sequence + 1) % 0x100

                        # Waiting for new packet
                        char = self.getc(1, timeout)
                        continue

                # Sequence numbering is off or CRC is incorrect, request new
                # packet
                self.getc(packet_size + 1 + crc_mode)
                self.putc(NAK)
            elif char == EOT:
                # We are done, acknowledge <EOT>
                self.putc(ACK)
                return income_size
            elif char == CAN:
                # Cancel at two consecutive cancels
                if cancel:
                    return False
                else:
                    cancel = 1
                    self.putc(ACK)
                    char = self.getc(1, timeout)
                    continue
            else:
                log.debug(error.DEBUG_EXPECT_SOH_EOT % repr(char))
                error_count += 1
                if error_count >= retry:
                    log.error(error.ABORT_ERROR_LIMIT)
                    self.abort()
                    return False
Example #33
0
    def _recv_stream(self, stream, crc_mode, retry, timeout, delay):
        '''
        Receives data and write it on a stream. It assumes the protocol has
        already been initialized (<CRC> or <NAK> sent and optional packet 0
        received).

        On success it exits after an <EOT> and returns the number of bytes
        received. In case of failure returns ``False``.
        '''
        # IN CASE OF YMODEM THE FILE IS ALREADY OPEN AND THE PACKET 0 RECEIVED

        error_count = 0
        cancel = 0
        sequence = 1
        income_size = 0
        self.putc(CRC)

        char = self.getc(1, timeout)
        while True:
            if char is None:
                error_count += 1
                if error_count >= retry:
                    log.error(error.ABORT_ERROR_LIMIT)
                    self.abort(timeout=timeout)
                    return None
                else:
                    continue
            elif char == CAN:
                if cancel:
                    return None
                else:
                    cancel = 1
            elif char in [SOH, STX]:
                packet_size = 128 if char == SOH else 1024
                # Check the requested packet size, only YMODEM has a variable
                # size
                if self.protocol != PROTOCOL_YMODEM and \
                    PACKET_SIZE.get(self.protocol) != packet_size:
                    log.error(error.ABORT_PACKET_SIZE)
                    self.abort(timeout=timeout)
                    return False

                seq1 = ord(self.getc(1))
                seq2 = 0xff - ord(self.getc(1))

                if seq1 == sequence and seq2 == sequence:
                    data = self.getc(packet_size + 1 + crc_mode)
                    data = self._check_crc(data, crc_mode)

                    if data:
                        # Append data to the stream
                        income_size += len(data)
                        stream.write(data)
                        self.putc(ACK)
                        sequence = (sequence + 1) % 0x100

                        # Waiting for new packet
                        char = self.getc(1, timeout)
                        continue

                # Sequence numbering is off or CRC is incorrect, request new
                # packet
                self.getc(packet_size + 1 + crc_mode)
                self.putc(NAK)
            elif char == EOT:
                # We are done, acknowledge <EOT>
                self.putc(ACK)
                return income_size
            elif char == CAN:
                # Cancel at two consecutive cancels
                if cancel:
                    return False
                else:
                    cancel = 1
                    self.putc(ACK)
                    char = self.getc(1, timeout)
                    continue
            else:
                log.debug(error.DEBUG_EXPECT_SOH_EOT % ord(char))
                error_count += 1
                if error_count >= retry:
                    log.error(error.ABORT_ERROR_LIMIT)
                    self.abort()
                    return False
Example #34
0
    def recv(self, stream, crc_mode=1, retry=16, timeout=60, delay=1, quiet=0):
        '''
        Receive a stream via the XMODEM protocol.

            >>> stream = file('/etc/issue', 'wb')
            >>> print modem.recv(stream)
            2342

        Returns the number of bytes received on success or ``None`` in case of
        failure.
        '''

        # initiate protocol
        error_count = 0
        char = 0
        cancel = 0
        while True:
            # first try CRC mode, if this fails,
            # fall back to checksum mode
            if error_count >= retry:
                log.error(error.ABORT_ERROR_LIMIT)
                self.abort(timeout=timeout)
                return None
            elif crc_mode and error_count < (retry / 2):
                log.debug(error.DEBUG_TRY_CRC)
                if not self.putc(CRC):
                    time.sleep(delay)
                    error_count += 1
            else:
                log.debug(error.DEBUG_TRY_CHECKSUM)
                crc_mode = 0
                if not self.putc(NAK):
                    time.sleep(delay)
                    error_count += 1

            char = self.getc(1, timeout)
            if char is None:
                error_count += 1
                continue
            elif char in [SOH, STX]:
                break
            elif char == CAN:
                if cancel:
                    log.error(error.ABORT_RECV_CAN_CAN)
                    return None
                else:
                    log.debug(error.DEBUG_RECV_CAN)
                    cancel = 1
            else:
                error_count += 1

        # read data
        error_count = 0
        income_size = 0
        packet_size = 128
        sequence = 1
        cancel = 0
        while True:
            while True:
                if char == SOH:
                    packet_size = 128
                    break
                elif char == EOT:
                    # Acknowledge end of transmission
                    self.putc(ACK)
                    return income_size
                elif char == CAN:
                    # We abort if we receive two consecutive <CAN> bytes
                    if cancel:
                        return None
                    else:
                        cancel = 1
                else:
                    log.debug(error.DEBUG_EXPECT_SOH_EOT % repr(char))
                    error_count += 1
                    if error_count >= retry:
                        self.abort()
                        return None

            # read sequence
            error_count = 0
            cancel = 0
            # FIXME check error
            seq1 = self.getc(1)[0]
            seq2 = 0xff - self.getc(1)[0]
            if seq1 == sequence and seq2 == sequence:
                # sequence is ok, read packet
                # packet_size + checksum
                data = self._check_crc(self.getc(packet_size + 1 + crc_mode),
                                       crc_mode)

                # valid data, append chunk
                if data:
                    income_size += len(data)
                    stream.write(data)
                    self.putc(ACK)
                    sequence = (sequence + 1) % 0x100
                    char = self.getc(1, timeout)
                    continue
            else:
                # consume data
                self.getc(packet_size + 1 + crc_mode)
                log.warning(error.WARNS_SEQUENCE % (sequence, seq1, seq2))

            # something went wrong, request retransmission
            self.putc(NAK)
    def recv(self, stream, crc_mode=1, retry=16, timeout=60, delay=1):
        '''
        Receive a stream via the XMODEM1K protocol.

            >>> stream = file('/etc/issue', 'wb')
            >>> print modem.recv(stream)
            2342

        Returns the number of bytes received on success or ``None`` in case of
        failure.
        '''

        # initiate protocol
        error_count = 0
        char = 0
        cancel = 0
        while True:
            # first try CRC mode, if this fails,
            # fall back to checksum mode
            if error_count >= retry:
                self.abort(timeout=timeout)
                return None
            elif crc_mode and error_count < (retry / 2):
                if not self.putc(CRC):
                    time.sleep(delay)
                    error_count += 1
            else:
                crc_mode = 0
                if not self.putc(NAK):
                    time.sleep(delay)
                    error_count += 1

            char = self.getc(1, timeout)
            if char is None:
                error_count += 1
                continue
            elif char == SOH:
                #crc_mode = 0
                break
            elif char in [STX, CAN]:
                break
            elif char == CAN:
                if cancel:
                    return None
                else:
                    cancel = 1
            else:
                error_count += 1

        # read data
        error_count = 0
        income_size = 0
        packet_size = 128
        sequence = 1
        cancel = 0
        while True:
            while True:
                if char == SOH:
                    packet_size = 128
                    break
                elif char == STX:
                    packet_size = 1024
                    break
                elif char == EOT:
                    # SEND LAST <ACK>
                    self.putc(ACK)
                    return income_size
                elif char == CAN:
                    # cancel at two consecutive cancels
                    if cancel:
                        log.error(error.ABORT_RECV_CAN_CAN)
                        return None
                    else:
                        log.debug(error.DEBUG_RECV_CAN)
                        cancel = 1
                else:
                    log.error(error.ERROR_EXPECT_SOH_EOT % ord(char))
                    error_count += 1
                    if error_count >= retry:
                        self.abort()
                        return None

            # read sequence
            error_count = 0
            cancel = 0
            seq1 = ord(self.getc(1))
            seq2 = 0xff - ord(self.getc(1))
            if seq1 == sequence and seq2 == sequence:
                # sequence is ok, read packet
                # packet_size + checksum
                data = self.getc(packet_size + 1 + crc_mode)
                data = self._check_crc(data, crc_mode)
                # valid data, append chunk
                if data:
                    income_size += len(data)
                    stream.write(data)
                    self.putc(ACK)
                    sequence = (sequence + 1) % 0x100
                    char = self.getc(1, timeout)
                    continue
            else:
                # consume data
                self.getc(packet_size + 1 + crc_mode)
                log.debug(error.ERROR_INVALID_SEQ)

            # something went wrong, request retransmission
            self.putc(NAK)
Example #36
0
    def send(self, pattern, retry=10, timeout=60):
        '''
        Send one or more files via the YMODEM protocol.

            >>> print modem.send('*.txt')
            True

        Returns ``True`` upon succesful transmission or ``False`` in case of
        failure.
        '''

        # Get a list of files to send
        filenames = glob.glob(pattern)
        # filenames = 'mixer.bin'
        if not filenames:
            return True

        # initialize protocol
        error_count = 0
        crc_mode = 0

        start_char = self._wait_recv(error_count, timeout, retry)

        if start_char:
            crc_mode = 1 if (start_char == CRC) else 0
        else:
            log.error(error.ABORT_PROTOCOL)
            # Already aborted
            return False

        for filename in filenames:
            # Send meta data packet
            sequence = 0
            error_count = 0
            # Add filesize
            filesize = os.path.getsize(filename)
            data = ''.join(
                [os.path.basename(filename), '\x00',
                 str(filesize), '\x00'])

            log.debug(error.DEBUG_START_FILENAME % (filename, ))
            # Pick a suitable packet length for the filename
            packet_size = 128 if (len(data) < 128) else 1024

            # Packet padding
            data = data.ljust(packet_size, '\0')

            # Calculate checksum
            crc = crc32_byte(list(bytearray(data.encode())))

            # Emit packet
            if not self._send_packet(sequence, data, packet_size, crc_mode,
                                     crc, error_count, retry, timeout):
                self.abort(timeout=timeout)
                return False

            # Wait for <CRC> before transmitting the file contents
            error_count = 0
            if not self._wait_recv(error_count, timeout, retry):
                self.abort(timeout)
                return False

            filedesc = open(filename, 'rb')

            # AT THIS POINT
            # - PACKET 0 WITH METADATA TRANSMITTED
            # - INITIAL <CRC> OR <NAK> ALREADY RECEIVED

            if not self._send_stream(filedesc, crc_mode, retry, timeout):
                log.error(error.ABORT_SEND_STREAM)
                return False

            # AT THIS POINT
            # - FILE CONTENTS TRANSMITTED
            # - <EOT> TRANSMITTED
            # - <ACK> RECEIVED

            filedesc.close()
            # WAIT A <CRC> BEFORE NEXT FILE
            error_count = 0
            if not self._wait_recv(error_count, timeout, retry):
                log.error(error.ABORT_INIT_NEXT)
                # Already aborted
                return False

        # End of batch transmission, send NULL file name
        sequence = 0
        error_count = 0
        packet_size = 128
        data = '\x00' * packet_size
        crc = crc32_byte(list(bytearray(data.encode())))

        # Emit packet
        if not self._send_packet(sequence, data, packet_size, crc_mode, crc,
                                 error_count, retry, timeout):
            log.error(error.ABORT_SEND_PACKET)
            # Already aborted
            return False

        # All went fine
        return True
Example #37
0
    def recv(self, basedir, crc_mode=1, retry=16, timeout=60, delay=1):
        '''
        Receive some files via the YMODEM protocol and place them under
        ``basedir``::

            >>> print modem.recv(basedir)
            3

        Returns the number of files received on success or ``None`` in case of
        failure.

        N.B.: currently there are no control on the existence of files, so they
        will be silently overwritten.
        '''
        # Initiate protocol
        error_count = 0
        char = 0
        cancel = 0
        sequence = 0
        num_files = 0
        while True:
            # First try CRC mode, if this fails, fall back to checksum mode
            if error_count >= retry:
                self.abort(timeout=timeout)
                return None
            elif crc_mode and error_count < (retry / 2):
                if not self.putc(CRC):
                    time.sleep(delay)
                    error_count += 1
            else:
                crc_mode = 0
                if not self.putc(NAK):
                    time.sleep(delay)
                    error_count += 1

            # <CRC> or <NAK> sent, waiting answer
            char = self.getc(1, timeout)
            if char is None:
                error_count += 1
                continue
            elif char == CAN:
                if cancel:
                    log.error(error.ABORT_RECV_CAN_CAN)
                    return None
                else:
                    log.debug(error.DEBUG_RECV_CAN)
                    cancel = 1
                    continue
            elif char in [SOH, STX]:
                break
            else:
                error_count += 1
                continue

        # Receiver loop
        fileout = None
        while True:
            # Read next file in batch mode
            while True:
                if char is None:
                    error_count += 1
                elif char == CAN:
                    if cancel:
                        log.error(error.ABORT_RECV_CAN_CAN)
                        return None
                    else:
                        log.debug(debug.DEBUG_RECV_CAN)
                        cancel = 1
                        continue
                elif char in [SOH, STX]:
                    seq1 = ord(self.getc(1))
                    seq2 = 0xff - ord(self.getc(1))

                    if seq1 == sequence and seq2 == sequence:
                        packet_size = 128 if char == SOH else 1024
                        data = self.getc(packet_size + 1 + crc_mode)
                        data = self._check_crc(data, crc_mode)
                        if data:
                            filename = data.split('\x00')[0]
                            if not filename:
                                # No filename, end of batch reception
                                self.putc(ACK)
                                return num_files

                            log.info('Receiving %s to %s' % (filename,
                                basedir))
                            fileout = open(os.path.join(basedir,
                                os.path.basename(filename)), 'wb')

                            if not fileout:
                                log.error(error.ABORT_OPEN_FILE)
                                self.putc(NAK)
                                self.abort(timeout=timeout)
                                return False
                            else:
                                self.putc(ACK)
                            break

                    # Request retransmission if something went wrong
                    self.getc(packet_size + 1 + crc_mode)
                    self.putc(NAK)
                    self.getc(1, timeout)
                    continue
                else:
                    error_count += 1

                self.getc(packet_size + 1 + crc_mode)
                self.putc(NAK)
                self.getc(1, timeout)

            stream_size = self._recv_stream(fileout, crc_mode, retry, timeout,
                delay)

            if not stream_size:
                log.error(error.ABORT_RECV_STREAM)
                return False

            log.debug('File transfer done, requesting next')
            fileout.close()
            num_files += 1
            sequence = 0

            # Ask for the next sequence and receive the reply
            self.putc(CRC)
            char = self.getc(1, timeout)